diff --git a/src/tls.c b/src/tls.c index 5dde7dfa3..f647be84f 100644 --- a/src/tls.c +++ b/src/tls.c @@ -7306,12 +7306,16 @@ static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) if (ssl->options.side == WOLFSSL_SERVER_END) { /* I am the server, the shared secret has already been generated and - * is in keyShareEntry->ke; transfer ownership of the buffer. */ - if (ssl->arrays->preMasterSecret != NULL) - XFREE(ssl->arrays->preMasterSecret, ssl->heap, - DYNAMIC_TYPE_SECRET); - ssl->arrays->preMasterSecret = keyShareEntry->ke; + * 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.\n"); + return LENGTH_ERROR; + } + + XMEMCPY(ssl->arrays->preMasterSecret, keyShareEntry->ke, keyShareEntry->keLen); ssl->arrays->preMasterSz = keyShareEntry->keLen; + XFREE(keyShareEntry->ke, sl->heap, DYNAMIC_TYPE_TLSX) keyShareEntry->ke = NULL; keyShareEntry->keLen = 0; return 0; @@ -7404,10 +7408,16 @@ static int TLSX_KeyShare_ProcessOqs(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) } } + if (sharedSecretLen > ENCRYPT_LEN) { + WOLFSSL_MSG("shared secret is too long.\n"); + ret = LENGTH_ERROR; + } + if (ret == 0) { - ssl->arrays->preMasterSecret = sharedSecret; + /* Copy the shared secret to the pre-master secret pre-allocated + * buffer. */ + XMEMCPY(ssl->arrays->preMasterSecret, sharedSecret, sharedSecretLen); ssl->arrays->preMasterSz = (word32) sharedSecretLen; - sharedSecret = NULL; } if (sharedSecret != NULL) { @@ -7493,16 +7503,29 @@ static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, const byte* input, if (keLen > length - offset) return BUFFER_ERROR; - /* Store a copy in the key share object. */ - ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (ke == NULL) - return MEMORY_E; - XMEMCPY(ke, &input[offset], keLen); +#ifdef HAVE_LIBOQS + if (group >= WOLFSSL_OQS_MIN && + group <= WOLFSSL_OQS_MAX && + ssl->options.side == WOLFSSL_SERVER_END) { + /* For KEMs, the public key is not stored. Casting away const because + * we know for KEMs, it will be read-only.*/ + ke = (byte *) &input[offset]; + } else +#endif + { + /* Store a copy in the key share object. */ + ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ke == NULL) + return MEMORY_E; + XMEMCPY(ke, &input[offset], keLen); + } /* Populate a key share object in the extension. */ ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse); if (ret != 0) { - XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ke != &input[offset]) { + XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } return ret; } @@ -7685,8 +7708,11 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, return ret; } - /* Try to use the server's group. */ - ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); +#ifdef HAVE_LIBOQS + /* For oqs groups, do this in TLSX_PopulateExtensions(). */ + if (group < WOLFSSL_OQS_MIN || group > WOLFSSL_OQS_MAX) +#endif + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); } else { /* Not a message type that is allowed to have this extension. */ @@ -7923,25 +7949,24 @@ int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, return ret; } - if (data != NULL) { + #ifdef HAVE_LIBOQS - if (group >= WOLFSSL_OQS_MIN && - group <= WOLFSSL_OQS_MAX && - ssl->options.side == WOLFSSL_SERVER_END) { - ret = server_generate_oqs_ciphertext(ssl, keyShareEntry, data, - len); - if (ret != 0) - return ret; - } - else + if (group >= WOLFSSL_OQS_MIN && + group <= WOLFSSL_OQS_MAX && + ssl->options.side == WOLFSSL_SERVER_END) { + ret = server_generate_oqs_ciphertext(ssl, keyShareEntry, data, + len); + if (ret != 0) + return ret; + } + else #endif - { - if (keyShareEntry->ke != NULL) { - XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - } - keyShareEntry->ke = data; - keyShareEntry->keLen = len; + if (data != NULL) { + if (keyShareEntry->ke != NULL) { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); } + keyShareEntry->ke = data; + keyShareEntry->keLen = len; } else { /* Generate a key pair. */ @@ -10316,7 +10341,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) namedGroup = kse->group; } if (namedGroup > 0) { - ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); +#ifdef HAVE_LIBOQS + /* For KEMs, the key share has already been generated. */ + if (namedGroup < WOLFSSL_OQS_MIN || namedGroup > WOLFSSL_OQS_MAX) +#endif + ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); if (ret != 0) return ret; } diff --git a/src/tls13.c b/src/tls13.c index 3963cb18a..71e725a38 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8690,14 +8690,20 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) #ifdef HAVE_LIBOQS if (group >= WOLFSSL_OQS_MIN && - group <= WOLFSSL_OQS_MAX && - ssl->options.side == WOLFSSL_SERVER_END) { - /* If I am the server of a KEM connection, do not do keygen because I'm - * going to encapsulate with the client's public key. Note that I might - * be the client and ssl->option.side has not been properly set yet. In - * that case the KeyGen operation will be deferred to connection time. - */ - return WOLFSSL_SUCCESS; + group <= WOLFSSL_OQS_MAX) { + + if (ssl->ctx != NULL && ssl->ctx->method != NULL && + ssl->ctx->method->version.minor != TLSv1_3_MINOR) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* If I am the server of a KEM connection, do not do keygen because I'm + * going to encapsulate with the client's public key. Note that I might + * be the client and ssl->option.side has not been properly set yet. In + * that case the KeyGen operation will be deferred to connection time. */ + return WOLFSSL_SUCCESS; + } } #endif diff --git a/tests/api.c b/tests/api.c index a77bb55f6..3f14e74ba 100644 --- a/tests/api.c +++ b/tests/api.c @@ -44755,7 +44755,13 @@ static int test_tls13_apis(void) int outSz; #endif #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - int groups[2] = { WOLFSSL_ECC_SECP256R1, WOLFSSL_ECC_SECP256R1 }; + int groups[2] = { WOLFSSL_ECC_SECP256R1, +#ifdef HAVE_LIBOQS + WOLFSSL_SABER_LEVEL3 +#else + WOLFSSL_ECC_SECP256R1 +#endif + }; int bad_groups[2] = { 0xDEAD, 0xBEEF }; int numGroups = 2; #endif @@ -44770,6 +44776,12 @@ static int test_tls13_apis(void) #endif #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 "P-256" +#ifdef HAVE_LIBOQS + ":P256_SABER_LEVEL1" +#endif +#endif +#ifdef HAVE_LIBOQS + ":KYBER_LEVEL1" #endif ""; #endif /* !defined(NO_ECC_SECP) */ @@ -44872,6 +44884,22 @@ static int test_tls13_apis(void) AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_ECC_SECP256R1), NOT_COMPILED_IN); #endif +#endif + +#if defined(HAVE_LIBOQS) + AssertIntEQ(wolfSSL_UseKeyShare(NULL, WOLFSSL_KYBER_LEVEL3), BAD_FUNC_ARG); +#ifndef NO_WOLFSSL_SERVER + AssertIntEQ(wolfSSL_UseKeyShare(serverSsl, WOLFSSL_KYBER_LEVEL3), + WOLFSSL_SUCCESS); +#endif +#ifndef NO_WOLFSSL_CLIENT +#ifndef WOLFSSL_NO_TLS12 + AssertIntEQ(wolfSSL_UseKeyShare(clientTls12Ssl, WOLFSSL_KYBER_LEVEL3), + BAD_FUNC_ARG); +#endif + AssertIntEQ(wolfSSL_UseKeyShare(clientSsl, WOLFSSL_KYBER_LEVEL3), + WOLFSSL_SUCCESS); +#endif #endif AssertIntEQ(wolfSSL_NoKeyShares(NULL), BAD_FUNC_ARG); diff --git a/tests/include.am b/tests/include.am index 4e704c896..6c5331600 100644 --- a/tests/include.am +++ b/tests/include.am @@ -17,13 +17,14 @@ tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) $(WOLFSENTRY_INCLUD tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) $(WOLFSENTRY_LIB) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif -EXTRA_DIST += tests/unit.h -EXTRA_DIST += tests/test.conf \ +EXTRA_DIST += tests/unit.h \ + tests/test.conf \ tests/test-sha2.conf \ tests/test-tls13.conf \ tests/test-tls13-down.conf \ tests/test-tls13-ecc.conf \ tests/test-tls13-psk.conf \ + tests/test-tls13-pq.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 453a4ec0e..7c4afbb0c 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -867,7 +867,7 @@ int SuiteTest(int argc, char** argv) } #endif #ifndef WOLFSSL_NO_TLS12 - /* add TLSv13 downgrade tets */ + /* add TLSv13 downgrade tests */ strcpy(argv0[1], "tests/test-tls13-down.conf"); printf("starting TLSv13 Downgrade extra tests\n"); test_harness(&args); @@ -877,6 +877,17 @@ int SuiteTest(int argc, char** argv) goto exit; } #endif + #ifdef HAVE_LIBOQS + /* add TLSv13 pq tests */ + strcpy(argv0[1], "tests/test-tls13-pq.conf"); + 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_CURVE25519) && defined(HAVE_ED25519) && \ defined(HAVE_ED25519_SIGN) && defined(HAVE_ED25519_VERIFY) && \ diff --git a/tests/test-tls13-pq.conf b/tests/test-tls13-pq.conf new file mode 100644 index 000000000..0d2baecc1 --- /dev/null +++ b/tests/test-tls13-pq.conf @@ -0,0 +1,260 @@ +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs KYBER_90S_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HPS_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HRSS_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs NTRU_HRSS_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs SABER_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_NTRU_HPS_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_NTRU_HPS_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_NTRU_HPS_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_NTRU_HPS_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_NTRU_HPS_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_NTRU_HPS_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_NTRU_HRSS_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_NTRU_HRSS_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_SABER_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_SABER_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_SABER_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_SABER_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_SABER_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_SABER_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_KYBER_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_KYBER_LEVEL5 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_KYBER_90S_LEVEL1 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P256_KYBER_90S_LEVEL1 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_KYBER_90S_LEVEL3 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P384_KYBER_90S_LEVEL3 + +# server TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_KYBER_90S_LEVEL5 + +# client TLSv1.3 with post-quantum group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--oqs P521_KYBER_90S_LEVEL5 + diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 858c5c368..720ffe148 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -4579,10 +4579,15 @@ typedef struct { int nid; } WOLF_EC_NIST_NAME; extern const WOLF_EC_NIST_NAME kNistCurves[]; -/* This is the longest and shortest curve name in the kNistCurves list */ +/* This is the longest and shortest curve name in the kNistCurves list. Note we + * also have quantum-safe group names as well. */ #define kNistCurves_MIN_NAME_LEN 5 +#ifdef HAVE_LIBOQS +#define kNistCurves_MAX_NAME_LEN 32 +#else #define kNistCurves_MAX_NAME_LEN 7 #endif +#endif /* internal functions */ WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*);