Skip to content

Commit 0252ff3

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 9039120 commit 0252ff3

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
@@ -712,6 +715,10 @@ class EVPKeyPointer final {
712715
const Buffer<const unsigned char>& data);
713716
static EVPKeyPointer NewRawPrivate(int id,
714717
const Buffer<const unsigned char>& data);
718+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
719+
static EVPKeyPointer NewRawSeed(int id,
720+
const Buffer<const unsigned char>& data);
721+
#endif
715722
static EVPKeyPointer NewDH(DHPointer&& dh);
716723
static EVPKeyPointer NewRSA(RSAPointer&& rsa);
717724

@@ -805,6 +812,10 @@ class EVPKeyPointer final {
805812
DataPointer rawPrivateKey() const;
806813
BIOPointer derPublicKey() const;
807814

815+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
816+
DataPointer rawSeed() const;
817+
#endif
818+
808819
Result<BIOPointer, bool> writePrivateKey(
809820
const PrivateKeyEncodingConfig& config) const;
810821
Result<BIOPointer, bool> writePublicKey(

src/ncrypto.cpp

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,31 @@ EVPKeyPointer EVPKeyPointer::NewRawPrivate(
19831983
EVP_PKEY_new_raw_private_key(id, nullptr, data.data, data.len));
19841984
}
19851985

1986+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
1987+
EVPKeyPointer EVPKeyPointer::NewRawSeed(
1988+
int id, const Buffer<const unsigned char>& data) {
1989+
if (id == 0) return {};
1990+
1991+
OSSL_PARAM params[] = {
1992+
OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_ML_DSA_SEED,
1993+
const_cast<unsigned char*>(data.data),
1994+
data.len),
1995+
OSSL_PARAM_END};
1996+
1997+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(id, nullptr);
1998+
if (ctx == nullptr) return {};
1999+
2000+
EVP_PKEY* pkey = nullptr;
2001+
if (ctx == nullptr || EVP_PKEY_fromdata_init(ctx) <= 0 ||
2002+
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
2003+
EVP_PKEY_CTX_free(ctx);
2004+
return {};
2005+
}
2006+
2007+
return EVPKeyPointer(pkey);
2008+
}
2009+
#endif
2010+
19862011
EVPKeyPointer EVPKeyPointer::NewDH(DHPointer&& dh) {
19872012
#ifndef NCRYPTO_NO_EVP_DH
19882013
if (!dh) return {};
@@ -2040,7 +2065,16 @@ EVP_PKEY* EVPKeyPointer::release() {
20402065

20412066
int EVPKeyPointer::id(const EVP_PKEY* key) {
20422067
if (key == nullptr) return 0;
2043-
return EVP_PKEY_id(key);
2068+
int type = EVP_PKEY_id(key);
2069+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2070+
// https://github.com/openssl/openssl/issues/27738#issuecomment-3013215870
2071+
if (type == -1) {
2072+
if (EVP_PKEY_is_a(key, "ML-DSA-44")) return EVP_PKEY_ML_DSA_44;
2073+
if (EVP_PKEY_is_a(key, "ML-DSA-65")) return EVP_PKEY_ML_DSA_65;
2074+
if (EVP_PKEY_is_a(key, "ML-DSA-87")) return EVP_PKEY_ML_DSA_87;
2075+
}
2076+
#endif
2077+
return type;
20442078
}
20452079

20462080
int EVPKeyPointer::base_id(const EVP_PKEY* key) {
@@ -2096,6 +2130,31 @@ DataPointer EVPKeyPointer::rawPublicKey() const {
20962130
return {};
20972131
}
20982132

2133+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2134+
DataPointer EVPKeyPointer::rawSeed() const {
2135+
if (!pkey_) return {};
2136+
switch (id()) {
2137+
case EVP_PKEY_ML_DSA_44:
2138+
case EVP_PKEY_ML_DSA_65:
2139+
case EVP_PKEY_ML_DSA_87:
2140+
break;
2141+
default:
2142+
unreachable();
2143+
}
2144+
2145+
size_t seed_len = 32;
2146+
if (auto data = DataPointer::Alloc(seed_len)) {
2147+
const Buffer<unsigned char> buf = data;
2148+
size_t len = data.size();
2149+
if (EVP_PKEY_get_octet_string_param(
2150+
get(), OSSL_PKEY_PARAM_ML_DSA_SEED, buf.data, len, &seed_len) != 1)
2151+
return {};
2152+
return data;
2153+
}
2154+
return {};
2155+
}
2156+
#endif
2157+
20992158
DataPointer EVPKeyPointer::rawPrivateKey() const {
21002159
if (!pkey_) return {};
21012160
if (auto data = DataPointer::Alloc(rawPrivateKeySize())) {
@@ -2546,7 +2605,18 @@ bool EVPKeyPointer::isRsaVariant() const {
25462605
bool EVPKeyPointer::isOneShotVariant() const {
25472606
if (!pkey_) return false;
25482607
int type = id();
2549-
return type == EVP_PKEY_ED25519 || type == EVP_PKEY_ED448;
2608+
switch (type) {
2609+
case EVP_PKEY_ED25519:
2610+
case EVP_PKEY_ED448:
2611+
#if OPENSSL_VERSION_MAJOR >= 3 && OPENSSL_VERSION_MINOR >= 5
2612+
case EVP_PKEY_ML_DSA_44:
2613+
case EVP_PKEY_ML_DSA_65:
2614+
case EVP_PKEY_ML_DSA_87:
2615+
#endif
2616+
return true;
2617+
default:
2618+
return false;
2619+
}
25502620
}
25512621

25522622
bool EVPKeyPointer::isSigVariant() const {

0 commit comments

Comments
 (0)