diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index 609481a3e0..177c3c3988 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -291,9 +291,14 @@ static struct group_info groups[] = { { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" }, { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" }, { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" }, - { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" }, - { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" }, - { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" }, + { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" }, + { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" }, + { WOLFSSL_P256_KYBER_LEVEL3, "P256_KYBER_LEVEL3" }, + { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" }, + { WOLFSSL_P384_KYBER_LEVEL5, "P384_KYBER_LEVEL5" }, + { WOLFSSL_X25519_KYBER_LEVEL1, "X25519_KYBER_LEVEL1" }, + { WOLFSSL_X448_KYBER_LEVEL3, "X448_KYBER_LEVEL3" }, + { WOLFSSL_X25519_KYBER_LEVEL3, "X25519_KYBER_LEVEL3" }, #endif { 0, NULL } }; diff --git a/examples/client/client.c b/examples/client/client.c index b8adcc1924..3fdd2b1a8b 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -426,15 +426,38 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, if (XSTRCMP(pqcAlg, "P384_KYBER_LEVEL3") == 0) { group = WOLFSSL_P384_KYBER_LEVEL3; } + else if (XSTRCMP(pqcAlg, "P256_KYBER_LEVEL3") == 0) { + group = WOLFSSL_P256_KYBER_LEVEL3; + } else #endif #ifndef WOLFSSL_NO_KYBER1024 if (XSTRCMP(pqcAlg, "P521_KYBER_LEVEL5") == 0) { group = WOLFSSL_P521_KYBER_LEVEL5; } + else if (XSTRCMP(pqcAlg, "P384_KYBER_LEVEL5") == 0) { + group = WOLFSSL_P384_KYBER_LEVEL5; + } else #endif - { + #if !defined(WOLFSSL_NO_KYBER512) && defined(HAVE_CURVE25519) + if (XSTRCMP(pqcAlg, "X25519_KYBER_LEVEL1") == 0) { + group = WOLFSSL_X25519_KYBER_LEVEL1; + } + else + #endif + #if !defined(WOLFSSL_NO_KYBER768) && defined(HAVE_CURVE25519) + if (XSTRCMP(pqcAlg, "X25519_KYBER_LEVEL3") == 0) { + group = WOLFSSL_X25519_KYBER_LEVEL3; + } + else + #endif + #if !defined(WOLFSSL_NO_KYBER768) && defined(HAVE_CURVE448) + if (XSTRCMP(pqcAlg, "X448_KYBER_LEVEL3") == 0) { + group = WOLFSSL_X448_KYBER_LEVEL3; + } + #endif + else { err_sys("invalid post-quantum KEM specified"); } diff --git a/examples/server/server.c b/examples/server/server.c index 2f42a909e3..c2af4dadb7 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -740,12 +740,36 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, if (XSTRCMP(pqcAlg, "P384_KYBER_LEVEL3") == 0) { groups[count] = WOLFSSL_P384_KYBER_LEVEL3; } + else if (XSTRCMP(pqcAlg, "P256_KYBER_LEVEL3") == 0) { + groups[count] = WOLFSSL_P256_KYBER_LEVEL3; + } else #endif #ifndef WOLFSSL_NO_KYBER1024 if (XSTRCMP(pqcAlg, "P521_KYBER_LEVEL5") == 0) { groups[count] = WOLFSSL_P521_KYBER_LEVEL5; } + else if (XSTRCMP(pqcAlg, "P384_KYBER_LEVEL5") == 0) { + groups[count] = WOLFSSL_P384_KYBER_LEVEL5; + } + else + #endif + #if !defined(WOLFSSL_NO_KYBER512) && defined(HAVE_CURVE25519) + if (XSTRCMP(pqcAlg, "X25519_KYBER_LEVEL1") == 0) { + groups[count] = WOLFSSL_X25519_KYBER_LEVEL1; + } + else + #endif + #if !defined(WOLFSSL_NO_KYBER768) && defined(HAVE_CURVE25519) + if (XSTRCMP(pqcAlg, "X25519_KYBER_LEVEL3") == 0) { + groups[count] = WOLFSSL_X25519_KYBER_LEVEL3; + } + else + #endif + #if !defined(WOLFSSL_NO_KYBER768) && defined(HAVE_CURVE448) + if (XSTRCMP(pqcAlg, "X448_KYBER_LEVEL3") == 0) { + groups[count] = WOLFSSL_X448_KYBER_LEVEL3; + } else #endif { diff --git a/src/internal.c b/src/internal.c index 2fc63753f6..390493cda5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -34131,6 +34131,29 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* HAVE_ECC */ +#ifdef WOLFSSL_HAVE_KYBER + /* Returns 1 when the given group is a PQC group, 0 otherwise. */ + int NamedGroupIsPqc(int group) + { + switch (group) { + case WOLFSSL_KYBER_LEVEL1: + case WOLFSSL_KYBER_LEVEL3: + case WOLFSSL_KYBER_LEVEL5: + case WOLFSSL_P256_KYBER_LEVEL3: + case WOLFSSL_X25519_KYBER_LEVEL3: + case WOLFSSL_P384_KYBER_LEVEL5: + case WOLFSSL_P256_KYBER_LEVEL1: + case WOLFSSL_P384_KYBER_LEVEL3: + case WOLFSSL_P521_KYBER_LEVEL5: + case WOLFSSL_X25519_KYBER_LEVEL1: + case WOLFSSL_X448_KYBER_LEVEL3: + return 1; + default: + return 0; + } + } +#endif /* WOLFSSL_HAVE_KYBER */ + int TranslateErrorToAlert(int err) { switch (err) { diff --git a/src/ssl.c b/src/ssl.c index 264f2c04ec..4f39fa5380 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3304,6 +3304,11 @@ static int isValidCurveGroup(word16 name) case WOLFSSL_P256_KYBER_LEVEL1: case WOLFSSL_P384_KYBER_LEVEL3: case WOLFSSL_P521_KYBER_LEVEL5: + case WOLFSSL_P384_KYBER_LEVEL5: + case WOLFSSL_X25519_KYBER_LEVEL1: + case WOLFSSL_X448_KYBER_LEVEL3: + case WOLFSSL_X25519_KYBER_LEVEL3: + case WOLFSSL_P256_KYBER_LEVEL3: #endif #endif return 1; @@ -14448,37 +14453,67 @@ const char* wolfSSL_get_curve_name(WOLFSSL* ssl) * check to override this result in the case of a hybrid. */ if (IsAtLeastTLSv1_3(ssl->version)) { switch (ssl->namedGroup) { -#ifdef HAVE_LIBOQS - case WOLFSSL_KYBER_LEVEL1: - return "KYBER_LEVEL1"; - case WOLFSSL_KYBER_LEVEL3: - return "KYBER_LEVEL3"; - case WOLFSSL_KYBER_LEVEL5: - return "KYBER_LEVEL5"; - case WOLFSSL_P256_KYBER_LEVEL1: - return "P256_KYBER_LEVEL1"; - case WOLFSSL_P384_KYBER_LEVEL3: - return "P384_KYBER_LEVEL3"; - case WOLFSSL_P521_KYBER_LEVEL5: - return "P521_KYBER_LEVEL5"; -#elif defined(WOLFSSL_WC_KYBER) +#if defined(WOLFSSL_WC_KYBER) #ifdef WOLFSSL_KYBER512 case WOLFSSL_KYBER_LEVEL1: return "KYBER_LEVEL1"; case WOLFSSL_P256_KYBER_LEVEL1: return "P256_KYBER_LEVEL1"; + #ifdef HAVE_CURVE25519 + case WOLFSSL_X25519_KYBER_LEVEL1: + return "X25519_KYBER_LEVEL1"; + #endif #endif #ifdef WOLFSSL_KYBER768 case WOLFSSL_KYBER_LEVEL3: return "KYBER_LEVEL3"; case WOLFSSL_P384_KYBER_LEVEL3: return "P384_KYBER_LEVEL3"; + case WOLFSSL_P256_KYBER_LEVEL3: + return "P256_KYBER_LEVEL3"; + #ifdef HAVE_CURVE25519 + case WOLFSSL_X25519_KYBER_LEVEL3: + return "X25519_KYBER_LEVEL3"; + #endif + #ifdef HAVE_CURVE448 + case WOLFSSL_X448_KYBER_LEVEL3: + return "X448_KYBER_LEVEL3"; + #endif #endif #ifdef WOLFSSL_KYBER1024 case WOLFSSL_KYBER_LEVEL5: return "KYBER_LEVEL5"; case WOLFSSL_P521_KYBER_LEVEL5: return "P521_KYBER_LEVEL5"; + case WOLFSSL_P384_KYBER_LEVEL5: + return "P384_KYBER_LEVEL5"; + #endif +#elif defined (HAVE_LIBOQS) + case WOLFSSL_KYBER_LEVEL1: + return "KYBER_LEVEL1"; + case WOLFSSL_KYBER_LEVEL3: + return "KYBER_LEVEL3"; + case WOLFSSL_KYBER_LEVEL5: + return "KYBER_LEVEL5"; + case WOLFSSL_P256_KYBER_LEVEL1: + return "P256_KYBER_LEVEL1"; + case WOLFSSL_P384_KYBER_LEVEL3: + return "P384_KYBER_LEVEL3"; + case WOLFSSL_P256_KYBER_LEVEL3: + return "P256_KYBER_LEVEL3"; + case WOLFSSL_P521_KYBER_LEVEL5: + return "P521_KYBER_LEVEL5"; + case WOLFSSL_P384_KYBER_LEVEL5: + return "P384_KYBER_LEVEL5"; + #ifdef HAVE_CURVE25519 + case WOLFSSL_X25519_KYBER_LEVEL1: + return "X25519_KYBER_LEVEL1"; + case WOLFSSL_X25519_KYBER_LEVEL3: + return "X25519_KYBER_LEVEL3"; + #endif + #ifdef HAVE_CURVE448 + case WOLFSSL_X448_KYBER_LEVEL3: + return "X448_KYBER_LEVEL3"; #endif #endif } @@ -21775,7 +21810,12 @@ const WOLF_EC_NIST_NAME kNistCurves[] = { #if (defined(WOLFSSL_WC_KYBER) || defined(HAVE_LIBOQS)) && defined(HAVE_ECC) {CURVE_NAME("P256_KYBER_LEVEL1"), WOLFSSL_P256_KYBER_LEVEL1, WOLFSSL_P256_KYBER_LEVEL1}, {CURVE_NAME("P384_KYBER_LEVEL3"), WOLFSSL_P384_KYBER_LEVEL3, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("P256_KYBER_LEVEL3"), WOLFSSL_P256_KYBER_LEVEL3, WOLFSSL_P256_KYBER_LEVEL1}, {CURVE_NAME("P521_KYBER_LEVEL5"), WOLFSSL_P521_KYBER_LEVEL5, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("P384_KYBER_LEVEL5"), WOLFSSL_P384_KYBER_LEVEL5, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("X25519_KYBER_LEVEL1"), WOLFSSL_X25519_KYBER_LEVEL1, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("X448_KYBER_LEVEL3"), WOLFSSL_X448_KYBER_LEVEL3, WOLFSSL_P256_KYBER_LEVEL1}, + {CURVE_NAME("X25519_KYBER_LEVEL3"), WOLFSSL_X25519_KYBER_LEVEL3, WOLFSSL_P256_KYBER_LEVEL1}, #endif #endif #ifdef WOLFSSL_SM2 diff --git a/src/tls.c b/src/tls.c index 0aff791697..9c646481d8 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7435,6 +7435,7 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse) if (ret == 0) { /* setting "key" means okay to call wc_curve25519_free */ key = (curve25519_key*)kse->key; + kse->keyLen = CURVE25519_KEYSIZE; #ifdef WOLFSSL_STATIC_EPHEMERAL ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519, kse->key); @@ -7520,6 +7521,7 @@ static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse) ret = wc_curve448_init((curve448_key*)kse->key); if (ret == 0) { key = (curve448_key*)kse->key; + kse->keyLen = CURVE448_KEY_SIZE; #ifdef WOLFSSL_STATIC_EPHEMERAL ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE448, kse->key); @@ -7777,8 +7779,22 @@ static const PqcHybridMapping pqc_hybrid_mapping[] = { .pqc = WOLFSSL_KYBER_LEVEL1}, {.hybrid = WOLFSSL_P384_KYBER_LEVEL3, .ecc = WOLFSSL_ECC_SECP384R1, .pqc = WOLFSSL_KYBER_LEVEL3}, + {.hybrid = WOLFSSL_P256_KYBER_LEVEL3, .ecc = WOLFSSL_ECC_SECP256R1, + .pqc = WOLFSSL_KYBER_LEVEL3}, {.hybrid = WOLFSSL_P521_KYBER_LEVEL5, .ecc = WOLFSSL_ECC_SECP521R1, .pqc = WOLFSSL_KYBER_LEVEL5}, + {.hybrid = WOLFSSL_P384_KYBER_LEVEL5, .ecc = WOLFSSL_ECC_SECP384R1, + .pqc = WOLFSSL_KYBER_LEVEL5}, +#ifdef HAVE_CURVE25519 + {.hybrid = WOLFSSL_X25519_KYBER_LEVEL1, .ecc = WOLFSSL_ECC_X25519, + .pqc = WOLFSSL_KYBER_LEVEL1}, + {.hybrid = WOLFSSL_X25519_KYBER_LEVEL3, .ecc = WOLFSSL_ECC_X25519, + .pqc = WOLFSSL_KYBER_LEVEL3}, +#endif +#ifdef HAVE_CURVE448 + {.hybrid = WOLFSSL_X448_KYBER_LEVEL3, .ecc = WOLFSSL_ECC_X448, + .pqc = WOLFSSL_KYBER_LEVEL3}, +#endif {.hybrid = 0, .ecc = 0, .pqc = 0} }; @@ -7812,7 +7828,7 @@ static void findEccPqc(int *ecc, int *pqc, int group) } } -/* Create a key share entry using liboqs parameters group. +/* Create a key share entry using pqc parameters group. * Generates a key pair. * * ssl The SSL/TLS object. @@ -7827,7 +7843,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) byte* pubKey = NULL; byte* privKey = NULL; KeyShareEntry *ecc_kse = NULL; - int oqs_group = 0; + int pqc_group = 0; int ecc_group = 0; word32 privSz = 0; word32 pubSz = 0; @@ -7839,8 +7855,8 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) return ret; } - findEccPqc(&ecc_group, &oqs_group, kse->group); - ret = kyber_id2type(oqs_group, &type); + findEccPqc(&ecc_group, &pqc_group, kse->group); + ret = kyber_id2type(pqc_group, &type); if (ret == WC_NO_ERR_TRACE(NOT_COMPILED_IN)) { WOLFSSL_MSG("Invalid Kyber algorithm specified."); ret = BAD_FUNC_ARG; @@ -7873,8 +7889,22 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) if (ret == 0 && ecc_group != 0) { ecc_kse->group = ecc_group; - ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); - /* If fail, no error message, TLSX_KeyShare_GenEccKey will do it. */ + #ifdef HAVE_CURVE25519 + if (ecc_group == WOLFSSL_ECC_X25519) { + ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse); + } + else + #endif + #ifdef HAVE_CURVE448 + if (ecc_group == WOLFSSL_ECC_X448) { + ret = TLSX_KeyShare_GenX448Key(ssl, ecc_kse); + } + else + #endif + { + ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); + } + /* No error message, TLSX_KeyShare_GenKey will do it. */ } if (ret == 0) { @@ -7914,7 +7944,7 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse) kse->pubKeyLen = ecc_kse->pubKeyLen + pubSz; pubKey = NULL; - /* Note we are saving the OQS private key and ECC private key + /* Note we are saving the PQC private key and ECC private key * separately. That's because the ECC private key is not simply a * buffer. Its is an ecc_key struct. Typically do not need the private * key size, but will need to zero it out upon freeing. */ @@ -8303,6 +8333,8 @@ static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl, wc_curve25519_free((curve25519_key*)keyShareEntry->key); XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); keyShareEntry->key = NULL; + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; #else (void)ssl; (void)keyShareEntry; @@ -8381,6 +8413,8 @@ static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) wc_curve448_free((curve448_key*)keyShareEntry->key); XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); keyShareEntry->key = NULL; + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; #else (void)ssl; (void)keyShareEntry; @@ -8548,58 +8582,36 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) int ret = 0; int type; KyberKey kem[1]; - byte* sharedSecret = NULL; - word32 sharedSecretLen = 0; - int oqs_group = 0; + int pqc_group = 0; int ecc_group = 0; - ecc_key eccpubkey; + KeyShareEntry *ecc_kse = NULL; word32 outlen = 0; word32 privSz = 0; word32 ctSz = 0; word32 ssSz = 0; - if (keyShareEntry->ke == NULL) { - WOLFSSL_MSG("Invalid OQS algorithm specified."); - return BAD_FUNC_ARG; - } - if (ssl->options.side == WOLFSSL_SERVER_END) { /* I am the server, the shared secret has already been generated and - * is in keyShareEntry->ke; copy it to the pre-master secret - * pre-allocated buffer. */ - if (keyShareEntry->keLen > ENCRYPT_LEN) { - WOLFSSL_MSG("shared secret is too long."); - return LENGTH_ERROR; - } - - XMEMCPY(ssl->arrays->preMasterSecret, keyShareEntry->ke, - keyShareEntry->keLen); - ssl->arrays->preMasterSz = keyShareEntry->keLen; - XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_SECRET); - keyShareEntry->ke = NULL; - keyShareEntry->keLen = 0; + * is in ssl->arrays->preMasterSecret, so nothing really to do here. */ return 0; } - /* I am the client, the ciphertext is in keyShareEntry->ke */ - findEccPqc(&ecc_group, &oqs_group, keyShareEntry->group); - - ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId); - if (ret != 0) { - WOLFSSL_MSG("Memory allocation error."); - return MEMORY_E; + if (keyShareEntry->ke == NULL) { + WOLFSSL_MSG("Invalid PQC algorithm specified."); + return BAD_FUNC_ARG; } - ret = kyber_id2type(oqs_group, &type); + /* I am the client, the ciphertext is in keyShareEntry->ke */ + findEccPqc(&ecc_group, &pqc_group, keyShareEntry->group); + + ret = kyber_id2type(pqc_group, &type); if (ret != 0) { - wc_ecc_free(&eccpubkey); - WOLFSSL_MSG("Invalid OQS algorithm specified."); + WOLFSSL_MSG("Invalid PQC algorithm specified."); return BAD_FUNC_ARG; } ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId); if (ret != 0) { - wc_ecc_free(&eccpubkey); WOLFSSL_MSG("Error creating Kyber KEM"); return MEMORY_E; } @@ -8608,35 +8620,62 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = wc_KyberKey_SharedSecretSize(kem, &ssSz); } if (ret == 0) { - sharedSecretLen = ssSz; - switch (ecc_group) { - case WOLFSSL_ECC_SECP256R1: - sharedSecretLen += 32; - outlen = 32; - break; - case WOLFSSL_ECC_SECP384R1: - sharedSecretLen += 48; - outlen = 48; - break; - case WOLFSSL_ECC_SECP521R1: - sharedSecretLen += 66; - outlen = 66; - break; - default: - break; - } + ret = wc_KyberKey_CipherTextSize(kem, &ctSz); } - if (ret == 0) { - sharedSecret = (byte*)XMALLOC(sharedSecretLen, ssl->heap, - DYNAMIC_TYPE_TLSX); - if (sharedSecret == NULL) { - WOLFSSL_MSG("Memory allocation error."); - ret = MEMORY_E; + + if (ret == 0 && ecc_group != 0) { + /* We are performing a hybrid key exchange */ + ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (ecc_kse == NULL) { + WOLFSSL_MSG("ecc_kse memory allocation failure"); + ret = MEMORY_ERROR; } + if (ret == 0) { + XMEMSET(ecc_kse, 0, sizeof(*ecc_kse)); + ecc_kse->group = ecc_group; + ecc_kse->keLen = keyShareEntry->keLen - ctSz; + ecc_kse->key = keyShareEntry->key; + ecc_kse->ke = (byte*)XMALLOC(ecc_kse->keLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ecc_kse->ke == NULL) { + WOLFSSL_MSG("ecc_kse memory allocation failure"); + ret = MEMORY_ERROR; + } + } + if (ret == 0) { + XMEMCPY(ecc_kse->ke, keyShareEntry->ke, ecc_kse->keLen); + + #ifdef HAVE_CURVE25519 + if (ecc_group == WOLFSSL_ECC_X25519) { + ret = TLSX_KeyShare_ProcessX25519(ssl, ecc_kse); + } + else + #endif + #ifdef HAVE_CURVE448 + if (ecc_group == WOLFSSL_ECC_X448) { + ret = TLSX_KeyShare_ProcessX448(ssl, ecc_kse); + } + else + #endif + { + ret = TLSX_KeyShare_ProcessEcc(ssl, ecc_kse); + } + } + if (ret == 0) { + outlen = ssl->arrays->preMasterSz; + ssSz += ssl->arrays->preMasterSz; + keyShareEntry->key = ecc_kse->key; + + if ((ret == 0) && (ssSz > ENCRYPT_LEN)) { + WOLFSSL_MSG("shared secret is too long."); + ret = LENGTH_ERROR; + } + } + /* ecc_kse->ke is freed in the TLSX_KeyShare_Process methods */ + XFREE(ecc_kse, ssl->heap, DYNAMIC_TYPE_TLSX); } - if (ret == 0) { - ret = wc_KyberKey_CipherTextSize(kem, &ctSz); - } + if (ret == 0) { ret = wc_KyberKey_PrivateKeySize(kem, &privSz); } @@ -8644,62 +8683,17 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = wc_KyberKey_DecodePrivateKey(kem, keyShareEntry->privKey, privSz); } if (ret == 0) { - ret = wc_KyberKey_Decapsulate(kem, sharedSecret + outlen, - keyShareEntry->ke + keyShareEntry->keLen - ctSz, ctSz); + ret = wc_KyberKey_Decapsulate(kem, ssl->arrays->preMasterSecret + outlen, + keyShareEntry->ke + keyShareEntry->keLen - ctSz, ctSz); if (ret != 0) { WOLFSSL_MSG("wc_KyberKey decapsulation failure."); ret = BAD_FUNC_ARG; } } - - if (ecc_group != 0) { - if (ret == 0) { - /* Point is validated by import function. */ - ret = wc_ecc_import_x963(keyShareEntry->ke, - keyShareEntry->keLen - ctSz, - &eccpubkey); - if (ret != 0) { - WOLFSSL_MSG("ECC Public key import error."); - } - } - -#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ - !defined(HAVE_SELFTEST) - if (ret == 0) { - ret = wc_ecc_set_rng((ecc_key *)keyShareEntry->key, ssl->rng); - if (ret != 0) { - WOLFSSL_MSG("Failure to set the ECC private key RNG."); - } - } -#endif - - if (ret == 0) { - PRIVATE_KEY_UNLOCK(); - ret = wc_ecc_shared_secret((ecc_key *)keyShareEntry->key, - &eccpubkey, sharedSecret, &outlen); - PRIVATE_KEY_LOCK(); - if (outlen != sharedSecretLen - ssSz) { - WOLFSSL_MSG("ECC shared secret derivation error."); - ret = BAD_FUNC_ARG; - } - } - } - if ((ret == 0) && (sharedSecretLen > ENCRYPT_LEN)) { - WOLFSSL_MSG("shared secret is too long."); - ret = LENGTH_ERROR; - } - if (ret == 0) { - /* Copy the shared secret to the pre-master secret pre-allocated - * buffer. */ - XMEMCPY(ssl->arrays->preMasterSecret, sharedSecret, sharedSecretLen); - ssl->arrays->preMasterSz = (word32) sharedSecretLen; + ssl->arrays->preMasterSz = ssSz; } - XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_SECRET); - - wc_ecc_free(&eccpubkey); wc_KyberKey_Free(kem); return ret; } @@ -9062,41 +9056,32 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, */ int type; KyberKey kem[1]; - byte* sharedSecret = NULL; byte* ciphertext = NULL; int ret = 0; - int oqs_group = 0; + int pqc_group = 0; int ecc_group = 0; KeyShareEntry *ecc_kse = NULL; - ecc_key eccpubkey; word32 outlen = 0; word32 pubSz = 0; word32 ctSz = 0; word32 ssSz = 0; - findEccPqc(&ecc_group, &oqs_group, keyShareEntry->group); - ret = kyber_id2type(oqs_group, &type); + findEccPqc(&ecc_group, &pqc_group, keyShareEntry->group); + ret = kyber_id2type(pqc_group, &type); if (ret != 0) { WOLFSSL_MSG("Invalid Kyber algorithm specified."); return BAD_FUNC_ARG; } - ret = wc_ecc_init_ex(&eccpubkey, ssl->heap, ssl->devId); - if (ret != 0) { - WOLFSSL_MSG("Could not do ECC public key initialization."); - return MEMORY_E; - } - ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId); if (ret != 0) { - wc_ecc_free(&eccpubkey); WOLFSSL_MSG("Error creating Kyber KEM"); return MEMORY_E; } if (ret == 0) { ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap, - DYNAMIC_TYPE_TLSX); + DYNAMIC_TYPE_TLSX); if (ecc_kse == NULL) { WOLFSSL_MSG("ecc_kse memory allocation failure"); ret = MEMORY_ERROR; @@ -9109,8 +9094,22 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, if (ret == 0 && ecc_group != 0) { ecc_kse->group = ecc_group; - ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); - /* No message, TLSX_KeyShare_GenEccKey() will do it. */ + #ifdef HAVE_CURVE25519 + if (ecc_group == WOLFSSL_ECC_X25519) { + ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse); + } + else + #endif + #ifdef HAVE_CURVE448 + if (ecc_group == WOLFSSL_ECC_X448) { + ret = TLSX_KeyShare_GenX448Key(ssl, ecc_kse); + } + else + #endif + { + ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); + } + /* No error message, TLSX_KeyShare_GenKey will do it. */ } if (ret == 0) { @@ -9129,41 +9128,45 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, } if (ret == 0) { - sharedSecret = (byte*)XMALLOC(ecc_kse->keyLen + ssSz, ssl->heap, - DYNAMIC_TYPE_SECRET); ciphertext = (byte*)XMALLOC(ecc_kse->pubKeyLen + ctSz, ssl->heap, DYNAMIC_TYPE_TLSX); - if (sharedSecret == NULL || ciphertext == NULL) { - WOLFSSL_MSG("Ciphertext/shared secret memory allocation failure."); + if (ciphertext == NULL) { + WOLFSSL_MSG("Ciphertext memory allocation failure."); ret = MEMORY_E; } } - if (ecc_group != 0) { + if (ret == 0 && ecc_group != 0) { + ecc_kse->keLen = len - pubSz; + ecc_kse->ke = (byte*)XMALLOC(ecc_kse->keLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ecc_kse->ke == NULL) { + WOLFSSL_MSG("ecc_kse memory allocation failure"); + ret = MEMORY_ERROR; + } if (ret == 0) { - /* Point is validated by import function. */ - ret = wc_ecc_import_x963(data, len - pubSz, &eccpubkey); - if (ret != 0) { - WOLFSSL_MSG("Bad ECC public key."); + XMEMCPY(ecc_kse->ke, data, ecc_kse->keLen); + + #ifdef HAVE_CURVE25519 + if (ecc_group == WOLFSSL_ECC_X25519) { + ret = TLSX_KeyShare_ProcessX25519(ssl, ecc_kse); + } + else + #endif + #ifdef HAVE_CURVE448 + if (ecc_group == WOLFSSL_ECC_X448) { + ret = TLSX_KeyShare_ProcessX448(ssl, ecc_kse); + } + else + #endif + { + ret = TLSX_KeyShare_ProcessEcc(ssl, ecc_kse); } } - -#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ - !defined(HAVE_SELFTEST) if (ret == 0) { - ret = wc_ecc_set_rng((ecc_key *)ecc_kse->key, ssl->rng); - } -#endif + outlen = ssl->arrays->preMasterSz; - if (ret == 0) { - outlen = ecc_kse->keyLen; - PRIVATE_KEY_UNLOCK(); - ret = wc_ecc_shared_secret((ecc_key *)ecc_kse->key, &eccpubkey, - sharedSecret, - &outlen); - PRIVATE_KEY_LOCK(); if (outlen != ecc_kse->keyLen) { WOLFSSL_MSG("Data length mismatch."); ret = BAD_FUNC_ARG; @@ -9171,13 +9174,18 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, } } + if (ret == 0 && outlen + ssSz > ENCRYPT_LEN) { + WOLFSSL_MSG("shared secret is too long."); + ret = LENGTH_ERROR; + } + if (ret == 0) { ret = wc_KyberKey_DecodePublicKey(kem, data + ecc_kse->pubKeyLen, pubSz); } if (ret == 0) { ret = wc_KyberKey_Encapsulate(kem, ciphertext + ecc_kse->pubKeyLen, - sharedSecret + outlen, ssl->rng); + ssl->arrays->preMasterSecret + outlen, ssl->rng); if (ret != 0) { WOLFSSL_MSG("wc_KyberKey encapsulation failure."); } @@ -9186,9 +9194,9 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, if (ret == 0) { XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - keyShareEntry->ke = sharedSecret; - keyShareEntry->keLen = outlen + ssSz; - sharedSecret = NULL; + ssl->arrays->preMasterSz = outlen + ssSz; + keyShareEntry->ke = NULL; + keyShareEntry->keLen = 0; if (ecc_kse->pubKeyLen > 0) XMEMCPY(ciphertext, ecc_kse->pubKey, ecc_kse->pubKeyLen); @@ -9202,9 +9210,7 @@ static int server_generate_pqc_ciphertext(WOLFSSL* ssl, } TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap); - XFREE(sharedSecret, ssl->heap, DYNAMIC_TYPE_SECRET); XFREE(ciphertext, ssl->heap, DYNAMIC_TYPE_TLSX); - wc_ecc_free(&eccpubkey); wc_KyberKey_Free(kem); return ret; } @@ -9427,14 +9433,25 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) #ifdef WOLFSSL_KYBER512 case WOLFSSL_KYBER_LEVEL1: case WOLFSSL_P256_KYBER_LEVEL1: + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + case WOLFSSL_X25519_KYBER_LEVEL1: + #endif #endif #ifdef WOLFSSL_KYBER768 case WOLFSSL_KYBER_LEVEL3: case WOLFSSL_P384_KYBER_LEVEL3: + case WOLFSSL_P256_KYBER_LEVEL3: + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + case WOLFSSL_X25519_KYBER_LEVEL3: + #endif + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + case WOLFSSL_X448_KYBER_LEVEL3: + #endif #endif #ifdef WOLFSSL_KYBER1024 case WOLFSSL_KYBER_LEVEL5: case WOLFSSL_P521_KYBER_LEVEL5: + case WOLFSSL_P384_KYBER_LEVEL5: #endif break; #elif defined(HAVE_LIBOQS) @@ -9443,7 +9460,12 @@ static int TLSX_KeyShare_IsSupported(int namedGroup) case WOLFSSL_KYBER_LEVEL5: case WOLFSSL_P256_KYBER_LEVEL1: case WOLFSSL_P384_KYBER_LEVEL3: + case WOLFSSL_P256_KYBER_LEVEL3: case WOLFSSL_P521_KYBER_LEVEL5: + case WOLFSSL_P384_KYBER_LEVEL5: + case WOLFSSL_X25519_KYBER_LEVEL1: + case WOLFSSL_X448_KYBER_LEVEL3: + case WOLFSSL_X25519_KYBER_LEVEL3: { int ret; int id; @@ -9509,14 +9531,25 @@ static const word16 preferredGroup[] = { #ifdef WOLFSSL_KYBER512 WOLFSSL_KYBER_LEVEL1, WOLFSSL_P256_KYBER_LEVEL1, + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_X25519_KYBER_LEVEL1, + #endif #endif #ifdef WOLFSSL_KYBER768 WOLFSSL_KYBER_LEVEL3, WOLFSSL_P384_KYBER_LEVEL3, + WOLFSSL_P256_KYBER_LEVEL3, + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_X25519_KYBER_LEVEL3, + #endif + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + WOLFSSL_X448_KYBER_LEVEL3, + #endif #endif #ifdef WOLFSSL_KYBER1024 WOLFSSL_KYBER_LEVEL5, WOLFSSL_P521_KYBER_LEVEL5, + WOLFSSL_P384_KYBER_LEVEL5, #endif #elif defined(HAVE_LIBOQS) /* These require a runtime call to TLSX_KeyShare_IsSupported to use */ @@ -9525,7 +9558,16 @@ static const word16 preferredGroup[] = { WOLFSSL_KYBER_LEVEL5, WOLFSSL_P256_KYBER_LEVEL1, WOLFSSL_P384_KYBER_LEVEL3, + WOLFSSL_P256_KYBER_LEVEL3, WOLFSSL_P521_KYBER_LEVEL5, + WOLFSSL_P384_KYBER_LEVEL5, + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_X25519_KYBER_LEVEL1, + WOLFSSL_X25519_KYBER_LEVEL3, + #endif + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + WOLFSSL_X448_KYBER_LEVEL3, + #endif #endif WOLFSSL_NAMED_GROUP_INVALID }; @@ -9809,7 +9851,8 @@ int TLSX_KeyShare_Choose(const WOLFSSL *ssl, TLSX* extensions, /* Use server's preference order. */ for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { - if (clientKSE->ke == NULL) + if ((clientKSE->ke == NULL) && + (!WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group))) continue; #ifdef WOLFSSL_SM2 @@ -9888,7 +9931,7 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) return BAD_FUNC_ARG; } - /* Generate a new key pair except in the case of OQS KEM because we + /* Generate a new key pair except in the case of PQC KEM because we * are going to encapsulate and that does not require us to generate a * key pair. */ @@ -13132,6 +13175,11 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1, ssl->heap); + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL1, + ssl->heap); + #endif #endif #ifdef WOLFSSL_KYBER768 if (ret == WOLFSSL_SUCCESS) @@ -13140,6 +13188,19 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL3, + ssl->heap); + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL3, + ssl->heap); + #endif + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448_KYBER_LEVEL3, + ssl->heap); + #endif #endif #ifdef WOLFSSL_KYBER1024 if (ret == WOLFSSL_SUCCESS) @@ -13148,6 +13209,9 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL5, + ssl->heap); #endif #elif defined(HAVE_LIBOQS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); @@ -13163,9 +13227,28 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL3, + ssl->heap); if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL5, + ssl->heap); + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL1, + ssl->heap); + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL3, + ssl->heap); + #endif + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + if (ret == WOLFSSL_SUCCESS) + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448_KYBER_LEVEL3, + ssl->heap); + #endif #endif /* HAVE_LIBOQS */ #endif /* WOLFSSL_HAVE_KYBER */ diff --git a/tests/include.am b/tests/include.am index 5ed4fe40dc..1bb9fa38ab 100644 --- a/tests/include.am +++ b/tests/include.am @@ -27,11 +27,11 @@ EXTRA_DIST += tests/unit.h \ tests/test-tls13-ecc.conf \ tests/test-tls13-psk.conf \ tests/test-tls13-pq.conf \ - tests/test-tls13-pq-2.conf \ + tests/test-tls13-pq-hybrid.conf \ tests/test-dtls13-pq.conf \ tests/test-dtls13-pq-frag.conf \ - tests/test-dtls13-pq-2.conf \ - tests/test-dtls13-pq-2-frag.conf \ + tests/test-dtls13-pq-hybrid.conf \ + tests/test-dtls13-pq-hybrid-frag.conf \ tests/test-psk.conf \ tests/test-psk-no-id.conf \ tests/test-psk-no-id-sha2.conf \ diff --git a/tests/suites.c b/tests/suites.c index 7328789f46..8d65cfaf34 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -969,9 +969,8 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } - #ifdef HAVE_LIBOQS - /* add TLSv13 pq tests */ - XSTRLCPY(argv0[1], "tests/test-tls13-pq-2.conf", sizeof(argv0[1])); + /* add TLSv13 pq hybrid tests */ + XSTRLCPY(argv0[1], "tests/test-tls13-pq-hybrid.conf", sizeof(argv0[1])); printf("starting TLSv13 post-quantum groups tests\n"); test_harness(&args); if (args.return_code != 0) { @@ -980,29 +979,6 @@ int SuiteTest(int argc, char** argv) goto exit; } #endif - #endif - #ifdef HAVE_PQC - /* add TLSv13 pq tests */ - XSTRLCPY(argv0[1], "tests/test-tls13-pq.conf", sizeof(argv0[1])); - printf("starting TLSv13 post-quantum groups tests\n"); - test_harness(&args); - if (args.return_code != 0) { - printf("error from script %d\n", args.return_code); - args.return_code = EXIT_FAILURE; - goto exit; - } - #ifdef HAVE_LIBOQS - /* add TLSv13 pq tests */ - XSTRLCPY(argv0[1], "tests/test-tls13-pq-2.conf", sizeof(argv0[1])); - printf("starting TLSv13 post-quantum groups tests\n"); - test_harness(&args); - if (args.return_code != 0) { - printf("error from script %d\n", args.return_code); - args.return_code = EXIT_FAILURE; - goto exit; - } - #endif - #endif #if defined(HAVE_PQC) && defined(WOLFSSL_DTLS13) /* add DTLSv13 pq tests */ XSTRLCPY(argv0[1], "tests/test-dtls13-pq.conf", sizeof(argv0[1])); @@ -1013,30 +989,27 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } - #ifdef WOLFSSL_DTLS_CH_FRAG - /* add DTLSv13 pq frag tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq-frag.conf", sizeof(argv0[1])); - printf("starting DTLSv13 post-quantum groups tests with fragmentation\n"); + /* add DTLSv13 pq hybrid tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid.conf", sizeof(argv0[1])); + printf("starting DTLSv13 post-quantum 2 groups tests\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); args.return_code = EXIT_FAILURE; goto exit; } - #endif - #ifdef HAVE_LIBOQS - /* add DTLSv13 pq 2 tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq-2.conf", sizeof(argv0[1])); - printf("starting DTLSv13 post-quantum 2 groups tests\n"); + #ifdef WOLFSSL_DTLS_CH_FRAG + /* add DTLSv13 pq frag tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-frag.conf", sizeof(argv0[1])); + printf("starting DTLSv13 post-quantum groups tests with fragmentation\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); args.return_code = EXIT_FAILURE; goto exit; } - #ifdef WOLFSSL_DTLS_CH_FRAG - /* add DTLSv13 pq 2 frag tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq-2-frag.conf", sizeof(argv0[1])); + /* add DTLSv13 pq hybrid frag tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid-frag.conf", sizeof(argv0[1])); printf("starting DTLSv13 post-quantum 2 groups tests with fragmentation\n"); test_harness(&args); if (args.return_code != 0) { @@ -1046,7 +1019,6 @@ int SuiteTest(int argc, char** argv) } #endif #endif - #endif #endif #if defined(WC_RSA_PSS) && (!defined(HAVE_FIPS) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \ diff --git a/tests/test-dtls13-pq-2-frag.conf b/tests/test-dtls13-pq-2-frag.conf deleted file mode 100644 index 6ea8317db0..0000000000 --- a/tests/test-dtls13-pq-2-frag.conf +++ /dev/null @@ -1,23 +0,0 @@ -# server DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# client DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# server DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# client DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 diff --git a/tests/test-dtls13-pq-2.conf b/tests/test-dtls13-pq-2.conf deleted file mode 100644 index 6a4bfac084..0000000000 --- a/tests/test-dtls13-pq-2.conf +++ /dev/null @@ -1,13 +0,0 @@ -# server DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# client DTLSv1.3 with post-quantum group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# P384_KYBER_LEVEL3 and P521_KYBER_LEVEL5 would fragment the ClientHello. diff --git a/tests/test-dtls13-pq-frag.conf b/tests/test-dtls13-pq-frag.conf index 01aaf477fe..3696286078 100644 --- a/tests/test-dtls13-pq-frag.conf +++ b/tests/test-dtls13-pq-frag.conf @@ -21,4 +21,3 @@ -v 4 -l TLS13-AES256-GCM-SHA384 --pqc KYBER_LEVEL5 - diff --git a/tests/test-dtls13-pq-hybrid-frag.conf b/tests/test-dtls13-pq-hybrid-frag.conf new file mode 100644 index 0000000000..88ee706764 --- /dev/null +++ b/tests/test-dtls13-pq-hybrid-frag.conf @@ -0,0 +1,71 @@ +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL5 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL5 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 diff --git a/tests/test-dtls13-pq-hybrid.conf b/tests/test-dtls13-pq-hybrid.conf new file mode 100644 index 0000000000..64332b5dd0 --- /dev/null +++ b/tests/test-dtls13-pq-hybrid.conf @@ -0,0 +1,25 @@ +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# Hybrids with KYBER_LEVEL3 and KYBER_LEVEL5 would fragment the ClientHello. diff --git a/tests/test-tls13-pq-2.conf b/tests/test-tls13-pq-2.conf deleted file mode 100644 index ff09d72a71..0000000000 --- a/tests/test-tls13-pq-2.conf +++ /dev/null @@ -1,29 +0,0 @@ -# server TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# client TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# server TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# client TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# server TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# client TLSv1.3 with post-quantum group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 diff --git a/tests/test-tls13-pq-hybrid.conf b/tests/test-tls13-pq-hybrid.conf new file mode 100644 index 0000000000..3d98f94c45 --- /dev/null +++ b/tests/test-tls13-pq-hybrid.conf @@ -0,0 +1,79 @@ +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL5 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL5 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 37cf731ae2..ffe523a92b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1861,9 +1861,8 @@ enum Misc { #define WOLFSSL_NAMED_GROUP_IS_FFHDE(group) \ (MIN_FFHDE_GROUP <= (group) && (group) <= MAX_FFHDE_GROUP) #ifdef WOLFSSL_HAVE_KYBER -#define WOLFSSL_NAMED_GROUP_IS_PQC(group) \ - ((WOLFSSL_PQC_SIMPLE_MIN <= (group) && (group) <= WOLFSSL_PQC_SIMPLE_MAX) || \ - (WOLFSSL_PQC_HYBRID_MIN <= (group) && (group) <= WOLFSSL_PQC_HYBRID_MAX)) +WOLFSSL_LOCAL int NamedGroupIsPqc(int group); +#define WOLFSSL_NAMED_GROUP_IS_PQC(group) NamedGroupIsPqc(group) #else #define WOLFSSL_NAMED_GROUP_IS_PQC(group) ((void)(group), 0) #endif /* WOLFSSL_HAVE_KYBER */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 90f711589e..59850e58ff 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -4108,51 +4108,54 @@ enum { WOLFSSL_FFDHE_8192 = 260, #ifdef HAVE_PQC - /* These group numbers were taken from OQS's openssl provider, see: + +#ifdef WOLFSSL_KYBER_ORIGINAL + /* Old code points to keep compatibility with Kyber Round 3. + * To be removed in the future. + * Taken from OQS's openssl provider, see: * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/ - * oqs-kem-info.md. - * - * The levels in the group name refer to the claimed NIST level of each - * parameter set. The associated parameter set name is listed as a comment - * beside the group number. Please see the NIST PQC Competition's submitted - * papers for more details. - * - * LEVEL1 means that an attack on that parameter set would require the same - * or more resources as a key search on AES 128. LEVEL3 would require the - * same or more resources as a key search on AES 192. LEVEL5 would require - * the same or more resources as a key search on AES 256. None of the - * algorithms have LEVEL2 and LEVEL4 because none of these submissions - * included them. */ - -#ifndef WOLFSSL_ML_KEM - WOLFSSL_PQC_MIN = 570, - WOLFSSL_PQC_SIMPLE_MIN = 570, + * oqs-kem-info.md + */ WOLFSSL_KYBER_LEVEL1 = 570, /* KYBER_512 */ WOLFSSL_KYBER_LEVEL3 = 572, /* KYBER_768 */ WOLFSSL_KYBER_LEVEL5 = 573, /* KYBER_1024 */ - WOLFSSL_PQC_SIMPLE_MAX = 573, - WOLFSSL_PQC_HYBRID_MIN = 12090, WOLFSSL_P256_KYBER_LEVEL1 = 12090, WOLFSSL_P384_KYBER_LEVEL3 = 12092, WOLFSSL_P521_KYBER_LEVEL5 = 12093, - WOLFSSL_PQC_HYBRID_MAX = 12093, - WOLFSSL_PQC_MAX = 12093, + WOLFSSL_P384_KYBER_LEVEL5 = 12094, /* Not defined in OQS! */ + WOLFSSL_X25519_KYBER_LEVEL1 = 12089, + WOLFSSL_X448_KYBER_LEVEL3 = 12176, + WOLFSSL_X25519_KYBER_LEVEL3 = 25497, + WOLFSSL_P256_KYBER_LEVEL3 = 25498, + #else - WOLFSSL_PQC_MIN = 583, - WOLFSSL_PQC_SIMPLE_MIN = 583, - WOLFSSL_KYBER_LEVEL1 = 583, /* ML-KEM 512 */ - WOLFSSL_KYBER_LEVEL3 = 584, /* ML-KEM 768 */ - WOLFSSL_KYBER_LEVEL5 = 585, /* ML-KEM 1024 */ - WOLFSSL_PQC_SIMPLE_MAX = 585, - - WOLFSSL_PQC_HYBRID_MIN = 12103, - WOLFSSL_P256_KYBER_LEVEL1 = 12103, - WOLFSSL_P384_KYBER_LEVEL3 = 12104, - WOLFSSL_P521_KYBER_LEVEL5 = 12105, - WOLFSSL_PQC_HYBRID_MAX = 12105, - WOLFSSL_PQC_MAX = 12105, -#endif /* WOLFSSL_ML_KEM */ + /* Taken from OQS's openssl provider, see: + * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/ + * oqs-kem-info.md + */ + WOLFSSL_KYBER_LEVEL1 = 586, /* ML-KEM 512 */ + WOLFSSL_KYBER_LEVEL3 = 1896, /* ML-KEM 768 */ + WOLFSSL_KYBER_LEVEL5 = 4132, /* ML-KEM 1024 */ + + /* Taken from draft-kwiatkowski-tls-ecdhe-mlkem. see: + * https://github.com/post-quantum-cryptography/ + * draft-kwiatkowski-tls-ecdhe-mlkem/ + */ + WOLFSSL_P256_KYBER_LEVEL3 = 4587, + WOLFSSL_X25519_KYBER_LEVEL3 = 4588, + WOLFSSL_P384_KYBER_LEVEL5 = 4589, + + /* Taken from OQS's openssl provider, see: + * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/ + * oqs-kem-info.md + */ + WOLFSSL_P256_KYBER_LEVEL1 = 12107, + WOLFSSL_P384_KYBER_LEVEL3 = 12108, + WOLFSSL_P521_KYBER_LEVEL5 = 12109, + WOLFSSL_X25519_KYBER_LEVEL1 = 12214, + WOLFSSL_X448_KYBER_LEVEL3 = 12215, +#endif /* WOLFSSL_KYBER_ORIGINAL */ #endif /* HAVE_PQC */ };