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>`.
This commit is contained in:
devgianlu 2024-11-26 14:54:29 +01:00 committed by Andreas Kling
parent 1647893fc8
commit 9eea94aa14
Notes: github-actions[bot] 2024-11-27 10:02:00 +00:00
3 changed files with 21 additions and 25 deletions

View file

@ -13,8 +13,8 @@
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;
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(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 {};
}));
@ -39,8 +38,8 @@ ErrorOr<ByteBuffer> wrap_in_private_key_info(ByteBuffer key, Span<int> algorithm
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) {
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(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 {};
}));
@ -69,8 +67,8 @@ requires requires(ExportableKey k) {
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;
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(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 {};
}));
@ -94,8 +91,8 @@ ErrorOr<ByteBuffer> wrap_in_subject_public_key_info(ByteBuffer key, Span<int> al
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) {
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(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 {};
}));

View file

@ -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
auto maybe_data = handle.visit(
[&](::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> {
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
auto maybe_data = handle.visit(
[&](::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> {
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 subjectPublicKey field to keyData.
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.
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
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.
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 subjectPublicKey field to keyData.
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.
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],
// that represents the X25519 private key represented by the [[handle]] internal slot of key
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.
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 subjectPublicKey field to keyData.
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.
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 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 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.
return JS::ArrayBuffer::create(m_realm, data);

View file

@ -126,7 +126,7 @@ c8yGzl89pYST
auto keypair = Crypto::PK::RSA::parse_rsa_key(decoded);
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 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 rsa_from_pair = Crypto::PK::RSA(keypair.public_key, keypair.private_key);
auto rsa_from_pem = Crypto::PK::RSA(priv_pem);