Replace Saber Level1 with hybrid ECDH-P256 Kyber-Level1.

pull/437/head
Anthony Hu 2022-08-05 12:59:43 -04:00
parent a0da4e3cc5
commit ae668a0e8d
3 changed files with 192 additions and 98 deletions

View File

@ -402,9 +402,9 @@ behavior, give the echoserver the command line option `-f`.
POST-QUANTUM
============
wolfSSH now supports the post-quantum algorithm SABER. It uses the NIST
wolfSSH now supports the post-quantum algorithm Kyber. It uses the NIST
submission's Level 1 parameter set implemented by liboqs via an integration
with wolfSSH.
with wolfSSH. It is hybridized with ECDHE over the P-256 ECC curve.
In order be able to use liboqs, you must have it built and installed on your
system. We support the 0.7.0 release of liboqs. You can download it from the
@ -422,13 +422,13 @@ Once unpacked, this would be sufficient:
$ sudo make install
In order to enable support for SABER Level1 in wolfSSH, use the `--with-liboqs`
build option during configuration:
In order to enable support for Kyber Level1 hybridized with ECDHE over the P-256
ECC curve in wolfSSH, use the `--with-liboqs` build option during configuration:
$ ./configure --with-liboqs
The wolfSSH client and server will automatically negotiate using SABER Level1
if this feature is enabled.
The wolfSSH client and server will automatically negotiate using Kyber Level1
hybridized with ECDHE over the P-256 ECC curve if this feature is enabled.
$ ./examples/echoserver/echoserver -f
@ -450,7 +450,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 +saber-lightsaber-sha256" \
$ ./ssh -o"KexAlgorithms +ecdh-sha2-nistp256-kyber-512-sha256" \
-o"PubkeyAcceptedAlgorithms +ssh-rsa" \
-o"HostkeyAlgorithms +ssh-rsa" \
jill@localhost -p 22222

View File

@ -107,9 +107,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_SABER_LEVEL1_SHA256
Set when there is no liboqs integration. Set to disable use of post-quantum
SABER Level 1 KEM.
WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
Set when there is no liboqs integration. Set to disable use of ECDHE with
prime NISTP256 hybridized with post-quantum Kyber Level1 KEM.
WOLFSSH_NO_AES_CBC
Set when AES or AES-CBC are disabled. Set to disable use of AES-CBC
encryption.
@ -1098,9 +1098,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_DH_GEX_SHA256
{ ID_DH_GROUP14_SHA256, "diffie-hellman-group14-sha256" },
#endif
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
/* We use lightsaber here to achieve interop with OQS's fork. */
{ ID_SABER_LEVEL1_SHA256, "saber-lightsaber-sha256" },
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
/* We use kyber-512 here to achieve interop with OQS's fork. */
{ ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256, "ecdh-sha2-nistp256-kyber-512-sha256" },
#endif
/* Public Key IDs */
#ifndef WOLFSSH_NO_SSH_RSA_SHA1
@ -2092,8 +2092,8 @@ static const word32 cannedKeyAlgoEcc521Sz = sizeof(cannedKeyAlgoEcc521);
static const byte cannedKexAlgo[] = {
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
ID_SABER_LEVEL1_SHA256,
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256,
#endif
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP521
ID_ECDH_SHA2_NISTP521,
@ -2279,8 +2279,8 @@ static INLINE enum wc_HashType HashForId(byte id)
case ID_ECDSA_SHA2_NISTP256:
return WC_HASH_TYPE_SHA256;
#endif
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
case ID_SABER_LEVEL1_SHA256:
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256:
return WC_HASH_TYPE_SHA256;
#endif
@ -2313,6 +2313,10 @@ static INLINE enum wc_HashType HashForId(byte id)
static INLINE int wcPrimeForId(byte id)
{
switch (id) {
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256:
return ECC_SECP256R1;
#endif
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256
case ID_ECDH_SHA2_NISTP256:
return ECC_SECP256R1;
@ -3275,8 +3279,8 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
* issues with re-key */
ssh->kSz = MAX_KEX_KEY_SZ;
if (!ssh->handshake->useEcc
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
&& !ssh->handshake->useSaber
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
&& !ssh->handshake->useEccKyber
#endif
) {
#ifndef WOLFSSH_NO_DH
@ -3329,33 +3333,55 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
ret = WS_INVALID_ALGO_ID;
#endif
}
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
else if (ssh->handshake->useSaber) {
/* This is a KEM. In this case, I need to decapsulate the
* ciphertext. */
OQS_KEM* kem = NULL;
ret = 0;
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
else if (ssh->handshake->useEccKyber) {
/* 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. */
OQS_KEM* kem = OQS_KEM_new(OQS_KEM_alg_kyber_512);
if (kem == NULL) {
ret = WS_INVALID_ALGO_ID;
}
ret = wc_ecc_init(key_ptr);
#ifdef HAVE_WC_ECC_SET_RNG
if (ret == WS_SUCCESS)
ret = wc_ecc_set_rng(key_ptr, ssh->rng);
#endif
if (ret == 0) {
kem = OQS_KEM_new(OQS_KEM_alg_saber_lightsaber);
if (kem == NULL) {
ret = WS_INVALID_ALGO_ID;
}
ret = wc_ecc_import_x963(f, fSz - kem->length_ciphertext,
key_ptr);
}
if (ret == 0) {
if (fSz != kem->length_ciphertext) {
ret = WS_BUFFER_E;
}
#ifdef PRIVATE_KEY_UNLOCK
PRIVATE_KEY_UNLOCK();
#endif
ret = wc_ecc_shared_secret(&ssh->handshake->privKey.ecc,
key_ptr, ssh->k, &ssh->kSz);
#ifdef PRIVATE_KEY_LOCK
PRIVATE_KEY_LOCK();
#endif
}
wc_ecc_free(key_ptr);
wc_ecc_free(&ssh->handshake->privKey.ecc);
if (OQS_KEM_decaps(kem, ssh->k, f, ssh->handshake->x)
if (OQS_KEM_decaps(kem, ssh->k + ssh->kSz,
f + fSz - kem->length_ciphertext, ssh->handshake->x)
!= OQS_SUCCESS) {
ret = WS_ERROR;
}
if (ret == 0) {
ssh->kSz = kem->length_shared_secret;
ssh->kSz += kem->length_shared_secret;
} else {
ssh->kSz = 0;
WLOG(WS_LOG_ERROR,
"Generate ECC-kyber (decap) shared secret failed, %d", ret);
}
if (kem != NULL) {
OQS_KEM_free(kem);
}
}
#endif
@ -6683,8 +6709,8 @@ static const char cannedKeyAlgoEcc521Names[] = "ecdsa-sha2-nistp521";
#endif
static const char cannedKexAlgoNames[] =
#if !defined(WOLFSSH_NO_SABER_LEVEL1_SHA256)
"saber-lightsaber-sha256,"
#if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256)
"ecdh-sha2-nistp256-kyber-512-sha256,"
#endif
#if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP521)
"ecdh-sha2-nistp521,"
@ -6712,7 +6738,7 @@ static const char cannedKexAlgoNames[] =
defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP521) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \
defined(WOLFSSH_NO_SABER_LEVEL1_256)
defined(WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256)
#warning "You need at least one key exchange algorithm."
#endif
@ -6897,9 +6923,10 @@ struct wolfSSH_sigKeyBlockFull {
} sk;
};
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
/* Size of SABER Level1 ciphertext. */
#define KEX_F_SIZE 736
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
/* Size of Kyber public key (bigger than ciphertext) and some extra for the
* ECC hybrid component. */
#define KEX_F_SIZE 1024
#else
#define KEX_F_SIZE (256 + 1)
#endif
@ -6927,8 +6954,8 @@ int SendKexDhReply(WOLFSSH* ssh)
word32 fSz = KEX_F_SIZE;
word32 sigSz = KEX_SIG_SIZE;
byte useEcc = 0;
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
byte useSaber = 0;
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
byte useEccKyber = 0;
#endif
byte fPad = 0;
byte kPad = 0;
@ -7032,9 +7059,9 @@ int SendKexDhReply(WOLFSSH* ssh)
msgId = MSGID_KEXDH_REPLY;
break;
#endif
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
case ID_SABER_LEVEL1_SHA256:
useSaber = 1; /* Only support level 1 for now. */
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256:
useEccKyber = 1; /* Only support level 1 for now. */
msgId = MSGID_KEXKEM_REPLY;
break;
#endif
@ -7332,8 +7359,8 @@ int SendKexDhReply(WOLFSSH* ssh)
/* Or make the server's ECDH private value, and the shared secret K. */
if (ret == 0) {
if (!useEcc
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
&& !useSaber
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
&& !useEccKyber
#endif
) {
#ifndef WOLFSSH_NO_DH
@ -7445,36 +7472,108 @@ int SendKexDhReply(WOLFSSH* ssh)
#endif
#endif /* !defined(WOLFSSH_NO_ECDH) */
}
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
else if (useSaber) {
/* This is a KEM. In this case, I need to encapsulate the
* shared secret. */
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
else if (useEccKyber) {
/* This is a hybrid KEM. In this case, I need to generate my ECC
* keypair, send the public one, use the private one to generate
* the shared secret, use the post-quantum public key to
* generate and encapsulate the shared secret and send the
* ciphertext. */
OQS_KEM* kem = NULL;
int primeId;
ret = 0;
#ifdef WOLFSSH_SMALL_STACK
ecc_key *pubKey = NULL, *privKey = NULL;
pubKey = (ecc_key*)WMALLOC(sizeof(ecc_key), heap,
DYNTYPE_PUBKEY);
privKey = (ecc_key*)WMALLOC(sizeof(ecc_key), heap,
DYNTYPE_PRIVKEY);
if (pubKey == NULL || privKey == NULL) {
ret = WS_MEMORY_E;
}
#else
ecc_key pubKey[1];
ecc_key privKey[1];
#endif
if (ret == 0) {
kem = OQS_KEM_new(OQS_KEM_alg_saber_lightsaber);
kem = OQS_KEM_new(OQS_KEM_alg_kyber_512);
if (kem == NULL) {
ret = WS_INVALID_ALGO_ID;
}
}
primeId = wcPrimeForId(ssh->handshake->kexId);
if (primeId == ECC_CURVE_INVALID)
ret = WS_INVALID_PRIME_CURVE;
if (ret == 0)
ret = wc_ecc_init_ex(pubKey, heap, INVALID_DEVID);
if (ret == 0)
ret = wc_ecc_init_ex(privKey, heap, INVALID_DEVID);
#ifdef HAVE_WC_ECC_SET_RNG
if (ret == 0)
ret = wc_ecc_set_rng(privKey, ssh->rng);
#endif
if (ret == 0)
ret = wc_ecc_import_x963_ex(ssh->handshake->e,
ssh->handshake->eSz - kem->length_public_key,
pubKey, primeId);
if (ret == 0)
ret = wc_ecc_make_key_ex(ssh->rng,
wc_ecc_get_curve_size_from_id(primeId),
privKey, primeId);
if (ret == 0) {
if (ssh->handshake->eSz != kem->length_public_key) {
ret = WS_PUBKEY_REJECTED_E;
}
#ifdef PRIVATE_KEY_UNLOCK
PRIVATE_KEY_UNLOCK();
#endif
ret = wc_ecc_export_x963(privKey, f_ptr, &fSz);
#ifdef PRIVATE_KEY_LOCK
PRIVATE_KEY_LOCK();
#endif
}
if (ret == 0) {
#ifdef PRIVATE_KEY_UNLOCK
PRIVATE_KEY_UNLOCK();
#endif
ret = wc_ecc_shared_secret(privKey, pubKey,
ssh->k, &ssh->kSz);
#ifdef PRIVATE_KEY_LOCK
PRIVATE_KEY_LOCK();
#endif
}
wc_ecc_free(privKey);
wc_ecc_free(pubKey);
#ifdef WOLFSSH_SMALL_STACK
WFREE(pubKey, heap, DYNTYPE_PUBKEY);
WFREE(privKey, heap, DYNTYPE_PRIVKEY);
pubKey = NULL;
privKey = NULL;
#endif
if (ret == 0) {
if (OQS_KEM_encaps(kem, f_ptr, ssh->k, ssh->handshake->e)
if (OQS_KEM_encaps(kem, f_ptr + fSz, ssh->k + ssh->kSz,
ssh->handshake->e + ssh->handshake->eSz
- kem->length_public_key)
!= OQS_SUCCESS) {
ret = WS_PUBKEY_REJECTED_E;
}
}
if (ret == 0) {
ssh->kSz = kem->length_shared_secret;
fSz = kem->length_ciphertext;
fSz += kem->length_ciphertext;
ssh->kSz += kem->length_shared_secret;
} else {
fSz = 0;
ssh->kSz = 0;
WLOG(WS_LOG_ERROR,
"Generate ECC-kyber (encap) shared secret failed, %d", ret);
}
if (kem != NULL) {
OQS_KEM_free(kem);
}
}
#endif
@ -7485,12 +7584,7 @@ int SendKexDhReply(WOLFSSH* ssh)
}
/* Hash in the server's DH f-value. */
/* Do not want leading zero's removed for SABER. */
if (ret == 0
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
&& !useSaber
#endif
) {
if (ret == 0) {
ret = CreateMpint(f_ptr, &fSz, &fPad);
}
if (ret == 0) {
@ -8055,10 +8149,10 @@ int SendKexDhInit(WOLFSSH* ssh)
msgId = MSGID_KEXECDH_INIT;
break;
#endif
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
case ID_SABER_LEVEL1_SHA256:
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256:
/* Only support level 1 for now. */
ssh->handshake->useSaber = 1;
ssh->handshake->useEccKyber = 1;
msgId = MSGID_KEXKEM_INIT;
break;
#endif
@ -8070,8 +8164,8 @@ int SendKexDhInit(WOLFSSH* ssh)
if (ret == WS_SUCCESS) {
if (!ssh->handshake->useEcc
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
&& !ssh->handshake->useSaber
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
&& !ssh->handshake->useEccKyber
#endif
) {
#ifndef WOLFSSH_NO_DH
@ -8088,7 +8182,7 @@ int SendKexDhInit(WOLFSSH* ssh)
e, &eSz);
#endif
}
else if (ssh->handshake->useEcc) {
else if (ssh->handshake->useEcc || ssh->handshake->useEccKyber) {
#if !defined(WOLFSSH_NO_ECDH)
ecc_key* privKey = &ssh->handshake->privKey.ecc;
int primeId = wcPrimeForId(ssh->handshake->kexId);
@ -8120,41 +8214,41 @@ int SendKexDhInit(WOLFSSH* ssh)
ret = WS_INVALID_ALGO_ID;
#endif /* !defined(WOLFSSH_NO_ECDH) */
}
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
else if (ssh->handshake->useSaber) {
else {
ret = WS_INVALID_ALGO_ID;
}
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
if (ssh->handshake->useEccKyber) {
OQS_KEM* kem = NULL;
ret = 0;
kem = OQS_KEM_new(OQS_KEM_alg_saber_lightsaber);
kem = OQS_KEM_new(OQS_KEM_alg_kyber_512);
if (kem == NULL) {
ret = WS_INVALID_ALGO_ID;
}
if (ret == 0) {
if (OQS_KEM_keypair(kem, e, ssh->handshake->x)
if (OQS_KEM_keypair(kem, e + eSz, ssh->handshake->x)
!= OQS_SUCCESS) {
/* This should never happen */
ret = WS_ERROR;
}
eSz = kem->length_public_key;
eSz += kem->length_public_key;
ssh->handshake->xSz = kem->length_secret_key;
}
if (kem != NULL) {
OQS_KEM_free(kem);
}
}
#endif
else {
ret = WS_INVALID_ALGO_ID;
}
if (ret == 0)
ret = WS_SUCCESS;
}
/* Do not want leading zero's removed for SABER. */
if (ret == WS_SUCCESS
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
&& !ssh->handshake->useSaber
#endif
) {
if (ret == WS_SUCCESS) {
ret = CreateMpint(e, &eSz, &ePad);
}

View File

@ -133,8 +133,8 @@ extern "C" {
#define WOLFSSH_NO_ECDH_SHA2_ED25519
#endif
#if !defined(WOLFSSH_HAVE_LIBOQS) || defined(NO_SHA256)
#undef WOLFSSH_NO_SABER_LEVEL1_SHA256
#define WOLFSSH_NO_SABER_LEVEL1_SHA256
#undef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
#define WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
#endif
#if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
@ -144,7 +144,7 @@ extern "C" {
defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP521) && \
defined(WOLFSSH_NO_ECDH_SHA2_ED25519) && \
defined(WOLFSSH_NO_SABER_LEVEL1_SHA256)
defined(WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256)
#error "You need at least one key agreement algorithm."
#endif
@ -271,8 +271,8 @@ enum {
ID_ECDH_SHA2_ED25519,
ID_ECDH_SHA2_ED25519_LIBSSH,
ID_DH_GROUP14_SHA256,
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
ID_SABER_LEVEL1_SHA256,
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
ID_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256,
#endif
/* Public Key IDs */
@ -350,9 +350,9 @@ enum {
#define WOLFSSH_DEFAULT_GEXDH_MAX 8192
#endif
#ifndef MAX_KEX_KEY_SZ
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
/* Private key size of SABER Level1. Biggest artifact. */
#define MAX_KEX_KEY_SZ 1568
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
/* Private key size of Kyber Level1. Biggest artifact. */
#define MAX_KEX_KEY_SZ 1632
#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)
@ -417,8 +417,8 @@ struct WOLFSSH_CTX {
byte* privateKey; /* Owned by CTX */
word32 privateKeySz;
byte useEcc; /* Depends on the private key */
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
byte useSaber:1; /* Depends on the private key */
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
byte useEccKyber; /* Depends on the private key */
#endif
word32 highwaterMark;
const char* banner;
@ -483,8 +483,8 @@ typedef struct HandshakeInfo {
#endif
byte useEcc;
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
byte useSaber:1;
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
byte useEccKyber;
#endif
union {
@ -909,13 +909,13 @@ enum WS_MessageIds {
MSGID_KEXDH_INIT = 30,
MSGID_KEXECDH_INIT = 30,
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
MSGID_KEXKEM_INIT = 30,
#endif
MSGID_KEXDH_REPLY = 31,
MSGID_KEXECDH_REPLY = 31,
#ifndef WOLFSSH_NO_SABER_LEVEL1_SHA256
#ifndef WOLFSSH_NO_ECDH_SHA2_NISTP256_KYBER_LEVEL1_SHA256
MSGID_KEXKEM_REPLY = 31,
#endif