nss/nss-3.112-add-sec384r1-mlkem-1024.patch
Robert Relyea 2a8572a8f9 Resolves: RHEL-103353
rebase NSS to 3.112
Include mlkem1024 support and ml-dsa support for tls
2025-07-14 09:01:26 -07:00

2150 lines
79 KiB
Diff

diff --git a/cmd/lib/secutil.c b/cmd/lib/secutil.c
--- a/cmd/lib/secutil.c
+++ b/cmd/lib/secutil.c
@@ -4212,17 +4212,21 @@ static const struct SSLNamedGroupString
{ NAME_AND_LEN("FF3072"), ssl_grp_ffdhe_3072 },
{ NAME_AND_LEN("FF4096"), ssl_grp_ffdhe_4096 },
{ NAME_AND_LEN("FF6144"), ssl_grp_ffdhe_6144 },
{ NAME_AND_LEN("FF8192"), ssl_grp_ffdhe_8192 },
#ifndef NSS_DISABLE_KYBER
{ NAME_AND_LEN("xyber76800"), ssl_grp_kem_xyber768d00 },
#endif
+ { NAME_AND_LEN("x25519mlkem768"), ssl_grp_kem_mlkem768x25519 },
{ NAME_AND_LEN("mlkem768x25519"), ssl_grp_kem_mlkem768x25519 },
+ { NAME_AND_LEN("secp256r1mlkem768"), ssl_grp_kem_secp256r1mlkem768 },
{ NAME_AND_LEN("mlkem768secp256r1"), ssl_grp_kem_secp256r1mlkem768 },
+ { NAME_AND_LEN("secp384r1mlkem1024"), ssl_grp_kem_secp384r1mlkem1024 },
+ { NAME_AND_LEN("mlkem1024secp384r1"), ssl_grp_kem_secp384r1mlkem1024},
};
static const size_t sslNamedGroupStringLen=PR_ARRAY_SIZE(sslNamedGroupStringArray);
static SSLNamedGroup
groupNameToNamedGroup(char *name)
{
int len = PL_strlen(name);
@@ -4231,21 +4235,16 @@ groupNameToNamedGroup(char *name)
for (i=0; i < sslNamedGroupStringLen; i++) {
const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i];
if (len == ngs->len) {
if (!strncmp(name, ngs->name, len)) {
return ngs->grp;
}
}
}
- if (PL_strlen(name) == 14) {
- if (!strncmp(name, "mlkem768x25519", 14)) {
- return ssl_grp_kem_mlkem768x25519;
- }
- }
return ssl_grp_none;
}
static SECStatus
countItems(const char *arg, unsigned int *numItems)
{
char *str = PORT_Strdup(arg);
diff --git a/cmd/selfserv/selfserv.c b/cmd/selfserv/selfserv.c
--- a/cmd/selfserv/selfserv.c
+++ b/cmd/selfserv/selfserv.c
@@ -226,17 +226,17 @@ PrintParameterUsage()
"-Q enables ALPN for HTTP/1.1 [RFC7301]\n"
"-I comma separated list of enabled groups for TLS key exchange.\n"
" The following values are valid:\n"
" P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192,\n"
" "
#ifndef NSS_DISABLE_KYBER
"xyber768d00, "
#endif
- "mlkem768x25519, mlkem768secp256r1\n"
+ "x25519mlkem768, secp256r1mlkem768, secp384r1mlkem1024\n"
"-J comma separated list of enabled signature schemes in preference order.\n"
" The following values are valid:\n"
" rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
" ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
" ecdsa_secp521r1_sha512,\n"
" rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
" rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
"-Z enable 0-RTT (for TLS 1.3; also use -u)\n"
diff --git a/cmd/tstclnt/tstclnt.c b/cmd/tstclnt/tstclnt.c
--- a/cmd/tstclnt/tstclnt.c
+++ b/cmd/tstclnt/tstclnt.c
@@ -309,17 +309,17 @@ PrintParameterUsage()
fprintf(stderr, "%-20s Disconnect and reconnect up to N times total\n", "-L");
fprintf(stderr, "%-20s Comma separated list of enabled groups for TLS key exchange.\n"
"%-20s The following values are valid:\n"
"%-20s P256, P384, P521, x25519, FF2048, FF3072, FF4096, FF6144, FF8192\n"
"%-20s "
#ifndef NSS_DISABLE_KYBER
"xyber768d00, "
#endif
- "mlkem768x25519, mlkem768secp256r1\n",
+ "x25519mlkem768, secp256r1mlkem768, secp384r1mlkem1024\n",
"-I", "", "", "");
fprintf(stderr, "%-20s Comma separated list of signature schemes in preference order.\n"
"%-20s The following values are valid:\n"
"%-20s rsa_pkcs1_sha1, rsa_pkcs1_sha256, rsa_pkcs1_sha384, rsa_pkcs1_sha512,\n"
"%-20s ecdsa_sha1, ecdsa_secp256r1_sha256, ecdsa_secp384r1_sha384,\n"
"%-20s ecdsa_secp521r1_sha512,\n"
"%-20s rsa_pss_rsae_sha256, rsa_pss_rsae_sha384, rsa_pss_rsae_sha512,\n"
"%-20s rsa_pss_pss_sha256, rsa_pss_pss_sha384, rsa_pss_pss_sha512,\n"
diff --git a/gtests/pk11_gtest/pk11_keygen.cc b/gtests/pk11_gtest/pk11_keygen.cc
--- a/gtests/pk11_gtest/pk11_keygen.cc
+++ b/gtests/pk11_gtest/pk11_keygen.cc
@@ -162,15 +162,20 @@ std::unique_ptr<ParamHolder> Pkcs11KeyPa
return std::unique_ptr<ParamHolder>(
new KyberParamHolder(CKP_NSS_KYBER_768_ROUND3));
case CKM_NSS_ML_KEM_KEY_PAIR_GEN:
std::cerr << "Generate ML-KEM768 pair" << std::endl;
return std::unique_ptr<ParamHolder>(
new KyberParamHolder(CKP_NSS_ML_KEM_768));
+ case CKM_ML_KEM_KEY_PAIR_GEN:
+ std::cerr << "Generate ML-KEM1024 pair" << std::endl;
+ return std::unique_ptr<ParamHolder>(
+ new KyberParamHolder(CKP_ML_KEM_1024));
+
default:
- ADD_FAILURE() << "unknown OID " << mech_;
+ ADD_FAILURE() << "unknown Mechanism " << mech_;
}
return nullptr;
}
} // namespace nss_test
diff --git a/gtests/pk11_gtest/pk11_kem_unittest.cc b/gtests/pk11_gtest/pk11_kem_unittest.cc
--- a/gtests/pk11_gtest/pk11_kem_unittest.cc
+++ b/gtests/pk11_gtest/pk11_kem_unittest.cc
@@ -69,41 +69,50 @@ class Pkcs11KEMTest
}
CK_MECHANISM_TYPE keyGenMech() {
switch (GetParam()) {
case CKP_NSS_KYBER_768_ROUND3:
return CKM_NSS_KYBER_KEY_PAIR_GEN;
case CKP_NSS_ML_KEM_768:
return CKM_NSS_ML_KEM_KEY_PAIR_GEN;
+ case CKP_ML_KEM_768:
+ case CKP_ML_KEM_1024:
+ return CKM_ML_KEM_KEY_PAIR_GEN;
default:
EXPECT_TRUE(false);
return 0;
}
}
CK_MECHANISM_TYPE encapsMech() {
switch (GetParam()) {
case CKP_NSS_KYBER_768_ROUND3:
return CKM_NSS_KYBER;
case CKP_NSS_ML_KEM_768:
return CKM_NSS_ML_KEM;
+ case CKP_ML_KEM_768:
+ case CKP_ML_KEM_1024:
+ return CKM_ML_KEM;
default:
EXPECT_TRUE(false);
return 0;
}
}
};
TEST_P(Pkcs11KEMTest, KemConsistencyTest) {
Pkcs11KeyPairGenerator generator(keyGenMech());
ScopedSECKEYPrivateKey priv;
ScopedSECKEYPublicKey pub;
generator.GenerateKey(&priv, &pub, false);
+ ASSERT_NE(nullptr, pub);
+ ASSERT_NE(nullptr, priv);
+
// Copy the public key to simulate receiving the key as an octet string
ScopedSECKEYPublicKey pubCopy(SECKEY_CopyPublicKey(pub.get()));
ASSERT_NE(nullptr, pubCopy);
ScopedPK11SlotInfo slot(PK11_GetBestSlot(encapsMech(), nullptr));
ASSERT_NE(nullptr, slot);
ASSERT_NE((unsigned int)CK_INVALID_HANDLE,
@@ -139,11 +148,13 @@ TEST_P(Pkcs11KEMTest, KemConsistencyTest
EXPECT_EQ(0, SECITEM_CompareItem(item1, item2));
}
INSTANTIATE_TEST_SUITE_P(Pkcs11KEMTest, Pkcs11KEMTest,
::testing::Values(
#ifndef NSS_DISABLE_KYBER
CKP_NSS_KYBER_768_ROUND3,
#endif
+ CKP_ML_KEM_768,
+ CKP_ML_KEM_1024,
CKP_NSS_ML_KEM_768));
} // namespace nss_test
diff --git a/gtests/ssl_gtest/tls_agent.cc b/gtests/ssl_gtest/tls_agent.cc
--- a/gtests/ssl_gtest/tls_agent.cc
+++ b/gtests/ssl_gtest/tls_agent.cc
@@ -521,53 +521,57 @@ void TlsAgent::DisableAllCiphers() {
const std::vector<SSLNamedGroup> kAllDHEGroups = {
ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072,
ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192,
#ifndef NSS_DISABLE_KYBER
ssl_grp_kem_xyber768d00,
#endif
ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768,
+ ssl_grp_kem_secp384r1mlkem1024,
};
const std::vector<SSLNamedGroup> kNonPQDHEGroups = {
ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
ssl_grp_ec_secp521r1, ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072,
ssl_grp_ffdhe_4096, ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192,
};
const std::vector<SSLNamedGroup> kECDHEGroups = {
ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
ssl_grp_ec_secp521r1,
#ifndef NSS_DISABLE_KYBER
ssl_grp_kem_xyber768d00,
#endif
- ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768
+ ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768,
+ ssl_grp_kem_secp384r1mlkem1024,
};
const std::vector<SSLNamedGroup> kFFDHEGroups = {
ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072, ssl_grp_ffdhe_4096,
ssl_grp_ffdhe_6144, ssl_grp_ffdhe_8192};
// Defined because the big DHE groups are ridiculously slow.
const std::vector<SSLNamedGroup> kFasterDHEGroups = {
ssl_grp_ec_curve25519, ssl_grp_ec_secp256r1, ssl_grp_ec_secp384r1,
ssl_grp_ffdhe_2048, ssl_grp_ffdhe_3072,
#ifndef NSS_DISABLE_KYBER
ssl_grp_kem_xyber768d00,
#endif
ssl_grp_kem_mlkem768x25519, ssl_grp_kem_secp256r1mlkem768,
+ ssl_grp_kem_secp384r1mlkem1024,
};
const std::vector<SSLNamedGroup> kEcdhHybridGroups = {
#ifndef NSS_DISABLE_KYBER
ssl_grp_kem_xyber768d00,
#endif
ssl_grp_kem_mlkem768x25519,
ssl_grp_kem_secp256r1mlkem768,
+ ssl_grp_kem_secp384r1mlkem1024,
};
void TlsAgent::EnableCiphersByKeyExchange(SSLKEAType kea) {
EXPECT_TRUE(EnsureTlsSetup());
for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) {
SSLCipherSuiteInfo csinfo;
@@ -735,16 +739,19 @@ void TlsAgent::CheckKEA(SSLKEAType kea,
#endif
case ssl_grp_kem_mlkem768x25519:
kea_size = 255;
break;
case ssl_grp_ec_secp256r1:
case ssl_grp_kem_secp256r1mlkem768:
kea_size = 256;
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ kea_size = 384;
+ break;
case ssl_grp_ec_secp384r1:
kea_size = 384;
break;
case ssl_grp_ffdhe_2048:
kea_size = 2048;
break;
case ssl_grp_ffdhe_3072:
kea_size = 3072;
diff --git a/gtests/ssl_gtest/tls_mlkem_unittest.cc b/gtests/ssl_gtest/tls_mlkem_unittest.cc
--- a/gtests/ssl_gtest/tls_mlkem_unittest.cc
+++ b/gtests/ssl_gtest/tls_mlkem_unittest.cc
@@ -35,16 +35,25 @@ TEST_P(TlsKeyExchangeTest13, Mlkem768Sec
EnsureKeyShareSetup();
ConfigNamedGroups({ssl_grp_kem_secp256r1mlkem768});
Connect();
CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_secp256r1mlkem768,
ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256);
}
+TEST_P(TlsKeyExchangeTest13, Mlkem1024Secp384r1Supported) {
+ EnsureKeyShareSetup();
+ ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024});
+
+ Connect();
+ CheckKeys(ssl_kea_ecdh_hybrid, ssl_grp_kem_secp384r1mlkem1024,
+ ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256);
+}
+
TEST_P(TlsKeyExchangeTest, Tls12ClientMlkem768StartNotSupported) {
EnsureKeyShareSetup();
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
client_->DisableAllCiphers();
client_->EnableCiphersByKeyExchange(ssl_kea_ecdh);
@@ -53,16 +62,17 @@ TEST_P(TlsKeyExchangeTest, Tls12ClientMl
client_->ssl_fd(),
kECDHEGroups.size() + kEcdhHybridGroups.size()));
Connect();
std::vector<SSLNamedGroup> groups = GetGroupDetails(groups_capture_);
for (auto group : groups) {
EXPECT_NE(group, ssl_grp_kem_mlkem768x25519);
EXPECT_NE(group, ssl_grp_kem_secp256r1mlkem768);
+ EXPECT_NE(group, ssl_grp_kem_secp384r1mlkem1024);
}
}
TEST_P(TlsKeyExchangeTest13, Tls12ServerMlkem768x25519NotSupported) {
EnsureKeyShareSetup();
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
@@ -127,43 +137,63 @@ TEST_P(TlsKeyExchangeTest13, Mlkem768x25
Connect();
CheckKEXDetails({ssl_grp_kem_mlkem768x25519, ssl_grp_ec_secp256r1},
{ssl_grp_kem_mlkem768x25519}, ssl_grp_ec_secp256r1);
}
TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ClientDisabledByPolicy) {
EnsureKeyShareSetup();
- client_->SetPolicy(SEC_OID_SECP256R1MLKEM768, 0, NSS_USE_ALG_IN_SSL_KX);
+ client_->SetPolicy(SEC_OID_SECP256R1MLKEM768, 0, NSS_USE_ALG_IN_SSL_KX);
ConfigNamedGroups({ssl_grp_kem_secp256r1mlkem768, ssl_grp_ec_secp256r1});
Connect();
CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1});
}
TEST_P(TlsKeyExchangeTest13, Mlkem768Secp256r1ServerDisabledByPolicy) {
EnsureKeyShareSetup();
- server_->SetPolicy(SEC_OID_SECP256R1MLKEM768, 0, NSS_USE_ALG_IN_SSL_KX);
+ server_->SetPolicy(SEC_OID_SECP256R1MLKEM768, 0, NSS_USE_ALG_IN_SSL_KX);
ConfigNamedGroups({ssl_grp_kem_secp256r1mlkem768, ssl_grp_ec_secp256r1});
Connect();
CheckKEXDetails({ssl_grp_kem_secp256r1mlkem768, ssl_grp_ec_secp256r1},
{ssl_grp_kem_secp256r1mlkem768}, ssl_grp_ec_secp256r1);
}
+TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ClientDisabledByPolicy) {
+ EnsureKeyShareSetup();
+ client_->SetPolicy(SEC_OID_SECP384R1MLKEM1024, 0, NSS_USE_ALG_IN_SSL_KX);
+ ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1});
+
+ Connect();
+ CheckKEXDetails({ssl_grp_ec_secp256r1}, {ssl_grp_ec_secp256r1});
+}
+
+TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ServerDisabledByPolicy) {
+ EnsureKeyShareSetup();
+ server_->SetPolicy(SEC_OID_SECP384R1MLKEM1024, 0, NSS_USE_ALG_IN_SSL_KX);
+ ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1});
+
+ Connect();
+ CheckKEXDetails({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp256r1},
+ {ssl_grp_kem_secp384r1mlkem1024}, ssl_grp_ec_secp256r1);
+}
+
static void CheckECDHShareReuse(
const std::shared_ptr<TlsExtensionCapture>& capture) {
EXPECT_TRUE(capture->captured());
const DataBuffer& ext = capture->extension();
- DataBuffer hybrid_share[4];
- DataBuffer ecdh_share[4];
- int hybrid_offset[4];
- SSLNamedGroup hybrid_ec_type[4];
- SSLNamedGroup ec_type[4];
- int ecdh_index[4];
+ const int max_count=4;
+ DataBuffer hybrid_share[max_count];
+ DataBuffer ecdh_share[max_count];
+ int hybrid_offset[max_count];
+ SSLNamedGroup hybrid_ec_type[max_count];
+ SSLNamedGroup ec_type[max_count];
+ int ecdh_index[max_count];
int nextHybrid = 0;
int nextECDH = 0;
size_t offset = 0;
uint32_t ext_len;
ext.Read(0, 2, &ext_len);
EXPECT_EQ(ext.len() - 2, ext_len);
offset += 2;
@@ -180,30 +210,40 @@ static void CheckECDHShareReuse(
hybrid_ec_type[nextHybrid] = ssl_grp_ec_curve25519;
nextHybrid++;
break;
case ssl_grp_kem_secp256r1mlkem768:
hybrid_share[nextHybrid] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len);
hybrid_offset[nextHybrid] = 0;
hybrid_ec_type[nextHybrid] = ssl_grp_ec_secp256r1;
nextHybrid++;
+ break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ hybrid_share[nextHybrid] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len);
+ hybrid_offset[nextHybrid] = 0;
+ hybrid_ec_type[nextHybrid] = ssl_grp_ec_secp384r1;
+ nextHybrid++;
+ break;
case ssl_grp_ec_curve25519:
case ssl_grp_ec_secp256r1:
+ case ssl_grp_ec_secp384r1:
ecdh_share[nextECDH] = DataBuffer(ext.data() + offset + 2 + 2, named_group_len);
ec_type[nextECDH] = (SSLNamedGroup) named_group;
nextECDH++;
}
offset += 2 + 2 + named_group_len;
ext.Read(offset, 2, &named_group);
ext.Read(offset + 2, 2, &named_group_len);
}
EXPECT_EQ(offset, ext.len());
ASSERT_TRUE(nextECDH > 0);
ASSERT_TRUE(nextHybrid > 0);
+ ASSERT_TRUE(nextECDH <= max_count);
+ ASSERT_TRUE(nextHybrid <= max_count);
/* setup the hybrid ecdh indeces */
for (int i=0; i < nextHybrid; i++) {
ecdh_index[i] = -1;
for (int j=0; j < nextECDH; j++) {
if (hybrid_ec_type[i] == ec_type[j]) {
ecdh_index[i] = j;
break;
}
@@ -265,16 +305,40 @@ TEST_P(TlsKeyExchangeTest13, Mlkem768Sec
Connect();
CheckKEXDetails({ssl_grp_ec_secp256r1, ssl_grp_kem_secp256r1mlkem768},
{ssl_grp_ec_secp256r1, ssl_grp_kem_secp256r1mlkem768});
CheckECDHShareReuse(shares_capture_);
}
+TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ShareReuseFirst) {
+ EnsureKeyShareSetup();
+ ConfigNamedGroups({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1});
+ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
+
+ Connect();
+
+ CheckKEXDetails({ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1},
+ {ssl_grp_kem_secp384r1mlkem1024, ssl_grp_ec_secp384r1});
+ CheckECDHShareReuse(shares_capture_);
+}
+
+TEST_P(TlsKeyExchangeTest13, Secp384r1Mlkem1024ShareReuseSecond) {
+ EnsureKeyShareSetup();
+ ConfigNamedGroups({ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024});
+ EXPECT_EQ(SECSuccess, SSL_SendAdditionalKeyShares(client_->ssl_fd(), 1));
+
+ Connect();
+
+ CheckKEXDetails({ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024},
+ {ssl_grp_ec_secp384r1, ssl_grp_kem_secp384r1mlkem1024});
+ CheckECDHShareReuse(shares_capture_);
+}
+
class Mlkem768x25519ShareDamager : public TlsExtensionFilter {
public:
typedef enum {
downgrade,
extend,
truncate,
zero_ecdh,
modify_ecdh,
diff --git a/lib/freebl/Makefile b/lib/freebl/Makefile
--- a/lib/freebl/Makefile
+++ b/lib/freebl/Makefile
@@ -594,17 +594,22 @@ ifndef NSS_DISABLE_CHACHAPOLY
EXTRA_SRCS += Hacl_Poly1305_128.c Hacl_Chacha20_Vec128.c Hacl_Chacha20Poly1305_128.c
DEFINES += -DHACL_CAN_COMPILE_VEC128
endif
endif # x86_64
VERIFIED_SRCS += Hacl_Poly1305_32.c Hacl_Chacha20.c Hacl_Chacha20Poly1305_32.c
endif # NSS_DISABLE_CHACHAPOLY
+ifndef NSS_DISABLE_KYBER
+KYBER_PQCRYSTALS = kyber-pqcrystals-ref.c
+endif
+
VERIFIED_SRCS += Hacl_Hash_SHA3.c Hacl_P256.c Hacl_P384.c Hacl_P521.c libcrux_mlkem768_portable.c libcrux_mlkem_portable.c libcrux_core.c
+VERIFIED_SRCS += libcrux_mlkem1024_portable.c
VERIFIED_SRCS += Hacl_Ed25519.c
VERIFIED_SRCS += Hacl_Curve25519_51.c
# Bug 1918767 / Bug 1918711 - by setting KRML_MUSTINLINE=inline here, we
# avoid it being defined to `inline __forceinline` (for msvc) or `inline
# __attribute__((always_inline))` (for gcc/clang) in
# verified/karamel/include/krml/internal/target.h. These other
# configurations can cause excessive stack usage.
diff --git a/lib/freebl/freebl_base.gypi b/lib/freebl/freebl_base.gypi
--- a/lib/freebl/freebl_base.gypi
+++ b/lib/freebl/freebl_base.gypi
@@ -27,17 +27,16 @@
'ecl/ecp_secp521r1.c',
'fipsfreebl.c',
'blinit.c',
'freeblver.c',
'gcm.c',
'hmacct.c',
'jpake.c',
'kyber.c',
- 'kyber-pqcrystals-ref.c',
'ldvector.c',
'md2.c',
'md5.c',
'mpi/mp_gf2m.c',
'mpi/mpcpucache.c',
'mpi/mpi.c',
'mpi/mplogic.c',
'mpi/mpmontg.c',
@@ -228,13 +227,25 @@
'MP_IS_LITTLE_ENDIAN',
'MPI_AMD64',
'MP_ASSEMBLY_MULTIPLY',
'NSS_USE_COMBA',
],
}],
],
}],
+ [ 'no_kyber_support==0', {
+ 'sources': [
+ 'kyber-pqcrystals-ref.c',
+ ],
+ }]
+ [ 'ml_kem_1024_support==1', {
+ 'sources': [
+ 'verified/libcrux_mlkem1024_portable.c',
+ ],
+ }]
+
+
],
'ldflags': [
'-Wl,-Bsymbolic'
],
}
diff --git a/lib/freebl/kyber.c b/lib/freebl/kyber.c
--- a/lib/freebl/kyber.c
+++ b/lib/freebl/kyber.c
@@ -12,126 +12,168 @@
#include "secerr.h"
#include "secitem.h"
#include "kyber-pqcrystals-ref.h"
#include "kyber.h"
#include "verified/internal/libcrux_core.h"
#include "verified/libcrux_mlkem768_portable.h"
#include "verified/libcrux_mlkem768.h"
+#include "verified/libcrux_mlkem1024_portable.h"
+#include "verified/libcrux_mlkem1024.h"
/* Consistency check between kyber-pqcrystals-ref.h and kyber.h */
PR_STATIC_ASSERT(KYBER768_PUBLIC_KEY_BYTES == pqcrystals_kyber768_PUBLICKEYBYTES);
PR_STATIC_ASSERT(KYBER768_PRIVATE_KEY_BYTES == pqcrystals_kyber768_SECRETKEYBYTES);
PR_STATIC_ASSERT(KYBER768_CIPHERTEXT_BYTES == pqcrystals_kyber768_CIPHERTEXTBYTES);
PR_STATIC_ASSERT(KYBER_SHARED_SECRET_BYTES == pqcrystals_kyber768_BYTES);
PR_STATIC_ASSERT(KYBER_KEYPAIR_COIN_BYTES == pqcrystals_kyber768_KEYPAIRCOINBYTES);
PR_STATIC_ASSERT(KYBER_ENC_COIN_BYTES == pqcrystals_kyber768_ENCCOINBYTES);
/* Consistency check between libcrux_mlkem768_portable.h and kyber.h */
PR_STATIC_ASSERT(KYBER768_PUBLIC_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_PUBLIC_KEY_SIZE_768);
PR_STATIC_ASSERT(KYBER768_PRIVATE_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM768_SECRET_KEY_SIZE_768);
PR_STATIC_ASSERT(KYBER768_CIPHERTEXT_BYTES == LIBCRUX_ML_KEM_MLKEM768_CPA_PKE_CIPHERTEXT_SIZE_768);
PR_STATIC_ASSERT(KYBER_SHARED_SECRET_BYTES == LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE);
+
+/* Consistency check between libcrux_mlkem1024_portable.h and kyber.h */
+PR_STATIC_ASSERT(MLKEM1024_PUBLIC_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_PUBLIC_KEY_SIZE_1024);
+PR_STATIC_ASSERT(MLKEM1024_PRIVATE_KEY_BYTES == LIBCRUX_ML_KEM_MLKEM1024_SECRET_KEY_SIZE_1024);
+PR_STATIC_ASSERT(MLKEM1024_CIPHERTEXT_BYTES == LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_CIPHERTEXT_SIZE_1024);
+
PR_STATIC_ASSERT(KYBER_KEYPAIR_COIN_BYTES == 64);
PR_STATIC_ASSERT(KYBER_ENC_COIN_BYTES == 32);
static bool
valid_params(KyberParams params)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
return true;
default:
return false;
}
}
static bool
valid_pubkey(KyberParams params, const SECItem *pubkey)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return pubkey && pubkey->len == KYBER768_PUBLIC_KEY_BYTES;
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return pubkey && pubkey->len ==MLKEM1024_PUBLIC_KEY_BYTES;
default:
return false;
}
}
static bool
valid_privkey(KyberParams params, const SECItem *privkey)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return privkey && privkey->len == KYBER768_PRIVATE_KEY_BYTES;
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return privkey && privkey->len == MLKEM1024_PRIVATE_KEY_BYTES;
default:
return false;
}
}
static bool
valid_ciphertext(KyberParams params, const SECItem *ciphertext)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return ciphertext && ciphertext->len == KYBER768_CIPHERTEXT_BYTES;
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return ciphertext && ciphertext->len == MLKEM1024_CIPHERTEXT_BYTES;
default:
return false;
}
}
static bool
valid_secret(KyberParams params, const SECItem *secret)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
return secret && secret->len == KYBER_SHARED_SECRET_BYTES;
default:
return false;
}
}
static bool
valid_keypair_seed(KyberParams params, const SECItem *seed)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
return !seed || seed->len == KYBER_KEYPAIR_COIN_BYTES;
default:
return false;
}
}
static bool
valid_enc_seed(KyberParams params, const SECItem *seed)
{
switch (params) {
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
+#endif
case params_ml_kem768:
+ case params_ml_kem1024:
return !seed;
+#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3_test_mode:
+#endif
case params_ml_kem768_test_mode:
+ case params_ml_kem1024_test_mode:
+ return !seed;
return !seed || seed->len == KYBER_SHARED_SECRET_BYTES;
default:
return false;
}
}
SECStatus
Kyber_NewKey(KyberParams params, const SECItem *keypair_seed, SECItem *privkey, SECItem *pubkey)
@@ -153,22 +195,28 @@ Kyber_NewKey(KyberParams params, const S
} else {
if (RNG_GenerateGlobalRandomBytes(randbuf, sizeof randbuf) != SECSuccess) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
coins = randbuf;
}
NSS_CLASSIFY(coins, KYBER_KEYPAIR_COIN_BYTES);
- if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
- pqcrystals_kyber768_ref_keypair_derand(pubkey->data, privkey->data, coins);
- } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
+ if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
libcrux_ml_kem_mlkem768_MlKem768KeyPair keys = libcrux_ml_kem_mlkem768_portable_generate_key_pair(coins);
memcpy(pubkey->data, keys.pk.value, KYBER768_PUBLIC_KEY_BYTES);
memcpy(privkey->data, keys.sk.value, KYBER768_PRIVATE_KEY_BYTES);
+ } else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
+ libcrux_ml_kem_mlkem1024_MlKem1024KeyPair keys = libcrux_ml_kem_mlkem1024_portable_generate_key_pair(coins);
+ memcpy(pubkey->data, keys.pk.value, MLKEM1024_PUBLIC_KEY_BYTES);
+ memcpy(privkey->data, keys.sk.value, MLKEM1024_PRIVATE_KEY_BYTES);
+#ifndef NSS_DISABLE_KYBER
+ } else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
+ pqcrystals_kyber768_ref_keypair_derand(pubkey->data, privkey->data, coins);
+#endif
} else {
/* unreachable */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
NSS_DECLASSIFY(pubkey->data, pubkey->len);
return SECSuccess;
}
@@ -193,31 +241,48 @@ Kyber_Encapsulate(KyberParams params, co
} else {
if (RNG_GenerateGlobalRandomBytes(randbuf, sizeof randbuf) != SECSuccess) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
coins = randbuf;
}
NSS_CLASSIFY(coins, KYBER_ENC_COIN_BYTES);
- if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
- pqcrystals_kyber768_ref_enc_derand(ciphertext->data, secret->data, pubkey->data, coins);
- } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
+ if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
+ /* shouldn't this just use the typedef im libcrux_mlkem768.h? */
libcrux_ml_kem_types_MlKemPublicKey_15 pk_value;
memcpy(pk_value.value, pubkey->data, KYBER768_PUBLIC_KEY_BYTES);
bool valid_pk = libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk_value);
if (!valid_pk) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
tuple_3c encap = libcrux_ml_kem_mlkem768_portable_encapsulate(&pk_value, coins);
memcpy(ciphertext->data, encap.fst.value, KYBER768_CIPHERTEXT_BYTES);
memcpy(secret->data, encap.snd, KYBER_SHARED_SECRET_BYTES);
+ } else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
+ /* shouldn't this just use the typedef im libcrux_mlkem1024.h? */
+ libcrux_ml_kem_types_MlKemPublicKey_1f pk_value;
+ memcpy(pk_value.value, pubkey->data, MLKEM1024_PUBLIC_KEY_BYTES);
+
+ bool valid_pk = libcrux_ml_kem_mlkem1024_portable_validate_public_key(&pk_value);
+ if (!valid_pk) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ tuple_21 encap = libcrux_ml_kem_mlkem1024_portable_encapsulate(&pk_value, coins);
+ memcpy(ciphertext->data, encap.fst.value, MLKEM1024_CIPHERTEXT_BYTES);
+ memcpy(secret->data, encap.snd, KYBER_SHARED_SECRET_BYTES);
+#ifndef NSS_DISABLE_KYBER
+ } else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
+ pqcrystals_kyber768_ref_enc_derand(ciphertext->data, secret->data, pubkey->data, coins);
+#endif
} else {
/* unreachable */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return SECSuccess;
}
@@ -230,32 +295,48 @@ Kyber_Decapsulate(KyberParams params, co
return SECFailure;
}
if (!(valid_privkey(params, privkey) && valid_ciphertext(params, ciphertext) && valid_secret(params, secret))) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
- pqcrystals_kyber768_ref_dec(secret->data, ciphertext->data, privkey->data);
- } else if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
+ if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
libcrux_ml_kem_types_MlKemPrivateKey_55 private_key;
memcpy(private_key.value, privkey->data, KYBER768_PRIVATE_KEY_BYTES);
libcrux_ml_kem_mlkem768_MlKem768Ciphertext cipher_text;
memcpy(cipher_text.value, ciphertext->data, KYBER768_CIPHERTEXT_BYTES);
bool valid = libcrux_ml_kem_mlkem768_portable_validate_private_key(&private_key, &cipher_text);
if (!valid) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
libcrux_ml_kem_mlkem768_portable_decapsulate(&private_key, &cipher_text, secret->data);
+ } else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
+ libcrux_ml_kem_types_MlKemPrivateKey_95 private_key;
+ memcpy(private_key.value, privkey->data, MLKEM1024_PRIVATE_KEY_BYTES);
+
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext cipher_text;
+ memcpy(cipher_text.value, ciphertext->data, MLKEM1024_CIPHERTEXT_BYTES);
+
+ bool valid = libcrux_ml_kem_mlkem1024_portable_validate_private_key(&private_key, &cipher_text);
+ if (!valid) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ libcrux_ml_kem_mlkem1024_portable_decapsulate(&private_key, &cipher_text, secret->data);
+#ifndef NSS_DISABLE_KYBER
+ } else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
+ pqcrystals_kyber768_ref_dec(secret->data, ciphertext->data, privkey->data);
+#endif
} else {
// unreachable
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return SECSuccess;
}
diff --git a/lib/freebl/manifest.mn b/lib/freebl/manifest.mn
--- a/lib/freebl/manifest.mn
+++ b/lib/freebl/manifest.mn
@@ -152,17 +152,17 @@ CSRCS = \
rsa.c \
rsa_blind.c \
rsapkcs.c \
shvfy.c \
tlsprfalg.c \
jpake.c \
secmpi.c \
kyber.c \
- kyber-pqcrystals-ref.c \
+ $(KYBER_PQCRYSTALS) \
$(MPI_SRCS) \
$(MPCPU_SRCS) \
$(ECL_SRCS) \
$(VERIFIED_SRCS) \
$(STUBS_SRCS) \
$(LOWHASH_SRCS) \
$(EXTRA_SRCS) \
$(NULL)
diff --git a/lib/freebl/verified/libcrux_mlkem1024.h b/lib/freebl/verified/libcrux_mlkem1024.h
new file mode 100644
--- /dev/null
+++ b/lib/freebl/verified/libcrux_mlkem1024.h
@@ -0,0 +1,94 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Cryspen Sarl <info@cryspen.com>
+ *
+ * SPDX-License-Identifier: MIT or Apache-2.0
+ *
+ * This code was generated with the following revisions:
+ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d
+ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46
+ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0
+ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7
+ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb
+ */
+
+#ifndef __libcrux_mlkem1024_H
+#define __libcrux_mlkem1024_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "eurydice_glue.h"
+#include "libcrux_core.h"
+
+#define LIBCRUX_ML_KEM_MLKEM1024_VECTOR_U_COMPRESSION_FACTOR_1024 ((size_t)11U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_C1_BLOCK_SIZE_1024 \
+ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \
+ LIBCRUX_ML_KEM_MLKEM1024_VECTOR_U_COMPRESSION_FACTOR_1024 / (size_t)8U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_RANK_1024 ((size_t)4U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_C1_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_C1_BLOCK_SIZE_1024 * \
+ LIBCRUX_ML_KEM_MLKEM1024_RANK_1024)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_VECTOR_V_COMPRESSION_FACTOR_1024 ((size_t)5U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_C2_SIZE_1024 \
+ (LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \
+ LIBCRUX_ML_KEM_MLKEM1024_VECTOR_V_COMPRESSION_FACTOR_1024 / (size_t)8U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_CIPHERTEXT_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_C1_SIZE_1024 + \
+ LIBCRUX_ML_KEM_MLKEM1024_C2_SIZE_1024)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_T_AS_NTT_ENCODED_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_RANK_1024 * \
+ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \
+ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_PUBLIC_KEY_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_T_AS_NTT_ENCODED_SIZE_1024 + (size_t)32U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_SECRET_KEY_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_RANK_1024 * \
+ LIBCRUX_ML_KEM_CONSTANTS_COEFFICIENTS_IN_RING_ELEMENT * \
+ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_COEFFICIENT / (size_t)8U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_ETA1 ((size_t)2U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_ETA1_RANDOMNESS_SIZE \
+ (LIBCRUX_ML_KEM_MLKEM1024_ETA1 * (size_t)64U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_ETA2 ((size_t)2U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_ETA2_RANDOMNESS_SIZE \
+ (LIBCRUX_ML_KEM_MLKEM1024_ETA2 * (size_t)64U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_IMPLICIT_REJECTION_HASH_INPUT_SIZE \
+ (LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE + \
+ LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_CIPHERTEXT_SIZE_1024)
+
+typedef libcrux_ml_kem_types_MlKemPrivateKey_95
+ libcrux_ml_kem_mlkem1024_MlKem1024PrivateKey;
+
+typedef libcrux_ml_kem_types_MlKemPublicKey_1f
+ libcrux_ml_kem_mlkem1024_MlKem1024PublicKey;
+
+#define LIBCRUX_ML_KEM_MLKEM1024_RANKED_BYTES_PER_RING_ELEMENT_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_RANK_1024 * \
+ LIBCRUX_ML_KEM_CONSTANTS_BITS_PER_RING_ELEMENT / (size_t)8U)
+
+#define LIBCRUX_ML_KEM_MLKEM1024_SECRET_KEY_SIZE_1024 \
+ (LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_SECRET_KEY_SIZE_1024 + \
+ LIBCRUX_ML_KEM_MLKEM1024_CPA_PKE_PUBLIC_KEY_SIZE_1024 + \
+ LIBCRUX_ML_KEM_CONSTANTS_H_DIGEST_SIZE + \
+ LIBCRUX_ML_KEM_CONSTANTS_SHARED_SECRET_SIZE)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __libcrux_mlkem1024_H_DEFINED
+#endif
diff --git a/lib/freebl/verified/libcrux_mlkem1024_portable.c b/lib/freebl/verified/libcrux_mlkem1024_portable.c
new file mode 100644
--- /dev/null
+++ b/lib/freebl/verified/libcrux_mlkem1024_portable.c
@@ -0,0 +1,192 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Cryspen Sarl <info@cryspen.com>
+ *
+ * SPDX-License-Identifier: MIT or Apache-2.0
+ *
+ * This code was generated with the following revisions:
+ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d
+ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46
+ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0
+ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7
+ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb
+ */
+
+#include "libcrux_mlkem1024_portable.h"
+
+#include "internal/libcrux_mlkem_portable.h"
+
+/**
+ Portable decapsulate
+*/
+/**
+A monomorphic instance of
+libcrux_ml_kem.ind_cca.instantiations.portable.decapsulate with const generics
+- K= 4
+- SECRET_KEY_SIZE= 3168
+- CPA_SECRET_KEY_SIZE= 1536
+- PUBLIC_KEY_SIZE= 1568
+- CIPHERTEXT_SIZE= 1568
+- T_AS_NTT_ENCODED_SIZE= 1536
+- C1_SIZE= 1408
+- C2_SIZE= 160
+- VECTOR_U_COMPRESSION_FACTOR= 11
+- VECTOR_V_COMPRESSION_FACTOR= 5
+- C1_BLOCK_SIZE= 352
+- ETA1= 2
+- ETA1_RANDOMNESS_SIZE= 128
+- ETA2= 2
+- ETA2_RANDOMNESS_SIZE= 128
+- IMPLICIT_REJECTION_HASH_INPUT_SIZE= 1600
+*/
+static void decapsulate_671(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext,
+ uint8_t ret[32U]) {
+ libcrux_ml_kem_ind_cca_decapsulate_1f1(private_key, ciphertext, ret);
+}
+
+/**
+ Decapsulate ML-KEM 1024
+
+ Generates an [`MlKemSharedSecret`].
+ The input is a reference to an [`MlKem1024PrivateKey`] and an
+ [`MlKem1024Ciphertext`].
+*/
+void libcrux_ml_kem_mlkem1024_portable_decapsulate(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext,
+ uint8_t ret[32U]) {
+ decapsulate_671(private_key, ciphertext, ret);
+}
+
+/**
+A monomorphic instance of
+libcrux_ml_kem.ind_cca.instantiations.portable.encapsulate with const generics
+- K= 4
+- CIPHERTEXT_SIZE= 1568
+- PUBLIC_KEY_SIZE= 1568
+- T_AS_NTT_ENCODED_SIZE= 1536
+- C1_SIZE= 1408
+- C2_SIZE= 160
+- VECTOR_U_COMPRESSION_FACTOR= 11
+- VECTOR_V_COMPRESSION_FACTOR= 5
+- VECTOR_U_BLOCK_LEN= 352
+- ETA1= 2
+- ETA1_RANDOMNESS_SIZE= 128
+- ETA2= 2
+- ETA2_RANDOMNESS_SIZE= 128
+*/
+static tuple_21 encapsulate_021(
+ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key,
+ uint8_t randomness[32U]) {
+ libcrux_ml_kem_types_MlKemPublicKey_1f *uu____0 = public_key;
+ /* Passing arrays by value in Rust generates a copy in C */
+ uint8_t copy_of_randomness[32U];
+ memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t));
+ return libcrux_ml_kem_ind_cca_encapsulate_eb1(uu____0, copy_of_randomness);
+}
+
+/**
+ Encapsulate ML-KEM 1024
+
+ Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple.
+ The input is a reference to an [`MlKem1024PublicKey`] and
+ [`SHARED_SECRET_SIZE`] bytes of `randomness`.
+*/
+tuple_21 libcrux_ml_kem_mlkem1024_portable_encapsulate(
+ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key,
+ uint8_t randomness[32U]) {
+ libcrux_ml_kem_types_MlKemPublicKey_1f *uu____0 = public_key;
+ /* Passing arrays by value in Rust generates a copy in C */
+ uint8_t copy_of_randomness[32U];
+ memcpy(copy_of_randomness, randomness, (size_t)32U * sizeof(uint8_t));
+ return encapsulate_021(uu____0, copy_of_randomness);
+}
+
+/**
+ Portable generate key pair.
+*/
+/**
+A monomorphic instance of
+libcrux_ml_kem.ind_cca.instantiations.portable.generate_keypair with const
+generics
+- K= 4
+- CPA_PRIVATE_KEY_SIZE= 1536
+- PRIVATE_KEY_SIZE= 3168
+- PUBLIC_KEY_SIZE= 1568
+- BYTES_PER_RING_ELEMENT= 1536
+- ETA1= 2
+- ETA1_RANDOMNESS_SIZE= 128
+*/
+static libcrux_ml_kem_mlkem1024_MlKem1024KeyPair generate_keypair_871(
+ uint8_t randomness[64U]) {
+ /* Passing arrays by value in Rust generates a copy in C */
+ uint8_t copy_of_randomness[64U];
+ memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t));
+ return libcrux_ml_kem_ind_cca_generate_keypair_f61(copy_of_randomness);
+}
+
+/**
+ Generate ML-KEM 1024 Key Pair
+*/
+libcrux_ml_kem_mlkem1024_MlKem1024KeyPair
+libcrux_ml_kem_mlkem1024_portable_generate_key_pair(uint8_t randomness[64U]) {
+ /* Passing arrays by value in Rust generates a copy in C */
+ uint8_t copy_of_randomness[64U];
+ memcpy(copy_of_randomness, randomness, (size_t)64U * sizeof(uint8_t));
+ return generate_keypair_871(copy_of_randomness);
+}
+
+/**
+ Portable private key validation
+*/
+/**
+A monomorphic instance of
+libcrux_ml_kem.ind_cca.instantiations.portable.validate_private_key with const
+generics
+- K= 4
+- SECRET_KEY_SIZE= 3168
+- CIPHERTEXT_SIZE= 1568
+*/
+static KRML_MUSTINLINE bool validate_private_key_e81(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext) {
+ return libcrux_ml_kem_ind_cca_validate_private_key_dc(private_key,
+ ciphertext);
+}
+
+/**
+ Validate a private key.
+
+ Returns `true` if valid, and `false` otherwise.
+*/
+bool libcrux_ml_kem_mlkem1024_portable_validate_private_key(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext) {
+ return validate_private_key_e81(private_key, ciphertext);
+}
+
+/**
+ Portable public key validation
+*/
+/**
+A monomorphic instance of
+libcrux_ml_kem.ind_cca.instantiations.portable.validate_public_key with const
+generics
+- K= 4
+- RANKED_BYTES_PER_RING_ELEMENT= 1536
+- PUBLIC_KEY_SIZE= 1568
+*/
+static KRML_MUSTINLINE bool validate_public_key_7d1(uint8_t *public_key) {
+ return libcrux_ml_kem_ind_cca_validate_public_key_b71(public_key);
+}
+
+/**
+ Validate a public key.
+
+ Returns `true` if valid, and `false` otherwise.
+*/
+bool libcrux_ml_kem_mlkem1024_portable_validate_public_key(
+ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key) {
+ return validate_public_key_7d1(public_key->value);
+}
diff --git a/lib/freebl/verified/libcrux_mlkem1024_portable.h b/lib/freebl/verified/libcrux_mlkem1024_portable.h
new file mode 100644
--- /dev/null
+++ b/lib/freebl/verified/libcrux_mlkem1024_portable.h
@@ -0,0 +1,74 @@
+/*
+ * SPDX-FileCopyrightText: 2024 Cryspen Sarl <info@cryspen.com>
+ *
+ * SPDX-License-Identifier: MIT or Apache-2.0
+ *
+ * This code was generated with the following revisions:
+ * Charon: b351338f6a84c7a1afc27433eb0ffdc668b3581d
+ * Eurydice: 7efec1624422fd5e94388ef06b9c76dfe7a48d46
+ * Karamel: c96fb69d15693284644d6aecaa90afa37e4de8f0
+ * F*: 58c915a86a2c07c8eca8d9deafd76cb7a91f0eb7
+ * Libcrux: 6ff01fb3c57ff29ecb59bc62d9dc7fd231060cfb
+ */
+
+#ifndef __libcrux_mlkem1024_portable_H
+#define __libcrux_mlkem1024_portable_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#include "eurydice_glue.h"
+#include "libcrux_core.h"
+
+/**
+ Decapsulate ML-KEM 1024
+
+ Generates an [`MlKemSharedSecret`].
+ The input is a reference to an [`MlKem1024PrivateKey`] and an
+ [`MlKem1024Ciphertext`].
+*/
+void libcrux_ml_kem_mlkem1024_portable_decapsulate(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext, uint8_t ret[32U]);
+
+/**
+ Encapsulate ML-KEM 1024
+
+ Generates an ([`MlKem1024Ciphertext`], [`MlKemSharedSecret`]) tuple.
+ The input is a reference to an [`MlKem1024PublicKey`] and
+ [`SHARED_SECRET_SIZE`] bytes of `randomness`.
+*/
+tuple_21 libcrux_ml_kem_mlkem1024_portable_encapsulate(
+ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key,
+ uint8_t randomness[32U]);
+
+/**
+ Generate ML-KEM 1024 Key Pair
+*/
+libcrux_ml_kem_mlkem1024_MlKem1024KeyPair
+libcrux_ml_kem_mlkem1024_portable_generate_key_pair(uint8_t randomness[64U]);
+
+/**
+ Validate a private key.
+
+ Returns `true` if valid, and `false` otherwise.
+*/
+bool libcrux_ml_kem_mlkem1024_portable_validate_private_key(
+ libcrux_ml_kem_types_MlKemPrivateKey_95 *private_key,
+ libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext *ciphertext);
+
+/**
+ Validate a public key.
+
+ Returns `true` if valid, and `false` otherwise.
+*/
+bool libcrux_ml_kem_mlkem1024_portable_validate_public_key(
+ libcrux_ml_kem_types_MlKemPublicKey_1f *public_key);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#define __libcrux_mlkem1024_portable_H_DEFINED
+#endif
diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c
--- a/lib/pk11wrap/pk11akey.c
+++ b/lib/pk11wrap/pk11akey.c
@@ -259,16 +259,21 @@ PK11_ImportPublicKey(PK11SlotInfo *slot,
kemParams = CKP_NSS_KYBER_768_ROUND3;
break;
#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
keyType = CKK_ML_KEM;
kemParams = CKP_ML_KEM_768;
break;
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ keyType = CKK_ML_KEM;
+ kemParams = CKP_ML_KEM_1024;
+ break;
default:
kemParams = CKP_INVALID_ID;
break;
}
/*fprintf(stderr, "PK11_ImportPublic KEY_TYPE=0x%08lx, kem_params=0x%08lxd\n",
keyType, kemParams); */
PK11_SETATTRS(attrs, CKA_PARAMETER_SET,
@@ -908,16 +913,19 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot
case CKP_NSS_KYBER_768_ROUND3:
pubKey->u.kyber.params = params_kyber768_round3;
break;
#endif
case CKP_NSS_ML_KEM_768:
case CKP_ML_KEM_768:
pubKey->u.kyber.params = params_ml_kem768;
break;
+ case CKP_ML_KEM_1024:
+ pubKey->u.kyber.params = params_ml_kem1024;
+ break;
default:
pubKey->u.kyber.params = params_kyber_invalid;
break;
}
crv = pk11_Attr2SecItem(arena, value, &pubKey->u.kyber.publicValue);
break;
case fortezzaKey:
case nullKey:
diff --git a/lib/pk11wrap/pk11pars.c b/lib/pk11wrap/pk11pars.c
--- a/lib/pk11wrap/pk11pars.c
+++ b/lib/pk11wrap/pk11pars.c
@@ -244,17 +244,32 @@ static const oidValDef curveOptList[] =
{ CIPHER_NAME("SECP521R1"), SEC_OID_SECG_EC_SECP521R1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("CURVE25519"), SEC_OID_CURVE25519,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("XYBER768D00"), SEC_OID_XYBER768D00,
NSS_USE_ALG_IN_SSL_KX },
{ CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519,
NSS_USE_ALG_IN_SSL_KX },
- { CIPHER_NAME("MLKEM768SECP256R1"), SEC_OID_SECP256R1MLKEM768,
+ { CIPHER_NAME("SECP256R1MLKEM768"), SEC_OID_SECP256R1MLKEM768,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("MLKEM1024SECP384R1"), SEC_OID_SECP384R1MLKEM1024,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("X25519MLKEM768"), SEC_OID_MLKEM768X25519,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("SECP256R1MLKEM768"), SEC_OID_SECP256R1MLKEM768,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("SECP384R1MLKEM1024"), SEC_OID_SECP384R1MLKEM1024,
+ NSS_USE_ALG_IN_SSL_KX },
+ /* aliases for old names */
+ { CIPHER_NAME("MLKEM768X25519"), SEC_OID_MLKEM768X25519,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("SECP256R1MLKEM768"), SEC_OID_SECP256R1MLKEM768,
+ NSS_USE_ALG_IN_SSL_KX },
+ { CIPHER_NAME("MLKEM1024SECP384R1"), SEC_OID_SECP384R1MLKEM1024,
NSS_USE_ALG_IN_SSL_KX },
/* ANSI X9.62 named elliptic curves (characteristic two field) */
{ CIPHER_NAME("C2PNB163V1"), SEC_OID_ANSIX962_EC_C2PNB163V1,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("C2PNB163V2"), SEC_OID_ANSIX962_EC_C2PNB163V2,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
{ CIPHER_NAME("C2PNB163V3"), SEC_OID_ANSIX962_EC_C2PNB163V3,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c
--- a/lib/pk11wrap/pk11skey.c
+++ b/lib/pk11wrap/pk11skey.c
@@ -3083,16 +3083,19 @@ static CK_ULONG
pk11_KyberCiphertextLength(SECKEYKyberPublicKey *pubKey)
{
switch (pubKey->params) {
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
case params_ml_kem768:
case params_ml_kem768_test_mode:
return KYBER768_CIPHERTEXT_BYTES;
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return MLKEM1024_CIPHERTEXT_BYTES;
default:
// unreachable
return 0;
}
}
static CK_ULONG
pk11_KEMCiphertextLength(SECKEYPublicKey *pubKey)
diff --git a/lib/pk11wrap/secmodti.h b/lib/pk11wrap/secmodti.h
--- a/lib/pk11wrap/secmodti.h
+++ b/lib/pk11wrap/secmodti.h
@@ -201,12 +201,13 @@ struct PK11GenericObjectStr {
/* This mask includes all CK_FLAGs with an equivalent CKA_ attribute. */
#define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL
/*
* private header file, so we can set real names for oids that aren't upstream
* yet, so we applications don't try to use them and get hosed when they change
*/
-#define SEC_OID_SECP256R1MLKEM768 SEC_OID_PRIVATE_1
-#define SEC_OID_MLKEM1024SECP256R1 SEC_OID_PRIVATE_2
+#define SEC_OID_X25519MLKEM768 SEC_OID_MLKEM768X25519
+#define SEC_OID_SECP256R1MLKEM768 SEC_OID_PRIVATE_1
+#define SEC_OID_SECP384R1MLKEM1024 SEC_OID_PRIVATE_2
#endif /* _SECMODTI_H_ */
diff --git a/lib/softoken/kem.c b/lib/softoken/kem.c
--- a/lib/softoken/kem.c
+++ b/lib/softoken/kem.c
@@ -7,77 +7,90 @@
#include "pkcs11i.h"
#include "pkcs11n.h"
#include "secerr.h"
#include "secitem.h"
#include "secport.h"
#include "softoken.h"
/* change to the largest KEM Secret Bytes value supported */
-#define MAX_SHARED_SECRET_BYTES KYBER_SHARED_SECRET_BYTES
+/* currenly only mlkem is supported */
+#define MAX_KEM_SHARED_SECRET_BYTES KYBER_SHARED_SECRET_BYTES
KyberParams
sftk_kyber_PK11ParamToInternal(CK_ML_KEM_PARAMETER_SET_TYPE pk11ParamSet)
{
switch (pk11ParamSet) {
#ifndef NSS_DISABLE_KYBER
case CKP_NSS_KYBER_768_ROUND3:
return params_kyber768_round3;
#endif
case CKP_NSS_ML_KEM_768:
case CKP_ML_KEM_768:
return params_ml_kem768;
+ case CKP_ML_KEM_1024:
+ return params_ml_kem1024;
default:
return params_kyber_invalid;
}
}
SECItem *
sftk_kyber_AllocPubKeyItem(KyberParams params, SECItem *pubkey)
{
switch (params) {
#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return SECITEM_AllocItem(NULL, pubkey, KYBER768_PUBLIC_KEY_BYTES);
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return SECITEM_AllocItem(NULL, pubkey, MLKEM1024_PUBLIC_KEY_BYTES);
default:
return NULL;
}
}
SECItem *
sftk_kyber_AllocPrivKeyItem(KyberParams params, SECItem *privkey)
{
switch (params) {
#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return SECITEM_AllocItem(NULL, privkey, KYBER768_PRIVATE_KEY_BYTES);
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return SECITEM_AllocItem(NULL, privkey, MLKEM1024_PRIVATE_KEY_BYTES);
default:
return NULL;
}
}
SECItem *
sftk_kyber_AllocCiphertextItem(KyberParams params, SECItem *ciphertext)
{
switch (params) {
#ifndef NSS_DISABLE_KYBER
case params_kyber768_round3:
case params_kyber768_round3_test_mode:
#endif
case params_ml_kem768:
case params_ml_kem768_test_mode:
return SECITEM_AllocItem(NULL, ciphertext, KYBER768_CIPHERTEXT_BYTES);
+ case params_ml_kem1024:
+ case params_ml_kem1024_test_mode:
+ return SECITEM_AllocItem(NULL, ciphertext, MLKEM1024_CIPHERTEXT_BYTES);
+
default:
return NULL;
}
}
static PRBool
sftk_kem_ValidateMechanism(CK_MECHANISM_PTR pMechanism)
{
@@ -147,16 +160,18 @@ sftk_kem_CiphertextLen(CK_MECHANISM_PTR
case CKM_ML_KEM:
switch (paramSet) {
#ifndef NSS_DISABLE_KYBER
case CKP_NSS_KYBER_768_ROUND3:
#endif
case CKP_NSS_ML_KEM_768:
case CKP_ML_KEM_768:
return KYBER768_CIPHERTEXT_BYTES;
+ case CKP_ML_KEM_1024:
+ return MLKEM1024_CIPHERTEXT_BYTES;
default:
break;
}
default:
break;
}
return 0;
}
@@ -245,17 +260,17 @@ NSC_EncapsulateKey(CK_SESSION_HANDLE hSe
goto cleanup;
}
SECItem ciphertext = { siBuffer, pCiphertext, ciphertextLen };
SECItem pubKey = { siBuffer, encapsulationKey->attrib.pValue, encapsulationKey->attrib.ulValueLen };
/* The length of secretBuf can be increased if we ever support other KEMs
* by changing the define at the top of this file */
- uint8_t secretBuf[MAX_SHARED_SECRET_BYTES] = { 0 };
+ uint8_t secretBuf[MAX_KEM_SHARED_SECRET_BYTES] = { 0 };
SECItem secret = { siBuffer, secretBuf, sizeof secretBuf };
key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_ENCAPSULATE,
key, 0);
key->source = SFTK_SOURCE_KEA;
switch (pMechanism->mechanism) {
#ifndef NSS_DISABLE_KYBER
case CKM_NSS_KYBER:
@@ -394,17 +409,17 @@ NSC_DecapsulateKey(CK_SESSION_HANDLE hSe
}
SECItem privKey = { siBuffer, decapsulationKey->attrib.pValue,
decapsulationKey->attrib.ulValueLen };
SECItem ciphertext = { siBuffer, pCiphertext, ulCiphertextLen };
/* The length of secretBuf can be increased if we ever support other KEMs
* by changing the define at the top of this file */
- uint8_t secretBuf[MAX_SHARED_SECRET_BYTES] = { 0 };
+ uint8_t secretBuf[MAX_KEM_SHARED_SECRET_BYTES] = { 0 };
SECItem secret = { siBuffer, secretBuf, sizeof secretBuf };
key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DECAPSULATE,
key, 0);
key->source = SFTK_SOURCE_KEA;
switch (pMechanism->mechanism) {
#ifndef NSS_DISABLE_KYBER
case CKM_NSS_KYBER:
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -5532,17 +5532,17 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
CK_KEY_TYPE genType = CKO_SECRET_KEY;
CK_ATTRIBUTE template = { CKA_KEY_TYPE, NULL, 0 };
template.pValue = &genType;
template.ulValueLen = sizeof(genType);
crv = CKR_OK;
switch (keyType) {
case CKK_ML_KEM:
- cipher_text_length = KYBER_SHARED_SECRET_BYTES;
+ cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH;
mech.mechanism = CKM_ML_KEM;
break;
case CKK_RSA:
if (!isEncryptable) {
/* already handled the pairwise test, no need to
* do it again */
goto kem_done;
}
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -128,19 +128,19 @@ typedef enum { SSLAppOpRead = 0,
#define DTLS_RETRANSMIT_MAX_MS 10000
/* Time to wait in FINISHED state for retransmissions. */
#define DTLS_RETRANSMIT_FINISHED_MS 30000
/* default number of entries in namedGroupPreferences */
#ifndef NSS_DISABLE_KYBER
/* this define is checked against the namedGroup table
* and compile time asserts kick in if it doesn't match */
-#define SSL_NAMED_GROUP_COUNT 34
+#define SSL_NAMED_GROUP_COUNT 35
#else
-#define SSL_NAMED_GROUP_COUNT 33
+#define SSL_NAMED_GROUP_COUNT 34
#endif
/* The maximum DH and RSA bit-length supported. */
#define SSL_MAX_DH_KEY_BITS 8192
#define SSL_MAX_RSA_KEY_BITS 8192
/* Types and names of elliptic curves used in TLS */
typedef enum {
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
@@ -156,25 +156,26 @@ static const PRUint16 srtpCiphers[] = {
}
#define FFGROUP(size) \
{ \
ssl_grp_ffdhe_##size, size, ssl_kea_dh, \
SEC_OID_TLS_FFDHE_##size, PR_TRUE \
}
#define HYGROUP(kem, ec, size, kem_oid, ec_oid, assumeSupported) \
{ \
- ssl_grp_kem_##kem##ec, size, ssl_kea_ecdh_hybrid, \
- SEC_OID_##kem_oid##ec_oid, assumeSupported \
+ ssl_grp_kem_##ec##kem, size, ssl_kea_ecdh_hybrid, \
+ SEC_OID_##ec_oid##kem_oid, assumeSupported \
}
const sslNamedGroupDef ssl_named_groups[] = {
/* Note that 256 for 25519 and hybrid is a lie, but we only use it for
* checking bit security and expect 256 bits there (not 255). */
HYGROUP(mlkem768, x25519, 256, MLKEM768, X25519, PR_TRUE),
HYGROUP(mlkem768, secp256r1, 256, MLKEM768, SECP256R1, PR_TRUE),
+ HYGROUP(mlkem1024, secp384r1, 384, MLKEM1024, SECP384R1, PR_TRUE),
{ ssl_grp_ec_curve25519, 256, ssl_kea_ecdh, SEC_OID_CURVE25519, PR_TRUE },
ECGROUP(secp256r1, 256, SECP256R1, PR_TRUE),
ECGROUP(secp384r1, 384, SECP384R1, PR_TRUE),
ECGROUP(secp521r1, 521, SECP521R1, PR_TRUE),
#ifndef NSS_DISABLE_KYBER
{ ssl_grp_kem_xyber768d00, 256, ssl_kea_ecdh_hybrid, SEC_OID_XYBER768D00, PR_TRUE },
#endif
FFGROUP(2048),
@@ -204,16 +205,17 @@ const sslNamedGroupDef ssl_named_groups[
ECGROUP(sect409r1, 409, SECT409R1, PR_FALSE),
ECGROUP(sect571k1, 571, SECT571K1, PR_FALSE),
ECGROUP(sect571r1, 571, SECT571R1, PR_FALSE),
};
PR_STATIC_ASSERT(SSL_NAMED_GROUP_COUNT == PR_ARRAY_SIZE(ssl_named_groups));
#undef ECGROUP
#undef FFGROUP
+#undef HYGROUP
/* forward declarations. */
static sslSocket *ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant variant);
static SECStatus ssl_MakeLocks(sslSocket *ss);
static PRStatus ssl_SetDefaultsFromEnvironmentCallOnce(void);
static void ssl_SetDefaultsFromEnvironment(void);
static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
PRDescIdentity id);
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
--- a/lib/ssl/sslt.h
+++ b/lib/ssl/sslt.h
@@ -255,25 +255,29 @@ typedef enum {
ssl_grp_ec_secp384r1 = 24,
ssl_grp_ec_secp521r1 = 25,
ssl_grp_ec_curve25519 = 29, /* RFC4492 */
ssl_grp_ffdhe_2048 = 256, /* RFC7919 */
ssl_grp_ffdhe_3072 = 257,
ssl_grp_ffdhe_4096 = 258,
ssl_grp_ffdhe_6144 = 259,
ssl_grp_ffdhe_8192 = 260,
- ssl_grp_kem_mlkem768x25519 = 4588,
- ssl_grp_kem_secp256r1mlkem768 = 4587,
+ ssl_grp_kem_x25519mlkem768 = 4588,
+ ssl_grp_kem_secp256r1mlkem768 = 4587,
+ ssl_grp_kem_secp384r1mlkem1024 = 4589,
#ifndef NSS_DISABLE_KYBER
ssl_grp_kem_xyber768d00 = 25497, /* draft-tls-westerbaan-xyber768d00-02 */
#endif
ssl_grp_none = 65537, /* special value */
ssl_grp_ffdhe_custom = 65538 /* special value */
} SSLNamedGroup;
+/* alias old names */
+#define ssl_grp_kem_mlkem768x25519 ssl_grp_kem_x25519mlkem768
+#define ssl_grp_kem_mlkem768secp256r1 ssl_grp_kem_secp256r1mlkem768
typedef struct SSLExtraServerCertDataStr {
/* When this struct is passed to SSL_ConfigServerCert, and authType is set
* to a value other than ssl_auth_null, this limits the use of the key to
* the type defined; otherwise, the certificate is configured for all
* compatible types. */
SSLAuthType authType;
/* The remainder of the certificate chain. */
const CERTCertificateList* certChain;
diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c
--- a/lib/ssl/tls13con.c
+++ b/lib/ssl/tls13con.c
@@ -385,19 +385,23 @@ tls13_CreateKEMKeyPair(sslSocket *ss, co
#ifndef NSS_DISABLE_KYBER
case ssl_grp_kem_xyber768d00:
mechanism = CKM_NSS_KYBER_KEY_PAIR_GEN;
paramSet = CKP_NSS_KYBER_768_ROUND3;
break;
#endif
case ssl_grp_kem_mlkem768x25519:
case ssl_grp_kem_secp256r1mlkem768:
- mechanism = CKM_NSS_ML_KEM_KEY_PAIR_GEN;
+ mechanism = CKM_ML_KEM_KEY_PAIR_GEN;
paramSet = CKP_ML_KEM_768;
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ mechanism = CKM_ML_KEM_KEY_PAIR_GEN;
+ paramSet = CKP_ML_KEM_1024;
+ break;
default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
PK11SlotInfo *slot = PK11_GetBestSlot(mechanism, ss->pkcs11PinArg);
if (!slot) {
@@ -494,16 +498,20 @@ tls13_FindHybridKeyPair(sslSocket *ss, c
{
sslEphemeralKeyPair *hybridPair = NULL;
switch (groupDef->name) {
case ssl_grp_ec_secp256r1:
/* future, this may be a loop to check multiple named groups */
hybridPair = ssl_LookupEphemeralKeyPair(ss,
ssl_LookupNamedGroup(ssl_grp_kem_secp256r1mlkem768));
break;
+ case ssl_grp_ec_secp384r1:
+ hybridPair = ssl_LookupEphemeralKeyPair(ss,
+ ssl_LookupNamedGroup(ssl_grp_kem_secp384r1mlkem1024));
+ break;
case ssl_grp_ec_curve25519:
#ifndef NSS_DISABLE_KYBER
/* a loop to check multiple named groups */
SSLNamedGroup gnames[] = { ssl_grp_kem_xyber768d00,
ssl_grp_kem_mlkem768x25519 };
for (int i=0; i < PR_ARRAY_SIZE(gnames); i++) {
hybridPair = ssl_LookupEphemeralKeyPair(ss,
ssl_LookupNamedGroup(gnames[i]));
@@ -563,16 +571,19 @@ tls13_CreateKeyShare(sslSocket *ss, cons
PORT_Assert(groupDef);
switch (groupDef->keaType) {
case ssl_kea_ecdh_hybrid:
switch (groupDef->name) {
case ssl_grp_kem_secp256r1mlkem768:
dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1);
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp384r1);
+ break;
#ifndef NSS_DISABLE_KYBER
case ssl_grp_kem_xyber768d00:
#endif
case ssl_grp_kem_mlkem768x25519:
dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_curve25519);
break;
default:
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
@@ -832,16 +843,19 @@ tls13_ImportKEMKeyShare(SECKEYPublicKey
break;
#endif
case ssl_grp_kem_mlkem768x25519:
expected_len = X25519_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES;
break;
case ssl_grp_kem_secp256r1mlkem768:
expected_len = SECP256_PUBLIC_KEY_BYTES + KYBER768_PUBLIC_KEY_BYTES;
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ expected_len = SECP384_PUBLIC_KEY_BYTES + MLKEM1024_PUBLIC_KEY_BYTES;
+ break;
default:
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
return SECFailure;
}
if (entry->key_exchange.len != expected_len) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
return SECFailure;
@@ -866,16 +880,23 @@ tls13_ImportKEMKeyShare(SECKEYPublicKey
break;
case ssl_grp_kem_secp256r1mlkem768:
peerKey->keyType = kyberKey;
peerKey->u.kyber.params = params_ml_kem768;
/* key_exchange.data is `secp256 || mlkem768` */
pk.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES;
pk.len = KYBER768_PUBLIC_KEY_BYTES;
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ peerKey->keyType = kyberKey;
+ peerKey->u.kyber.params = params_ml_kem1024;
+ /* key_exchange.data is `secp384 || mlkem1024` */
+ pk.data = entry->key_exchange.data + SECP384_PUBLIC_KEY_BYTES;
+ pk.len = MLKEM1024_PUBLIC_KEY_BYTES;
+ break;
default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
rv = SECITEM_CopyItem(peerKey->arena, &peerKey->u.kyber.publicValue, &pk);
if (rv != SECSuccess) {
@@ -914,16 +935,24 @@ tls13_HandleKEMCiphertext(sslSocket *ss,
case ssl_grp_kem_secp256r1mlkem768:
if (entry->key_exchange.len != SECP256_PUBLIC_KEY_BYTES + KYBER768_CIPHERTEXT_BYTES) {
ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
return SECFailure;
}
ct.data = entry->key_exchange.data + SECP256_PUBLIC_KEY_BYTES;
ct.len = KYBER768_CIPHERTEXT_BYTES;
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ if (entry->key_exchange.len != SECP384_PUBLIC_KEY_BYTES + MLKEM1024_CIPHERTEXT_BYTES) {
+ ssl_MapLowLevelError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
+ return SECFailure;
+ }
+ ct.data = entry->key_exchange.data + SECP384_PUBLIC_KEY_BYTES;
+ ct.len = MLKEM1024_CIPHERTEXT_BYTES;
+ break;
default:
PORT_Assert(0);
ssl_MapLowLevelError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
rv = PK11_Decapsulate(keyPair->privKey, &ct, CKM_HKDF_DERIVE, PK11_ATTR_SESSION,
CKF_DERIVE, outKey);
@@ -1039,16 +1068,24 @@ tls13_HandleKeyShare(sslSocket *ss,
case ssl_grp_kem_secp256r1mlkem768:
dhLen = SECP256_PUBLIC_KEY_BYTES;
/* secp256 share is at the beginning */
ec_data = entry->key_exchange.len < dhLen
? NULL
: entry->key_exchange.data;
dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1);
break;
+ case ssl_grp_kem_secp384r1mlkem1024:
+ dhLen = SECP384_PUBLIC_KEY_BYTES;
+ /* secp256 share is at the beginning */
+ ec_data = entry->key_exchange.len < dhLen
+ ? NULL
+ : entry->key_exchange.data;
+ dhGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp384r1);
+ break;
default:
ec_data = NULL;
break;
}
if (!ec_data) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_HYBRID_KEY_SHARE);
goto loser;
}
@@ -2927,16 +2964,17 @@ tls13_HandleClientKeyShare(sslSocket *ss
case ssl_grp_kem_xyber768d00:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
#endif
case ssl_grp_kem_mlkem768x25519:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(kemSecret, dheSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
case ssl_grp_kem_secp256r1mlkem768:
+ case ssl_grp_kem_secp384r1mlkem1024:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
ss->ssl3.hs.dheSecret = NULL;
break;
}
@@ -3791,16 +3829,17 @@ tls13_HandleServerKeyShare(sslSocket *ss
case ssl_grp_kem_xyber768d00:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
#endif
case ssl_grp_kem_mlkem768x25519:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(kemSecret, dheSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
case ssl_grp_kem_secp256r1mlkem768:
+ case ssl_grp_kem_secp384r1mlkem1024:
ss->ssl3.hs.dheSecret = PK11_ConcatSymKeys(dheSecret, kemSecret, CKM_HKDF_DERIVE, CKA_DERIVE);
break;
default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
ss->ssl3.hs.dheSecret = NULL;
break;
}
diff --git a/lib/ssl/tls13exthandle.c b/lib/ssl/tls13exthandle.c
--- a/lib/ssl/tls13exthandle.c
+++ b/lib/ssl/tls13exthandle.c
@@ -80,70 +80,47 @@ tls13_SizeOfKeyShareEntry(const sslEphem
if (keyPair->kemKeys) {
PORT_Assert(!keyPair->kemCt);
PORT_Assert(
#ifndef NSS_DISABLE_KYBER
keyPair->group->name == ssl_grp_kem_xyber768d00 ||
#endif
keyPair->group->name == ssl_grp_kem_mlkem768x25519 ||
- keyPair->group->name == ssl_grp_kem_secp256r1mlkem768);
+ keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 ||
+ keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024);
pubKey = keyPair->kemKeys->pubKey;
size += pubKey->u.kyber.publicValue.len;
}
if (keyPair->kemCt) {
PORT_Assert(!keyPair->kemKeys);
PORT_Assert(
#ifndef NSS_DISABLE_KYBER
keyPair->group->name == ssl_grp_kem_xyber768d00 ||
#endif
keyPair->group->name == ssl_grp_kem_mlkem768x25519 ||
- keyPair->group->name == ssl_grp_kem_secp256r1mlkem768);
+ keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 ||
+ keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024);
size += keyPair->kemCt->len;
}
return size;
}
+static SECStatus
+tls13_WriteECCFirstMLKEMKeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair)
+ {
+ PORT_Assert(keyPair->group->name == ssl_grp_kem_secp256r1mlkem768 ||
#ifndef NSS_DISABLE_KYBER
-static SECStatus
-tls13_WriteXyber768D00KeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair)
-{
- PORT_Assert(keyPair->group->name == ssl_grp_kem_xyber768d00);
+ keyPair->group->name == ssl_grp_kem_xyber768d00 ||
+#endif
+ keyPair->group->name == ssl_grp_kem_secp384r1mlkem1024);
PORT_Assert(keyPair->keys->pubKey->keyType == ecKey);
- // Encode the X25519 share first, then the Kyber768 key or ciphertext.
- SECStatus rv;
- rv = sslBuffer_Append(buf, keyPair->keys->pubKey->u.ec.publicValue.data,
- keyPair->keys->pubKey->u.ec.publicValue.len);
- if (rv != SECSuccess) {
- return rv;
- }
-
- if (keyPair->kemKeys) {
- PORT_Assert(!keyPair->kemCt);
- rv = sslBuffer_Append(buf, keyPair->kemKeys->pubKey->u.kyber.publicValue.data, keyPair->kemKeys->pubKey->u.kyber.publicValue.len);
- } else if (keyPair->kemCt) {
- rv = sslBuffer_Append(buf, keyPair->kemCt->data, keyPair->kemCt->len);
- } else {
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- rv = SECFailure;
- }
- return rv;
-}
-#endif
-
-static SECStatus
-tls13_WriteMLKEM768Secp256r1KeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair)
- {
- PORT_Assert(keyPair->group->name == ssl_grp_kem_secp256r1mlkem768);
- PORT_Assert(keyPair->keys->pubKey->keyType == ecKey);
-
- // Encode the p256 key first, then the Kyber768 key or ciphertext.
+ // Encode the ECC key first, then the ML-KEM key or ciphertext.
SECStatus rv;
rv = sslBuffer_Append(buf, keyPair->keys->pubKey->u.ec.publicValue.data,
keyPair->keys->pubKey->u.ec.publicValue.len);
if (rv != SECSuccess) {
return rv;
}
if (keyPair->kemKeys) {
@@ -155,22 +132,22 @@ tls13_WriteMLKEM768Secp256r1KeyExchangeI
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
}
return rv;
}
static SECStatus
-tls13_WriteMLKEM768X25519KeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair)
+tls13_WriteMLKEMFirstKeyExchangeInfo(sslBuffer *buf, sslEphemeralKeyPair *keyPair)
{
PORT_Assert(keyPair->group->name == ssl_grp_kem_mlkem768x25519);
PORT_Assert(keyPair->keys->pubKey->keyType == ecKey);
- // Encode the ML-KEM-768 key or ciphertext first, then the X25519 share.
+ // Encode the ML-KEM key or ciphertext first, then the ecc share.
SECStatus rv;
if (keyPair->kemKeys) {
PORT_Assert(!keyPair->kemCt);
rv = sslBuffer_Append(buf, keyPair->kemKeys->pubKey->u.kyber.publicValue.data, keyPair->kemKeys->pubKey->u.kyber.publicValue.len);
} else if (keyPair->kemCt) {
rv = sslBuffer_Append(buf, keyPair->kemCt->data, keyPair->kemCt->len);
} else {
PORT_Assert(0);
@@ -223,26 +200,24 @@ tls13_EncodeKeyShareEntry(sslBuffer *buf
rv = sslBuffer_AppendNumber(buf, size - 4, 2);
if (rv != SECSuccess) {
return rv;
}
switch (keyPair->group->name) {
#ifndef NSS_DISABLE_KYBER
case ssl_grp_kem_xyber768d00:
- rv = tls13_WriteXyber768D00KeyExchangeInfo(buf, keyPair);
+#endif
+ case ssl_grp_kem_secp256r1mlkem768:
+ case ssl_grp_kem_secp384r1mlkem1024:
+ rv = tls13_WriteECCFirstMLKEMKeyExchangeInfo(buf, keyPair);
break;
-#endif
case ssl_grp_kem_mlkem768x25519:
- rv = tls13_WriteMLKEM768X25519KeyExchangeInfo(buf, keyPair);
+ rv = tls13_WriteMLKEMFirstKeyExchangeInfo(buf, keyPair);
break;
- case ssl_grp_kem_secp256r1mlkem768:
- rv = tls13_WriteMLKEM768Secp256r1KeyExchangeInfo(buf, keyPair);
- break;
-
default:
rv = tls13_WriteKeyExchangeInfo(buf, keyPair);
break;
}
return rv;
}
SECStatus
diff --git a/lib/util/eccutil.h b/lib/util/eccutil.h
--- a/lib/util/eccutil.h
+++ b/lib/util/eccutil.h
@@ -2,16 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _FREEBL_H_
#define _FREEBL_H_
#define X25519_PUBLIC_KEY_BYTES 32U
#define SECP256_PUBLIC_KEY_BYTES 65U
+#define SECP384_PUBLIC_KEY_BYTES 97U
/* deprecated */
typedef enum {
ECPoint_Uncompressed,
ECPoint_XOnly,
ECPoint_Undefined
} ECPointEncoding;
diff --git a/lib/util/kyber.h b/lib/util/kyber.h
--- a/lib/util/kyber.h
+++ b/lib/util/kyber.h
@@ -4,20 +4,28 @@
#ifndef KYBER_UTIL_H
#define KYBER_UTIL_H
#define KYBER768_PUBLIC_KEY_BYTES 1184U
#define KYBER768_PRIVATE_KEY_BYTES 2400U
#define KYBER768_CIPHERTEXT_BYTES 1088U
+#define MLKEM1024_PUBLIC_KEY_BYTES 1568U
+#define MLKEM1024_PRIVATE_KEY_BYTES 3168U
+#define MLKEM1024_CIPHERTEXT_BYTES 1568U
+
#define KYBER_SHARED_SECRET_BYTES 32U
#define KYBER_KEYPAIR_COIN_BYTES 64U
#define KYBER_ENC_COIN_BYTES 32U
+#define MAX_ML_KEM_CIPHER_LENGTH MLKEM1024_CIPHERTEXT_BYTES
+#define MAX_ML_KEM_PRIVATE_KEY_LENGTH MLKEM1024_PRIVATE_KEY_BYTES
+#define MAX_ML_KEM_PUBLIC_KEY_LENGTH MLKEM1024_PUBLIC_KEY_BYTES
+
typedef enum {
params_kyber_invalid,
/*
* The Kyber768 parameters specified in version 3.02 of the NIST submission
* https://pq-crystals.org/kyber/data/kyber-specification-round3-20210804.pdf
*/
params_kyber768_round3,
@@ -34,11 +42,24 @@ typedef enum {
*/
params_ml_kem768,
/*
* Identical to params_ml_kem768 except that this parameter set allows
* the use of a seed in `Kyber_Encapsulate` for testing.
*/
params_ml_kem768_test_mode,
+
+ /*
+ * The ML-KEM parameters specified in FIPS 203.
+ * https://csrc.nist.gov/pubs/fips/203/final
+ */
+ params_ml_kem1024,
+
+ /*
+ * Identical to params_ml_kem1024 except that this parameter set allows
+ * the use of a seed in `Kyber_Encapsulate` for testing.
+ */
+ params_ml_kem1024_test_mode,
+
} KyberParams;
#endif /* KYBER_UTIL_H */
diff --git a/tests/ssl/ssl.sh b/tests/ssl/ssl.sh
--- a/tests/ssl/ssl.sh
+++ b/tests/ssl/ssl.sh
@@ -119,19 +119,19 @@ ssl_init()
# List of cipher suites to test, including ECC cipher suites.
CIPHER_SUITES="-c ${EC_SUITES}${NON_EC_SUITES}"
TLS13_CIPHER_SUITES="-c ${TLS13_SUITES}${EC_SUITES}${NON_EC_SUITES}"
# FIPS specific options for both clients and servers
FIPS_OPTIONS=""
# in fips mode, turn off curve25519 until it's NIST approved
- ALL_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192,mlkem768secp256r1,mlkem768x25519"
+ ALL_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192,secp256r1mlkem768,secp384r1mlkem1024, mlkem768x25519"
NON_PQ_GROUPS="P256,P384,P521,x25519,FF2048,FF3072,FF4096,FF6144,FF8192"
- FIPS_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192,mlkem768secp256r1,mlkem768x25519"
+ FIPS_GROUPS="P256,P384,P521,FF2048,FF3072,FF4096,FF6144,FF8192,secp256r1mlkem768,secp384r1mlkem1024,mlkem768x25519"
# in non-fips mode, tstclnt may run without the db password in some
# cases, but in fips mode it's always needed
CLIENT_PW=""
CLIENT_PW_FIPS="-w nss"
CLIENT_PW_NORMAL=""
if [ "${OS_ARCH}" != "WINNT" ]; then
@@ -372,19 +372,21 @@ ssl_cov()
if [ "$VMAX" = "ssl3" -a "$VMIN" = "tls1.1" ]; then
kill_selfserv
start_selfserv $CIPHER_SUITES
VMIN="ssl3"
fi
TLS_GROUPS=${CLIENT_GROUPS}
if [ "$ectype" = "MLKEM256" ]; then
- TLS_GROUPS="mlkem768secp256r1"
+ TLS_GROUPS="secp256r1mlkem768"
elif [ "$ectype" = "MLKEM219" ]; then
- TLS_GROUPS="mlkem768x25519"
+ TLS_GROUPS="x25519mlkem768"
+ elif [ "$ectype" = "MLKEM384" ]; then
+ TLS_GROUPS="secp384r1mlkem1024"
fi
echo "TLS_GROUPS=${TLS_GROUPS}"
echo "tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -I \"${TLS_GROUPS}\" -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} \\"
echo " -f -d ${P_R_CLIENTDIR} $verbose -w nss < ${REQUEST_FILE}"
rm ${TMP}/$HOST.tmp.$$ 2>/dev/null
${PROFTOOL} ${BINDIR}/tstclnt -4 -p ${PORT} -h ${HOSTADDR} -c ${param} -I "${TLS_GROUPS}" -V ${VMIN}:${VMAX} ${CLIENT_OPTIONS} -f \
diff --git a/tests/ssl/sslcov.txt b/tests/ssl/sslcov.txt
--- a/tests/ssl/sslcov.txt
+++ b/tests/ssl/sslcov.txt
@@ -148,14 +148,17 @@
# Test against server with RSA-PSS server certificate
#
ECC TLS12 :C02F TLS12_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - RSA-PSS
ECC TLS12 :C030 TLS12_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - RSA-PSS
# test TLS 1.3
ECC TLS13 :1301 TLS13_ECDHE_WITH_AES_128_GCM_SHA256
ECC TLS13 :1302 TLS13_ECDHE_WITH_AES_256_GCM_SHA384
ECC TLS13 :1303 TLS13_ECDHE_WITH_CHACHA20_POLY1305_SHA256
-MLKEM256 TLS13 :1301 TLS13_MLKEMP256_WITH_AES_128_GCM_SHA256
-MLKEM256 TLS13 :1302 TLS13_MLKEMP256_WITH_AES_256_GCM_SHA384
-MLKEM256 TLS13 :1303 TLS13_MLKEMP256_WITH_CHACHA20_POLY1305_SHA256
-MLKEM219 TLS13 :1301 TLS13_MLKEMX25519_WITH_AES_128_GCM_SHA256
-MLKEM219 TLS13 :1302 TLS13_MLKEMX25519_WITH_AES_256_GCM_SHA384
-MLKEM219 TLS13 :1303 TLS13_MLKEMX25519_WITH_CHACHA20_POLY1305_SHA256
+MLKEM384 TLS13 :1301 TLS13_MLKEM1024P384_WITH_AES_128_GCM_SHA256
+MLKEM384 TLS13 :1302 TLS13_MLKEM1024P384_WITH_AES_256_GCM_SHA384
+MLKEM384 TLS13 :1303 TLS13_MLKEM1024P384_WITH_CHACHA20_POLY1305_SHA256
+MLKEM256 TLS13 :1301 TLS13_MLKEM768P256_WITH_AES_128_GCM_SHA256
+MLKEM256 TLS13 :1302 TLS13_MLKEM768P256_WITH_AES_256_GCM_SHA384
+MLKEM256 TLS13 :1303 TLS13_MLKEM768P256_WITH_CHACHA20_POLY1305_SHA256
+MLKEM219 TLS13 :1301 TLS13_MLKEM768X25519_WITH_AES_128_GCM_SHA256
+MLKEM219 TLS13 :1302 TLS13_MLKEM768X25519_WITH_AES_256_GCM_SHA384
+MLKEM219 TLS13 :1303 TLS13_MLKEM768X25519_WITH_CHACHA20_POLY1305_SHA256