CryptoAlgorithms.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  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/#hkdf-params
  56. struct HKDFParams : public AlgorithmParams {
  57. virtual ~HKDFParams() override;
  58. HKDFParams(String name, HashAlgorithmIdentifier hash, ByteBuffer salt, ByteBuffer info)
  59. : AlgorithmParams(move(name))
  60. , hash(move(hash))
  61. , salt(move(salt))
  62. , info(move(info))
  63. {
  64. }
  65. HashAlgorithmIdentifier hash;
  66. ByteBuffer salt;
  67. ByteBuffer info;
  68. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  69. };
  70. // https://w3c.github.io/webcrypto/#pbkdf2-params
  71. struct PBKDF2Params : public AlgorithmParams {
  72. virtual ~PBKDF2Params() override;
  73. PBKDF2Params(String name, ByteBuffer salt, u32 iterations, HashAlgorithmIdentifier hash)
  74. : AlgorithmParams(move(name))
  75. , salt(move(salt))
  76. , iterations(iterations)
  77. , hash(move(hash))
  78. {
  79. }
  80. ByteBuffer salt;
  81. u32 iterations;
  82. HashAlgorithmIdentifier hash;
  83. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  84. };
  85. // https://w3c.github.io/webcrypto/#dfn-RsaKeyGenParams
  86. struct RsaKeyGenParams : public AlgorithmParams {
  87. virtual ~RsaKeyGenParams() override;
  88. RsaKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent)
  89. : AlgorithmParams(move(name))
  90. , modulus_length(modulus_length)
  91. , public_exponent(move(public_exponent))
  92. {
  93. }
  94. u32 modulus_length;
  95. // NOTE that the raw data is going to be in Big Endian u8[] format
  96. ::Crypto::UnsignedBigInteger public_exponent;
  97. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  98. };
  99. // https://w3c.github.io/webcrypto/#dfn-RsaHashedKeyGenParams
  100. struct RsaHashedKeyGenParams : public RsaKeyGenParams {
  101. virtual ~RsaHashedKeyGenParams() override;
  102. RsaHashedKeyGenParams(String name, u32 modulus_length, ::Crypto::UnsignedBigInteger public_exponent, HashAlgorithmIdentifier hash)
  103. : RsaKeyGenParams(move(name), modulus_length, move(public_exponent))
  104. , hash(move(hash))
  105. {
  106. }
  107. HashAlgorithmIdentifier hash;
  108. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  109. };
  110. // https://w3c.github.io/webcrypto/#dfn-RsaHashedImportParams
  111. struct RsaHashedImportParams : public AlgorithmParams {
  112. virtual ~RsaHashedImportParams() override;
  113. RsaHashedImportParams(String name, HashAlgorithmIdentifier hash)
  114. : AlgorithmParams(move(name))
  115. , hash(move(hash))
  116. {
  117. }
  118. HashAlgorithmIdentifier hash;
  119. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  120. };
  121. // https://w3c.github.io/webcrypto/#dfn-RsaOaepParams
  122. struct RsaOaepParams : public AlgorithmParams {
  123. virtual ~RsaOaepParams() override;
  124. RsaOaepParams(String name, ByteBuffer label)
  125. : AlgorithmParams(move(name))
  126. , label(move(label))
  127. {
  128. }
  129. ByteBuffer label;
  130. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  131. };
  132. // https://w3c.github.io/webcrypto/#dfn-EcdsaParams
  133. struct EcdsaParams : public AlgorithmParams {
  134. virtual ~EcdsaParams() override;
  135. EcdsaParams(String name, HashAlgorithmIdentifier hash)
  136. : AlgorithmParams(move(name))
  137. , hash(move(hash))
  138. {
  139. }
  140. HashAlgorithmIdentifier hash;
  141. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  142. };
  143. // https://w3c.github.io/webcrypto/#dfn-EcKeyGenParams
  144. struct EcKeyGenParams : public AlgorithmParams {
  145. virtual ~EcKeyGenParams() override;
  146. EcKeyGenParams(String name, NamedCurve named_curve)
  147. : AlgorithmParams(move(name))
  148. , named_curve(move(named_curve))
  149. {
  150. }
  151. NamedCurve named_curve;
  152. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  153. };
  154. // https://w3c.github.io/webcrypto/#dfn-AesKeyGenParams
  155. struct AesKeyGenParams : public AlgorithmParams {
  156. virtual ~AesKeyGenParams() override;
  157. AesKeyGenParams(String name, u16 length)
  158. : AlgorithmParams(move(name))
  159. , length(length)
  160. {
  161. }
  162. u16 length;
  163. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  164. };
  165. // https://w3c.github.io/webcrypto/#dfn-AesDerivedKeyParams
  166. struct AesDerivedKeyParams : public AlgorithmParams {
  167. virtual ~AesDerivedKeyParams() override;
  168. AesDerivedKeyParams(String name, u16 length)
  169. : AlgorithmParams(move(name))
  170. , length(length)
  171. {
  172. }
  173. u16 length;
  174. static JS::ThrowCompletionOr<NonnullOwnPtr<AlgorithmParams>> from_value(JS::VM&, JS::Value);
  175. };
  176. class AlgorithmMethods {
  177. public:
  178. virtual ~AlgorithmMethods();
  179. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  180. {
  181. return WebIDL::NotSupportedError::create(m_realm, "encrypt is not supported"_string);
  182. }
  183. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  184. {
  185. return WebIDL::NotSupportedError::create(m_realm, "decrypt is not supported"_string);
  186. }
  187. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&)
  188. {
  189. return WebIDL::NotSupportedError::create(m_realm, "sign is not supported"_string);
  190. }
  191. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&)
  192. {
  193. return WebIDL::NotSupportedError::create(m_realm, "verify is not supported"_string);
  194. }
  195. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> digest(AlgorithmParams const&, ByteBuffer const&)
  196. {
  197. return WebIDL::NotSupportedError::create(m_realm, "digest is not supported"_string);
  198. }
  199. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>)
  200. {
  201. return WebIDL::NotSupportedError::create(m_realm, "deriveBits is not supported"_string);
  202. }
  203. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&)
  204. {
  205. return WebIDL::NotSupportedError::create(m_realm, "importKey is not supported"_string);
  206. }
  207. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&)
  208. {
  209. return WebIDL::NotSupportedError::create(m_realm, "generateKey is not supported"_string);
  210. }
  211. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>)
  212. {
  213. return WebIDL::NotSupportedError::create(m_realm, "exportKey is not supported"_string);
  214. }
  215. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&)
  216. {
  217. return WebIDL::NotSupportedError::create(m_realm, "getKeyLength is not supported"_string);
  218. }
  219. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AlgorithmMethods(realm)); }
  220. protected:
  221. explicit AlgorithmMethods(JS::Realm& realm)
  222. : m_realm(realm)
  223. {
  224. }
  225. JS::NonnullGCPtr<JS::Realm> m_realm;
  226. };
  227. class RSAOAEP : public AlgorithmMethods {
  228. public:
  229. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  230. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  231. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  232. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  233. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  234. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new RSAOAEP(realm)); }
  235. private:
  236. explicit RSAOAEP(JS::Realm& realm)
  237. : AlgorithmMethods(realm)
  238. {
  239. }
  240. };
  241. class AesCbc : public AlgorithmMethods {
  242. public:
  243. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> encrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  244. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> decrypt(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer 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<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  247. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  248. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  249. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AesCbc(realm)); }
  250. private:
  251. explicit AesCbc(JS::Realm& realm)
  252. : AlgorithmMethods(realm)
  253. {
  254. }
  255. };
  256. class AesCtr : public AlgorithmMethods {
  257. public:
  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<JS::NonnullGCPtr<JS::Object>> export_key(Bindings::KeyFormat, JS::NonnullGCPtr<CryptoKey>) override;
  260. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  261. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  262. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new AesCtr(realm)); }
  263. private:
  264. explicit AesCtr(JS::Realm& realm)
  265. : AlgorithmMethods(realm)
  266. {
  267. }
  268. };
  269. class HKDF : 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::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>) override;
  273. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  274. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new HKDF(realm)); }
  275. private:
  276. explicit HKDF(JS::Realm& realm)
  277. : AlgorithmMethods(realm)
  278. {
  279. }
  280. };
  281. class PBKDF2 : public AlgorithmMethods {
  282. public:
  283. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<CryptoKey>> import_key(AlgorithmParams const&, Bindings::KeyFormat, CryptoKey::InternalKeyData, bool, Vector<Bindings::KeyUsage> const&) override;
  284. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> derive_bits(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, Optional<u32>) override;
  285. virtual WebIDL::ExceptionOr<JS::Value> get_key_length(AlgorithmParams const&) override;
  286. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new PBKDF2(realm)); }
  287. private:
  288. explicit PBKDF2(JS::Realm& realm)
  289. : AlgorithmMethods(realm)
  290. {
  291. }
  292. };
  293. class SHA : public AlgorithmMethods {
  294. public:
  295. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> digest(AlgorithmParams const&, ByteBuffer const&) override;
  296. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new SHA(realm)); }
  297. private:
  298. explicit SHA(JS::Realm& realm)
  299. : AlgorithmMethods(realm)
  300. {
  301. }
  302. };
  303. class ECDSA : public AlgorithmMethods {
  304. public:
  305. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  306. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&) override;
  307. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  308. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new ECDSA(realm)); }
  309. private:
  310. explicit ECDSA(JS::Realm& realm)
  311. : AlgorithmMethods(realm)
  312. {
  313. }
  314. };
  315. class ED25519 : public AlgorithmMethods {
  316. public:
  317. virtual WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> sign(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&) override;
  318. virtual WebIDL::ExceptionOr<JS::Value> verify(AlgorithmParams const&, JS::NonnullGCPtr<CryptoKey>, ByteBuffer const&, ByteBuffer const&) override;
  319. virtual WebIDL::ExceptionOr<Variant<JS::NonnullGCPtr<CryptoKey>, JS::NonnullGCPtr<CryptoKeyPair>>> generate_key(AlgorithmParams const&, bool, Vector<Bindings::KeyUsage> const&) override;
  320. static NonnullOwnPtr<AlgorithmMethods> create(JS::Realm& realm) { return adopt_own(*new ED25519(realm)); }
  321. private:
  322. explicit ED25519(JS::Realm& realm)
  323. : AlgorithmMethods(realm)
  324. {
  325. }
  326. };
  327. ErrorOr<String> base64_url_uint_encode(::Crypto::UnsignedBigInteger);
  328. WebIDL::ExceptionOr<ByteBuffer> base64_url_bytes_decode(JS::Realm&, String const& base64_url_string);
  329. WebIDL::ExceptionOr<::Crypto::UnsignedBigInteger> base64_url_uint_decode(JS::Realm&, String const& base64_url_string);
  330. }