CryptoAlgorithms.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/EnumBits.h>
  8. #include <AK/String.h>
  9. #include <LibCrypto/BigInt/UnsignedBigInteger.h>
  10. #include <LibJS/Forward.h>
  11. #include <LibJS/Heap/GCPtr.h>
  12. #include <LibWeb/Bindings/SubtleCryptoPrototype.h>
  13. #include <LibWeb/Crypto/CryptoBindings.h>
  14. #include <LibWeb/Crypto/CryptoKey.h>
  15. #include <LibWeb/WebIDL/Buffers.h>
  16. #include <LibWeb/WebIDL/ExceptionOr.h>
  17. namespace Web::Crypto {
  18. using AlgorithmIdentifier = Variant<JS::Handle<JS::Object>, String>;
  19. using NamedCurve = String;
  20. using KeyDataType = Variant<JS::Handle<WebIDL::BufferSource>, Bindings::JsonWebKey>;
  21. struct HashAlgorithmIdentifier : public AlgorithmIdentifier {
  22. using AlgorithmIdentifier::AlgorithmIdentifier;
  23. JS::ThrowCompletionOr<String> name(JS::VM& vm) const
  24. {
  25. auto value = visit(
  26. [](String const& name) -> JS::ThrowCompletionOr<String> { return name; },
  27. [&](JS::Handle<JS::Object> const& obj) -> JS::ThrowCompletionOr<String> {
  28. auto name_property = TRY(obj->get("name"));
  29. return name_property.to_string(vm);
  30. });
  31. return value;
  32. }
  33. };
  34. // https://w3c.github.io/webcrypto/#algorithm-overview
  35. struct AlgorithmParams {
  36. virtual ~AlgorithmParams();
  37. explicit AlgorithmParams(String name)
  38. : name(move(name))
  39. {
  40. }
  41. String name;
  42. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  43. };
  44. // https://w3c.github.io/webcrypto/#aes-cbc
  45. struct AesCbcParams : public AlgorithmParams {
  46. virtual ~AesCbcParams() override;
  47. AesCbcParams(String name, ByteBuffer iv)
  48. : AlgorithmParams(move(name))
  49. , iv(move(iv))
  50. {
  51. }
  52. ByteBuffer iv;
  53. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  54. };
  55. // https://w3c.github.io/webcrypto/#dfn-AesCtrParams
  56. struct AesCtrParams : public AlgorithmParams {
  57. virtual ~AesCtrParams() override;
  58. AesCtrParams(String name, ByteBuffer counter, u8 length)
  59. : AlgorithmParams(move(name))
  60. , counter(move(counter))
  61. , length(length)
  62. {
  63. }
  64. ByteBuffer counter;
  65. u8 length;
  66. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  67. };
  68. // https://w3c.github.io/webcrypto/#hkdf-params
  69. struct HKDFParams : public AlgorithmParams {
  70. virtual ~HKDFParams() override;
  71. HKDFParams(String name, HashAlgorithmIdentifier hash, ByteBuffer salt, ByteBuffer info)
  72. : AlgorithmParams(move(name))
  73. , hash(move(hash))
  74. , salt(move(salt))
  75. , info(move(info))
  76. {
  77. }
  78. HashAlgorithmIdentifier hash;
  79. ByteBuffer salt;
  80. ByteBuffer info;
  81. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  82. };
  83. // https://w3c.github.io/webcrypto/#pbkdf2-params
  84. struct PBKDF2Params : public AlgorithmParams {
  85. virtual ~PBKDF2Params() override;
  86. PBKDF2Params(String name, ByteBuffer salt, u32 iterations, HashAlgorithmIdentifier hash)
  87. : AlgorithmParams(move(name))
  88. , salt(move(salt))
  89. , iterations(iterations)
  90. , hash(move(hash))
  91. {
  92. }
  93. ByteBuffer salt;
  94. u32 iterations;
  95. HashAlgorithmIdentifier hash;
  96. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  97. };
  98. // https://w3c.github.io/webcrypto/#dfn-RsaKeyGenParams
  99. struct RsaKeyGenParams : public AlgorithmParams {
  100. virtual ~RsaKeyGenParams() override;
  101. RsaKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent)
  102. : AlgorithmParams(move(name))
  103. , modulus_length(modulus_length)
  104. , public_exponent(move(public_exponent))
  105. {
  106. }
  107. u32 modulus_length;
  108. // NOTE that the raw data is going to be in Big Endian u8[] format
  109. ::Crypto::UnsignedBigInteger public_exponent;
  110. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  111. };
  112. // https://w3c.github.io/webcrypto/#dfn-RsaHashedKeyGenParams
  113. struct RsaHashedKeyGenParams : public RsaKeyGenParams {
  114. virtual ~RsaHashedKeyGenParams() override;
  115. RsaHashedKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent, HashAlgorithmIdentifier hash)
  116. : RsaKeyGenParams(move(name), modulus_length, move(public_exponent))
  117. , hash(move(hash))
  118. {
  119. }
  120. HashAlgorithmIdentifier hash;
  121. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  122. };
  123. // https://w3c.github.io/webcrypto/#dfn-RsaHashedImportParams
  124. struct RsaHashedImportParams : public AlgorithmParams {
  125. virtual ~RsaHashedImportParams() override;
  126. RsaHashedImportParams(String name, HashAlgorithmIdentifier hash)
  127. : AlgorithmParams(move(name))
  128. , hash(move(hash))
  129. {
  130. }
  131. HashAlgorithmIdentifier hash;
  132. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  133. };
  134. // https://w3c.github.io/webcrypto/#dfn-RsaOaepParams
  135. struct RsaOaepParams : public AlgorithmParams {
  136. virtual ~RsaOaepParams() override;
  137. RsaOaepParams(String name, ByteBuffer label)
  138. : AlgorithmParams(move(name))
  139. , label(move(label))
  140. {
  141. }
  142. ByteBuffer label;
  143. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  144. };
  145. // https://w3c.github.io/webcrypto/#dfn-EcdsaParams
  146. struct EcdsaParams : public AlgorithmParams {
  147. virtual ~EcdsaParams() override;
  148. EcdsaParams(String name, HashAlgorithmIdentifier hash)
  149. : AlgorithmParams(move(name))
  150. , hash(move(hash))
  151. {
  152. }
  153. HashAlgorithmIdentifier hash;
  154. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  155. };
  156. // https://w3c.github.io/webcrypto/#dfn-EcKeyGenParams
  157. struct EcKeyGenParams : public AlgorithmParams {
  158. virtual ~EcKeyGenParams() override;
  159. EcKeyGenParams(String name, NamedCurve named_curve)
  160. : AlgorithmParams(move(name))
  161. , named_curve(move(named_curve))
  162. {
  163. }
  164. NamedCurve named_curve;
  165. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  166. };
  167. // https://w3c.github.io/webcrypto/#dfn-AesKeyGenParams
  168. struct AesKeyGenParams : public AlgorithmParams {
  169. virtual ~AesKeyGenParams() override;
  170. AesKeyGenParams(String name, u16 length)
  171. : AlgorithmParams(move(name))
  172. , length(length)
  173. {
  174. }
  175. u16 length;
  176. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  177. };
  178. // https://w3c.github.io/webcrypto/#dfn-AesDerivedKeyParams
  179. struct AesDerivedKeyParams : public AlgorithmParams {
  180. virtual ~AesDerivedKeyParams() override;
  181. AesDerivedKeyParams(String name, u16 length)
  182. : AlgorithmParams(move(name))
  183. , length(length)
  184. {
  185. }
  186. u16 length;
  187. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  188. };
  189. class AlgorithmMethods {
  190. public:
  191. virtual ~AlgorithmMethods();
  192. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  193. {
  194. return WebIDL::NotSupportedError::create(m_realm, "encrypt is not supported"_string);
  195. }
  196. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  197. {
  198. return WebIDL::NotSupportedError::create(m_realm, "decrypt is not supported"_string);
  199. }
  200. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  201. {
  202. return WebIDL::NotSupportedError::create(m_realm, "sign is not supported"_string);
  203. }
  204. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&)
  205. {
  206. return WebIDL::NotSupportedError::create(m_realm, "verify is not supported"_string);
  207. }
  208. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> digest(AlgorithmParams const&, ByteBuffer const&)
  209. {
  210. return WebIDL::NotSupportedError::create(m_realm, "digest is not supported"_string);
  211. }
  212. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>)
  213. {
  214. return WebIDL::NotSupportedError::create(m_realm, "deriveBits is not supported"_string);
  215. }
  216. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&)
  217. {
  218. return WebIDL::NotSupportedError::create(m_realm, "importKey is not supported"_string);
  219. }
  220. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&)
  221. {
  222. return WebIDL::NotSupportedError::create(m_realm, "generateKey is not supported"_string);
  223. }
  224. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>)
  225. {
  226. return WebIDL::NotSupportedError::create(m_realm, "exportKey is not supported"_string);
  227. }
  228. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&)
  229. {
  230. return WebIDL::NotSupportedError::create(m_realm, "getKeyLength is not supported"_string);
  231. }
  232. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AlgorithmMethods(realm)); }
  233. protected:
  234. explicit AlgorithmMethods(JS::Realm& realm)
  235. : m_realm(realm)
  236. {
  237. }
  238. JS::NonnullGCPtr<JS::Realm> m_realm;
  239. };
  240. class RSAOAEP : public AlgorithmMethods {
  241. public:
  242. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  243. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  244. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  245. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  246. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  247. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new RSAOAEP(realm)); }
  248. private:
  249. explicit RSAOAEP(JS::Realm& realm)
  250. : AlgorithmMethods(realm)
  251. {
  252. }
  253. };
  254. class AesCbc : public AlgorithmMethods {
  255. public:
  256. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  257. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  258. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  259. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  260. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  261. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  262. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AesCbc(realm)); }
  263. private:
  264. explicit AesCbc(JS::Realm& realm)
  265. : AlgorithmMethods(realm)
  266. {
  267. }
  268. };
  269. class AesCtr : public AlgorithmMethods {
  270. public:
  271. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  272. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  273. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  274. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  275. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  276. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  277. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AesCtr(realm)); }
  278. private:
  279. explicit AesCtr(JS::Realm& realm)
  280. : AlgorithmMethods(realm)
  281. {
  282. }
  283. };
  284. class HKDF : public AlgorithmMethods {
  285. public:
  286. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  287. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>) override;
  288. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  289. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new HKDF(realm)); }
  290. private:
  291. explicit HKDF(JS::Realm& realm)
  292. : AlgorithmMethods(realm)
  293. {
  294. }
  295. };
  296. class PBKDF2 : public AlgorithmMethods {
  297. public:
  298. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  299. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>) override;
  300. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  301. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new PBKDF2(realm)); }
  302. private:
  303. explicit PBKDF2(JS::Realm& realm)
  304. : AlgorithmMethods(realm)
  305. {
  306. }
  307. };
  308. class SHA : public AlgorithmMethods {
  309. public:
  310. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> digest(AlgorithmParams const&, ByteBuffer const&) override;
  311. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new SHA(realm)); }
  312. private:
  313. explicit SHA(JS::Realm& realm)
  314. : AlgorithmMethods(realm)
  315. {
  316. }
  317. };
  318. class ECDSA : public AlgorithmMethods {
  319. public:
  320. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  321. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&) override;
  322. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  323. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new ECDSA(realm)); }
  324. private:
  325. explicit ECDSA(JS::Realm& realm)
  326. : AlgorithmMethods(realm)
  327. {
  328. }
  329. };
  330. class ED25519 : public AlgorithmMethods {
  331. public:
  332. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  333. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&) override;
  334. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  335. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new ED25519(realm)); }
  336. private:
  337. explicit ED25519(JS::Realm& realm)
  338. : AlgorithmMethods(realm)
  339. {
  340. }
  341. };
  342. ErrorOr<String> base64_url_uint_encode(::Crypto::UnsignedBigInteger);
  343. WebIDL::ExceptionOr<ByteBuffer> base64_url_bytes_decode(JS::Realm&, String const& base64_url_string);
  344. WebIDL::ExceptionOr<::Crypto::UnsignedBigInteger> base64_url_uint_decode(JS::Realm&, String const& base64_url_string);
  345. }