Jelajahi Sumber

LibCrypto+LibWeb: Support passing parameters to ASN.1 wrappers

Add support for encoding parameters in `wrap_in_private_key_info` and
`wrap_in_subject_public_key_info` as well as turn `Span<int>` into
`Span<int const>`.
devgianlu 7 bulan lalu
induk
melakukan
9eea94aa14

+ 12 - 16
Libraries/LibCrypto/PK/PK.h

@@ -13,8 +13,8 @@
 
 
 namespace Crypto::PK {
 namespace Crypto::PK {
 
 
-template<class ByteBuffer>
-ErrorOr<ByteBuffer> wrap_in_private_key_info(ByteBuffer key, Span<int> algorithm_identifier)
+template<class ByteBuffer, typename Params>
+ErrorOr<ByteBuffer> wrap_in_private_key_info(ByteBuffer key, Span<int const> algorithm_identifier, Params params)
 {
 {
     ASN1::Encoder encoder;
     ASN1::Encoder encoder;
     TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
     TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
@@ -24,8 +24,7 @@ ErrorOr<ByteBuffer> wrap_in_private_key_info(ByteBuffer key, Span<int> algorithm
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
             TRY(encoder.write(algorithm_identifier)); // algorithm
             TRY(encoder.write(algorithm_identifier)); // algorithm
 
 
-            // FIXME: This assumes we have a NULL parameter, this is not always the case
-            TRY(encoder.write(nullptr)); // parameters
+            TRY(encoder.write(params)); // parameters
 
 
             return {};
             return {};
         }));
         }));
@@ -39,8 +38,8 @@ ErrorOr<ByteBuffer> wrap_in_private_key_info(ByteBuffer key, Span<int> algorithm
     return encoder.finish();
     return encoder.finish();
 }
 }
 
 
-template<typename ExportableKey>
-ErrorOr<ByteBuffer> wrap_in_private_key_info(ExportableKey key, Span<int> algorithm_identifier)
+template<typename ExportableKey, typename Params>
+ErrorOr<ByteBuffer> wrap_in_private_key_info(ExportableKey key, Span<int const> algorithm_identifier, Params params)
 requires requires(ExportableKey k) {
 requires requires(ExportableKey k) {
     k.export_as_der();
     k.export_as_der();
 }
 }
@@ -53,8 +52,7 @@ requires requires(ExportableKey k) {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
             TRY(encoder.write(algorithm_identifier)); // algorithm
             TRY(encoder.write(algorithm_identifier)); // algorithm
 
 
-            // FIXME: This assumes we have a NULL parameter, this is not always the case
-            TRY(encoder.write(nullptr)); // parameters
+            TRY(encoder.write(params)); // parameters
 
 
             return {};
             return {};
         }));
         }));
@@ -69,8 +67,8 @@ requires requires(ExportableKey k) {
     return encoder.finish();
     return encoder.finish();
 }
 }
 
 
-template<class ByteBuffer>
-ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ByteBuffer key, Span<int> algorithm_identifier)
+template<class ByteBuffer, typename ParamsType>
+ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ByteBuffer key, Span<int const> algorithm_identifier, ParamsType const& params)
 {
 {
     ASN1::Encoder encoder;
     ASN1::Encoder encoder;
     TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
     TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
@@ -78,8 +76,7 @@ ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ByteBuffer key, Span<int> al
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
             TRY(encoder.write(algorithm_identifier)); // algorithm
             TRY(encoder.write(algorithm_identifier)); // algorithm
 
 
-            // FIXME: This assumes we have a NULL parameter, this is not always the case
-            TRY(encoder.write(nullptr)); // parameters
+            TRY(encoder.write(params)); // parameters
 
 
             return {};
             return {};
         }));
         }));
@@ -94,8 +91,8 @@ ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ByteBuffer key, Span<int> al
     return encoder.finish();
     return encoder.finish();
 }
 }
 
 
-template<typename ExportableKey>
-ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ExportableKey key, Span<int> algorithm_identifier)
+template<typename ExportableKey, typename ParamsType>
+ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ExportableKey key, Span<int const> algorithm_identifier, ParamsType const& params)
 requires requires(ExportableKey k) {
 requires requires(ExportableKey k) {
     k.export_as_der();
     k.export_as_der();
 }
 }
@@ -106,8 +103,7 @@ requires requires(ExportableKey k) {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
         TRY(encoder.write_constructed(ASN1::Class::Universal, ASN1::Kind::Sequence, [&]() -> ErrorOr<void> {
             TRY(encoder.write(algorithm_identifier)); // algorithm
             TRY(encoder.write(algorithm_identifier)); // algorithm
 
 
-            // FIXME: This assumes we have a NULL parameter, this is not always the case
-            TRY(encoder.write(nullptr)); // parameters
+            TRY(encoder.write(params)); // parameters
 
 
             return {};
             return {};
         }));
         }));

+ 8 - 8
Libraries/LibWeb/Crypto/CryptoAlgorithms.cpp

@@ -1112,7 +1112,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> RSAOAEP::export_key(Bindings::KeyFormat
         //   that represents the RSA public key represented by the [[handle]] internal slot of key
         //   that represents the RSA public key represented by the [[handle]] internal slot of key
         auto maybe_data = handle.visit(
         auto maybe_data = handle.visit(
             [&](::Crypto::PK::RSAPublicKey<> const& public_key) -> ErrorOr<ByteBuffer> {
             [&](::Crypto::PK::RSAPublicKey<> const& public_key) -> ErrorOr<ByteBuffer> {
-                return TRY(::Crypto::PK::wrap_in_subject_public_key_info(public_key, Array { ::Crypto::Certificate::rsa_encryption_oid }));
+                return TRY(::Crypto::PK::wrap_in_subject_public_key_info(public_key, Array { ::Crypto::Certificate::rsa_encryption_oid }, nullptr));
             },
             },
             [](auto) -> ErrorOr<ByteBuffer> {
             [](auto) -> ErrorOr<ByteBuffer> {
                 VERIFY_NOT_REACHED();
                 VERIFY_NOT_REACHED();
@@ -1139,7 +1139,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> RSAOAEP::export_key(Bindings::KeyFormat
         // that represents the RSA private key represented by the [[handle]] internal slot of key
         // that represents the RSA private key represented by the [[handle]] internal slot of key
         auto maybe_data = handle.visit(
         auto maybe_data = handle.visit(
             [&](::Crypto::PK::RSAPrivateKey<> const& private_key) -> ErrorOr<ByteBuffer> {
             [&](::Crypto::PK::RSAPrivateKey<> const& private_key) -> ErrorOr<ByteBuffer> {
-                return TRY(::Crypto::PK::wrap_in_private_key_info(private_key, Array { ::Crypto::Certificate::rsa_encryption_oid }));
+                return TRY(::Crypto::PK::wrap_in_private_key_info(private_key, Array { ::Crypto::Certificate::rsa_encryption_oid }, nullptr));
             },
             },
             [](auto) -> ErrorOr<ByteBuffer> {
             [](auto) -> ErrorOr<ByteBuffer> {
                 VERIFY_NOT_REACHED();
                 VERIFY_NOT_REACHED();
@@ -2971,7 +2971,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED25519::export_key(Bindings::KeyFormat
         //      * Set the algorithm object identifier to the id-Ed25519 OID defined in [RFC8410].
         //      * Set the algorithm object identifier to the id-Ed25519 OID defined in [RFC8410].
         //    * Set the subjectPublicKey field to keyData.
         //    * Set the subjectPublicKey field to keyData.
         auto ed25519_oid = ::Crypto::Certificate::ed25519_oid;
         auto ed25519_oid = ::Crypto::Certificate::ed25519_oid;
-        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(key_data, ed25519_oid));
+        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(key_data, ed25519_oid, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         return JS::ArrayBuffer::create(m_realm, move(data));
         return JS::ArrayBuffer::create(m_realm, move(data));
@@ -2990,7 +2990,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> ED25519::export_key(Bindings::KeyFormat
         //    * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410], that represents the Ed25519 private key represented by the [[handle]] internal slot of key
         //    * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410], that represents the Ed25519 private key represented by the [[handle]] internal slot of key
 
 
         auto ed25519_oid = ::Crypto::Certificate::ed25519_oid;
         auto ed25519_oid = ::Crypto::Certificate::ed25519_oid;
-        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(key_data, ed25519_oid));
+        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(key_data, ed25519_oid, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         return JS::ArrayBuffer::create(m_realm, move(data));
         return JS::ArrayBuffer::create(m_realm, move(data));
@@ -3659,7 +3659,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> X25519::export_key(Bindings::KeyFormat
         //    Set the algorithm object identifier to the id-X25519 OID defined in [RFC8410].
         //    Set the algorithm object identifier to the id-X25519 OID defined in [RFC8410].
         //    Set the subjectPublicKey field to keyData.
         //    Set the subjectPublicKey field to keyData.
         auto public_key = handle.get<ByteBuffer>();
         auto public_key = handle.get<ByteBuffer>();
-        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(public_key, Array { ::Crypto::Certificate::x25519_oid }));
+        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_subject_public_key_info(public_key, Array { ::Crypto::Certificate::x25519_oid }, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         result = JS::ArrayBuffer::create(m_realm, data);
         result = JS::ArrayBuffer::create(m_realm, data);
@@ -3678,7 +3678,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> X25519::export_key(Bindings::KeyFormat
         //    Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410],
         //    Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410],
         //    that represents the X25519 private key represented by the [[handle]] internal slot of key
         //    that represents the X25519 private key represented by the [[handle]] internal slot of key
         auto private_key = handle.get<ByteBuffer>();
         auto private_key = handle.get<ByteBuffer>();
-        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(private_key, Array { ::Crypto::Certificate::x25519_oid }));
+        auto data = TRY_OR_THROW_OOM(vm, ::Crypto::PK::wrap_in_private_key_info(private_key, Array { ::Crypto::Certificate::x25519_oid }, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         result = JS::ArrayBuffer::create(m_realm, data);
         result = JS::ArrayBuffer::create(m_realm, data);
@@ -3903,7 +3903,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> X448::export_key(Bindings::KeyFormat fo
         //      * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
         //      * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
         //    * Set the subjectPublicKey field to keyData.
         //    * Set the subjectPublicKey field to keyData.
         auto x448_oid = ::Crypto::Certificate::x448_oid;
         auto x448_oid = ::Crypto::Certificate::x448_oid;
-        auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_subject_public_key_info(key_data, x448_oid));
+        auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_subject_public_key_info(key_data, x448_oid, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         return JS::ArrayBuffer::create(m_realm, data);
         return JS::ArrayBuffer::create(m_realm, data);
@@ -3921,7 +3921,7 @@ WebIDL::ExceptionOr<GC::Ref<JS::Object>> X448::export_key(Bindings::KeyFormat fo
         //      * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
         //      * Set the algorithm object identifier to the id-X448 OID defined in [RFC8410].
         //    * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410], that represents the X448 private key represented by the [[handle]] internal slot of key
         //    * Set the privateKey field to the result of DER-encoding a CurvePrivateKey ASN.1 type, as defined in Section 7 of [RFC8410], that represents the X448 private key represented by the [[handle]] internal slot of key
         auto x448_oid = ::Crypto::Certificate::x448_oid;
         auto x448_oid = ::Crypto::Certificate::x448_oid;
-        auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_private_key_info(key_data, x448_oid));
+        auto data = TRY_OR_THROW_OOM(m_realm->vm(), ::Crypto::PK::wrap_in_private_key_info(key_data, x448_oid, nullptr));
 
 
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         // 3. Let result be a new ArrayBuffer associated with the relevant global object of this [HTML], and containing data.
         return JS::ArrayBuffer::create(m_realm, data);
         return JS::ArrayBuffer::create(m_realm, data);

+ 1 - 1
Tests/LibCrypto/TestRSA.cpp

@@ -126,7 +126,7 @@ c8yGzl89pYST
     auto keypair = Crypto::PK::RSA::parse_rsa_key(decoded);
     auto keypair = Crypto::PK::RSA::parse_rsa_key(decoded);
     auto priv_der = MUST(keypair.private_key.export_as_der());
     auto priv_der = MUST(keypair.private_key.export_as_der());
     auto rsa_encryption_oid = Array<int, 7> { 1, 2, 840, 113549, 1, 1, 1 };
     auto rsa_encryption_oid = Array<int, 7> { 1, 2, 840, 113549, 1, 1, 1 };
-    auto wrapped_priv_der = MUST(Crypto::PK::wrap_in_private_key_info(keypair.private_key, rsa_encryption_oid));
+    auto wrapped_priv_der = MUST(Crypto::PK::wrap_in_private_key_info(keypair.private_key, rsa_encryption_oid, nullptr));
     auto priv_pem = MUST(Crypto::encode_pem(wrapped_priv_der, Crypto::PEMType::PrivateKey));
     auto priv_pem = MUST(Crypto::encode_pem(wrapped_priv_der, Crypto::PEMType::PrivateKey));
     auto rsa_from_pair = Crypto::PK::RSA(keypair.public_key, keypair.private_key);
     auto rsa_from_pair = Crypto::PK::RSA(keypair.public_key, keypair.private_key);
     auto rsa_from_pem = Crypto::PK::RSA(priv_pem);
     auto rsa_from_pem = Crypto::PK::RSA(priv_pem);