From df8b48cd0fc013b5584c2df9ef749c2ab1b051d8 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Sat, 11 Jul 2015 12:52:22 -0600 Subject: [PATCH] NTRU suites from earlier code --- examples/echoserver/echoserver.c | 17 ++- examples/server/server.c | 16 +- src/internal.c | 242 +++++++++++++++++++++++++++---- src/keys.c | 67 +++++++++ src/ssl.c | 16 +- src/tls.c | 25 +++- tests/test-qsh.conf | 117 +++++++++++++++ tests/test.conf | 118 +++++++++++++++ wolfssl/internal.h | 22 +++ 9 files changed, 605 insertions(+), 35 deletions(-) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 2c4af4ee0..db499ae08 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -151,7 +151,18 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #ifndef NO_FILESYSTEM if (doPSK == 0) { - #if defined(HAVE_ECC) && !defined(CYASSL_SNIFFER) + #ifdef HAVE_NTRU + /* ntru */ + if (CyaSSL_CTX_use_certificate_file(ctx, ntruCert, SSL_FILETYPE_PEM) + != SSL_SUCCESS) + err_sys("can't load ntru cert file, " + "Please run from wolfSSL home dir"); + + if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ntruKey) + != SSL_SUCCESS) + err_sys("can't load ntru key file, " + "Please run from wolfSSL home dir"); + #elif defined(HAVE_ECC) && !defined(CYASSL_SNIFFER) /* ecc */ if (CyaSSL_CTX_use_certificate_file(ctx, eccCert, SSL_FILETYPE_PEM) != SSL_SUCCESS) @@ -214,8 +225,8 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) int clientfd; int firstRead = 1; int gotFirstG = 0; - -#ifndef CYASSL_DTLS + +#ifndef CYASSL_DTLS SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, diff --git a/examples/server/server.c b/examples/server/server.c index d9be47eab..118a7e98e 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -181,6 +181,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int useAnon = 0; int doDTLS = 0; int needDH = 0; + int useNtruKey = 0; int nonBlocking = 0; int trackMemory = 0; int fewerPackets = 0; @@ -221,6 +222,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)ourCert; (void)ourDhParam; (void)verifyCert; + (void)useNtruKey; (void)doCliCertCheck; (void)minDhKeyBits; @@ -253,6 +255,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case 'n' : + useNtruKey = 1; + break; + case 'u' : doDTLS = 1; break; @@ -474,8 +480,16 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); #endif +#ifdef HAVE_NTRU + if (useNtruKey) { + if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) + != SSL_SUCCESS) + err_sys("can't load ntru key file, " + "Please run from wolfSSL home dir"); + } +#endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - if (!usePsk && !useAnon) { + if (!useNtruKey && !usePsk && !useAnon) { if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server private key file, check file and run " diff --git a/src/internal.c b/src/internal.c index 5ac91ff01..b63b1fe2a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -181,7 +181,7 @@ static int QSH_FreeAll(WOLFSSL* ssl) QSHScheme* preList = NULL; /* free elements in struct */ - while(key) { + while (key) { preKey = key; if (key->pri.buffer) XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); @@ -192,11 +192,12 @@ static int QSH_FreeAll(WOLFSSL* ssl) /* free struct */ XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); } + key = NULL; /* free all of peers QSH keys */ key = ssl->peerQSHKey; - while(key) { + while (key) { preKey = key; if (key->pri.buffer) XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); @@ -207,6 +208,7 @@ static int QSH_FreeAll(WOLFSSL* ssl) /* free struct */ XFREE(preKey, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); } + key = NULL; /* free secret information */ if (secret) { @@ -234,6 +236,7 @@ static int QSH_FreeAll(WOLFSSL* ssl) } } XFREE(secret, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + secret = NULL; return 0; } @@ -773,12 +776,40 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_QSH - if (tls && haveNTRU) { + if (tls) { suites->suites[idx++] = QSH_BYTE; suites->suites[idx++] = TLS_QSH; } #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = 0; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveECDSAsig) { suites->suites[idx++] = ECC_BYTE; @@ -1655,11 +1686,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif #ifdef HAVE_TLS_EXTENSIONS -#ifdef HAVE_QSH - #ifdef HAVE_NTRU - ssl->options.haveNTRU = 1; - #endif -#endif #ifdef HAVE_MAX_FRAGMENT ssl->max_fragment = MAX_RECORD_SIZE; #endif @@ -3282,17 +3308,6 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) } } - if (first == QSH_BYTE) { - - switch (second) { - - case TLS_QSH : - if (requirement == REQUIRES_NTRU) - return 1; - break; - } - } - /* ECC extensions */ if (first == ECC_BYTE) { @@ -3526,6 +3541,11 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; @@ -3536,11 +3556,21 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA : if (requirement == REQUIRES_RSA) return 1; break; + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256 : if (requirement == REQUIRES_RSA) return 1; @@ -3552,6 +3582,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 1; break; + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; #endif case TLS_PSK_WITH_AES_128_GCM_SHA256 : @@ -4332,6 +4366,21 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, } break; #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, dCert->publicKey, + dCert->pubKeySize); + ssl->peerNtruKeyLen = (word16)dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + } + break; + #endif /* HAVE_NTRU */ #ifdef HAVE_ECC case ECDSAk: { @@ -8238,6 +8287,22 @@ static const char* const cipher_names[] = "RABBIT-SHA", #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + "NTRU-RC4-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + "NTRU-DES-CBC3-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + "NTRU-AES128-SHA", +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + "NTRU-AES256-SHA", +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 "AES128-CCM-8", #endif @@ -8620,6 +8685,22 @@ static int cipher_name_idx[] = TLS_RSA_WITH_RABBIT_SHA, #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + TLS_NTRU_RSA_WITH_RC4_128_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + TLS_NTRU_RSA_WITH_AES_128_CBC_SHA, +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + TLS_NTRU_RSA_WITH_AES_256_CBC_SHA, +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 TLS_RSA_WITH_AES_128_CCM_8, #endif @@ -11145,6 +11226,57 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) } break; #endif /* !NO_DH && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word32 rc; + word16 cipherLen = MAX_ENCRYPT_SZ; + DRBG_HANDLE drbg; + + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->peerNtruKeyPresent == 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NO_PEER_KEY; + } + + rc = ntru_crypto_external_drbg_instantiate(GetEntropy, &drbg); + if (rc != DRBG_OK) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NTRU_DRBG_ERROR; + } + + rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, + ssl->peerNtruKey, + ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, + &cipherLen, encSecret); + ntru_crypto_drbg_uninstantiate(drbg); + if (rc != NTRU_OK) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return NTRU_ENCRYPT_ERROR; + } + + encSz = cipherLen; + ret = 0; + } + break; + #endif /* HAVE_NTRU */ #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { @@ -11964,7 +12096,7 @@ int DoSessionTicket(WOLFSSL* ssl, #ifdef HAVE_QSH word32 qshSz = 0; - if (ssl->peerQSHKeyPresent) { + if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) { qshSz = QSH_KeyGetSize(ssl); } #endif @@ -13408,6 +13540,9 @@ int DoSessionTicket(WOLFSSL* ssl, havePSK = ssl->options.havePSK; #endif + if (ssl->options.haveNTRU) + haveRSA = 0; + if (CipherRequires(first, second, REQUIRES_RSA)) { WOLFSSL_MSG("Requires RSA"); if (haveRSA == 0) { @@ -13478,7 +13613,7 @@ int DoSessionTicket(WOLFSSL* ssl, /* need to negotiate a classic suite in addition to TLS_QSH */ if (first == QSH_BYTE && second == TLS_QSH) { if (TLSX_SupportExtensions(ssl)) { - ssl->peerQSHKeyPresent = 1; /* matched TLS_QSH */ + ssl->options.haveQSH = 1; /* matched TLS_QSH */ } else { WOLFSSL_MSG("Version of SSL connection does not support TLS_QSH"); @@ -14627,7 +14762,7 @@ int DoSessionTicket(WOLFSSL* ssl, else { #ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { + if (ssl->options.haveQSH) { /* extension name */ ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; @@ -14700,7 +14835,7 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; #ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { + if (ssl->options.haveQSH) { /* extension name */ ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; @@ -14724,6 +14859,61 @@ int DoSessionTicket(WOLFSSL* ssl, } break; #endif /* NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word16 cipherLen; + word16 plainLen = sizeof(ssl->arrays->preMasterSecret); + + if (!ssl->buffers.key.buffer) + return NO_PRIVATE_KEY; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &cipherLen); + *inOutIdx += OPAQUE16_LEN; + + if (cipherLen > MAX_NTRU_ENCRYPT_SZ) + return NTRU_KEY_ERROR; + + if ((*inOutIdx - begin) + cipherLen > size) + return BUFFER_ERROR; + + if (NTRU_OK != ntru_crypto_ntru_decrypt( + (word16) ssl->buffers.key.length, + ssl->buffers.key.buffer, cipherLen, + input + *inOutIdx, &plainLen, + ssl->arrays->preMasterSecret)) + return NTRU_DECRYPT_ERROR; + + if (plainLen != SECRET_LEN) + return NTRU_DECRYPT_ERROR; + + *inOutIdx += cipherLen; + + #ifdef HAVE_QSH + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + *inOutIdx, &name); + *inOutIdx += OPAQUE16_LEN; + + if (name == WOLFSSL_QSH) { + *inOutIdx += TLSX_QSHCipher_Parse(ssl, input + + *inOutIdx, size - *inOutIdx + begin, 1); + } + else { + /* unknown extension sent client ignored + handshake */ + return BUFFER_ERROR; + } + } + #endif + ssl->arrays->preMasterSz = plainLen; + ret = MakeMasterSecret(ssl); + } + break; + #endif /* HAVE_NTRU */ #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { @@ -14787,7 +14977,7 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->arrays->preMasterSz = length; #ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { + if (ssl->options.haveQSH) { /* extension name */ ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; @@ -14838,7 +15028,7 @@ int DoSessionTicket(WOLFSSL* ssl, *inOutIdx += clientPubSz; #ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { + if (ssl->options.haveQSH) { /* extension name */ ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; @@ -14929,7 +15119,7 @@ int DoSessionTicket(WOLFSSL* ssl, ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + OPAQUE16_LEN; #ifdef HAVE_QSH - if (ssl->peerQSHKeyPresent) { + if (ssl->options.haveQSH) { /* extension name */ ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; diff --git a/src/keys.c b/src/keys.c index 93c769219..1b15dbb93 100644 --- a/src/keys.c +++ b/src/keys.c @@ -877,6 +877,22 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif #ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 case SSL_RSA_WITH_RC4_128_MD5 : @@ -912,6 +928,23 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA case TLS_RSA_WITH_AES_128_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_aes; @@ -980,6 +1013,23 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA case TLS_RSA_WITH_AES_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_aes; @@ -1014,6 +1064,23 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + #ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 case TLS_PSK_WITH_AES_128_GCM_SHA256 : ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; diff --git a/src/ssl.c b/src/ssl.c index b49eeecc6..626436fec 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -9873,10 +9873,24 @@ const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) case TLS_RSA_WITH_RABBIT_SHA : return "TLS_RSA_WITH_RABBIT_SHA"; #endif + #ifdef HAVE_NTRU + #ifndef NO_RC4 + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + return "TLS_NTRU_RSA_WITH_RC4_128_SHA"; + #endif + #ifndef NO_DES3 + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + return "TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA"; + #endif + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + return "TLS_NTRU_RSA_WITH_AES_128_CBC_SHA"; + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + return "TLS_NTRU_RSA_WITH_AES_256_CBC_SHA"; + #endif /* HAVE_NTRU */ #ifdef HAVE_QSH case TLS_QSH : return "TLS_QSH"; - #endif /* HAVE_NTRU */ + #endif /* HAVE_QSH*/ #endif /* NO_SHA */ case TLS_RSA_WITH_AES_128_GCM_SHA256 : return "TLS_RSA_WITH_AES_128_GCM_SHA256"; diff --git a/src/tls.c b/src/tls.c index 78da2efa5..5a070f667 100644 --- a/src/tls.c +++ b/src/tls.c @@ -2232,6 +2232,7 @@ static void TLSX_QSHAgreement(TLSX** extensions) { TLSX* extension = TLSX_Find(*extensions, WOLFSSL_QSH); QSHScheme* format = NULL; + QSHScheme* delete = NULL; QSHScheme* prev = NULL; if (extension == NULL) @@ -2246,9 +2247,10 @@ static void TLSX_QSHAgreement(TLSX** extensions) } if (prev) prev->next = format->next; - prev = format; + delete = format; format = format->next; - XFREE(format, ssl->heap, DYNAMIC_TYPE_TMP_ARRAY); + XFREE(delete, 0, DYNAMIC_TYPE_TMP_ARRAY); + delete = NULL; } else { prev = format; format = format->next; @@ -2275,6 +2277,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, byte* PK = NULL; int r; + if (OPAQUE16_LEN > length) return BUFFER_ERROR; @@ -2313,6 +2316,11 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, offset += OPAQUE16_LEN; schemSz += offset; + + /* check buffer size */ + if (schemSz > length) + return BUFFER_ERROR; + while ((offset < schemSz) && numKeys) { /* Scheme ID list */ ato16(input + offset, &name); @@ -3028,7 +3036,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) /* test if user has set a specific scheme already */ if (!ssl->user_set_QSHSchemes) { - if (ssl->sendQSHKeys) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { WOLFSSL_MSG("Error creating ntru keys"); return ret; @@ -3068,7 +3076,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) public_key, public_key_len) != SSL_SUCCESS) ret = -1; } - else if (ssl->sendQSHKeys) { + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { /* for each scheme make a client key */ extension = TLSX_Find(ssl->extensions, WOLFSSL_QSH); if (extension) { @@ -3192,6 +3200,15 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl) word16 length = 0; byte semaphore[SEMAPHORE_SIZE] = {0}; + #ifdef HAVE_QSH + /* change response if not using TLS_QSH */ + if (!ssl->options.haveQSH) { + TLSX* ext = TLSX_Find(ssl->extensions, WOLFSSL_QSH); + if (ext) + ext->resp = 0; + } + #endif + if (TLSX_SupportExtensions(ssl)) length += TLSX_GetSize(ssl->extensions, semaphore, 0); diff --git a/tests/test-qsh.conf b/tests/test-qsh.conf index 0261e9e47..8261f147d 100644 --- a/tests/test-qsh.conf +++ b/tests/test-qsh.conf @@ -1901,4 +1901,121 @@ -v 1 -l QSH:ADH-AES128-SHA +# server TLSv1 NTRU_RC4 +-v 1 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_RC4 +-v 1 +-l QSH:NTRU-RC4-SHA + +# server TLSv1 NTRU_DES3 +-v 1 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_DES3 +-v 1 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1 NTRU_AES128 +-v 1 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES128 +-v 1 +-l QSH:NTRU-AES128-SHA + +# server TLSv1 NTRU_AES256 +-v 1 +-l QSH:NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES256 +-v 1 +-l QSH:NTRU-AES256-SHA + +# server TLSv1.1 NTRU_RC4 +-v 2 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_RC4 +-v 2 +-l QSH:NTRU-RC4-SHA + +# server TLSv1.1 NTRU_DES3 +-v 2 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_DES3 +-v 2 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1.1 NTRU_AES128 +-v 2 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES128 +-v 2 +-l QSH:NTRU-AES128-SHA + +# server TLSv1.1 NTRU_AES256 +-v 2 +-l QSH:NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES256 +-v 2 +-l QSH:NTRU-AES256-SHA + +# server TLSv1.2 NTRU_RC4 +-v 3 +-l QSH:NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_RC4 +-v 3 +-l QSH:NTRU-RC4-SHA + +# server TLSv1.2 NTRU_DES3 +-v 3 +-l QSH:NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_DES3 +-v 3 +-l QSH:NTRU-DES-CBC3-SHA + +# server TLSv1.2 NTRU_AES128 +-v 3 +-l QSH:NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + diff --git a/tests/test.conf b/tests/test.conf index 89e024860..963db7b06 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -1901,3 +1901,121 @@ -v 1 -l ADH-AES128-SHA +# server TLSv1 NTRU_RC4 +-v 1 +-l NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_RC4 +-v 1 +-l NTRU-RC4-SHA + +# server TLSv1 NTRU_DES3 +-v 1 +-l NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_DES3 +-v 1 +-l NTRU-DES-CBC3-SHA + +# server TLSv1 NTRU_AES128 +-v 1 +-l NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES128 +-v 1 +-l NTRU-AES128-SHA + +# server TLSv1 NTRU_AES256 +-v 1 +-l NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1 NTRU_AES256 +-v 1 +-l NTRU-AES256-SHA + +# server TLSv1.1 NTRU_RC4 +-v 2 +-l NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_RC4 +-v 2 +-l NTRU-RC4-SHA + +# server TLSv1.1 NTRU_DES3 +-v 2 +-l NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_DES3 +-v 2 +-l NTRU-DES-CBC3-SHA + +# server TLSv1.1 NTRU_AES128 +-v 2 +-l NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES128 +-v 2 +-l NTRU-AES128-SHA + +# server TLSv1.1 NTRU_AES256 +-v 2 +-l NTRU-AES256-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.1 NTRU_AES256 +-v 2 +-l NTRU-AES256-SHA + +# server TLSv1.2 NTRU_RC4 +-v 3 +-l NTRU-RC4-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_RC4 +-v 3 +-l NTRU-RC4-SHA + +# server TLSv1.2 NTRU_DES3 +-v 3 +-l NTRU-DES-CBC3-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + +# client TLSv1.2 NTRU_DES3 +-v 3 +-l NTRU-DES-CBC3-SHA + +# server TLSv1.2 NTRU_AES128 +-v 3 +-l NTRU-AES128-SHA +-n +-c ./certs/ntru-cert.pem +-k ./certs/ntru-key.raw + + diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 46c439b2a..9664bf0e4 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -217,11 +217,17 @@ typedef byte word24[3]; #if !defined(NO_MD5) #define BUILD_SSL_RSA_WITH_RC4_128_MD5 #endif + #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) + #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + #endif #endif #if !defined(NO_RSA) && !defined(NO_DES3) #if !defined(NO_SHA) #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + #if !defined(NO_TLS) && defined(HAVE_NTRU) + #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + #endif #endif #endif @@ -229,6 +235,10 @@ typedef byte word24[3]; #if !defined(NO_SHA) #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + #if defined(HAVE_NTRU) + #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + #endif #endif #if !defined (NO_SHA256) #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 @@ -632,6 +642,12 @@ enum { TLS_RSA_WITH_AES_256_CBC_B2B256 = 0xF9, TLS_RSA_WITH_HC_128_B2B256 = 0xFA, /* eSTREAM too */ + /* wolfSSL extension - NTRU */ + TLS_NTRU_RSA_WITH_RC4_128_SHA = 0xe5, + TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0xe6, + TLS_NTRU_RSA_WITH_AES_128_CBC_SHA = 0xe7, /* clashes w/official SHA-256 */ + TLS_NTRU_RSA_WITH_AES_256_CBC_SHA = 0xe8, + /* wolfSSL extension - NTRU , Quantum-safe Handshake first byte is 0xD0 (QSH_BYTE) */ TLS_QSH = 0x01, @@ -1947,6 +1963,7 @@ typedef struct Options { word16 haveRSA:1; /* RSA available */ word16 haveDH:1; /* server DH parms set by user */ word16 haveNTRU:1; /* server NTRU private key loaded */ + byte haveQSH:1; /* have QSH ability */ word16 haveECDSAsig:1; /* server ECDSA signed cert */ word16 haveStaticECC:1; /* static server ECC private key */ word16 havePeerCert:1; /* do we have peer's cert */ @@ -2241,6 +2258,11 @@ struct WOLFSSL { byte maxRequest; byte user_set_QSHSchemes; #endif +#ifdef HAVE_NTRU + word16 peerNtruKeyLen; + byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; + byte peerNtruKeyPresent; +#endif #ifdef HAVE_ECC ecc_key* peerEccKey; /* peer's ECDHE key */ ecc_key* peerEccDsaKey; /* peer's ECDSA key */