Skip to content

Commit 12d244a

Browse files
panvanpaun
authored andcommitted
crypto: support ML-DSA KeyObject, sign, and verify
PR-URL: nodejs/node#59259 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Ethan Arrowood <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 527ff15 commit 12d244a

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

include/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
@@ -703,6 +706,10 @@ class EVPKeyPointer final {
703706
const Buffer<const unsigned char>& data);
704707
static EVPKeyPointer NewRawPrivate(int id,
705708
const Buffer<const unsigned char>& data);
709+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
710+
static EVPKeyPointer NewRawSeed(int id,
711+
const Buffer<const unsigned char>& data);
712+
#endif
706713
static EVPKeyPointer NewDH(DHPointer&& dh);
707714
static EVPKeyPointer NewRSA(RSAPointer&& rsa);
708715

@@ -794,6 +801,10 @@ class EVPKeyPointer final {
794801
DataPointer rawPrivateKey() const;
795802
BIOPointer derPublicKey() const;
796803

804+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
805+
DataPointer rawSeed() const;
806+
#endif
807+
797808
Result<BIOPointer, bool> writePrivateKey(
798809
const PrivateKeyEncodingConfig& config) const;
799810
Result<BIOPointer, bool> writePublicKey(

src/ncrypto.cpp

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,31 @@ EVPKeyPointer EVPKeyPointer::NewRawPrivate(
18631863
EVP_PKEY_new_raw_private_key(id, nullptr, data.data, data.len));
18641864
}
18651865

1866+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
1867+
EVPKeyPointer EVPKeyPointer::NewRawSeed(
1868+
int id, const Buffer<const unsigned char>& data) {
1869+
if (id == 0) return {};
1870+
1871+
OSSL_PARAM params[] = {
1872+
OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_DSA_SEED,
1873+
const_cast<unsigned char*>(data.data),
1874+
data.len),
1875+
OSSL_PARAM_END};
1876+
1877+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(id, nullptr);
1878+
if (ctx == nullptr) return {};
1879+
1880+
EVP_PKEY* pkey = nullptr;
1881+
if (ctx == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 ||
1882+
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
1883+
EVP_PKEY_CTX_free(ctx);
1884+
return {};
1885+
}
1886+
1887+
return EVPKeyPointer(pkey);
1888+
}
1889+
#endif
1890+
18661891
EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) {
18671892
#ifndef NCRYPTO_NO_EVP_DH
18681893
if (!dh) return {};
@@ -1914,7 +1939,16 @@ EVP_PKEY* EVPKeyPointer::release() { return pkey_.release(); }
19141939

19151940
int EVPKeyPointer::id(const EVP_PKEY* key) {
19161941
if (key == nullptr) return 0;
1917-
return EVP_PKEY_id(key);
1942+
int type = EVP_PKEY_id(key);
1943+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
1944+
// https://github.com/openssl/openssl/issues/27738#issuecomment-3013215870
1945+
if (type == -1) {
1946+
if (EVP_PKEY_is_a(key, "ML-DSA-44")) return EVP_PKEY_ML_DSA_44;
1947+
if (EVP_PKEY_is_a(key, "ML-DSA-65")) return EVP_PKEY_ML_DSA_65;
1948+
if (EVP_PKEY_is_a(key, "ML-DSA-87")) return EVP_PKEY_ML_DSA_87;
1949+
}
1950+
#endif
1951+
return type;
19181952
}
19191953

19201954
int EVPKeyPointer::base_id(const EVP_PKEY* key) {
@@ -1966,6 +2000,31 @@ DataPointer EVPKeyPointer::rawPublicKey() const {
19662000
return {};
19672001
}
19682002

2003+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2004+
DataPointer EVPKeyPointer::rawSeed() const {
2005+
if (!pkey_) return {};
2006+
switch (id()) {
2007+
case EVP_PKEY_ML_DSA_44:
2008+
case EVP_PKEY_ML_DSA_65:
2009+
case EVP_PKEY_ML_DSA_87:
2010+
break;
2011+
default:
2012+
unreachable();
2013+
}
2014+
2015+
size_t seed_len = 32;
2016+
if (auto data = DataPointer::Alloc(seed_len)) {
2017+
const Buffer<unsigned char> buf = data;
2018+
size_t len = data.size();
2019+
if (EVP_PKEY_get_octet_string_param(
2020+
get(), OSSL_PKEY_PARAM_ML_DSA_SEED, buf.data, len, &seed_len) != 1)
2021+
return {};
2022+
return data;
2023+
}
2024+
return {};
2025+
}
2026+
#endif
2027+
19692028
DataPointer EVPKeyPointer::rawPrivateKey() const {
19702029
if (!pkey_) return {};
19712030
if (auto data = DataPointer::Alloc(rawPrivateKeySize())) {
@@ -2390,7 +2449,18 @@ bool EVPKeyPointer::isRsaVariant() const {
23902449
bool EVPKeyPointer::isOneShotVariant() const {
23912450
if (!pkey_) return false;
23922451
int type = id();
2393-
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
2452+
switch (type) {
2453+
case EVP_PKEY_ED25519:
2454+
case EVP_PKEY_ED448:
2455+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2456+
case EVP_PKEY_ML_DSA_44:
2457+
case EVP_PKEY_ML_DSA_65:
2458+
case EVP_PKEY_ML_DSA_87:
2459+
#endif
2460+
return true;
2461+
default:
2462+
return false;
2463+
}
23942464
}
23952465

23962466
bool EVPKeyPointer::isSigVariant() const {

0 commit comments

Comments
 (0)