Skip to content

Commit a423b99

Browse files
panvanpaun
authored andcommitted
crypto: support ML-DSA KeyObject, sign, and verify
PR-URL: nodejs/node#59259 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 443b35c commit a423b99

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

ncrypto.cc

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,6 +1897,31 @@ EVPKeyPointer EVPKeyPointer::NewRawPrivate(
18971897
EVP_PKEY_new_raw_private_key(id, nullptr, data.data, data.len));
18981898
}
18991899

1900+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
1901+
EVPKeyPointer EVPKeyPointer::NewRawSeed(
1902+
int id, const Buffer<const unsigned char>& data) {
1903+
if (id == 0) return {};
1904+
1905+
OSSL_PARAM params[] = {
1906+
OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_DSA_SEED,
1907+
const_cast<unsigned char*>(data.data),
1908+
data.len),
1909+
OSSL_PARAM_END};
1910+
1911+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(id, nullptr);
1912+
if (ctx == nullptr) return {};
1913+
1914+
EVP_PKEY* pkey = nullptr;
1915+
if (ctx == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 ||
1916+
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
1917+
EVP_PKEY_CTX_free(ctx);
1918+
return {};
1919+
}
1920+
1921+
return EVPKeyPointer(pkey);
1922+
}
1923+
#endif
1924+
19001925
EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) {
19011926
if (!dh) return {};
19021927
auto key = New();
@@ -1942,7 +1967,16 @@ EVP_PKEY* EVPKeyPointer::release() {
19421967

19431968
int EVPKeyPointer::id(const EVP_PKEY* key) {
19441969
if (key == nullptr) return 0;
1945-
return EVP_PKEY_id(key);
1970+
int type = EVP_PKEY_id(key);
1971+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
1972+
// https://github.com/openssl/openssl/issues/27738#issuecomment-3013215870
1973+
if (type == -1) {
1974+
if (EVP_PKEY_is_a(key, "ML-DSA-44")) return EVP_PKEY_ML_DSA_44;
1975+
if (EVP_PKEY_is_a(key, "ML-DSA-65")) return EVP_PKEY_ML_DSA_65;
1976+
if (EVP_PKEY_is_a(key, "ML-DSA-87")) return EVP_PKEY_ML_DSA_87;
1977+
}
1978+
#endif
1979+
return type;
19461980
}
19471981

19481982
int EVPKeyPointer::base_id(const EVP_PKEY* key) {
@@ -1998,6 +2032,31 @@ DataPointer EVPKeyPointer::rawPublicKey() const {
19982032
return {};
19992033
}
20002034

2035+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2036+
DataPointer EVPKeyPointer::rawSeed() const {
2037+
if (!pkey_) return {};
2038+
switch (id()) {
2039+
case EVP_PKEY_ML_DSA_44:
2040+
case EVP_PKEY_ML_DSA_65:
2041+
case EVP_PKEY_ML_DSA_87:
2042+
break;
2043+
default:
2044+
unreachable();
2045+
}
2046+
2047+
size_t seed_len = 32;
2048+
if (auto data = DataPointer::Alloc(seed_len)) {
2049+
const Buffer<unsigned char> buf = data;
2050+
size_t len = data.size();
2051+
if (EVP_PKEY_get_octet_string_param(
2052+
get(), OSSL_PKEY_PARAM_ML_DSA_SEED, buf.data, len, &seed_len) != 1)
2053+
return {};
2054+
return data;
2055+
}
2056+
return {};
2057+
}
2058+
#endif
2059+
20012060
DataPointer EVPKeyPointer::rawPrivateKey() const {
20022061
if (!pkey_) return {};
20032062
if (auto data = DataPointer::Alloc(rawPrivateKeySize())) {
@@ -2453,7 +2512,18 @@ bool EVPKeyPointer::isRsaVariant() const {
24532512
bool EVPKeyPointer::isOneShotVariant() const {
24542513
if (!pkey_) return false;
24552514
int type = id();
2456-
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
2515+
switch (type) {
2516+
case EVP_PKEY_ED25519:
2517+
case EVP_PKEY_ED448:
2518+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2519+
case EVP_PKEY_ML_DSA_44:
2520+
case EVP_PKEY_ML_DSA_65:
2521+
case EVP_PKEY_ML_DSA_87:
2522+
#endif
2523+
return true;
2524+
default:
2525+
return false;
2526+
}
24572527
}
24582528

24592529
bool EVPKeyPointer::isSigVariant() const {

ncrypto.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030

3131
#if OPENSSL_VERSION_MAJOR >= 3
3232
#define OSSL3_CONST const
33+
#if OPENSSL_VERSION_MINOR >= 5
34+
#include <openssl/core_names.h>
35+
#endif
3336
#else
3437
#define OSSL3_CONST
3538
#endif
@@ -817,6 +820,10 @@ class EVPKeyPointer final {
817820
const Buffer<const unsigned char>& data);
818821
static EVPKeyPointer NewRawPrivate(int id,
819822
const Buffer<const unsigned char>& data);
823+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
824+
static EVPKeyPointer NewRawSeed(int id,
825+
const Buffer<const unsigned char>& data);
826+
#endif
820827
static EVPKeyPointer NewDH(DHPointer&& dh);
821828
static EVPKeyPointer NewRSA(RSAPointer&& rsa);
822829

@@ -910,6 +917,10 @@ class EVPKeyPointer final {
910917
DataPointer rawPrivateKey() const;
911918
BIOPointer derPublicKey() const;
912919

920+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
921+
DataPointer rawSeed() const;
922+
#endif
923+
913924
Result<BIOPointer, bool> writePrivateKey(
914925
const PrivateKeyEncodingConfig& config) const;
915926
Result<BIOPointer, bool> writePublicKey(

0 commit comments

Comments
 (0)