diff --git a/include/mls/crypto.h b/include/mls/crypto.h index ab507ebbf..8f2c23c21 100644 --- a/include/mls/crypto.h +++ b/include/mls/crypto.h @@ -223,6 +223,7 @@ struct SignaturePrivateKey { static SignaturePrivateKey generate(CipherSuite suite); static SignaturePrivateKey parse(CipherSuite suite, const bytes& data); + static SignaturePrivateKey parse_der(CipherSuite suite, const bytes& data); static SignaturePrivateKey derive(CipherSuite suite, const bytes& secret); SignaturePrivateKey() = default; diff --git a/lib/hpke/include/hpke/signature.h b/lib/hpke/include/hpke/signature.h index 8ee0b39ba..979a54cfc 100644 --- a/lib/hpke/include/hpke/signature.h +++ b/lib/hpke/include/hpke/signature.h @@ -50,6 +50,9 @@ struct Signature virtual std::unique_ptr deserialize_private( const bytes& skm) const; + virtual std::unique_ptr deserialize_private_der( + const bytes& der) const; + virtual bytes sign(const bytes& data, const PrivateKey& sk) const = 0; virtual bool verify(const bytes& data, const bytes& sig, diff --git a/lib/hpke/src/group.cpp b/lib/hpke/src/group.cpp index 5afcd0250..b1df64357 100644 --- a/lib/hpke/src/group.cpp +++ b/lib/hpke/src/group.cpp @@ -8,6 +8,7 @@ #include "openssl/ec.h" #include "openssl/evp.h" #include "openssl/obj_mac.h" +#include "openssl/pem.h" #if defined(WITH_OPENSSL3) #include "openssl/core_names.h" #include "openssl/param_build.h" @@ -526,6 +527,22 @@ struct ECKeyGroup : public EVPGroup #endif } + std::unique_ptr deserialize_private_der( + const bytes& der) const override + { + BIO* mem = BIO_new_mem_buf(der.data(), static_cast(der.size())); + if (!mem) { + throw openssl_error(); + } + EVP_PKEY* pkey = d2i_PrivateKey_bio(mem, NULL); + BIO_free(mem); + if (!pkey) { + throw openssl_error(); + } + + return std::make_unique(pkey); + } + private: int curve_nid; @@ -651,6 +668,22 @@ struct RawKeyGroup : public EVPGroup return std::make_unique(pkey); } + std::unique_ptr deserialize_private_der( + const bytes& der) const override + { + BIO* mem = BIO_new_mem_buf(der.data(), static_cast(der.size())); + if (!mem) { + throw openssl_error(); + } + EVP_PKEY* pkey = d2i_PrivateKey_bio(mem, NULL); + BIO_free(mem); + if (!pkey) { + throw openssl_error(); + } + + return std::make_unique(pkey); + } + private: const int evp_type; diff --git a/lib/hpke/src/group.h b/lib/hpke/src/group.h index ace8d7a92..33d775c48 100644 --- a/lib/hpke/src/group.h +++ b/lib/hpke/src/group.h @@ -55,6 +55,8 @@ struct Group virtual bytes serialize_private(const PrivateKey& sk) const = 0; virtual std::unique_ptr deserialize_private( const bytes& skm) const = 0; + virtual std::unique_ptr deserialize_private_der( + const bytes& der) const = 0; virtual bytes dh(const PrivateKey& sk, const PublicKey& pk) const = 0; diff --git a/lib/hpke/src/signature.cpp b/lib/hpke/src/signature.cpp index a79cafeaa..05f30c1f8 100644 --- a/lib/hpke/src/signature.cpp +++ b/lib/hpke/src/signature.cpp @@ -7,6 +7,7 @@ #include "group.h" #include "rsa.h" #include +#include #include namespace hpke { @@ -89,6 +90,13 @@ struct GroupSignature : public Signature group.deserialize_private(skm).release()); } + std::unique_ptr deserialize_private_der( + const bytes& der) const override + { + return std::make_unique( + group.deserialize_private_der(der).release()); + } + bytes sign(const bytes& data, const Signature::PrivateKey& sk) const override { const auto& rsk = dynamic_cast(sk); @@ -188,6 +196,12 @@ Signature::deserialize_private(const bytes& /* unused */) const throw std::runtime_error("Not implemented"); } +std::unique_ptr +Signature::deserialize_private_der(const bytes&) const +{ + throw std::runtime_error("Not implemented"); +} + std::unique_ptr Signature::generate_rsa(size_t bits) { diff --git a/src/crypto.cpp b/src/crypto.cpp index 3236e0267..51a6518dd 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -402,6 +402,16 @@ SignaturePrivateKey::parse(CipherSuite suite, const bytes& data) return { data, pub_data }; } +SignaturePrivateKey +SignaturePrivateKey::parse_der(CipherSuite suite, const bytes& data) +{ + auto priv = suite.sig().deserialize_private_der(data); + auto pub = priv->public_key(); + auto pub_data = suite.sig().serialize(*pub); + auto priv_data = suite.sig().serialize_private(*priv); + return { priv_data, pub_data }; +} + SignaturePrivateKey SignaturePrivateKey::derive(CipherSuite suite, const bytes& secret) { diff --git a/test/credential.cpp b/test/credential.cpp index 4c1a5fdcd..4db0e5008 100644 --- a/test/credential.cpp +++ b/test/credential.cpp @@ -74,7 +74,7 @@ TEST_CASE("X509 Credential EC certificates") const std::vector der_in{ cert }; - auto key = SignaturePrivateKey::parse( + auto key = SignaturePrivateKey::parse_der( mls::CipherSuite::ID::P256_AES128GCM_SHA256_P256, keydata); auto cred = Credential::x509(der_in);