Merge pull request #792 from anhu/mlkem

Replace Kyber 512 with ML-KEM 768.
pull/794/head
Sean Parkinson 2025-03-27 13:05:56 +10:00 committed by GitHub
commit e5042df0c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 115 additions and 115 deletions

View File

@ -1,4 +1,4 @@
name: Kyber Tests
name: ML-KEM Tests
on:
push:
@ -22,7 +22,7 @@ jobs:
id: cache-liboqs
with:
path: build-dir/
key: wolfssh-kyber-liboqs-${{ env.LIBOQS_REF }}-${{ env.OS_REF }}
key: wolfssh-mlkem-liboqs-${{ env.LIBOQS_REF }}-${{ env.OS_REF }}
lookup-only: true
- name: Checkout liboqs
@ -53,7 +53,7 @@ jobs:
id: cache-wolfssl
with:
path: build-dir/
key: wolfssh-kyber-wolfssl-${{ env.WOLFSSL_REF }}-${{ env.OS_REF }}
key: wolfssh-mlkem-wolfssl-${{ env.WOLFSSL_REF }}-${{ env.OS_REF }}
lookup-only: true
- name: Checkout, build, and install wolfssl
@ -77,14 +77,14 @@ jobs:
uses: actions/cache@v4
with:
path: build-dir/
key: wolfssh-kyber-liboqs-${{ env.LIBOQS_REF }}-${{ env.OS_REF }}
key: wolfssh-mlkem-liboqs-${{ env.LIBOQS_REF }}-${{ env.OS_REF }}
fail-on-cache-miss: true
- name: Checking cache for wolfssl
uses: actions/cache@v4
with:
path: build-dir/
key: wolfssh-kyber-wolfssl-${{ env.WOLFSSL_REF }}-${{ env.OS_REF }}
key: wolfssh-mlkem-wolfssl-${{ env.WOLFSSL_REF }}-${{ env.OS_REF }}
fail-on-cache-miss: true
- name: Checkout, build, and test wolfssh

View File

@ -450,21 +450,21 @@ The wolfSSH client and server will automatically negotiate using Curve25519.
POST-QUANTUM
============
wolfSSH now supports the post-quantum algorithm ML-KEM (also known as Kyber).
It uses the KYBER512 parameter set and is hybridized with ECDHE over the P-256
ECC curve.
wolfSSH now supports the post-quantum algorithm ML-KEM (formerly known as
Kyber). It uses the ML-KEM-768 parameter set and is hybridized with ECDHE over
the P-256 ECC curve.
In order to use this key exchange you must build and install wolfSSL on your
system. Here is an example of an effective configuration:
$ ./configure --enable-wolfssh --enable-experimental --enable-kyber
$ ./configure --enable-wolfssh --enable-mlkem
After that, simply configure and build wolfssh as usual:
$ ./configure
$ make all
The wolfSSH client and server will automatically negotiate using KYBER512
The wolfSSH client and server will automatically negotiate using ML-KEM-768
hybridized with ECDHE over the P-256 ECC curve.
$ ./examples/echoserver/echoserver -f
@ -487,7 +487,7 @@ The following is sufficient for build and execution:
$ cd openssh-OQS-OpenSSH-snapshot-2021-08/
$ ./configure --with-liboqs-dir=/usr/local
$ make all
$ ./ssh -o"KexAlgorithms=ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org" \
$ ./ssh -o"KexAlgorithms=mlkem768nistp256-sha256" \
-o"PubkeyAcceptedAlgorithms +ssh-rsa" \
-o"HostkeyAlgorithms +ssh-rsa" \
jill@localhost -p 22222

View File

@ -50,13 +50,13 @@
#if (LIBWOLFSSL_VERSION_HEX >= WOLFSSL_V5_0_0) \
&& ((defined(HAVE_FIPS) && FIPS_VERSION_GE(5,2)) \
|| defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256))
|| defined(WOLFSSH_NO_NISTP256_MLKEM768_SHA256))
#include <wolfssl/wolfcrypt/kdf.h>
#endif
#ifdef WOLFSSL_HAVE_KYBER
#include <wolfssl/wolfcrypt/kyber.h>
#include <wolfssl/wolfcrypt/wc_kyber.h>
#ifdef WOLFSSL_HAVE_MLKEM
#include <wolfssl/wolfcrypt/mlkem.h>
#include <wolfssl/wolfcrypt/wc_mlkem.h>
#endif
#ifdef NO_INLINE
@ -138,9 +138,9 @@ Flags:
WOLFSSH_NO_ECDSA_SHA2_NISTP521
Set when ECC or SHA2-512 are disabled. Set to disable use of ECDSA server
authentication with prime NISTP521.
WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
Set when Kyber is disabled in wolfssl. Set to disable use of ECDHE with
prime NISTP256 hybridized with post-quantum KYBER512 KEM.
WOLFSSH_NO_NISTP256_MLKEM768_SHA256
Set when ML-KEM is disabled in wolfssl. Set to disable use of ECDHE with
prime NISTP256 hybridized with post-quantum ML-KEM 768.
WOLFSSH_NO_AES_CBC
Set when AES or AES-CBC are disabled. Set to disable use of AES-CBC
encryption.
@ -679,8 +679,8 @@ INLINE static int IsMessageAllowed(WOLFSSH *ssh, byte msg)
static const char cannedKexAlgoNames[] =
#if !defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256)
"ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org,"
#if !defined(WOLFSSH_NO_NISTP256_MLKEM768_SHA256)
"mlkem768nistp256-sha256,"
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
"curve25519-sha256,"
@ -2200,15 +2200,15 @@ int GenerateKey(byte hashId, byte keyId,
byte doKeyPad)
#if (LIBWOLFSSL_VERSION_HEX >= WOLFSSL_V5_0_0) \
&& ((defined(HAVE_FIPS) && FIPS_VERSION_GE(5,2)) \
|| defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256))
/* Cannot use the SSH KDF with Kyber. With Kyber, doKeyPad must be false,
* and the FIPS SSH KDF doesn't handle no-padding. Also, the Kyber algorithm
|| defined(WOLFSSH_NO_NISTP256_MLKEM768_SHA256))
/* Cannot use the SSH KDF with ML-KEM. With ML-KEM, doKeyPad must be false,
* and the FIPS SSH KDF doesn't handle no-padding. Also, the ML-KEM algorithm
* isn't in our FIPS boundary. */
{
int ret = WS_SUCCESS;
if (!doKeyPad) {
WLOG(WS_LOG_ERROR, "cannot use FIPS KDF with Kyber");
WLOG(WS_LOG_ERROR, "cannot use FIPS KDF with ML-KEM");
ret = WS_INVALID_ALGO_ID;
}
else {
@ -2486,9 +2486,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP521
{ ID_ECDH_SHA2_NISTP521, TYPE_KEX, "ecdh-sha2-nistp521" },
#endif
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
{ ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256, TYPE_KEX,
"ecdh-nistp256-kyber-512r3-sha256-d00@openquantumsafe.org" },
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
{ ID_NISTP256_MLKEM768_SHA256, TYPE_KEX,
"mlkem768nistp256-sha256" },
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
/* See RFC 8731 */
@ -3746,8 +3746,8 @@ enum wc_HashType HashForId(byte id)
#endif
return WC_HASH_TYPE_SHA256;
#endif
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
case ID_NISTP256_MLKEM768_SHA256:
return WC_HASH_TYPE_SHA256;
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
@ -3808,8 +3808,8 @@ enum wc_HashType HashForId(byte id)
int wcPrimeForId(byte id)
{
switch (id) {
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
case ID_NISTP256_MLKEM768_SHA256:
return ECC_SECP256R1;
#endif
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256
@ -5173,20 +5173,20 @@ static int KeyAgreeCurve25519_client(WOLFSSH* ssh, byte hashId,
#endif /* WOLFSSH_NO_CURVE25519_SHA256 */
/* KeyAgreeEcdhKyber512_client
/* KeyAgreeEcdhMlKem_client
* hashId - wolfCrypt hash type ID used
* f - peer public key
* fSz - peer public key size
*/
static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
static int KeyAgreeEcdhMlKem_client(WOLFSSH* ssh, byte hashId,
const byte* f, word32 fSz)
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
{
int ret = WS_SUCCESS;
byte sharedSecretHashSz = 0;
byte *sharedSecretHash = NULL;
ecc_key *key_ptr = NULL;
KyberKey kem = {0};
MlKemKey kem = {0};
word32 length_ciphertext = 0;
word32 length_sharedsecret = 0;
word32 length_privatekey = 0;
@ -5204,26 +5204,26 @@ static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
key_ptr = &key_s;
#endif /* WOLFSSH_SMALL_STACK */
WLOG(WS_LOG_DEBUG, "Entering KeyAgreeEcdhKyber512_client()");
WLOG(WS_LOG_DEBUG, "Entering KeyAgreeEcdhMlKem_client()");
/* This is a a hybrid of ECDHE and a post-quantum KEM. In this
* case, I need to generated the ECC shared secret and
* decapsulate the ciphertext of the post-quantum KEM. */
if (ret == 0) {
ret = wc_KyberKey_Init(KYBER512, &kem, ssh->ctx->heap, INVALID_DEVID);
ret = wc_MlKemKey_Init(&kem, WC_ML_KEM_768, ssh->ctx->heap, INVALID_DEVID);
}
if (ret == 0) {
ret = wc_KyberKey_CipherTextSize(&kem, &length_ciphertext);
ret = wc_MlKemKey_CipherTextSize(&kem, &length_ciphertext);
}
if (ret == 0) {
ret = wc_KyberKey_SharedSecretSize(&kem, &length_sharedsecret);
ret = wc_MlKemKey_SharedSecretSize(&kem, &length_sharedsecret);
}
if (ret == 0) {
ret = wc_KyberKey_PrivateKeySize(&kem, &length_privatekey);
ret = wc_MlKemKey_PrivateKeySize(&kem, &length_privatekey);
}
if ((ret == 0) && (ssh->handshake->xSz < length_privatekey)) {
@ -5263,12 +5263,12 @@ static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
wc_ecc_free(&ssh->handshake->privKey.ecc);
if (ret == 0) {
wc_KyberKey_DecodePrivateKey(&kem, ssh->handshake->x,
wc_MlKemKey_DecodePrivateKey(&kem, ssh->handshake->x,
length_privatekey);
}
if (ret == 0) {
ret = wc_KyberKey_Decapsulate(&kem, ssh->k, f, length_ciphertext);
ret = wc_MlKemKey_Decapsulate(&kem, ssh->k, f, length_ciphertext);
}
if (ret == 0) {
@ -5276,11 +5276,11 @@ static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
} else {
ssh->kSz = 0;
WLOG(WS_LOG_ERROR,
"Generate ECC-kyber (decap) shared secret failed, %d",
"Generate ECC and ML-KEM (decap) shared secret failed, %d",
ret);
}
wc_KyberKey_Free(&kem);
wc_MlKemKey_Free(&kem);
/* Replace the concatenated shared secrets with the hash. That
* will become the new shared secret. */
@ -5309,10 +5309,10 @@ static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
WFREE(sharedSecretHash, ssh->ctx->heap, DYNTYPE_PRIVKEY);
}
WLOG(WS_LOG_DEBUG, "Leaving KeyAgreeEcdhKyber512_client(), ret = %d", ret);
WLOG(WS_LOG_DEBUG, "Leaving KeyAgreeEcdhMlKem_client(), ret = %d", ret);
return ret;
}
#else /* WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
#else /* WOLFSSH_NO_NISTP256_MLKEM768_SHA256 */
{
WOLFSSH_UNUSED(ssh);
WOLFSSH_UNUSED(hashId);
@ -5320,7 +5320,7 @@ static int KeyAgreeEcdhKyber512_client(WOLFSSH* ssh, byte hashId,
WOLFSSH_UNUSED(fSz);
return WS_INVALID_ALGO_ID;
}
#endif /* WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
#endif /* WOLFSSH_NO_NISTP256_MLKEM768_SHA256 */
/* KeyAgree_client
@ -5346,8 +5346,8 @@ static int KeyAgree_client(WOLFSSH* ssh, byte hashId, const byte* f, word32 fSz)
else if (ssh->handshake->useCurve25519) {
ret = KeyAgreeCurve25519_client(ssh, hashId, f, fSz);
}
else if (ssh->handshake->useEccKyber) {
ret = KeyAgreeEcdhKyber512_client(ssh, hashId, f, fSz);
else if (ssh->handshake->useEccMlKem) {
ret = KeyAgreeEcdhMlKem_client(ssh, hashId, f, fSz);
}
else {
ret = WS_INVALID_ALGO_ID;
@ -5563,7 +5563,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
/* Hash in the shared secret K. */
if (ret == WS_SUCCESS) {
if (!ssh->handshake->useEccKyber) {
if (!ssh->handshake->useEccMlKem) {
ret = CreateMpint(ssh->k, &ssh->kSz, &kPad);
}
}
@ -5719,8 +5719,8 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
}
if (ret == WS_SUCCESS) {
/* If we aren't using EccKyber, use padding. */
ret = GenerateKeys(ssh, hashId, !ssh->handshake->useEccKyber);
/* If we aren't using ECC with ML-KEM, use padding. */
ret = GenerateKeys(ssh, hashId, !ssh->handshake->useEccMlKem);
}
if (ret == WS_SUCCESS)
@ -10488,10 +10488,10 @@ struct wolfSSH_sigKeyBlockFull {
} sk;
};
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
/* Size of Kyber public key (bigger than ciphertext) and some extra for the
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
/* Size of ML-KEM public key (bigger than ciphertext) and some extra for the
* ECC hybrid component. */
#define KEX_F_SIZE 1024
#define KEX_F_SIZE 1300
#elif !defined(WOLFSSH_NO_DH_GROUP16_SHA512)
#define KEX_F_SIZE (512 + 1)
#else
@ -11388,7 +11388,7 @@ static int KeyAgreeCurve25519_server(WOLFSSH* ssh, byte hashId,
#endif /* WOLFSSH_NO_CURVE25519_SHA256 */
/* KeyAgreeEcdhKyber512_server
/* KeyAgreeEcdhMlKem_server
* hashId - wolfCrypt hash type ID used
* f - peer public key
* fSz - peer public key size
@ -11399,14 +11399,14 @@ static int KeyAgreeCurve25519_server(WOLFSSH* ssh, byte hashId,
* generate and encapsulate the shared secret and send the
* ciphertext.
*/
static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
static int KeyAgreeEcdhMlKem_server(WOLFSSH* ssh, byte hashId,
byte* f, word32* fSz)
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
{
int ret = WS_SUCCESS;
byte sharedSecretHashSz = 0;
byte *sharedSecretHash = NULL;
KyberKey kem = {0};
MlKemKey kem = {0};
word32 length_publickey = 0;
word32 length_ciphertext = 0;
word32 length_sharedsecret = 0;
@ -11417,7 +11417,7 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
ecc_key eccKeys[2];
#endif
WLOG(WS_LOG_DEBUG, "Entering KeyAgreeEcdhKyber512_server()");
WLOG(WS_LOG_DEBUG, "Entering KeyAgreeEcdhMlKem_server()");
#ifdef WOLFSSH_SMALL_STACK
pubKey = (ecc_key*)WMALLOC(sizeof(ecc_key),
@ -11442,20 +11442,20 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
}
if (ret == 0) {
ret = wc_KyberKey_Init(KYBER512, &kem, ssh->ctx->heap,
ret = wc_MlKemKey_Init(&kem, WC_ML_KEM_768, ssh->ctx->heap,
INVALID_DEVID);
}
if (ret == 0) {
ret = wc_KyberKey_CipherTextSize(&kem, &length_ciphertext);
ret = wc_MlKemKey_CipherTextSize(&kem, &length_ciphertext);
}
if (ret == 0) {
ret = wc_KyberKey_SharedSecretSize(&kem, &length_sharedsecret);
ret = wc_MlKemKey_SharedSecretSize(&kem, &length_sharedsecret);
}
if (ret == 0) {
ret = wc_KyberKey_PublicKeySize(&kem, &length_publickey);
ret = wc_MlKemKey_PublicKeySize(&kem, &length_publickey);
}
if ((ret == 0) && (ssh->handshake->eSz <= length_publickey)) {
@ -11463,12 +11463,12 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
}
if (ret == 0) {
ret = wc_KyberKey_DecodePublicKey(&kem, ssh->handshake->e,
ret = wc_MlKemKey_DecodePublicKey(&kem, ssh->handshake->e,
length_publickey);
}
if (ret == 0) {
ret = wc_KyberKey_Encapsulate(&kem, f, ssh->k, ssh->rng);
ret = wc_MlKemKey_Encapsulate(&kem, f, ssh->k, ssh->rng);
}
if (ret == 0) {
@ -11478,12 +11478,12 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
else {
ret = WS_PUBKEY_REJECTED_E;
WLOG(WS_LOG_ERROR,
"Generate ECC-kyber (encap) shared secret failed, %d", ret);
"Generate ECC and ML-KEM (encap) shared secret failed, %d", ret);
*fSz = 0;
ssh->kSz = 0;
}
wc_KyberKey_Free(&kem);
wc_MlKemKey_Free(&kem);
if (ret == 0) {
ret = wc_ecc_init_ex(pubKey, ssh->ctx->heap, INVALID_DEVID);
@ -11554,10 +11554,10 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
WFREE(sharedSecretHash, ssh->ctx->heap, DYNTYPE_PRIVKEY);
}
WLOG(WS_LOG_DEBUG, "Leaving KeyAgreeEcdhKyber512_server(), ret = %d", ret);
WLOG(WS_LOG_DEBUG, "Leaving KeyAgreeEcdhMlKem_server(), ret = %d", ret);
return ret;
}
#else /* WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
#else /* WOLFSSH_NO_NISTP256_MLKEM768_SHA256 */
{
WOLFSSH_UNUSED(ssh);
WOLFSSH_UNUSED(hashId);
@ -11565,7 +11565,7 @@ static int KeyAgreeEcdhKyber512_server(WOLFSSH* ssh, byte hashId,
WOLFSSH_UNUSED(fSz);
return WS_INVALID_ALGO_ID;
}
#endif /* WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
#endif /* WOLFSSH_NO_NISTP256_MLKEM768_SHA256 */
static int SignHRsa(WOLFSSH* ssh, byte* sig, word32* sigSz,
@ -11856,7 +11856,7 @@ int SendKexDhReply(WOLFSSH* ssh)
byte useDh = 0;
byte useEcc = 0;
byte useCurve25519 = 0;
byte useEccKyber = 0;
byte useEccMlKem = 0;
WLOG(WS_LOG_DEBUG, "Entering SendKexDhReply()");
@ -11962,9 +11962,9 @@ int SendKexDhReply(WOLFSSH* ssh)
msgId = MSGID_KEXDH_REPLY;
break;
#endif
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
useEccKyber = 1; /* Only support level 1 for now. */
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
case ID_NISTP256_MLKEM768_SHA256:
useEccMlKem = 1; /* Only support level 1 for now. */
msgId = MSGID_KEXKEM_REPLY;
break;
#endif
@ -12012,8 +12012,8 @@ int SendKexDhReply(WOLFSSH* ssh)
if (useCurve25519) {
ret = KeyAgreeCurve25519_server(ssh, hashId, f_ptr, &fSz);
}
else if (useEccKyber) {
ret = KeyAgreeEcdhKyber512_server(ssh, hashId, f_ptr, &fSz);
else if (useEccMlKem) {
ret = KeyAgreeEcdhMlKem_server(ssh, hashId, f_ptr, &fSz);
}
}
@ -12034,7 +12034,7 @@ int SendKexDhReply(WOLFSSH* ssh)
}
/* Hash in the shared secret K. */
if (ret == 0 && !useEccKyber) {
if (ret == 0 && !useEccMlKem) {
ret = CreateMpint(ssh->k, &ssh->kSz, &kPad);
}
if (ret == 0) {
@ -12099,8 +12099,8 @@ int SendKexDhReply(WOLFSSH* ssh)
}
if (ret == WS_SUCCESS) {
/* If we aren't using EccKyber, use padding. */
ret = GenerateKeys(ssh, hashId, !useEccKyber);
/* If we aren't using ECC with ML-KEM, use padding. */
ret = GenerateKeys(ssh, hashId, !useEccMlKem);
}
/* Get the buffer, copy the packet data, once f is laid into the buffer,
@ -12545,10 +12545,10 @@ int SendKexDhInit(WOLFSSH* ssh)
msgId = MSGID_KEXECDH_INIT;
break;
#endif
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
case ID_NISTP256_MLKEM768_SHA256:
/* Only support level 1 for now. */
ssh->handshake->useEccKyber = 1;
ssh->handshake->useEccMlKem = 1;
msgId = MSGID_KEXKEM_INIT;
break;
#endif
@ -12560,8 +12560,8 @@ int SendKexDhInit(WOLFSSH* ssh)
if (ret == WS_SUCCESS) {
if (!ssh->handshake->useEcc
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
&& !ssh->handshake->useEccKyber
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
&& !ssh->handshake->useEccMlKem
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
&& !ssh->handshake->useCurve25519
@ -12599,8 +12599,8 @@ int SendKexDhInit(WOLFSSH* ssh)
}
#endif /* ! WOLFSSH_NO_CURVE25519_SHA256 */
else if (ssh->handshake->useEcc
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
|| ssh->handshake->useEccKyber
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
|| ssh->handshake->useEccMlKem
#endif
) {
#if !defined(WOLFSSH_NO_ECDH)
@ -12634,28 +12634,28 @@ int SendKexDhInit(WOLFSSH* ssh)
ret = WS_INVALID_ALGO_ID;
}
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
if (ssh->handshake->useEccKyber) {
KyberKey kem = {0};
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
if (ssh->handshake->useEccMlKem) {
MlKemKey kem = {0};
word32 length_publickey = 0;
word32 length_privatekey = 0;
ret = 0;
if (ret == 0) {
ret = wc_KyberKey_Init(KYBER512, &kem, ssh->ctx->heap,
ret = wc_MlKemKey_Init(&kem, WC_ML_KEM_768, ssh->ctx->heap,
INVALID_DEVID);
}
if (ret == 0) {
ret = wc_KyberKey_MakeKey(&kem, ssh->rng);
ret = wc_MlKemKey_MakeKey(&kem, ssh->rng);
}
if (ret == 0) {
ret = wc_KyberKey_PublicKeySize(&kem, &length_publickey);
ret = wc_MlKemKey_PublicKeySize(&kem, &length_publickey);
}
if (ret == 0) {
ret = wc_KyberKey_PrivateKeySize(&kem, &length_privatekey);
ret = wc_MlKemKey_PrivateKeySize(&kem, &length_privatekey);
}
if (ret == 0) {
@ -12663,27 +12663,27 @@ int SendKexDhInit(WOLFSSH* ssh)
* this assumes the PQ public key is bigger than the ECC public
* key. */
XMEMCPY(e + length_publickey, e, eSz);
ret = wc_KyberKey_EncodePublicKey(&kem, e, length_publickey);
ret = wc_MlKemKey_EncodePublicKey(&kem, e, length_publickey);
eSz += length_publickey;
}
if (ret == 0) {
ret = wc_KyberKey_EncodePrivateKey(&kem, ssh->handshake->x,
ret = wc_MlKemKey_EncodePrivateKey(&kem, ssh->handshake->x,
length_privatekey);
ssh->handshake->xSz = length_privatekey;
}
wc_KyberKey_Free(&kem);
wc_MlKemKey_Free(&kem);
}
#endif /* ! WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256 */
#endif /* ! WOLFSSH_NO_NISTP256_MLKEM768_SHA256 */
if (ret == 0) {
ret = WS_SUCCESS;
}
}
if (ret == WS_SUCCESS
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
&& !ssh->handshake->useEccKyber
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
&& !ssh->handshake->useEccMlKem
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
&& !ssh->handshake->useCurve25519

View File

@ -3034,9 +3034,9 @@ size_t wolfSSH_GetText(WOLFSSH *ssh, WS_Text id, char *str, size_t strSz)
ret = WSNPRINTF(str, strSz, "%s", "ECDH");
break;
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
ret = WSNPRINTF(str, strSz, "%s", "ECDH-KYBER512");
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
case ID_NISTP256_MLKEM768_SHA256:
ret = WSNPRINTF(str, strSz, "%s", "ECDH-MLKEM768");
break;
#endif

View File

@ -174,10 +174,10 @@ extern "C" {
#undef WOLFSSH_NO_ECDH_SHA2_NISTP521
#define WOLFSSH_NO_ECDH_SHA2_NISTP521
#endif
#if !defined(WOLFSSL_HAVE_KYBER) || defined(NO_SHA256) \
#if !defined(WOLFSSL_HAVE_MLKEM) || defined(NO_SHA256) \
|| defined(WOLFSSH_NO_ECDH_SHA2_NISTP256)
#undef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#define WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#undef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
#define WOLFSSH_NO_NISTP256_MLKEM768_SHA256
#endif
#if !defined(HAVE_CURVE25519) || defined(NO_SHA256)
#undef WOLFSSH_NO_CURVE25519_SHA256
@ -192,7 +192,7 @@ extern "C" {
defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP521) && \
defined(WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256) && \
defined(WOLFSSH_NO_NISTP256_MLKEM768_SHA256) && \
defined(WOLFSSH_NO_CURVE25519_SHA256)
#error "You need at least one key agreement algorithm."
#endif
@ -335,8 +335,8 @@ enum {
ID_ECDH_SHA2_NISTP256,
ID_ECDH_SHA2_NISTP384,
ID_ECDH_SHA2_NISTP521,
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256,
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
ID_NISTP256_MLKEM768_SHA256,
#endif
#ifndef WOLFSSH_NO_CURVE25519_SHA256
ID_CURVE25519_SHA256,
@ -445,9 +445,9 @@ enum NameIdType {
#define WOLFSSH_DEFAULT_GEXDH_MAX 8192
#endif
#ifndef MAX_KEX_KEY_SZ
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
/* Private key size of Kyber Level1. Biggest artifact. */
#define MAX_KEX_KEY_SZ 1632
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
/* Private key size of ML-KEM 768. Biggest artifact. */
#define MAX_KEX_KEY_SZ 2400
#else
/* This is based on the 8192-bit DH key that is the max size. */
#define MAX_KEX_KEY_SZ (WOLFSSH_DEFAULT_GEXDH_MAX / 8)
@ -627,7 +627,7 @@ typedef struct HandshakeInfo {
byte useDh:1;
byte useEcc:1;
byte useEccKyber:1;
byte useEccMlKem:1;
byte useCurve25519:1;
union {
@ -1146,13 +1146,13 @@ enum WS_MessageIds {
MSGID_KEXDH_INIT = 30,
MSGID_KEXECDH_INIT = 30,
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
MSGID_KEXKEM_INIT = 30,
#endif
MSGID_KEXDH_REPLY = 31,
MSGID_KEXECDH_REPLY = 31,
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_NISTP256_MLKEM768_SHA256
MSGID_KEXKEM_REPLY = 31,
#endif