\n"; char body[] = "greetings from wolfSSL\n"; char footer[] = "\r\n\r\n"; - + strncpy(command, type, sizeof(type)); echoSz = sizeof(type) - 1; @@ -354,21 +388,57 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) strncpy(&command[echoSz], footer, sizeof(footer)); echoSz += (int)sizeof(footer); - if (CyaSSL_write(ssl, command, echoSz) != echoSz) - err_sys("SSL_write failed"); + do { + err = 0; /* reset error */ + ret = CyaSSL_write(write_ssl, command, echoSz); + if (ret <= 0) { + err = CyaSSL_get_error(write_ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != echoSz) { + printf("SSL_write get error = %d, %s\n", err, + CyaSSL_ERR_error_string(err, buffer)); + err_sys("SSL_write get failed"); + } break; } command[echoSz] = 0; - #ifdef ECHO_OUT - fputs(command, fout); - #endif + #ifdef ECHO_OUT + fputs(command, fout); + #endif - if (CyaSSL_write(ssl, command, echoSz) != echoSz) - err_sys("SSL_write failed"); + do { + err = 0; /* reset error */ + ret = CyaSSL_write(write_ssl, command, echoSz); + if (ret <= 0) { + err = CyaSSL_get_error(write_ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(write_ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + + if (ret != echoSz) { + printf("SSL_write echo error = %d, %s\n", err, + CyaSSL_ERR_error_string(err, buffer)); + err_sys("SSL_write echo failed"); + } } #ifndef CYASSL_DTLS CyaSSL_shutdown(ssl); +#endif +#ifdef HAVE_WRITE_DUP + CyaSSL_free(write_ssl); #endif CyaSSL_free(ssl); CloseSocket(clientfd); @@ -445,7 +515,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) return args.return_code; } - + #endif /* NO_MAIN_DRIVER */ diff --git a/examples/server/server.c b/examples/server/server.c index d39db8070..4ef51341f 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -30,11 +30,6 @@ #include/* ecc_fp_free */ #endif -#if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER) - /* in case memory tracker wants stats */ - #define WOLFSSL_TRACK_MEMORY -#endif - #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) #include #include @@ -74,7 +69,19 @@ int myHsDoneCb(WOLFSSL* ssl, void* user_ctx); #endif - +static const char webServerMsg[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + " Welcome to wolfSSL! \n" + "\n" + "\n" + "wolfSSL has successfully performed handshake!
\n" + "\n" + "\n"; static int NonBlockingSSL_Accept(SSL* ssl) { @@ -85,25 +92,35 @@ static int NonBlockingSSL_Accept(SSL* ssl) #endif int error = SSL_get_error(ssl, 0); SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl); - int select_ret; + int select_ret = 0; while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ || - error == SSL_ERROR_WANT_WRITE)) { + error == SSL_ERROR_WANT_WRITE || + error == WC_PENDING_E)) { int currTimeout = 1; if (error == SSL_ERROR_WANT_READ) { /* printf("... server would read block\n"); */ - } else { + } + else if (error == SSL_ERROR_WANT_WRITE) { /* printf("... server would write block\n"); */ } + #ifdef WOLFSSL_ASYNC_CRYPT + else if (error == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif -#ifdef CYASSL_DTLS - currTimeout = CyaSSL_dtls_get_current_timeout(ssl); -#endif - select_ret = tcp_select(sockfd, currTimeout); + if (error != WC_PENDING_E) { + #ifdef CYASSL_DTLS + currTimeout = CyaSSL_dtls_get_current_timeout(ssl); + #endif + select_ret = tcp_select(sockfd, currTimeout); + } if ((select_ret == TEST_RECV_READY) || - (select_ret == TEST_ERROR_READY)) { + (select_ret == TEST_ERROR_READY) || error == WC_PENDING_E) { #ifndef CYASSL_CALLBACKS ret = SSL_accept(ssl); #else @@ -115,12 +132,12 @@ static int NonBlockingSSL_Accept(SSL* ssl) else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) { error = SSL_ERROR_WANT_READ; } -#ifdef CYASSL_DTLS + #ifdef CYASSL_DTLS else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) && CyaSSL_dtls_got_timeout(ssl) >= 0) { error = SSL_ERROR_WANT_READ; } -#endif + #endif else { error = SSL_FATAL_ERROR; } @@ -132,60 +149,92 @@ static int NonBlockingSSL_Accept(SSL* ssl) /* Echo number of bytes specified by -e arg */ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int throughput) { - int ret = 0; - char* buffer = (char*)malloc(TEST_BUFFER_SIZE); - if(buffer) { - double start = 0, rx_time = 0, tx_time = 0; - int xfer_bytes = 0; - while((echoData && throughput == 0) || (!echoData && xfer_bytes < throughput)) { - int select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ - if (select_ret == TEST_RECV_READY) { - int len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); - int rx_pos = 0; - if(throughput) { - start = current_time(1); - } - while(rx_pos < len) { - ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); - if (ret <= 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) { - printf("SSL_read error %d!\n", readErr); - err_sys("SSL_read failed"); - } - } - else { - rx_pos += ret; - } - } - if(throughput) { - rx_time += current_time(0) - start; - start = current_time(1); - } - if (SSL_write(ssl, buffer, len) != len) { - err_sys("SSL_write failed"); - } - if(throughput) { - tx_time += current_time(0) - start; - } + int ret = 0, err; + double start = 0, rx_time = 0, tx_time = 0; + int xfer_bytes = 0, select_ret, len, rx_pos; + char* buffer; - xfer_bytes += len; + buffer = (char*)malloc(TEST_BUFFER_SIZE); + if (!buffer) { + err_sys("Server buffer malloc failed"); + } + + while ((echoData && throughput == 0) || + (!echoData && xfer_bytes < throughput)) + { + select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ + if (select_ret == TEST_RECV_READY) { + + len = min(TEST_BUFFER_SIZE, throughput - xfer_bytes); + rx_pos = 0; + + if (throughput) { + start = current_time(1); } - } - free(buffer); - if(throughput) { - printf("wolfSSL Server Benchmark %d bytes\n" - "\tRX %8.3f ms (%8.3f MBps)\n" - "\tTX %8.3f ms (%8.3f MBps)\n", - throughput, - tx_time * 1000, throughput / tx_time / 1024 / 1024, - rx_time * 1000, throughput / rx_time / 1024 / 1024 - ); + /* Read data */ + while (rx_pos < len) { + ret = SSL_read(ssl, &buffer[rx_pos], len - rx_pos); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read echo error %d\n", err); + err_sys("SSL_read failed"); + } + } + else { + rx_pos += ret; + } + } + if (throughput) { + rx_time += current_time(0) - start; + start = current_time(1); + } + + /* Write data */ + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, buffer, len); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + if (ret != len) { + printf("SSL_write echo error %d\n", err); + err_sys("SSL_write failed"); + } + + if (throughput) { + tx_time += current_time(0) - start; + } + + xfer_bytes += len; } } - else { - err_sys("Server buffer malloc failed"); + + free(buffer); + + if (throughput) { + printf("wolfSSL Server Benchmark %d bytes\n" + "\tRX %8.3f ms (%8.3f MBps)\n" + "\tTX %8.3f ms (%8.3f MBps)\n", + throughput, + tx_time * 1000, throughput / tx_time / 1024 / 1024, + rx_time * 1000, throughput / rx_time / 1024 / 1024 + ); } return EXIT_SUCCESS; @@ -201,12 +250,12 @@ static void Usage(void) printf("-vSSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n", SERVER_DEFAULT_VERSION); printf("-l Cipher suite list (: delimited)\n"); - printf("-c Certificate file, default %s\n", svrCert); - printf("-k Key file, default %s\n", svrKey); - printf("-A Certificate Authority file, default %s\n", cliCert); + printf("-c Certificate file, default %s\n", svrCertFile); + printf("-k Key file, default %s\n", svrKeyFile); + printf("-A Certificate Authority file, default %s\n", cliCertFile); printf("-R Create Ready file for external monitor default none\n"); #ifndef NO_DH - printf("-D Diffie-Hellman Params file, default %s\n", dhParam); + printf("-D Diffie-Hellman Params file, default %s\n", dhParamFile); printf("-Z Minimum DH key bits, default %d\n", DEFAULT_MIN_DHKEY_BITS); #endif @@ -252,6 +301,13 @@ static void Usage(void) #endif #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif + printf("-g Return basic HTML web page\n"); + printf("-C The number of connections to accept, default: 1\n"); + printf("-H Force use of the default cipher suite list\n"); +#ifdef WOLFSSL_TLS13 + printf("-K Key Exchange for PSK not using (EC)DHE\n"); + printf("-U Update keys and IVs before sending\n"); #endif } @@ -269,6 +325,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #else const char msg[] = "I hear you fa shizzle!\n"; #endif + int useWebServerMsg = 0; char input[80]; int ch; int version = SERVER_DEFAULT_VERSION; @@ -284,13 +341,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; - int trackMemory = 0; int fewerPackets = 0; int pkCallbacks = 0; int wc_shutdown = 0; int resume = 0; int resumeCount = 0; - int loopIndefinitely = 0; + int loops = 1; int echoData = 0; int throughput = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; @@ -304,10 +360,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; - const char* verifyCert = cliCert; - const char* ourCert = svrCert; - const char* ourKey = svrKey; - const char* ourDhParam = dhParam; + int useDefCipherList = 0; + const char* verifyCert = cliCertFile; + const char* ourCert = svrCertFile; + const char* ourKey = svrKeyFile; + const char* ourDhParam = dhParamFile; tcp_ready* readySignal = NULL; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -332,6 +389,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif + char buffer[CYASSL_MAX_ERROR_SZ]; +#ifdef WOLFSSL_TLS13 + int noPskDheKe = 0; +#endif + int updateKeysIVs = 0; #ifdef WOLFSSL_STATIC_MEMORY #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ @@ -348,9 +410,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA - verifyCert = (char*)cliEccCert; - ourCert = (char*)eccCert; - ourKey = (char*)eccKey; + verifyCert = (char*)cliEccCertFile; + ourCert = (char*)eccCertFile; + ourKey = (char*)eccKeyFile; #endif (void)pkCallbacks; (void)needDH; @@ -367,6 +429,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void)alpn_opt; (void)crlFlags; (void)readySignal; + (void)updateKeysIVs; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); @@ -375,8 +438,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, - "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + /* Not Used: h, m, t, x, y, z, F, J, M, Q, T, V, W, X, Y */ + while ((ch = mygetopt(argc, argv, "?" + "abc:defgijk:l:nop:q:rsuv:w" + "A:B:C:D:E:GHIKL:NO:PR:S:UYZ:")) != -1) { switch (ch) { case '?' : Usage(); @@ -398,12 +463,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) usePskPlus = 1; break; - case 't' : - #ifdef USE_WOLFSSL_MEMORY - trackMemory = 1; - #endif - break; - case 'n' : useNtruKey = 1; break; @@ -450,7 +509,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) case 'v' : version = atoi(myoptarg); - if (version < 0 || version > 3) { + if (version < 0 || version > 4) { Usage(); exit(MY_EX_USAGE); } @@ -460,6 +519,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) cipherList = myoptarg; break; + case 'H' : + useDefCipherList = 1; + break; + case 'A' : verifyCert = myoptarg; break; @@ -541,7 +604,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'i' : - loopIndefinitely = 1; + loops = -1; + break; + + case 'C' : + loops = atoi(myoptarg); + if (loops <= 0) { + Usage(); + exit(MY_EX_USAGE); + } break; case 'e' : @@ -568,6 +639,22 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case 'g' : + useWebServerMsg = 1; + break; + + case 'K' : + #ifdef WOLFSSL_TLS13 + noPskDheKe = 1; + #endif + break; + + case 'U' : + #ifdef WOLFSSL_TLS13 + updateKeysIVs = 1; + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -598,11 +685,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } } -#if defined(USE_CYASSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - InitMemoryTracker(); -#endif - #ifdef HAVE_WNR if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) err_sys("can't load whitewood net random config file"); @@ -635,6 +717,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; #endif +#ifdef WOLFSSL_TLS13 + case 4: + method = wolfTLSv1_3_server_method_ex; + break; +#endif + #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS case -1: @@ -689,9 +777,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif - if (cipherList) + if (cipherList && !useDefCipherList) { if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 1"); + } #ifdef CYASSL_LEANPSK if (!usePsk) { @@ -795,7 +884,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); - if (cipherList == NULL) { + if (cipherList == NULL || (cipherList && useDefCipherList)) { if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 4"); } @@ -846,25 +935,31 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_ASYNC_CRYPT ret = wolfAsync_DevOpen(&devId); - if (ret != 0) { - err_sys("Async device open failed"); + if (ret < 0) { + printf("Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_TLS13 + if (noPskDheKe) + wolfSSL_CTX_no_dhe_psk(ctx); +#endif + while (1) { /* allow resume option */ - if(resumeCount > 1) { + if (resumeCount > 1) { if (dtlsUDP == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - } else { + } + else { tcp_listen(&sockfd, &port, useAnyAddr, dtlsUDP, dtlsSCTP); clientfd = sockfd; } - if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { + if (WOLFSSL_SOCKET_IS_INVALID(clientfd)) { err_sys("tcp accept failed"); } } @@ -882,6 +977,9 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ssl = SSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL"); + #ifdef OPENSSL_EXTRA + wolfSSL_KeepArrays(ssl); + #endif #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) { @@ -990,38 +1088,69 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } #endif - do { -#ifdef WOLFSSL_ASYNC_CRYPT - if (err == WC_PENDING_E) { - ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); - if (ret < 0) { break; } else if (ret == 0) { continue; } - } -#endif - - err = 0; /* Reset error */ #ifndef CYASSL_CALLBACKS - if (nonBlocking) { - ret = NonBlockingSSL_Accept(ssl); - } - else { - ret = SSL_accept(ssl); - } -#else + if (nonBlocking) { ret = NonBlockingSSL_Accept(ssl); + } + else { + do { + err = 0; /* reset error */ + ret = SSL_accept(ssl); + if (ret != SSL_SUCCESS) { + err = SSL_get_error(ssl, 0); + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E); + } +#else + ret = NonBlockingSSL_Accept(ssl); #endif - if (ret != SSL_SUCCESS) { - err = SSL_get_error(ssl, 0); - } - } while (ret != SSL_SUCCESS && err == WC_PENDING_E); - if (ret != SSL_SUCCESS) { - char buffer[CYASSL_MAX_ERROR_SZ]; err = SSL_get_error(ssl, 0); - printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); + printf("SSL_accept error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_accept failed"); } showPeer(ssl); + if (SSL_state(ssl) != 0) { + err_sys("SSL in error state"); + } + +#ifdef OPENSSL_EXTRA + { + byte* rnd; + byte* pt; + size_t size; + + /* get size of buffer then print */ + size = wolfSSL_get_server_random(NULL, NULL, 0); + if (size == 0) { + err_sys("error getting server random buffer size"); + } + + rnd = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (rnd == NULL) { + err_sys("error creating server random buffer"); + } + + size = wolfSSL_get_server_random(ssl, rnd, size); + if (size == 0) { + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err_sys("error getting server random buffer"); + } + + printf("Server Random : "); + for (pt = rnd; pt < rnd + size; pt++) printf("%02X", *pt); + printf("\n"); + XFREE(rnd, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif #ifdef HAVE_ALPN if (alpnList != NULL) { @@ -1047,21 +1176,69 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) free(list); } #endif - if(echoData == 0 && throughput == 0) { - ret = SSL_read(ssl, input, sizeof(input)-1); + if (echoData == 0 && throughput == 0) { + const char* write_msg; + int write_msg_sz; + + /* Read data */ + do { + err = 0; /* reset error */ + ret = SSL_read(ssl, input, sizeof(input)-1); + if (ret < 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + else + #endif + if (err != SSL_ERROR_WANT_READ) { + printf("SSL_read input error %d, %s\n", err, + ERR_error_string(err, buffer)); + err_sys("SSL_read failed"); + } + } + } while (err == WC_PENDING_E); if (ret > 0) { - input[ret] = 0; + input[ret] = 0; /* null terminate message */ printf("Client message: %s\n", input); - - } - else if (ret < 0) { - int readErr = SSL_get_error(ssl, 0); - if (readErr != SSL_ERROR_WANT_READ) - err_sys("SSL_read failed"); } - if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) +#ifdef WOLFSSL_TLS13 + if (updateKeysIVs) + wolfSSL_update_keys(ssl); +#endif + + /* Write data */ + if (!useWebServerMsg) { + write_msg = msg; + write_msg_sz = sizeof(msg); + } + else { + write_msg = webServerMsg; + write_msg_sz = sizeof(webServerMsg); + } + do { + err = 0; /* reset error */ + ret = SSL_write(ssl, write_msg, write_msg_sz); + if (ret <= 0) { + err = SSL_get_error(ssl, 0); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (err == WC_PENDING_E) { + ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + if (ret < 0) break; + } + #endif + } + } while (err == WC_PENDING_E || err == SSL_ERROR_WANT_WRITE); + if (ret != write_msg_sz) { + printf("SSL_write msg error %d, %s\n", err, + ERR_error_string(err, buffer)); err_sys("SSL_write failed"); + } } else { ServerEchoData(ssl, clientfd, echoData, throughput); @@ -1103,7 +1280,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } resumeCount = 0; - if(!loopIndefinitely) { + if (loops > 0 && --loops == 0) { break; /* out of while loop, done with normal and resume option */ } } /* while(1) */ @@ -1120,11 +1297,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) ecc_fp_free(); /* free per thread cache */ #endif -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - if (trackMemory) - ShowMemoryTracker(); -#endif - #ifdef CYASSL_TIRTOS fdCloseSession(Task_self()); #endif @@ -1147,7 +1319,6 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) (void) useNtruKey; (void) ourDhParam; (void) ourCert; - (void) trackMemory; #ifndef CYASSL_TIRTOS return 0; #endif diff --git a/fips-check.sh b/fips-check.sh index 31e8a51d3..d6d88375c 100755 --- a/fips-check.sh +++ b/fips-check.sh @@ -9,14 +9,17 @@ # This should check out all the approved versions. The command line # option selects the version. # -# $ ./fips-check [version] +# $ ./fips-check [version] [keep] # -# - version: linux (default), ios, android, windows, freertos +# - version: linux (default), ios, android, windows, freertos, linux-ecc +# +# - keep: (default off) XXX-fips-test temp dir around for inspection # function Usage() { - echo "Usage: $0 [platform]" - echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos" + echo "Usage: $0 [platform] [keep]" + echo "Where \"platform\" is one of linux (default), ios, android, windows, freertos, openrtos-3.9.2, linux-ecc" + echo "Where \"keep\" means keep (default off) XXX-fips-test temp dir around for inspection" } LINUX_FIPS_VERSION=v3.2.6 @@ -24,6 +27,11 @@ LINUX_FIPS_REPO=git@github.com:wolfSSL/fips.git LINUX_CTAO_VERSION=v3.2.6 LINUX_CTAO_REPO=git@github.com:cyassl/cyassl.git +LINUX_ECC_FIPS_VERSION=v3.10.3 +LINUX_ECC_FIPS_REPO=git@github.com:wolfSSL/fips.git +LINUX_ECC_CTAO_VERSION=v3.2.6 +LINUX_ECC_CTAO_REPO=git@github.com:cyassl/cyassl.git + IOS_FIPS_VERSION=v3.4.8a IOS_FIPS_REPO=git@github.com:wolfSSL/fips.git IOS_CTAO_VERSION=v3.4.8.fips @@ -44,6 +52,11 @@ FREERTOS_FIPS_REPO=git@github.com:wolfSSL/fips.git FREERTOS_CTAO_VERSION=v3.6.1 FREERTOS_CTAO_REPO=git@github.com:cyassl/cyassl.git +OPENRTOS_3_9_2_FIPS_VERSION=v3.9.2-OpenRTOS +OPENRTOS_3_9_2_FIPS_REPO=git@github.com:wolfSSL/fips.git +OPENRTOS_3_9_2_CTAO_VERSION=v3.6.1 +OPENRTOS_3_9_2_CTAO_REPO=git@github.com:cyassl/cyassl.git + FIPS_SRCS=( fips.c fips_test.c ) WC_MODS=( aes des3 sha sha256 sha512 rsa hmac random ) TEST_DIR=XXX-fips-test @@ -52,6 +65,8 @@ WC_SRC_PATH=ctaocrypt/src if [ "x$1" == "x" ]; then PLATFORM="linux"; else PLATFORM=$1; fi +if [ "x$2" == "xkeep" ]; then KEEP="yes"; else KEEP="no"; fi + case $PLATFORM in ios) FIPS_VERSION=$IOS_FIPS_VERSION @@ -77,12 +92,25 @@ freertos) CTAO_VERSION=$FREERTOS_CTAO_VERSION CTAO_REPO=$FREERTOS_CTAO_REPO ;; +openrtos-3.9.2) + FIPS_VERSION=$OPENRTOS_3_9_2_FIPS_VERSION + FIPS_REPO=$OPENRTOS_3_9_2_FIPS_REPO + CTAO_VERSION=$OPENRTOS_3_9_2_CTAO_VERSION + CTAO_REPO=$OPENRTOS_3_9_2_CTAO_REPO + FIPS_CONFLICTS=( aes hmac random sha256 ) + ;; linux) FIPS_VERSION=$LINUX_FIPS_VERSION FIPS_REPO=$LINUX_FIPS_REPO CTAO_VERSION=$LINUX_CTAO_VERSION CTAO_REPO=$LINUX_CTAO_REPO ;; +linux-ecc) + FIPS_VERSION=$LINUX_ECC_FIPS_VERSION + FIPS_REPO=$LINUX_ECC_FIPS_REPO + CTAO_VERSION=$LINUX_ECC_CTAO_VERSION + CTAO_REPO=$LINUX_ECC_CTAO_REPO + ;; *) Usage exit 1 @@ -134,7 +162,22 @@ fi make test [ $? -ne 0 ] && echo "\n\nTest failed. Debris left for analysis." && exit 1 +if [ ${#FIPS_CONFLICTS[@]} -ne 0 ]; +then + echo "Due to the way this package is compiled by the customer duplicate" + echo "source file names are an issue, renaming:" + for FNAME in ${FIPS_CONFLICTS[@]} + do + echo "wolfcrypt/src/$FNAME.c to wolfcrypt/src/wc_$FNAME.c" + mv ./wolfcrypt/src/$FNAME.c ./wolfcrypt/src/wc_$FNAME.c + done + echo "Confirming files were renamed..." + ls -la ./wolfcrypt/src/wc_*.c +fi + # Clean up popd -rm -rf $TEST_DIR - +if [ "x$KEEP" == "xno" ]; +then + rm -rf $TEST_DIR +fi diff --git a/gencertbuf.pl b/gencertbuf.pl index 09c6114c2..e7dc9f7d6 100755 --- a/gencertbuf.pl +++ b/gencertbuf.pl @@ -55,6 +55,7 @@ my @fileList_2048 = ( [ "./certs/dh2048.der", "dh_key_der_2048" ], [ "./certs/dsa2048.der", "dsa_key_der_2048" ], [ "./certs/rsa2048.der", "rsa_key_der_2048" ], + [ "./certs/ca-key.der", "ca_key_der_2048" ], [ "./certs/ca-cert.der", "ca_cert_der_2048" ], [ "./certs/server-key.der", "server_key_der_2048" ], [ "./certs/server-cert.der", "server_cert_der_2048" ] diff --git a/mcapi/crypto.c b/mcapi/crypto.c index d0216035d..8ccf00460 100644 --- a/mcapi/crypto.c +++ b/mcapi/crypto.c @@ -52,9 +52,7 @@ int CRYPT_MD5_Initialize(CRYPT_MD5_CTX* md5) if (md5 == NULL) return BAD_FUNC_ARG; - wc_InitMd5((Md5*)md5); - - return 0; + return wc_InitMd5((Md5*)md5); } @@ -65,9 +63,7 @@ int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX* md5, const unsigned char* input, if (md5 == NULL || input == NULL) return BAD_FUNC_ARG; - wc_Md5Update((Md5*)md5, input, sz); - - return 0; + return wc_Md5Update((Md5*)md5, input, sz); } @@ -77,9 +73,7 @@ int CRYPT_MD5_Finalize(CRYPT_MD5_CTX* md5, unsigned char* digest) if (md5 == NULL || digest == NULL) return BAD_FUNC_ARG; - wc_Md5Final((Md5*)md5, digest); - - return 0; + return wc_Md5Final((Md5*)md5, digest); } diff --git a/mcapi/crypto.h b/mcapi/crypto.h index 6db1dd211..4d71a3f26 100644 --- a/mcapi/crypto.h +++ b/mcapi/crypto.h @@ -34,7 +34,7 @@ /* MD5 */ typedef struct CRYPT_MD5_CTX { - int holder[24]; /* big enough to hold internal, but check on init */ + int holder[28]; /* big enough to hold internal, but check on init */ } CRYPT_MD5_CTX; int CRYPT_MD5_Initialize(CRYPT_MD5_CTX*); @@ -42,13 +42,13 @@ int CRYPT_MD5_DataAdd(CRYPT_MD5_CTX*, const unsigned char*, unsigned int); int CRYPT_MD5_Finalize(CRYPT_MD5_CTX*, unsigned char*); enum { - CRYPT_MD5_DIGEST_SIZE = 16 + CRYPT_MD5_DIGEST_SIZE = 16 }; /* SHA */ typedef struct CRYPT_SHA_CTX { - int holder[24]; /* big enough to hold internal, but check on init */ + int holder[28]; /* big enough to hold internal, but check on init */ } CRYPT_SHA_CTX; int CRYPT_SHA_Initialize(CRYPT_SHA_CTX*); @@ -62,7 +62,7 @@ enum { /* SHA-256 */ typedef struct CRYPT_SHA256_CTX { - int holder[28]; /* big enough to hold internal, but check on init */ + int holder[32]; /* big enough to hold internal, but check on init */ } CRYPT_SHA256_CTX; int CRYPT_SHA256_Initialize(CRYPT_SHA256_CTX*); @@ -70,13 +70,13 @@ int CRYPT_SHA256_DataAdd(CRYPT_SHA256_CTX*, const unsigned char*, unsigned int); int CRYPT_SHA256_Finalize(CRYPT_SHA256_CTX*, unsigned char*); enum { - CRYPT_SHA256_DIGEST_SIZE = 32 + CRYPT_SHA256_DIGEST_SIZE = 32 }; /* SHA-384 */ typedef struct CRYPT_SHA384_CTX { - long long holder[32]; /* big enough to hold internal, but check on init */ + long long holder[36]; /* big enough to hold internal, but check on init */ } CRYPT_SHA384_CTX; int CRYPT_SHA384_Initialize(CRYPT_SHA384_CTX*); @@ -98,13 +98,13 @@ int CRYPT_SHA512_DataAdd(CRYPT_SHA512_CTX*, const unsigned char*, unsigned int); int CRYPT_SHA512_Finalize(CRYPT_SHA512_CTX*, unsigned char*); enum { - CRYPT_SHA512_DIGEST_SIZE = 64 + CRYPT_SHA512_DIGEST_SIZE = 64 }; /* HMAC */ typedef struct CRYPT_HMAC_CTX { - long long holder[69]; /* big enough to hold internal, but check on init */ + long long holder[72]; /* big enough to hold internal, but check on init */ } CRYPT_HMAC_CTX; int CRYPT_HMAC_SetKey(CRYPT_HMAC_CTX*, int, const unsigned char*, unsigned int); @@ -113,10 +113,10 @@ int CRYPT_HMAC_Finalize(CRYPT_HMAC_CTX*, unsigned char*); /* HMAC types */ enum { - CRYPT_HMAC_SHA = 1, - CRYPT_HMAC_SHA256 = 2, - CRYPT_HMAC_SHA384 = 5, - CRYPT_HMAC_SHA512 = 4 + CRYPT_HMAC_SHA = 1, + CRYPT_HMAC_SHA256 = 2, + CRYPT_HMAC_SHA384 = 5, + CRYPT_HMAC_SHA512 = 4 }; @@ -128,7 +128,7 @@ int CRYPT_HUFFMAN_DeCompress(unsigned char*, unsigned int, const unsigned char*, /* flag to use static huffman */ enum { - CRYPT_HUFFMAN_COMPRESS_STATIC = 1 + CRYPT_HUFFMAN_COMPRESS_STATIC = 1 }; @@ -144,7 +144,7 @@ int CRYPT_RNG_BlockGenerate(CRYPT_RNG_CTX*, unsigned char*, unsigned int); /* TDES */ typedef struct CRYPT_TDES_CTX { - int holder[100]; /* big enough to hold internal, but check on init */ + int holder[104]; /* big enough to hold internal, but check on init */ } CRYPT_TDES_CTX; int CRYPT_TDES_KeySet(CRYPT_TDES_CTX*, const unsigned char*, @@ -158,13 +158,13 @@ int CRYPT_TDES_CBC_Decrypt(CRYPT_TDES_CTX*, unsigned char*, /* key direction flags for setup */ enum { CRYPT_TDES_ENCRYPTION = 0, - CRYPT_TDES_DECRYPTION = 1 + CRYPT_TDES_DECRYPTION = 1 }; /* AES */ typedef struct CRYPT_AES_CTX { - int holder[76]; /* big enough to hold internal, but check on init */ + int holder[78]; /* big enough to hold internal, but check on init */ } CRYPT_AES_CTX; /* key */ @@ -262,7 +262,7 @@ int CRYPT_ERROR_StringGet(int, char*); #ifdef __cplusplus - } /* extern "C" */ + } /* extern "C" */ #endif diff --git a/mcapi/mcapi_test.c b/mcapi/mcapi_test.c index 0a6d77e74..5f1e4549e 100644 --- a/mcapi/mcapi_test.c +++ b/mcapi/mcapi_test.c @@ -214,25 +214,30 @@ static int check_md5(void) { CRYPT_MD5_CTX mcMd5; Md5 defMd5; + int ret; byte mcDigest[CRYPT_MD5_DIGEST_SIZE]; byte defDigest[MD5_DIGEST_SIZE]; CRYPT_MD5_Initialize(&mcMd5); - wc_InitMd5(&defMd5); + ret = wc_InitMd5(&defMd5); - CRYPT_MD5_DataAdd(&mcMd5, ourData, OUR_DATA_SIZE); - wc_Md5Update(&defMd5, ourData, OUR_DATA_SIZE); + if (ret == 0) { + CRYPT_MD5_DataAdd(&mcMd5, ourData, OUR_DATA_SIZE); + ret = wc_Md5Update(&defMd5, ourData, OUR_DATA_SIZE); + } - CRYPT_MD5_Finalize(&mcMd5, mcDigest); - wc_Md5Final(&defMd5, defDigest); + if (ret == 0) { + CRYPT_MD5_Finalize(&mcMd5, mcDigest); + ret = wc_Md5Final(&defMd5, defDigest); + } if (memcmp(mcDigest, defDigest, CRYPT_MD5_DIGEST_SIZE) != 0) { printf("md5 final memcmp fialed\n"); return -1; - } + } printf("md5 mcapi test passed\n"); - return 0; + return ret; } @@ -261,7 +266,7 @@ static int check_sha(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { printf("sha final memcmp failed\n"); return -1; - } + } printf("sha mcapi test passed\n"); return 0; @@ -301,7 +306,7 @@ static int check_sha256(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { printf("sha256 final memcmp fialed\n"); return -1; - } + } printf("sha256 mcapi test passed\n"); return 0; @@ -341,7 +346,7 @@ static int check_sha384(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { printf("sha384 final memcmp fialed\n"); return -1; - } + } printf("sha384 mcapi test passed\n"); return 0; @@ -381,7 +386,7 @@ static int check_sha512(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { printf("sha512 final memcmp fialed\n"); return -1; - } + } printf("sha512 mcapi test passed\n"); return 0; @@ -424,7 +429,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA_DIGEST_SIZE) != 0) { printf("hmac sha final memcmp fialed\n"); return -1; - } + } printf("hmac sha mcapi test passed\n"); /* SHA-256 */ @@ -452,7 +457,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA256_DIGEST_SIZE) != 0) { printf("hmac sha256 final memcmp fialed\n"); return -1; - } + } printf("hmac sha256 mcapi test passed\n"); /* SHA-384 */ @@ -480,7 +485,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA384_DIGEST_SIZE) != 0) { printf("hmac sha384 final memcmp fialed\n"); return -1; - } + } printf("hmac sha384 mcapi test passed\n"); /* SHA-512 */ @@ -508,7 +513,7 @@ static int check_hmac(void) if (memcmp(mcDigest, defDigest, CRYPT_SHA512_DIGEST_SIZE) != 0) { printf("hmac sha512 final memcmp fialed\n"); return -1; - } + } printf("hmac sha512 mcapi test passed\n"); return 0; @@ -621,7 +626,7 @@ static int check_compress(void) static int check_rng(void) { int ret; - int i; + int i; byte in[RANDOM_BYTE_SZ]; byte out[RANDOM_BYTE_SZ]; @@ -1326,7 +1331,7 @@ static int check_rsa(void) return -1; } - ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); + ret = CRYPT_RSA_PrivateDecrypt(&mcRsa, out2, sizeof(out2), out1, ret); if (ret < 0) { printf("mcapi rsa private derypt failed\n"); return -1; @@ -1348,7 +1353,7 @@ static int check_rsa(void) printf("mcapi rsa free failed\n"); return -1; } - + printf("rsa mcapi test passed\n"); return 0; @@ -1358,7 +1363,7 @@ static int check_rsa(void) /* check mcapi ecc */ static int check_ecc(void) { - CRYPT_ECC_CTX userA; + CRYPT_ECC_CTX userA; CRYPT_ECC_CTX userB; int ret; byte sharedA[100]; @@ -1463,7 +1468,7 @@ static int check_ecc(void) printf("mcapi ecc public export failed\n"); return -1; } - + ret = CRYPT_ECC_PublicImport(&userB, sharedA, usedA); if (ret != 0) { printf("mcapi ecc public import failed\n"); diff --git a/mplabx/benchmark_main.c b/mplabx/benchmark_main.c index 5c4c8651e..c7a31b4be 100644 --- a/mplabx/benchmark_main.c +++ b/mplabx/benchmark_main.c @@ -53,7 +53,7 @@ void bench_md5(void); void bench_sha(void); void bench_sha256(void); void bench_sha512(void); -void bench_ripemd(void); +int bench_ripemd(void); void bench_rsa(void); void bench_rsaKeyGen(void); diff --git a/rpm/spec.in b/rpm/spec.in index e7871d05b..182491a1f 100644 --- a/rpm/spec.in +++ b/rpm/spec.in @@ -72,8 +72,8 @@ mkdir -p $RPM_BUILD_ROOT/ %{_docdir}/wolfssl/README.txt %{_libdir}/libwolfssl.la %{_libdir}/libwolfssl.so -%{_libdir}/libwolfssl.so.3 -%{_libdir}/libwolfssl.so.3.6.0 +%{_libdir}/libwolfssl.so.12 +%{_libdir}/libwolfssl.so.12.0.0 %files devel %defattr(-,root,root,-) @@ -159,6 +159,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/cyassl/openssl/rsa.h %{_includedir}/cyassl/openssl/sha.h %{_includedir}/cyassl/openssl/ssl.h +%{_includedir}/cyassl/openssl/ssl23.h %{_includedir}/cyassl/openssl/stack.h %{_includedir}/cyassl/openssl/ui.h %{_includedir}/cyassl/openssl/x509.h @@ -172,6 +173,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/callbacks.h %{_includedir}/wolfssl/certs_test.h %{_includedir}/wolfssl/crl.h +%{_includedir}/wolfssl/io.h %{_includedir}/wolfssl/wolfcrypt/aes.h %{_includedir}/wolfssl/wolfcrypt/cmac.h %{_includedir}/wolfssl/wolfcrypt/arc4.h @@ -229,8 +231,10 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/wolfcrypt/visibility.h %{_includedir}/wolfssl/wolfcrypt/wc_encrypt.h %{_includedir}/wolfssl/wolfcrypt/wolfevent.h +%{_includedir}/wolfssl/wolfcrypt/wolfmath.h %{_includedir}/wolfssl/error-ssl.h %{_includedir}/wolfssl/ocsp.h +%{_includedir}/wolfssl/openssl/aes.h %{_includedir}/wolfssl/openssl/asn1.h %{_includedir}/wolfssl/openssl/bio.h %{_includedir}/wolfssl/openssl/bn.h @@ -262,6 +266,7 @@ mkdir -p $RPM_BUILD_ROOT/ %{_includedir}/wolfssl/openssl/rsa.h %{_includedir}/wolfssl/openssl/sha.h %{_includedir}/wolfssl/openssl/ssl.h +%{_includedir}/wolfssl/openssl/ssl23.h %{_includedir}/wolfssl/openssl/stack.h %{_includedir}/wolfssl/openssl/ui.h %{_includedir}/wolfssl/openssl/x509.h @@ -275,6 +280,12 @@ mkdir -p $RPM_BUILD_ROOT/ %{_libdir}/pkgconfig/wolfssl.pc %changelog +* Thu May 04 2017 Jacob Barthelmeh +- Added header for wolfssl/io.h, wolfssl/openssl/ssl23.h, cyassl/openssl/ssl23.h +* Thu Feb 09 2017 Jacob Barthelmeh +- Added header for wolfssl/wolfcrypt/wolfmath.h +* Fri Nov 11 2016 Jacob Barthelmeh +- Added header for wolfssl/openssl/aes.h * Fri Oct 28 2016 Jacob Barthelmeh - Added header for pkcs12 * Fri Sep 23 2016 John Safranek diff --git a/scripts/include.am b/scripts/include.am index 0a49b14af..442d758f7 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -62,6 +62,10 @@ dist_noinst_SCRIPTS+= scripts/openssl.test endif endif +if BUILD_TLS13 +dist_noinst_SCRIPTS+= scripts/tls13.test +endif + EXTRA_DIST += scripts/testsuite.pcap \ scripts/ping.test diff --git a/scripts/openssl.test b/scripts/openssl.test index 1a013518b..83c2ad084 100755 --- a/scripts/openssl.test +++ b/scripts/openssl.test @@ -82,7 +82,7 @@ found_free_port=0 while [ "$counter" -lt 20 ]; do echo -e "\nTrying to start openssl server on port $openssl_port...\n" - openssl s_server -accept $openssl_port -cert ./certs/server-cert.pem -key ./certs/server-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -dcert ./certs/server-ecc.pem -dkey ./certs/ecc-key.pem -verify 10 -verify_return_error -cipher "ALL:eNULL" & + openssl s_server -accept $openssl_port -cert ./certs/server-cert.pem -key ./certs/server-key.pem -quiet -CAfile ./certs/client-ca.pem -www -dhparam ./certs/dh2048.pem -dcert ./certs/server-ecc.pem -dkey ./certs/ecc-key.pem -verify 10 -verify_return_error -psk 1a2b3c4d -cipher "ALL:eNULL" & server_pid=$! # wait to see if s_server successfully starts before continuing sleep 0.1 @@ -215,12 +215,19 @@ do continue fi + # check for psk suite and turn on client psk if so + psk = "" + case $wolfSuite in + *PSK*) + psk="-s " ;; + esac + if [ $version -lt 4 ] then - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite -v $version + ./examples/client/client -p $openssl_port -g -r -l $wolfSuite -v $version $psk else # do all versions - ./examples/client/client -p $openssl_port -g -r -l $wolfSuite + ./examples/client/client -p $openssl_port -g -r -l $wolfSuite $psk fi client_result=$? diff --git a/scripts/tls13.test b/scripts/tls13.test new file mode 100755 index 000000000..27a891f58 --- /dev/null +++ b/scripts/tls13.test @@ -0,0 +1,312 @@ +#!/bin/sh + +# tls13.test +# copyright wolfSSL 2016 + +# getting unique port is modeled after resume.test script +# need a unique port since may run the same time as testsuite +# use server port zero hack to get one +port=0 +no_pid=-1 +server_pid=$no_pid +counter=0 +# let's use absolute path to a local dir (make distcheck may be in sub dir) +# also let's add some randomness by adding pid in case multiple 'make check's +# per source tree +ready_file=`pwd`/wolfssl_psk_ready$$ + +echo "ready file $ready_file" + +create_port() { + while [ ! -s $ready_file -a "$counter" -lt 50 ]; do + echo -e "waiting for ready file..." + sleep 0.1 + counter=$((counter+ 1)) + done + + if test -e $ready_file; then + echo -e "found ready file, starting client..." + + # get created port 0 ephemeral port + port=`cat $ready_file` + else + echo -e "NO ready file ending test..." + do_cleanup + fi +} + +remove_ready_file() { + if test -e $ready_file; then + echo -e "removing existing ready file" + rm $ready_file + fi +} + +do_cleanup() { + echo "in cleanup" + + if [ $server_pid != $no_pid ] + then + echo "killing server" + kill -9 $server_pid + fi + remove_ready_file +} + +do_trap() { + echo "got trap" + do_cleanup + exit -1 +} + +trap do_trap INT TERM + +[ ! -x ./examples/client/client ] && echo -e "\n\nClient doesn't exist" && exit 1 + +# Usual TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 not enabled" + do_cleanup + exit 1 +fi +echo "" + +# Use HelloRetryRequest with TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 HelloRetryRequest" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -J -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 HelloRetryRequest not working" + do_cleanup + exit 1 +fi +echo "" + +# Resumption TLS v1.3 server / TLS v1.3 client. +echo -e "\n\nTLS v1.3 resumption" +port=0 +./examples/server/server -v 4 -r -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -r -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 resumption not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and ECC certificates. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC certificates" +port=0 +./examples/server/server -v 4 -A certs/client-ecc-cert.pem -c certs/server-ecc.pem -k certs/ecc-key.pem -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -A certs/server-ecc.pem -c certs/client-ecc-cert.pem -k certs/ecc-client-key.pem -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECC certificates not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and DH Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - DH Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 DH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# Usual TLS v1.3 server / TLS v1.3 client and ECC Key. +echo -e "\n\nTLS v1.3 server with TLS v1.3 client - ECC Key Exchange" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -Y -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nTLS v1.3 ECDH Key Exchange not working" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suites" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES128-CCM-SHA256:TLS13-AES128-CCM-8-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - only TLS v1.3" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-GCM SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-GCM-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-GCM SHA-256" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - AES256-GCM SHA-384" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES256-GCM-SHA384 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES256-GCM SHA-384" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 cipher suites server / client. +echo -e "\n\nOnly TLS v1.3 cipher suite - CHACHA20-POLY1305 SHA-256" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-CHACHA20-POLY1305-SHA256 & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - CHACHA20-POLY1305 SHA-256" + do_cleanup + exit 1 +fi +echo "" + +./examples/client/client -v 4 -e 2>&1 | grep -- '-CCM' +if [ $? -eq 0 ]; then + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM SHA-256" + do_cleanup + exit 1 + fi + echo "" + + # TLS 1.3 cipher suites server / client. + echo -e "\n\nOnly TLS v1.3 cipher suite - AES128-CCM-8 SHA-256" + port=0 + ./examples/server/server -v 4 -R $ready_file -p $port -l TLS13-AES128-CCM-8-SHA256 & + server_pid=$! + create_port + ./examples/client/client -v 4 -p $port + RESULT=$? + remove_ready_file + if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 cipher suites - AES128-CCM-8 SHA-256" + do_cleanup + exit 1 + fi + echo "" +fi + +# TLS 1.3 server / TLS 1.2 client. +echo -e "\n\nTLS v1.3 server downgrading to TLS v1.2" +port=0 +./examples/server/server -v 4 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 3 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 server downgrading to TLS v1.2" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.2 server / TLS 1.3 client. +echo -e "\n\nTLS v1.3 client downgrading to TLS v1.2" +port=0 +./examples/server/server -v 3 -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 client downgrading to TLS v1.2" + do_cleanup + exit 1 +fi +echo "" + +# TLS 1.3 server / TLS 1.3 client send KeyUpdate before sending app data. +echo -e "\n\nTLS v1.3 KeyUpdate" +port=0 +./examples/server/server -v 4 -U -R $ready_file -p $port & +server_pid=$! +create_port +./examples/client/client -v 4 -I -p $port +RESULT=$? +remove_ready_file +if [ $RESULT -ne 0 ]; then + echo -e "\n\nIssue with TLS v1.3 KeyUpdate" + do_cleanup + exit 1 +fi +echo "" + +echo -e "\nALL Tests Passed" + +exit 0 + diff --git a/src/bio.c b/src/bio.c new file mode 100644 index 000000000..aa02a9ada --- /dev/null +++ b/src/bio.c @@ -0,0 +1,446 @@ +/* bio.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg) +{ + (void)bio; + (void)cmd; + (void)larg; + (void)parg; + + WOLFSSL_ENTER("BIO_ctrl"); + return 1; +} + + +/* Return the number of pending bytes in read and write buffers */ +size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("BIO_ctrl_pending"); + if (bio == NULL) { + return 0; + } + + if (bio->ssl != NULL) { + return (long)wolfSSL_pending(bio->ssl); + } + + if (bio->type == BIO_MEMORY) { + return bio->memLen; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) { + /* in wrap around state where begining of buffer is being + * overwritten */ + return pair->wrSz - pair->rdIdx + pair->wrIdx; + } + else { + /* simple case where has not wrapped around */ + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr) +{ + WOLFSSL_ENTER("BIO_get_mem_ptr"); + + if (bio == NULL || ptr == NULL) { + return SSL_FAILURE; + } + + *ptr = (WOLFSSL_BUF_MEM*)(bio->mem); + return SSL_SUCCESS; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg) +{ + (void) bp; + (void) cmd; + (void) larg; + (void) iarg; + WOLFSSL_ENTER("BIO_int_ctrl"); + return 0; +} + + +int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); + + if (bio == NULL || bio->type != BIO_BIO || size < 0) { + return SSL_FAILURE; + } + + /* if already in pair then do not change size */ + if (bio->pair != NULL) { + WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing"); + return SSL_FAILURE; + } + + bio->wrSz = (int)size; + if (bio->wrSz < 0) { + WOLFSSL_MSG("Unexpected negative size value"); + return SSL_FAILURE; + } + + if (bio->mem != NULL) { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + } + + bio->mem = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Memory allocation error"); + return SSL_FAILURE; + } + bio->wrIdx = 0; + bio->rdIdx = 0; + + return SSL_SUCCESS; +} + + +/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vise + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. */ +int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) +{ + WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair"); + + if (b1 == NULL || b2 == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + /* both are expected to be of type BIO and not already paired */ + if (b1->type != BIO_BIO || b2->type != BIO_BIO || + b1->pair != NULL || b2->pair != NULL) { + WOLFSSL_MSG("Expected type BIO and not already paired"); + return SSL_FAILURE; + } + + /* set default write size if not already set */ + if (b1->mem == NULL && wolfSSL_BIO_set_write_buf_size(b1, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + if (b2->mem == NULL && wolfSSL_BIO_set_write_buf_size(b2, + WOLFSSL_BIO_SIZE) != SSL_SUCCESS) { + return SSL_FAILURE; + } + + b1->pair = b2; + b2->pair = b1; + + return SSL_SUCCESS; +} + + +int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); + + if (b == NULL) { + return SSL_FAILURE; + } + + b->readRq = 0; + + return SSL_SUCCESS; +} + + +/* Does not advance read index pointer */ +int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) +{ + WOLFSSL_ENTER("wolfSSL_BIO_nread0"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + /* if paired read from pair */ + if (bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + + /* case where have wrapped around write buffer */ + *buf = (char*)pair->mem + pair->rdIdx; + if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) { + return pair->wrSz - pair->rdIdx; + } + else { + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +/* similar to wolfSSL_BIO_nread0 but advances the read index */ +int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nread"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + /* special case if asking to read 0 bytes */ + if (num == 0) { + *buf = (char*)bio->pair->mem + bio->pair->rdIdx; + return 0; + } + + /* get amount able to read and set buffer pointer */ + sz = wolfSSL_BIO_nread0(bio, buf); + if (sz == 0) { + return WOLFSSL_BIO_ERROR; + } + + if (num < sz) { + sz = num; + } + bio->pair->rdIdx += sz; + + /* check if have read to the end of the buffer and need to reset */ + if (bio->pair->rdIdx == bio->pair->wrSz) { + bio->pair->rdIdx = 0; + if (bio->pair->wrIdx == bio->pair->wrSz) { + bio->pair->wrIdx = 0; + } + } + + /* check if read up to write index, if so then reset indexs */ + if (bio->pair->rdIdx == bio->pair->wrIdx) { + bio->pair->rdIdx = 0; + bio->pair->wrIdx = 0; + } + } + + return sz; +} + + +int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nwrite"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + if (bio->pair != NULL) { + if (num == 0) { + *buf = (char*)bio->mem + bio->wrIdx; + return 0; + } + + if (bio->wrIdx < bio->rdIdx) { + /* if wrapped around only write up to read index. In this case + * rdIdx is always greater then wrIdx so sz will not be negative. */ + sz = bio->rdIdx - bio->wrIdx; + } + else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) { + return WOLFSSL_BIO_ERROR; /* no more room to write */ + } + else { + /* write index is past read index so write to end of buffer */ + sz = bio->wrSz - bio->wrIdx; + + if (sz <= 0) { + /* either an error has occured with write index or it is at the + * end of the write buffer. */ + if (bio->rdIdx == 0) { + /* no more room, nothing has been read */ + return WOLFSSL_BIO_ERROR; + } + + bio->wrIdx = 0; + + /* check case where read index is not at 0 */ + if (bio->rdIdx > 0) { + sz = bio->rdIdx; /* can write up to the read index */ + } + else { + sz = bio->wrSz; /* no restriction other then buffer size */ + } + } + } + + if (num < sz) { + sz = num; + } + *buf = (char*)bio->mem + bio->wrIdx; + bio->wrIdx += sz; + + /* if at the end of the buffer and space for wrap around then set + * write index back to 0 */ + if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) { + bio->wrIdx = 0; + } + } + + return sz; +} + + +/* Reset BIO to initial state */ +int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_reset"); + + if (bio == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + /* -1 is consistent failure even for FILE type */ + return WOLFSSL_BIO_ERROR; + } + + switch (bio->type) { + #ifndef NO_FILESYSTEM + case BIO_FILE: + XREWIND(bio->file); + return 0; + #endif + + case BIO_BIO: + bio->rdIdx = 0; + bio->wrIdx = 0; + return 0; + + default: + WOLFSSL_MSG("Unknown BIO type needs added to reset function"); + } + + return WOLFSSL_BIO_ERROR; +} + +#ifndef NO_FILESYSTEM +long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_fp"); + + if (bio == NULL || fp == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + bio->close = (byte)c; + bio->file = fp; + + return SSL_SUCCESS; +} + + +long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); + + if (bio == NULL || fp == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_FILE) { + return SSL_FAILURE; + } + + *fp = bio->file; + + return SSL_SUCCESS; +} + +/* overwrites file */ +int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) +{ + WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); + + if (bio == NULL || name == NULL) { + return SSL_FAILURE; + } + + if (bio->type == BIO_FILE) { + if (bio->file != NULL && bio->close == BIO_CLOSE) { + XFCLOSE(bio->file); + } + + bio->file = XFOPEN(name, "w"); + if (bio->file == NULL) { + return SSL_FAILURE; + } + bio->close = BIO_CLOSE; + + return SSL_SUCCESS; + } + + return SSL_FAILURE; +} + + +int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +{ + WOLFSSL_ENTER("wolfSSL_BIO_seek"); + + if (bio == NULL) { + return -1; + } + + /* offset ofs from begining of file */ + if (bio->type == BIO_FILE && XFSEEK(bio->file, ofs, SEEK_SET) < 0) { + return -1; + } + + return 0; +} +#endif /* NO_FILESYSTEM */ + + +long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return"); + + if (bio != NULL) { + bio->eof = v; + } + + return 0; +} diff --git a/src/crl.c b/src/crl.c old mode 100644 new mode 100755 index 2fbcde08c..40a2c3160 --- a/src/crl.c +++ b/src/crl.c @@ -34,11 +34,6 @@ #include #include -#ifndef NO_FILESYSTEM - #include - #include -#endif - #include #ifdef HAVE_CRL_MONITOR @@ -79,7 +74,8 @@ int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) /* Initialize CRL Entry */ -static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) { WOLFSSL_ENTER("InitCRL_Entry"); @@ -94,6 +90,34 @@ static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) crle->certs = dcrl->certs; /* take ownsership */ dcrl->certs = NULL; crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = XMALLOC(crle->tbsSz, heap, DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->toBeSigned, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; return 0; } @@ -111,6 +135,10 @@ static void FreeCRL_Entry(CRL_Entry* crle, void* heap) XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); tmp = next; } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); (void)heap; } @@ -154,15 +182,12 @@ void FreeCRL(WOLFSSL_CRL* crl, int dynamic) } -/* Is the cert ok with CRL, return 0 on success */ -int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) { CRL_Entry* crle; int foundEntry = 0; int ret = 0; - WOLFSSL_ENTER("CheckCertCRL"); - if (wc_LockMutex(&crl->crlLock) != 0) { WOLFSSL_MSG("wc_LockMutex failed"); return BAD_MUTEX_E; @@ -175,6 +200,95 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) int doNextDate = 1; WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca; + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyId[KEYID_SIZE] + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs = NULL; + word32 tbsSz = crle->tbsSz; + byte* sig = NULL; + word32 sigSz = crle->signatureSz; + word32 sigOID = crle->signatureOID; + SignatureCtx sigCtx; + + tbs = XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (tbs == NULL) { + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + sig = XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (sig == NULL) { + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + + XMEMCPY(tbs, crle->toBeSigned, tbsSz); + XMEMCPY(sig, crle->signature, sigSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + XMEMCMPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, + sigOID, ca, crl->heap); + + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, + CRL_DIGEST_SIZE) == 0) { + + if (ret == 0) + crle->verified = 1; + else + crle->verified = ret; + + XFREE(crle->toBeSigned, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->toBeSigned = NULL; + XFREE(crle->signature, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->signature = NULL; + break; + } + crle = crle->next; + } + if (crle == NULL || crle->verified < 0) + break; + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + WOLFSSL_MSG("Checking next date validity"); #ifdef WOLFSSL_NO_CRL_NEXT_DATE @@ -182,13 +296,17 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) doNextDate = 0; /* skip */ #endif - if (doNextDate && !ValidateDate(crle->nextDate, - crle->nextDateFormat, AFTER)) { - WOLFSSL_MSG("CRL next date is no longer valid"); - ret = ASN_AFTER_DATE_E; + if (doNextDate) { + #ifndef NO_ASN_TIME + if (!ValidateDate(crle->nextDate,crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + #endif } - else + if (ret == 0) { foundEntry = 1; + } break; } crle = crle->next; @@ -209,9 +327,39 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) wc_UnLockMutex(&crl->crlLock); + *pFoundEntry = foundEntry; + + return ret; +} + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + ret = CheckCertCRLList(crl, cert, &foundEntry); + +#ifdef HAVE_CRL_IO + if (foundEntry == 0) { + /* perform embedded lookup */ + if (crl->crlIOCb) { + ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, + cert->extCrlInfoSz); + if (ret >= 0) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif + if (foundEntry == 0) { WOLFSSL_MSG("Couldn't find CRL for status check"); ret = CRL_MISSING; + if (crl->cm->cbMissingCRL) { char url[256]; @@ -224,17 +372,18 @@ int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) else { WOLFSSL_MSG("CRL url too long"); } + crl->cm->cbMissingCRL(url); } } - return ret; } /* Add Decoded CRL, 0 on success */ -static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) { CRL_Entry* crle; @@ -246,7 +395,7 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) return -1; } - if (InitCRL_Entry(crle, dcrl) < 0) { + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { WOLFSSL_MSG("Init CRL Entry failed"); XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); return -1; @@ -267,7 +416,8 @@ static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl) /* Load CRL File of type, SSL_SUCCESS on ok */ -int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, + int noVerify) { int ret = SSL_SUCCESS; const byte* myBuffer = buff; /* if DER ok, otherwise switch */ @@ -310,11 +460,11 @@ int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type) InitDecodedCRL(dcrl, crl->heap); ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); - if (ret != 0) { + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) { WOLFSSL_MSG("ParseCRL error"); } else { - ret = AddCRL(crl, dcrl); + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); if (ret != 0) { WOLFSSL_MSG("AddCRL error"); } @@ -790,74 +940,61 @@ static int StartMonitorCRL(WOLFSSL_CRL* crl) #endif /* HAVE_CRL_MONITOR */ -#ifndef NO_FILESYSTEM +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) /* Load CRL path files of type, SSL_SUCCESS on ok */ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) { - struct dirent* entry; - DIR* dir; - int ret = SSL_SUCCESS; + int ret = SSL_SUCCESS; + char* name = NULL; #ifdef WOLFSSL_SMALL_STACK - char* name; + ReadDirCtx* readCtx = NULL; #else - char name[MAX_FILENAME_SZ]; + ReadDirCtx readCtx[1]; #endif WOLFSSL_ENTER("LoadCRL"); if (crl == NULL) return BAD_FUNC_ARG; - dir = opendir(path); - if (dir == NULL) { - WOLFSSL_MSG("opendir path crl load failed"); - return BAD_PATH_ERROR; - } - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) return MEMORY_E; #endif - while ( (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - continue; - } - if (s.st_mode & S_IFREG) { - - if (type == SSL_FILETYPE_PEM) { - if (XSTRSTR(entry->d_name, ".pem") == NULL) { - WOLFSSL_MSG("not .pem file, skipping"); - continue; - } - } - else { - if (XSTRSTR(entry->d_name, ".der") == NULL && - XSTRSTR(entry->d_name, ".crl") == NULL) { - - WOLFSSL_MSG("not .der or .crl file, skipping"); - continue; - } - } - - if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) - != SSL_SUCCESS) { - WOLFSSL_MSG("CRL file load failed, continuing"); + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + int skip = 0; + if (type == SSL_FILETYPE_PEM) { + if (XSTRSTR(name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + skip = 1; } } + else { + if (XSTRSTR(name, ".der") == NULL && + XSTRSTR(name, ".crl") == NULL) + { + WOLFSSL_MSG("not .der or .crl file, skipping"); + skip = 1; + } + } + + if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) + != SSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); + } + + ret = wc_ReadDirNext(readCtx, path, &name); } + wc_ReadDirClose(readCtx); + ret = SSL_SUCCESS; /* load failures not reported, for backwards compat */ #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (monitor & WOLFSSL_CRL_MONITOR) { @@ -873,9 +1010,19 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) pathBuf[pathLen] = '\0'; /* Null Terminate */ if (type == SSL_FILETYPE_PEM) { + /* free old path before setting a new one */ + if (crl->monitors[0].path) { + XFREE(crl->monitors[0].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } crl->monitors[0].path = pathBuf; crl->monitors[0].type = SSL_FILETYPE_PEM; } else { + /* free old path before setting a new one */ + if (crl->monitors[1].path) { + XFREE(crl->monitors[1].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } crl->monitors[1].path = pathBuf; crl->monitors[1].type = SSL_FILETYPE_ASN1; } @@ -891,12 +1038,21 @@ int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) } } - closedir(dir); - return ret; } -#endif /* NO_FILESYSTEM */ +#else +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + (void)crl; + (void)path; + (void)type; + (void)monitor; + + /* stub for scenario where file system is not supported */ + return NOT_COMPILED_IN; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ #endif /* HAVE_CRL */ #endif /* !WOLFCRYPT_ONLY */ diff --git a/src/include.am b/src/include.am index 82be0c1a0..b8dd4951d 100644 --- a/src/include.am +++ b/src/include.am @@ -120,7 +120,8 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/wc_encrypt.c \ wolfcrypt/src/wc_port.c \ wolfcrypt/src/error.c \ - wolfcrypt/src/signature.c + wolfcrypt/src/signature.c \ + wolfcrypt/src/wolfmath.c if BUILD_MEMORY src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c @@ -261,7 +262,8 @@ src_libwolfssl_la_SOURCES += \ src/io.c \ src/keys.c \ src/ssl.c \ - src/tls.c + src/tls.c \ + src/tls13.c if BUILD_OCSP src_libwolfssl_la_SOURCES += src/ocsp.c diff --git a/src/internal.c b/src/internal.c old mode 100644 new mode 100755 index efce9c491..d88716f46 --- a/src/internal.c +++ b/src/internal.c @@ -65,12 +65,6 @@ #include #endif -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } @@ -91,7 +85,6 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_CLIENT static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*, word32); - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*, word32); #ifndef NO_CERTS @@ -106,14 +99,10 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #ifndef NO_WOLFSSL_SERVER - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, word32); static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32); #if !defined(NO_RSA) || defined(HAVE_ECC) static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); #endif - #ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl); - #endif #ifdef WOLFSSL_DTLS static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); #endif /* WOLFSSL_DTLS */ @@ -126,15 +115,34 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #endif -typedef enum { +enum processReply { doProcessInit = 0, #ifndef NO_WOLFSSL_SERVER runProcessOldClientHello, #endif getRecordLayerHeader, getData, + decryptMessage, + verifyMessage, runProcessingOneMessage -} processReply; +}; + +/* sub-states for build message */ +enum buildMsgState { + BUILD_MSG_BEGIN = 0, + BUILD_MSG_SIZE, + BUILD_MSG_HASH, + BUILD_MSG_VERIFY_MAC, + BUILD_MSG_ENCRYPT, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + #ifndef NO_OLD_TLS static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, @@ -142,24 +150,10 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, #endif -#ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); -#endif - #ifdef HAVE_QSH int QSH_Init(WOLFSSL* ssl); #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - int IsTLS(const WOLFSSL* ssl) { @@ -180,6 +174,11 @@ int IsAtLeastTLSv1_2(const WOLFSSL* ssl) return 0; } +int IsAtLeastTLSv1_3(const ProtocolVersion pv) +{ + return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); +} + static INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) { @@ -345,7 +344,8 @@ static INLINE void c16toa(word16 u16, byte* c) #if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT) + || defined(HAVE_AESGCM) || defined(WOLFSSL_SESSION_EXPORT) \ + || defined(WOLFSSL_DTLS) || defined(HAVE_SESSION_TICKET) /* convert 32 bit integer to opaque */ static INLINE void c32toa(word32 u32, byte* c) { @@ -869,9 +869,15 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) #ifdef HAVE_SESSION_TICKET exp[idx++] = options->createTicket; exp[idx++] = options->useTicket; +#ifdef WOLFSSL_TLS13 + exp[idx++] = options->noTicketTls13; +#endif #else exp[idx++] = 0; exp[idx++] = 0; +#ifdef WOLFSSL_TLS13 + exp[idx++] = 0; +#endif #endif exp[idx++] = options->processReply; exp[idx++] = options->cipherSuite0; @@ -883,7 +889,7 @@ static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) exp[idx++] = options->minDowngrade; exp[idx++] = options->connectState; exp[idx++] = options->acceptState; - exp[idx++] = options->keyShareState; + exp[idx++] = options->asyncState; /* version of connection */ exp[idx++] = ssl->version.major; @@ -988,11 +994,17 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) idx++; #endif #ifdef HAVE_SESSION_TICKET - options->createTicket = exp[idx++]; /* Server to create new Ticket */ - options->useTicket = exp[idx++]; /* Use Ticket not session cache */ + options->createTicket = exp[idx++]; /* Server to create new Ticket */ + options->useTicket = exp[idx++]; /* Use Ticket not session cache */ +#ifdef WOLFSSL_TLS13 + options->noTicketTls13 = exp[idx++]; /* Server won't create new Ticket */ +#endif #else idx++; idx++; +#ifdef WOLFSSL_TLS13 + idx++; +#endif #endif options->processReply = exp[idx++]; options->cipherSuite0 = exp[idx++]; @@ -1004,7 +1016,7 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) options->minDowngrade = exp[idx++]; options->connectState = exp[idx++]; options->acceptState = exp[idx++]; - options->keyShareState = exp[idx++]; + options->asyncState = exp[idx++]; /* version of connection */ if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { @@ -1078,12 +1090,12 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) /* import ip address idx, and ipSz are unsigned but cast for enum */ ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN; - if (ipSz > sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { + if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { return BUFFER_E; } XMEMSET(ip, 0, sizeof(ip)); XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; - ip[ipSz] = '\0'; + ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */ ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; /* sanity check for a function to call, then use it to import peer info */ @@ -1402,6 +1414,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) WOLFSSL_MSG("Bad Cert Manager New"); return BAD_CERT_MANAGER_ERROR; } + #ifdef OPENSSL_EXTRA + /* setup WOLFSSL_X509_STORE */ + ctx->x509_store.cm = ctx->cm; + #endif #endif #if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) @@ -1435,9 +1451,9 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) /* In case contexts are held in array and don't want to free actual ctx */ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 int i; - - (void)i; +#endif #ifdef HAVE_WOLF_EVENT wolfEventQueue_Free(&ctx->event_queue); @@ -1448,35 +1464,51 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); #ifndef NO_DH - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); -#endif + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); +#endif /* !NO_DH */ #ifdef SINGLE_THREADED if (ctx->rng) { wc_FreeRng(ctx->rng); XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG); } -#endif +#endif /* SINGLE_THREADED */ #ifndef NO_CERTS FreeDer(&ctx->privateKey); FreeDer(&ctx->certificate); #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); - if (ctx->ourCert) { + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); } - #endif + #endif /* KEEP_OUR_CERT */ FreeDer(&ctx->certChain); wolfSSL_CertManagerFree(ctx->cm); -#endif + #ifdef OPENSSL_EXTRA + while (ctx->ca_names != NULL) { + WOLFSSL_STACK *next = ctx->ca_names->next; + wolfSSL_X509_NAME_free(ctx->ca_names->data.name); + XFREE(ctx->ca_names->data.name, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + while (ctx->x509Chain != NULL) { + WOLFSSL_STACK *next = ctx->x509Chain->next; + wolfSSL_X509_free(ctx->x509Chain->data.x509); + XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->x509Chain = next; + } + #endif +#endif /* !NO_CERTS */ #ifdef HAVE_TLS_EXTENSIONS TLSX_FreeAll(ctx->extensions, ctx->heap); #ifndef NO_WOLFSSL_SERVER - #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (ctx->certOcspRequest) { @@ -1485,29 +1517,28 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) } #endif -#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 for (i = 0; i < MAX_CHAIN_DEPTH; i++) { if (ctx->chainOcspRequest[i]) { FreeOcspRequest(ctx->chainOcspRequest[i]); XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); } } -#endif - -#endif /* NO_WOLFSSL_SERVER */ +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* !NO_WOLFSSL_SERVER */ #endif /* HAVE_TLS_EXTENSIONS */ + #ifdef WOLFSSL_STATIC_MEMORY if (ctx->heap != NULL) { #ifdef WOLFSSL_HEAP_TEST /* avoid derefrencing a test value */ - if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) { + if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) #endif - WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); - wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); -#ifdef WOLFSSL_HEAP_TEST + { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); + wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); } -#endif } #endif /* WOLFSSL_STATIC_MEMORY */ } @@ -1597,31 +1628,25 @@ void FreeCiphers(WOLFSSL* ssl) { (void)ssl; #ifdef BUILD_ARC4 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Arc4AsyncFree(ssl->encrypt.arc4); - wc_Arc4AsyncFree(ssl->decrypt.arc4); - } - #endif + wc_Arc4Free(ssl->encrypt.arc4); + wc_Arc4Free(ssl->decrypt.arc4); XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_DES3 - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_Des3AsyncFree(ssl->encrypt.des3); - wc_Des3AsyncFree(ssl->decrypt.des3); - } - #endif + wc_Des3Free(ssl->encrypt.des3); + wc_Des3Free(ssl->decrypt.des3); XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_AES - #ifdef WOLFSSL_ASYNC_CRYPT - if (ssl->devId != INVALID_DEVID) { - wc_AesAsyncFree(ssl->encrypt.aes); - wc_AesAsyncFree(ssl->decrypt.aes); - } + wc_AesFree(ssl->encrypt.aes); + wc_AesFree(ssl->decrypt.aes); + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES); + XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES); #endif XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); @@ -1685,7 +1710,8 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = ecc_dsa_sa_algo; #endif @@ -1704,7 +1730,8 @@ static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, suites->hashSigAlgo[idx++] = sha256_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif - #if !defined(NO_SHA) && !defined(NO_OLD_TLS) + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) suites->hashSigAlgo[idx++] = sha_mac; suites->hashSigAlgo[idx++] = rsa_sa_algo; #endif @@ -1728,6 +1755,9 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, word16 idx = 0; int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; +#ifdef WOLFSSL_TLS13 + int tls1_3 = IsAtLeastTLSv1_3(pv); +#endif int dtls = 0; int haveRSAsig = 1; @@ -1811,6 +1841,43 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif +#ifdef WOLFSSL_TLS13 +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256; + } +#endif +#endif /* WOLFSSL_TLS13 */ + #ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 if (tls1_2 && haveECC) { suites->suites[idx++] = ECC_BYTE; @@ -1955,7 +2022,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -1983,7 +2050,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - if (tls1_2 && haveRSAsig) { + if (tls1_2 && haveRSA) { suites->suites[idx++] = ECC_BYTE; suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; } @@ -2158,14 +2225,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveDH && haveRSA) { + if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; } @@ -2196,14 +2263,14 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, #endif #ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; } #endif #ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 - if (tls1_2 && haveRSA) { + if (tls && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256; } @@ -2504,7 +2571,7 @@ void InitSuites(Suites* suites, ProtocolVersion pv, word16 haveRSA, } #endif -#ifdef BUILD_TLS_DHE_WITH_RSA_CAMELLIA_256_CBC_SHA +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA if (tls && haveDH && haveRSA) { suites->suites[idx++] = 0; suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA; @@ -2589,6 +2656,13 @@ void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap) /* Initialize wolfSSL X509 type */ void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap) { + if (x509 == NULL) { + WOLFSSL_MSG("Null parameter passed in!"); + return; + } + + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + x509->heap = heap; InitX509Name(&x509->issuer, 0); InitX509Name(&x509->subject, 0); @@ -2644,6 +2718,12 @@ void FreeX509(WOLFSSL_X509* x509) #ifdef OPENSSL_EXTRA XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); + } + if (x509->extKeyUsageSrc != NULL) { + XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + } #endif /* OPENSSL_EXTRA */ if (x509->altNames) FreeAltNames(x509->altNames, NULL); @@ -2678,11 +2758,7 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2697,8 +2773,9 @@ int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, return ret; } -int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, - byte** out, RsaKey* key, const byte* keyBuf, word32 keySz, void* ctx) +int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, + int hashAlgo, RsaKey* key, const byte* keyBuf, word32 keySz, + void* ctx) { int ret; @@ -2706,6 +2783,8 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, (void)keyBuf; (void)keySz; (void)ctx; + (void)sigAlgo; + (void)hashAlgo; WOLFSSL_ENTER("RsaVerify"); @@ -2716,17 +2795,43 @@ int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, else #endif /*HAVE_PK_CALLBACKS */ { - ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); +#ifdef WOLFSSL_TLS13 + #ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + switch (hashAlgo) { + case sha512_mac: + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + mgf = WC_MGF1SHA512; + #endif + break; + case sha384_mac: + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + mgf = WC_MGF1SHA384; + #endif + break; + case sha256_mac: + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + mgf = WC_MGF1SHA256; + #endif + break; + } + ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); + } + else + #endif +#endif + ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2770,11 +2875,7 @@ int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2814,11 +2915,7 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2859,11 +2956,7 @@ int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2908,11 +3001,7 @@ int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -2925,7 +3014,7 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, word32 outSz, ecc_key* key, byte* keyBuf, word32 keySz, void* ctx) { - int ret, verify; + int ret; (void)ssl; (void)keyBuf; @@ -2937,27 +3026,23 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccVerifyCb) { ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, - &verify, ctx); + &ssl->eccVerifyRes, ctx); } else #endif /* HAVE_PK_CALLBACKS */ { - ret = wc_ecc_verify_hash(in, inSz, out, outSz, &verify, key); + ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key); } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); } else #endif /* WOLFSSL_ASYNC_CRYPT */ { - ret = (ret != 0 || verify == 0) ? VERIFY_SIGN_ERROR : 0; + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; } WOLFSSL_LEAVE("EccVerify", ret); @@ -2997,10 +3082,10 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, } else if (ssl->options.side == WOLFSSL_SERVER_END) { if (ssl->specs.static_ecdh) { - if (ssl->sigKey == NULL) { + if (ssl->hsKey == NULL) { return NO_PRIVATE_KEY; } - tmpKey = (struct ecc_key*)ssl->sigKey; + tmpKey = (struct ecc_key*)ssl->hsKey; } else { if (!ssl->eccTempKeyPresent) { @@ -3052,11 +3137,8 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &priv_key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3079,17 +3161,20 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) keySz = peer->dp->size; } - /* TODO: Implement _ex version here */ - ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ssl->ecdhCurveOID > 0) { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, + wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); + } + else { + ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ret == 0) + ssl->ecdhCurveOID = key->dp->oidSum; + } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) if (ret == WC_PENDING_E) { - ret = wolfAsync_EventInit(&ssl->event, - WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = WC_PENDING_E; - } + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -3105,60 +3190,67 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) #if !defined(NO_CERTS) || !defined(NO_PSK) #if !defined(NO_DH) -int DhGenKeyPair(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, +int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0) { - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); + WOLFSSL_ENTER("DhGenKeyPair"); + + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz); + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhGenKeyPair", ret); return ret; } -int DhAgree(WOLFSSL* ssl, - byte* p, word32 pSz, - byte* g, word32 gSz, - byte* priv, word32* privSz, - byte* pub, word32* pubSz, +int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, byte* agree, word32* agreeSz) { int ret; - DhKey dhKey; - wc_InitDhKey(&dhKey); - ret = wc_DhSetKey(&dhKey, p, pSz, g, gSz); - if (ret == 0 && pub) { - /* for DH, encSecret is Yc, agree is pre-master */ - ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, priv, privSz, pub, pubSz); + (void)ssl; + + WOLFSSL_ENTER("DhAgree"); + + ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub, otherPubSz); + + /* Handle async pending response */ +#if defined(WOLFSSL_ASYNC_CRYPT) + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); } - if (ret == 0) { - ret = wc_DhAgree(&dhKey, agree, agreeSz, priv, *privSz, otherPub, otherPubSz); - } - wc_FreeDhKey(&dhKey); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhAgree", ret); return ret; } - #endif /* !NO_DH */ #endif /* !NO_CERTS || !NO_PSK */ - /* This function inherits a WOLFSSL_CTX's fields into an SSL object. It is used during initialization and to switch an ssl's CTX with wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK + unless writeDup is on. + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + SSL_SUCCESS return value on success */ -int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { byte havePSK = 0; byte haveAnon = 0; @@ -3166,13 +3258,16 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) byte haveRSA = 0; (void) haveAnon; /* Squash unused var warnings */ - if(!ssl || !ctx || ssl->suites == NULL) + if (!ssl || !ctx) + return BAD_FUNC_ARG; + + if (ssl->suites == NULL && !writeDup) return BAD_FUNC_ARG; newSSL = ssl->ctx == NULL; /* Assign after null check */ #ifndef NO_PSK - if (ctx->server_hint[0] && ssl->arrays == NULL) { + if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) { return BAD_FUNC_ARG; /* needed for copy below */ } #endif @@ -3208,17 +3303,19 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ECC ssl->eccTempKeySz = ctx->eccTempKeySz; ssl->pkCurveOID = ctx->pkCurveOID; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; #endif +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; +#endif ssl->timeout = ctx->timeout; ssl->verifyCallback = ctx->verifyCallback; ssl->options.side = ctx->method->side; ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.haveDH = ctx->haveDH; - + ssl->options.haveDH = ctx->haveDH; ssl->options.haveNTRU = ctx->haveNTRU; ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; @@ -3245,6 +3342,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.sessionCacheOff = ctx->sessionCacheOff; ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + ssl->options.internalCacheOff = ctx->internalCacheOff; +#endif ssl->options.verifyPeer = ctx->verifyPeer; ssl->options.verifyNone = ctx->verifyNone; @@ -3257,16 +3357,17 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.groupMessages = ctx->groupMessages; #ifndef NO_DH - if (ssl->options.side == WOLFSSL_SERVER_END) { - ssl->buffers.serverDH_P = ctx->serverDH_P; - ssl->buffers.serverDH_G = ctx->serverDH_G; - } + ssl->buffers.serverDH_P = ctx->serverDH_P; + ssl->buffers.serverDH_G = ctx->serverDH_G; #endif #ifndef NO_CERTS /* ctx still owns certificate, certChain, key, dh, and cm */ ssl->buffers.certificate = ctx->certificate; ssl->buffers.certChain = ctx->certChain; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif ssl->buffers.key = ctx->privateKey; #endif @@ -3274,55 +3375,144 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->devId = ctx->devId; #endif + if (writeDup == 0) { + #ifndef NO_PSK - if (ctx->server_hint[0]) { /* set in CTX */ - XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; - } + if (ctx->server_hint[0]) { /* set in CTX */ + XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ + } #endif /* NO_PSK */ - if (ctx->suites) - *ssl->suites = *ctx->suites; - else - XMEMSET(ssl->suites, 0, sizeof(Suites)); + if (ctx->suites) + *ssl->suites = *ctx->suites; + else + XMEMSET(ssl->suites, 0, sizeof(Suites)); - /* make sure server has DH parms, and add PSK if there, add NTRU too */ - if (ssl->options.side == WOLFSSL_SERVER_END) - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + /* make sure server has DH parms, and add PSK if there, add NTRU too */ + if (ssl->options.side == WOLFSSL_SERVER_END) + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, ssl->options.haveDH, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); - else - InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, + else + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, TRUE, ssl->options.haveNTRU, ssl->options.haveECDSAsig, ssl->options.haveECC, ssl->options.haveStaticECC, ssl->options.side); #if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) - /* make sure server has cert and key unless using PSK or Anon - * This should be true even if just switching ssl ctx */ - if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) - if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer || - !ssl->buffers.key || !ssl->buffers.key->buffer) { - WOLFSSL_MSG("Server missing certificate and/or private key"); - return NO_PRIVATE_KEY; - } + /* make sure server has cert and key unless using PSK or Anon + * This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && !havePSK && !haveAnon) + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer + || !ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing certificate and/or private key"); + return NO_PRIVATE_KEY; + } #endif + } /* writeDup check */ + #ifdef WOLFSSL_SESSION_EXPORT #ifdef WOLFSSL_DTLS ssl->dtls_export = ctx->dtls_export; /* export function for session */ #endif #endif +#ifdef OPENSSL_EXTRA + ssl->readAhead = ctx->readAhead; +#endif + return SSL_SUCCESS; } +int InitHandshakeHashes(WOLFSSL* ssl) +{ + int ret; + + /* make sure existing handshake hashes are free'd */ + if (ssl->hsHashes != NULL) { + FreeHandshakeHashes(ssl); + } + + /* allocate handshake hashes */ + ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, + DYNAMIC_TYPE_HASHES); + if (ssl->hsHashes == NULL) { + WOLFSSL_MSG("HS_Hashes Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifndef NO_SHA + ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#endif /* !NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId); + if (ret != 0) + return ret; +#endif + + return ret; +} + +void FreeHandshakeHashes(WOLFSSL* ssl) +{ + if (ssl->hsHashes) { +#ifndef NO_OLD_TLS + #ifndef NO_MD5 + wc_Md5Free(&ssl->hsHashes->hashMd5); + #endif + #ifndef NO_SHA + wc_ShaFree(&ssl->hsHashes->hashSha); + #endif +#endif /* !NO_OLD_TLS */ + #ifndef NO_SHA256 + wc_Sha256Free(&ssl->hsHashes->hashSha256); + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384Free(&ssl->hsHashes->hashSha384); + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512Free(&ssl->hsHashes->hashSha512); + #endif + + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + } +} + /* init everything to 0, NULL, default values before calling anything that may fail so that destructor has a "good" state to cleanup + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + 0 on success */ -int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) { int ret; @@ -3433,6 +3623,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->rfd = -1; /* set to invalid descriptor */ ssl->wfd = -1; + ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */ ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ @@ -3442,12 +3633,17 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ #endif + /* initialize states */ ssl->options.serverState = NULL_STATE; ssl->options.clientState = NULL_STATE; ssl->options.connectState = CONNECT_BEGIN; ssl->options.acceptState = ACCEPT_BEGIN; ssl->options.handShakeState = NULL_STATE; ssl->options.processReply = doProcessInit; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + ssl->encrypt.state = CIPHER_STATE_BEGIN; + ssl->decrypt.state = CIPHER_STATE_BEGIN; #ifdef WOLFSSL_DTLS #ifdef WOLFSSL_SCTP @@ -3476,6 +3672,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_EXTENDED_MASTER ssl->options.haveEMS = ctx->haveEMS; #endif + ssl->options.useClientOrder = ctx->useClientOrder; + +#ifdef WOLFSSL_TLS13 +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = ctx->noTicketTls13; +#endif + ssl->options.noPskDheKe = ctx->noPskDheKe; +#endif #ifdef HAVE_TLS_EXTENSIONS #ifdef HAVE_MAX_FRAGMENT @@ -3483,6 +3687,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif #ifdef HAVE_ALPN ssl->alpn_client_list = NULL; + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + ssl->alpnSelect = ctx->alpnSelect; + ssl->alpnSelectArg = ctx->alpnSelectArg; + #endif +#endif +#ifdef HAVE_SUPPORTED_CURVES + ssl->options.userCurves = ctx->userCurves; #endif #endif /* HAVE_TLS_EXTENSIONS */ @@ -3497,68 +3708,38 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* all done with init, now can return errors, call other stuff */ - /* arrays */ - ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, + if (!writeDup) { + /* arrays */ + ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, DYNAMIC_TYPE_ARRAYS); - if (ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays Memory error"); - return MEMORY_E; - } - XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (ssl->arrays->preMasterSecret == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); - /* suites */ - ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + /* suites */ + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, DYNAMIC_TYPE_SUITES); - if (ssl->suites == NULL) { - WOLFSSL_MSG("Suites Memory error"); - return MEMORY_E; + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } } /* Initialize SSL with the appropriate fields from it's ctx */ - /* requires valid arrays and suites */ - if((ret = SetSSL_CTX(ssl, ctx)) != SSL_SUCCESS) + /* requires valid arrays and suites unless writeDup ing */ + if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != SSL_SUCCESS) return ret; ssl->options.dtls = ssl->version.major == DTLS_MAJOR; - /* hsHashes */ - ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, - DYNAMIC_TYPE_HASHES); - if (ssl->hsHashes == NULL) { - WOLFSSL_MSG("HS_Hashes Memory error"); - return MEMORY_E; - } - -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); - if (ret != 0) { - return ret; - } -#endif -#endif -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret != 0) { - return ret; - } -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); - if (ret != 0) { - return ret; - } -#endif - #ifdef SINGLE_THREADED ssl->rng = ctx->rng; /* CTX may have one, if so use it */ #endif @@ -3570,11 +3751,12 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) WOLFSSL_MSG("RNG Memory error"); return MEMORY_E; } + XMEMSET(ssl->rng, 0, sizeof(WC_RNG)); ssl->options.weOwnRng = 1; /* FIPS RNG API does not accept a heap hint */ #ifndef HAVE_FIPS - if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap)) != 0) { + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { WOLFSSL_MSG("RNG Init error"); return ret; } @@ -3586,6 +3768,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif } + if (writeDup) { + /* all done */ + return 0; + } + + /* hsHashes */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + #if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); @@ -3611,12 +3803,16 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) /* free use of temporary arrays */ void FreeArrays(WOLFSSL* ssl, int keep) { - if (ssl->arrays && keep) { - /* keeps session id for user retrieval */ - XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); - ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; - } if (ssl->arrays) { + if (keep) { + /* keeps session id for user retrieval */ + XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + } + if (ssl->arrays->preMasterSecret) { + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->arrays->preMasterSecret = NULL; + } XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); ssl->arrays->pendingMsg = NULL; ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ @@ -3625,7 +3821,111 @@ void FreeArrays(WOLFSSL* ssl, int keep) ssl->arrays = NULL; } -static void FreeKeyExchange(WOLFSSL* ssl) +void FreeKey(WOLFSSL* ssl, int type, void** pKey) +{ + if (ssl && pKey && *pKey) { + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)*pKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)*pKey); + break; + #endif /* HAVE_ECC */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)*pKey); + break; + #endif /* !NO_DH */ + default: + break; + } + XFREE(*pKey, ssl->heap, type); + + /* Reset pointer */ + *pKey = NULL; + } +} + +int AllocKey(WOLFSSL* ssl, int type, void** pKey) +{ + int ret = BAD_FUNC_ARG; + int sz = 0; + + if (ssl == NULL || pKey == NULL) { + return BAD_FUNC_ARG; + } + + /* Sanity check key destination */ + if (*pKey != NULL) { + WOLFSSL_MSG("Key already present!"); + return BAD_STATE_E; + } + + /* Determine size */ + switch (type) { + case DYNAMIC_TYPE_RSA: + #ifndef NO_RSA + sz = sizeof(RsaKey); + #endif /* ! NO_RSA */ + break; + case DYNAMIC_TYPE_ECC: + #ifdef HAVE_ECC + sz = sizeof(ecc_key); + #endif /* HAVE_ECC */ + break; + case DYNAMIC_TYPE_DH: + #ifndef NO_DH + sz = sizeof(DhKey); + #endif /* !NO_DH */ + break; + default: + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return NOT_COMPILED_IN; + } + + /* Allocate memeory for key */ + *pKey = XMALLOC(sz, ssl->heap, type); + if (*pKey == NULL) { + return MEMORY_E; + } + + /* Initialize key */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + /* On error free handshake key */ + if (ret != 0) { + FreeKey(ssl, type, pKey); + } + + return ret; +} + +void FreeKeyExchange(WOLFSSL* ssl) { /* Cleanup signature buffer */ if (ssl->buffers.sig.buffer) { @@ -3641,33 +3941,21 @@ static void FreeKeyExchange(WOLFSSL* ssl) ssl->buffers.digest.length = 0; } - /* Free sigKey */ - if (ssl->sigKey) { - switch (ssl->sigType) - { - #ifndef NO_RSA - case DYNAMIC_TYPE_RSA: - { - wc_FreeRsaKey((RsaKey*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); - break; - } - #endif /* ! NO_RSA */ - #ifdef HAVE_ECC - case DYNAMIC_TYPE_ECC: - { - wc_ecc_free((ecc_key*)ssl->sigKey); - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_ECC); - break; - } - #endif /* HAVE_ECC */ - default: - break; - } - /* Reset type and pointer */ - ssl->sigType = 0; - ssl->sigKey = NULL; + /* Free handshake key */ + FreeKey(ssl, ssl->hsType, &ssl->hsKey); + +#ifndef NO_DH + /* Free temp DH key */ + FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); +#endif + + /* Cleanup async */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->async.freeArgs) { + ssl->async.freeArgs(ssl, ssl->async.args); + ssl->async.freeArgs = NULL; } +#endif } /* In case holding SSL object in array and don't want to free actual ssl */ @@ -3687,23 +3975,23 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); } XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + FreeHandshakeHashes(ssl); XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); /* clear keys struct after session */ - ForceZero(&(ssl->keys), sizeof(Keys)); + ForceZero(&ssl->keys, sizeof(Keys)); #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); } #endif /* !NO_DH */ #ifndef NO_CERTS @@ -3711,10 +3999,8 @@ void SSL_ResourceFree(WOLFSSL* ssl) wolfSSL_UnloadCertsKeys(ssl); #endif #ifndef NO_RSA - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, FORCED_FREE); @@ -3743,21 +4029,12 @@ void SSL_ResourceFree(WOLFSSL* ssl) FreeStreams(ssl); #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) { - if (ssl->peerEccKeyPresent) - wc_ecc_free(ssl->peerEccKey); - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - } - if (ssl->peerEccDsaKey) { - if (ssl->peerEccDsaKeyPresent) - wc_ecc_free(ssl->peerEccDsaKey); - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - } - if (ssl->eccTempKey) { - if (ssl->eccTempKeyPresent) - wc_ecc_free(ssl->eccTempKey); - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); - } + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; #endif /* HAVE_ECC */ #ifdef HAVE_PK_CALLBACKS #ifdef HAVE_ECC @@ -3793,6 +4070,14 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); +#endif +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + FreeWriteDup(ssl); + } +#endif #ifdef WOLFSSL_STATIC_MEMORY /* check if using fixed io buffers and free them */ @@ -3835,15 +4120,6 @@ void SSL_ResourceFree(WOLFSSL* ssl) /* Free any handshake resources no longer needed */ void FreeHandshakeResources(WOLFSSL* ssl) { -#ifndef NO_MD5 - wc_Md5Free(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - wc_ShaFree(&ssl->hsHashes->hashSha); -#endif -#ifndef NO_SHA256 - wc_Sha256Free(&ssl->hsHashes->hashSha25); -#endif #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { @@ -3861,8 +4137,7 @@ void FreeHandshakeResources(WOLFSSL* ssl) ssl->suites = NULL; /* hsHashes */ - XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); - ssl->hsHashes = NULL; + FreeHandshakeHashes(ssl); /* RNG */ if (ssl->specs.cipher_type == stream || ssl->options.tls1_1 == 0) { @@ -3890,56 +4165,32 @@ void FreeHandshakeResources(WOLFSSL* ssl) #ifndef NO_RSA /* peerRsaKey */ - if (ssl->peerRsaKey) { - wc_FreeRsaKey(ssl->peerRsaKey); - XFREE(ssl->peerRsaKey, ssl->heap, DYNAMIC_TYPE_RSA); - ssl->peerRsaKey = NULL; - } + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; #endif #ifdef HAVE_ECC - if (ssl->peerEccKey) - { - if (ssl->peerEccKeyPresent) { - wc_ecc_free(ssl->peerEccKey); - ssl->peerEccKeyPresent = 0; - } - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; - } - if (ssl->peerEccDsaKey) - { - if (ssl->peerEccDsaKeyPresent) { - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - } - XFREE(ssl->peerEccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccDsaKey = NULL; - } - if (ssl->eccTempKey) - { - if (ssl->eccTempKeyPresent) { - wc_ecc_free(ssl->eccTempKey); - ssl->eccTempKeyPresent = 0; - } - XFREE(ssl->eccTempKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->eccTempKey = NULL; - } + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; #endif /* HAVE_ECC */ #ifndef NO_DH if (ssl->buffers.serverDH_Priv.buffer) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } - XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_Priv.buffer = NULL; - XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_Pub.buffer = NULL; /* parameters (p,g) may be owned by ctx */ if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) { - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_G.buffer = NULL; - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); ssl->buffers.serverDH_P.buffer = NULL; } #endif /* !NO_DH */ @@ -4008,7 +4259,7 @@ void FreeSSL(WOLFSSL* ssl, void* heap) #if !defined(NO_OLD_TLS) || defined(HAVE_CHACHA) || defined(HAVE_AESCCM) \ - || defined(HAVE_AESGCM) + || defined(HAVE_AESGCM) || defined(WOLFSSL_DTLS) static INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) { if (verify) { @@ -4112,6 +4363,7 @@ DtlsMsg* DtlsMsgNew(word32 sz, void* heap) { DtlsMsg* msg = NULL; + (void)heap; msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); if (msg != NULL) { @@ -4168,6 +4420,7 @@ static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, DtlsFrag* newFrag; word32 added = end - *begin + 1; + (void)heap; newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap, DYNAMIC_TYPE_DTLS_FRAG); if (newFrag != NULL) { @@ -4506,7 +4759,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0); + handshake, 0, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -4730,7 +4983,7 @@ ProtocolVersion MakeDTLSv1_2(void) #ifndef NO_CERTS -static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) { int ret = 0; @@ -4774,7 +5027,7 @@ static int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) /* add output to md5 and sha handshake hashes, exclude record header */ -static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) +int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) { int ret = 0; const byte* adj; @@ -4824,10 +5077,12 @@ static int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) /* add input to md5 and sha handshake hashes, include handshake header */ -static int HashInput(WOLFSSL* ssl, const byte* input, int sz) +int HashInput(WOLFSSL* ssl, const byte* input, int sz) { int ret = 0; - const byte* adj = input - HANDSHAKE_HEADER_SZ; + const byte* adj; + + adj = input - HANDSHAKE_HEADER_SZ; sz += HANDSHAKE_HEADER_SZ; (void)adj; @@ -4839,6 +5094,10 @@ static int HashInput(WOLFSSL* ssl, const byte* input, int sz) } #endif + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + #ifndef NO_OLD_TLS #ifndef NO_SHA wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); @@ -4882,7 +5141,12 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl } rl->type = type; rl->pvMajor = ssl->version.major; /* type and version same in each */ - rl->pvMinor = ssl->version.minor; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + rl->pvMinor = TLSv1_MINOR; + else +#endif + rl->pvMinor = ssl->version.minor; #ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE if (ssl->options.side == WOLFSSL_CLIENT_END @@ -5092,6 +5356,14 @@ int SendBuffered(WOLFSSL* ssl) return SOCKET_ERROR_E; } +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.outputBuffer.idx == 0) { + WOLFSSL_MSG("Data to send"); + WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + } +#endif + while (ssl->buffers.outputBuffer.length > 0) { int sent = ssl->ctx->CBIOSend(ssl, (char*)ssl->buffers.outputBuffer.buffer + @@ -5158,9 +5430,15 @@ int SendBuffered(WOLFSSL* ssl) static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) { byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : RECORD_HEADER_SZ; - byte align = WOLFSSL_GENERAL_ALIGNMENT; + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the header, if the user wants encrypted alignment they need to define their alignment requirement */ @@ -5169,14 +5447,19 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) while (align < hdrSz) align *= 2; } +#endif - tmp = (byte*) XMALLOC(size + ssl->buffers.outputBuffer.length + align, - ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); WOLFSSL_MSG("growing output buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (ssl->buffers.outputBuffer.length) XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, @@ -5187,10 +5470,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); ssl->buffers.outputBuffer.dynamicFlag = 1; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.outputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.outputBuffer.offset = 0; + ssl->buffers.outputBuffer.buffer = tmp; ssl->buffers.outputBuffer.bufferSize = size + ssl->buffers.outputBuffer.length; @@ -5202,8 +5489,14 @@ static INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) { byte* tmp; - byte hdrSz = DTLS_RECORD_HEADER_SZ; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; + byte hdrSz = DTLS_RECORD_HEADER_SZ; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 /* the encrypted data will be offset from the front of the buffer by the dtls record header, if the user wants encrypted alignment they need to define their alignment requirement. in tls we read record header @@ -5213,19 +5506,24 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) while (align < hdrSz) align *= 2; } +#endif if (usedLength < 0 || size < 0) { WOLFSSL_MSG("GrowInputBuffer() called with negative number"); return BAD_FUNC_ARG; } - tmp = (byte*) XMALLOC(size + usedLength + align, ssl->heap, - DYNAMIC_TYPE_IN_BUFFER); + tmp = (byte*)XMALLOC(size + usedLength + align, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); WOLFSSL_MSG("growing input buffer\n"); - if (!tmp) return MEMORY_E; + if (tmp == NULL) + return MEMORY_E; + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) tmp += align - hdrSz; +#endif if (usedLength) XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + @@ -5236,10 +5534,13 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) ssl->heap,DYNAMIC_TYPE_IN_BUFFER); ssl->buffers.inputBuffer.dynamicFlag = 1; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 if (align) ssl->buffers.inputBuffer.offset = align - hdrSz; else +#endif ssl->buffers.inputBuffer.offset = 0; + ssl->buffers.inputBuffer.buffer = tmp; ssl->buffers.inputBuffer.bufferSize = size + usedLength; ssl->buffers.inputBuffer.idx = 0; @@ -5252,7 +5553,6 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) /* check available size into output buffer, make room if needed */ int CheckAvailableSize(WOLFSSL *ssl, int size) { - if (size < 0) { WOLFSSL_MSG("CheckAvailableSize() called with negative number"); return BAD_FUNC_ARG; @@ -5311,8 +5611,41 @@ static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif +#ifdef OPENSSL_EXTRA + /* case where specific protocols are turned off */ + if (!ssl->options.dtls && ssl->options.mask > 0) { + if (rh->pvMinor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("Option set to not allow SSLv3"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("Option set to not allow TLSv1"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("Option set to not allow TLSv1.1"); + return VERSION_ERROR; + } + if (rh->pvMinor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("Option set to not allow TLSv1.2"); + return VERSION_ERROR; + } + } +#endif /* OPENSSL_EXTRA */ + /* catch version mismatch */ - if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor){ +#ifndef WOLFSSL_TLS13 + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) +#else + if (rh->pvMajor != ssl->version.major || + (rh->pvMinor != ssl->version.minor && + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR))) +#endif + { if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) @@ -5392,7 +5725,7 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, *type = input[idx++]; c24to32(input + idx, size); - idx += BYTE3_LEN; + idx += OPAQUE24_LEN; ato16(input + idx, &ssl->keys.dtls_peer_handshake_number); idx += DTLS_HANDSHAKE_SEQ_SZ; @@ -5415,7 +5748,8 @@ static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, #endif -#ifndef NO_OLD_TLS +#if !defined(NO_OLD_TLS) || \ + (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1)) /* fill with MD5 pad size since biggest required */ static const byte PAD1[PAD_MD5] = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, @@ -5433,82 +5767,104 @@ static const byte PAD2[PAD_MD5] = 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c }; +#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */ + +#ifndef NO_OLD_TLS /* calculate MD5 hash for finished */ #ifdef WOLFSSL_TI_HASH #include #endif -static void BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { - + int ret; byte md5_result[MD5_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; #else - Md5 md5[1]; - Md5 md5_2[1]; + Md5 md5[1]; #endif /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - - wc_Md5Update(&ssl->hsHashes->hashMd5, sender, SIZEOF_SENDER); - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); + if (ret == 0) + ret = wc_Md5Update(md5, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - wc_Md5Final(md5_2, hashes->md5); + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, hashes->md5); + wc_Md5Free(md5); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } /* calculate SHA hash for finished */ -static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { + int ret; byte sha_result[SHA_DIGEST_SIZE]; - #ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; #else - Sha sha[1]; - Sha sha2[1] ; + Sha sha[1]; #endif /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - - wc_ShaUpdate(&ssl->hsHashes->hashSha, sender, SIZEOF_SENDER); - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - wc_ShaFinal(sha2, hashes->sha); + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, hashes->sha); + wc_ShaFree(sha); + } + } #ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } #endif @@ -5516,28 +5872,25 @@ static void BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret = 0; +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - #ifdef WOLFSSL_SHA384 - Sha384* sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + Sha384* sha384; #else - #ifdef WOLFSSL_SHA384 - Sha384 sha384[1]; - #endif -#endif + Sha384 sha384[1]; +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SHA384 #ifdef WOLFSSL_SMALL_STACK - if (ssl == NULL - #ifdef WOLFSSL_SHA384 - || sha384 == NULL - #endif - ) { - #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) return MEMORY_E; - } -#endif +#endif /* WOLFSSL_SMALL_STACK */ +#endif /* WOLFSSL_SHA384 */ /* store current states, building requires get_digest which resets state */ #ifdef WOLFSSL_SHA384 @@ -5551,8 +5904,10 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif #ifndef NO_OLD_TLS if (!ssl->options.tls) { - BuildMD5(ssl, hashes, sender); - BuildSHA(ssl, hashes, sender); + ret = BuildMD5(ssl, hashes, sender); + if (ret == 0) { + ret = BuildSHA(ssl, hashes, sender); + } } #endif @@ -5563,9 +5918,9 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) #endif } -#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SHA384 - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif #endif @@ -5810,8 +6165,6 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : if (requirement == REQUIRES_RSA) return 1; - if (requirement == REQUIRES_RSA_SIG) - return 1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : @@ -5880,7 +6233,29 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) return 0; } /* switch */ } /* if */ - if (first != ECC_BYTE && first != CHACHA_BYTE) { /* normal suites */ + + /* Distinct TLS v1.3 cipher suites with cipher and digest only. */ + if (first == TLS13_BYTE) { + + switch (second) { +#ifdef WOLFSSL_TLS13 + case TLS_AES_128_GCM_SHA256: + case TLS_AES_256_GCM_SHA384: + case TLS_CHACHA20_POLY1305_SHA256: + case TLS_AES_128_CCM_SHA256: + case TLS_AES_128_CCM_8_SHA256: + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires " + "TLS v1.3"); + return 0; + } + } + + if (first != ECC_BYTE && first != CHACHA_BYTE && + first != TLS13_BYTE) { /* normal suites */ switch (second) { #ifndef NO_RSA @@ -6099,7 +6474,7 @@ static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) *.z.com matches y.z.com but not x.y.z.com return 1 on success */ -static int MatchDomainName(const char* pattern, int len, const char* str) +int MatchDomainName(const char* pattern, int len, const char* str) { char p, s; @@ -6114,8 +6489,8 @@ static int MatchDomainName(const char* pattern, int len, const char* str) if (p == '*') { while (--len > 0 && - (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') - ; + (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') { + } if (len == 0) p = '\0'; @@ -6145,7 +6520,7 @@ static int MatchDomainName(const char* pattern, int len, const char* str) /* try to find an altName match to domain, return 1 on success */ -static int CheckAltNames(DecodedCert* dCert, char* domain) +int CheckAltNames(DecodedCert* dCert, char* domain) { int match = 0; DNS_entry* altName = NULL; @@ -6156,7 +6531,7 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) altName = dCert->altNames; while (altName) { - WOLFSSL_MSG(" individual AltName check"); + WOLFSSL_MSG("\tindividual AltName check"); if (MatchDomainName(altName->name,(int)XSTRLEN(altName->name), domain)){ match = 1; @@ -6170,6 +6545,78 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) } +#ifdef OPENSSL_EXTRA +/* Check that alternative names, if they exists, match the domain. + * Fail if there are wild patterns and they didn't match. + * Check the common name if no alternative names matched. + * + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * checkCN Whether to check the common name. + * returns whether there was a problem in matching. + */ +static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN) +{ + int match; + DNS_entry* altName = NULL; + + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + *checkCN = altName == NULL; + match = 0; + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, (int)XSTRLEN(altName->name), + domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name[0] == '*' && match == 0) + match = -1; + + altName = altName->next; + } + + return match != -1; +} + +/* Check the domain name matches the subject alternative name or the subject + * name. + * + * dcert Decoded certificate. + * domainName The domain name. + * domainNameLen The length of the domain name. + * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. + */ +int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) +{ + int checkCN; + + /* Assume name is NUL terminated. */ + (void)domainNameLen; + + if (CheckForAltNames(dCert, domainName, &checkCN) == 0) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + return DOMAIN_NAME_MISMATCH; + } + if (checkCN == 1) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + domainName) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + return DOMAIN_NAME_MISMATCH; + } + } + + return 0; +} +#endif + #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) /* Copy parts X509 needs from Decoded cert, 0 on success */ @@ -6279,7 +6726,8 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; } - if (dCert->signature != NULL && dCert->sigLength != 0) { + if (dCert->signature != NULL && dCert->sigLength != 0 && + dCert->sigLength <= MAX_ENCODED_SIG_SZ) { x509->sig.buffer = (byte*)XMALLOC( dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE); if (x509->sig.buffer == NULL) { @@ -6309,6 +6757,23 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) x509->pathLength = dCert->pathLength; x509->keyUsage = dCert->extKeyUsage; + x509->CRLdistSet = dCert->extCRLdistSet; + x509->CRLdistCrit = dCert->extCRLdistCrit; + x509->CRLInfo = dCert->extCrlInfo; + x509->CRLInfoSz = dCert->extCrlInfoSz; + x509->authInfoSet = dCert->extAuthInfoSet; + x509->authInfoCrit = dCert->extAuthInfoCrit; + if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) { + x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz); + x509->authInfoSz = dCert->extAuthInfoSz; + } + else { + ret = MEMORY_E; + } + } x509->basicConstSet = dCert->extBasicConstSet; x509->basicConstCrit = dCert->extBasicConstCrit; x509->basicConstPlSet = dCert->pathLengthSet; @@ -6342,10 +6807,33 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) } x509->keyUsageSet = dCert->extKeyUsageSet; x509->keyUsageCrit = dCert->extKeyUsageCrit; + if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) { + x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz, + x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->extKeyUsageSrc != NULL) { + XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc, + dCert->extExtKeyUsageSz); + x509->extKeyUsageSz = dCert->extExtKeyUsageSz; + x509->extKeyUsageCrit = dCert->extExtKeyUsageCrit; + x509->extKeyUsageCount = dCert->extExtKeyUsageCount; + } + else { + ret = MEMORY_E; + } + } #ifdef WOLFSSL_SEP x509->certPolicySet = dCert->extCertPolicySet; x509->certPolicyCrit = dCert->extCertPolicyCrit; #endif /* WOLFSSL_SEP */ + #ifdef WOLFSSL_CERT_EXT + { + int i; + for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++) + XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i], + MAX_CERTPOL_SZ); + x509->certPoliciesNb = dCert->extCertPoliciesNb; + } + #endif /* WOLFSSL_CERT_EXT */ #endif /* OPENSSL_EXTRA */ #ifdef HAVE_ECC x509->pkCurveOID = dCert->pkCurveOID; @@ -6356,699 +6844,1036 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #endif /* KEEP_PEER_CERT || SESSION_CERTS */ - -static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, - word32 size) -{ - word32 listSz; - word32 begin = *inOutIdx; - int ret = 0; - int anyError = 0; - int totalCerts = 0; /* number of certs in certs buffer */ +typedef struct ProcPeerCertArgs { + buffer* certs; +#ifdef WOLFSSL_TLS13 + buffer* exts; /* extentions */ +#endif + DecodedCert* dCert; + char* domain; + word32 idx; + word32 begin; + int totalCerts; /* number of certs in certs buffer */ int count; - buffer certs[MAX_CHAIN_DEPTH]; + int dCertInit; + int certIdx; + int fatal; + int lastErr; +#ifdef WOLFSSL_TLS13 + byte ctxSz; +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + byte haveTrustPeer; /* was cert verified by loaded trusted peer cert */ +#endif +} ProcPeerCertArgs; -#ifdef WOLFSSL_SMALL_STACK - char* domain = NULL; - DecodedCert* dCert = NULL; - WOLFSSL_X509_STORE_CTX* store = NULL; +static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) +{ + ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; + + (void)ssl; + + if (args->domain) { + XFREE(args->domain, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->domain = NULL; + } + if (args->certs) { + XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->certs = NULL; + } +#ifdef WOLFSSL_TLS13 + if (args->exts) { + XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->exts = NULL; + } +#endif + if (args->dCert) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->dCert = NULL; + } +} + +int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 totalSz) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); #else - char domain[ASN_NAME_MAX]; - DecodedCert dCert[1]; - WOLFSSL_X509_STORE_CTX store[1]; + ProcPeerCertArgs args[1]; #endif #ifdef WOLFSSL_TRUST_PEER_CERT byte haveTrustPeer = 0; /* was cert verified by loaded trusted peer cert */ #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) AddLateName("Certificate", &ssl->timeoutInfo); + WOLFSSL_ENTER("ProcessPeerCerts"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_ppc; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ProcPeerCertArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeProcPeerCertArgs; #endif - - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; - - c24to32(input + *inOutIdx, &listSz); - *inOutIdx += OPAQUE24_LEN; - - if (listSz > MAX_RECORD_SIZE) - return BUFFER_E; - - if ((*inOutIdx - begin) + listSz != size) - return BUFFER_ERROR; - - WOLFSSL_MSG("Loading peer's cert chain"); - /* first put cert chain into buffer so can verify top down - we're sent bottom up */ - while (listSz) { - word32 certSz; - - if (totalCerts >= MAX_CHAIN_DEPTH) - return MAX_CHAIN_ERROR; - - if ((*inOutIdx - begin) + OPAQUE24_LEN > size) - return BUFFER_ERROR; - - c24to32(input + *inOutIdx, &certSz); - *inOutIdx += OPAQUE24_LEN; - - if ((*inOutIdx - begin) + certSz > size) - return BUFFER_ERROR; - - certs[totalCerts].length = certSz; - certs[totalCerts].buffer = input + *inOutIdx; - -#ifdef SESSION_CERTS - if (ssl->session.chain.count < MAX_CHAIN_DEPTH && - certSz < MAX_X509_SIZE) { - ssl->session.chain.certs[ssl->session.chain.count].length = certSz; - XMEMCPY(ssl->session.chain.certs[ssl->session.chain.count].buffer, - input + *inOutIdx, certSz); - ssl->session.chain.count++; - } else { - WOLFSSL_MSG("Couldn't store chain cert for session"); - } -#endif - - *inOutIdx += certSz; - listSz -= certSz + CERT_HEADER_SZ; - - totalCerts++; - WOLFSSL_MSG(" Put another cert into chain"); } - count = totalCerts; - -#ifdef WOLFSSL_SMALL_STACK - dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (dCert == NULL) - return MEMORY_E; -#endif - -#ifdef WOLFSSL_TRUST_PEER_CERT - /* if using trusted peer certs check before verify chain and CA test */ - if (count > 0) { - TrustedPeerCert* tp = NULL; - - InitDecodedCert(dCert, certs[0].buffer, certs[0].length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, 0, ssl->ctx->cm); - #ifndef NO_SKID - if (dCert->extAuthKeyIdSet) { - tp = GetTrustedPeer(ssl->ctx->cm, dCert->extSubjKeyId, - WC_MATCH_SKID); - } - else { /* if the cert has no SKID try to match by name */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); - } - #else /* NO_SKID */ - tp = GetTrustedPeer(ssl->ctx->cm, dCert->subjectHash, - WC_MATCH_NAME); - #endif /* NO SKID */ - WOLFSSL_MSG("Checking for trusted peer cert"); - - if (tp == NULL) { - /* no trusted peer cert */ - WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); - FreeDecodedCert(dCert); - } else if (MatchTrustedPeer(tp, dCert)){ - WOLFSSL_MSG("Found matching trusted peer cert"); - haveTrustPeer = 1; - } else { - WOLFSSL_MSG("Trusted peer cert did not match!"); - FreeDecodedCert(dCert); - } - } - if (!haveTrustPeer) { /* do not verify chain if trusted peer cert found */ -#endif /* WOLFSSL_TRUST_PEER_CERT */ - - /* verify up to peer's first */ - while (count > 1) { - buffer myCert = certs[count - 1]; - byte* subjectHash; - - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); - #ifndef NO_SKID - subjectHash = dCert->extSubjKeyId; - #else - subjectHash = dCert->subjectHash; - #endif - - /* Check key sizes for certs. Is redundent check since ProcessBuffer - also performs this check. */ - if (!ssl->options.verifyNone) { - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - if (ssl->options.minRsaKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size in cert chain error"); - ret = RSA_KEY_SIZE_E; - } - break; - #endif /* !NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: - if (ssl->options.minEccKeySz < 0 || - dCert->pubKeySize < (word16)ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size in cert chain error"); - ret = ECC_KEY_SIZE_E; - } - break; - #endif /* HAVE_ECC */ - - default: - WOLFSSL_MSG("Key size not checked"); - break; /* key not being checked for size if not in switch */ - } - } - - if (ret == 0 && dCert->isCA == 0) { - WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); - } - else if (ret == 0 && ssl->options.verifyNone) { - WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); - } - else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { - DerBuffer* add = NULL; - ret = AllocDer(&add, myCert.length, CA_TYPE, ssl->heap); - if (ret < 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } - - WOLFSSL_MSG("Adding CA from chain"); - - XMEMCPY(add->buffer, myCert.buffer, myCert.length); - - /* already verified above */ - ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); - if (ret == 1) ret = 0; /* SSL_SUCCESS for external */ - } - else if (ret != 0) { - WOLFSSL_MSG("Failed to verify CA from chain"); - } - else { - WOLFSSL_MSG("Verified CA from chain and already had it"); - } - -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (ret == 0) { - int doCrlLookup = 1; - -#ifdef HAVE_OCSP - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) - ret = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 0, - ssl->heap); - else /* skips OCSP and force CRL check */ - #endif - if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { - WOLFSSL_MSG("Doing Non Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - doCrlLookup = 0; - WOLFSSL_MSG("\tOCSP Lookup not ok"); - } - } -#endif /* HAVE_OCSP */ - -#ifdef HAVE_CRL - if (ret == 0 && doCrlLookup && ssl->ctx->cm->crlEnabled - && ssl->ctx->cm->crlCheckAll) { - WOLFSSL_MSG("Doing Non Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); - - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - } - } -#else - (void)doCrlLookup; -#endif /* HAVE_CRL */ - } -#endif /* HAVE_OCSP || HAVE_CRL */ - - if (ret != 0 && anyError == 0) - anyError = ret; /* save error from last time */ - - FreeDecodedCert(dCert); - count--; - } - -#ifdef WOLFSSL_TRUST_PEER_CERT - } /* end of if (haveTrustPeer) -- a check for if already verified */ -#endif - - /* peer's, may not have one if blank client cert sent by TLSv1.2 */ - if (count) { - buffer myCert = certs[0]; - int fatal = 0; - - WOLFSSL_MSG("Verifying Peer's cert"); - -#ifdef WOLFSSL_TRUST_PEER_CERT - if (!haveTrustPeer) { /* do not parse again if previously verified */ -#endif - InitDecodedCert(dCert, myCert.buffer, myCert.length, ssl->heap); - ret = ParseCertRelative(dCert, CERT_TYPE, !ssl->options.verifyNone, - ssl->ctx->cm); -#ifdef WOLFSSL_TRUST_PEER_CERT - } -#endif - - if (ret == 0) { - WOLFSSL_MSG("Verified Peer's cert"); - fatal = 0; - } - else if (ret == ASN_PARSE_E) { - WOLFSSL_MSG("Got Peer cert ASN PARSE ERROR, fatal"); - fatal = 1; - } - else { - WOLFSSL_MSG("Failed to verify Peer's cert"); - if (ssl->verifyCallback) { - WOLFSSL_MSG("\tCallback override available, will continue"); - fatal = 0; - } - else { - WOLFSSL_MSG("\tNo callback override available, fatal"); - fatal = 1; - } - } - -#ifdef HAVE_SECURE_RENEGOTIATION - if (fatal == 0 && ssl->secure_renegotiation - && ssl->secure_renegotiation->enabled) { - - if (IsEncryptionOn(ssl, 0)) { - /* compare against previous time */ - if (XMEMCMP(dCert->subjectHash, - ssl->secure_renegotiation->subject_hash, - SHA_DIGEST_SIZE) != 0) { - WOLFSSL_MSG("Peer sent different cert during scr, fatal"); - fatal = 1; - ret = SCR_DIFFERENT_CERT_E; - } - } - - /* cache peer's hash */ - if (fatal == 0) { - XMEMCPY(ssl->secure_renegotiation->subject_hash, - dCert->subjectHash, SHA_DIGEST_SIZE); - } - } -#endif - -#if defined(HAVE_OCSP) || defined(HAVE_CRL) - if (fatal == 0) { - int doLookup = 1; - - if (ssl->options.side == WOLFSSL_CLIENT_END) { -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (ssl->status_request) { - fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert, - ssl->heap); - doLookup = 0; - } -#endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { - fatal = TLSX_CSR2_InitRequests(ssl->extensions, dCert, 1, - ssl->heap); - doLookup = 0; - } -#endif - } - -#ifdef HAVE_OCSP - if (doLookup && ssl->ctx->cm->ocspEnabled) { - WOLFSSL_MSG("Doing Leaf OCSP check"); - ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert, NULL); - doLookup = (ret == OCSP_CERT_UNKNOWN); - if (ret != 0) { - WOLFSSL_MSG("\tOCSP Lookup not ok"); - fatal = 0; - } - } -#endif /* HAVE_OCSP */ - -#ifdef HAVE_CRL - if (doLookup && ssl->ctx->cm->crlEnabled) { - WOLFSSL_MSG("Doing Leaf CRL check"); - ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); - if (ret != 0) { - WOLFSSL_MSG("\tCRL check not ok"); - fatal = 0; - } - } -#endif /* HAVE_CRL */ - (void)doLookup; - } -#endif /* HAVE_OCSP || HAVE_CRL */ - -#ifdef KEEP_PEER_CERT + switch (ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: { - /* set X509 format for peer cert even if fatal */ - int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); - if (copyRet == MEMORY_E) - fatal = 1; - } -#endif + word32 listSz; -#ifndef IGNORE_KEY_EXTENSIONS - if (dCert->extKeyUsageSet) { - if ((ssl->specs.kea == rsa_kea) && - (ssl->options.side == WOLFSSL_CLIENT_END) && - (dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { - ret = KEYUSE_ENCIPHER_E; - } - if ((ssl->specs.sig_algo == rsa_sa_algo || - (ssl->specs.sig_algo == ecc_dsa_sa_algo && - !ssl->specs.static_ecdh)) && - (dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { - WOLFSSL_MSG("KeyUse Digital Sig not set"); - ret = KEYUSE_SIGNATURE_E; - } - } - - if (dCert->extExtKeyUsageSet) { - if (ssl->options.side == WOLFSSL_CLIENT_END) { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Server Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } - } - else { - if ((dCert->extExtKeyUsage & - (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { - WOLFSSL_MSG("ExtKeyUse Client Auth not set"); - ret = EXTKEYUSE_AUTH_E; - } - } - } -#endif /* IGNORE_KEY_EXTENSIONS */ - - if (fatal) { - FreeDecodedCert(dCert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("Certificate", &ssl->timeoutInfo); #endif - ssl->error = ret; - return ret; - } - ssl->options.havePeerCert = 1; -#ifdef WOLFSSL_SMALL_STACK - domain = (char*)XMALLOC(ASN_NAME_MAX, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (domain == NULL) { - FreeDecodedCert(dCert); - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - /* store for callback use */ - if (dCert->subjectCNLen < ASN_NAME_MAX) { - XMEMCPY(domain, dCert->subjectCN, dCert->subjectCNLen); - domain[dCert->subjectCNLen] = '\0'; - } - else - domain[0] = '\0'; + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + byte ctxSz; - if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { - if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, - (char*)ssl->buffers.domainName.buffer) == 0) { - WOLFSSL_MSG("DomainName match on common name failed"); - if (CheckAltNames(dCert, - (char*)ssl->buffers.domainName.buffer) == 0 ) { - WOLFSSL_MSG("DomainName match on alt names failed too"); - ret = DOMAIN_NAME_MISMATCH; /* try to get peer key still */ + /* Certificate Request Context */ + if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz) + return BUFFER_ERROR; + ctxSz = *(input + args->idx); + args->idx++; + if ((args->idx - args->begin) + ctxSz > totalSz) + return BUFFER_ERROR; + #ifndef NO_WOLFSSL_CLIENT + /* Must be empty when received from server. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + /* Must contain value sent in request when received from client. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->clientCertCtx.length != ctxSz || + XMEMCMP(ssl->clientCertCtx.buffer, + input + args->idx, ctxSz) != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + args->idx += ctxSz; + + /* allocate buffer for cert extensions */ + args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exts == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); } } - } + #endif - /* decode peer key */ - switch (dCert->keyOID) { - #ifndef NO_RSA - case RSAk: - { - word32 idx = 0; - int keyRet = 0; + /* allocate buffer for certs */ + args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH); + + /* Certificate List */ + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + c24to32(input + args->idx, &listSz); + args->idx += OPAQUE24_LEN; + if (listSz > MAX_RECORD_SIZE) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + if ((args->idx - args->begin) + listSz != totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + WOLFSSL_MSG("Loading peer's cert chain"); + /* first put cert chain into buffer so can verify top down + we're sent bottom up */ + while (listSz) { + word32 certSz; + + if (args->totalCerts >= MAX_CHAIN_DEPTH) { + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + #endif + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + c24to32(input + args->idx, &certSz); + args->idx += OPAQUE24_LEN; + + if ((args->idx - args->begin) + certSz > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + args->certs[args->totalCerts].length = certSz; + args->certs[args->totalCerts].buffer = input + args->idx; + + #ifdef SESSION_CERTS + if (ssl->session.chain.count < MAX_CHAIN_DEPTH && + certSz < MAX_X509_SIZE) { + ssl->session.chain.certs[ + ssl->session.chain.count].length = certSz; + XMEMCPY(ssl->session.chain.certs[ + ssl->session.chain.count].buffer, + input + args->idx, certSz); + ssl->session.chain.count++; + } + else { + WOLFSSL_MSG("Couldn't store chain cert for session"); + } + #endif /* SESSION_CERTS */ + + args->idx += certSz; + listSz -= certSz + CERT_HEADER_SZ; + + #ifdef WOLFSSL_TLS13 + /* Extensions */ + if (ssl->options.tls1_3) { + word16 extSz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) + return BUFFER_ERROR; + ato16(input + args->idx, &extSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + extSz > totalSz) + return BUFFER_ERROR; + /* Store extension data info for later processing. */ + args->exts[args->totalCerts].length = extSz; + args->exts[args->totalCerts].buffer = input + args->idx; + args->idx += extSz; + listSz -= extSz + OPAQUE16_LEN; + } + #endif + + args->totalCerts++; + WOLFSSL_MSG("\tPut another cert into chain"); + } /* while (listSz) */ + + args->count = args->totalCerts; + args->certIdx = 0; + + args->dCertInit = 0; + args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->dCert == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + if (args->count > 0) { + #ifdef WOLFSSL_TRUST_PEER_CERT + if (args->certIdx == 0) { + /* if using trusted peer certs check before verify chain + and CA test */ + TrustedPeerCert* tp; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + args->dCertInit = 1; + } + + ret = ParseCertRelative(args->dCert, CERT_TYPE, 0, + ssl->ctx->cm); + if (ret != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + goto exit_ppc; + } + + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) { + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->extSubjKeyId, WC_MATCH_SKID); + } + else { /* if the cert has no SKID try to match by name */ + tp = GetTrustedPeer(ssl->ctx->cm, + args->dCert->subjectHash, WC_MATCH_NAME); + } + #else /* NO_SKID */ + tp = GetTrustedPeer(ssl->ctx->cm, args->dCert->subjectHash, + WC_MATCH_NAME); + #endif /* NO SKID */ + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. " + "Checking CAs"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } else if (MatchTrustedPeer(tp, args->dCert)){ + WOLFSSL_MSG("Found matching trusted peer cert"); + haveTrustPeer = 1; + } else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT */ + + /* verify up to peer's first */ + /* do not verify chain if trusted peer cert found */ + while (args->count > 1 + #ifdef WOLFSSL_TRUST_PEER_CERT + && !haveTrustPeer + #endif /* WOLFSSL_TRUST_PEER_CERT */ + ) { + byte* subjectHash; + + args->certIdx = args->count - 1; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCert->sigCtx.devId = ssl->devId; /* setup async dev */ + args->dCertInit = 1; + } + + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + goto exit_ppc; + } + #endif + + #ifndef NO_SKID + subjectHash = args->dCert->extSubjKeyId; + #else + subjectHash = args->dCert->subjectHash; + #endif + + /* Check key sizes for certs. Is redundent check since + ProcessBuffer also performs this check. */ + if (!ssl->options.verifyNone) { + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (ssl->options.minRsaKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minRsaKeySz) { + WOLFSSL_MSG( + "RSA key size in cert chain error"); + ret = RSA_KEY_SIZE_E; + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (ssl->options.minEccKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Key size not checked"); + /* key not being checked for size if not in + switch */ + break; + } /* switch (dCert->keyOID) */ + } /* if (!ssl->options.verifyNone) */ + + if (ret == 0 && args->dCert->isCA == 0) { + WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); + } + else if (ret == 0 && ssl->options.verifyNone) { + WOLFSSL_MSG("Chain cert not verified by option, not adding as CA"); + } + else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { + DerBuffer* add = NULL; + ret = AllocDer(&add, args->certs[args->certIdx].length, + CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + WOLFSSL_MSG("Adding CA from chain"); + + XMEMCPY(add->buffer, args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length); + + /* already verified above */ + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); + if (ret == 1) { + ret = 0; /* SSL_SUCCESS for external */ + } + } + else if (ret != 0) { + WOLFSSL_MSG("Failed to verify CA from chain"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #endif + } + else { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (ret == 0) { + int doCrlLookup = 1; + #ifdef HAVE_OCSP + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ret = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 0, ssl->heap); + } + else /* skips OCSP and force CRL check */ + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + if (ssl->ctx->cm->ocspEnabled && + ssl->ctx->cm->ocspCheckAll) { + WOLFSSL_MSG("Doing Non Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, args->dCert, + NULL); + doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + doCrlLookup = 0; + WOLFSSL_MSG("\tOCSP Lookup not ok"); + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (ret == 0 && doCrlLookup && + ssl->ctx->cm->crlEnabled && + ssl->ctx->cm->crlCheckAll) { + WOLFSSL_MSG("Doing Non Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + } + } + #endif /* HAVE_CRL */ + (void)doCrlLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + if (ret != 0 && args->lastErr == 0) { + args->lastErr = ret; /* save error from last time */ + ret = 0; /* reset error */ + } + + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + args->count--; + } /* while (count > 0 && !haveTrustPeer) */ + } /* if (count > 0) */ + + /* Check for error */ + if (ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ + if (args->count > 0) { + WOLFSSL_MSG("Verifying Peer's cert"); + + args->certIdx = 0; + + if (!args->dCertInit) { + InitDecodedCert(args->dCert, + args->certs[args->certIdx].buffer, + args->certs[args->certIdx].length, ssl->heap); + args->dCertInit = 1; + } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (!haveTrustPeer) + #endif + { /* only parse if not already present in dCert from above */ + ret = ParseCertRelative(args->dCert, CERT_TYPE, + !ssl->options.verifyNone, ssl->ctx->cm); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + goto exit_ppc; + } + #endif + } + + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_OK; + #endif + args->fatal = 0; + } + else if (ret == ASN_PARSE_E || ret == BUFFER_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + args->fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif + if (ssl->verifyCallback) { + WOLFSSL_MSG( + "\tCallback override available, will continue"); + args->fatal = 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + args->fatal = 1; + } + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (args->fatal == 0 && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (XMEMCMP(args->dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + SHA_DIGEST_SIZE) != 0) { + WOLFSSL_MSG( + "Peer sent different cert during scr, fatal"); + args->fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } + + /* cache peer's hash */ + if (args->fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + args->dCert->subjectHash, SHA_DIGEST_SIZE); + } + } + #endif /* HAVE_SECURE_RENEGOTIATION */ + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (args->fatal == 0) { + int doLookup = 1; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + args->fatal = TLSX_CSR_InitRequest(ssl->extensions, + args->dCert, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + args->fatal = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 1, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + } + + #ifdef HAVE_OCSP + if (doLookup && ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); + ret = CheckCertOCSP(ssl->ctx->cm->ocsp, + args->dCert, NULL); + doLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Lookup not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (doLookup && ssl->ctx->cm->crlEnabled) { + WOLFSSL_MSG("Doing Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + args->fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_CRL */ + (void)doLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + #ifdef KEEP_PEER_CERT + if (args->fatal == 0) { + /* set X509 format for peer cert */ + int copyRet = CopyDecodedToX509(&ssl->peerCert, + args->dCert); + if (copyRet == MEMORY_E) + args->fatal = 1; + } + #endif /* KEEP_PEER_CERT */ + + #ifndef IGNORE_KEY_EXTENSIONS + if (args->dCert->extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (ssl->options.side == WOLFSSL_CLIENT_END) && + (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { + ret = KEYUSE_ENCIPHER_E; + } + if ((ssl->specs.sig_algo == rsa_sa_algo || + (ssl->specs.sig_algo == ecc_dsa_sa_algo && + !ssl->specs.static_ecdh)) && + (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + WOLFSSL_MSG("KeyUse Digital Sig not set"); + ret = KEYUSE_SIGNATURE_E; + } + } + + if (args->dCert->extExtKeyUsageSet) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Server Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Client Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + } + #endif /* IGNORE_KEY_EXTENSIONS */ + + if (args->fatal) { + ssl->error = ret; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + goto exit_ppc; + } + + ssl->options.havePeerCert = 1; + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + if (args->count > 0) { + args->domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->domain == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + + /* store for callback use */ + if (args->dCert->subjectCNLen < ASN_NAME_MAX) { + XMEMCPY(args->domain, args->dCert->subjectCN, args->dCert->subjectCNLen); + args->domain[args->dCert->subjectCNLen] = '\0'; + } + else { + args->domain[0] = '\0'; + } + + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + if (CheckAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer) == 0 ) { + WOLFSSL_MSG( + "DomainName match on alt names failed too"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } + } + + /* decode peer key */ + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 keyIdx = 0; + int keyRet = 0; - if (ssl->peerRsaKey == NULL) { - ssl->peerRsaKey = (RsaKey*)XMALLOC(sizeof(RsaKey), - ssl->heap, DYNAMIC_TYPE_RSA); if (ssl->peerRsaKey == NULL) { - WOLFSSL_MSG("PeerRsaKey Memory error"); - keyRet = MEMORY_E; - } else { + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + } else if (ssl->peerRsaKeyPresent) { + /* don't leak on reuse */ + wc_FreeRsaKey(ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, - ssl->heap, ssl->devId); + ssl->heap, ssl->devId); } - } else if (ssl->peerRsaKeyPresent) { - /* don't leak on reuse */ - wc_FreeRsaKey(ssl->peerRsaKey); - ssl->peerRsaKeyPresent = 0; - keyRet = wc_InitRsaKey_ex(ssl->peerRsaKey, ssl->heap, ssl->devId); - } - if (keyRet != 0 || wc_RsaPublicKeyDecode(dCert->publicKey, - &idx, ssl->peerRsaKey, dCert->pubKeySize) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerRsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifndef NO_RSA - ssl->buffers.peerRsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_RSA); - if (ssl->buffers.peerRsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerRsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerRsaKey.length = - dCert->pubKeySize; - } - #endif /* NO_RSA */ - #endif /*HAVE_PK_CALLBACKS */ - } + if (keyRet != 0 || wc_RsaPublicKeyDecode( + args->dCert->publicKey, &keyIdx, ssl->peerRsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + ssl->buffers.peerRsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->buffers.peerRsaKey.buffer == NULL) { + ret = MEMORY_ERROR; + } + else { + XMEMCPY(ssl->buffers.peerRsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerRsaKey.length = + args->dCert->pubKeySize; + } + #endif /* NO_RSA */ + #endif /* HAVE_PK_CALLBACKS */ + } - /* check size of peer RSA key */ - if (ret == 0 && ssl->peerRsaKeyPresent && - !ssl->options.verifyNone && - wc_RsaEncryptSize(ssl->peerRsaKey) + /* check size of peer RSA key */ + if (ret == 0 && ssl->peerRsaKeyPresent && + !ssl->options.verifyNone && + wc_RsaEncryptSize(ssl->peerRsaKey) < ssl->options.minRsaKeySz) { - ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG("Peer RSA key is too small"); - } - - } - 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: - { - int curveId; - if (ssl->peerEccDsaKey == NULL) { - /* alloc/init on demand */ - ssl->peerEccDsaKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccDsaKey == NULL) { - WOLFSSL_MSG("PeerEccDsaKey Memory error"); - return MEMORY_E; + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Peer RSA key is too small"); } - wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, - ssl->devId); - } else if (ssl->peerEccDsaKeyPresent) { - /* don't leak on reuse */ - wc_ecc_free(ssl->peerEccDsaKey); - ssl->peerEccDsaKeyPresent = 0; - wc_ecc_init_ex(ssl->peerEccDsaKey, ssl->heap, - ssl->devId); + break; } + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->peerNtruKeyLen = + (word16)args->dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + int curveId; + int keyRet = 0; + if (ssl->peerEccDsaKey == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + } else if (ssl->peerEccDsaKeyPresent) { + /* don't leak on reuse */ + wc_ecc_free(ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + keyRet = wc_ecc_init_ex(ssl->peerEccDsaKey, + ssl->heap, ssl->devId); + } - curveId = wc_ecc_get_oid(dCert->keyOID, NULL, NULL); - if (wc_ecc_import_x963_ex(dCert->publicKey, - dCert->pubKeySize, ssl->peerEccDsaKey, curveId) != 0) { - ret = PEER_KEY_ERROR; - } - else { - ssl->peerEccDsaKeyPresent = 1; - #ifdef HAVE_PK_CALLBACKS - #ifdef HAVE_ECC - ssl->buffers.peerEccDsaKey.buffer = - (byte*)XMALLOC(dCert->pubKeySize, - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->buffers.peerEccDsaKey.buffer == NULL) - ret = MEMORY_ERROR; - else { - XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, - dCert->publicKey, dCert->pubKeySize); - ssl->buffers.peerEccDsaKey.length = - dCert->pubKeySize; - } - #endif /* HAVE_ECC */ - #endif /*HAVE_PK_CALLBACKS */ - } + curveId = wc_ecc_get_oid(args->dCert->keyOID, NULL, NULL); + if (keyRet != 0 || + wc_ecc_import_x963_ex(args->dCert->publicKey, + args->dCert->pubKeySize, ssl->peerEccDsaKey, + curveId) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEccDsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + ssl->buffers.peerEccDsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEccDsaKey.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEccDsaKey.length = + args->dCert->pubKeySize; + } + #endif /* HAVE_ECC */ + #endif /*HAVE_PK_CALLBACKS */ + } - /* check size of peer ECC key */ - if (ret == 0 && ssl->peerEccDsaKeyPresent && + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEccDsaKeyPresent && !ssl->options.verifyNone && wc_ecc_size(ssl->peerEccDsaKey) < ssl->options.minEccKeySz) { - ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG("Peer ECC key is too small"); + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; } - + #endif /* HAVE_ECC */ + default: + break; } - break; - #endif /* HAVE_ECC */ - default: - break; - } - FreeDecodedCert(dCert); - } + FreeDecodedCert(args->dCert); + args->dCertInit = 0; -#ifdef WOLFSSL_SMALL_STACK - XFREE(dCert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - store = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (store == NULL) { - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); - - if (anyError != 0 && ret == 0) - ret = anyError; - - if (ret != 0) { - if (!ssl->options.verifyNone) { - int why = bad_certificate; - - if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) - why = certificate_expired; - if (ssl->verifyCallback) { - int ok; - - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#else - store->current_cert = NULL; -#endif -#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL) - store->ex_data = ssl; -#endif - ok = ssl->verifyCallback(0, store); - if (ok) { - WOLFSSL_MSG("Verify callback overriding error!"); - ret = 0; + /* release since we don't need it anymore */ + if (args->dCert) { + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->dCert = NULL; } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; - } - #endif + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + #ifdef WOLFSSL_SMALL_STACK + WOLFSSL_X509_STORE_CTX* store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (store == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + #else + WOLFSSL_X509_STORE_CTX store[1]; + #endif + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + + /* load last error */ + if (args->lastErr != 0 && ret == 0) { + ret = args->lastErr; + } + if (ret != 0) { - SendAlert(ssl, alert_fatal, why); /* try to send */ - ssl->options.isClosed = 1; + if (!ssl->options.verifyNone) { + int why = bad_certificate; + + if (ret == ASN_AFTER_DATE_E || ret == ASN_BEFORE_DATE_E) { + why = certificate_expired; + } + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + store->error_depth = args->totalCerts; + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #else + store->current_cert = NULL; + #endif /* KEEP_PEER_CERT */ + #if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS) + store->ex_data = ssl; + #endif + ok = ssl->verifyCallback(0, store); + if (ok) { + WOLFSSL_MSG("Verify callback overriding error!"); + ret = 0; + } + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + } + #endif /* SESSION_CERTS */ + } + if (ret != 0) { + SendAlert(ssl, alert_fatal, why); /* try to send */ + ssl->options.isClosed = 1; + } + } + ssl->error = ret; } + #ifdef WOLFSSL_ALWAYS_VERIFY_CB + else { + if (ssl->verifyCallback) { + int ok; + + store->error = ret; + #ifdef WOLFSSL_WPAS + store->error_depth = 0; + #else + store->error_depth = args->totalCerts; + #endif + store->discardSessionCerts = 0; + store->domain = args->domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + #ifdef KEEP_PEER_CERT + if (ssl->peerCert.subject.sz > 0) + store->current_cert = &ssl->peerCert; + else + store->current_cert = NULL; + #endif + store->ex_data = ssl; + + ok = ssl->verifyCallback(1, store); + if (!ok) { + WOLFSSL_MSG("Verify callback overriding valid certificate!"); + ret = -1; + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->options.isClosed = 1; + } + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + } + #endif /* SESSION_CERTS */ + } + } + #endif /* WOLFSSL_ALWAYS_VERIFY_CB */ + + if (ssl->options.verifyNone && + (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { + WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); + ret = ssl->error = 0; + } + + if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(store, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* Set final index */ + *inOutIdx = args->idx; + + break; } - ssl->error = ret; + default: + ret = INPUT_CASE_ERROR; + break; + } /* switch(ssl->options.asyncState) */ + +exit_ppc: + + WOLFSSL_LEAVE("ProcessPeerCerts", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle WC_PENDING_E */ + if (ret == WC_PENDING_E) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate = 0; + + return ret; } -#ifdef WOLFSSL_ALWAYS_VERIFY_CB - else { - if (ssl->verifyCallback) { - int ok; +#endif /* WOLFSSL_ASYNC_CRYPT */ - store->error = ret; - store->error_depth = totalCerts; - store->discardSessionCerts = 0; - store->domain = domain; - store->userCtx = ssl->verifyCbCtx; - store->certs = certs; - store->totalCerts = totalCerts; -#ifdef KEEP_PEER_CERT - store->current_cert = &ssl->peerCert; -#endif - store->ex_data = ssl; - - ok = ssl->verifyCallback(1, store); - if (!ok) { - WOLFSSL_MSG("Verify callback overriding valid certificate!"); - ret = -1; - SendAlert(ssl, alert_fatal, bad_certificate); - ssl->options.isClosed = 1; - } - #ifdef SESSION_CERTS - if (store->discardSessionCerts) { - WOLFSSL_MSG("Verify callback requested discard sess certs"); - ssl->session.chain.count = 0; - } - #endif - } - } -#endif - - if (ssl->options.verifyNone && - (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { - WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); - ret = ssl->error = 0; - } - - if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) - ssl->options.serverState = SERVER_CERT_COMPLETE; - - if (IsEncryptionOn(ssl, 0)) { - *inOutIdx += ssl->keys.padSz; - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(store, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(domain, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + FreeProcPeerCertArgs(ssl, args); + FreeKeyExchange(ssl); return ret; } +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + return ProcessPeerCerts(ssl, input, inOutIdx, size); +} static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) @@ -7088,7 +7913,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, do { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { - request = TLSX_CSR_GetRequest(ssl->extensions); + request = (OcspRequest*)TLSX_CSR_GetRequest( + ssl->extensions); ssl->status_request = 0; break; } @@ -7096,8 +7922,8 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 if (ssl->status_request_v2) { - request = TLSX_CSR2_GetRequest(ssl->extensions, - status_type, 0); + request = (OcspRequest*)TLSX_CSR2_GetRequest( + ssl->extensions, status_type, 0); ssl->status_request_v2 = 0; break; } @@ -7110,9 +7936,9 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (status == NULL || response == NULL) { @@ -7127,17 +7953,22 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) != 0) - || (response->responseStatus != OCSP_SUCCESSFUL) - || (response->status->status != CERT_GOOD) - || (CompareOcspReqResp(request, response) != 0)) + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) ret = BAD_CERTIFICATE_STATUS_ERROR; *inOutIdx += status_length; #ifdef WOLFSSL_SMALL_STACK - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif } @@ -7150,7 +7981,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, case WOLFSSL_CSR2_OCSP_MULTI: { OcspRequest* request; word32 list_length = status_length; - byte index = 0; + byte idx = 0; #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -7170,16 +8001,16 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, } while(0); #ifdef WOLFSSL_SMALL_STACK - status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (status == NULL || response == NULL) { if (status) - XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(status, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (response) - XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_ERROR; } @@ -7204,21 +8035,21 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) - != 0) + if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, + 0) != 0) || (response->responseStatus != OCSP_SUCCESSFUL) || (response->status->status != CERT_GOOD)) ret = BAD_CERTIFICATE_STATUS_ERROR; while (ret == 0) { - request = TLSX_CSR2_GetRequest(ssl->extensions, - status_type, index++); + request = (OcspRequest*)TLSX_CSR2_GetRequest( + ssl->extensions, status_type, idx++); if (request == NULL) ret = BAD_CERTIFICATE_STATUS_ERROR; else if (CompareOcspReqResp(request, response) == 0) break; - else if (index == 1) /* server cert must be OK */ + else if (idx == 1) /* server cert must be OK */ ret = BAD_CERTIFICATE_STATUS_ERROR; } @@ -7578,7 +8409,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("Finished received before ChangeCipher"); return NO_CHANGE_CIPHER_E; } - break; case change_cipher_hs: @@ -7654,6 +8484,13 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ENTER("DoHandShakeMsgType"); +#ifdef WOLFSSL_TLS13 + if (type == hello_retry_request) { + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } +#endif + /* make sure can read the message */ if (*inOutIdx + size > totalSz) return INCOMPLETE_DATA; @@ -7768,12 +8605,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case server_hello_done: WOLFSSL_MSG("processing server hello done"); - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("ServerHelloDone", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddLateName("ServerHelloDone", &ssl->timeoutInfo); - #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHelloDone", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddLateName("ServerHelloDone", &ssl->timeoutInfo); + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; if (IsEncryptionOn(ssl, 0)) { *inOutIdx += ssl->keys.padSz; @@ -7822,6 +8659,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DECODE_E; } +#ifdef WOLFSSL_ASYNC_CRYPT /* if async, offset index so this msg will be processed again */ if (ret == WC_PENDING_E) { *inOutIdx -= HANDSHAKE_HEADER_SZ; @@ -7831,6 +8669,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, } #endif } +#endif WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); return ret; @@ -7926,7 +8765,6 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } - #ifdef WOLFSSL_DTLS static INLINE int DtlsCheckWindow(WOLFSSL* ssl) @@ -7986,6 +8824,12 @@ static INLINE int DtlsCheckWindow(WOLFSSL* ssl) word32 idx = diff / DTLS_WORD_BITS; word32 newDiff = diff % DTLS_WORD_BITS; + /* verify idx is valid for window array */ + if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) { + WOLFSSL_MSG("Invalid DTLS windows index"); + return 0; + } + if (window[idx] & (1 << (newDiff - 1))) { WOLFSSL_MSG("Current record sequence number already received."); return 0; @@ -8261,6 +9105,20 @@ static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * out output buffer to hold encrypted data + * input data to encrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) { @@ -8280,14 +9138,14 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, XMEMSET(poly, 0, sizeof(poly)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, CUR_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* opaque SEQ number stored for AD */ WriteSEQ(ssl, CUR_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce. SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* Store the type, version. Unfortunately, they are in * the input buffer ahead of the plaintext. */ #ifdef WOLFSSL_DTLS @@ -8398,6 +9256,20 @@ static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, } +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implmentation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automaticlly depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparision to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * plain output buffer to hold decrypted data + * input data to decrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { @@ -8424,14 +9296,14 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, XMEMSET(nonce, 0, sizeof(nonce)); XMEMSET(add, 0, sizeof(add)); - if (ssl->options.oldPoly != 0) { - /* get nonce */ - WriteSEQ(ssl, PEER_ORDER, nonce + CHACHA20_OLD_OFFSET); - } - /* sequence number field is 64-bits */ WriteSEQ(ssl, PEER_ORDER, add); + if (ssl->options.oldPoly != 0) { + /* get nonce, SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + /* get AD info */ /* Store the type, version. */ add[AEAD_TYPE_OFFSET] = ssl->curRL.type; @@ -8526,185 +9398,258 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ -static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz) +static INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, + word16 sz, int asyncOkay) { int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#else + (void)asyncOkay; +#endif (void)out; (void)input; (void)sz; - if (ssl->encrypt.setup == 0) { - WOLFSSL_MSG("Encrypt ciphers not setup"); - return ENCRYPT_ERROR; - } - -#ifdef HAVE_FUZZER - if (ssl->fuzzerCb) - ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); -#endif - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); - break; + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.des3->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); + } #endif + break; + #endif - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.aes->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); break; + } #endif + break; + #endif - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); - break; + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthEncryptFunc aes_auth_fn; + const byte* additionalSrc; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmEncrypt : wc_AesCcmEncrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmEncrypt; + #else + aes_auth_fn = wc_AesCcmEncrypt; #endif + additionalSrc = input - 5; - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; + XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ); - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); + /* sequence number field is 64-bits */ + WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional); - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - break; + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } #endif + XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET, + additionalSrc, 3); - #ifdef HAVE_AESCCM - /* AEAD CCM uses same size as macros for AESGCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - const byte* additionalSrc = input - 5; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, CUR_ORDER, additional); - - /* Store the type, version. Unfortunately, they are in - * the input buffer ahead of the plaintext. */ - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - additionalSrc -= DTLS_HANDSHAKE_EXTRA; - } - #endif - XMEMCPY(additional + AEAD_TYPE_OFFSET, additionalSrc, 3); - - /* Store the length of the plain text minus the explicit - * IV length minus the authentication tag size. */ - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - ret = wc_AesCcmEncrypt(ssl->encrypt.aes, - out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - out + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ); - AeadIncrementExpIV(ssl); - ForceZero(nonce, AESGCM_NONCE_SZ); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - break; + /* Store the length of the plain text minus the explicit + * IV length minus the authentication tag size. */ + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->encrypt.nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + ret = aes_auth_fn(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + asyncDev = &ssl->encrypt.aes->asyncDev; + if (asyncOkay) + ret = wolfSSL_AsyncPush(ssl, asyncDev, event_flags); + } #endif + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); - break; - #endif + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); + break; + #endif - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); - break; - #endif + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); + break; + #endif - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); - break; - #endif + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); + break; + #endif - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADEncrypt(ssl, out, input, sz); - break; - #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADEncrypt(ssl, out, input, sz); + break; + #endif - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != out) { - XMEMMOVE(out, input, sz); - } - break; - #endif + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != out) { + XMEMMOVE(out, input, sz); + } + break; + #endif - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); - break; - #endif + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); + break; + #endif - default: - WOLFSSL_MSG("wolfSSL Encrypt programming error"); - ret = ENCRYPT_ERROR; + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + ret = ENCRYPT_ERROR; } +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async is not okay, then block */ + if (ret == WC_PENDING_E && !asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } +#endif + return ret; } +static INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, + int asyncOkay) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay && ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif -static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->encrypt.setup == 0) { + WOLFSSL_MSG("Encrypt ciphers not setup"); + return ENCRYPT_ERROR; + } + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->encrypt.additional == NULL) + ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->encrypt.additional == NULL || + ssl->encrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + ret = EncryptDo(ssl, out, input, sz, asyncOkay); + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, then leave and return will resume below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + { + /* finalize authentication cipher */ + AeadIncrementExpIV(ssl); + + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + +static INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { int ret = 0; @@ -8713,149 +9658,246 @@ static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, (void)input; (void)sz; - if (ssl->decrypt.setup == 0) { - WOLFSSL_MSG("Decrypt ciphers not setup"); - return DECRYPT_ERROR; - } + switch (ssl->specs.bulk_cipher_algorithm) + { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); + break; + #endif - switch (ssl->specs.bulk_cipher_algorithm) { - #ifdef BUILD_ARC4 - case wolfssl_rc4: - wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); - break; + #ifdef BUILD_DES3 + case wolfssl_triple_des: + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthDecryptFunc aes_auth_fn; + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmDecrypt : wc_AesCcmDecrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmDecrypt; + #else + aes_auth_fn = wc_AesCcmDecrypt; #endif - #ifdef BUILD_DES3 - case wolfssl_triple_des: - ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); - break; - #endif + XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); - #ifdef BUILD_AES - case wolfssl_aes: - ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); - break; - #endif + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional); - #ifdef BUILD_AESGCM - case wolfssl_aes_gcm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; + ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesGcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, + AESGCM_EXP_IV_SZ); + if ((ret = aes_auth_fn(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + break; } - ForceZero(nonce, AESGCM_NONCE_SZ); + #endif + } + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADDecrypt(ssl, plain, input, sz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != plain) { + XMEMMOVE(plain, input, sz); } break; - #endif + #endif - #ifdef HAVE_AESCCM - /* AESGCM AEAD macros use same size as AESCCM */ - case wolfssl_aes_ccm: - { - byte additional[AEAD_AUTH_DATA_SZ]; - byte nonce[AESGCM_NONCE_SZ]; - - XMEMSET(additional, 0, AEAD_AUTH_DATA_SZ); - - /* sequence number field is 64-bits */ - WriteSEQ(ssl, PEER_ORDER, additional); - - additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; - additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; - additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; - - c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - additional + AEAD_LEN_OFFSET); - XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); - if (wc_AesCcmDecrypt(ssl->decrypt.aes, - plain + AESGCM_EXP_IV_SZ, - input + AESGCM_EXP_IV_SZ, - sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, - nonce, AESGCM_NONCE_SZ, - input + sz - ssl->specs.aead_mac_size, - ssl->specs.aead_mac_size, - additional, AEAD_AUTH_DATA_SZ) < 0) { - if (!ssl->options.dtls) - SendAlert(ssl, alert_fatal, bad_record_mac); - ret = VERIFY_MAC_ERROR; - } - ForceZero(nonce, AESGCM_NONCE_SZ); - } + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); break; - #endif + #endif - #ifdef HAVE_CAMELLIA - case wolfssl_camellia: - wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); - break; - #endif - - #ifdef HAVE_HC128 - case wolfssl_hc128: - ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); - break; - #endif - - #ifdef BUILD_RABBIT - case wolfssl_rabbit: - ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); - break; - #endif - - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) - case wolfssl_chacha: - ret = ChachaAEADDecrypt(ssl, plain, input, sz); - break; - #endif - - #ifdef HAVE_NULL_CIPHER - case wolfssl_cipher_null: - if (input != plain) { - XMEMMOVE(plain, input, sz); - } - break; - #endif - - #ifdef HAVE_IDEA - case wolfssl_idea: - ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); - break; - #endif - - default: - WOLFSSL_MSG("wolfSSL Decrypt programming error"); - ret = DECRYPT_ERROR; + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + ret = DECRYPT_ERROR; } return ret; } +static INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } + + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->decrypt.setup == 0) { + WOLFSSL_MSG("Decrypt ciphers not setup"); + return DECRYPT_ERROR; + } + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->decrypt.additional == NULL) + ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES); + if (ssl->decrypt.additional == NULL || + ssl->decrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + case CIPHER_STATE_DO: + { + ret = DecryptDo(ssl, plain, input, sz); + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave and return below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM nonce is cleared */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + if (ssl->decrypt.nonce) + ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ); + + if (ret < 0) + ret = VERIFY_MAC_ERROR; + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->decrypt.state = CIPHER_STATE_BEGIN; + + /* handle mac error case */ + if (ret == VERIFY_MAC_ERROR) { + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + } + + return ret; +} + +/* Check conditions for a cipher to have an explicit IV. + * + * ssl The SSL/TLS object. + * returns 1 if the cipher in use has an explicit IV and 0 otherwise. + */ +static INLINE int CipherHasExpIV(WOLFSSL *ssl) +{ +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return 0; +#endif + return (ssl->specs.cipher_type == aead) && + (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha); +} /* check cipher text size for sanity */ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) @@ -8883,8 +9925,8 @@ static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) } else if (ssl->specs.cipher_type == aead) { minLength = ssl->specs.aead_mac_size; /* authTag size */ - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ } if (encryptSz < minLength) { @@ -8903,11 +9945,11 @@ static INLINE void Md5Rounds(int rounds, const byte* data, int sz) Md5 md5; int i; - wc_InitMd5(&md5); + wc_InitMd5(&md5); /* no error check on purpose, dummy round */ for (i = 0; i < rounds; i++) wc_Md5Update(&md5, data, sz); - wc_Md5Free(&md5) ; /* in case needed to release resources */ + wc_Md5Free(&md5); /* in case needed to release resources */ } @@ -8922,7 +9964,7 @@ static INLINE void ShaRounds(int rounds, const byte* data, int sz) for (i = 0; i < rounds; i++) wc_ShaUpdate(&sha, data, sz); - wc_ShaFree(&sha) ; /* in case needed to release resources */ + wc_ShaFree(&sha); /* in case needed to release resources */ } #endif @@ -8940,7 +9982,7 @@ static INLINE void Sha256Rounds(int rounds, const byte* data, int sz) wc_Sha256Update(&sha256, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha256Free(&sha256) ; /* in case needed to release resources */ + wc_Sha256Free(&sha256); /* in case needed to release resources */ } #endif @@ -8959,7 +10001,7 @@ static INLINE void Sha384Rounds(int rounds, const byte* data, int sz) wc_Sha384Update(&sha384, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha384Free(&sha384) ; /* in case needed to release resources */ + wc_Sha384Free(&sha384); /* in case needed to release resources */ } #endif @@ -8978,7 +10020,7 @@ static INLINE void Sha512Rounds(int rounds, const byte* data, int sz) wc_Sha512Update(&sha512, data, sz); /* no error check on purpose, dummy round */ } - wc_Sha512Free(&sha512) ; /* in case needed to release resources */ + wc_Sha512Free(&sha512); /* in case needed to release resources */ } #endif @@ -9144,9 +10186,11 @@ static int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, return VERIFY_MAC_ERROR; } + /* treat any faulure as verify MAC error */ if (ret != 0) - return VERIFY_MAC_ERROR; - return 0; + ret = VERIFY_MAC_ERROR; + + return ret; } @@ -9172,7 +10216,7 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) ivExtra = ssl->specs.block_size; } else if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ivExtra = AESGCM_EXP_IV_SZ; } @@ -9222,9 +10266,10 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, if (ssl->hsInfoOn) AddPacketName("Alert", &ssl->handShakeInfo); if (ssl->toInfoOn) - /* add record header back on to info + 2 byte level, data */ + /* add record header back on to info + alert bytes level/code */ AddPacketInfo("Alert", &ssl->timeoutInfo, input + *inOutIdx - - RECORD_HEADER_SZ, 2 + RECORD_HEADER_SZ, ssl->heap); + RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE, + ssl->heap); #endif /* make sure can read the message */ @@ -9242,9 +10287,17 @@ static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, WOLFSSL_MSG("Got alert"); if (*type == close_notify) { - WOLFSSL_MSG(" close notify"); + WOLFSSL_MSG("\tclose notify"); ssl->options.closeNotify = 1; } +#ifdef WOLFSSL_TLS13 + if (*type == decode_error) { + WOLFSSL_MSG(" decode error"); + } + if (*type == illegal_parameter) { + WOLFSSL_MSG(" illegal parameter"); + } +#endif WOLFSSL_ERROR(*type); if (IsEncryptionOn(ssl, 0)) { if (*inOutIdx + ssl->keys.padSz > totalSz) @@ -9317,6 +10370,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size) } while (ssl->buffers.inputBuffer.length < size); +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.inputBuffer.idx == 0) { + WOLFSSL_MSG("Data received"); + WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + } +#endif + return 0; } @@ -9398,7 +10459,7 @@ int ProcessReply(WOLFSSL* ssl) int ret = 0, type, readSz; int atomicUser = 0; word32 startIdx = 0; -#ifdef WOLFSSL_DTLS +#if defined(WOLFSSL_DTLS) int used; #endif @@ -9422,10 +10483,10 @@ int ProcessReply(WOLFSSL* ssl) readSz = RECORD_HEADER_SZ; - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - readSz = DTLS_RECORD_HEADER_SZ; - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + readSz = DTLS_RECORD_HEADER_SZ; + #endif /* get header or return error */ if (!ssl->options.dtls) { @@ -9436,9 +10497,10 @@ int ProcessReply(WOLFSSL* ssl) /* read ahead may already have header */ used = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; - if (used < readSz) + if (used < readSz) { if ((ret = GetInputData(ssl, readSz)) < 0) return ret; + } #endif } @@ -9455,15 +10517,15 @@ int ProcessReply(WOLFSSL* ssl) /* sanity checks before getting size at front */ if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 2] != OLD_HELLO_ID) { + ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) { WOLFSSL_MSG("Not a valid old client hello"); return PARSE_ERROR; } if (ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != SSLv3_MAJOR && + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR && ssl->buffers.inputBuffer.buffer[ - ssl->buffers.inputBuffer.idx + 3] != DTLS_MAJOR) { + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) { WOLFSSL_MSG("Not a valid version in old client hello"); return PARSE_ERROR; } @@ -9479,6 +10541,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.processReply = getRecordLayerHeader; continue; } + FALL_THROUGH; /* in the WOLFSSL_SERVER case, run the old client hello */ case runProcessOldClientHello: @@ -9513,6 +10576,7 @@ int ProcessReply(WOLFSSL* ssl) } #endif /* OLD_HELLO_ALLOWED */ + FALL_THROUGH; /* get the record layer header */ case getRecordLayerHeader: @@ -9540,6 +10604,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; ssl->options.processReply = getData; + FALL_THROUGH; /* retrieve record layer data */ case getData: @@ -9559,14 +10624,16 @@ int ProcessReply(WOLFSSL* ssl) #endif } - ssl->options.processReply = runProcessingOneMessage; + ssl->options.processReply = decryptMessage; startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + FALL_THROUGH; - /* the record layer is here */ - case runProcessingOneMessage: + /* decrypt message */ + case decryptMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + bufferStatic* in = &ssl->buffers.inputBuffer; - if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) - { ret = SanityCheckCipherText(ssl, ssl->curSize); if (ret < 0) return ret; @@ -9574,84 +10641,135 @@ int ProcessReply(WOLFSSL* ssl) if (atomicUser) { #ifdef ATOMIC_USER ret = ssl->ctx->DecryptVerifyCb(ssl, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, + in->buffer + in->idx, + in->buffer + in->idx, ssl->curSize, ssl->curRL.type, 1, &ssl->keys.padSz, ssl->DecryptVerifyCtx); - if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) - ssl->buffers.inputBuffer.idx += ssl->specs.block_size; - /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; #endif /* ATOMIC_USER */ } else { - ret = Decrypt(ssl, ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx, - ssl->curSize); - if (ret < 0) { - WOLFSSL_MSG("Decrypt failed"); - WOLFSSL_ERROR(ret); - #ifdef WOLFSSL_DTLS - /* If in DTLS mode, if the decrypt fails for any - * reason, pretend the datagram never happened. */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - ssl->buffers.inputBuffer.idx = - ssl->buffers.inputBuffer.length; - } - #endif /* WOLFSSL_DTLS */ - return DECRYPT_ERROR; + if (!ssl->options.tls1_3) { + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); } + else { + #ifdef WOLFSSL_TLS13 + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + + if (ret >= 0) { + /* handle success */ if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) ssl->buffers.inputBuffer.idx += ssl->specs.block_size; /* go past TLSv1.1 IV */ - if (ssl->specs.cipher_type == aead && - ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + if (CipherHasExpIV(ssl)) ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + } + else { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + } + #endif /* WOLFSSL_DTLS */ + return DECRYPT_ERROR; + } + } + + ssl->options.processReply = verifyMessage; + FALL_THROUGH; + + /* verify digest of message */ + case verifyMessage: + + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) { + if (!atomicUser) { ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, ssl->curSize, ssl->curRL.type, &ssl->keys.padSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR(ret); + return DECRYPT_ERROR; + } } - if (ret < 0) { - WOLFSSL_MSG("VerifyMac failed"); - WOLFSSL_ERROR(ret); - return DECRYPT_ERROR; - } + ssl->keys.encryptSz = ssl->curSize; ssl->keys.decryptedCur = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + /* Get the real content type from the end of the data. */ + ssl->keys.padSz++; + ssl->curRL.type = ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.length - ssl->keys.padSz]; + } +#endif } - #ifdef WOLFSSL_DTLS + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneMessage: + + #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { DtlsUpdateWindow(ssl); } - #endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ WOLFSSL_MSG("received record layer msg"); switch (ssl->curRL.type) { case handshake : /* debugging in DoHandShakeMsg */ - if (!ssl->options.dtls) { + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ret = DoDtlsHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#endif + } + else if (!IsAtLeastTLSv1_3(ssl->version)) { ret = DoHandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); } else { -#ifdef WOLFSSL_DTLS - ret = DoDtlsHandShakeMsg(ssl, +#ifdef WOLFSSL_TLS13 + ret = DoTls13HandShakeMsg(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, ssl->buffers.inputBuffer.length); +#else + ret = BUFFER_ERROR; #endif } if (ret != 0) @@ -9679,7 +10797,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; } else { -#ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_DTLS /* Check for duplicate CCS message in DTLS mode. * DTLS allows for duplicate messages, and it should be * skipped. Also skip if out of order. */ @@ -9699,7 +10817,7 @@ int ProcessReply(WOLFSSL* ssl) } ssl->buffers.inputBuffer.idx++; break; -#endif /* WOLFSSL_DTLS */ + #endif /* WOLFSSL_DTLS */ } } @@ -9754,6 +10872,12 @@ int ProcessReply(WOLFSSL* ssl) ssl->options.dtlsHsRetain = 0; } #endif + #ifdef WOLFSSL_TLS13 + if (ssl->keys.keyUpdateRespond) { + WOLFSSL_MSG("No KeyUpdate from peer seen"); + return SANITY_MSG_E; + } + #endif if ((ret = DoApplicationData(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx)) @@ -9795,18 +10919,18 @@ int ProcessReply(WOLFSSL* ssl) /* more messages per record */ else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) { WOLFSSL_MSG("More messages in record"); - #ifdef WOLFSSL_DTLS - /* read-ahead but dtls doesn't bundle messages per record */ - if (ssl->options.dtls) { - ssl->options.processReply = doProcessInit; - continue; - } - #endif + ssl->options.processReply = runProcessingOneMessage; if (IsEncryptionOn(ssl, 0)) { WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); - ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + return FATAL_ERROR; + } } continue; @@ -9863,9 +10987,10 @@ int SendChangeCipher(WOLFSSL* ssl) input[0] = 1; /* turn it on */ sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - change_cipher_spec, 0, 0); - if (sendSz < 0) + change_cipher_spec, 0, 0, 0); + if (sendSz < 0) { return sendSz; + } } #ifdef WOLFSSL_DTLS @@ -9924,127 +11049,200 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, WriteSEQ(ssl, verify, seq); if (ssl->specs.mac_algorithm == md5_mac) { - wc_InitMd5(&md5); - /* inner */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD1, padSz); - wc_Md5Update(&md5, seq, SEQ_SZ); - wc_Md5Update(&md5, conLen, sizeof(conLen)); - /* in buffer */ - wc_Md5Update(&md5, in, sz); - wc_Md5Final(&md5, result); - /* outer */ - wc_Md5Update(&md5, macSecret, digestSz); - wc_Md5Update(&md5, PAD2, padSz); - wc_Md5Update(&md5, result, digestSz); - wc_Md5Final(&md5, digest); - } - else { - ret = wc_InitSha(&sha); + ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId); if (ret != 0) return ret; + /* inner */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD1, padSz); - wc_ShaUpdate(&sha, seq, SEQ_SZ); - wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD1, padSz); + ret |= wc_Md5Update(&md5, seq, SEQ_SZ); + ret |= wc_Md5Update(&md5, conLen, sizeof(conLen)); /* in buffer */ - wc_ShaUpdate(&sha, in, sz); - wc_ShaFinal(&sha, result); + ret |= wc_Md5Update(&md5, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + /* outer */ - wc_ShaUpdate(&sha, macSecret, digestSz); - wc_ShaUpdate(&sha, PAD2, padSz); - wc_ShaUpdate(&sha, result, digestSz); - wc_ShaFinal(&sha, digest); + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD2, padSz); + ret |= wc_Md5Update(&md5, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_Md5Free(&md5); + } + else { + ret = wc_InitSha_ex(&sha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* inner */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD1, padSz); + ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ); + ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + /* in buffer */ + ret |= wc_ShaUpdate(&sha, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + /* outer */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD2, padSz); + ret |= wc_ShaUpdate(&sha, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_ShaFree(&sha); } return 0; } - -#ifndef NO_CERTS -static void BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) -{ - byte md5_result[MD5_DIGEST_SIZE]; - -#ifdef WOLFSSL_SMALL_STACK - Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Md5* md5_2 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); -#else - Md5 md5[1]; - Md5 md5_2[1]; -#endif - - /* make md5 inner */ - md5[0] = ssl->hsHashes->hashMd5 ; /* Save current position */ - wc_Md5Update(&ssl->hsHashes->hashMd5, ssl->arrays->masterSecret,SECRET_LEN); - wc_Md5Update(&ssl->hsHashes->hashMd5, PAD1, PAD_MD5); - wc_Md5GetHash(&ssl->hsHashes->hashMd5, md5_result); - wc_Md5RestorePos(&ssl->hsHashes->hashMd5, md5) ; /* Restore current position */ - - /* make md5 outer */ - wc_InitMd5(md5_2) ; - wc_Md5Update(md5_2, ssl->arrays->masterSecret, SECRET_LEN); - wc_Md5Update(md5_2, PAD2, PAD_MD5); - wc_Md5Update(md5_2, md5_result, MD5_DIGEST_SIZE); - - wc_Md5Final(md5_2, digest); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(md5_2, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif -} - - -static void BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) -{ - byte sha_result[SHA_DIGEST_SIZE]; - -#ifdef WOLFSSL_SMALL_STACK - Sha* sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - Sha* sha2 = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); -#else - Sha sha[1]; - Sha sha2[1]; -#endif - - /* make sha inner */ - sha[0] = ssl->hsHashes->hashSha ; /* Save current position */ - wc_ShaUpdate(&ssl->hsHashes->hashSha, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(&ssl->hsHashes->hashSha, PAD1, PAD_SHA); - wc_ShaGetHash(&ssl->hsHashes->hashSha, sha_result); - wc_ShaRestorePos(&ssl->hsHashes->hashSha, sha) ; /* Restore current position */ - - /* make sha outer */ - wc_InitSha(sha2) ; - wc_ShaUpdate(sha2, ssl->arrays->masterSecret,SECRET_LEN); - wc_ShaUpdate(sha2, PAD2, PAD_SHA); - wc_ShaUpdate(sha2, sha_result, SHA_DIGEST_SIZE); - - wc_ShaFinal(sha2, digest); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(sha2, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - -} -#endif /* NO_CERTS */ #endif /* NO_OLD_TLS */ #ifndef NO_CERTS -static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) +static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte md5_result[MD5_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + Md5* md5 = (Md5*)XMALLOC(sizeof(Md5), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#else + Md5 md5[1]; +#endif + + /* make md5 inner */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */ + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); + + /* make md5 outer */ + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, digest); + wc_Md5Free(md5); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* !NO_MD5 && !NO_OLD_TLS */ + +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) +static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte sha_result[SHA_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + Sha* sha = (Sha*)XMALLOC(sizeof(Sha), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#else + Sha sha[1]; +#endif + + /* make sha inner */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); + + /* make sha outer */ + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, digest); + wc_ShaFree(sha); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ + +int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) { int ret = 0; (void)hashes; if (ssl->options.tls) { -#if ! defined( NO_OLD_TLS ) - wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); - wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); -#endif + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) + ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); + if (ret != 0) + return ret; + #endif if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, @@ -10066,145 +11264,228 @@ static int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) #endif } } -#if ! defined( NO_OLD_TLS ) else { - BuildMD5_CertVerify(ssl, hashes->md5); - BuildSHA_CertVerify(ssl, hashes->sha); + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = BuildMD5_CertVerify(ssl, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + ret = BuildSHA_CertVerify(ssl, hashes->sha); + if (ret != 0) + return ret; + #endif } -#endif return ret; } #endif /* WOLFSSL_LEANPSK */ +/* Persistable BuildMessage arguments */ +typedef struct BuildMsgArgs { + word32 digestSz; + word32 sz; + word32 pad; + word32 idx; + word32 headerSz; + word16 size; + word32 ivSz; /* TLSv1.1 IV */ + byte iv[AES_BLOCK_SIZE]; /* max size */ +} BuildMsgArgs; + +static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) +{ + BuildMsgArgs* args = (BuildMsgArgs*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildMessage */ +} + /* Build SSL Message, encrypted */ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly) + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) { - word32 digestSz; - word32 sz = RECORD_HEADER_SZ + inSz; - word32 pad = 0, i; - word32 idx = RECORD_HEADER_SZ; - word32 ivSz = 0; /* TLSv1.1 IV */ - word32 headerSz = RECORD_HEADER_SZ; - word16 size; - byte iv[AES_BLOCK_SIZE]; /* max size */ - int ret = 0; - int atomicUser = 0; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + BuildMsgArgs* args = (BuildMsgArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + BuildMsgArgs args[1]; +#endif + + WOLFSSL_ENTER("BuildMessage"); if (ssl == NULL) { return BAD_FUNC_ARG; } - if (!sizeOnly && (output == NULL || input == NULL) ) { - return BAD_FUNC_ARG; - } - - /* catch mistaken sizeOnly parameter */ - if (sizeOnly && (output || input) ) { - WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); - return BAD_FUNC_ARG; - } - - digestSz = ssl->specs.hash_size; -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac) - digestSz = min(TRUNCATED_HMAC_SZ, digestSz); -#endif - sz += digestSz; - -#ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - sz += DTLS_RECORD_EXTRA; - idx += DTLS_RECORD_EXTRA; - headerSz += DTLS_RECORD_EXTRA; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly); } #endif -#ifdef ATOMIC_USER - if (ssl->ctx->MacEncryptCb) - atomicUser = 1; + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } + } #endif - if (ssl->specs.cipher_type == block) { - word32 blockSz = ssl->specs.block_size; - if (ssl->options.tls1_1) { - ivSz = blockSz; - sz += ivSz; + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); - if (ivSz > (word32)sizeof(iv)) - return BUFFER_E; + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsgArgs; + #endif + } - if (!sizeOnly) { - ret = wc_RNG_GenerateBlock(ssl->rng, iv, ivSz); - if (ret != 0) - return ret; + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + return BAD_FUNC_ARG; + } + if (sizeOnly && (output || input) ) { + WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); + return BAD_FUNC_ARG; } + ssl->options.buildMsgState = BUILD_MSG_SIZE; } - sz += 1; /* pad byte */ - pad = (sz - headerSz) % blockSz; - pad = blockSz - pad; - sz += pad; - } + FALL_THROUGH; + case BUILD_MSG_SIZE: + { + args->digestSz = ssl->specs.hash_size; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) + args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz); + #endif + args->sz += args->digestSz; -#ifdef HAVE_AEAD - if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - ivSz = AESGCM_EXP_IV_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sz += DTLS_RECORD_EXTRA; + args->idx += DTLS_RECORD_EXTRA; + args->headerSz += DTLS_RECORD_EXTRA; + } + #endif - sz += (ivSz + ssl->specs.aead_mac_size - digestSz); - if (!sizeOnly) { - XMEMCPY(iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + if (ssl->specs.cipher_type == block) { + word32 blockSz = ssl->specs.block_size; + if (ssl->options.tls1_1) { + args->ivSz = blockSz; + args->sz += args->ivSz; + + if (args->ivSz > (word32)sizeof(args->iv)) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + args->pad = (args->sz - args->headerSz) % blockSz; + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + args->ivSz = AESGCM_EXP_IV_SZ; + + args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz); + } + #endif + + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + + if (args->ivSz > 0) { + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + + } + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } + #endif + + args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ + AddRecordHeader(output, args->size, (byte)type, ssl); + + /* write to output */ + if (args->ivSz) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, sizeof(args->iv))); + args->idx += args->ivSz; + } + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; } - } -#endif - /* done with size calculations */ - if (sizeOnly) { - return sz; - } - if (sz > (word32)outSz) { - WOLFSSL_MSG("Oops, want to write past output buffer size"); - return BUFFER_E; - } - size = (word16)(sz - headerSz); /* include mac and digest */ - AddRecordHeader(output, size, (byte)type, ssl); + FALL_THROUGH; + case BUILD_MSG_HASH: + { + word32 i; - /* write to output */ - if (ivSz) { - XMEMCPY(output + idx, iv, min(ivSz, sizeof(iv))); - idx += ivSz; - } - XMEMCPY(output + idx, input, inSz); - idx += inSz; + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } + if (ssl->specs.cipher_type == block) { + word32 tmpIdx = args->idx + args->digestSz; - if (type == handshake && hashOutput) { - ret = HashOutput(ssl, output, headerSz + inSz, ivSz); - if (ret != 0) - return ret; - } + for (i = 0; i <= args->pad; i++) + output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */ + } - if (ssl->specs.cipher_type == block) { - word32 tmpIdx = idx + digestSz; + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* User Record Layer Callback handling */ + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx, + output + args->headerSz + args->ivSz, inSz, type, 0, + output + args->headerSz, output + args->headerSz, args->size, + ssl->MacEncryptCtx); + goto exit_buildmsg; + } + #endif - for (i = 0; i <= pad; i++) - output[tmpIdx++] = (byte)pad; /* pad byte gets pad value too */ - } - - if (atomicUser) { /* User Record Layer Callback handling */ -#ifdef ATOMIC_USER - if ( (ret = ssl->ctx->MacEncryptCb(ssl, output + idx, - output + headerSz + ivSz, inSz, type, 0, - output + headerSz, output + headerSz, size, - ssl->MacEncryptCtx)) != 0) - return ret; -#endif - } - else { - if (ssl->specs.cipher_type != aead) { -#ifdef HAVE_TRUNCATED_HMAC - if (ssl->truncated_hmac && ssl->specs.hash_size > digestSz) { + if (ssl->specs.cipher_type != aead) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && ssl->specs.hash_size > args->digestSz) { #ifdef WOLFSSL_SMALL_STACK byte* hmac = NULL; #else @@ -10212,36 +11493,64 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif #ifdef WOLFSSL_SMALL_STACK - hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, + hmac = (byte*)XMALLOC(MAX_DIGEST_SIZE, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (hmac == NULL) - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_buildmsg); #endif - ret = ssl->hmac(ssl, hmac, output + headerSz + ivSz, inSz, + ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz, type, 0); - XMEMCPY(output + idx, hmac, digestSz); + XMEMCPY(output + args->idx, hmac, args->digestSz); #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - } else -#endif - ret = ssl->hmac(ssl, output+idx, output + headerSz + ivSz, inSz, - type, 0); - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - } - if (ret != 0) - return ret; + } + else + #endif + ret = ssl->hmac(ssl, output + args->idx, output + args->headerSz + args->ivSz, + inSz, type, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + if (ret != 0) + goto exit_buildmsg; - if ( (ret = Encrypt(ssl, output + headerSz, output+headerSz,size)) != 0) - return ret; + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size, + asyncOkay); + break; + } } - return sz; +exit_buildmsg: + + WOLFSSL_LEAVE("BuildMessage", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); + + return ret; } @@ -10310,7 +11619,7 @@ int SendFinished(WOLFSSL* ssl) #endif sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -10540,7 +11849,7 @@ int SendCertificate(WOLFSSL* ssl) } sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); if (inputSz > 0) XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -10549,26 +11858,26 @@ int SendCertificate(WOLFSSL* ssl) return sendSz; } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif - #ifdef WOLFSSL_CALLBACKS - if (ssl->hsInfoOn) - AddPacketName("Certificate", &ssl->handShakeInfo); - if (ssl->toInfoOn) - AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, - ssl->heap); - #endif + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif ssl->buffers.outputBuffer.length += sendSz; if (!ssl->options.groupMessages) @@ -10696,7 +12005,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, switch (type) { case WOLFSSL_CSR2_OCSP_MULTI: length += OPAQUE24_LEN; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP: for (i = 0; i < count; i++) @@ -10743,7 +12052,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (sendSz < 0) @@ -10793,13 +12102,13 @@ int SendCertificateStatus(WOLFSSL* ssl) (void) ssl; - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - status_type = ssl->status_request; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + status_type = ssl->status_request; +#endif - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - status_type = status_type ? status_type : ssl->status_request_v2; - #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + status_type = status_type ? status_type : ssl->status_request_v2; +#endif switch (status_type) { @@ -10807,7 +12116,8 @@ int SendCertificateStatus(WOLFSSL* ssl) #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) /* case WOLFSSL_CSR_OCSP: */ - case WOLFSSL_CSR2_OCSP: { + case WOLFSSL_CSR2_OCSP: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer response; @@ -10817,7 +12127,7 @@ int SendCertificateStatus(WOLFSSL* ssl) if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) return 0; - if (!request || ssl->buffers.weOwnCert) { + if (request == NULL || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; #ifdef WOLFSSL_SMALL_STACK DecodedCert* cert = NULL; @@ -10829,15 +12139,15 @@ int SendCertificateStatus(WOLFSSL* ssl) if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -10845,44 +12155,50 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } if (ret == 0) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &response); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (response.buffer) { if (ret == 0) @@ -10896,14 +12212,16 @@ int SendCertificateStatus(WOLFSSL* ssl) if (request != ssl->ctx->certOcspRequest) XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + + break; } - break; #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 - case WOLFSSL_CSR2_OCSP_MULTI: { + case WOLFSSL_CSR2_OCSP_MULTI: + { OcspRequest* request = ssl->ctx->certOcspRequest; buffer responses[1 + MAX_CHAIN_DEPTH]; int i = 0; @@ -10916,25 +12234,25 @@ int SendCertificateStatus(WOLFSSL* ssl) if (!request || ssl->buffers.weOwnCert) { DerBuffer* der = ssl->buffers.certificate; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif /* unable to fetch status. skip. */ if (der->buffer == NULL || der->length == 0) return 0; - #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (cert == NULL) - return MEMORY_E; - #endif + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif InitDecodedCert(cert, der->buffer, der->length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -10942,45 +12260,50 @@ int SendCertificateStatus(WOLFSSL* ssl) else { request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - if (request == NULL) { - FreeDecodedCert(cert); - - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return MEMORY_E; + if (request) { + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } } - - ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); - } - else if (!ssl->buffers.weOwnCert && 0 == wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->certOcspRequest) - ssl->ctx->certOcspRequest = request; - - wc_UnLockMutex(&ssl->ctx->cm->ocsp_stapling->ocspLock); + else { + ret = MEMORY_E; } } FreeDecodedCert(cert); - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } if (ret == 0) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[0]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } if (request != ssl->ctx->certOcspRequest) @@ -10990,16 +12313,16 @@ int SendCertificateStatus(WOLFSSL* ssl) || ssl->buffers.weOwnCertChain)) { buffer der; word32 idx = 0; - #ifdef WOLFSSL_SMALL_STACK - DecodedCert* cert = NULL; - #else - DecodedCert cert[1]; - #endif + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif XMEMSET(&der, 0, sizeof(buffer)); #ifdef WOLFSSL_SMALL_STACK - cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (cert == NULL) return MEMORY_E; @@ -11016,7 +12339,7 @@ int SendCertificateStatus(WOLFSSL* ssl) break; InitDecodedCert(cert, der.buffer, der.length, ssl->heap); - + /* TODO: Setup async support here */ if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm)) != 0) { WOLFSSL_MSG("ParseCert failed"); @@ -11026,36 +12349,47 @@ int SendCertificateStatus(WOLFSSL* ssl) request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); if (request == NULL) { + FreeDecodedCert(cert); + ret = MEMORY_E; break; } ret = InitOcspRequest(request, cert, 0, ssl->heap); - if (ret != 0) { - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCertChain) { + wolfSSL_Mutex* ocspLock = + &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->chainOcspRequest[i] == NULL) + ssl->ctx->chainOcspRequest[i] = request; + wc_UnLockMutex(ocspLock); + } + } + } + else { + FreeDecodedCert(cert); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; break; } - else if (!ssl->buffers.weOwnCertChain && 0 == - wc_LockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock)) { - if (!ssl->ctx->chainOcspRequest[i]) - ssl->ctx->chainOcspRequest[i] = request; - - wc_UnLockMutex( - &ssl->ctx->cm->ocsp_stapling->ocspLock); - } + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[i + 1]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } if (request != ssl->ctx->chainOcspRequest[i]) - XFREE(request, ssl->heap,DYNAMIC_TYPE_OCSP_REQUEST); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); i++; } @@ -11063,42 +12397,46 @@ int SendCertificateStatus(WOLFSSL* ssl) FreeDecodedCert(cert); } - #ifdef WOLFSSL_SMALL_STACK - XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif } else { while (ret == 0 && NULL != (request = ssl->ctx->chainOcspRequest[i])) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[++i]); /* Suppressing, not critical */ - if (ret == OCSP_CERT_REVOKED - || ret == OCSP_CERT_UNKNOWN - || ret == OCSP_LOOKUP_FAIL) + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { ret = 0; + } } } if (responses[0].buffer) { if (ret == 0) ret = BuildCertificateStatus(ssl, status_type, - responses, i + 1); + responses, (byte)i + 1); for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) if (responses[i].buffer) XFREE(responses[i].buffer, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); } - } - break; + break; + } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ #endif /* NO_WOLFSSL_SERVER */ default: - break; + break; } return ret; @@ -11198,10 +12536,25 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) sendBuffer = comp; } #endif - sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0); - if (sendSz < 0) + if (!ssl->options.tls1_3) { + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); + } + else { +#ifdef WOLFSSL_TLS13 + sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0); +#else + sendSz = BUFFER_ERROR; +#endif + } + if (sendSz < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (sendSz == WC_PENDING_E) + ssl->error = sendSz; + #endif return BUILD_MSG_ERROR; + } ssl->buffers.outputBuffer.length += sendSz; @@ -11235,8 +12588,10 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) WOLFSSL_ENTER("ReceiveData()"); - if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) + /* reset error state */ + if (ssl->error == WANT_READ || ssl->error == WC_PENDING_E) { ssl->error = 0; + } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { @@ -11256,10 +12611,12 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) int err; WOLFSSL_MSG("Handshake not complete, trying to finish"); if ( (err = wolfSSL_negotiate(ssl)) != SSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT /* if async would block return WANT_WRITE */ if (ssl->error == WC_PENDING_E) { return WOLFSSL_CBIO_ERR_WANT_READ; } + #endif return err; } } @@ -11331,6 +12688,26 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) int outputSz; int dtlsExtra = 0; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + int notifyErr = 0; + + WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling"); + + if (type == close_notify) { + notifyErr = ZERO_RETURN; + } else if (severity == alert_fatal) { + notifyErr = FATAL_ERROR; + } + + if (notifyErr != 0) { + return NotifyWriteSide(ssl, notifyErr); + } + + return 0; + } +#endif + /* if sendalert is called again for nonblocking */ if (ssl->options.sendAlertState != 0) { ret = SendBuffered(ssl); @@ -11365,7 +12742,7 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) other side may not be able to handle it */ if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, - alert, 0, 0); + alert, 0, 0, 0); else { AddRecordHeader(output, ALERT_SIZE, alert, ssl); @@ -11596,8 +12973,8 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case NOT_CA_ERROR: return "Not a CA by basic constraint error"; - case BAD_PATH_ERROR: - return "Bad path for opendir error"; + case HTTP_TIMEOUT: + return "HTTP timeout for OCSP or CRL req"; case BAD_CERT_MANAGER_ERROR: return "Bad Cert Manager error"; @@ -11767,6 +13144,33 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case DECODE_E: return "Decode handshake message error"; + case WRITE_DUP_READ_E: + return "Write dup write side can't read error"; + + case WRITE_DUP_WRITE_E: + return "Write dup read side can't write error"; + + case INVALID_CERT_CTX_E: + return "Certificate context does not match request or not empty"; + + case BAD_KEY_SHARE_DATA: + return "The Key Share data contains group that was in Client Hello"; + + case MISSING_HANDSHAKE_DATA: + return "The handshake message is missing required data"; + + case BAD_BINDER: + return "Binder value does not match value server calculated"; + + case EXT_NOT_ALLOWED: + return "Extension type not allowed in handshake message type"; + + case INVALID_PARAMETER: + return "The security parameter is invalid"; + + case KEY_SHARE_ERROR: + return "Key share extension did not contain a valid named group"; + default : return "unknown error number"; } @@ -12222,6 +13626,27 @@ static const char* const cipher_names[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA "EDH-RSA-DES-CBC3-SHA", #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + "TLS13-AES128-GCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + "TLS13-AES256-GCM-SHA384", +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + "TLS13-CHACHA20-POLY1305-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + "TLS13-AES128-CCM-SHA256", +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + "TLS13-AES128-CCM-8-SHA256", +#endif + }; @@ -12668,6 +14093,27 @@ static int cipher_name_idx[] = #ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, #endif + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + TLS_AES_128_GCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + TLS_AES_256_GCM_SHA384, +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + TLS_CHACHA20_POLY1305_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + TLS_AES_128_CCM_SHA256, +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + TLS_AES_128_CCM_8_SHA256, +#endif + }; @@ -12944,8 +14390,38 @@ const char* wolfSSL_get_cipher_name_from_suite(const unsigned char cipherSuite, } /* ECC and AES CCM/GCM */ #endif /* HAVE_ECC || HAVE_AESCCM*/ + if (cipherSuite0 == TLS13_BYTE) { + /* TLS v1.3 suites */ + switch (cipherSuite) { +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_AESGCM + case TLS_AES_128_GCM_SHA256 : + return "TLS_AES_128_GCM_SHA256"; + case TLS_AES_256_GCM_SHA384 : + return "TLS_AES_256_GCM_SHA384"; + #endif + + #ifdef HAVE_CHACHA + case TLS_CHACHA20_POLY1305_SHA256 : + return "TLS_CHACHA20_POLY1305_SHA256"; + #endif + + #ifdef HAVE_AESCCM + case TLS_AES_128_CCM_SHA256 : + return "TLS_AES_128_CCM_SHA256"; + case TLS_AES_128_CCM_8_SHA256 : + return "TLS_AES_256_CCM_8_SHA256"; + #endif +#endif + + default: + return "NONE"; + } + } + if (cipherSuite0 != ECC_BYTE && - cipherSuite0 != CHACHA_BYTE) { + cipherSuite0 != CHACHA_BYTE && + cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (cipherSuite) { @@ -13142,11 +14618,11 @@ Set the enabled cipher suites. @param [out] suites Suites structure. @param [in] list List of cipher suites, only supports full name from - cipher_name[] delimited by ':'. + cipher_names[] delimited by ':'. @return true on success, else false. */ -int SetCipherList(Suites* suites, const char* list) +int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) { int ret = 0; int idx = 0; @@ -13161,7 +14637,8 @@ int SetCipherList(Suites* suites, const char* list) return 0; } - if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0) + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) return 1; /* wolfSSL defualt */ do { @@ -13179,17 +14656,35 @@ int SetCipherList(Suites* suites, const char* list) for (i = 0; i < suiteSz; i++) { if (XSTRNCMP(name, cipher_names[i], sizeof(name)) == 0) { - suites->suites[idx++] = (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE + #ifdef WOLFSSL_DTLS + /* don't allow stream ciphers with DTLS */ + if (ctx->method->version.major == DTLS_MAJOR) { + if (XSTRSTR(name, "RC4") || + XSTRSTR(name, "HC128") || + XSTRSTR(name, "RABBIT")) + { + WOLFSSL_MSG("Stream ciphers not supported with DTLS"); + continue; + } + + } + #endif /* WOLFSSL_DTLS */ + + suites->suites[idx++] = (XSTRSTR(name, "TLS13")) ? TLS13_BYTE + : (XSTRSTR(name, "CHACHA")) ? CHACHA_BYTE : (XSTRSTR(name, "QSH")) ? QSH_BYTE : (XSTRSTR(name, "EC")) ? ECC_BYTE : (XSTRSTR(name, "CCM")) ? ECC_BYTE : 0x00; /* normal */ - suites->suites[idx++] = (byte)cipher_name_idx[i]; /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA * suites don't necessarily have RSA in the name. */ - if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) + if (XSTRSTR(name, "TLS13")) { + haveRSAsig = 1; + haveECDSAsig = 1; + } + else if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) haveECDSAsig = 1; else if (XSTRSTR(name, "ADH")) haveAnon = 1; @@ -13209,20 +14704,32 @@ int SetCipherList(Suites* suites, const char* list) InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon); } + (void)ctx; + return ret; } #if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) -static void PickHashSigAlgo(WOLFSSL* ssl, - const byte* hashSigAlgo, word32 hashSigAlgoSz) +void PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) { word32 i; ssl->suites->sigAlgo = ssl->specs.sig_algo; - ssl->suites->hashAlgo = sha_mac; + + /* set defaults */ + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_ALLOW_TLS_SHA1 + ssl->suites->hashAlgo = sha_mac; + #else + ssl->suites->hashAlgo = sha256_mac; + #endif + } + else { + ssl->suites->hashAlgo = sha_mac; + } /* i+1 since peek a byte ahead for type */ - for (i = 0; (i+1) < hashSigAlgoSz; i += 2) { + for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { if (hashSigAlgo[i+1] == ssl->specs.sig_algo) { if (hashSigAlgo[i] == sha_mac) { break; @@ -13246,6 +14753,9 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #endif } + else if (ssl->specs.sig_algo == 0) { + ssl->suites->hashAlgo = ssl->specs.mac_algorithm; + } } } #endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ @@ -13348,7 +14858,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(info->packets[info->numberPackets].value, data, sz); else { info->packets[info->numberPackets].bufferValue = - XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); + (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); if (!info->packets[info->numberPackets].bufferValue) /* let next alloc catch, just don't fill, not fatal here */ info->packets[info->numberPackets].valueSz = 0; @@ -13410,6 +14920,12 @@ static void PickHashSigAlgo(WOLFSSL* ssl, int ret; word16 extSz = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return SendTls13ClientHello(ssl); +#endif + if (ssl->suites == NULL) { WOLFSSL_MSG("Bad suites pointer in SendClientHello"); return SUITES_ERROR; @@ -13485,23 +15001,23 @@ static void PickHashSigAlgo(WOLFSSL* ssl, output[idx++] = ssl->version.minor; ssl->chVersion = ssl->version; /* store in case changed */ - /* then random */ + /* then random */ if (ssl->options.connectState == CONNECT_BEGIN) { ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); if (ret != 0) return ret; - /* store random */ + /* store random */ XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); } else { #ifdef WOLFSSL_DTLS - /* send same random on hello again */ + /* send same random on hello again */ XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); #endif } idx += RAN_LEN; - /* then session id */ + /* then session id */ output[idx++] = (byte)idSz; if (idSz) { XMEMCPY(output + idx, ssl->session.sessionID, @@ -13509,7 +15025,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, idx += ssl->session.sessionIDSz; } - /* then DTLS cookie */ + /* then DTLS cookie */ #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { byte cookieSz = ssl->arrays->cookieSz; @@ -13521,13 +15037,13 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } } #endif - /* then cipher suites */ + /* then cipher suites */ c16toa(ssl->suites->suiteSz, output + idx); - idx += 2; + idx += OPAQUE16_LEN; XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); idx += ssl->suites->suiteSz; - /* last, compression */ + /* last, compression */ output[idx++] = COMP_LEN; if (ssl->options.usingCompression) output[idx++] = ZLIB_COMPRESSION; @@ -13582,7 +15098,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); + handshake, 1, 0, 0); XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (sendSz < 0) @@ -13691,8 +15207,81 @@ static void PickHashSigAlgo(WOLFSSL* ssl, return ret; } - static int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, - word32 helloSz) + /* Check the version in the received message is valid and set protocol + * version to use. + * + * ssl The SSL/TLS object. + * pv The protocol version from the packet. + * returns 0 on success, otherwise failure. + */ + int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) + { +#ifdef WOLFSSL_TLS13 + /* TODO: [TLS13] Remove this. + * Translate the draft TLS v1.3 version to final version. + */ + if (pv.major == TLS_DRAFT_MAJOR) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + } +#endif + + /* Check for upgrade attack. */ + if (pv.minor > ssl->version.minor) { + WOLFSSL_MSG("Server using higher version, fatal error"); + return VERSION_ERROR; + } + if (pv.minor < ssl->version.minor) { + WOLFSSL_MSG("server using lower version"); + + /* Check for downgrade attack. */ + if (!ssl->options.downgrade) { + WOLFSSL_MSG("\tno downgrade allowed, fatal error"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled && + ssl->options.handShakeDone) { + WOLFSSL_MSG("Server changed version during scr"); + return VERSION_ERROR; + } + #endif + + /* Checks made - OK to downgrade. */ + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG("\tdowngrading to SSLv3"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + else if (pv.minor == TLSv1_MINOR) { + /* turn off tls 1.1+ */ + WOLFSSL_MSG("\tdowngrading to TLSv1"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } + } + + return 0; + } + + int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) { byte cs0; /* cipher suite bytes 0, 1 */ byte cs1; @@ -13700,6 +15289,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, byte compression; word32 i = *inOutIdx; word32 begin = i; + int ret; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); @@ -13714,49 +15304,14 @@ static void PickHashSigAlgo(WOLFSSL* ssl, XMEMCPY(&pv, input + i, OPAQUE16_LEN); i += OPAQUE16_LEN; - if (pv.minor > ssl->version.minor) { - WOLFSSL_MSG("Server using higher version, fatal error"); - return VERSION_ERROR; - } - else if (pv.minor < ssl->version.minor) { - WOLFSSL_MSG("server using lower version"); + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; - if (!ssl->options.downgrade) { - WOLFSSL_MSG(" no downgrade allowed, fatal error"); - return VERSION_ERROR; - } - if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); - return VERSION_ERROR; - } - - #ifdef HAVE_SECURE_RENEGOTIATION - if (ssl->secure_renegotiation && - ssl->secure_renegotiation->enabled && - ssl->options.handShakeDone) { - WOLFSSL_MSG("Server changed version during scr"); - return VERSION_ERROR; - } - #endif - - if (pv.minor == SSLv3_MINOR) { - /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); - ssl->options.tls = 0; - ssl->options.tls1_1 = 0; - ssl->version.minor = SSLv3_MINOR; - } - else if (pv.minor == TLSv1_MINOR) { - /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); - ssl->options.tls1_1 = 0; - ssl->version.minor = TLSv1_MINOR; - } - else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); - ssl->version.minor = TLSv1_1_MINOR; - } - } +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(pv)) + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz); +#endif /* random */ XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); @@ -13818,7 +15373,6 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_TLS_EXTENSIONS if ( (i - begin) < helloSz) { if (TLSX_SupportExtensions(ssl)) { - int ret = 0; word16 totalExtSz; if ((i - begin) + OPAQUE16_LEN > helloSz) @@ -13911,7 +15465,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef HAVE_SECRET_CALLBACK if (ssl->sessionSecretCb != NULL) { - int secretSz = SECRET_LEN, ret; + int secretSz = SECRET_LEN; ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, &secretSz, ssl->sessionSecretCtx); if (ret != 0 || secretSz != SECRET_LEN) @@ -13922,20 +15476,20 @@ static void PickHashSigAlgo(WOLFSSL* ssl, if (ssl->options.resuming) { if (DSH_CheckSessionId(ssl)) { if (SetCipherSpecs(ssl) == 0) { - int ret = -1; XMEMCPY(ssl->arrays->masterSecret, ssl->session.masterSecret, SECRET_LEN); - #ifdef NO_OLD_TLS + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + ret = -1; /* default value */ + #ifndef NO_TLS + if (ssl->options.tls) ret = DeriveTlsKeys(ssl); - #else - #ifndef NO_TLS - if (ssl->options.tls) - ret = DeriveTlsKeys(ssl); - #endif - if (!ssl->options.tls) - ret = DeriveKeys(ssl); - #endif + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif /* NO_OLD_TLS */ ssl->options.serverState = SERVER_HELLODONE_COMPLETE; return ret; @@ -14139,71 +15693,78 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #endif /* HAVE_ECC */ +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ +#if !defined(NO_DH) || defined(HAVE_ECC) + byte* verifySig; +#endif + word32 idx; + word32 begin; +#ifndef NO_RSA + int typeH; +#endif +#if !defined(NO_DH) || defined(HAVE_ECC) + word16 verifySigSz; +#endif + word16 sigSz; + byte sigAlgo; +} DskeArgs; + +static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) +{ + DskeArgs* args = (DskeArgs*)pArgs; + + (void)ssl; + (void)args; + +#if !defined(NO_DH) || defined(HAVE_ECC) + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif +} + static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - word16 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; -#ifndef NO_RSA - int typeH = 0; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + DskeArgs* args = (DskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + DskeArgs args[1]; #endif - byte* output = NULL; - byte sigAlgo = ssl->specs.sig_algo; - word16 sigSz = 0; -#if !defined(NO_DH) || defined(HAVE_ECC) - byte* verifySig = NULL; -#endif - - (void)output; - (void)sigAlgo; - (void)sigSz; WOLFSSL_ENTER("DoServerKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dske; - } - else { - /* Restore variables needed for async */ - idx = ssl->async.idx; - length = ssl->async.length; - output = ssl->async.output; - sigSz = ssl->async.sigSz; - #ifndef NO_RSA - typeH = ssl->async.hashAlgo; - #endif - sigAlgo = ssl->async.sigAlgo; - #if !defined(NO_DH) || defined(HAVE_ECC) - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DskeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + args->sigAlgo = ssl->specs.sig_algo; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -14218,38 +15779,42 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; - idx += length; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; break; } #endif /* !NO_PSK */ #ifndef NO_DH case diffie_hellman_kea: { + word16 length; + /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14260,7 +15825,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14268,25 +15833,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14294,23 +15860,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = - (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH); + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14318,8 +15885,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH */ @@ -14328,24 +15896,27 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, { byte b; int curveId, curveOid; + word16 length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } + ssl->ecdhCurveOID = curveOid; - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14372,12 +15943,12 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + idx, length, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14386,33 +15957,35 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case dhe_psk_kea: { int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; - idx += length; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; /* p */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14423,7 +15996,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer) { ssl->buffers.serverDH_P.length = length; } @@ -14431,25 +16004,26 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_P.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; ssl->options.dhKeySz = length; /* g */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer) { ssl->buffers.serverDH_G.length = length; } @@ -14457,23 +16031,24 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_G.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; /* pub */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC(length, - ssl->heap, DYNAMIC_TYPE_DH); + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer) { ssl->buffers.serverDH_Pub.length = length; } @@ -14481,8 +16056,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ERROR_OUT(MEMORY_ERROR, exit_dske); } - XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + idx, length); - idx += length; + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; break; } #endif /* !NO_DH || !NO_PSK */ @@ -14492,75 +16068,79 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, byte b; int curveOid, curveId; int srvHintLen; + word16 length; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* get PSK server hint from the wire */ - srvHintLen = min(length, MAX_PSK_ID_LEN - 1); - XMEMCPY(ssl->arrays->server_hint, input + idx, srvHintLen); - ssl->arrays->server_hint[srvHintLen] = 0; + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ - idx += length; + args->idx += length; - if ((idx - begin) + ENUM_LEN + OPAQUE16_LEN + + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } /* Check curve name and ID */ - b = input[idx++]; + b = input[args->idx++]; if (b != named_curve) { ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); } - idx += 1; /* curve type, eat leading 0 */ - b = input[idx++]; + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } - length = input[idx++]; - if ((idx - begin) + length > size) { + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); + ssl->heap, DYNAMIC_TYPE_ECC); if (ssl->peerEccKey == NULL) { WOLFSSL_MSG("PeerEccKey Memory error"); ERROR_OUT(MEMORY_E, exit_dske); } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); if (ret != 0) { goto exit_dske; } } else if (ssl->peerEccKeyPresent) { /* don't leak on reuse */ wc_ecc_free(ssl->peerEccKey); ssl->peerEccKeyPresent = 0; - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, + ssl->devId); if (ret != 0) { goto exit_dske; } } curveId = wc_ecc_get_oid(curveOid, NULL, NULL); - if (wc_ecc_import_x963_ex(input + idx, length, + if (wc_ecc_import_x963_ex(input + args->idx, length, ssl->peerEccKey, curveId) != 0) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); } - idx += length; + args->idx += length; ssl->peerEccKeyPresent = 1; break; } @@ -14575,10 +16155,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch(ssl->specs.kea) { @@ -14604,37 +16185,40 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } - verifySz = (word16)(idx - begin); + verifySz = (word16)(args->idx - args->begin); if (verifySz > MAX_DH_SZ) { ERROR_OUT(BUFFER_ERROR, exit_dske); } if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > + size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; + hashAlgo = input[args->idx++]; + args->sigAlgo = input[args->idx++]; switch (hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -14650,7 +16234,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, /* only using sha and md5 for rsa */ #ifndef NO_OLD_TLS hashType = WC_HASH_TYPE_SHA; - if (sigAlgo == rsa_sa_algo) { + if (args->sigAlgo == rsa_sa_algo) { hashType = WC_HASH_TYPE_MD5_SHA; } #else @@ -14658,18 +16242,18 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, #endif } #ifndef NO_RSA - typeH = wc_HashGetOID(hashType); + args->typeH = wc_HashGetOID(hashType); #endif /* signature */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } - ato16(input + idx, &length); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->verifySigSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->verifySigSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dske); } @@ -14696,7 +16280,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN], ssl->arrays->serverRandom, RAN_LEN); XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], - input + begin, verifySz); /* message */ + input + args->begin, verifySz); /* message */ /* Perform hash */ ret = wc_Hash(hashType, @@ -14706,7 +16290,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, goto exit_dske; } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: @@ -14730,7 +16314,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, default: ret = ALGO_ID_E; - } /* switch (sigAlgo) */ + } /* switch (args->sigAlgo) */ #endif /* NO_DH && !HAVE_ECC */ break; @@ -14745,10 +16329,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -14770,23 +16355,25 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, break; } - if (verifySig == NULL) { - verifySig = (byte*)XMALLOC(length, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->verifySigSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_dske); } - XMEMCPY(verifySig, input + idx, length); + XMEMCPY(args->verifySig, input + args->idx, + args->verifySigSz); } - switch (sigAlgo) + switch (args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: { ret = RsaVerify(ssl, - verifySig, length, - &output, + args->verifySig, args->verifySigSz, + &args->output, + rsa_sa_algo, no_mac, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -14798,7 +16385,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, ); if (ret >= 0) { - sigSz = (word16)ret; + args->sigSz = (word16)ret; ret = 0; } break; @@ -14808,7 +16395,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, case ecc_dsa_sa_algo: { ret = EccVerify(ssl, - verifySig, length, + args->verifySig, args->verifySigSz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, @@ -14820,6 +16407,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, NULL, 0, NULL #endif ); + break; } #endif /* HAVE_ECC */ @@ -14840,10 +16428,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -14866,9 +16455,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* increment index after verify is done */ - idx += length; + args->idx += args->verifySigSz; - switch(sigAlgo) + switch(args->sigAlgo) { #ifndef NO_RSA case rsa_sa_algo: @@ -14891,9 +16480,9 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, encSigSz = wc_EncodeSignature(encodedSig, ssl->buffers.digest.buffer, - ssl->buffers.digest.length, typeH); - if (encSigSz != sigSz || !output || - XMEMCMP(output, encodedSig, + ssl->buffers.digest.length, args->typeH); + if (encSigSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { ret = VERIFY_SIGN_ERROR; } @@ -14904,9 +16493,11 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, goto exit_dske; } } - else if (sigSz != FINISHED_SZ || !output || - XMEMCMP(output, ssl->buffers.digest.buffer, - FINISHED_SZ) != 0) { + else if (args->sigSz != FINISHED_SZ || + !args->output || + XMEMCMP(args->output, + ssl->buffers.digest.buffer, + FINISHED_SZ) != 0) { ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske); } break; @@ -14933,13 +16524,14 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { if (IsEncryptionOn(ssl, 0)) { - idx += ssl->keys.padSz; + args->idx += ssl->keys.padSz; } /* QSH extensions */ @@ -14949,17 +16541,17 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, int qshSz; /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ - if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + idx, + if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx, size, 0)) < 0) { ERROR_OUT(qshSz, exit_dske); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent server ignored handshake */ @@ -14968,69 +16560,39 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, } #endif - /* Check for error */ - if (ret != 0) { - goto exit_dske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* return index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dske: WOLFSSL_LEAVE("DoServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.output = output; - ssl->async.sigSz = sigSz; - #ifndef NO_RSA - ssl->async.hashAlgo = typeH; - #endif - ssl->async.sigAlgo = sigAlgo; - #if !defined(NO_DH) || defined(HAVE_ECC) - ssl->async.data = verifySig; - #endif - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_server_key_exchange = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ -#if !defined(NO_DH) || defined(HAVE_ECC) - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } -#endif - /* Final cleanup */ + FreeDskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -15171,6 +16733,11 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Encrypting QSH key material"); switch (key->name) { @@ -15193,12 +16760,16 @@ static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, /* Decrypt using Quantum Safe Handshake algorithms */ -int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, - byte* out, word16* szOut) +int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut) { int ret = 0; word16 size = *szOut; + (void)in; + (void)szIn; + (void)out; + (void)szOut; + WOLFSSL_MSG("Decrypting QSH key material"); switch (key->name) { @@ -15225,12 +16796,14 @@ int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, */ static word32 QSH_MaxSecret(QSHKey* key) { + int ret = 0; +#ifdef HAVE_NTRU byte isNtru = 0; word16 inSz = 48; word16 outSz; DRBG_HANDLE drbg = 0; byte bufIn[48]; - int ret = 0; +#endif if (key == NULL || key->pub.length == 0) return 0; @@ -15252,6 +16825,7 @@ static word32 QSH_MaxSecret(QSHKey* key) return 0; } +#ifdef HAVE_NTRU if (isNtru) { ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); if (ret != DRBG_OK) @@ -15262,10 +16836,11 @@ static word32 QSH_MaxSecret(QSHKey* key) return NTRU_ENCRYPT_ERROR; } ntru_crypto_drbg_uninstantiate(drbg); - return outSz; + ret = outSz; } +#endif - return 0; + return ret; } /* Generate the secret byte material for pms @@ -15406,59 +16981,67 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) #endif /* HAVE_QSH */ +typedef struct SckeArgs { + byte* output; /* not allocated */ + byte* encSecret; + byte* input; + word32 encSz; + word32 length; + int sendSz; + int inputSz; +} SckeArgs; + +static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs) +{ + SckeArgs* args = (SckeArgs*)pArgs; + + (void)ssl; + + if (args->encSecret) { + XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->encSecret = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} + int SendClientKeyExchange(WOLFSSL* ssl) { int ret = 0; - int sendSz = 0; - word32 length_lcl = 0; - word32* length = &length_lcl; - byte* output = NULL; - byte* encSecret = NULL; - word32 encSz = 0; - - (void)length; +#ifdef WOLFSSL_ASYNC_CRYPT + SckeArgs* args = (SckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + SckeArgs args[1]; +#endif WOLFSSL_ENTER("SendClientKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - /* use async pointer for length */ - length = &ssl->async.length; - - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_scke; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - encSecret = ssl->async.data; - encSz = ssl->async.sigSz; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSckeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -15524,20 +17107,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, - ssl->peerEccKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey); + break; #endif /* HAVE_ECC && !NO_PSK */ #ifdef HAVE_NTRU @@ -15580,19 +17157,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* create private key */ - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_scke; } - ret = EccMakeKey(ssl, (ecc_key*)ssl->sigKey, peerKey); + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey); + break; } #endif /* HAVE_ECC */ @@ -15607,15 +17179,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - encSz = MAX_ENCRYPT_SZ; - encSecret = (byte*)XMALLOC(MAX_ENCRYPT_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (encSecret == NULL) { + args->encSz = MAX_ENCRYPT_SZ; + args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->encSecret == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -15640,11 +17213,31 @@ int SendClientKeyExchange(WOLFSSL* ssl) case diffie_hellman_kea: { ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->encSecret, &args->encSz); break; } #endif /* !NO_DH */ @@ -15659,23 +17252,25 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - encSz = (word32)XSTRLEN(ssl->arrays->client_identity); - if (encSz > MAX_PSK_ID_LEN) { + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (args->encSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } - XMEMCPY(encSecret, - ssl->arrays->client_identity, encSz); + XMEMCPY(args->encSecret, ssl->arrays->client_identity, + args->encSz); /* make psk pre master secret */ /* length of key + length 0s + length of key + key */ c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMSET(pms, 0, ssl->arrays->psk_keySz); pms += ssl->arrays->psk_keySz; c16toa((word16)ssl->arrays->psk_keySz, pms); - pms += 2; + pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) + + (2 * OPAQUE16_LEN); ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); ssl->arrays->psk_keySz = 0; /* No further need */ break; @@ -15685,7 +17280,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case dhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, @@ -15694,6 +17289,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { @@ -15701,19 +17297,39 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->buffers.sig.length = ENCRYPT_LEN; - ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - c16toa((word16)esSz, output); - output += OPAQUE16_LEN; - XMEMCPY(output, ssl->arrays->client_identity, esSz); - output += esSz; - encSz = esSz + OPAQUE16_LEN; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; - *length = 0; + args->length = 0; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, &ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -15721,7 +17337,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecdhe_psk_kea: { word32 esSz = 0; - output = encSecret; + args->output = args->encSecret; /* Send PSK client identity */ ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, @@ -15731,21 +17347,25 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { ERROR_OUT(PSK_KEY_ERROR, exit_scke); } - + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ esSz = (word32)XSTRLEN(ssl->arrays->client_identity); if (esSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_scke); } /* place size and identity in output buffer sz:identity */ - c16toa((word16)esSz, output); - output += OPAQUE16_LEN; - XMEMCPY(output, ssl->arrays->client_identity, esSz); - output += esSz; - encSz = esSz + OPAQUE16_LEN; + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; /* length is used for public key size */ - *length = MAX_ENCRYPT_SZ; + args->length = MAX_ENCRYPT_SZ; + + /* Create shared ECC key leaving room at the begining + of buffer for size of shared key. */ + ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ @@ -15754,12 +17374,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - output + OPAQUE8_LEN, length); + /* Place ECC key in output buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } + break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -15773,14 +17394,16 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->arrays->preMasterSz = SECRET_LEN; - encSz = MAX_ENCRYPT_SZ; + args->encSz = MAX_ENCRYPT_SZ; break; } #endif /* HAVE_NTRU */ #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { - #ifdef HAVE_PK_CALLBACKS + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { break; @@ -15788,8 +17411,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) #endif /* Place ECC key in buffer, leaving room for size */ - ret = wc_ecc_export_x963((ecc_key*)ssl->sigKey, - encSecret + OPAQUE8_LEN, &encSz); + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz); if (ret != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); } @@ -15807,10 +17430,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -15819,7 +17443,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) { ret = RsaEnc(ssl, ssl->arrays->preMasterSecret, SECRET_LEN, - encSecret, &encSz, + args->encSecret, &args->encSz, ssl->peerRsaKey, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.peerRsaKey.buffer, @@ -15829,19 +17453,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) NULL, 0, NULL #endif ); + break; } #endif /* !NO_RSA */ #ifndef NO_DH case diffie_hellman_kea: { - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - encSecret, &encSz, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret, @@ -15858,13 +17478,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, - ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - output + OPAQUE16_LEN, length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, @@ -15875,13 +17490,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - /* Create shared ECC key leaving room at the begining - of buffer for size of shared key. */ - ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; - - ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, ssl->peerEccKey, - output + OPAQUE8_LEN, length, + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSharedSecret(ssl, key, ssl->peerEccKey, + args->output + OPAQUE8_LEN, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -15908,8 +17519,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->peerNtruKey, ssl->arrays->preMasterSz, ssl->arrays->preMasterSecret, - (word16*)&encSz, - encSecret); + (word16*)&args->encSz, + args->encSecret); ntru_crypto_drbg_uninstantiate(drbg); if (rc != NTRU_OK) { ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); @@ -15921,14 +17532,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef HAVE_ECC case ecc_diffie_hellman_kea: { + ecc_key* key = (ecc_key*)ssl->hsKey; ecc_key* peerKey = (ssl->specs.static_ecdh) ? ssl->peerEccDsaKey : ssl->peerEccKey; - ssl->arrays->preMasterSz = ENCRYPT_LEN; - ret = EccSharedSecret(ssl, - (ecc_key*)ssl->sigKey, peerKey, - encSecret + OPAQUE8_LEN, &encSz, + key, peerKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_CLIENT_END, @@ -15938,6 +17548,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) NULL #endif ); + break; } #endif /* HAVE_ECC */ @@ -15952,10 +17563,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -15980,15 +17592,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; + byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length == 0) { + if (args->output == NULL || args->length == 0) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } - c16toa((word16)*length, output); - encSz += *length + OPAQUE16_LEN; + c16toa((word16)args->length, args->output); + args->encSz += args->length + OPAQUE16_LEN; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -16011,13 +17623,13 @@ int SendClientKeyExchange(WOLFSSL* ssl) byte* pms = ssl->arrays->preMasterSecret; /* validate args */ - if (output == NULL || *length > ENCRYPT_LEN) { + if (args->output == NULL || args->length > ENCRYPT_LEN) { ERROR_OUT(BAD_FUNC_ARG, exit_scke); } /* place size of public key in output buffer */ - *output = (byte)*length; - encSz += *length + OPAQUE8_LEN; + *args->output = (byte)args->length; + args->encSz += args->length + OPAQUE8_LEN; /* Create pre master secret is the concatination of eccSize + eccSharedKey + pskSize + pskKey */ @@ -16046,8 +17658,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) case ecc_diffie_hellman_kea: { /* place size of public key in buffer */ - *encSecret = (byte)encSz; - encSz += OPAQUE8_LEN; + *args->encSecret = (byte)args->encSz; + args->encSz += OPAQUE8_LEN; break; } #endif /* HAVE_ECC */ @@ -16062,10 +17674,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { word32 tlsSz = 0; word32 idx = 0; @@ -16087,50 +17700,50 @@ int SendClientKeyExchange(WOLFSSL* ssl) tlsSz = 0; } - idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; - sendSz = encSz + tlsSz + idx; + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->encSz + tlsSz + idx; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; - sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } #ifdef HAVE_QSH - encSz += qshSz; - sendSz += qshSz; + args->encSz += qshSz; + args->sendSz += qshSz; #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scke; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { byte idxSave = idx; - idx = sendSz - qshSz; + idx = args->sendSz - qshSz; if (QSH_KeyExchangeWrite(ssl, 0) != 0) { ERROR_OUT(MEMORY_E, exit_scke); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + idx) > qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_scke); } @@ -16138,52 +17751,69 @@ int SendClientKeyExchange(WOLFSSL* ssl) } #endif - AddHeaders(output, encSz + tlsSz, client_key_exchange, ssl); + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl); #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - encSz -= qshSz; + args->encSz -= qshSz; } #endif if (tlsSz) { - c16toa((word16)encSz, &output[idx]); - idx += 2; + c16toa((word16)args->encSz, &args->output[idx]); + idx += OPAQUE16_LEN; } - XMEMCPY(output + idx, encSecret, encSz); - idx += encSz; + XMEMCPY(args->output + idx, args->encSecret, args->encSz); + idx += args->encSz; if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = idx-RECORD_HEADER_SZ; /* buildmsg adds rechdr */ - - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (sendSz < 0) { - ERROR_OUT(sendSz, exit_scke); + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_scke; + #endif + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); - if (ret != 0) { - goto exit_scke; - } + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scke; } #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_scke; } } @@ -16194,21 +17824,10 @@ int SendClientKeyExchange(WOLFSSL* ssl) AddPacketName("ClientKeyExchange", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ClientKeyExchange", &ssl->timeoutInfo, - output, sendSz, ssl->heap); + args->output, args->sendSz, ssl->heap); #endif - /* Check for error */ - if (ret != 0) { - goto exit_scke; - } - - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ - - case KEYSHARE_END: - { - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16224,45 +17843,24 @@ int SendClientKeyExchange(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_scke: WOLFSSL_LEAVE("SendClientKeyExchange", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - length_lcl = ssl->async.length; - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.data = encSecret; - ssl->async.sigSz = encSz; - ssl->async.length = length_lcl; - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } - } + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; #endif /* No further need for PMS */ ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); ssl->arrays->preMasterSz = 0; - if (encSecret) { - XFREE(encSecret, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - encSecret = NULL; - } - /* Final cleanup */ + FreeSckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16270,173 +17868,218 @@ exit_scke: #ifndef NO_CERTS +/* Decode the private key - RSA or ECC - and creates a key object. + * The signature type is set as well. + * The maximum length of a signature is returned. + * + * ssl The SSL/TLS object. + * length The length of a signature. + * returns 0 on success, otherwise failure. + */ +int DecodePrivateKey(WOLFSSL *ssl, word16* length) +{ + int ret; + int keySz; + word32 idx; + + /* make sure private key exists */ + if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) { + WOLFSSL_MSG("Private key missing!"); + ERROR_OUT(NO_PRIVATE_KEY, exit_dpk); + } + +#ifndef NO_RSA + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + WOLFSSL_MSG("Trying RSA private key"); + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an RSA private key. */ + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using RSA private key"); + + /* It worked so check it meeets minimum key size requirements. */ + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_dpk); + } + + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)keySz; + + goto exit_dpk; + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +#ifndef NO_RSA + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif /* !NO_RSA */ + + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + +#ifndef NO_RSA + WOLFSSL_MSG("Trying ECC private key, RSA didn't work"); +#else + WOLFSSL_MSG("Trying ECC private key"); +#endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ECC private key. */ + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + WOLFSSL_MSG("Bad client cert type"); + goto exit_dpk; + } + + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = wc_ecc_sig_size((ecc_key*)ssl->hsKey); +#endif + +exit_dpk: + return ret; +} + + +typedef struct ScvArgs { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 extraSz; + word32 sigSz; + int sendSz; + int length; + int inputSz; +} ScvArgs; + +static void FreeScvArgs(WOLFSSL* ssl, void* pArgs) +{ + ScvArgs* args = (ScvArgs*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} int SendCertificateVerify(WOLFSSL* ssl) { - byte* output = NULL; - int sendSz = 0, length = 0, ret; - byte* verify = NULL; - word32 idx = 0; - word32 extraSz = 0; -#ifndef NO_RSA - byte* verifySig = NULL; + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ScvArgs* args = (ScvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + ScvArgs args[1]; #endif WOLFSSL_ENTER("SendCertificateVerify"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_scv; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - extraSz = ssl->async.sigSz; - length = ssl->async.length; - idx = ssl->async.idx; - #ifndef NO_RSA - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ScvArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { if (ssl->options.sendVerify == SEND_BLANK_CERT) { return 0; /* sent blank cert, can't verify */ } - sendSz = MAX_CERT_VERIFY_SZ; + args->sendSz = MAX_CERT_VERIFY_SZ; if (IsEncryptionOn(ssl, 1)) { - sendSz += MAX_MSG_EXTRA; + args->sendSz += MAX_MSG_EXTRA; } /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_scv; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { - int keySz; - int typeH = 0; + int typeH; ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); if (ret != 0) { goto exit_scv; } - #ifndef NO_RSA - ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scv); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, ssl->devId); + /* Decode private key. */ + ret = DecodePrivateKey(ssl, (word16*)&args->length); if (ret != 0) { goto exit_scv; } - WOLFSSL_MSG("Trying RSA client cert"); - - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, - (RsaKey*)ssl->sigKey, ssl->buffers.key->length); - if (ret == 0) { - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); - if (keySz < 0) { /* check if keySz has error case */ - ERROR_OUT(keySz, exit_scv); - } - - length = (word32)keySz; - if (keySz < ssl->options.minRsaKeySz) { - WOLFSSL_MSG("RSA key size too small"); - ERROR_OUT(RSA_KEY_SIZE_E, exit_scv); - } - } - else - #endif /* !NO_RSA */ - { - #ifdef HAVE_ECC - if (ssl->sigKey) { - XFREE(ssl->sigKey, ssl->heap, DYNAMIC_TYPE_RSA); - } - ssl->sigKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_scv); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); - if (ret != 0) { - goto exit_scv; - } - - WOLFSSL_MSG("Trying ECC client cert, RSA didn't work"); - - if (ssl->buffers.key == NULL) { - WOLFSSL_MSG("ECC Key missing"); - ERROR_OUT(NO_PRIVATE_KEY, exit_scv); - } - - idx = 0; - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, - (ecc_key*)ssl->sigKey, ssl->buffers.key->length); - if (ret != 0) { - WOLFSSL_MSG("Bad client cert type"); - goto exit_scv; - } - - WOLFSSL_MSG("Using ECC client cert"); - length = MAX_ENCODED_SIG_SZ; - - /* check minimum size of ECC key */ - keySz = wc_ecc_size((ecc_key*)ssl->sigKey); - if (keySz < ssl->options.minEccKeySz) { - WOLFSSL_MSG("ECC key size too small"); - ERROR_OUT(ECC_KEY_SIZE_E, exit_scv); - } - #endif - } - - /* idx is used to track verify pointer offset to output */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - verify = &output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; - extraSz = 0; /* tls 1.2 hash/sig */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + args->extraSz = 0; /* tls 1.2 hash/sig */ /* build encoded signature buffer */ ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; @@ -16448,8 +18091,8 @@ int SendCertificateVerify(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif @@ -16470,37 +18113,41 @@ int SendCertificateVerify(WOLFSSL* ssl) #endif /* !NO_OLD_TLS */ if (IsAtLeastTLSv1_2(ssl)) { - verify[0] = ssl->suites->hashAlgo; - verify[1] = (ssl->sigType == DYNAMIC_TYPE_ECC) ? + args->verify[0] = ssl->suites->hashAlgo; + args->verify[1] = (ssl->hsType == DYNAMIC_TYPE_ECC) ? ecc_dsa_sa_algo : rsa_sa_algo; - extraSz = HASH_SIG_SIZE; + args->extraSz = HASH_SIG_SIZE; switch (ssl->suites->hashAlgo) { #ifndef NO_SHA case sha_mac: ssl->buffers.digest.length = SHA_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.buffer = + ssl->hsHashes->certHashes.sha; typeH = SHAh; break; #endif /* NO_SHA */ #ifndef NO_SHA256 case sha256_mac: ssl->buffers.digest.length = SHA256_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.buffer = + ssl->hsHashes->certHashes.sha256; typeH = SHA256h; break; #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA384 case sha384_mac: ssl->buffers.digest.length = SHA384_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.buffer = + ssl->hsHashes->certHashes.sha384; typeH = SHA384h; break; #endif /* WOLFSSL_SHA384 */ #ifdef WOLFSSL_SHA512 case sha512_mac: ssl->buffers.digest.length = SHA512_DIGEST_SIZE; - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.buffer = + ssl->hsHashes->certHashes.sha512; typeH = SHA512h; break; #endif /* WOLFSSL_SHA512 */ @@ -16508,9 +18155,9 @@ int SendCertificateVerify(WOLFSSL* ssl) } #ifndef NO_OLD_TLS else { - /* if old TLS load MD5 hash as value to sign */ - XMEMCPY(ssl->buffers.sig.buffer, ssl->hsHashes->certHashes.md5, - FINISHED_SZ); + /* if old TLS load MD5 and SHA hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, + (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); } #endif @@ -16519,9 +18166,9 @@ int SendCertificateVerify(WOLFSSL* ssl) } #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { ssl->buffers.sig.length = FINISHED_SZ; - ssl->sigLen = ENCRYPT_LEN; + args->sigSz = ENCRYPT_LEN; if (IsAtLeastTLSv1_2(ssl)) { ssl->buffers.sig.length = wc_EncodeSignature( @@ -16529,22 +18176,26 @@ int SendCertificateVerify(WOLFSSL* ssl) ssl->buffers.digest.length, typeH); } - c16toa((word16)length, verify + extraSz); /* prepend hdr */ + /* prepend hdr */ + c16toa((word16)args->length, args->verify + args->extraSz); } #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { #ifdef HAVE_ECC - if (ssl->sigType == DYNAMIC_TYPE_ECC) { + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->buffers.sig.buffer, &ssl->buffers.sig.length, - (ecc_key*)ssl->sigKey, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -16556,14 +18207,16 @@ int SendCertificateVerify(WOLFSSL* ssl) } #endif /* HAVE_ECC */ #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->idx]; ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - verify + extraSz + VERIFY_HEADER, &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -16581,39 +18234,45 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { /* restore verify pointer */ - verify = &output[idx]; + args->verify = &args->output[args->idx]; #ifdef HAVE_ECC - if (ssl->sigType == DYNAMIC_TYPE_ECC) { - length = ssl->buffers.sig.length; - c16toa((word16)ssl->buffers.sig.length, verify + extraSz); /* prepend hdr */ - XMEMCPY(verify + extraSz + VERIFY_HEADER, + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + args->length = ssl->buffers.sig.length; + /* prepend hdr */ + c16toa((word16)ssl->buffers.sig.length, args->verify + + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, ssl->buffers.sig.buffer, ssl->buffers.sig.length); } #endif /* HAVE_ECC */ #ifndef NO_RSA - if (ssl->sigType == DYNAMIC_TYPE_RSA) { - if (verifySig == NULL) { - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (verifySig == NULL) { + if (args->verifySig == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(verifySig, verify + extraSz + VERIFY_HEADER, - ssl->sigLen); + XMEMCPY(args->verifySig, args->verify + args->extraSz + + VERIFY_HEADER, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); } #endif /* !NO_RSA */ @@ -16623,77 +18282,93 @@ int SendCertificateVerify(WOLFSSL* ssl) } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { - AddHeaders(output, length + extraSz + VERIFY_HEADER, - certificate_verify, ssl); + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_scv); + } + AddHeaders(args->output, args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, ssl); - sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + length + - extraSz + VERIFY_HEADER; + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + args->length + args->extraSz + VERIFY_HEADER; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif if (IsEncryptionOn(ssl, 1)) { - byte* input; - int inputSz = sendSz - RECORD_HEADER_SZ; + args->inputSz = args->sendSz - RECORD_HEADER_SZ; /* build msg adds rec hdr */ - input = (byte*)XMALLOC(inputSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (input == NULL) { + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); - sendSz = BuildMessage(ssl, output, - MAX_CERT_VERIFY_SZ +MAX_MSG_EXTRA, - input, inputSz, handshake, 1, 0); - XFREE(input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } - if (sendSz < 0) { - ret = sendSz; + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->input, args->inputSz, handshake, + 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_scv; + #endif + + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; } } else { - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif - ret = HashOutput(ssl, output, sendSz, 0); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSave(ssl, output, sendSz); - } - #endif - - /* Check for error */ if (ret != 0) { goto exit_scv; } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz); + } + #endif + - case KEYSHARE_END: - { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("CertificateVerify", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, - output, sendSz, ssl->heap); + args->output, args->sendSz, ssl->heap); #endif - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); @@ -16702,49 +18377,25 @@ int SendCertificateVerify(WOLFSSL* ssl) } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_scv: WOLFSSL_LEAVE("SendCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.sigSz = extraSz; - ssl->async.length = length; - ssl->async.idx = idx; - #ifndef NO_RSA - ssl->async.data = verifySig; - #endif - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } -#endif - -#ifndef NO_RSA - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ /* Digest is not allocated, so do this to prevent free */ ssl->buffers.digest.buffer = NULL; ssl->buffers.digest.length = 0; /* Final cleanup */ + FreeScvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -16754,7 +18405,7 @@ exit_scv: #ifdef HAVE_SESSION_TICKET -int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, +static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size) { word32 begin = *inOutIdx; @@ -16850,6 +18501,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int sendSz; int ret; byte sessIdSz = ID_LEN; + byte echoId = 0; /* ticket echo id flag */ + byte cacheOff = 0; /* session cache off flag */ length = VERSION_SZ + RAN_LEN + ID_LEN + ENUM_LEN @@ -16857,7 +18510,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + ENUM_LEN; #ifdef HAVE_TLS_EXTENSIONS - length += TLSX_GetResponseSize(ssl); + length += TLSX_GetResponseSize(ssl, server_hello); #ifdef HAVE_SESSION_TICKET if (ssl->options.useTicket) { /* echo session id sz can be 0,32 or bogus len inbetween */ @@ -16866,7 +18519,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad bogus session id len"); return BUFFER_ERROR; } - length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + if (!IsAtLeastTLSv1_3(ssl->version)) + length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + echoId = 1; } #endif /* HAVE_SESSION_TICKET */ #else @@ -16875,6 +18530,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif + /* is the session cahce off at build or runtime */ +#ifdef NO_SESSION_CACHE + cacheOff = 1; +#else + if (ssl->options.sessionCacheOff == 1) { + cacheOff = 1; + } +#endif + + /* if no session cache don't send a session ID unless we're echoing + * an ID as part of session tickets */ + if (echoId == 0 && cacheOff == 1) { + length -= ID_LEN; /* adjust ID_LEN assumption */ + sessIdSz = 0; + } + /* check for avalaible size */ if ((ret = CheckAvailableSize(ssl, MAX_HELLO_SZ)) != 0) return ret; @@ -16914,6 +18585,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, idx += RAN_LEN; output[idx++] = sessIdSz; XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz); + ssl->arrays->sessionIDSz = sessIdSz; } else { /* If resuming, use info from SSL */ @@ -16946,7 +18618,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* last, extensions */ #ifdef HAVE_TLS_EXTENSIONS - TLSX_WriteResponse(ssl, output + idx); + TLSX_WriteResponse(ssl, output + idx, server_hello); #else #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -16979,6 +18651,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ret != 0) return ret; + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); @@ -17083,80 +18756,102 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_ECC */ + typedef struct SskeArgs { + byte* output; /* not allocated */ + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + byte* sigDataBuf; + #endif + #if defined(HAVE_ECC) + byte* exportBuf; + #endif + #ifndef NO_RSA + byte* verifySig; + #endif + word32 idx; + word32 tmpSigSz; + word32 length; + word32 sigSz; + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + word32 sigDataSz; + #endif + #if defined(HAVE_ECC) + word32 exportSz; + #endif + #ifdef HAVE_QSH + word32 qshSz; + #endif + int sendSz; + } SskeArgs; + + static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) + { + SskeArgs* args = (SskeArgs*)pArgs; + + (void)ssl; + + #if defined(HAVE_ECC) + if (args->exportBuf) { + XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->exportBuf = NULL; + } + #endif + #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) + if (args->sigDataBuf) { + XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigDataBuf = NULL; + } + #endif + #ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } + #endif + (void)args; + } int SendServerKeyExchange(WOLFSSL* ssl) { int ret; - int sendSz = 0; - byte *output = NULL; - word32 idx = 0, sigSz = 0, length = 0; - #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - byte *sigDataBuf = NULL; - word32 sigDataSz = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + SskeArgs* args = (SskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + SskeArgs args[1]; #endif - #if defined(HAVE_ECC) - byte *exportBuf = NULL; - word32 exportSz = 0; - #endif - - #ifdef HAVE_QSH - word32 qshSz = 0; - if (ssl->peerQSHKeyPresent) { - qshSz = QSH_KeyGetSize(ssl); - } - #endif - #ifndef NO_RSA - byte* verifySig = NULL; - #endif - - (void)ssl; - (void)sigSz; - (void)length; - (void)idx; WOLFSSL_ENTER("SendServerKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_sske; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - idx = ssl->async.idx; - sigSz = ssl->async.sigSz; - length = ssl->async.length; - #ifndef NO_RSA - verifySig = ssl->async.data; - #endif - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SskeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSskeArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + args->qshSz = QSH_KeyGetSize(ssl); + } + #endif + /* Do some checks / debug msgs */ switch(ssl->specs.kea) { @@ -17175,7 +18870,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(0, exit_sske); } - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } @@ -17212,8 +18909,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Pub.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Pub.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } @@ -17222,25 +18919,39 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Priv.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + 2, ssl->heap, - DYNAMIC_TYPE_DH); + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_Priv.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } } - ret = DhGenKeyPair(ssl, + ssl->options.dhKeySz = + (word16)ssl->buffers.serverDH_P.length; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_sske; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_sske; + } + + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, &ssl->buffers.serverDH_Priv.length, ssl->buffers.serverDH_Pub.buffer, &ssl->buffers.serverDH_Pub.length); break; } - #endif /* !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA)) */ + #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */ #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: /* Fall through to create temp ECC key */ @@ -17251,19 +18962,16 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* need ephemeral key now, create it if missing */ if (ssl->eccTempKey == NULL) { /* alloc/init on demand */ - ssl->eccTempKey = (ecc_key*)XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->eccTempKey == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - ERROR_OUT(MEMORY_E, exit_sske); - } - ret = wc_ecc_init_ex(ssl->eccTempKey, ssl->heap, ssl->devId); - if (ret != 0) + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->eccTempKey); + if (ret != 0) { goto exit_sske; + } } if (ssl->eccTempKeyPresent == 0) { - /* TODO: Need to first do wc_EccPrivateKeyDecode, then we know curve dp */ + /* TODO: Need to first do wc_EccPrivateKeyDecode, + then we know curve dp */ ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); if (ret == 0 || ret == WC_PENDING_E) { ssl->eccTempKeyPresent = 1; @@ -17283,10 +18991,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { #if (!defined(NO_DH) && !defined(NO_RSA)) || defined(HAVE_ECC) word32 preSigSz, preSigIdx; @@ -17297,52 +19006,58 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_PSK case psk_kea: { - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; if (ssl->arrays->server_hint[0] == 0) { ERROR_OUT(0, exit_sske); /* don't send */ } /* include size part */ - length = (word32)XSTRLEN(ssl->arrays->server_hint); - if (length > MAX_PSK_ID_LEN) { + args->length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (args->length > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ #ifdef HAVE_QSH - c16toa((word16)(length - qshSz - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - args->qshSz - + HINT_LEN_SZ), args->output + args->idx); #else - c16toa((word16)(length - HINT_LEN_SZ), output + idx); + c16toa((word16)(args->length - HINT_LEN_SZ), + args->output + args->idx); #endif - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, length - HINT_LEN_SZ); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, + args->length - HINT_LEN_SZ); break; } #endif /* !NO_PSK */ @@ -17351,8 +19066,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { word32 hintLen; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3 + /* p, g, pub */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3 + /* p, g, pub */ ssl->buffers.serverDH_P.length + ssl->buffers.serverDH_G.length + ssl->buffers.serverDH_Pub.length; @@ -17362,58 +19077,67 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, - ssl->buffers.serverDH_Pub.length); + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); /* No need to update idx, since sizes are already set */ - /* idx += ssl->buffers.serverDH_Pub.length; */ + /* args->idx += ssl->buffers.serverDH_Pub.length; */ break; } #endif /* !defined(NO_DH) && !defined(NO_PSK) */ @@ -17423,59 +19147,62 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 hintLen; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { + if (wc_ecc_export_x963(ssl->eccTempKey, args->exportBuf, + &args->exportSz) != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); } - length += exportSz; + args->length += args->exportSz; /* include size part */ hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); if (hintLen > MAX_PSK_ID_LEN) { ERROR_OUT(SERVER_HINT_ERROR, exit_sske); } - length += hintLen + HINT_LEN_SZ; - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get output buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* key data */ - c16toa((word16)hintLen, output + idx); - idx += HINT_LEN_SZ; - XMEMCPY(output + idx, ssl->arrays->server_hint, hintLen); - idx += hintLen; + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; /* ECC key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + args->output[args->idx++] = SetCurveId(ssl->eccTempKey); + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, + args->exportSz); break; } #endif /* HAVE_ECC && !NO_PSK */ @@ -17485,23 +19212,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, enum wc_HashType hashType = WC_HASH_TYPE_NONE; /* curve type, named curve, length(1) */ - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; /* Export temp ECC key and add to length */ - exportSz = MAX_EXPORT_ECC_SZ; - exportBuf = (byte*)XMALLOC(exportSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (exportBuf == NULL) { + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->exportBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &exportSz) != 0) { + if (wc_ecc_export_x963(ssl->eccTempKey, args->exportBuf, + &args->exportSz) != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); } - length += exportSz; + args->length += args->exportSz; - preSigSz = length; - preSigIdx = idx; + preSigSz = args->length; + preSigIdx = args->idx; switch(ssl->specs.sig_algo) { @@ -17511,31 +19239,26 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (RsaKey*)ssl->sigKey, - ssl->buffers.key->length); + ret = wc_RsaPrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (RsaKey*)ssl->hsKey, + ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; + args->tmpSigSz = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA signature key size too small"); ERROR_OUT(RSA_KEY_SIZE_E, exit_sske); @@ -17546,27 +19269,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_dsa_sa_algo: { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), - ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); - if (ret != 0) - goto exit_sske; - - ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (ecc_key*)ssl->sigKey, - ssl->buffers.key->length); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } - sigSz = wc_ecc_sig_size((ecc_key*)ssl->sigKey); /* worst case estimate */ + + ret = wc_EccPrivateKeyDecode( + ssl->buffers.key->buffer, + &i, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = wc_ecc_sig_size( + (ecc_key*)ssl->hsKey); /* check the minimum ECC key size */ - if (wc_ecc_size((ecc_key*)ssl->sigKey) < + if (wc_ecc_size((ecc_key*)ssl->hsKey) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key size too small"); ret = ECC_KEY_SIZE_E; @@ -17579,69 +19302,71 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* switch(ssl->specs.sig_algo) */ /* sig length */ - length += LENGTH_SZ; - length += sigSz; + args->length += LENGTH_SZ; + args->length += args->tmpSigSz; if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* record and message headers will be added below, when we're sure of the sig length */ /* key exchange data */ - output[idx++] = named_curve; - output[idx++] = 0x00; /* leading zero */ - output[idx++] = SetCurveId(ssl->eccTempKey); - output[idx++] = (byte)exportSz; - XMEMCPY(output + idx, exportBuf, exportSz); - idx += exportSz; + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + args->output[args->idx++] = SetCurveId(ssl->eccTempKey); + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz); + args->idx += args->exportSz; /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; + args->output[args->idx++] = ssl->suites->hashAlgo; + args->output[args->idx++] = ssl->suites->sigAlgo; switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -17670,37 +19395,42 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif /* Assemble buffer to hash for signature */ - sigDataSz = RAN_LEN + RAN_LEN + preSigSz; - sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigDataBuf == NULL) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigDataBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); - ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, + ssl->buffers.sig.buffer = (byte*)XMALLOC( + ssl->buffers.sig.length, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (ssl->buffers.sig.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, + ret = wc_Hash(hashType, + args->sigDataBuf, args->sigDataSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length); if (ret != 0) { goto exit_sske; } - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ switch (ssl->specs.sig_algo) @@ -17720,22 +19450,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif + #ifdef WOLFSSL_SHA512 + typeH = SHA512h; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif + #ifdef WOLFSSL_SHA384 + typeH = SHA384h; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif + #ifndef NO_SHA256 + typeH = SHA256h; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) typeH = SHAh; #endif break; @@ -17743,8 +19475,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, typeH); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, @@ -17753,8 +19487,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* write sig size here */ - c16toa((word16)ssl->sigLen, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; break; } #endif /* !NO_RSA */ @@ -17771,50 +19506,46 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { enum wc_HashType hashType = WC_HASH_TYPE_NONE; - idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - length = LENGTH_SZ * 3; /* p, g, pub */ - length += ssl->buffers.serverDH_P.length + - ssl->buffers.serverDH_G.length + - ssl->buffers.serverDH_Pub.length; + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3; /* p, g, pub */ + args->length += ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; - preSigIdx = idx; - preSigSz = length; + preSigIdx = args->idx; + preSigSz = args->length; if (!ssl->options.usingAnon_cipher) { word32 i = 0; int keySz; - ssl->sigKey = (RsaKey*)XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_sske); + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); } - ssl->sigType = DYNAMIC_TYPE_RSA; - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, - ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_sske; } /* sig length */ - length += LENGTH_SZ; + args->length += LENGTH_SZ; - if (!ssl->buffers.key->buffer) { - ERROR_OUT(NO_PRIVATE_KEY, exit_sske); - } - - ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &i, - (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + ret = wc_RsaPrivateKeyDecode( + ssl->buffers.key->buffer, &i, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_sske; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_sske); } - sigSz = (word32)keySz; - length += sigSz; + args->tmpSigSz = (word32)keySz; + args->length += args->tmpSigSz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("RSA key size too small"); @@ -17822,60 +19553,68 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } if (IsAtLeastTLSv1_2(ssl)) { - length += HASH_SIG_SIZE; + args->length += HASH_SIG_SIZE; } } - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; #ifdef HAVE_QSH - length += qshSz; - sendSz += qshSz; + args->length += args->qshSz; + args->sendSz += args->qshSz; #endif #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - preSigIdx = idx; + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; } #endif /* check for available size */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { goto exit_sske; } /* get ouput buffer */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; - AddHeaders(output, length, server_key_exchange, ssl); + AddHeaders(args->output, args->length, + server_key_exchange, ssl); /* add p, g, pub */ - c16toa((word16)ssl->buffers.serverDH_P.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_P.buffer, + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length); - idx += ssl->buffers.serverDH_P.length; + args->idx += ssl->buffers.serverDH_P.length; /* g */ - c16toa((word16)ssl->buffers.serverDH_G.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_G.buffer, + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.length); - idx += ssl->buffers.serverDH_G.length; + args->idx += ssl->buffers.serverDH_G.length; /* pub */ - c16toa((word16)ssl->buffers.serverDH_Pub.length, output + idx); - idx += LENGTH_SZ; - XMEMCPY(output + idx, ssl->buffers.serverDH_Pub.buffer, + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length); - idx += ssl->buffers.serverDH_Pub.length; + args->idx += ssl->buffers.serverDH_Pub.length; #ifdef HAVE_FUZZER if (ssl->fuzzerCb) { - ssl->fuzzerCb(ssl, output + preSigIdx, preSigSz, - FUZZ_SIGNATURE, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); } #endif @@ -17885,27 +19624,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Determine hash type */ if (IsAtLeastTLSv1_2(ssl)) { - output[idx++] = ssl->suites->hashAlgo; - output[idx++] = ssl->suites->sigAlgo; + args->output[args->idx++] = ssl->suites->hashAlgo; + args->output[args->idx++] = ssl->suites->sigAlgo; switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - hashType = WC_HASH_TYPE_SHA512; - #endif + #ifdef WOLFSSL_SHA512 + hashType = WC_HASH_TYPE_SHA512; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - hashType = WC_HASH_TYPE_SHA384; - #endif + #ifdef WOLFSSL_SHA384 + hashType = WC_HASH_TYPE_SHA384; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - hashType = WC_HASH_TYPE_SHA256; - #endif + #ifndef NO_SHA256 + hashType = WC_HASH_TYPE_SHA256; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) hashType = WC_HASH_TYPE_SHA; #endif break; @@ -17930,19 +19671,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* signature size */ - c16toa((word16)sigSz, output + idx); - idx += LENGTH_SZ; + c16toa((word16)args->tmpSigSz, args->output + args->idx); + args->idx += LENGTH_SZ; /* Assemble buffer to hash for signature */ - sigDataSz = RAN_LEN + RAN_LEN + preSigSz; - sigDataBuf = (byte*)XMALLOC(sigDataSz, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (sigDataBuf == NULL) { + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigDataBuf == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(sigDataBuf, ssl->arrays->clientRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - XMEMCPY(sigDataBuf+RAN_LEN+RAN_LEN, output + preSigIdx, preSigSz); + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); ssl->buffers.sig.length = wc_HashGetDigestSize(hashType); ssl->buffers.sig.buffer = (byte*)XMALLOC( @@ -17953,13 +19697,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Perform hash */ - ret = wc_Hash(hashType, sigDataBuf, sigDataSz, + ret = wc_Hash(hashType, + args->sigDataBuf, args->sigDataSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length); if (ret != 0) { goto exit_sske; } - ssl->sigLen = sigSz; + args->sigSz = args->tmpSigSz; /* Sign hash to create signature */ switch (ssl->suites->sigAlgo) @@ -17979,22 +19724,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, switch (ssl->suites->hashAlgo) { case sha512_mac: - #ifdef WOLFSSL_SHA512 - typeH = SHA512h; - #endif + #ifdef WOLFSSL_SHA512 + typeH = SHA512h; + #endif break; case sha384_mac: - #ifdef WOLFSSL_SHA384 - typeH = SHA384h; - #endif + #ifdef WOLFSSL_SHA384 + typeH = SHA384h; + #endif break; case sha256_mac: - #ifndef NO_SHA256 - typeH = SHA256h; - #endif + #ifndef NO_SHA256 + typeH = SHA256h; + #endif break; case sha_mac: - #ifndef NO_OLD_TLS + #if !defined(NO_SHA) && \ + (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) typeH = SHAh; #endif break; @@ -18002,8 +19749,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, break; } - ssl->buffers.sig.length = wc_EncodeSignature(encodedSig, - ssl->buffers.sig.buffer, ssl->buffers.sig.length, typeH); + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, typeH); /* Replace sig buffer with new one */ XFREE(ssl->buffers.sig.buffer, ssl->heap, @@ -18025,10 +19774,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch(ssl->specs.kea) { @@ -18059,12 +19809,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18078,12 +19830,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ case ecc_dsa_sa_algo: { + ecc_key* key = (ecc_key*)ssl->hsKey; + ret = EccSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + LENGTH_SZ + idx, - &ssl->sigLen, - (ecc_key*)ssl->sigKey, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -18107,6 +19861,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } @@ -18114,9 +19870,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RsaSign(ssl, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - output + idx, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + args->output + args->idx, + &args->sigSz, + key, ssl->buffers.key->buffer, ssl->buffers.key->length, #ifdef HAVE_PK_CALLBACKS @@ -18141,10 +19897,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch(ssl->specs.kea) { @@ -18177,35 +19934,41 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); break; } #endif case ecc_dsa_sa_algo: { /* Now that we know the real sig size, write it. */ - c16toa((word16)ssl->sigLen, output + idx); + c16toa((word16)args->sigSz, + args->output + args->idx); /* And adjust length and sendSz from estimates */ - length += ssl->sigLen - sigSz; - sendSz += ssl->sigLen - sigSz; + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; break; } default: @@ -18222,28 +19985,33 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_sa_algo: { + RsaKey* key = (RsaKey*)ssl->hsKey; + if (ssl->options.usingAnon_cipher) { break; } - if (verifySig == NULL) { - if (ssl->sigLen == 0) { + if (args->verifySig == NULL) { + if (args->sigSz == 0) { ERROR_OUT(BAD_COND_E, exit_sske); } - verifySig = (byte*)XMALLOC(ssl->sigLen, ssl->heap, + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (!verifySig) { + if (!args->verifySig) { ERROR_OUT(MEMORY_E, exit_sske); } - XMEMCPY(verifySig, output + idx, ssl->sigLen); + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); } /* check for signature faults */ ret = VerifyRsaSign(ssl, - verifySig, ssl->sigLen, + args->verifySig, args->sigSz, ssl->buffers.sig.buffer, ssl->buffers.sig.length, - (RsaKey*)ssl->sigKey); + key + ); break; } #endif @@ -18259,26 +20027,29 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH if (ssl->peerQSHKeyPresent) { - if (qshSz > 0) { - idx = sendSz - qshSz; + if (args->qshSz > 0) { + args->idx = args->sendSz - args->qshSz; if (QSH_KeyExchangeWrite(ssl, 1) != 0) { ERROR_OUT(MEMORY_E, exit_sske); } /* extension type */ - c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); - idx += OPAQUE16_LEN; + c16toa(TLSX_QUANTUM_SAFE_HYBRID, + args->output + args->idx); + args->idx += OPAQUE16_LEN; /* write to output and check amount written */ - if (TLSX_QSHPK_Write(ssl->QSH_secret->list, output + idx) - > qshSz - OPAQUE16_LEN) { + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + args->idx) > + args->qshSz - OPAQUE16_LEN) { ERROR_OUT(MEMORY_E, exit_sske); } } @@ -18289,8 +20060,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->specs.kea == ecdhe_psk_kea || ssl->specs.kea == ecc_diffie_hellman_kea) { /* Check output to make sure it was set */ - if (output) { - AddHeaders(output, length, server_key_exchange, ssl); + if (args->output) { + AddHeaders(args->output, args->length, + server_key_exchange, ssl); } else { ERROR_OUT(BUFFER_ERROR, exit_sske); @@ -18300,7 +20072,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { goto exit_sske; } } @@ -18309,7 +20081,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, DtlsSEQIncrement(ssl, CUR_ORDER); #endif - ret = HashOutput(ssl, output, sendSz, 0); + ret = HashOutput(ssl, args->output, args->sendSz, 0); if (ret != 0) { goto exit_sske; } @@ -18319,23 +20091,19 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddPacketName("ServerKeyExchange", &ssl->handShakeInfo); } if (ssl->toInfoOn) { - AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, output, - sendSz, ssl->heap); + AddPacketInfo("ServerKeyExchange", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); } #endif - /* Check for error */ - if (ret != 0) { - goto exit_sske; - } - /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; if (!ssl->options.groupMessages) { ret = SendBuffered(ssl); } @@ -18345,57 +20113,20 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_sske: WOLFSSL_LEAVE("SendServerKeyExchange", ret); - /* Handle cleanup for stack variables here */ - #if defined(HAVE_ECC) - if (exportBuf) { - XFREE(exportBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - exportBuf = NULL; - } - #endif - #if defined(HAVE_ECC) || (!defined(NO_DH) && !defined(NO_RSA)) - if (sigDataBuf) { - XFREE(sigDataBuf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - sigDataBuf = NULL; - } - #endif - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ - if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.sigSz = sigSz; - #ifndef NO_RSA - ssl->async.data = verifySig; - #endif - - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } - } - #endif - - #ifndef NO_RSA - if (verifySig) { - XFREE(verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); - verifySig = NULL; - } - #endif + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; + #endif /* WOLFSSL_ASYNC_CRYPT */ /* Final cleanup */ + FreeSskeArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -18528,12 +20259,50 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END) { + /* Try to establish a key share. */ + int ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + else if (ret != 0) + return 0; + } +#endif + return 1; } #ifndef NO_WOLFSSL_SERVER - static int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i, + word16 j) { + if (ssl->suites->suites[i] == peerSuites->suites[j] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { + + if (VerifyServerSuite(ssl, i)) { + int result; + WOLFSSL_MSG("Verified suite validity"); + ssl->options.cipherSuite0 = ssl->suites->suites[i]; + ssl->options.cipherSuite = ssl->suites->suites[i+1]; + result = SetCipherSpecs(ssl); + if (result == 0) + PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); + return result; + } + else { + WOLFSSL_MSG("Could not verify suite validity, continue"); + } + } + + return MATCH_SUITE_ERROR; + } + + int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + { + int ret; word16 i, j; WOLFSSL_ENTER("MatchSuite"); @@ -18544,27 +20313,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->suites == NULL) return SUITES_ERROR; - /* start with best, if a match we are good */ - for (i = 0; i < ssl->suites->suiteSz; i += 2) - for (j = 0; j < peerSuites->suiteSz; j += 2) - if (ssl->suites->suites[i] == peerSuites->suites[j] && - ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { - if (VerifyServerSuite(ssl, i)) { - int result; - WOLFSSL_MSG("Verified suite validity"); - ssl->options.cipherSuite0 = ssl->suites->suites[i]; - ssl->options.cipherSuite = ssl->suites->suites[i+1]; - result = SetCipherSpecs(ssl); - if (result == 0) - PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, - peerSuites->hashSigAlgoSz); - return result; - } - else { - WOLFSSL_MSG("Could not verify suite validity, continue"); - } + if (!ssl->options.useClientOrder) { + /* Server order */ + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; } + } + } + else { + /* Client order */ + for (j = 0; j < peerSuites->suiteSz; j += 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; + } + } + } return MATCH_SUITE_ERROR; } @@ -18626,26 +20395,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); /* turn off tls 1.1+ */ ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif @@ -18661,7 +20434,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* suite size */ ato16(&input[idx], &clSuites.suiteSz); - idx += 2; + idx += OPAQUE16_LEN; if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) return BUFFER_ERROR; @@ -18669,14 +20442,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* session size */ ato16(&input[idx], &sessionSz); - idx += 2; + idx += OPAQUE16_LEN; if (sessionSz > ID_LEN) return BUFFER_ERROR; /* random size */ ato16(&input[idx], &randomSz); - idx += 2; + idx += OPAQUE16_LEN; if (randomSz > RAN_LEN) return BUFFER_ERROR; @@ -18685,10 +20458,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) { byte first = input[idx++]; if (!first) { /* implicit: skip sslv2 type */ - XMEMCPY(&clSuites.suites[j], &input[idx], 2); - j += 2; + XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN); + j += SUITE_LEN; } - idx += 2; + idx += SUITE_LEN; } clSuites.suiteSz = j; @@ -18729,6 +20502,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Session lookup for resume failed"); ssl->options.resuming = 0; } else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); return UNSUPPORTED_SUITE; @@ -18761,7 +20537,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* OLD_HELLO_ALLOWED */ - static int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { byte b; @@ -18776,6 +20552,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte peerCookieSz = 0; byte cookieType; byte cookieSz = 0; + + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); #endif /* WOLFSSL_DTLS */ #ifdef WOLFSSL_CALLBACKS @@ -18810,7 +20588,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.dtlsCookieSecret.length); if (ret != 0) return ret; ret = wc_HmacUpdate(&cookieHmac, - ssl->buffers.dtlsCtx.peer.sa, + (const byte*)ssl->buffers.dtlsCtx.peer.sa, ssl->buffers.dtlsCtx.peer.sz); if (ret != 0) return ret; ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN); @@ -18832,27 +20610,31 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } if (pv.minor < ssl->options.minDowngrade) { - WOLFSSL_MSG(" version below minimum allowed, fatal error"); + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); return VERSION_ERROR; } if (pv.minor == SSLv3_MINOR) { /* turn off tls */ - WOLFSSL_MSG(" downgrading to SSLv3"); + WOLFSSL_MSG("\tdowngrading to SSLv3"); ssl->options.tls = 0; ssl->options.tls1_1 = 0; ssl->version.minor = SSLv3_MINOR; } else if (pv.minor == TLSv1_MINOR) { /* turn off tls 1.1+ */ - WOLFSSL_MSG(" downgrading to TLSv1"); + WOLFSSL_MSG("\tdowngrading to TLSv1"); ssl->options.tls1_1 = 0; ssl->version.minor = TLSv1_MINOR; } else if (pv.minor == TLSv1_1_MINOR) { - WOLFSSL_MSG(" downgrading to TLSv1.1"); + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); ssl->version.minor = TLSv1_1_MINOR; } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } #ifndef NO_RSA haveRSA = 1; #endif @@ -19089,12 +20871,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_TLS_EXTENSIONS /* tls extensions */ - if ((ret = TLSX_Parse(ssl, (byte *) input + i, - totalExtSz, 1, &clSuites))) + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + client_hello, &clSuites))) return ret; -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) if((ret=SNI_Callback(ssl))) return ret; + ssl->options.side = WOLFSSL_SERVER_END; #endif /*HAVE_STUNNEL*/ i += totalExtSz; @@ -19179,8 +20962,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, "using EMS"); return EXT_MASTER_SECRET_NEEDED_E; } +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif } else { +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return UNSUPPORTED_SUITE; @@ -19212,63 +21001,65 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_RSA) || defined(HAVE_ECC) + typedef struct DcvArgs { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + } DcvArgs; + + static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs) + { + DcvArgs* args = (DcvArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret = 0; - byte* output = NULL; - word32 sendSz = 0; - word16 sz = 0; - word32 sigSz = 0; - byte hashAlgo = sha_mac; - byte sigAlgo = anonymous_sa_algo; - word32 idx = *inOutIdx, begin = *inOutIdx; + int ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + DcvArgs* args = (DcvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DcvArgs args[1]; + #endif WOLFSSL_ENTER("DoCertificateVerify"); - (void)sigSz; - (void)output; - (void)sendSz; - #ifdef WOLFSSL_ASYNC_CRYPT - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dcv; - } - else { - /* Restore variables needed for async */ - output = ssl->async.output; - sendSz = ssl->async.sendSz; - idx = ssl->async.idx; - sigSz = ssl->async.sigSz; - sz = ssl->async.length; - sigAlgo = ssl->async.sigAlgo; - hashAlgo = ssl->async.hashAlgo; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DcvArgs)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcvArgs; + #endif } - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) @@ -19278,79 +21069,100 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* case KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { if (IsAtLeastTLSv1_2(ssl)) { - if ((idx - begin) + ENUM_LEN + ENUM_LEN > size) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - hashAlgo = input[idx++]; - sigAlgo = input[idx++]; + args->hashAlgo = input[args->idx++]; + args->sigAlgo = input[args->idx++]; } - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } - ato16(input + idx, &sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + sz > size || sz > ENCRYPT_LEN) { + if ((args->idx - args->begin) + args->sz > size || + args->sz > ENCRYPT_LEN) { ERROR_OUT(BUFFER_ERROR, exit_dcv); } #ifdef HAVE_ECC if (ssl->peerEccDsaKeyPresent) { - ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; - ssl->buffers.digest.length = SHA_DIGEST_SIZE; WOLFSSL_MSG("Doing ECC peer cert verify"); + /* make sure a default is defined */ + #if !defined(NO_SHA) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = SHA_DIGEST_SIZE; + #elif !defined(NO_SHA256) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA384) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA512) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #else + #error No digest enabled for ECC sig verify + #endif + if (IsAtLeastTLSv1_2(ssl)) { - if (sigAlgo != ecc_dsa_sa_algo) { + if (args->sigAlgo != ecc_dsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); } - if (hashAlgo == sha256_mac) { + switch (args->hashAlgo) { + case sha256_mac: #ifndef NO_SHA256 ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; ssl->buffers.digest.length = SHA256_DIGEST_SIZE; #endif - } - else if (hashAlgo == sha384_mac) { + break; + case sha384_mac: #ifdef WOLFSSL_SHA384 ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; ssl->buffers.digest.length = SHA384_DIGEST_SIZE; #endif - } - else if (hashAlgo == sha512_mac) { + break; + case sha512_mac: #ifdef WOLFSSL_SHA512 ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; ssl->buffers.digest.length = SHA512_DIGEST_SIZE; #endif + break; } } } #endif /* HAVE_ECC */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* case KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { WOLFSSL_MSG("Doing RSA peer cert verify"); ret = RsaVerify(ssl, - input + idx, - sz, - &output, + input + args->idx, + args->sz, + &args->output, + rsa_sa_algo, no_mac, ssl->peerRsaKey, #ifdef HAVE_PK_CALLBACKS ssl->buffers.peerRsaKey.buffer, @@ -19361,7 +21173,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ); if (ret >= 0) { - sendSz = ret; + args->sendSz = ret; ret = 0; } } @@ -19371,7 +21183,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Doing ECC peer cert verify"); ret = EccVerify(ssl, - input + idx, sz, + input + args->idx, args->sz, ssl->buffers.digest.buffer, ssl->buffers.digest.length, ssl->peerEccDsaKey, #ifdef HAVE_PK_CALLBACKS @@ -19391,75 +21203,92 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* case KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { #ifndef NO_RSA if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { if (IsAtLeastTLSv1_2(ssl)) { #ifdef WOLFSSL_SMALL_STACK - byte* encodedSig = NULL; + byte* encodedSig = NULL; #else - byte encodedSig[MAX_ENCODED_SIG_SZ]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; #endif - int typeH = SHAh; + int typeH = SHAh; + /* make sure a default is defined */ + #if !defined(NO_SHA) ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; ssl->buffers.digest.length = SHA_DIGEST_SIZE; + #elif !defined(NO_SHA256) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA384) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #elif defined(WOLFSSL_SHA512) + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #else + #error No digest enabled for RSA sig verify + #endif #ifdef WOLFSSL_SMALL_STACK - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); if (encodedSig == NULL) { ERROR_OUT(MEMORY_E, exit_dcv); } #endif - if (sigAlgo != rsa_sa_algo) { + if (args->sigAlgo != rsa_sa_algo) { WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); } - switch (hashAlgo) { - #ifndef NO_SHA256 + switch (args->hashAlgo) { case sha256_mac: + #ifndef NO_SHA256 typeH = SHA256h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; ssl->buffers.digest.length = SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ break; - #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 case sha384_mac: + #ifdef WOLFSSL_SHA384 typeH = SHA384h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; ssl->buffers.digest.length = SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 case sha512_mac: + #ifdef WOLFSSL_SHA512 typeH = SHA512h; ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; ssl->buffers.digest.length = SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ break; - #endif /* WOLFSSL_SHA512 */ } /* switch */ - sigSz = wc_EncodeSignature(encodedSig, - ssl->buffers.digest.buffer, ssl->buffers.digest.length, - typeH); + args->sigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, typeH); - if (sendSz != sigSz || !output || XMEMCMP(output, - encodedSig, min(sigSz, MAX_ENCODED_SIG_SZ)) != 0) { + if (args->sendSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { ret = VERIFY_CERT_ERROR; } #ifdef WOLFSSL_SMALL_STACK - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif } else { - if (sendSz != FINISHED_SZ || !output || XMEMCMP(output, + if (args->sendSz != FINISHED_SZ || !args->output || + XMEMCMP(args->output, &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { ret = VERIFY_CERT_ERROR; } @@ -19468,57 +21297,41 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !NO_RSA */ /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* case KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { ssl->options.havePeerVerify = 1; /* Set final index */ - idx += sz; - *inOutIdx = idx; + args->idx += args->sz; + *inOutIdx = args->idx; /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* case KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ - case KEYSHARE_END: + case TLS_ASYNC_END: { break; } default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcv: WOLFSSL_LEAVE("DoCertificateVerify", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.output = output; - ssl->async.sendSz = sendSz; - ssl->async.idx = idx; - ssl->async.sigSz = sigSz; - ssl->async.length = sz; - ssl->async.sigAlgo = sigAlgo; - ssl->async.hashAlgo = hashAlgo; - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_certificate_verify = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -19527,6 +21340,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.digest.length = 0; /* Final cleanup */ + FreeDcvArgs(ssl, args); FreeKeyExchange(ssl); return ret; @@ -19536,14 +21350,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int SendServerHelloDone(WOLFSSL* ssl) { - byte *output; - int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int ret; + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) - sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; - #endif /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -19554,27 +21369,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, AddHeaders(output, 0, server_hello_done, ssl); - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return 0; - } + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return 0; + } - if (ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); - #endif + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif ret = HashOutput(ssl, output, sendSz, 0); if (ret != 0) return ret; -#ifdef WOLFSSL_CALLBACKS + #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("ServerHelloDone", &ssl->handShakeInfo); if (ssl->toInfoOn) AddPacketInfo("ServerHelloDone", &ssl->timeoutInfo, output, sendSz, ssl->heap); -#endif + #endif ssl->options.serverState = SERVER_HELLODONE_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; @@ -19596,6 +21411,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte msecret[SECRET_LEN]; /* master secret */ word32 timestamp; /* born on */ word16 haveEMS; /* have extended master secret */ +#ifdef WOLFSSL_TLS13 + word32 ageAdd; /* Obfuscation of age */ + byte namedGroup; /* Named group used */ +#endif } InternalTicket; /* fit within SESSION_TICKET_LEN */ @@ -19609,7 +21428,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } ExternalTicket; /* create a new session ticket, 0 on success */ - static int CreateTicket(WOLFSSL* ssl) + int CreateTicket(WOLFSSL* ssl) { InternalTicket it; ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; @@ -19626,9 +21445,25 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, it.suite[0] = ssl->options.cipherSuite0; it.suite[1] = ssl->options.cipherSuite; - XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); - c32toa(LowResTimer(), (byte*)&it.timestamp); - it.haveEMS = ssl->options.haveEMS; + if (!ssl->options.tls1_3) { + XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); + c32toa(LowResTimer(), (byte*)&it.timestamp); + it.haveEMS = ssl->options.haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Client adds to ticket age to obfuscate. */ + ret = wc_RNG_GenerateBlock(ssl->rng, (void*)&it.ageAdd, + sizeof(it.ageAdd)); + if (ret != 0) + return BAD_TICKET_ENCRYPT; + ssl->session.ticketAdd = it.ageAdd; + it.namedGroup = ssl->session.namedGroup; + it.timestamp = TimeNowInMilliseconds(); + /* Resumption master secret. */ + XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); +#endif + } /* build external */ XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket)); @@ -19721,10 +21556,24 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* get master secret */ if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { - XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); - /* Copy the haveExtendedMasterSecret property from the ticket to - * the saved session, so the property may be checked later. */ - ssl->session.haveEMS = it->haveEMS; + if (!IsAtLeastTLSv1_3(ssl->version)) { + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + /* Copy the haveExtendedMasterSecret property from the ticket to + * the saved session, so the property may be checked later. */ + ssl->session.haveEMS = it->haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Restore information to renegotiate. */ + ssl->session.ticketSeen = it->timestamp; + ssl->session.ticketAdd = it->ageAdd; + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + /* Resumption master secret. */ + XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN); + ssl->session.namedGroup = it->namedGroup; +#endif + } } return ret; @@ -19847,62 +21696,61 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS */ + typedef struct DckeArgs { + byte* output; /* not allocated */ + word32 length; + word32 idx; + word32 begin; + word32 sigSz; + } DckeArgs; + + static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs) + { + DckeArgs* args = (DckeArgs*)pArgs; + + (void)ssl; + (void)args; + } + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size) { - int ret; - word32 length = 0; - word32 idx = *inOutIdx, begin = *inOutIdx; - byte* output_lcl = NULL; - byte** output = &output_lcl; - - /* suppress possible compiler warnings */ - (void)input; - (void)size; - (void)length; - (void)idx; - (void)output; + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + DckeArgs* args = (DckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DckeArgs args[1]; + #endif WOLFSSL_ENTER("DoClientKeyExchange"); #ifdef WOLFSSL_ASYNC_CRYPT - /* use async pointer for output */ - output = &ssl->async.output; - - ret = wolfAsync_EventPop(&ssl->event, WOLF_EVENT_TYPE_ASYNC_ANY); + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); if (ret != WC_NOT_PENDING_E) { - WOLF_EVENT_TYPE eType = ssl->event.type; - - /* Clear event */ - XMEMSET(&ssl->event, 0, sizeof(ssl->event)); - /* Check for error */ - if (ret < 0) { + if (ret < 0) goto exit_dcke; - } - else { - /* Restore variables needed for async */ - idx = ssl->async.idx; - length = ssl->async.length; - - /* Advance key share state if not wolfCrypt */ - if (eType == WOLF_EVENT_TYPE_ASYNC_WOLFSSL) { - ssl->options.keyShareState++; - } - } } else #endif /* WOLFSSL_ASYNC_CRYPT */ { /* Reset state */ ret = 0; - ssl->options.keyShareState = KEYSHARE_BEGIN; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DckeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDckeArgs; + #endif } /* Do Client Key Exchange State Machine */ - switch(ssl->options.keyShareState) + switch(ssl->options.asyncState) { - case KEYSHARE_BEGIN: + case TLS_ASYNC_BEGIN: { /* Sanity checks */ if (ssl->options.side != WOLFSSL_SERVER_END) { @@ -19927,7 +21775,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) { if (!ssl->options.havePeerCert && - !ssl->options.usingPSK_cipher){ + !ssl->options.usingPSK_cipher) { WOLFSSL_MSG("client didn't present peer cert"); return NO_PEER_CERT; } @@ -19947,7 +21795,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_RSA case rsa_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -19967,7 +21817,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_NTRU case ntru_kea: { - if (!ssl->buffers.key->buffer) { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); } break; @@ -20018,10 +21870,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_BUILD; - } /* KEYSHARE_BEGIN */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* TLS_ASYNC_BEGIN */ + FALL_THROUGH; - case KEYSHARE_BUILD: + case TLS_ASYNC_BUILD: { switch (ssl->specs.kea) { #ifndef NO_RSA @@ -20030,29 +21883,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 i = 0; int keySz; - ssl->sigKey = XMALLOC(sizeof(RsaKey), ssl->heap, - DYNAMIC_TYPE_RSA); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_RSA; - - ret = wc_InitRsaKey_ex((RsaKey*)ssl->sigKey, ssl->heap, - ssl->devId); + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, - &i, (RsaKey*)ssl->sigKey, ssl->buffers.key->length); + &i, (RsaKey*)ssl->hsKey, ssl->buffers.key->length); if (ret != 0) { goto exit_dcke; } - keySz = wc_RsaEncryptSize((RsaKey*)ssl->sigKey); + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); if (keySz < 0) { /* test if keySz has error */ ERROR_OUT(keySz, exit_dcke); } - length = (word32)keySz; + args->length = (word32)keySz; if (keySz < ssl->options.minRsaKeySz) { WOLFSSL_MSG("Peer RSA key is too small"); @@ -20063,25 +21909,25 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->options.tls) { word16 check; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &check); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &check); + args->idx += OPAQUE16_LEN; - if ((word32)check != length) { + if ((word32)check != args->length) { WOLFSSL_MSG("RSA explicit size doesn't match"); ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); } } - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { WOLFSSL_MSG("RSA message too big"); ERROR_OUT(BUFFER_ERROR, exit_dcke); } - *output = NULL; + args->output = NULL; break; } /* rsa_kea */ #endif /* !NO_RSA */ @@ -20091,25 +21937,26 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte* pms = ssl->arrays->preMasterSecret; word16 ci_sz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &ci_sz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &ci_sz); + args->idx += OPAQUE16_LEN; if (ci_sz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + ci_sz > size) { + if ((args->idx - args->begin) + ci_sz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, ci_sz); - idx += ci_sz; + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, ci_sz); + args->idx += ci_sz; - ssl->arrays->client_identity[min(ci_sz, MAX_PSK_ID_LEN-1)] = 0; + ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */ ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, ssl->arrays->client_identity, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); @@ -20131,7 +21978,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, pms += OPAQUE16_LEN; XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz = ssl->arrays->psk_keySz * 2 + 4; + ssl->arrays->preMasterSz = + (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2); break; } #endif /* !NO_PSK */ @@ -20139,27 +21987,27 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ntru_kea: { word16 cipherLen; - word16 plainLen = sizeof(ssl->arrays->preMasterSecret); + word16 plainLen = ENCRYPT_LEN; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &cipherLen); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &cipherLen); + args->idx += OPAQUE16_LEN; if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { ERROR_OUT(NTRU_KEY_ERROR, exit_dcke); } - if ((idx - begin) + cipherLen > size) { + if ((args->idx - args->begin) + cipherLen > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } if (NTRU_OK != ntru_crypto_ntru_decrypt( (word16) ssl->buffers.key->length, ssl->buffers.key->buffer, cipherLen, - input + idx, &plainLen, + input + args->idx, &plainLen, ssl->arrays->preMasterSecret)) { ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } @@ -20168,7 +22016,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); } - idx += cipherLen; + args->idx += cipherLen; ssl->arrays->preMasterSz = plainLen; break; } @@ -20182,14 +22030,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->specs.static_ecdh) { word32 i = 0; - ssl->sigKey = XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->sigKey == NULL) { - ERROR_OUT(MEMORY_E, exit_dcke); - } - ssl->sigType = DYNAMIC_TYPE_ECC; - - ret = wc_ecc_init_ex((ecc_key*)ssl->sigKey, ssl->heap, ssl->devId); + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); if (ret != 0) { goto exit_dcke; } @@ -20197,10 +22039,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = wc_EccPrivateKeyDecode( ssl->buffers.key->buffer, &i, - (ecc_key*)ssl->sigKey, + (ecc_key*)ssl->hsKey, ssl->buffers.key->length); if (ret == 0) { - private_key = (ecc_key*)ssl->sigKey; + private_key = (ecc_key*)ssl->hsKey; if (wc_ecc_size(private_key) < ssl->options.minEccKeySz) { WOLFSSL_MSG("ECC key too small"); @@ -20210,16 +22052,18 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + ssl->arrays->preMasterSz = ENCRYPT_LEN; + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20235,14 +22079,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC( - sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } @@ -20256,12 +22094,16 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, private_key->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, private_key->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } ssl->peerEccKeyPresent = 1; + + if (ret != 0) { + goto exit_dcke; + } break; } #endif /* HAVE_ECC */ @@ -20270,18 +22112,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { word16 clientPubSz; - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientPubSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientPubSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientPubSz > size) { + if ((args->idx - args->begin) + clientPubSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientPubSz; + args->sigSz = clientPubSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); break; } #endif /* !NO_DH */ @@ -20291,38 +22145,51 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - XMEMCPY(ssl->arrays->client_identity, input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + XMEMCPY(ssl->arrays->client_identity, input + args->idx, + clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* Read in the DHE business */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ssl->sigLen = clientSz; + args->sigSz = clientSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + break; } #endif /* !NO_DH && !NO_PSK */ @@ -20332,36 +22199,37 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word16 clientSz; /* Read in the PSK hint */ - if ((idx - begin) + OPAQUE16_LEN > size) { + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - ato16(input + idx, &clientSz); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; if (clientSz > MAX_PSK_ID_LEN) { ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); } - if ((idx - begin) + clientSz > size) { + if ((args->idx - args->begin) + clientSz > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } XMEMCPY(ssl->arrays->client_identity, - input + idx, clientSz); - idx += clientSz; - ssl->arrays->client_identity[ - min(clientSz, MAX_PSK_ID_LEN-1)] = 0; + input + args->idx, clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ /* import peer ECC key */ - if ((idx - begin) + OPAQUE8_LEN > size) { + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } - length = input[idx++]; + args->length = input[args->idx++]; - if ((idx - begin) + length > size) { + if ((args->idx - args->begin) + args->length > size) { ERROR_OUT(BUFFER_ERROR, exit_dcke); } + args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN; + #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -20376,14 +22244,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->peerEccKey == NULL) { /* alloc/init on demand */ - ssl->peerEccKey = (ecc_key*)XMALLOC( - sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - ERROR_OUT(MEMORY_E, exit_dcke); - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, - ssl->devId); + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); if (ret != 0) { goto exit_dcke; } @@ -20397,9 +22259,8 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } } - - if (wc_ecc_import_x963_ex(input + idx, length, - ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); } @@ -20417,21 +22278,23 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_DO; - } /* KEYSHARE_BUILD */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* TLS_ASYNC_BUILD */ + FALL_THROUGH; - case KEYSHARE_DO: + case TLS_ASYNC_DO: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { + RsaKey* key = (RsaKey*)ssl->hsKey; ret = RsaDec(ssl, - input + idx, - length, - output, - &ssl->sigLen, - (RsaKey*)ssl->sigKey, + input + args->idx, + args->length, + &args->output, + &args->sigSz, + key, #if defined(HAVE_PK_CALLBACKS) ssl->buffers.key->buffer, ssl->buffers.key->length, @@ -20460,15 +22323,13 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, { ecc_key* private_key = ssl->eccTempKey; if (ssl->specs.static_ecdh) { - private_key = (ecc_key*)ssl->sigKey; + private_key = (ecc_key*)ssl->hsKey; } - ssl->arrays->preMasterSz = ENCRYPT_LEN; - /* Generate shared secret */ ret = EccSharedSecret(ssl, private_key, ssl->peerEccKey, - input + idx, &length, + input + args->idx, &args->length, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, WOLFSSL_SERVER_END, @@ -20484,19 +22345,11 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifndef NO_DH case diffie_hellman_kea: { - word16 clientPubSz = (word16)ssl->sigLen; - - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientPubSz, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); break; @@ -20505,21 +22358,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if !defined(NO_DH) && !defined(NO_PSK) case dhe_psk_kea: { - byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz = ssl->sigLen; - - ret = DhAgree(ssl, - ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, - ssl->buffers.serverDH_G.buffer, - ssl->buffers.serverDH_G.length, + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, ssl->buffers.serverDH_Priv.buffer, - &ssl->buffers.serverDH_Priv.length, - NULL, - 0, - input + idx, - clientSz, - pms + OPAQUE16_LEN, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, &ssl->arrays->preMasterSz); break; } @@ -20527,14 +22371,12 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #if defined(HAVE_ECC) && !defined(NO_PSK) case ecdhe_psk_kea: { - ssl->sigLen = ENCRYPT_LEN - OPAQUE16_LEN; - /* Generate shared secret */ ret = EccSharedSecret(ssl, ssl->eccTempKey, ssl->peerEccKey, - input + idx, &length, + input + args->idx, &args->length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->sigLen, + &args->sigSz, WOLFSSL_SERVER_END, #ifdef HAVE_PK_CALLBACKS ssl->EccSharedSecretCtx @@ -20555,20 +22397,21 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_VERIFY; - } /* KEYSHARE_DO */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* TLS_ASYNC_DO */ + FALL_THROUGH; - case KEYSHARE_VERIFY: + case TLS_ASYNC_VERIFY: { switch (ssl->specs.kea) { #ifndef NO_RSA case rsa_kea: { /* Add the signature length to idx */ - idx += length; + args->idx += args->length; - if (ssl->sigLen == SECRET_LEN && *output != NULL) { - XMEMCPY(ssl->arrays->preMasterSecret, *output, SECRET_LEN); + if (args->sigSz == SECRET_LEN && args->output != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret, args->output, SECRET_LEN); if (ssl->arrays->preMasterSecret[0] != ssl->chVersion.major || ssl->arrays->preMasterSecret[1] != ssl->chVersion.minor) { ERROR_OUT(PMS_VERSION_ERROR, exit_dcke); @@ -20596,15 +22439,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecc_diffie_hellman_kea: { /* skip past the imported peer key */ - idx += length; + args->idx += args->length; break; } #endif /* HAVE_ECC */ #ifndef NO_DH case diffie_hellman_kea: { - word16 clientPubSz = (word16)ssl->sigLen; - idx += clientPubSz; + args->idx += (word16)args->sigSz; break; } #endif /* !NO_DH */ @@ -20612,9 +22454,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case dhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; - word16 clientSz = ssl->sigLen; + word16 clientSz = (word16)args->sigSz; - idx += clientSz; + args->idx += clientSz; c16toa((word16)ssl->arrays->preMasterSz, pms); ssl->arrays->preMasterSz += OPAQUE16_LEN; pms += ssl->arrays->preMasterSz; @@ -20633,8 +22475,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, c16toa((word16) ssl->arrays->psk_keySz, pms); pms += OPAQUE16_LEN; - XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); - ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + OPAQUE16_LEN; + XMEMCPY(pms, ssl->arrays->psk_key, + ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + + OPAQUE16_LEN; break; } #endif /* !NO_DH && !NO_PSK */ @@ -20642,13 +22486,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, case ecdhe_psk_kea: { byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; /* skip past the imported peer key */ - idx += length; + args->idx += args->length; /* Add preMasterSecret */ - c16toa((word16)ssl->sigLen, pms); - ssl->arrays->preMasterSz += OPAQUE16_LEN + ssl->sigLen; + c16toa(clientSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN + clientSz; pms += ssl->arrays->preMasterSz; /* Use the PSK hint to look up the PSK and add it to the @@ -20681,29 +22526,30 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_FINALIZE; - } /* KEYSHARE_VERIFY */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* TLS_ASYNC_VERIFY */ + FALL_THROUGH; - case KEYSHARE_FINALIZE: + case TLS_ASYNC_FINALIZE: { #ifdef HAVE_QSH word16 name; if (ssl->options.haveQSH) { /* extension name */ - ato16(input + idx, &name); - idx += OPAQUE16_LEN; + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; if (name == TLSX_QUANTUM_SAFE_HYBRID) { int qshSz; /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, - input + idx, - size - idx + begin, 1)) < 0) { + input + args->idx, + size - args->idx + args->begin, 1)) < 0) { ERROR_OUT(qshSz, exit_dcke); } - idx += qshSz; + args->idx += qshSz; } else { /* unknown extension sent client ignored handshake */ @@ -20719,13 +22565,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } /* Advance state and proceed */ - ssl->options.keyShareState = KEYSHARE_END; - } /* KEYSHARE_FINALIZE */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* TLS_ASYNC_FINALIZE */ + FALL_THROUGH; - case KEYSHARE_END: + case TLS_ASYNC_END: { /* Set final index */ - *inOutIdx = idx; + *inOutIdx = args->idx; ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; #ifndef NO_CERTS @@ -20734,36 +22581,22 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif break; - } /* KEYSHARE_END */ + } /* TLS_ASYNC_END */ default: ret = INPUT_CASE_ERROR; - } /* switch(ssl->options.keyShareState) */ + } /* switch(ssl->options.asyncState) */ exit_dcke: WOLFSSL_LEAVE("DoClientKeyExchange", ret); - /* Handle cleanup for stack variables here */ - - #ifdef WOLFSSL_ASYNC_CRYPT - /* Handle WC_PENDING_E */ + /* Handle async operation */ if (ret == WC_PENDING_E) { - /* Store variables needed for async */ - output_lcl = ssl->async.output; - XMEMSET(&ssl->async, 0, sizeof(ssl->async)); - ssl->async.idx = idx; - ssl->async.length = length; - ssl->async.output = output_lcl; - /* Mark message as not recevied so it can process again */ ssl->msgsReceived.got_client_key_exchange = 0; - /* Push event to queue */ - ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, &ssl->event); - if (ret == 0) { - return WC_PENDING_E; - } + return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ @@ -20772,14 +22605,15 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->arrays->preMasterSz = 0; /* Final cleanup */ + FreeDckeArgs(ssl, args); FreeKeyExchange(ssl); return ret; } -#ifdef HAVE_STUNNEL - static int SNI_Callback(WOLFSSL* ssl) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + int SNI_Callback(WOLFSSL* ssl) { /* Stunnel supports a custom sni callback to switch an SSL's ctx * when SNI is received. Call it now if exists */ @@ -20794,9 +22628,85 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } return 0; } -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLGSSL_NGINX */ #endif /* NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) +{ + int ret = 0; + WC_ASYNC_DEV* asyncDev; + WOLF_EVENT* event; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* check for pending async */ + asyncDev = ssl->async.dev; + if (asyncDev) { + /* grab event pointer */ + event = &asyncDev->event; + + ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); + if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) { + + /* advance key share state if doesn't need called again */ + if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) { + (*state)++; + } + + /* clear event */ + XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT)); + + /* clear async dev */ + ssl->async.dev = NULL; + } + } + else { + ret = WC_NOT_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret); + + return ret; +} + +int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* init event */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags); + if (ret == 0) { + ssl->async.dev = asyncDev; + + /* place event into queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event); + } + + /* success means return WC_PENDING_E */ + if (ret == 0) { + ret = WC_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret); + + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + + #undef ERROR_OUT #endif /* WOLFCRYPT_ONLY */ diff --git a/src/io.c b/src/io.c index bbfd971af..8b9a9b960 100644 --- a/src/io.c +++ b/src/io.c @@ -36,188 +36,30 @@ #include #include +#include + +#if defined(HAVE_HTTP_CLIENT) + #include /* atoi(), strtol() */ +#endif + +/* +Possible IO enable options: + * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off + allows user to define their own using + wolfSSL_SetIORecv and wolfSSL_SetIOSend + * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off + * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off + (unless HAVE_OCSP or HAVE_CRL_IO defined) + * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off + */ /* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove automatic setting of default I/O functions EmbedSend() and EmbedReceive() but they'll still need SetCallback xxx() at end of file */ -#ifndef WOLFSSL_USER_IO - -#ifdef HAVE_LIBZ - #include "zlib.h" -#endif - -#ifndef USE_WINDOWS_API - #ifdef WOLFSSL_LWIP - /* lwIP needs to be configured to use sockets API in this mode */ - /* LWIP_SOCKET 1 in lwip/opt.h or in build */ - #include "lwip/sockets.h" - #include - #ifndef LWIP_PROVIDE_ERRNO - #define LWIP_PROVIDE_ERRNO 1 - #endif - #elif defined(FREESCALE_MQX) - #include - #include - #elif defined(FREESCALE_KSDK_MQX) - #include - #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #include "cmsis_os.h" - #include "rl_net.h" - #else - #include - #endif - #include "errno.h" - #define SOCKET_T int - #elif defined(WOLFSSL_TIRTOS) - #include - #elif defined(FREERTOS_TCP) - #include "FreeRTOS_Sockets.h" - #elif defined(WOLFSSL_IAR_ARM) - /* nothing */ - #elif defined(WOLFSSL_VXWORKS) - #include - #include - #elif defined(WOLFSSL_ATMEL) - #include "socket/include/socket.h" - #else - #include - #include - #ifndef EBSNET - #include - #endif - #include - - #if defined(HAVE_RTP_SYS) - #include - #elif defined(EBSNET) - #include "rtipapi.h" /* errno */ - #include "socket.h" - #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) - #include - #include - #include - #include - #ifdef __PPU - #include - #else - #include - #endif - #endif - #endif -#endif /* USE_WINDOWS_API */ - -#ifdef __sun - #include -#endif - -#ifdef USE_WINDOWS_API - /* no epipe yet */ - #ifndef WSAEPIPE - #define WSAEPIPE -12345 - #endif - #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK - #define SOCKET_EAGAIN WSAETIMEDOUT - #define SOCKET_ECONNRESET WSAECONNRESET - #define SOCKET_EINTR WSAEINTR - #define SOCKET_EPIPE WSAEPIPE - #define SOCKET_ECONNREFUSED WSAENOTCONN - #define SOCKET_ECONNABORTED WSAECONNABORTED - #define close(s) closesocket(s) -#elif defined(__PPU) - #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK - #define SOCKET_EAGAIN SYS_NET_EAGAIN - #define SOCKET_ECONNRESET SYS_NET_ECONNRESET - #define SOCKET_EINTR SYS_NET_EINTR - #define SOCKET_EPIPE SYS_NET_EPIPE - #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED - #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED -#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) - #if MQX_USE_IO_OLD - /* RTCS old I/O doesn't have an EWOULDBLOCK */ - #define SOCKET_EWOULDBLOCK EAGAIN - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED - #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED - #else - #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK - #define SOCKET_EAGAIN NIO_EAGAIN - #define SOCKET_ECONNRESET NIO_ECONNRESET - #define SOCKET_EINTR NIO_EINTR - #define SOCKET_EPIPE NIO_EPIPE - #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED - #define SOCKET_ECONNABORTED NIO_ECONNABORTED - #endif -#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) - #if !defined(WOLFSSL_MDK_ARM) - #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK - #define SOCKET_EAGAIN BSD_ERROR_LOCKED - #define SOCKET_ECONNRESET BSD_ERROR_CLOSED - #define SOCKET_EINTR BSD_ERROR - #define SOCKET_EPIPE BSD_ERROR - #define SOCKET_ECONNREFUSED BSD_ERROR - #define SOCKET_ECONNABORTED BSD_ERROR - #else - #define SOCKET_EWOULDBLOCK SCK_EWOULDBLOCK - #define SOCKET_EAGAIN SCK_ELOCKED - #define SOCKET_ECONNRESET SCK_ECLOSED - #define SOCKET_EINTR SCK_ERROR - #define SOCKET_EPIPE SCK_ERROR - #define SOCKET_ECONNREFUSED SCK_ERROR - #define SOCKET_ECONNABORTED SCK_ERROR - #endif -#elif defined(WOLFSSL_PICOTCP) - #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN - #define SOCKET_EAGAIN PICO_ERR_EAGAIN - #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET - #define SOCKET_EINTR PICO_ERR_EINTR - #define SOCKET_EPIPE PICO_ERR_EIO - #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED - #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN -#elif defined(FREERTOS_TCP) - #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK - #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK - #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR - #define SOCKET_EINTR FREERTOS_SOCKET_ERROR - #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR - #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR -#else - #define SOCKET_EWOULDBLOCK EWOULDBLOCK - #define SOCKET_EAGAIN EAGAIN - #define SOCKET_ECONNRESET ECONNRESET - #define SOCKET_EINTR EINTR - #define SOCKET_EPIPE EPIPE - #define SOCKET_ECONNREFUSED ECONNREFUSED - #define SOCKET_ECONNABORTED ECONNABORTED -#endif /* USE_WINDOWS_API */ - - -#ifdef DEVKITPRO - /* from network.h */ - int net_send(int, const void*, int, unsigned int); - int net_recv(int, void*, int, unsigned int); - #define SEND_FUNCTION net_send - #define RECV_FUNCTION net_recv -#elif defined(WOLFSSL_LWIP) - #define SEND_FUNCTION lwip_send - #define RECV_FUNCTION lwip_recv -#elif defined(WOLFSSL_PICOTCP) - #define SEND_FUNCTION pico_send - #define RECV_FUNCTION pico_recv -#elif defined(FREERTOS_TCP) - #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) - #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) -#else - #define SEND_FUNCTION send - #define RECV_FUNCTION recv -#endif +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) /* Translates return codes returned from * send() and recv() if need be. @@ -257,14 +99,18 @@ static INLINE int LastError(void) #endif } +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#ifdef USE_WOLFSSL_IO + /* The receive embedded callback * return : nb bytes read, or error */ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) { - int recvd; - int err; int sd = *(int*)ctx; + int recvd; #ifdef WOLFSSL_DTLS { @@ -287,42 +133,39 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) } #endif - recvd = (int)RECV_FUNCTION(sd, buf, sz, ssl->rflags); - - recvd = TranslateReturnCode(recvd, sd); - + recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); if (recvd < 0) { - err = LastError(); + int err = LastError(); WOLFSSL_MSG("Embed Receive error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG(" Would block"); + WOLFSSL_MSG("\tWould block"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" Socket timeout"); + WOLFSSL_MSG("\tSocket timeout"); return WOLFSSL_CBIO_ERR_TIMEOUT; } } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); + WOLFSSL_MSG("\tConnection refused"); return WOLFSSL_CBIO_ERR_WANT_READ; } else if (err == SOCKET_ECONNABORTED) { - WOLFSSL_MSG(" Connection aborted"); + WOLFSSL_MSG("\tConnection aborted"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -341,35 +184,30 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) { int sd = *(int*)ctx; int sent; - int len = sz; - int err; - - sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, ssl->wflags); - - sent = TranslateReturnCode(sent, sd); + sent = wolfIO_Send(sd, buf, sz, ssl->wflags); if (sent < 0) { - err = LastError(); + int err = LastError(); WOLFSSL_MSG("Embed Send error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); + WOLFSSL_MSG("\tWould Block"); return WOLFSSL_CBIO_ERR_WANT_WRITE; } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); + WOLFSSL_MSG("\tSocket EPIPE"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -382,12 +220,6 @@ int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) #include -#ifdef USE_WINDOWS_API - #define XSOCKLENT int -#else - #define XSOCKLENT socklen_t -#endif - #define SENDTO_FUNCTION sendto #define RECVFROM_FUNCTION recvfrom @@ -402,7 +234,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) int err; int sd = dtlsCtx->rfd; int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); - struct sockaddr_storage peer; + SOCKADDR_S peer; XSOCKLENT peerSz = sizeof(peer); WOLFSSL_ENTER("EmbedReceiveFrom()"); @@ -425,7 +257,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, - (struct sockaddr*)&peer, &peerSz); + (SOCKADDR*)&peer, &peerSz); recvd = TranslateReturnCode(recvd, sd); @@ -435,28 +267,28 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { if (wolfSSL_get_using_nonblock(ssl)) { - WOLFSSL_MSG(" Would block"); + WOLFSSL_MSG("\tWould block"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" Socket timeout"); + WOLFSSL_MSG("\tSocket timeout"); return WOLFSSL_CBIO_ERR_TIMEOUT; } } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_ECONNREFUSED) { - WOLFSSL_MSG(" Connection refused"); + WOLFSSL_MSG("\tConnection refused"); return WOLFSSL_CBIO_ERR_WANT_READ; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -464,7 +296,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (dtlsCtx->peer.sz > 0 && peerSz != (XSOCKLENT)dtlsCtx->peer.sz && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { - WOLFSSL_MSG(" Ignored packet from invalid peer"); + WOLFSSL_MSG("\tIgnored packet from invalid peer"); return WOLFSSL_CBIO_ERR_WANT_READ; } } @@ -487,7 +319,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedSendTo()"); sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, - (const struct sockaddr*)dtlsCtx->peer.sa, + (const SOCKADDR*)dtlsCtx->peer.sa, dtlsCtx->peer.sz); sent = TranslateReturnCode(sent, sd); @@ -497,23 +329,23 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) WOLFSSL_MSG("Embed Send To error"); if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { - WOLFSSL_MSG(" Would Block"); + WOLFSSL_MSG("\tWould Block"); return WOLFSSL_CBIO_ERR_WANT_WRITE; } else if (err == SOCKET_ECONNRESET) { - WOLFSSL_MSG(" Connection reset"); + WOLFSSL_MSG("\tConnection reset"); return WOLFSSL_CBIO_ERR_CONN_RST; } else if (err == SOCKET_EINTR) { - WOLFSSL_MSG(" Socket interrupted"); + WOLFSSL_MSG("\tSocket interrupted"); return WOLFSSL_CBIO_ERR_ISR; } else if (err == SOCKET_EPIPE) { - WOLFSSL_MSG(" Socket EPIPE"); + WOLFSSL_MSG("\tSocket EPIPE"); return WOLFSSL_CBIO_ERR_CONN_CLOSE; } else { - WOLFSSL_MSG(" General error"); + WOLFSSL_MSG("\tGeneral error"); return WOLFSSL_CBIO_ERR_GENERAL; } } @@ -528,7 +360,7 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) { int sd = ssl->wfd; - struct sockaddr_storage peer; + SOCKADDR_S peer; XSOCKLENT peerSz = sizeof(peer); byte digest[SHA_DIGEST_SIZE]; int ret = 0; @@ -536,7 +368,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) (void)ctx; XMEMSET(&peer, 0, sizeof(peer)); - if (getpeername(sd, (struct sockaddr*)&peer, &peerSz) != 0) { + if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); return GEN_COOKIE_E; } @@ -553,29 +385,6 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) } #ifdef WOLFSSL_SESSION_EXPORT - #ifndef XINET_NTOP - #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) - #endif - #ifndef XINET_PTON - #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) - #endif - #ifndef XHTONS - #define XHTONS(a) htons((a)) - #endif - #ifndef XNTOHS - #define XNTOHS(a) ntohs((a)) - #endif - - #ifndef WOLFSSL_IP4 - #define WOLFSSL_IP4 AF_INET - #endif - #ifndef WOLFSSL_IP6 - #define WOLFSSL_IP6 AF_INET6 - #endif - - typedef struct sockaddr_storage SOCKADDR_S; - typedef struct sockaddr_in SOCKADDR_IN; - typedef struct sockaddr_in6 SOCKADDR_IN6; /* get the peer information in human readable form (ip, port, family) * default function assumes BSD sockets @@ -613,12 +422,14 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) break; case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), ip, *ipSz) == NULL) { WOLFSSL_MSG("XINET_NTOP error"); return SOCKET_ERROR_E; } *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); + #endif /* WOLFSSL_IPV6 */ break; default: @@ -665,6 +476,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) break; case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 if (XINET_PTON(addr.ss_family, ip, &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { WOLFSSL_MSG("XINET_PTON error"); @@ -678,6 +490,7 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) WOLFSSL_MSG("Import DTLS peer info error"); return ret; } + #endif /* WOLFSSL_IPV6 */ break; default: @@ -690,92 +503,184 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) #endif /* WOLFSSL_SESSION_EXPORT */ #endif /* WOLFSSL_DTLS */ -#ifdef HAVE_OCSP -#include /* atoi() */ +int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) +{ + int recvd; + + recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); + recvd = TranslateReturnCode(recvd, sd); + + return recvd; +} + +int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) +{ + int sent; + int len = sz; + + sent = (int)SEND_FUNCTION(sd, &buf[sz - len], len, wrFlags); + sent = TranslateReturnCode(sent, sd); + + return sent; +} + +#endif /* USE_WOLFSSL_IO */ -static int Word16ToString(char* d, word16 number) +#ifdef HAVE_HTTP_CLIENT + +#ifndef HAVE_IO_TIMEOUT + #define io_timeout_sec 0 +#else + + #ifndef DEFAULT_TIMEOUT_SEC + #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */ + #endif + + static int io_timeout_sec = DEFAULT_TIMEOUT_SEC; + + void wolfIO_SetTimeout(int to_sec) + { + io_timeout_sec = to_sec; + } + + int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking) + { + int ret = 0; + + #ifdef USE_WINDOWS_API + unsigned long blocking = non_blocking; + ret = ioctlsocket(sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + ret = -1; + #else + ret = fcntl(sockfd, F_GETFL, 0); + if (ret >= 0) { + if (non_blocking) + ret |= O_NONBLOCK; + else + ret &= ~O_NONBLOCK; + ret = fcntl(sockfd, F_SETFL, ret); + } + #endif + if (ret < 0) { + WOLFSSL_MSG("wolfIO_SetBlockingMode failed"); + } + + return ret; + } + + #ifdef _MSC_VER + /* 4204: non-constant aggregate initializer (nfds = sockfd + 1) */ + #pragma warning(disable: 4204) + #endif + int wolfIO_Select(SOCKET_T sockfd, int to_sec) + { + fd_set fds; + SOCKET_T nfds = sockfd + 1; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int ret; + + FD_ZERO(&fds); + FD_SET(sockfd, &fds); + + ret = select(nfds, &fds, &fds, NULL, &timeout); + if (ret == 0) { + #ifdef DEBUG_HTTP + printf("Timeout: %d\n", ret); + #endif + return HTTP_TIMEOUT; + } + else if (ret > 0) { + if (FD_ISSET(sockfd, &fds)) + return 0; + } + return SOCKET_ERROR_E; + } +#endif /* HAVE_IO_TIMEOUT */ + +static int wolfIO_Word16ToString(char* d, word16 number) { int i = 0; + word16 order = 10000; + word16 digit; - if (d != NULL) { - word16 order = 10000; - word16 digit; + if (d == NULL) + return i; - if (number == 0) { - d[i++] = '0'; + if (number == 0) + d[i++] = '0'; + else { + while (order) { + digit = number / order; + if (i > 0 || digit != 0) + d[i++] = (char)digit + '0'; + if (digit != 0) + number %= digit * order; + + order = (order > 1) ? order / 10 : 0; } - else { - while (order) { - digit = number / order; - if (i > 0 || digit != 0) { - d[i++] = (char)digit + '0'; - } - if (digit != 0) - number %= digit * order; - if (order > 1) - order /= 10; - else - order = 0; - } - } - d[i] = 0; } + d[i] = 0; /* null terminate */ return i; } - -static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) +int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) { - struct sockaddr_storage addr; - int sockaddr_len = sizeof(struct sockaddr_in); +#ifdef HAVE_SOCKADDR + int ret = 0; + SOCKADDR_S addr; + int sockaddr_len = sizeof(SOCKADDR_IN); +#ifdef HAVE_GETADDRINFO + ADDRINFO hints; + ADDRINFO* answer = NULL; + char strPort[6]; +#else + HOSTENT* entry; + SOCKADDR_IN *sin; +#endif + XMEMSET(&addr, 0, sizeof(addr)); - #ifdef HAVE_GETADDRINFO - { - struct addrinfo hints; - struct addrinfo* answer = NULL; - char strPort[6]; +#ifdef WOLFIO_DEBUG + printf("TCP Connect: %s:%d\n", ip, port); +#endif - XMEMSET(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - - if (Word16ToString(strPort, port) == 0) { - WOLFSSL_MSG("invalid port number for OCSP responder"); - return -1; - } - - if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } - - sockaddr_len = answer->ai_addrlen; - XMEMCPY(&addr, answer->ai_addr, sockaddr_len); - freeaddrinfo(answer); +#ifdef HAVE_GETADDRINFO + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if (wolfIO_Word16ToString(strPort, port) == 0) { + WOLFSSL_MSG("invalid port number for responder"); + return -1; } - #else /* HAVE_GETADDRINFO */ - { - struct hostent* entry = gethostbyname(ip); - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - if (entry) { - sin->sin_family = AF_INET; - sin->sin_port = htons(port); - XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], - entry->h_length); - } - else { - WOLFSSL_MSG("no addr info for OCSP responder"); - return -1; - } + if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { + WOLFSSL_MSG("no addr info for responder"); + return -1; } - #endif /* HAVE_GETADDRINFO */ + + sockaddr_len = answer->ai_addrlen; + XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + freeaddrinfo(answer); +#else + entry = gethostbyname(ip); + sin = (SOCKADDR_IN *)&addr; + + if (entry) { + sin->sin_family = AF_INET; + sin->sin_port = XHTONS(port); + XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); + } + else { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } +#endif *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); @@ -791,248 +696,427 @@ static int tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) } #endif - if (connect(*sockfd, (struct sockaddr *)&addr, sockaddr_len) != 0) { - WOLFSSL_MSG("OCSP responder tcp connect failed"); +#ifdef HAVE_IO_TIMEOUT + /* if timeout value provided then set socket non-blocking */ + if (to_sec > 0) { + wolfIO_SetBlockingMode(*sockfd, 1); + } +#else + (void)to_sec; +#endif + + ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len); +#ifdef HAVE_IO_TIMEOUT + if (ret != 0) { + if ((errno == EINPROGRESS) && (to_sec > 0)) { + /* wait for connect to complete */ + ret = wolfIO_Select(*sockfd, to_sec); + + /* restore blocking mode */ + wolfIO_SetBlockingMode(*sockfd, 0); + } + } +#endif + if (ret != 0) { + WOLFSSL_MSG("Responder tcp connect failed"); return -1; } - - return 0; + return ret; +#else + (void)sockfd; + (void)ip; + (void)port; + (void)to_sec; + return -1; +#endif /* HAVE_SOCKADDR */ } +#ifndef HTTP_SCRATCH_BUFFER_SIZE + #define HTTP_SCRATCH_BUFFER_SIZE 512 +#endif +#ifndef MAX_URL_ITEM_SIZE + #define MAX_URL_ITEM_SIZE 80 +#endif -static int build_http_request(const char* domainName, const char* path, - int ocspReqSz, byte* buf, int bufSize) -{ - word32 domainNameLen, pathLen, ocspReqSzStrLen, completeLen; - char ocspReqSzStr[6]; - - domainNameLen = (word32)XSTRLEN(domainName); - pathLen = (word32)XSTRLEN(path); - ocspReqSzStrLen = Word16ToString(ocspReqSzStr, (word16)ocspReqSz); - - completeLen = domainNameLen + pathLen + ocspReqSzStrLen + 84; - if (completeLen > (word32)bufSize) - return 0; - - XSTRNCPY((char*)buf, "POST ", 5); - buf += 5; - XSTRNCPY((char*)buf, path, pathLen); - buf += pathLen; - XSTRNCPY((char*)buf, " HTTP/1.1\r\nHost: ", 17); - buf += 17; - XSTRNCPY((char*)buf, domainName, domainNameLen); - buf += domainNameLen; - XSTRNCPY((char*)buf, "\r\nContent-Length: ", 18); - buf += 18; - XSTRNCPY((char*)buf, ocspReqSzStr, ocspReqSzStrLen); - buf += ocspReqSzStrLen; - XSTRNCPY((char*)buf, - "\r\nContent-Type: application/ocsp-request\r\n\r\n", 44); - - return completeLen; -} - - -static int decode_url(const char* url, int urlSz, - char* outName, char* outPath, word16* outPort) +int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, + word16* outPort) { int result = -1; - if (outName != NULL && outPath != NULL && outPort != NULL) - { - if (url == NULL || urlSz == 0) - { + if (url == NULL || urlSz == 0) { + if (outName) *outName = 0; + if (outPath) *outPath = 0; + if (outPort) *outPort = 0; + } + else { + int i, cur; + + /* need to break the url down into scheme, address, and port */ + /* "http://example.com:8080/" */ + /* "http://[::1]:443/" */ + if (XSTRNCMP(url, "http://", 7) == 0) { + cur = 7; + } else cur = 0; + + i = 0; + if (url[cur] == '[') { + cur++; + /* copy until ']' */ + while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + cur++; /* skip ']' */ } - else - { - int i, cur; - - /* need to break the url down into scheme, address, and port */ - /* "http://example.com:8080/" */ - /* "http://[::1]:443/" */ - if (XSTRNCMP(url, "http://", 7) == 0) { - cur = 7; - } else cur = 0; - - i = 0; - if (url[cur] == '[') { - cur++; - /* copy until ']' */ - while (url[cur] != 0 && url[cur] != ']' && cur < urlSz) { - outName[i++] = url[cur++]; - } - cur++; /* skip ']' */ - } - else { - while (url[cur] != 0 && url[cur] != ':' && - url[cur] != '/' && cur < urlSz) { - outName[i++] = url[cur++]; - } + else { + while (url[cur] != 0 && url[cur] != ':' && + url[cur] != '/' && cur < urlSz) { + if (outName) + outName[i] = url[cur]; + i++; cur++; } + } + if (outName) outName[i] = 0; - /* Need to pick out the path after the domain name */ + /* Need to pick out the path after the domain name */ - if (cur < urlSz && url[cur] == ':') { - char port[6]; - int j; - word32 bigPort = 0; - i = 0; - cur++; - while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && - i < 6) { - port[i++] = url[cur++]; - } + if (cur < urlSz && url[cur] == ':') { + char port[6]; + int j; + word32 bigPort = 0; + i = 0; + cur++; + while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && + i < 6) { + port[i++] = url[cur++]; + } - for (j = 0; j < i; j++) { - if (port[j] < '0' || port[j] > '9') return -1; - bigPort = (bigPort * 10) + (port[j] - '0'); - } + for (j = 0; j < i; j++) { + if (port[j] < '0' || port[j] > '9') return -1; + bigPort = (bigPort * 10) + (port[j] - '0'); + } + if (outPort) *outPort = (word16)bigPort; - } - else - *outPort = 80; - - if (cur < urlSz && url[cur] == '/') { - i = 0; - while (cur < urlSz && url[cur] != 0 && i < 80) { - outPath[i++] = url[cur++]; - } - outPath[i] = 0; - } - else { - outPath[0] = '/'; - outPath[1] = 0; - } - result = 0; } + else if (outPort) + *outPort = 80; + + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) { + if (outPath) + outPath[i] = url[cur]; + i++; cur++; + } + if (outPath) + outPath[i] = 0; + } + else if (outPath) { + outPath[0] = '/'; + outPath[1] = 0; + } + + result = 0; } return result; } - -/* return: >0 OCSP Response Size - * -1 error */ -static int process_http_response(int sfd, byte** respBuf, - byte* httpBuf, int httpBufSz, void* heap) +static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz, + int chunkSz, char* start, int len, int dynType, void* heap) { - int result; + byte* newRecvBuf = NULL; + int newRecvSz = *recvBufSz + chunkSz; + int pos = 0; + + WOLFSSL_MSG("Processing HTTP response"); +#ifdef WOLFIO_DEBUG + printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz); +#endif + + newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); + if (newRecvBuf == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); + return MEMORY_E; + } + + /* if buffer already exists, then we are growing it */ + if (*recvBuf) { + XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); + XFREE(*recvBuf, heap, dynType); + pos += *recvBufSz; + *recvBuf = NULL; + } + + /* copy the remainder of the httpBuf into the respBuf */ + if (len != 0) { + XMEMCPY(&newRecvBuf[pos], start, len); + pos += len; + } + + /* receive the remainder of chunk */ + while (len < chunkSz) { + int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0); + if (rxSz > 0) { + len += rxSz; + pos += rxSz; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed"); + XFREE(newRecvBuf, heap, dynType); + return -1; + } + } + + *recvBuf = newRecvBuf; + *recvBufSz = newRecvSz; + + return 0; +} + +int wolfIO_HttpProcessResponse(int sfd, const char* appStr, + byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap) +{ + int result = 0; int len = 0; char *start, *end; - byte *recvBuf = NULL; - int recvBufSz = 0; - enum phr_state { phr_init, phr_http_start, phr_have_length, - phr_have_type, phr_wait_end, phr_http_end + int respBufSz = 0; + int isChunked = 0, chunkSz = 0; + enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, + phr_wait_end, phr_get_chunk_len, phr_get_chunk_data, + phr_http_end } state = phr_init; + *respBuf = NULL; start = end = NULL; do { + if (state == phr_get_chunk_data) { + /* get chunk of data */ + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, + chunkSz, start, len, dynType, heap); + + state = (result != 0) ? phr_http_end : phr_get_chunk_len; + end = NULL; + len = 0; + } + + /* read data if no \r\n or first time */ if (end == NULL) { - result = (int)recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); + result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); if (result > 0) { len += result; start = (char*)httpBuf; start[len] = 0; } else { - WOLFSSL_MSG("process_http_response recv http from peer failed"); + WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed"); return -1; } } - end = XSTRSTR(start, "\r\n"); + end = XSTRSTR(start, "\r\n"); /* locate end */ + /* handle incomplete rx */ if (end == NULL) { if (len != 0) XMEMMOVE(httpBuf, start, len); start = end = NULL; } + /* when start is "\r\n" */ else if (end == start) { - if (state == phr_wait_end) { - state = phr_http_end; - len -= 2; - start += 2; + /* if waiting for end or need chunk len */ + if (state == phr_wait_end || state == phr_get_chunk_len) { + state = (isChunked) ? phr_get_chunk_len : phr_http_end; + len -= 2; start += 2; /* skip \r\n */ } else { - WOLFSSL_MSG("process_http_response header ended early"); + WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early"); return -1; } } else { - *end = 0; + *end = 0; /* null terminate */ len -= (int)(end - start) + 2; /* adjust len to remove the first line including the /r/n */ - if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { - start += 9; - if (XSTRNCASECMP(start, "200 OK", 6) != 0 || - state != phr_init) { - WOLFSSL_MSG("process_http_response not OK"); - return -1; - } - state = phr_http_start; - } - else if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { - start += 13; - while (*start == ' ' && *start != '\0') start++; - if (XSTRNCASECMP(start, "application/ocsp-response", 25) != 0) { - WOLFSSL_MSG("process_http_response not ocsp-response"); - return -1; - } + #ifdef WOLFIO_DEBUG + printf("HTTP Resp: %s\n", start); + #endif - if (state == phr_http_start) state = phr_have_type; - else if (state == phr_have_length) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response type invalid state"); - return -1; - } - } - else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { - start += 15; - while (*start == ' ' && *start != '\0') start++; - recvBufSz = atoi(start); - - if (state == phr_http_start) state = phr_have_length; - else if (state == phr_have_type) state = phr_wait_end; - else { - WOLFSSL_MSG("process_http_response length invalid state"); - return -1; - } - } + switch (state) { + case phr_init: + if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { + start += 9; + if (XSTRNCASECMP(start, "200 OK", 6) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK"); + return -1; + } + state = phr_http_start; + } + break; + case phr_http_start: + case phr_have_length: + case phr_have_type: + if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + start += 13; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, appStr, XSTRLEN(appStr)) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch"); + return -1; + } + state = (state == phr_http_start) ? phr_have_type : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { + start += 15; + while (*start == ' ' && *start != '\0') start++; + chunkSz = atoi(start); + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) { + start += 18; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, "chunked", 7) == 0) { + isChunked = 1; + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + } + break; + case phr_get_chunk_len: + chunkSz = (int)strtol(start, NULL, 16); /* hex format */ + state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data; + break; + case phr_get_chunk_data: + /* processing for chunk data done above, since \r\n isn't required */ + case phr_wait_end: + case phr_http_end: + /* do nothing */ + break; + } /* switch (state) */ + /* skip to end plus \r\n */ start = end + 2; } } while (state != phr_http_end); - recvBuf = (byte*)XMALLOC(recvBufSz, heap, DYNAMIC_TYPE_OCSP); - if (recvBuf == NULL) { - WOLFSSL_MSG("process_http_response couldn't create response buffer"); - return -1; + if (!isChunked) { + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz, + start, len, dynType, heap); } - /* copy the remainder of the httpBuf into the respBuf */ - if (len != 0) - XMEMCPY(recvBuf, start, len); - - /* receive the OCSP response data */ - while (len < recvBufSz) { - result = (int)recv(sfd, (char*)recvBuf+len, recvBufSz-len, 0); - if (result > 0) - len += result; - else { - WOLFSSL_MSG("process_http_response recv ocsp from peer failed"); - return -1; - } + if (result >= 0) { + result = respBufSz; + } + else { + WOLFSSL_ERROR(result); } - *respBuf = recvBuf; - return recvBufSz; + return result; +} + +int wolfIO_HttpBuildRequest(const char* reqType, const char* domainName, + const char* path, int pathLen, int reqSz, const char* contentType, + byte* buf, int bufSize) +{ + word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, maxLen; + char reqSzStr[6]; + char* req = (char*)buf; + const char* blankStr = " "; + const char* http11Str = " HTTP/1.1"; + const char* hostStr = "\r\nHost: "; + const char* contentLenStr = "\r\nContent-Length: "; + const char* contentTypeStr = "\r\nContent-Type: "; + const char* doubleCrLfStr = "\r\n\r\n"; + word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, + contentTypeStrLen, doubleCrLfStrLen; + + reqTypeLen = (word32)XSTRLEN(reqType); + domainNameLen = (word32)XSTRLEN(domainName); + reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz); + contentTypeLen = (word32)XSTRLEN(contentType); + + blankStrLen = (word32)XSTRLEN(blankStr); + http11StrLen = (word32)XSTRLEN(http11Str); + hostStrLen = (word32)XSTRLEN(hostStr); + contentLenStrLen = (word32)XSTRLEN(contentLenStr); + contentTypeStrLen = (word32)XSTRLEN(contentTypeStr); + doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); + + /* determine max length and check it */ + maxLen = + reqTypeLen + + blankStrLen + + pathLen + + http11StrLen + + hostStrLen + + domainNameLen + + contentLenStrLen + + reqSzStrLen + + contentTypeStrLen + + contentTypeLen + + doubleCrLfStrLen + + 1 /* null term */; + if (maxLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, reqType, reqTypeLen); + buf += reqTypeLen; + XSTRNCPY((char*)buf, blankStr, blankStrLen+1); + buf += blankStrLen; + XSTRNCPY((char*)buf, path, pathLen); + buf += pathLen; + XSTRNCPY((char*)buf, http11Str, http11StrLen+1); + buf += http11StrLen; + if (domainNameLen > 0) { + XSTRNCPY((char*)buf, hostStr, hostStrLen+1); + buf += hostStrLen; + XSTRNCPY((char*)buf, domainName, domainNameLen); + buf += domainNameLen; + } + if (reqSz > 0 && reqSzStrLen > 0) { + XSTRNCPY((char*)buf, contentLenStr, contentLenStrLen+1); + buf += contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, reqSzStrLen); + buf += reqSzStrLen; + } + if (contentTypeLen > 0) { + XSTRNCPY((char*)buf, contentTypeStr, contentTypeStrLen+1); + buf += contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, contentTypeLen); + buf += contentTypeLen; + } + XSTRNCPY((char*)buf, doubleCrLfStr, doubleCrLfStrLen+1); + buf += doubleCrLfStrLen; + +#ifdef WOLFIO_DEBUG + printf("HTTP %s: %s", reqType, req); +#endif + + /* calculate actual length based on original and new pointer */ + return (int)((char*)buf - req); } -#define SCRATCH_BUFFER_SIZE 512 +#ifdef HAVE_OCSP + +int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("POST", domainName, path, (int)XSTRLEN(path), + ocspReqSz, "application/ocsp-request", buf, bufSize); +} + +/* return: >0 OCSP Response Size + * -1 error */ +int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, + byte* httpBuf, int httpBufSz, void* heap) +{ + return wolfIO_HttpProcessResponse(sfd, "application/ocsp-response", + respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap); +} /* in default wolfSSL callback ctx is the heap pointer */ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, @@ -1045,19 +1129,19 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, char* path; char* domainName; #else - char path[80]; - char domainName[80]; + char path[MAX_URL_ITEM_SIZE]; + char domainName[MAX_URL_ITEM_SIZE]; #endif #ifdef WOLFSSL_SMALL_STACK - path = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (path == NULL) - return -1; + return MEMORY_E; - domainName = (char*)XMALLOC(80, NULL, DYNAMIC_TYPE_TMP_BUFFER); + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (domainName == NULL) { XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return -1; + return MEMORY_E; } #endif @@ -1067,37 +1151,37 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, else if (ocspRespBuf == NULL) { WOLFSSL_MSG("Cannot save OCSP response"); } - else if (decode_url(url, urlSz, domainName, path, &port) < 0) { + else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) { WOLFSSL_MSG("Unable to decode OCSP URL"); } else { /* Note, the library uses the EmbedOcspRespFree() callback to * free this buffer. */ - int httpBufSz = SCRATCH_BUFFER_SIZE; - byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, - DYNAMIC_TYPE_OCSP); + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); if (httpBuf == NULL) { WOLFSSL_MSG("Unable to create OCSP response buffer"); } else { - httpBufSz = build_http_request(domainName, path, ocspReqSz, + httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz, httpBuf, httpBufSz); - if ((tcp_connect(&sfd, domainName, port) != 0) || (sfd <= 0)) { + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd <= 0)) { WOLFSSL_MSG("OCSP Responder connection failed"); } - else if ((int)send(sfd, (char*)httpBuf, httpBufSz, 0) != + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != httpBufSz) { WOLFSSL_MSG("OCSP http request failed"); } - else if ((int)send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != + else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != ocspReqSz) { WOLFSSL_MSG("OCSP ocsp request failed"); } else { - ret = process_http_response(sfd, ocspRespBuf, httpBuf, - SCRATCH_BUFFER_SIZE, ctx); + ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE, ctx); } close(sfd); @@ -1113,7 +1197,6 @@ int EmbedOcspLookup(void* ctx, const char* url, int urlSz, return ret; } - /* in default callback ctx is heap hint */ void EmbedOcspRespFree(void* ctx, byte *resp) { @@ -1122,11 +1205,96 @@ void EmbedOcspRespFree(void* ctx, byte *resp) (void)ctx; } +#endif /* HAVE_OCSP */ +#if defined(HAVE_CRL) && defined(HAVE_CRL_IO) + +int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, byte* buf, int bufSize) +{ + return wolfIO_HttpBuildRequest("GET", domainName, url, urlSz, 0, "", + buf, bufSize); +} + +int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, + int httpBufSz) +{ + int result; + byte *respBuf = NULL; + + result = wolfIO_HttpProcessResponse(sfd, "application/pkix-crl", + &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap); + if (result >= 0) { + result = BufferLoadCRL(crl, respBuf, result, SSL_FILETYPE_ASN1, 0); + } + XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL); + + return result; +} + +int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* domainName; +#else + char domainName[MAX_URL_ITEM_SIZE]; #endif -#endif /* WOLFSSL_USER_IO */ +#ifdef WOLFSSL_SMALL_STACK + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + return MEMORY_E; + } +#endif + + if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) { + WOLFSSL_MSG("Unable to decode CRL URL"); + } + else { + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, + DYNAMIC_TYPE_CRL); + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create CRL response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd <= 0)) { + WOLFSSL_MSG("CRL connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) + != httpBufSz) { + WOLFSSL_MSG("CRL http get failed"); + } + else { + ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE); + } + + close(sfd); + XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_CRL && HAVE_CRL_IO */ + +#endif /* HAVE_HTTP_CLIENT */ + + WOLFSSL_API void wolfSSL_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) { @@ -1328,5 +1496,5 @@ void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) } #endif /* HAVE_NETX */ -#endif /* WOLFCRYPT_ONLY */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/src/keys.c b/src/keys.c index a1095b1eb..92b03d651 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1053,8 +1053,109 @@ int SetCipherSpecs(WOLFSSL* ssl) return UNSUPPORTED_SUITE; } /* switch */ } /* if */ - if (ssl->options.cipherSuite0 != ECC_BYTE && - ssl->options.cipherSuite0 != CHACHA_BYTE) { /* normal suites */ + + /* TLSi v1.3 cipher suites, 0x13 */ + if (ssl->options.cipherSuite0 == TLS13_BYTE) { + switch (ssl->options.cipherSuite) { + +#ifdef WOLFSSL_TLS13 + #ifdef BUILD_TLS_AES_128_GCM_SHA256 + case TLS_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_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 = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_256_GCM_SHA384 + case TLS_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA384_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 = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + case TLS_CHACHA20_POLY1305_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_SHA256 + case TLS_AES_128_CCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_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 = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + case TLS_AES_128_CCM_8_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = SHA256_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 = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; + #endif +#endif /* WOLFSSL_TLS13 */ + } + } + + if (ssl->options.cipherSuite0 != ECC_BYTE && + ssl->options.cipherSuite0 != CHACHA_BYTE && + ssl->options.cipherSuite0 != TLS13_BYTE) { /* normal suites */ switch (ssl->options.cipherSuite) { #ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA @@ -1653,7 +1754,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_HC_128_SHA case TLS_RSA_WITH_HC_128_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; @@ -1667,7 +1768,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1684,7 +1785,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = HC_128_KEY_SIZE; ssl->specs.block_size = 0; ssl->specs.iv_size = HC_128_IV_SIZE; - + break; #endif @@ -1701,7 +1802,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_128_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1718,7 +1819,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = AES_256_KEY_SIZE; ssl->specs.iv_size = AES_IV_SIZE; ssl->specs.block_size = AES_BLOCK_SIZE; - + break; #endif @@ -1827,7 +1928,7 @@ int SetCipherSpecs(WOLFSSL* ssl) break; #endif - + #ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; @@ -1978,7 +2079,7 @@ int SetCipherSpecs(WOLFSSL* ssl) ssl->specs.key_size = IDEA_KEY_SIZE; ssl->specs.block_size = IDEA_BLOCK_SIZE; ssl->specs.iv_size = IDEA_IV_SIZE; - + break; #endif @@ -1993,8 +2094,11 @@ int SetCipherSpecs(WOLFSSL* ssl) #ifndef NO_TLS ssl->options.tls = 1; ssl->hmac = TLS_hmac; - if (ssl->version.minor >= 2) + if (ssl->version.minor >= 2) { ssl->options.tls1_1 = 1; + if (ssl->version.minor >= 4) + ssl->options.tls1_3 = 1; + } #endif } @@ -2049,7 +2153,7 @@ static int SetPrefix(byte* sha_input, int idx) break; default: WOLFSSL_MSG("Set Prefix error, bad input"); - return 0; + return 0; } return 1; } @@ -2070,22 +2174,20 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (dec && dec->arc4 == NULL) return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Arc4AsyncInit(enc->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_Arc4AsyncInit(dec->arc4, devId) != 0) { - WOLFSSL_MSG("Arc4AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + + if (enc) { + if (wc_Arc4Init(enc->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_Arc4Init(dec->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz); @@ -2103,9 +2205,9 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_ARC4 */ + - #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) /* Check that the max implicit iv size is suffecient */ #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */ @@ -2165,7 +2267,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ + #ifdef HAVE_HC128 /* check that buffer sizes are sufficient */ @@ -2214,8 +2317,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* HAVE_HC128 */ + #ifdef BUILD_RABBIT /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */ @@ -2263,8 +2366,8 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif - +#endif /* BUILD_RABBIT */ + #ifdef BUILD_DES3 /* check that buffer sizes are sufficient */ #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */ @@ -2274,30 +2377,34 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_triple_des) { int desRet = 0; - if (enc && enc->des3 == NULL) - enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->des3 == NULL) - return MEMORY_E; - if (dec && dec->des3 == NULL) - dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->des3 == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_Des3AsyncInit(enc->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_Des3AsyncInit(dec->des3, devId) != 0) { - WOLFSSL_MSG("Des3AsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->des3 == NULL) + enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (enc->des3 == NULL) + return MEMORY_E; + XMEMSET(enc->des3, 0, sizeof(Des3)); + } + if (dec) { + if (dec->des3 == NULL) + dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (dec->des3 == NULL) + return MEMORY_E; + XMEMSET(dec->des3, 0, sizeof(Des3)); + } + + if (enc) { + if (wc_Des3Init(enc->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_Des3Init(dec->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) { desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key, @@ -2327,7 +2434,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_DES3 */ #ifdef BUILD_AES /* check that buffer sizes are sufficient */ @@ -2338,30 +2445,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes) { int aesRet = 0; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - if (enc) { - if (wc_AesAsyncInit(enc->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } - } - if (dec) { - if (wc_AesAsyncInit(dec->aes, devId) != 0) { - WOLFSSL_MSG("AesAsyncInit failed in SetKeys"); - return ASYNC_INIT_E; - } + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; } } -#endif + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (side == WOLFSSL_CLIENT_END) { if (enc) { aesRet = wc_AesSetKey(enc->aes, keys->client_write_key, @@ -2395,7 +2505,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AES */ #ifdef BUILD_AESGCM /* check that buffer sizes are sufficient */ @@ -2412,14 +2522,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) { int gcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2427,14 +2556,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2443,14 +2572,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2458,7 +2587,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* BUILD_AESGCM */ #ifdef HAVE_AESCCM /* check that buffer sizes are sufficient (CCM is same size as GCM) */ @@ -2475,14 +2604,33 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) { int CcmRet; - if (enc && enc->aes == NULL) - enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (enc && enc->aes == NULL) - return MEMORY_E; - if (dec && dec->aes == NULL) - dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); - if (dec && dec->aes == NULL) - return MEMORY_E; + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } if (side == WOLFSSL_CLIENT_END) { if (enc) { @@ -2529,7 +2677,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_AESCCM */ #ifdef HAVE_CAMELLIA /* check that buffer sizes are sufficient */ @@ -2581,7 +2729,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_CAMELLIA */ #ifdef HAVE_IDEA /* check that buffer sizes are sufficient */ @@ -2635,7 +2783,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (dec) dec->setup = 1; } -#endif +#endif /* HAVE_IDEA */ #ifdef HAVE_NULL_CIPHER if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) { @@ -2681,6 +2829,7 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, if (authentication) authentication->setup = 1; #endif + (void)authentication; (void)heap; (void)keys; (void)specs; @@ -2690,6 +2839,40 @@ static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, } #endif /* HAVE_ONE_TIME_AUTH */ +#ifdef HAVE_SECURE_RENEGOTIATION +/* function name is for cache_status++ + * This function was added because of error incrementing enum type when + * compiling with a C++ compiler. + */ +static void CacheStatusPP(SecureRenegotiation* cache) +{ + switch (cache->cache_status) { + case SCR_CACHE_NULL: + cache->cache_status = SCR_CACHE_NEEDED; + break; + + case SCR_CACHE_NEEDED: + cache->cache_status = SCR_CACHE_COPY; + break; + + case SCR_CACHE_COPY: + cache->cache_status = SCR_CACHE_PARTIAL; + break; + + case SCR_CACHE_PARTIAL: + cache->cache_status = SCR_CACHE_COMPLETE; + break; + + case SCR_CACHE_COMPLETE: + WOLFSSL_MSG("SCR Cache state Complete"); + break; + + default: + WOLFSSL_MSG("Unknown cache state!!"); + } +} +#endif /* HAVE_SECURE_RENEGOTIATION */ + /* Set wc_encrypt/wc_decrypt or both sides of key setup * note: use wc_encrypt to avoid shadowing global encrypt @@ -2804,7 +2987,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) } #endif } - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -2822,7 +3005,7 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == SCR_CACHE_NEEDED) { keys = &ssl->secure_renegotiation->tmp_keys; - ssl->secure_renegotiation->cache_status++; + CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -2857,12 +3040,12 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData) #ifndef NO_OLD_TLS int DeriveKeys(WOLFSSL* ssl) { - int length = 2 * ssl->specs.hash_size + + int length = 2 * ssl->specs.hash_size + 2 * ssl->specs.key_size + 2 * ssl->specs.iv_size; int rounds = (length + MD5_DIGEST_SIZE - 1 ) / MD5_DIGEST_SIZE, i; int ret = 0; - + #ifdef WOLFSSL_SMALL_STACK byte* shaOutput; byte* md5Input; @@ -2878,9 +3061,9 @@ int DeriveKeys(WOLFSSL* ssl) Md5 md5[1]; Sha sha[1]; #endif - + #ifdef WOLFSSL_SMALL_STACK - shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, + shaOutput = (byte*)XMALLOC(SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); md5Input = (byte*)XMALLOC(SECRET_LEN + SHA_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2890,7 +3073,7 @@ int DeriveKeys(WOLFSSL* ssl) NULL, DYNAMIC_TYPE_TMP_BUFFER); md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || keyData == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -2899,15 +3082,15 @@ int DeriveKeys(WOLFSSL* ssl) if (keyData) XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN); @@ -2925,14 +3108,21 @@ int DeriveKeys(WOLFSSL* ssl) XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN); - - wc_ShaUpdate(sha, shaInput, (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - - KEY_PREFIX + j); - wc_ShaFinal(sha, shaOutput); + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, + (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } XMEMCPY(md5Input + SECRET_LEN, shaOutput, SHA_DIGEST_SIZE); - wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); - wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, SECRET_LEN + SHA_DIGEST_SIZE); + } + if (ret == 0) { + ret = wc_Md5Final(md5, keyData + i * MD5_DIGEST_SIZE); + } } if (ret == 0) @@ -3010,7 +3200,7 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) NULL, DYNAMIC_TYPE_TMP_BUFFER); md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || md5 == NULL || sha == NULL) { if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3018,15 +3208,15 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); - + return MEMORY_E; } #endif - wc_InitMd5(md5); - - ret = wc_InitSha(sha); - + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } if (ret == 0) { XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz); @@ -3047,14 +3237,22 @@ static int MakeSslMasterSecret(WOLFSSL* ssl) idx += RAN_LEN; XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); idx += RAN_LEN; - wc_ShaUpdate(sha, shaInput, idx); - wc_ShaFinal(sha, shaOutput); - + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, idx); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } idx = pmsSz; /* preSz */ XMEMCPY(md5Input + idx, shaOutput, SHA_DIGEST_SIZE); idx += SHA_DIGEST_SIZE; - wc_Md5Update(md5, md5Input, idx); - wc_Md5Final(md5, &ssl->arrays->masterSecret[i * MD5_DIGEST_SIZE]); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, idx); + } + if (ret == 0) { + ret = wc_Md5Final(md5, + &ssl->arrays->masterSecret[i * MD5_DIGEST_SIZE]); + } } #ifdef SHOW_SECRETS diff --git a/src/ocsp.c b/src/ocsp.c index e8de3d512..ae45322ed 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -110,9 +110,9 @@ void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) } -static int xstat2err(int stat) +static int xstat2err(int st) { - switch (stat) { + switch (st) { case CERT_GOOD: return 0; case CERT_REVOKED: @@ -219,9 +219,11 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, ret = OCSP_INVALID_STATUS; } else if (*status) { +#ifndef NO_ASN_TIME if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) && ((*status)->nextDate[0] != 0) && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) +#endif { ret = xstat2err((*status)->status); @@ -244,6 +246,134 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, return ret; } +/* Check that the response for validity. Store result in status. + * + * ocsp Context object for OCSP status. + * response OCSP response message data. + * responseSz Length of OCSP response message data. + * reponseBuffer Buffer object to return the response with. + * status The certificate status object. + * entry The OCSP entry for this certificate. + * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. + */ +static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz, + buffer* responseBuffer, CertStatus* status, + OcspEntry* entry, OcspRequest* ocspRequest) +{ +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + int ret; + int validated = 0; /* ocsp validation flag */ + +#ifdef WOLFSSL_SMALL_STACK + newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (newStatus == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, responseSz); + ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); + if (ret != 0) { + WOLFSSL_MSG("OcspResponseDecode failed"); + goto end; + } + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { + WOLFSSL_MSG("OcspResponse status bad"); + goto end; + } + if (ocspRequest != NULL) { + ret = CompareOcspReqResp(ocspRequest, ocspResponse); + if (ret != 0) { + goto end; + } + } + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = responseSz; + XMEMCPY(responseBuffer->buffer, response, responseSz); + } + } + + ret = xstat2err(ocspResponse->status->status); + if (ret == 0) { + validated = 1; + } + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + ret = BAD_MUTEX_E; + goto end; + } + + if (status != NULL) { + if (status->rawOcspResponse) { + XFREE(status->rawOcspResponse, ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + } + + /* Replace existing certificate entry with updated */ + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } + else { + /* Save new certificate entry */ + status = (CertStatus*)XMALLOC(sizeof(CertStatus), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; + } + } + + if (status && responseBuffer && responseBuffer->buffer) { + status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, + ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, + responseBuffer->length); + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + +end: + if (ret == 0 && validated == 1) { + WOLFSSL_MSG("New OcspResponse validated"); + } else if (ret != OCSP_CERT_REVOKED) { + ret = OCSP_LOOKUP_FAIL; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + +/* 0 on success */ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, buffer* responseBuffer) { @@ -251,19 +381,12 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, CertStatus* status = NULL; byte* request = NULL; int requestSz = 2048; + int responseSz = 0; byte* response = NULL; const char* url = NULL; int urlSz = 0; int ret = -1; -#ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; - OcspResponse* ocspResponse; -#else - CertStatus newStatus[1]; - OcspResponse ocspResponse[1]; -#endif - WOLFSSL_ENTER("CheckOcspRequest"); if (responseBuffer) { @@ -279,6 +402,22 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, if (ret != OCSP_INVALID_STATUS) return ret; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ocsp->statusCb != NULL && ocspRequest->ssl != NULL) { + ret = ocsp->statusCb((WOLFSSL*)ocspRequest->ssl, ocsp->cm->ocspIOCtx); + if (ret == 0) { + ret = wolfSSL_get_ocsp_response((WOLFSSL*)ocspRequest->ssl, + &response); + ret = CheckResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + return OCSP_LOOKUP_FAIL; + } +#endif + if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') @@ -301,102 +440,18 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return MEMORY_ERROR; } -#ifdef WOLFSSL_SMALL_STACK - newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (newStatus == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - XFREE(request, NULL, DYNAMIC_TYPE_OCSP); - - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_E; - } -#endif - requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); - - if (ocsp->cm->ocspIOCb) - ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, - request, requestSz, &response); - - if (ret >= 0 && response) { - XMEMSET(newStatus, 0, sizeof(CertStatus)); - - InitOcspResponse(ocspResponse, newStatus, response, ret); - OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap); - - if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) - ret = OCSP_LOOKUP_FAIL; - else { - if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - if (responseBuffer) { - responseBuffer->buffer = (byte*)XMALLOC(ret, ocsp->cm->heap, - DYNAMIC_TYPE_TMP_BUFFER); - - if (responseBuffer->buffer) { - responseBuffer->length = ret; - XMEMCPY(responseBuffer->buffer, response, ret); - } - } - - ret = xstat2err(ocspResponse->status->status); - - if (wc_LockMutex(&ocsp->ocspLock) != 0) - ret = BAD_MUTEX_E; - else { - if (status != NULL) { - if (status->rawOcspResponse) - XFREE(status->rawOcspResponse, ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - /* Replace existing certificate entry with updated */ - XMEMCPY(status, newStatus, sizeof(CertStatus)); - } - else { - /* Save new certificate entry */ - status = (CertStatus*)XMALLOC(sizeof(CertStatus), - ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); - if (status != NULL) { - XMEMCPY(status, newStatus, sizeof(CertStatus)); - status->next = entry->status; - entry->status = status; - entry->totalStatus++; - } - } - - if (status && responseBuffer && responseBuffer->buffer) { - status->rawOcspResponse = (byte*)XMALLOC( - responseBuffer->length, - ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - if (status->rawOcspResponse) { - status->rawOcspResponseSz = responseBuffer->length; - XMEMCPY(status->rawOcspResponse, - responseBuffer->buffer, - responseBuffer->length); - } - } - - wc_UnLockMutex(&ocsp->ocspLock); - } - } - else - ret = OCSP_LOOKUP_FAIL; - } + if (requestSz > 0 && ocsp->cm->ocspIOCb) { + responseSz = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + request, requestSz, &response); } - else - ret = OCSP_LOOKUP_FAIL; -#ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + + if (responseSz >= 0 && response) { + ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); + } if (response != NULL && ocsp->cm->ocspRespFreeCb) ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); @@ -405,6 +460,372 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return ret; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd) +{ + if (bs == NULL || id == NULL) + return SSL_FAILURE; + + /* Only supporting one certificate status in asn.c. */ + if (CompareOcspReqResp(id, bs) != 0) + return SSL_FAILURE; + + if (status != NULL) + *status = bs->status->status; + if (thisupd != NULL) + *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn; + if (nextupd != NULL) + *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn; + + /* TODO: Not needed for Nginx. */ + if (reason != NULL) + *reason = 0; + if (revtime != NULL) + *revtime = NULL; + + return SSL_SUCCESS; +} + +const char *wolfSSL_OCSP_cert_status_str(long s) +{ + switch (s) { + case CERT_GOOD: + return "good"; + case CERT_REVOKED: + return "revoked"; + case CERT_UNKNOWN: + return "unknown"; + default: + return "(UNKNOWN)"; + } +} + +int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) +{ + (void)thisupd; + (void)nextupd; + (void)sec; + (void)maxsec; + /* Dates validated in DecodeSingleResponse. */ + return SSL_SUCCESS; +} + +void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) +{ + FreeOcspRequest(certId); + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer) +{ + WOLFSSL_OCSP_CERTID* certId; + DecodedCert cert; + WOLFSSL_CERT_MANAGER* cm; + int ret; + DerBuffer* derCert = NULL; + + (void)dgst; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) + return NULL; + + ret = AllocDer(&derCert, issuer->derCert->length, + issuer->derCert->type, NULL); + if (ret == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, issuer->derCert->buffer, + issuer->derCert->length); + AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (certId != NULL) { + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + ret = InitOcspRequest(certId, &cert, 0, NULL); + if (ret != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + } + FreeDecodedCert(&cert); + } + + wolfSSL_CertManagerFree(cm); + + return certId; +} + +void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) +{ + wolfSSL_OCSP_RESPONSE_free(basicResponse); +} + +/* Signature verified in DecodeBasicOcspResponse. + * But no store available to verify certificate. */ +int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) +{ + DecodedCert cert; + int ret = SSL_SUCCESS; + + (void)certs; + + if (flags & OCSP_NOVERIFY) + return SSL_SUCCESS; + + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) + ret = SSL_FAILURE; + FreeDecodedCert(&cert); + + return ret; +} + +void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) +{ + if (response->status != NULL) + XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response->source != NULL) + XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response) +{ + byte* data; + byte* p; + int len; + int dataAlloced = 0; + OcspResponse* ret = NULL; + + if (bio == NULL) + return NULL; + + if (bio->type == BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } + else if (bio->type == BIO_FILE) { + long i; + long l; + + i = XFTELL(bio->file); + if (i < 0) + return NULL; + XFSEEK(bio->file, 0, SEEK_END); + l = XFTELL(bio->file); + if (l < 0) + return NULL; + XFSEEK(bio->file, i, SEEK_SET); + + /* check calulated length */ + if (l - i <= 0) + return NULL; + + data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)l); + } + else + return NULL; + + if (len > 0) { + p = data; + ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len); + } + + if (dataAlloced) + XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len) +{ + OcspResponse *resp = NULL; + word32 idx = 0; + int length = 0; + + if (data == NULL) + return NULL; + + if (response != NULL) + resp = *response; + if (resp == NULL) { + resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_OPENSSL); + if (resp == NULL) + return NULL; + XMEMSET(resp, 0, sizeof(OcspResponse)); + } + + resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (resp->source == NULL) { + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (resp->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(resp->source, *data, len); + resp->maxIdx = len; + + if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) { + wolfSSL_OCSP_RESPONSE_free(resp); + return NULL; + } + + if (GetSequence(*data, &idx, &length, len) >= 0) + (*data) += idx + length; + + return resp; +} + +int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data) +{ + if (data == NULL) + return response->maxIdx; + + XMEMCPY(*data, response->source, response->maxIdx); + return response->maxIdx; +} + +int wolfSSL_OCSP_response_status(OcspResponse *response) +{ + return response->responseStatus; +} + +const char *wolfSSL_OCSP_response_status_str(long s) +{ + switch (s) { + case OCSP_SUCCESSFUL: + return "successful"; + case OCSP_MALFORMED_REQUEST: + return "malformedrequest"; + case OCSP_INTERNAL_ERROR: + return "internalerror"; + case OCSP_TRY_LATER: + return "trylater"; + case OCSP_SIG_REQUIRED: + return "sigrequired"; + case OCSP_UNAUTHROIZED: + return "unauthorized"; + default: + return "(UNKNOWN)"; + } +} + +WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) +{ + WOLFSSL_OCSP_BASICRESP* bs; + + bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, + DYNAMIC_TYPE_OPENSSL); + if (bs == NULL) + return NULL; + + XMEMCPY(bs, response, sizeof(OcspResponse)); + bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->status == NULL || bs->source == NULL) { + if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_OCSP_RESPONSE_free(bs); + bs = NULL; + } + else { + XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->source, response->source, response->maxIdx); + } + return bs; +} + +OcspRequest* wolfSSL_OCSP_REQUEST_new(void) +{ + OcspRequest* request; + + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OPENSSL); + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + return request; +} + +void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) +{ + FreeOcspRequest(request); + XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) +{ + word32 size; + + size = EncodeOcspRequest(request, NULL, 0); + if (size <= 0 || data == NULL) + return size; + + return EncodeOcspRequest(request, *data, size); +} + +WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid) +{ + if (req == NULL || cid == NULL) + return NULL; + + FreeOcspRequest(req); + XMEMCPY(req, cid, sizeof(OcspRequest)); + + if (cid->serial != NULL) { + req->serial = (byte*)XMALLOC(cid->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL || req->url == NULL) { + FreeOcspRequest(req); + return NULL; + } + + XMEMCPY(req->serial, cid->serial, cid->serialSz); + XMEMCPY(req->url, cid->url, cid->urlSz); + } + + wolfSSL_OCSP_REQUEST_free(cid); + + return req; +} + +#endif #else /* HAVE_OCSP */ diff --git a/src/sniffer.c b/src/sniffer.c index 33278f4e0..738e5360f 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -55,16 +55,6 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - -static INLINE word32 min(word32 a, word32 b) -{ - return a > b ? b : a; -} - -#endif /* WOLFSSL_HAVE_MIN */ - #ifndef WOLFSSL_SNIFFER_TIMEOUT #define WOLFSSL_SNIFFER_TIMEOUT 900 /* Cache unclosed Sessions for 15 minutes since last used */ @@ -203,21 +193,21 @@ static const char* const msgTable[] = "Got an Alert msg", "Another msg to Process", "Removing Session From Table", - + /* 46 */ "Bad Key File", "Wrong IP Version", "Wrong Protocol type", "Packet Short for header processing", "Got Unknown Record Type", - + /* 51 */ "Can't Open Trace File", "Session in Fatal Error State", "Partial SSL record received", "Buffer Error, malformed input", "Added to Partial Input", - + /* 56 */ "Received a Duplicate Packet", "Received an Out of Order Packet", @@ -488,7 +478,7 @@ static void FreePacketList(PacketBuffer* in) if (in) { PacketBuffer* del; PacketBuffer* packet = in; - + while (packet) { del = packet; packet = packet->next; @@ -504,7 +494,7 @@ static void FreeSnifferSession(SnifferSession* session) if (session) { SSL_free(session->sslClient); SSL_free(session->sslServer); - + FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); @@ -528,7 +518,7 @@ void ssl_FreeSniffer(void) wc_LockMutex(&ServerListMutex); wc_LockMutex(&SessionMutex); - + srv = ServerList; while (srv) { removeServer = srv; @@ -576,8 +566,9 @@ static int HashInit(HsHashes* hash) ret = wc_InitSha(&hash->hashSha); #endif #ifndef NO_MD5 - if (ret == 0) - wc_InitMd5(&hash->hashMd5); + if (ret == 0) { + ret = wc_InitMd5(&hash->hashMd5); + } #endif #endif #ifndef NO_SHA256 @@ -606,8 +597,9 @@ static int HashUpdate(HsHashes* hash, const byte* input, int sz) ret = wc_ShaUpdate(&hash->hashSha, input, sz); #endif #ifndef NO_MD5 - if (ret == 0) - wc_Md5Update(&hash->hashMd5, input, sz); + if (ret == 0) { + ret = wc_Md5Update(&hash->hashMd5, input, sz); + } #endif #endif #ifndef NO_SHA256 @@ -714,7 +706,7 @@ static void InitSession(SnifferSession* session) session->srvReassemblyMemory = 0; session->next = 0; session->ticketID = 0; - + InitFlags(&session->flags); InitFinCapture(&session->finCaputre); #ifdef HAVE_EXTENDED_MASTER @@ -768,9 +760,9 @@ static int SetPassword(char* passwd, int sz, int rw, void* userdata) /* Ethernet Header */ typedef struct EthernetHdr { - byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ - byte src[ETHER_IF_ADDR_LEN]; /* source host address */ - word16 type; /* IP, ARP, etc */ + byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ + byte src[ETHER_IF_ADDR_LEN]; /* source host address */ + word16 type; /* IP, ARP, etc */ } EthernetHdr; @@ -796,8 +788,8 @@ typedef struct IpHdr { typedef struct TcpHdr { word16 srcPort; /* source port */ word16 dstPort; /* destination port */ - word32 sequence; /* sequence number */ - word32 ack; /* acknoledgment number */ + word32 sequence; /* sequence number */ + word32 ack; /* acknoledgment number */ byte offset; /* data offset, reserved */ byte flags; /* option flags */ word16 window; /* window */ @@ -815,8 +807,8 @@ typedef struct TcpHdr { -/* Use platform specific GetError to write to tracfile if tracing */ -static void Trace(int idx) +/* Use platform specific GetError to write to tracfile if tracing */ +static void Trace(int idx) { if (TraceOn) { char myBuffer[MAX_ERROR_LEN]; @@ -881,9 +873,9 @@ static void TracePacket(void) static char* IpToS(word32 addr, char* str) { byte* p = (byte*)&addr; - + SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - + return str; } @@ -1041,7 +1033,7 @@ static int IsServerRegistered(word32 addr) SnifferServer* sniffer; wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->server == addr) { @@ -1050,7 +1042,7 @@ static int IsServerRegistered(word32 addr) } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1063,18 +1055,18 @@ static int IsPortRegistered(word32 port) { int ret = 0; /* false */ SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == (int)port) { - ret = 1; + ret = 1; break; } sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); return ret; @@ -1085,9 +1077,9 @@ static int IsPortRegistered(word32 port) static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferServer* sniffer; - + wc_LockMutex(&ServerListMutex); - + sniffer = ServerList; while (sniffer) { if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) @@ -1096,9 +1088,9 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) break; sniffer = sniffer->next; } - + wc_UnLockMutex(&ServerListMutex); - + return sniffer; } @@ -1108,7 +1100,7 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { word32 hash = ipInfo->src * ipInfo->dst; hash *= tcpInfo->srcPort * tcpInfo->dstPort; - + return hash % HASH_SIZE; } @@ -1117,13 +1109,13 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) { SnifferSession* session; - time_t currTime = time(NULL); + time_t currTime = time(NULL); word32 row = SessionHash(ipInfo, tcpInfo); assert(row <= HASH_SIZE); - + wc_LockMutex(&SessionMutex); - + session = SessionTable[row]; while (session) { if (session->server == ipInfo->src && session->client == ipInfo->dst && @@ -1134,15 +1126,15 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->cliPort == tcpInfo->srcPort && session->srvPort == tcpInfo->dstPort) break; - + session = session->next; } if (session) session->lastUsed= currTime; /* keep session alive, remove stale will */ - /* leave alone */ + /* leave alone */ wc_UnLockMutex(&SessionMutex); - + /* determine side */ if (session) { if (ipInfo->dst == session->context->server && @@ -1150,8 +1142,8 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session->flags.side = WOLFSSL_SERVER_END; else session->flags.side = WOLFSSL_CLIENT_END; - } - + } + return session; } @@ -1183,9 +1175,14 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, return -1; } - ret = (int)XFREAD(loadBuf, fileSz, 1, file); + ret = (int)XFREAD(loadBuf, 1, fileSz, file); XFCLOSE(file); + if (ret != fileSz) { + free(loadBuf); + return -1; + } + if (typeKey == SSL_FILETYPE_PEM) { byte* saveBuf = (byte*)malloc(fileSz); int saveBufSz = 0; @@ -1394,11 +1391,11 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) Trace(IP_CHECK_STR); if (version != IPV4) { - SetError(BAD_IPVER_STR, error, NULL, 0); + SetError(BAD_IPVER_STR, error, NULL, 0); return -1; } - if (iphdr->protocol != TCP_PROTOCOL) { + if (iphdr->protocol != TCP_PROTOCOL) { SetError(BAD_PROTO_STR, error, NULL, 0); return -1; } @@ -1435,7 +1432,7 @@ static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error) info->syn = tcphdr->flags & TCP_SYN; info->ack = tcphdr->flags & TCP_ACK; if (info->ack) - info->ackNumber = ntohl(tcphdr->ack); + info->ackNumber = ntohl(tcphdr->ack); if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) { SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0); @@ -1920,12 +1917,12 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } input += bLen; *sslBytes -= bLen; - + if (*sslBytes == 0) { /* no extensions */ return 0; } - + /* skip extensions until session ticket */ /* make sure can read len */ if (SUITE_LEN > *sslBytes) { @@ -1998,7 +1995,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SSL* ssl; word32 inOutIdx = 0; int ret; - + if (session->flags.side == WOLFSSL_SERVER_END) ssl = session->sslServer; else @@ -2012,7 +2009,7 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); return ret; } - + if (ret == 0 && session->flags.cached == 0) { if (session->sslServer->options.haveSessionId) { WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); @@ -2048,7 +2045,7 @@ static int DoHandShake(const byte* input, int* sslBytes, } type = input[0]; size = (input[1] << 16) | (input[2] << 8) | input[3]; - + input += HANDSHAKE_HEADER_SZ; *sslBytes -= HANDSHAKE_HEADER_SZ; startBytes = *sslBytes; @@ -2065,7 +2062,7 @@ static int DoHandShake(const byte* input, int* sslBytes, SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); return -1; } - + #ifdef HAVE_EXTENDED_MASTER if (session->hash) { if (HashUpdate(session->hash, input, size) != 0) { @@ -2175,32 +2172,32 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) wc_Arc4Process(ssl->decrypt.arc4, output, input, sz); break; #endif - + #ifdef BUILD_DES3 case wolfssl_triple_des: ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz); break; #endif - + #ifdef BUILD_AES case wolfssl_aes: ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz); break; #endif - + #ifdef HAVE_HC128 case wolfssl_hc128: wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz); break; #endif - + #ifdef BUILD_RABBIT case wolfssl_rabbit: wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz); break; #endif - #ifdef HAVE_CAMELLIA + #ifdef HAVE_CAMELLIA case wolfssl_camellia: wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz); break; @@ -2216,6 +2213,9 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) case wolfssl_aes_gcm: if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size)) { + /* scratch buffer, sniffer ignores auth tag*/ + byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ]; + byte nonce[AESGCM_NONCE_SZ]; XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); @@ -2225,7 +2225,7 @@ static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) input + AESGCM_EXP_IV_SZ, sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, nonce, AESGCM_NONCE_SZ, - NULL, 0, + authTag, sizeof(authTag), NULL, 0) < 0) { Trace(BAD_DECRYPT); ret = -1; @@ -2276,7 +2276,7 @@ static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, if (ssl->specs.cipher_type == block) ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; - + return output; } @@ -2289,20 +2289,20 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, SnifferSession* current; word32 row = rowHint; int haveLock = 0; - + if (ipInfo && tcpInfo) row = SessionHash(ipInfo, tcpInfo); else haveLock = 1; - + assert(row <= HASH_SIZE); Trace(REMOVE_SESSION_STR); - + if (!haveLock) wc_LockMutex(&SessionMutex); - + current = SessionTable[row]; - + while (current) { if (current == session) { if (previous) @@ -2316,7 +2316,7 @@ static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, previous = current; current = current->next; } - + if (!haveLock) wc_UnLockMutex(&SessionMutex); } @@ -2327,11 +2327,11 @@ static void RemoveStaleSessions(void) { word32 i; SnifferSession* session; - + for (i = 0; i < HASH_SIZE; i++) { session = SessionTable[i]; while (session) { - SnifferSession* next = session->next; + SnifferSession* next = session->next; if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) { TraceStaleSession(); RemoveSession(session, NULL, NULL, i); @@ -2348,7 +2348,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, { SnifferSession* session = 0; int row; - + Trace(NEW_SESSION_STR); /* create a new one */ session = (SnifferSession*)malloc(sizeof(SnifferSession)); @@ -2380,14 +2380,14 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->cliSeqStart = tcpInfo->sequence; session->cliExpected = 1; /* relative */ session->lastUsed= time(NULL); - + session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); free(session); return 0; } - + session->sslServer = SSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); @@ -2405,31 +2405,31 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, } /* put server back into server mode */ session->sslServer->options.side = WOLFSSL_SERVER_END; - + row = SessionHash(ipInfo, tcpInfo); - + /* add it to the session table */ wc_LockMutex(&SessionMutex); - + session->next = SessionTable[row]; SessionTable[row] = session; - + SessionCount++; - + if ( (SessionCount % HASH_SIZE) == 0) { TraceFindingStale(); RemoveStaleSessions(); } - + wc_UnLockMutex(&SessionMutex); - + /* determine headed side */ if (ipInfo->dst == session->context->server && tcpInfo->dstPort == session->context->port) session->flags.side = WOLFSSL_SERVER_END; else - session->flags.side = WOLFSSL_CLIENT_END; - + session->flags.side = WOLFSSL_CLIENT_END; + return session; } @@ -2458,16 +2458,16 @@ static int DoOldHello(SnifferSession* session, const byte* sslFrame, } ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes, - (word16)*rhSize); + (word16)*rhSize); if (ret < 0 && ret != MATCH_SUITE_ERROR) { SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE); return -1; } - + Trace(OLD_CLIENT_OK_STR); XMEMCPY(session->sslClient->arrays->clientRandom, session->sslServer->arrays->clientRandom, RAN_LEN); - + *sslBytes -= *rhSize; return 0; } @@ -2490,38 +2490,38 @@ int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen, const word16* data = (word16*)&pseudo; word32 sum = 0; word16 checksum; - + pseudo.src = ipInfo->src; pseudo.dst = ipInfo->dst; pseudo.rsv = 0; pseudo.protocol = TCP_PROTO; pseudo.length = htons(tcpInfo->length + dataLen); - + /* pseudo header sum */ while (count >= 2) { sum += *data++; count -= 2; } - + count = tcpInfo->length + dataLen; data = (word16*)packet; - + /* main sum */ while (count > 1) { sum += *data++; count -=2; } - + /* get left-over, if any */ packet = (byte*)data; if (count > 0) { sum += *packet; } - + /* fold 32bit sum into 16 bits */ while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - + checksum = (word16)~sum; /* checksum should now equal 0, since included already calcd checksum */ /* field, but tcp checksum offloading could negate calculation */ @@ -2547,23 +2547,23 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet, } if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0) return -1; - - /* tcp header */ + + /* tcp header */ if (length < (ipInfo->length + TCP_HDR_SZ)) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0) return -1; - - /* setup */ + + /* setup */ *sslFrame = packet + ipInfo->length + tcpInfo->length; if (*sslFrame > packet + length) { SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } *sslBytes = (int)(packet + length - *sslFrame); - + return 0; } @@ -2582,7 +2582,7 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* already had existing, so OK */ if (*session) return 1; - + SetError(MEMORY_STR, error, NULL, 0); return -1; } @@ -2598,10 +2598,10 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, /* don't worry about duplicate ACKs either */ if (sslBytes == 0 && tcpInfo->ack) return 1; - + SetError(BAD_SESSION_STR, error, NULL, 0); return -1; - } + } } return 0; } @@ -2612,27 +2612,27 @@ static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data, int* bytesLeft) { PacketBuffer* pb; - + int added = end - *begin + 1; assert(*begin <= end); - + pb = (PacketBuffer*)malloc(sizeof(PacketBuffer)); if (pb == NULL) return NULL; - + pb->next = 0; pb->begin = *begin; pb->end = end; pb->data = (byte*)malloc(added); - + if (pb->data == NULL) { free(pb); return NULL; } XMEMCPY(pb->data, data, added); - + *bytesLeft -= added; *begin = pb->end + 1; - + return pb; } @@ -2647,7 +2647,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, &session->cliReassemblyList: &session->srvReassemblyList; PacketBuffer* curr = *front; PacketBuffer* prev = curr; - + word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; word32 startSeq = seq; @@ -2670,14 +2670,14 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *reassemblyMemory += sslBytes; return 1; } - + /* add to front if before current front, up to next->begin */ if (seq < curr->begin) { word32 end = seq + sslBytes - 1; - + if (end >= curr->begin) end = curr->begin - 1; - + if (MaxRecoveryMemory -1 && (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2692,7 +2692,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, *front = add; *reassemblyMemory += sslBytes; } - + /* while we have bytes left, try to find a gap to fill */ while (bytesLeft > 0) { /* get previous packet in list */ @@ -2700,7 +2700,7 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, prev = curr; curr = curr->next; } - + /* don't add duplicate data */ if (prev->end >= seq) { if ( (seq + bytesLeft - 1) <= prev->end) @@ -2708,18 +2708,18 @@ static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, seq = prev->end + 1; bytesLeft = startSeq + sslBytes - seq; } - + if (!curr) /* we're at the end */ added = bytesLeft; - else + else /* we're in between two frames */ added = min((word32)bytesLeft, curr->begin - seq); - + /* data already there */ if (added == 0) continue; - + if (MaxRecoveryMemory != -1 && (int)(*reassemblyMemory + added) > MaxRecoveryMemory) { SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); @@ -2760,7 +2760,7 @@ static int AddFinCapture(SnifferSession* session, word32 sequence) static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, int* sslBytes, const byte** sslFrame, char* error) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->cliSeqStart :session->srvSeqStart; word32 real = tcpInfo->sequence - seqStart; word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? @@ -2770,19 +2770,19 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? session->flags.srvSkipPartial : session->flags.cliSkipPartial; - + /* handle rollover of sequence */ if (tcpInfo->sequence < seqStart) real = 0xffffffffU - seqStart + tcpInfo->sequence; - + TraceRelativeSequence(*expected, real); - + if (real < *expected) { Trace(DUPLICATE_STR); if (real + *sslBytes > *expected) { int overlap = *expected - real; Trace(OVERLAP_DUPLICATE_STR); - + /* adjust to expected, remove duplicate */ *sslFrame += overlap; *sslBytes -= overlap; @@ -2792,16 +2792,16 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, * block be sure to also update the block below. */ if (reassemblyList) { word32 newEnd = *expected + *sslBytes; - + if (newEnd > reassemblyList->begin) { Trace(OVERLAP_REASSEMBLY_BEGIN_STR); - + /* remove bytes already on reassembly list */ *sslBytes -= newEnd - reassemblyList->begin; } if (newEnd > reassemblyList->end) { Trace(OVERLAP_REASSEMBLY_END_STR); - + /* may be past reassembly list end (could have more on list) so try to add what's past the front->end */ AddToReassembly(session->flags.side, reassemblyList->end +1, @@ -2865,7 +2865,7 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, *expected += *sslBytes; if (tcpInfo->fin) *expected += 1; - + return 0; } @@ -2985,16 +2985,16 @@ static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session) static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session) { if (tcpInfo->ack) { - word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvSeqStart :session->cliSeqStart; word32 real = tcpInfo->ackNumber - seqStart; word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ? session->srvExpected : session->cliExpected; - + /* handle rollover of sequence */ if (tcpInfo->ackNumber < seqStart) real = 0xffffffffU - seqStart + tcpInfo->ackNumber; - + TraceAck(real, expected); if (real > expected) @@ -3022,13 +3022,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerSyn(tcpInfo->sequence); return 1; } - + /* adjust potential ethernet trailer */ actualLen = ipInfo->total - ipInfo->length - tcpInfo->length; if (*sslBytes > actualLen) { *sslBytes = actualLen; } - + TraceSequence(tcpInfo->sequence, *sslBytes); if (CheckAck(tcpInfo, session) < 0) { if (!RecoveryEnabled) { @@ -3045,13 +3045,13 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, return FixSequence(tcpInfo, session); } } - + if (*ackFault) { Trace(CLEAR_ACK_FAULT); *ackFault = 0; } - return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); + return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); } @@ -3074,19 +3074,19 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, (*session)->flags.finCount += 1; else if (tcpInfo->rst) (*session)->flags.finCount += 2; - + if ((*session)->flags.finCount >= 2) { RemoveSession(*session, ipInfo, tcpInfo, 0); *session = NULL; return 1; } } - + if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { SetError(FATAL_ERROR_STR, error, NULL, 0); return -1; } - + if (skipPartial) { if (FindNextRecordInAssembly(*session, sslFrame, sslBytes, end, error) < 0) { @@ -3098,13 +3098,13 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, Trace(NO_DATA_STR); return 1; } - + /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) { Trace(PARTIAL_ADD_STR); - + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); @@ -3168,7 +3168,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, session->sslServer : session->sslClient; word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? &session->cliReassemblyMemory : &session->srvReassemblyMemory; - + while (*front && ((*front)->begin == *expected) ) { word32 room = *bufferSize - *length; word32 packetLen = (*front)->end - (*front)->begin + 1; @@ -3180,21 +3180,21 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } room = *bufferSize - *length; /* bufferSize is now bigger */ } - + if (packetLen <= room) { PacketBuffer* del = *front; byte* buf = *myBuffer; - + XMEMCPY(&buf[*length], (*front)->data, packetLen); *length += packetLen; *expected += packetLen; - + /* remove used packet */ *front = (*front)->next; *reassemblyMemory -= packetLen; FreePacketBuffer(del); - + moreInput = 1; } else @@ -3207,7 +3207,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, } return moreInput; } - + /* Process Message(s) from sslFrame */ @@ -3246,11 +3246,11 @@ doMessage: if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { /* don't have enough input yet to process full SSL record */ Trace(PARTIAL_INPUT_STR); - + /* store partial if not there already or we advanced */ if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) { if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) { - if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { + if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } @@ -3266,7 +3266,7 @@ doMessage: sslBytes -= RECORD_HEADER_SZ; recordEnd = sslFrame + rhSize; /* may have more than one record */ inRecordEnd = recordEnd; - + /* decrypt if needed */ if ((session->flags.side == WOLFSSL_SERVER_END && session->flags.serverCipherOn) @@ -3294,7 +3294,7 @@ doMessage: } doPart: - + switch ((enum ContentType)rh.type) { case handshake: { @@ -3334,7 +3334,7 @@ doPart: Trace(GOT_APP_DATA_STR); { word32 inOutIdx = 0; - + ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx); if (ret == 0) { ret = ssl->buffers.clearOutputBuffer.length; @@ -3398,26 +3398,26 @@ doPart: sslBytes = (int)(end - recordEnd); goto doMessage; } - + /* clear used input */ ssl->buffers.inputBuffer.length = 0; - + /* could have more input ready now */ if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error)) goto doMessage; if (ssl->buffers.inputBuffer.dynamicFlag) ShrinkInputBuffer(ssl, NO_FORCED_FREE); - + return decoded; } /* See if we need to process any pending FIN captures */ -static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, +static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session) { - if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= session->cliExpected) { if (session->finCaputre.cliCounted == 0) { session->flags.finCount += 1; @@ -3425,8 +3425,8 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected); } } - - if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= + + if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= session->srvExpected) { if (session->finCaputre.srvCounted == 0) { session->flags.finCount += 1; @@ -3434,13 +3434,13 @@ static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected); } } - - if (session->flags.finCount >= 2) + + if (session->flags.finCount >= 2) RemoveSession(session, ipInfo, tcpInfo, 0); } -/* If session is in fatal error state free resources now +/* If session is in fatal error state free resources now return true if removed, 0 otherwise */ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, SnifferSession* session, char* error) @@ -3469,17 +3469,17 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) return -1; - + ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) return 0; /* done for now */ - + ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, &end, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; @@ -3533,7 +3533,7 @@ int ssl_Trace(const char* traceFile, char* error) } TraceOn = 1; } - else + else TraceOn = 0; return 0; diff --git a/src/ssl.c b/src/ssl.c old mode 100644 new mode 100755 index d02cced24..b8b80b6ce --- a/src/ssl.c +++ b/src/ssl.c @@ -93,45 +93,6 @@ #include #endif -#ifndef NO_FILESYSTEM - #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR) \ - && !defined(EBSNET) - #include - #include - #endif - #ifdef EBSNET - #include "vfapi.h" - #include "vfile.h" - #endif -#endif /* NO_FILESYSTEM */ - -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSSL_HAVE_MIN */ - -#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_HAVE_MAX) -#define WOLFSSL_HAVE_MAX - - static INLINE word32 max(word32 a, word32 b) - { - return a > b ? a : b; - } - -#endif /* WOLFSSL_DTLS && !WOLFSSL_HAVE_MAX */ - #ifndef WOLFSSL_LEANPSK char* mystrnstr(const char* s1, const char* s2, unsigned int n) @@ -372,7 +333,7 @@ int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) } #ifndef HAVE_FIPS - ret = wc_InitRng_ex(rng, ctx->heap); + ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId); #else ret = wc_InitRng(rng); #endif @@ -400,7 +361,7 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL); if (ssl) - if ( (ret = InitSSL(ssl, ctx)) < 0) { + if ( (ret = InitSSL(ssl, ctx, 0)) < 0) { FreeSSL(ssl, ctx->heap); ssl = 0; } @@ -418,6 +379,167 @@ void wolfSSL_free(WOLFSSL* ssl) WOLFSSL_LEAVE("SSL_free", 0); } + +#ifdef HAVE_WRITE_DUP + +/* + * Release resources around WriteDup object + * + * ssl WOLFSSL object + * + * no return, destruction so make best attempt +*/ +void FreeWriteDup(WOLFSSL* ssl) +{ + int doFree = 0; + + WOLFSSL_ENTER("FreeWriteDup"); + + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) { + ssl->dupWrite->dupCount--; + if (ssl->dupWrite->dupCount == 0) { + doFree = 1; + } else { + WOLFSSL_MSG("WriteDup count not zero, no full free"); + } + wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + } + + if (doFree) { + WOLFSSL_MSG("Doing WriteDup full free, count to zero"); + wc_FreeMutex(&ssl->dupWrite->dupMutex); + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + } +} + + +/* + * duplicate existing ssl members into dup needed for writing + * + * dup write only WOLFSSL + * ssl exisiting WOLFSSL + * + * 0 on success +*/ +static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl) +{ + /* shared dupWrite setup */ + ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap, + DYNAMIC_TYPE_WRITEDUP); + if (ssl->dupWrite == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup)); + + if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) { + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + ssl->dupWrite = NULL; + return BAD_MUTEX_E; + } + ssl->dupWrite->dupCount = 2; /* both sides have a count to start */ + dup->dupWrite = ssl->dupWrite ; /* each side uses */ + + /* copy write parts over to dup writer */ + XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs)); + XMEMCPY(&dup->options, &ssl->options, sizeof(Options)); + XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys)); + XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers)); + /* dup side now owns encrypt/write ciphers */ + XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers)); + + dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx; + dup->wfd = ssl->wfd; + dup->wflags = ssl->wflags; + dup->hmac = ssl->hmac; +#ifdef HAVE_TRUNCATED_HMAC + dup->truncated_hmac = ssl->truncated_hmac; +#endif + + /* unique side dup setup */ + dup->dupSide = WRITE_DUP_SIDE; + ssl->dupSide = READ_DUP_SIDE; + + return 0; +} + + +/* + * duplicate a WOLFSSL object post handshake for writing only + * turn exisitng object into read only. Allows concurrent access from two + * different threads. + * + * ssl exisiting WOLFSSL object + * + * return dup'd WOLFSSL object on success +*/ +WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl) +{ + WOLFSSL* dup = NULL; + int ret = 0; + + (void)ret; + WOLFSSL_ENTER("wolfSSL_write_dup"); + + if (ssl == NULL) { + return ssl; + } + + if (ssl->options.handShakeDone == 0) { + WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete"); + return NULL; + } + + if (ssl->dupWrite) { + WOLFSSL_MSG("wolfSSL_write_dup already called once"); + return NULL; + } + + dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL); + if (dup) { + if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } else if ( (ret = DupSSL(dup, ssl) < 0)) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } + } + + WOLFSSL_LEAVE("wolfSSL_write_dup", ret); + + return dup; +} + + +/* + * Notify write dup side of fatal error or close notify + * + * ssl WOLFSSL object + * err Notify err + * + * 0 on success +*/ +int NotifyWriteSide(WOLFSSL* ssl, int err) +{ + int ret; + + WOLFSSL_ENTER("NotifyWriteSide"); + + ret = wc_LockMutex(&ssl->dupWrite->dupMutex); + if (ret == 0) { + ssl->dupWrite->dupErr = err; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + return ret; +} + + +#endif /* HAVE_WRITE_DUP */ + + #ifdef HAVE_POLY1305 /* set if to use old poly 1 for yes 0 to use new poly */ int wolfSSL_use_old_poly(WOLFSSL* ssl, int value) @@ -438,6 +560,10 @@ int wolfSSL_set_fd(WOLFSSL* ssl, int fd) WOLFSSL_ENTER("SSL_set_fd"); + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + ret = wolfSSL_set_read_fd(ssl, fd); if (ret == SSL_SUCCESS) { ret = wolfSSL_set_write_fd(ssl, fd); @@ -541,6 +667,19 @@ int wolfSSL_get_ciphers(char* buf, int len) return SSL_SUCCESS; } +const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) +{ + const char* cipher; + + if (ssl == NULL) + return NULL; + + cipher = wolfSSL_get_cipher_name_from_suite(ssl->options.cipherSuite, + ssl->options.cipherSuite0); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} int wolfSSL_get_fd(const WOLFSSL* ssl) { @@ -713,38 +852,38 @@ int wolfSSL_GetObjectSize(void) printf("sizeof suites = %lu\n", sizeof(Suites)); printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers)); #ifndef NO_RC4 - printf(" sizeof arc4 = %lu\n", sizeof(Arc4)); + printf("\tsizeof arc4 = %lu\n", sizeof(Arc4)); #endif - printf(" sizeof aes = %lu\n", sizeof(Aes)); + printf("\tsizeof aes = %lu\n", sizeof(Aes)); #ifndef NO_DES3 - printf(" sizeof des3 = %lu\n", sizeof(Des3)); + printf("\tsizeof des3 = %lu\n", sizeof(Des3)); #endif #ifndef NO_RABBIT - printf(" sizeof rabbit = %lu\n", sizeof(Rabbit)); + printf("\tsizeof rabbit = %lu\n", sizeof(Rabbit)); #endif #ifdef HAVE_CHACHA - printf(" sizeof chacha = %lu\n", sizeof(ChaCha)); + printf("\tsizeof chacha = %lu\n", sizeof(ChaCha)); #endif printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs)); printf("sizeof keys = %lu\n", sizeof(Keys)); printf("sizeof Hashes(2) = %lu\n", sizeof(Hashes)); #ifndef NO_MD5 - printf(" sizeof MD5 = %lu\n", sizeof(Md5)); + printf("\tsizeof MD5 = %lu\n", sizeof(Md5)); #endif #ifndef NO_SHA - printf(" sizeof SHA = %lu\n", sizeof(Sha)); + printf("\tsizeof SHA = %lu\n", sizeof(Sha)); #endif #ifdef WOLFSSL_SHA224 printf(" sizeof SHA224 = %lu\n", sizeof(Sha224)); #endif #ifndef NO_SHA256 - printf(" sizeof SHA256 = %lu\n", sizeof(Sha256)); + printf("\tsizeof SHA256 = %lu\n", sizeof(Sha256)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA384 = %lu\n", sizeof(Sha384)); + printf("\tsizeof SHA384 = %lu\n", sizeof(Sha384)); #endif #ifdef WOLFSSL_SHA384 - printf(" sizeof SHA512 = %lu\n", sizeof(Sha512)); + printf("\tsizeof SHA512 = %lu\n", sizeof(Sha512)); #endif printf("sizeof Buffers = %lu\n", sizeof(Buffers)); printf("sizeof Options = %lu\n", sizeof(Options)); @@ -930,7 +1069,7 @@ int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) if (inSz > maxSize) return INPUT_SIZE_E; - return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1); + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); } @@ -1004,21 +1143,26 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, if (ssl->options.side != WOLFSSL_SERVER_END) return SIDE_ERROR; - if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); - if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) - XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH); + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_P.buffer = NULL; + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_G.buffer = NULL; + } ssl->buffers.weOwnDH = 1; /* SSL owns now */ ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_P.buffer == NULL) return MEMORY_E; ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, - DYNAMIC_TYPE_DH); + DYNAMIC_TYPE_DH_BUFFER); if (ssl->buffers.serverDH_G.buffer == NULL) { - XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + ssl->buffers.serverDH_P.buffer = NULL; return MEMORY_E; } @@ -1054,16 +1198,16 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, if (pSz < ctx->minDhKeySz) return DH_KEY_SIZE_E; - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); - ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if (ctx->serverDH_P.buffer == NULL) return MEMORY_E; - ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if (ctx->serverDH_G.buffer == NULL) { - XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); return MEMORY_E; } @@ -1120,6 +1264,36 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef HAVE_WRITE_DUP + { /* local variable scope */ + int dupErr = 0; /* local copy */ + + ret = 0; + + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + WOLFSSL_MSG("Read dup side cannot write"); + return WRITE_DUP_WRITE_E; + } + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { + return BAD_MUTEX_E; + } + dupErr = ssl->dupWrite->dupErr; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + if (ret != 0) { + ssl->error = ret; /* high priority fatal error */ + return SSL_FATAL_ERROR; + } + if (dupErr != 0) { + WOLFSSL_MSG("Write dup error from other side"); + ssl->error = dupErr; + return SSL_FATAL_ERROR; + } + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1144,6 +1318,13 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { + WOLFSSL_MSG("Write dup side cannot read"); + return WRITE_DUP_READ_E; + } +#endif + #ifdef HAVE_ERRNO_H errno = 0; #endif @@ -1164,6 +1345,21 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) #endif ret = ReceiveData(ssl, (byte*)data, sz, peek); +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + if (ssl->error != 0 && ssl->error != WANT_READ && + ssl->error != WC_PENDING_E) { + int notifyErr; + + WOLFSSL_MSG("Notifying write side of fatal read error"); + notifyErr = NotifyWriteSide(ssl, ssl->error); + if (notifyErr < 0) { + ret = ssl->error = notifyErr; + } + } + } +#endif + WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); if (ret < 0) @@ -1338,7 +1534,7 @@ int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1349,7 +1545,7 @@ int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ @@ -1362,7 +1558,7 @@ int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, - options, ssl->heap); + options, ssl->heap, ssl->devId); } @@ -1373,7 +1569,7 @@ int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, return BAD_FUNC_ARG; return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, - options, ctx->heap); + options, ctx->heap, ctx->devId); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ @@ -1404,10 +1600,23 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) case WOLFSSL_ECC_BRAINPOOLP512R1: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + if (!IsAtLeastTLSv1_3(ssl->version)) + return SSL_SUCCESS; + break; +#endif + default: return BAD_FUNC_ARG; } + ssl->options.userCurves = 1; + return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); } @@ -1434,10 +1643,21 @@ int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) case WOLFSSL_ECC_BRAINPOOLP512R1: break; +#ifdef WOLFSSL_TLS13 + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + break; +#endif + default: return BAD_FUNC_ARG; } + ctx->userCurves = 1; + return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap); } @@ -1496,7 +1716,6 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_QSH */ - /* Application-Layer Protocol Negotiation */ #ifdef HAVE_ALPN @@ -1669,31 +1888,9 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl) ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; -#ifndef NO_OLD_TLS -#ifndef NO_MD5 - wc_InitMd5(&ssl->hsHashes->hashMd5); -#endif -#ifndef NO_SHA - ret = wc_InitSha(&ssl->hsHashes->hashSha); + ret = InitHandshakeHashes(ssl); if (ret !=0) return ret; -#endif -#endif /* NO_OLD_TLS */ -#ifndef NO_SHA256 - ret = wc_InitSha256(&ssl->hsHashes->hashSha256); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA384 - ret = wc_InitSha384(&ssl->hsHashes->hashSha384); - if (ret !=0) - return ret; -#endif -#ifdef WOLFSSL_SHA512 - ret = wc_InitSha512(&ssl->hsHashes->hashSha512); - if (ret !=0) - return ret; -#endif ret = wolfSSL_negotiate(ssl); return ret; @@ -1772,7 +1969,8 @@ WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, return SSL_SUCCESS; } -WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, + word32 bufSz) { if (ssl == NULL || (buf == NULL && bufSz > 0)) return BAD_FUNC_ARG; @@ -1790,7 +1988,7 @@ WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, byte* buf, word32 bufSz) if(ssl->session.isDynamic) XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - ssl->session.ticket = XMALLOC(bufSz, ssl->heap, + ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if(!ssl->session.ticket) { ssl->session.ticket = ssl->session.staticTicket; @@ -1909,38 +2107,49 @@ int wolfSSL_shutdown(WOLFSSL* ssl) if (ssl->options.quietShutdown) { WOLFSSL_MSG("quiet shutdown, no close notify sent"); - return SSL_SUCCESS; + ret = SSL_SUCCESS; } - - /* try to send close notify, not an error if can't */ - if (!ssl->options.isClosed && !ssl->options.connReset && - !ssl->options.sentNotify) { - ssl->error = SendAlert(ssl, alert_warning, close_notify); - if (ssl->error < 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + else { + /* try to send close notify, not an error if can't */ + if (!ssl->options.isClosed && !ssl->options.connReset && + !ssl->options.sentNotify) { + ssl->error = SendAlert(ssl, alert_warning, close_notify); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) + ret = SSL_SUCCESS; + else { + ret = SSL_SHUTDOWN_NOT_DONE; + WOLFSSL_LEAVE("SSL_shutdown()", ret); + return ret; + } } - ssl->options.sentNotify = 1; /* don't send close_notify twice */ - if (ssl->options.closeNotify) - ret = SSL_SUCCESS; - else - ret = SSL_SHUTDOWN_NOT_DONE; - WOLFSSL_LEAVE("SSL_shutdown()", ret); - return ret; + /* call wolfSSL_shutdown again for bidirectional shutdown */ + if (ssl->options.sentNotify && !ssl->options.closeNotify) { + ret = wolfSSL_read(ssl, &tmp, 0); + if (ret < 0) { + WOLFSSL_ERROR(ssl->error); + ret = SSL_FATAL_ERROR; + } else if (ssl->options.closeNotify) { + ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ + ret = SSL_SUCCESS; + } + } } - /* call wolfSSL_shutdown again for bidirectional shutdown */ - if (ssl->options.sentNotify && !ssl->options.closeNotify) { - ret = wolfSSL_read(ssl, &tmp, 0); - if (ret < 0) { - WOLFSSL_ERROR(ssl->error); +#ifdef OPENSSL_EXTRA + /* reset WOLFSSL structure state for possible re-use */ + if (ret == SSL_SUCCESS) { + if (wolfSSL_clear(ssl) != SSL_SUCCESS) { + WOLFSSL_MSG("could not clear WOLFSSL"); ret = SSL_FATAL_ERROR; - } else if (ssl->options.closeNotify) { - ssl->error = SSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ - ret = SSL_SUCCESS; } } +#endif WOLFSSL_LEAVE("SSL_shutdown()", ret); @@ -1948,6 +2157,17 @@ int wolfSSL_shutdown(WOLFSSL* ssl) } +/* get current error state value */ +int wolfSSL_state(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + return ssl->error; +} + + int wolfSSL_get_error(WOLFSSL* ssl, int ret) { WOLFSSL_ENTER("SSL_get_error"); @@ -2051,6 +2271,66 @@ void wolfSSL_FreeArrays(WOLFSSL* ssl) } } +/* Set option to indicate that the resources are not to be freed after + * handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.keepResources = 1; + + return 0; +} + +/* Free the handshake resources after handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + FreeHandshakeResources(ssl); + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS context object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->useClientOrder = 1; + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_UseClientSuites(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.useClientOrder = 1; + + return 0; +} const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) { @@ -2148,7 +2428,6 @@ const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl) return NULL; } - int wolfSSL_GetKeySize(WOLFSSL* ssl) { if (ssl) @@ -2243,7 +2522,6 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl) #endif /* ATOMIC_USER */ #ifndef NO_CERTS - int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) { int ret = BAD_FUNC_ARG; @@ -2267,6 +2545,7 @@ int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) if (*pDer == NULL) { return MEMORY_ERROR; } + XMEMSET(*pDer, 0, sizeof(DerBuffer) + length); der = *pDer; der->type = type; @@ -2355,8 +2634,10 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) #ifdef HAVE_OCSP if (cm->ocsp) FreeOCSP(cm->ocsp, 1); + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ - || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(WOLFSSL_HAPROXY) if (cm->ocsp_stapling) FreeOCSP(cm->ocsp_stapling, 1); #endif @@ -2480,31 +2761,147 @@ int wolfSSL_CertPemToDer(const unsigned char* pem, int pemSz, #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +static struct cipher{ + unsigned char type; + const char *name; +} cipher_tbl[] = { + #ifndef NO_AES -static const char *EVP_AES_128_CBC = "AES-128-CBC"; -static const char *EVP_AES_192_CBC = "AES-192-CBC"; -static const char *EVP_AES_256_CBC = "AES-256-CBC"; + {AES_128_CBC_TYPE, "AES-128-CBC"}, + {AES_192_CBC_TYPE, "AES-192-CBC"}, + {AES_256_CBC_TYPE, "AES-256-CBC"}, #if defined(OPENSSL_EXTRA) - static const char *EVP_AES_128_CTR = "AES-128-CTR"; - static const char *EVP_AES_192_CTR = "AES-192-CTR"; - static const char *EVP_AES_256_CTR = "AES-256-CTR"; + {AES_128_CTR_TYPE, "AES-128-CTR"}, + {AES_192_CTR_TYPE, "AES-192-CTR"}, + {AES_256_CTR_TYPE, "AES-256-CTR"}, + + {AES_128_ECB_TYPE, "AES-128-ECB"}, + {AES_192_ECB_TYPE, "AES-192-ECB"}, + {AES_256_ECB_TYPE, "AES-256-ECB"}, +#endif + +#endif + +#ifndef NO_DES3 + {DES_CBC_TYPE, "DES-CBC"}, + {DES_ECB_TYPE, "DES-ECB"}, + + {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC"}, + {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB"}, +#endif + +#ifdef HAVE_IDEA + {IDEA_CBC_TYPE, "IDEA-CBC"}, +#endif + { 0, NULL} +} ; + +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) +{ + + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"DES-CBC", "DES"}, + {"DES-CBC", "des"}, + {"DES-EDE3-CBC", "DES3"}, + {"DES-EDE3-CBC", "des3"}, + {"DES-EDE3-ECB", "des-ede3-ecb"}, + {"IDEA-CBC", "IDEA"}, + {"IDEA-CBC", "idea"}, + {"AES-128-CBC", "AES128"}, + {"AES-128-CBC", "aes128"}, + {"AES-192-CBC", "AES192"}, + {"AES-192-CBC", "aes192"}, + {"AES-256-CBC", "AES256"}, + {"AES-256-CBC", "aes256"}, + { NULL, NULL} + }; + + const struct cipher *ent ; + const struct alias *al ; + + WOLFSSL_ENTER("EVP_get_cipherbyname"); + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = cipher_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (WOLFSSL_EVP_CIPHER *)ent->name; + } + + return NULL; +} + + +#ifndef NO_AES +static char *EVP_AES_128_CBC; +static char *EVP_AES_192_CBC; +static char *EVP_AES_256_CBC; +#if defined(OPENSSL_EXTRA) + static char *EVP_AES_128_CTR; + static char *EVP_AES_192_CTR; + static char *EVP_AES_256_CTR; + + static char *EVP_AES_128_ECB; + static char *EVP_AES_192_ECB; + static char *EVP_AES_256_ECB; #endif static const int EVP_AES_SIZE = 11; #endif #ifndef NO_DES3 -static const char *EVP_DES_CBC = "DES-CBC"; +static char *EVP_DES_CBC; +static char *EVP_DES_ECB; static const int EVP_DES_SIZE = 7; -static const char *EVP_DES_EDE3_CBC = "DES-EDE3-CBC"; +static char *EVP_DES_EDE3_CBC; +static char *EVP_DES_EDE3_ECB; static const int EVP_DES_EDE3_SIZE = 12; #endif #ifdef HAVE_IDEA -static const char *EVP_IDEA_CBC = "IDEA-CBC"; +static char *EVP_IDEA_CBC; static const int EVP_IDEA_SIZE = 8; #endif +void wolfSSL_EVP_init(void) +{ +#ifndef NO_AES + EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC"); + EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC"); + EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC"); + +#if defined(OPENSSL_EXTRA) + EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR"); + EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR"); + EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR"); + + EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB"); + EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB"); + EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB"); +#endif +#endif + +#ifndef NO_DES3 + EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC"); + EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB"); + + EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC"); + EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB"); +#endif + +#ifdef HAVE_IDEA + EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC"); +#endif +} + /* our KeyPemToDer password callback, password in userData */ static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) { @@ -2611,6 +3008,12 @@ void wolfSSL_ERR_print_errors_fp(FILE* fp, int err) fprintf(fp, "%s", data); } +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +void wolfSSL_ERR_dump_errors_fp(FILE* fp) +{ + wc_ERR_print_errors_fp(fp); +} +#endif #endif @@ -2814,20 +3217,29 @@ int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) { Signer* signers; int ret = 0; - word32 row = HashSigner(hash); + word32 row; - if (wc_LockMutex(&cm->caLock) != 0) - return ret; + if (cm == NULL || hash == NULL) { + return ret; + } + + row = HashSigner(hash); + + if (wc_LockMutex(&cm->caLock) != 0) { + return ret; + } signers = cm->caTable[row]; while (signers) { byte* subjectHash; - #ifndef NO_SKID - subjectHash = signers->subjectKeyIdHash; - #else - subjectHash = signers->subjectNameHash; - #endif + + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { - ret = 1; + ret = 1; /* success */ break; } signers = signers->next; @@ -3032,7 +3444,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } - WOLFSSL_MSG(" Parsed new trusted peer cert"); + WOLFSSL_MSG("\tParsed new trusted peer cert"); peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap, DYNAMIC_TYPE_CERT); @@ -3062,7 +3474,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) #endif if (AlreadyTrustedPeer(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else { @@ -3117,7 +3529,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) wc_UnLockMutex(&cm->tpLock); } else { - WOLFSSL_MSG(" Trusted Peer Cert Mutex Lock failed"); + WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed"); FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); FreeTrustedPeer(peerCert, cm->heap); @@ -3125,12 +3537,12 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) } } - WOLFSSL_MSG(" Freeing parsed trusted peer cert"); + WOLFSSL_MSG("\tFreeing parsed trusted peer cert"); FreeDecodedCert(cert); XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG(" Freeing der trusted peer cert"); + WOLFSSL_MSG("\tFreeing der trusted peer cert"); FreeDer(&der); - WOLFSSL_MSG(" OK Freeing der trusted peer cert"); + WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert"); WOLFSSL_LEAVE("AddTrustedPeer", ret); return SSL_SUCCESS; @@ -3165,7 +3577,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) InitDecodedCert(cert, der->buffer, der->length, cm->heap); ret = ParseCert(cert, CA_TYPE, verify, cm); - WOLFSSL_MSG(" Parsed new CA"); + WOLFSSL_MSG("\tParsed new CA"); #ifndef NO_SKID subjectHash = cert->extSubjKeyId; @@ -3181,7 +3593,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minRsaKeySz < 0 || cert->pubKeySize < (word16)cm->minRsaKeySz) { ret = RSA_KEY_SIZE_E; - WOLFSSL_MSG(" CA RSA key size error"); + WOLFSSL_MSG("\tCA RSA key size error"); } break; #endif /* !NO_RSA */ @@ -3190,19 +3602,19 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) if (cm->minEccKeySz < 0 || cert->pubKeySize < (word16)cm->minEccKeySz) { ret = ECC_KEY_SIZE_E; - WOLFSSL_MSG(" CA ECC key size error"); + WOLFSSL_MSG("\tCA ECC key size error"); } break; #endif /* HAVE_ECC */ default: - WOLFSSL_MSG(" No key size check done on CA"); + WOLFSSL_MSG("\tNo key size check done on CA"); break; /* no size check if key type is not in switch */ } } if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { - WOLFSSL_MSG(" Can't add as CA if not actually one"); + WOLFSSL_MSG("\tCan't add as CA if not actually one"); ret = NOT_CA_ERROR; } #ifndef ALLOW_INVALID_CERTSIGN @@ -3210,12 +3622,12 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { /* Intermediate CA certs are required to have the keyCertSign * extension set. User loaded root certs are not. */ - WOLFSSL_MSG(" Doesn't have key usage certificate signing"); + WOLFSSL_MSG("\tDoesn't have key usage certificate signing"); ret = NOT_CA_ERROR; } #endif else if (ret == 0 && AlreadySigner(cm, subjectHash)) { - WOLFSSL_MSG(" Already have this CA, not adding again"); + WOLFSSL_MSG("\tAlready have this CA, not adding again"); (void)ret; } else if (ret == 0) { @@ -3225,10 +3637,14 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) ret = MEMORY_ERROR; else { signer->keyOID = cert->keyOID; - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } signer->pathLength = cert->pathLength; signer->pathLengthSet = cert->pathLengthSet; #ifndef IGNORE_NAME_CONSTRAINTS @@ -3265,21 +3681,21 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) cm->caCacheCallback(der->buffer, (int)der->length, type); } else { - WOLFSSL_MSG(" CA Mutex Lock failed"); + WOLFSSL_MSG("\tCA Mutex Lock failed"); ret = BAD_MUTEX_E; FreeSigner(signer, cm->heap); } } } - WOLFSSL_MSG(" Freeing Parsed CA"); + WOLFSSL_MSG("\tFreeing Parsed CA"); FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - WOLFSSL_MSG(" Freeing der CA"); + WOLFSSL_MSG("\tFreeing der CA"); FreeDer(pDer); - WOLFSSL_MSG(" OK Freeing der CA"); + WOLFSSL_MSG("\t\tOK Freeing der CA"); WOLFSSL_LEAVE("AddCA", ret); @@ -3452,7 +3868,7 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, ret = wc_Des3_CbcDecryptWithKey(der->buffer, der->buffer, der->length, key, info->iv); #endif /* NO_DES3 */ -#if !defined(NO_AES) && defined(HAVE_AES_CBC) +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT) if (XSTRNCMP(info->name, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, key, AES_128_KEY_SIZE, info->iv); @@ -3462,7 +3878,7 @@ static int wolfssl_decrypt_buffer_key(DerBuffer* der, byte* password, else if (XSTRNCMP(info->name, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) ret = wc_AesCbcDecryptWithKey(der->buffer, der->buffer, der->length, key, AES_256_KEY_SIZE, info->iv); -#endif /* !NO_AES && HAVE_AES_CBC */ +#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -3584,6 +4000,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, case CERT_TYPE: header=BEGIN_CERT; footer=END_CERT; break; case CRL_TYPE: header=BEGIN_X509_CRL; footer=END_X509_CRL; break; case DH_PARAM_TYPE: header=BEGIN_DH_PARAM; footer=END_DH_PARAM; break; + case DSA_PARAM_TYPE: header=BEGIN_DSA_PARAM; footer=END_DSA_PARAM; break; case CERTREQ_TYPE: header=BEGIN_CERT_REQ; footer=END_CERT_REQ; break; case DSA_TYPE: header=BEGIN_DSA_PRIV; footer=END_DSA_PRIV; break; case ECC_TYPE: header=BEGIN_EC_PRIV; footer=END_EC_PRIV; break; @@ -3792,6 +4209,9 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, { int ret = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); +#ifdef WOLFSSL_TLS13 + int cnt = 0; +#endif /* we may have a user cert chain, try to consume */ if (type == CERT_TYPE && info->consumed < sz) { @@ -3802,7 +4222,7 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif byte* chainBuffer = staticBuffer; int dynamicBuffer = 0; - word32 bufferSz = FILE_BUFFER_SIZE; + word32 bufferSz = sizeof(staticBuffer); long consumed = info->consumed; word32 idx = 0; int gotOne = 0; @@ -3849,6 +4269,9 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, } if (ret == 0) { gotOne = 1; +#ifdef WOLFSSL_TLS13 + cnt++; +#endif if ((idx + part->length) > bufferSz) { WOLFSSL_MSG(" Cert Chain bigger than buffer"); ret = BUFFER_E; @@ -3892,12 +4315,18 @@ static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, idx); ssl->buffers.weOwnCertChain = 1; } +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = cnt; +#endif } else if (ctx) { FreeDer(&ctx->certChain); ret = AllocDer(&ctx->certChain, idx, type, heap); if (ret == 0) { XMEMCPY(ctx->certChain->buffer, chainBuffer, idx); } +#ifdef WOLFSSL_TLS13 + ctx->certChainCnt = cnt; +#endif } } @@ -3918,7 +4347,9 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, int ret = 0; int eccKey = 0; int rsaKey = 0; + int resetSuites = 0; void* heap = ctx ? ctx->heap : ((ssl) ? ssl->heap : NULL); + int devId = ctx ? ctx->devId : ((ssl) ? ssl->devId : INVALID_DEVID); #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -3945,6 +4376,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return MEMORY_E; #endif + XMEMSET(info, 0, sizeof(EncryptedInfo)); info->set = 0; info->ctx = ctx; info->consumed = 0; @@ -4081,9 +4513,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) { FreeDer(&ctx->certificate); /* Make sure previous is free'd */ #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); if (ctx->ourCert) { - XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } ctx->ourCert = NULL; } #endif @@ -4127,19 +4561,21 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, return MEMORY_E; #endif - ret = wc_InitRsaKey(key, 0); + ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0) { if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length) != 0) { #ifdef HAVE_ECC /* could have DER ECC (or pkcs8 ecc), no easy way to tell */ eccKey = 1; /* so try it out */ + #else + WOLFSSL_MSG("RSA decode failed and ECC not enabled to try"); + ret = SSL_BAD_FILE; #endif - if (!eccKey) - ret = SSL_BAD_FILE; } else { /* check that the size of the RSA key is enough */ int RsaSz = wc_RsaEncryptSize((RsaKey*)key); + if (ssl) { if (RsaSz < ssl->options.minRsaKeySz) { ret = RSA_KEY_SIZE_E; @@ -4154,10 +4590,15 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } rsaKey = 1; (void)rsaKey; /* for no ecc builds */ - } - } - wc_FreeRsaKey(key); + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + resetSuites = 1; + } + } + + wc_FreeRsaKey(key); + } #ifdef WOLFSSL_SMALL_STACK XFREE(key, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -4173,7 +4614,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, word32 idx = 0; ecc_key key; - wc_ecc_init(&key); + ret = wc_ecc_init_ex(&key, heap, devId); + if (ret != 0) { + return ret; + } + if (wc_EccPrivateKeyDecode(der->buffer, &idx, &key, der->length) != 0) { wc_ecc_free(&key); @@ -4198,10 +4643,16 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, wc_ecc_free(&key); eccKey = 1; - if (ctx) - ctx->haveStaticECC = 1; - if (ssl) + if (ssl) { ssl->options.haveStaticECC = 1; + } + else if (ctx) { + ctx->haveStaticECC = 1; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } } #endif /* HAVE_ECC */ } @@ -4224,21 +4675,31 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (DecodeToKey(cert, 0) < 0) { WOLFSSL_MSG("Decode to key failed"); + FreeDecodedCert(cert); #ifdef WOLFSSL_SMALL_STACK XFREE(cert, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return SSL_BAD_FILE; } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + if (ssl && ssl->ctx->haveECDSAsig) { + WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off"); + ssl->options.haveECDSAsig = 0; /* may turn back on next */ + } + switch (cert->signatureOID) { case CTC_SHAwECDSA: case CTC_SHA256wECDSA: case CTC_SHA384wECDSA: case CTC_SHA512wECDSA: WOLFSSL_MSG("ECDSA cert signature"); - if (ctx) - ctx->haveECDSAsig = 1; if (ssl) ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; break; default: WOLFSSL_MSG("Not ECDSA cert signature"); @@ -4246,16 +4707,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #ifdef HAVE_ECC - if (ctx) { - ctx->pkCurveOID = cert->pkCurveOID; - #ifndef WC_STRICT_SIG - if (cert->keyOID == ECDSAk) { - ctx->haveECC = 1; - } - #else - ctx->haveECC = ctx->haveECDSAsig; - #endif - } if (ssl) { ssl->pkCurveOID = cert->pkCurveOID; #ifndef WC_STRICT_SIG @@ -4266,6 +4717,16 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ssl->options.haveECC = ssl->options.haveECDSAsig; #endif } + else if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ctx->haveECC = 1; + } + #else + ctx->haveECC = ctx->haveECDSAsig; + #endif + } #endif /* check key size of cert unless specified not to */ @@ -4322,6 +4783,26 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } + if (ssl && resetSuites) { + word16 havePSK = 0; + word16 haveRSA = 0; + + #ifndef NO_PSK + if (ssl->options.havePSK) { + havePSK = 1; + } + #endif + #ifndef NO_RSA + haveRSA = 1; + #endif + + /* let's reset suites */ + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + return SSL_SUCCESS; } @@ -4341,6 +4822,25 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, &consumed, 0); +#ifdef WOLFSSL_WPAS +#ifdef HAVE_CRL + if (ret < 0) { + DerBuffer* der = NULL; + EncryptedInfo info; + + WOLFSSL_MSG("Trying a CRL"); + if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info, + NULL) == 0) { + WOLFSSL_MSG(" Proccessed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, + der->length,SSL_FILETYPE_ASN1, 0); + FreeDer(&der); + used += info.consumed; + continue; + } + } +#endif +#endif if (ret < 0) { if(consumed > 0) { /* Made progress in file */ @@ -4437,7 +4937,7 @@ int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, } } - return BufferLoadCRL(cm->crl, buff, sz, type); + return BufferLoadCRL(cm->crl, buff, sz, type, 0); } @@ -4491,7 +4991,12 @@ int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) cm->crl = NULL; return SSL_FAILURE; } + + #ifdef HAVE_CRL_IO + cm->crl->crlIOCb = EmbedCrlLookup; + #endif } + cm->crlEnabled = 1; if (options & WOLFSSL_CRL_CHECKALL) cm->crlCheckAll = 1; @@ -4558,9 +5063,10 @@ int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, info, &eccKey); if (ret != 0) { FreeDer(&der); - #ifdef WOLFSSL_SMALL_STACK - XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(info, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } InitDecodedCert(cert, der->buffer, der->length, cm->heap); @@ -4909,12 +5415,12 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); return SSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else { if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) @@ -4922,7 +5428,7 @@ int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); #ifdef HAVE_CRL else if (type == CRL_TYPE) - ret = BufferLoadCRL(crl, myBuffer, sz, format); + ret = BufferLoadCRL(crl, myBuffer, sz, format, 0); #endif else ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, @@ -4944,7 +5450,6 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, int ret = SSL_SUCCESS; WOLFSSL_ENTER("wolfSSL_CTX_load_verify_locations"); - (void)path; if (ctx == NULL || (file == NULL && path == NULL) ) return SSL_FAILURE; @@ -4953,95 +5458,35 @@ int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, ret = ProcessFile(ctx, file, SSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); if (ret == SSL_SUCCESS && path) { +#ifndef NO_WOLFSSL_DIR + char* name = NULL; + #ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx = NULL; + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) + return MEMORY_E; + #else + ReadDirCtx readCtx[1]; + #endif + /* try to load each regular file in path */ - #ifdef USE_WINDOWS_API - WIN32_FIND_DATAA FindFileData; - HANDLE hFind; - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; - #else - char name[MAX_FILENAME_SZ]; - #endif - - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) - return MEMORY_E; - #endif - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ - 4); - XSTRNCAT(name, "\\*", 3); - - hFind = FindFirstFileA(name, &FindFileData); - if (hFind == INVALID_HANDLE_VALUE) { - WOLFSSL_MSG("FindFirstFile for path verify locations failed"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return BAD_PATH_ERROR; + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + if (ret != SSL_SUCCESS) + break; + ret = wc_ReadDirNext(readCtx, path, &name); } - - do { - if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 3); - XSTRNCAT(name, "\\", 2); - XSTRNCAT(name, FindFileData.cFileName, MAX_FILENAME_SZ/2); - - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); - } - } while (ret == SSL_SUCCESS && FindNextFileA(hFind, &FindFileData)); + wc_ReadDirClose(readCtx); #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - FindClose(hFind); - #elif !defined(NO_WOLFSSL_DIR) - struct dirent* entry; - DIR* dir = opendir(path); - #ifdef WOLFSSL_SMALL_STACK - char* name = NULL; - #else - char name[MAX_FILENAME_SZ]; - #endif - - if (dir == NULL) { - WOLFSSL_MSG("opendir path verify locations failed"); - return BAD_PATH_ERROR; - } - - #ifdef WOLFSSL_SMALL_STACK - name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (name == NULL) { - closedir(dir); - return MEMORY_E; - } - #endif - - while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) { - struct stat s; - - XMEMSET(name, 0, MAX_FILENAME_SZ); - XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); - XSTRNCAT(name, "/", 1); - XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); - - if (stat(name, &s) != 0) { - WOLFSSL_MSG("stat on name failed"); - ret = BAD_PATH_ERROR; - } else if (s.st_mode & S_IFREG) - ret = ProcessFile(ctx, name, SSL_FILETYPE_PEM, CA_TYPE, - NULL, 0, NULL); - } - - #ifdef WOLFSSL_SMALL_STACK - XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - closedir(dir); + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif +#else + ret = NOT_COMPILED_IN; +#endif } return ret; @@ -5089,7 +5534,7 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, sz = XFTELL(file); XREWIND(file); - if (sz > MAX_WOLFSSL_FILE_SIZE || sz < 0) { + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { WOLFSSL_MSG("CertManagerVerify file bad size"); XFCLOSE(file); return SSL_BAD_FILE; @@ -5105,7 +5550,7 @@ int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, dynamic = 1; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format); @@ -5220,6 +5665,17 @@ int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb) return SSL_SUCCESS; } +#ifdef HAVE_CRL_IO +int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb) +{ + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crl->crlIOCb = cb; + + return SSL_SUCCESS; +} +#endif int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, int type, int monitor) @@ -5278,6 +5734,16 @@ int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) + return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) { @@ -5319,6 +5785,17 @@ int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) return BAD_FUNC_ARG; } +#ifdef HAVE_CRL_IO +int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif + #endif /* HAVE_CRL */ @@ -5372,7 +5849,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) sz = XFTELL(file); XREWIND(file); - if (sz < 0) { + if (sz <= 0) { ret = SSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { @@ -5388,7 +5865,7 @@ int wolfSSL_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { ret = SSL_BAD_FILE; } else { @@ -5458,7 +5935,7 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, sz = XFTELL(file); XREWIND(file); - if (sz < 0) { + if (sz <= 0) { ret = SSL_BAD_FILE; } else if (sz > (long)sizeof(staticBuffer)) { @@ -5473,7 +5950,7 @@ int wolfSSL_PemPubKeyToDer(const char* fileName, dynamic = 1; } if (ret == 0) { - if ( (ret = (int)XFREAD(fileBuf, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, @@ -5625,12 +6102,12 @@ static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, } dynamic = 1; } - else if (sz < 0) { + else if (sz <= 0) { XFCLOSE(file); return SSL_BAD_FILE; } - if ( (ret = (int)XFREAD(myBuffer, sz, 1, file)) < 0) + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) ret = SSL_BAD_FILE; else { if (ssl) @@ -5668,6 +6145,529 @@ int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) #ifdef OPENSSL_EXTRA /* put SSL type in extra for now, not very common */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) +{ + WOLFSSL_EVP_PKEY* local; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + local = wolfSSL_PKEY_new(); + if (local == NULL) { + return NULL; + } + + local->type = type; + local->pkey_sz = (int)inSz; + local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + } + else { + XMEMCPY(local->pkey.ptr, *in, inSz); + } + + if (out != NULL) { + *out = local; + } + + return local; +} + + +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) +{ + WOLFSSL_STUB("wolfSSL_ctrl"); + (void)ssl; + (void)cmd; + (void)opt; + (void)pt; + return SSL_FAILURE; +} + + +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) +{ + WOLFSSL_STUB("wolfSSL_CTX_ctrl"); + (void)ctx; + (void)cmd; + (void)opt; + (void)pt; + return SSL_FAILURE; +} + +#ifndef NO_CERTS +int wolfSSL_check_private_key(const WOLFSSL* ssl) +{ + DecodedCert der; + word32 size; + byte* buff; + int ret; + + if (ssl == NULL) { + return SSL_FAILURE; + } + + size = ssl->buffers.certificate->length; + buff = ssl->buffers.certificate->buffer; + InitDecodedCert(&der, buff, size, ssl->heap); + if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(&der); + return SSL_FAILURE; + } + + size = ssl->buffers.key->length; + buff = ssl->buffers.key->buffer; + ret = wc_CheckPrivateKey(buff, size, &der); + FreeDecodedCert(&der); + return ret; +} + + +/* Looks for the extension matching the passed in nid + * + * c : if not null then is set to status value -2 if multiple occurances + * of the extension are found, -1 if not found, 0 if found and not + * critical, and 1 if found and critical. + * nid : Extension OID to be found. + * idx : if NULL return first extension found match, otherwise start search at + * idx location and set idx to the location of extension returned. + * returns NULL or a pointer to an WOLFSSL_STACK holding extension structure + * + * NOTE code for decoding extensions is in asn.c DecodeCertExtensions -- + * use already decoded extension in this function to avoid decoding twice. + * Currently we do not make use of idx since getting pre decoded extensions. + */ +void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx) +{ + WOLFSSL_STACK* sk = NULL; + WOLFSSL_ASN1_OBJECT* obj = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i"); + + if (x509 == NULL) { + return NULL; + } + + if (c != NULL) { + *c = -1; /* default to not found */ + } + + sk = (STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + return NULL; + } + XMEMSET(sk, 0, sizeof(STACK_OF(WOLFSSL_ASN1_OBJECT))); + + switch (nid) { + case BASIC_CA_OID: + if (x509->basicConstSet) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (c != NULL) { + *c = x509->basicConstCrit; + } + obj->type = BASIC_CA_OID; + } + else { + WOLFSSL_MSG("No Basic Constraint set"); + } + break; + + case ALT_NAMES_OID: + { + DNS_entry* dns; + + if (x509->subjAltNameSet && x509->altNames != NULL) { + /* alt names are DNS_entry structs */ + if (c != NULL) { + if (x509->altNames->next != NULL) { + *c = -2; /* more then one found */ + } + else { + *c = x509->subjAltNameCrit; + } + } + + dns = x509->altNames; + while (dns != NULL) { + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = ALT_NAMES_OID; + obj->obj = (byte*)dns->name; + dns = dns->next; + /* last dns in list add at end of function */ + if (dns != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != + SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + } + } + else { + WOLFSSL_MSG("No Alt Names set"); + } + } + break; + + case CRL_DIST_OID: + if (x509->CRLdistSet && x509->CRLInfo != NULL) { + if (c != NULL) { + *c = x509->CRLdistCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CRL_DIST_OID; + obj->obj = x509->CRLInfo; + obj->objSz = x509->CRLInfoSz; + } + else { + WOLFSSL_MSG("No CRL dist set"); + } + break; + + case AUTH_INFO_OID: + if (x509->authInfoSet && x509->authInfo != NULL) { + if (c != NULL) { + *c = x509->authInfoCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = AUTH_INFO_OID; + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + } + else { + WOLFSSL_MSG("No Auth Info set"); + } + break; + + case AUTH_KEY_OID: + if (x509->authKeyIdSet) { + if (c != NULL) { + *c = x509->authKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = AUTH_KEY_OID; + obj->obj = x509->authKeyId; + obj->objSz = x509->authKeyIdSz; + } + else { + WOLFSSL_MSG("No Auth Key set"); + } + break; + + case SUBJ_KEY_OID: + if (x509->subjKeyIdSet) { + if (c != NULL) { + *c = x509->subjKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = SUBJ_KEY_OID; + obj->obj = x509->subjKeyId; + obj->objSz = x509->subjKeyIdSz; + } + else { + WOLFSSL_MSG("No Subject Key set"); + } + break; + + case CERT_POLICY_OID: + #ifdef WOLFSSL_CERT_EXT + { + int i; + + if (x509->certPoliciesNb > 0) { + if (c != NULL) { + if (x509->certPoliciesNb > 1) { + *c = -2; + } + else { + *c = 0; + } + } + + for (i = 0; i < x509->certPoliciesNb - 1; i++) { + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) + != SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + } + #else + #ifdef WOLFSSL_SEP + if (x509->certPolicySet) { + if (c != NULL) { + *c = x509->certPolicyCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = CERT_POLICY_OID; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + #else + WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT"); + #endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_CERT_EXT */ + break; + + case KEY_USAGE_OID: + if (x509->keyUsageSet) { + if (c != NULL) { + *c = x509->keyUsageCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = KEY_USAGE_OID; + obj->obj = (byte*)&(x509->keyUsage); + obj->objSz = sizeof(word16); + } + else { + WOLFSSL_MSG("No Key Usage set"); + } + break; + + case INHIBIT_ANY_OID: + WOLFSSL_MSG("INHIBIT ANY extension not supported"); + break; + + case EXT_KEY_USAGE_OID: + if (x509->extKeyUsageSrc != NULL) { + if (c != NULL) { + if (x509->extKeyUsageCount > 1) { + *c = -2; + } + else { + *c = x509->extKeyUsageCrit; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + obj->type = EXT_KEY_USAGE_OID; + obj->obj = x509->extKeyUsageSrc; + obj->objSz = x509->extKeyUsageSz; + } + else { + WOLFSSL_MSG("No Extended Key Usage set"); + } + break; + + case NAME_CONS_OID: + WOLFSSL_MSG("Name Constraint OID extension not supported"); + break; + + case PRIV_KEY_USAGE_PERIOD_OID: + WOLFSSL_MSG("Private Key Usage Period extension not supported"); + break; + + case SUBJECT_INFO_ACCESS: + WOLFSSL_MSG("Subject Info Access extension not supported"); + break; + + case POLICY_MAP_OID: + WOLFSSL_MSG("Policy Map extension not supported"); + break; + + case POLICY_CONST_OID: + WOLFSSL_MSG("Policy Constraint extension not supported"); + break; + + case ISSUE_ALT_NAMES_OID: + WOLFSSL_MSG("Issue Alt Names extension not supported"); + break; + + case TLS_FEATURE_OID: + WOLFSSL_MSG("TLS Feature extension not supported"); + break; + + default: + WOLFSSL_MSG("Unsupported/Unknown extension OID"); + } + + if (obj != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != SSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + else { /* no ASN1 object found for extension, free stack */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + + (void)idx; + + return sk; +} + + +/* this function makes the assumption that out buffer is big enough for digest*/ +static int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng) +{ + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int hashSz; + + if (XSTRLEN(evp) < 3) { + /* do not try comparing strings if size is too small */ + return SSL_FAILURE; + } + + if (XSTRNCMP("SHA", evp, 3) == 0) { + if (XSTRLEN(evp) > 3) { + if (XSTRNCMP("SHA256", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA256; + } + else if (XSTRNCMP("SHA384", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA384; + } + else if (XSTRNCMP("SHA512", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA512; + } + else { + WOLFSSL_MSG("Unknown SHA hash"); + } + } + else { + hash = WC_HASH_TYPE_SHA; + } + } + else if (XSTRNCMP("MD2", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD2; + } + else if (XSTRNCMP("MD4", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD4; + } + else if (XSTRNCMP("MD5", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD5; + } + + hashSz = wc_HashGetDigestSize(hash); + if (hashSz < 0) { + WOLFSSL_LEAVE("wolfSSL_EVP_Digest", hashSz); + return SSL_FAILURE; + } + *outSz = hashSz; + + (void)eng; + if (wc_Hash(hash, in, inSz, out, *outSz) == 0) { + return SSL_SUCCESS; + } + else { + return SSL_FAILURE; + } +} + + +int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, + unsigned char* buf, unsigned int* len) +{ + WOLFSSL_ENTER("wolfSSL_X509_digest"); + + if (x509 == NULL || digest == NULL) { + return SSL_FAILURE; + } + + return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf, + len, digest, NULL); +} + + +int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); + if (ssl == NULL || pkey == NULL ) { + return SSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, SSL_FILETYPE_ASN1); +} + + +int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der, + long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return SSL_FAILURE; + } + + (void)pri; /* type of private key */ + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); +} + + +#ifndef NO_RSA +int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return SSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, SSL_FILETYPE_ASN1); +} +#endif + +int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); + if (der != NULL && ssl != NULL) { + if (ProcessBuffer(NULL, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, ssl, + &idx, 0) == SSL_SUCCESS) + return SSL_SUCCESS; + } + + (void)idx; + return SSL_FAILURE; +} + + +int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate"); + if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { + if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, + SSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == SSL_SUCCESS) + return SSL_SUCCESS; + } + + (void)idx; + return SSL_FAILURE; +} +#endif /* NO_CERTS */ + + int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) { WOLFSSL_ENTER("wolfSSL_use_certificate_file"); @@ -5702,45 +6702,6 @@ int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) } - -#if !defined(NO_WOLFSSL_CLIENT) -/* Return the amount of random bytes copied over or error case. - * ssl : ssl struct after handshake - * out : buffer to hold random bytes - * outSz : either 0 (return max buffer sz) or size of out buffer - * - * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. - */ -int wolfSSL_get_client_random(WOLFSSL* ssl, unsigned char* out, int outSz) -{ - int size; - - /* return max size of buffer */ - if (outSz == 0) { - return RAN_LEN; - } - - if (ssl == NULL || out == NULL || outSz < 0) { - return BAD_FUNC_ARG; - } - - if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { - WOLFSSL_MSG("Arrays struct not saved after handshake"); - return BAD_FUNC_ARG; - } - - if (outSz > RAN_LEN) { - size = RAN_LEN; - } - else { - size = outSz; - } - - XMEMCPY(out, ssl->arrays->clientRandom, size); - return size; -} -#endif /* !defined(NO_WOLFSSL_CLIENT) */ - #ifdef HAVE_ECC /* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ @@ -5787,6 +6748,47 @@ int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) return wolfSSL_use_PrivateKey_file(ssl, file, format); } + +/* Copies the master secret over to out buffer. If outSz is 0 returns the size + * of master secret. + * + * ses : a session from completed TLS/SSL handshake + * out : buffer to hold copy of master secret + * outSz : size of out buffer + * returns : number of bytes copied into out buffer on success + * less then or equal to 0 is considered a failure case + */ +int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz) +{ + int size; + + if (outSz == 0) { + return SECRET_LEN; + } + + if (ses == NULL || out == NULL || outSz < 0) { + return 0; + } + + if (outSz > SECRET_LEN) { + size = SECRET_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ses->masterSecret, size); + return size; +} + + +int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) +{ + (void)ses; + return SECRET_LEN; +} + #endif /* OPENSSL_EXTRA */ #ifdef HAVE_NTRU @@ -5988,6 +6990,9 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) session = GetSessionClient(ssl, id, len); if (session) { if (SetSession(ssl, session) != SSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif WOLFSSL_MSG("SetSession failed"); session = NULL; } @@ -6000,6 +7005,10 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); } + #ifdef HAVE_EXT_CACHE + else + wolfSSL_SESSION_free(session); + #endif return SSL_SUCCESS; } @@ -6327,9 +7336,14 @@ long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) if (mode == SSL_SESS_CACHE_OFF) ctx->sessionCacheOff = 1; - if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + if ((mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) ctx->sessionCacheFlushOff = 1; +#ifdef HAVE_EXT_CACHE + if ((mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; +#endif + return SSL_SUCCESS; } @@ -6799,14 +7813,14 @@ int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) XMEMSET(ctx->suites, 0, sizeof(Suites)); } - return (SetCipherList(ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ctx, ctx->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; } int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) { WOLFSSL_ENTER("wolfSSL_set_cipher_list"); - return (SetCipherList(ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? SSL_SUCCESS : SSL_FAILURE; } @@ -6879,6 +7893,8 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, const byte* secret, word32 secretSz) { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); if (ssl == NULL) { @@ -6917,18 +7933,35 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } /* If the supplied secret is NULL, randomly generate a new secret. */ - if (secret == NULL) - wc_RNG_GenerateBlock(ssl->rng, + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->buffers.dtlsCookieSecret.buffer, secretSz); + } else XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); - return 0; + return ret; } #endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ +#ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv23_method(void) { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("wolfSSLv23_method"); +#ifndef NO_WOLFSSL_CLIENT + m = wolfSSLv23_client_method(); +#else + m = wolfSSLv23_server_method(); +#endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } +#endif /* OPENSSL_EXTRA */ /* client only parts */ #ifndef NO_WOLFSSL_CLIENT @@ -6994,6 +8027,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_ENTER("DTLSv1_2_client_method_ex"); if (method) InitSSL_Method(method, MakeDTLSv1_2()); + (void)heap; return method; } #endif @@ -7013,6 +8047,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, return result; } + /* please see note at top of README if you get an error from connect */ int wolfSSL_connect(WOLFSSL* ssl) { @@ -7024,6 +8059,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, errno = 0; #endif + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side != WOLFSSL_CLIENT_END) { WOLFSSL_ERROR(ssl->error = SIDE_ERROR); return SSL_FATAL_ERROR; @@ -7068,6 +8106,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.connectState = CLIENT_HELLO_SENT; WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; case CLIENT_HELLO_SENT : neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : @@ -7097,45 +8136,24 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = HELLO_AGAIN; WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; case HELLO_AGAIN : if (ssl->options.certOnly) return SSL_SUCCESS; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); +#endif + #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { /* re-init hashes, exclude first hello and verify request */ -#ifndef NO_OLD_TLS - wc_InitMd5(&ssl->hsHashes->hashMd5); - if ( (ssl->error = wc_InitSha(&ssl->hsHashes->hashSha)) - != 0) { + if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } -#endif - if (IsAtLeastTLSv1_2(ssl)) { - #ifndef NO_SHA256 - if ( (ssl->error = wc_InitSha256( - &ssl->hsHashes->hashSha256)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA384 - if ( (ssl->error = wc_InitSha384( - &ssl->hsHashes->hashSha384)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - #ifdef WOLFSSL_SHA512 - if ( (ssl->error = wc_InitSha512( - &ssl->hsHashes->hashSha512)) != 0) { - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } - #endif - } if ( (ssl->error = SendClientHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; @@ -7145,6 +8163,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = HELLO_AGAIN_REPLY; WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; case HELLO_AGAIN_REPLY : #ifdef WOLFSSL_DTLS @@ -7168,6 +8187,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = FIRST_REPLY_DONE; WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; case FIRST_REPLY_DONE : #ifndef NO_CERTS @@ -7182,6 +8202,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.connectState = FIRST_REPLY_FIRST; WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; case FIRST_REPLY_FIRST : if (!ssl->options.resuming) { @@ -7194,6 +8215,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = FIRST_REPLY_SECOND; WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; case FIRST_REPLY_SECOND : #ifndef NO_CERTS @@ -7207,6 +8229,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.connectState = FIRST_REPLY_THIRD; WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; case FIRST_REPLY_THIRD : if ( (ssl->error = SendChangeCipher(ssl)) != 0) { @@ -7216,6 +8239,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_MSG("sent: change cipher spec"); ssl->options.connectState = FIRST_REPLY_FOURTH; WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; case FIRST_REPLY_FOURTH : if ( (ssl->error = SendFinished(ssl)) != 0) { @@ -7225,6 +8249,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_MSG("sent: finished"); ssl->options.connectState = FINISHED_DONE; WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; case FINISHED_DONE : /* get response */ @@ -7236,6 +8261,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.connectState = SECOND_REPLY_DONE; WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; case SECOND_REPLY_DONE: #ifndef NO_HANDSHAKE_DONE_CB @@ -7250,7 +8276,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -7342,14 +8370,22 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, InitSSL_Method(method, MakeDTLSv1_2()); method->side = WOLFSSL_SERVER_END; } + (void)heap; return method; } #endif + int wolfSSL_accept(WOLFSSL* ssl) { word16 havePSK = 0; word16 haveAnon = 0; + +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); +#endif + WOLFSSL_ENTER("SSL_accept()"); #ifdef HAVE_ERRNO_H @@ -7423,20 +8459,47 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } +#ifdef WOLFSSL_TLS13 ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_FIRST_REPLY_DONE : +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } +#endif if ( (ssl->error = SendServerHello(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } ssl->options.acceptState = SERVER_HELLO_SENT; WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; case SERVER_HELLO_SENT : #ifndef NO_CERTS @@ -7448,6 +8511,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.acceptState = CERT_SENT; WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; case CERT_SENT : #ifndef NO_CERTS @@ -7459,6 +8523,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif ssl->options.acceptState = CERT_STATUS_SENT; WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; case CERT_STATUS_SENT : if (!ssl->options.resuming) @@ -7468,18 +8533,22 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = KEY_EXCHANGE_SENT; WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + FALL_THROUGH; case KEY_EXCHANGE_SENT : #ifndef NO_CERTS - if (!ssl->options.resuming) - if (ssl->options.verifyPeer) + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { WOLFSSL_ERROR(ssl->error); return SSL_FATAL_ERROR; } + } + } #endif ssl->options.acceptState = CERT_REQ_SENT; WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; case CERT_REQ_SENT : if (!ssl->options.resuming) @@ -7489,6 +8558,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = SERVER_HELLO_DONE; WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + FALL_THROUGH; case SERVER_HELLO_DONE : if (!ssl->options.resuming) { @@ -7500,6 +8570,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_SECOND_REPLY_DONE : #ifdef HAVE_SESSION_TICKET @@ -7512,6 +8583,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* HAVE_SESSION_TICKET */ ssl->options.acceptState = TICKET_SENT; WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; case TICKET_SENT: if ( (ssl->error = SendChangeCipher(ssl)) != 0) { @@ -7520,6 +8592,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, } ssl->options.acceptState = CHANGE_CIPHER_SENT; WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + FALL_THROUGH; case CHANGE_CIPHER_SENT : if ( (ssl->error = SendFinished(ssl)) != 0) { @@ -7529,6 +8602,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.acceptState = ACCEPT_FINISHED_DONE; WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; case ACCEPT_FINISHED_DONE : if (ssl->options.resuming) @@ -7540,6 +8614,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; case ACCEPT_THIRD_REPLY_DONE : #ifndef NO_HANDSHAKE_DONE_CB @@ -7554,7 +8629,9 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #endif /* NO_HANDSHAKE_DONE_CB */ if (!ssl->options.dtls) { - FreeHandshakeResources(ssl); + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } } #ifdef WOLFSSL_DTLS else { @@ -7602,7 +8679,6 @@ int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) #endif /* NO_HANDSHAKE_DONE_CB */ - int wolfSSL_Cleanup(void) { int ret = SSL_SUCCESS; @@ -7634,9 +8710,10 @@ int wolfSSL_Cleanup(void) if (wc_FreeMutex(&count_mutex) != 0) ret = BAD_MUTEX_E; -#if defined(HAVE_ECC) && defined(FP_ECC) - wc_ecc_fp_free(); -#endif + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + ret = WC_CLEANUP_E; + } return ret; } @@ -7678,6 +8755,8 @@ int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) if (ssl == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ssl->timeout = to; return SSL_SUCCESS; @@ -7690,6 +8769,8 @@ int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) if (ctx == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ctx->timeout = to; return SSL_SUCCESS; @@ -7709,10 +8790,26 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) WOLFSSL_ENTER("GetSessionClient"); + if (ssl->ctx->sessionCacheOff) + return NULL; + if (ssl->options.side == WOLFSSL_SERVER_END) return NULL; len = min(SERVER_ID_LEN, (word32)len); + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); + if (ret != NULL) + return ret; + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, len, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -7763,6 +8860,32 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* NO_CLIENT_CACHE */ +/* Restore the master secret and session information for certificates. + * + * ssl The SSL/TLS object. + * session The cached session to restore. + * masterSecret The master secret from the cached session. + * restoreSessionCerts Restoring session certificates is required. + */ +static INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; + + if (masterSecret) + XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); +#ifdef SESSION_CERTS + /* If set, we should copy the session certs into the ssl object + * from the session we are returning so we can resume */ + if (restoreSessionCerts) { + ssl->session.chain = session->chain; + ssl->session.version = session->version; + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + } +#endif /* SESSION_CERTS */ +} WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -7792,6 +8915,21 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, else id = ssl->session.sessionID; +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + /* Attempt to retrieve the session from the external cache. */ + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (ret != NULL) { + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + return ret; + } + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -7821,19 +8959,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); ret = current; - if (masterSecret) - XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = ret->chain; - ssl->session.version = ret->version; - ssl->session.cipherSuite0 = ret->cipherSuite0; - ssl->session.cipherSuite = ret->cipherSuite; - } -#endif /* SESSION_CERTS */ - + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); } else { WOLFSSL_MSG("Session timed out"); } @@ -7895,10 +9021,29 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) } #ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13 + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; + copyInto->namedGroup = copyFrom->namedGroup; + copyInto->ticketSeen = copyFrom->ticketSeen; + copyInto->ticketAdd = copyFrom->ticketAdd; + XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN); + + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == SSL_SUCCESS) + ret = BAD_MUTEX_E; + } +#endif /* If doing dynamic copy, need to alloc outside lock, then inside a lock * confirm the size still matches and memcpy */ if (doDynamicCopy) { - tmpBuff = XMALLOC(ticketLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); if (!tmpBuff) return MEMORY_ERROR; @@ -7914,7 +9059,7 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) } if (ret == SSL_SUCCESS) { - copyInto->ticket = tmpBuff; + copyInto->ticket = (byte*)tmpBuff; copyInto->isDynamic = 1; XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen); } @@ -7924,9 +9069,11 @@ static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) copyInto->ticket = copyInto->staticTicket; } - if (wc_UnLockMutex(&session_mutex) != 0) { - if (ret == SSL_SUCCESS) - ret = BAD_MUTEX_E; + if (doDynamicCopy) { + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == SSL_SUCCESS) + ret = BAD_MUTEX_E; + } } if (ret != SSL_SUCCESS) { @@ -7951,7 +9098,8 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) if (ret == SSL_SUCCESS) { ssl->options.resuming = 1; -#ifdef SESSION_CERTS +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) ssl->version = session->version; ssl->options.cipherSuite0 = session->cipherSuite0; ssl->options.cipherSuite = session->cipherSuite; @@ -7971,12 +9119,14 @@ static int get_locked_session_stats(word32* active, word32* total, int AddSession(WOLFSSL* ssl) { - word32 row, idx; + word32 row = 0; + word32 idx = 0; int error = 0; #ifdef HAVE_SESSION_TICKET byte* tmpBuff = NULL; int ticLen = 0; #endif + WOLFSSL_SESSION* session; if (ssl->options.sessionCacheOff) return 0; @@ -7989,44 +9139,70 @@ int AddSession(WOLFSSL* ssl) return 0; #endif - row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return error; - } - #ifdef HAVE_SESSION_TICKET ticLen = ssl->session.ticketLen; /* Alloc Memory here so if Malloc fails can exit outside of lock */ if(ticLen > SESSION_TICKET_LEN) { - tmpBuff = XMALLOC(ticLen, ssl->heap, + tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); if(!tmpBuff) return MEMORY_E; } #endif - if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_EXT_CACHE + if (ssl->options.internalCacheOff) { + /* Create a new session object to be stored. */ + session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (session == NULL) { #ifdef HAVE_SESSION_TICKET - XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); #endif - return BAD_MUTEX_E; + return MEMORY_E; + } + XMEMSET(session, 0, sizeof(WOLFSSL_SESSION)); + session->isAlloced = 1; + } + else +#endif + { + /* Use the session object in the cache for external cache if required. + */ + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % + SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return error; + } + + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + idx = SessionCache[row].nextIdx++; +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + session = &SessionCache[row].Sessions[idx]; } - idx = SessionCache[row].nextIdx++; -#ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; -#endif + if (!ssl->options.tls1_3) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + else + XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; - XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, - ssl->arrays->masterSecret, SECRET_LEN); - SessionCache[row].Sessions[idx].haveEMS = ssl->options.haveEMS; - XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, - ID_LEN); - SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; - - SessionCache[row].Sessions[idx].timeout = ssl->timeout; - SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #ifdef HAVE_SESSION_TICKET /* Check if another thread modified ticket since alloc */ @@ -8036,32 +9212,28 @@ int AddSession(WOLFSSL* ssl) if (error == 0) { /* Cleanup cache row's old Dynamic buff if exists */ - if(SessionCache[row].Sessions[idx].isDynamic) { - XFREE(SessionCache[row].Sessions[idx].ticket, - ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - SessionCache[row].Sessions[idx].ticket = NULL; + if(session->isDynamic) { + XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = NULL; } /* If too large to store in static buffer, use dyn buffer */ if (ticLen > SESSION_TICKET_LEN) { - SessionCache[row].Sessions[idx].ticket = tmpBuff; - SessionCache[row].Sessions[idx].isDynamic = 1; + session->ticket = tmpBuff; + session->isDynamic = 1; } else { - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; } } if (error == 0) { - SessionCache[row].Sessions[idx].ticketLen = ticLen; - XMEMCPY(SessionCache[row].Sessions[idx].ticket, - ssl->session.ticket, ticLen); + session->ticketLen = ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); } else { /* cleanup, reset state */ - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; - SessionCache[row].Sessions[idx].ticketLen = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; if (tmpBuff) { XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); tmpBuff = NULL; @@ -8071,19 +9243,35 @@ int AddSession(WOLFSSL* ssl) #ifdef SESSION_CERTS if (error == 0) { - SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count; - XMEMCPY(SessionCache[row].Sessions[idx].chain.certs, - ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH); - - SessionCache[row].Sessions[idx].version = ssl->version; - SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0; - SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite; + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * MAX_CHAIN_DEPTH); } #endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET) && !defined(NO_PSK)) if (error == 0) { - SessionCache[row].totalCount++; - if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) - SessionCache[row].nextIdx = 0; + session->version = ssl->version; + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; + } +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & !NO_PSK) */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (error == 0) { + session->namedGroup = ssl->session.namedGroup; + session->ticketSeen = ssl->session.ticketSeen; + session->ticketAdd = ssl->session.ticketAdd; + } +#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + } } #ifndef NO_CLIENT_CACHE if (error == 0) { @@ -8092,48 +9280,70 @@ int AddSession(WOLFSSL* ssl) WOLFSSL_MSG("Adding client cache entry"); - SessionCache[row].Sessions[idx].idLen = ssl->session.idLen; - XMEMCPY(SessionCache[row].Sessions[idx].serverID, - ssl->session.serverID, ssl->session.idLen); + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); - clientRow = HashSession(ssl->session.serverID, ssl->session.idLen, - &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - } else { - clientIdx = ClientCache[clientRow].nextIdx++; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + } else { + clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = + ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = + ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } } } else - SessionCache[row].Sessions[idx].idLen = 0; + session->idLen = 0; } #endif /* NO_CLIENT_CACHE */ #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - if (error == 0) { - word32 active = 0; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + word32 active = 0; - error = get_locked_session_stats(&active, NULL, NULL); - if (error == SSL_SUCCESS) { - error = 0; /* back to this function ok */ + error = get_locked_session_stats(&active, NULL, NULL); + if (error == SSL_SUCCESS) { + error = 0; /* back to this function ok */ - if (active > PeakSessions) - PeakSessions = active; + if (active > PeakSessions) + PeakSessions = active; + } } } #endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ - if (wc_UnLockMutex(&session_mutex) != 0) - return BAD_MUTEX_E; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (wc_UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) + ssl->ctx->new_sess_cb(ssl, session); + if (ssl->options.internalCacheOff) + wolfSSL_SESSION_free(session); +#endif return error; } @@ -8713,8 +9923,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hint == 0) ctx->server_hint[0] = 0; else { - XSTRNCPY(ctx->server_hint, hint, MAX_PSK_ID_LEN); - ctx->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint)); + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } return SSL_SUCCESS; } @@ -8730,8 +9940,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (hint == 0) ssl->arrays->server_hint[0] = 0; else { - XSTRNCPY(ssl->arrays->server_hint, hint, MAX_PSK_ID_LEN); - ssl->arrays->server_hint[MAX_PSK_ID_LEN - 1] = '\0'; + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ } return SSL_SUCCESS; } @@ -8872,6 +10083,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) FreeDer(&der); ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, NULL, NULL); +#ifdef WOLFSSL_WPAS + #ifndef NO_DSA + if (ret < 0) { + ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + } + #endif +#endif } if (ret == 0) { @@ -9025,12 +10244,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + /* returns previous set cache size which stays constant */ long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz) { /* cache size fixed at compile time in wolfSSL */ (void)ctx; (void)sz; - return 0; + WOLFSSL_MSG("session cache is set at compile time"); + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif } @@ -9064,15 +10289,71 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, STACK_OF(WOLFSSL_X509_NAME)* names) { - (void)ctx; - (void)names; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list"); + + if (ctx != NULL) + ctx->ca_names = names; } + STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) + { + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; + } STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) { - (void)fname; - return 0; + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "r"); + if (bio == NULL) + return NULL; + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + subjectName = wolfSSL_X509_get_subject_name(cert); + if (subjectName == NULL) + break; + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + break; + + /* Need a persistent copy of the subject name. */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + break; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + /* Clear pointers so freeing certificate doesn't free memory. */ + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* Put node on the front of the list. */ + node->num = (list == NULL) ? 1 : list->num + 1; + node->next = list; + list = node; + + wolfSSL_X509_free(cert); + cert = NULL; + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; } @@ -9121,6 +10402,31 @@ int wolfSSL_set_compression(WOLFSSL* ssl) word16 havePSK = 0; WOLFSSL_ENTER("SSL_set_accept_state"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + ecc_key key; + word32 idx = 0; + + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + wc_ecc_init(&key); + if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, + ssl->buffers.key->length) != 0) { + ssl->options.haveECDSAsig = 0; + ssl->options.haveECC = 0; + ssl->options.haveStaticECC = 0; + } + wc_ecc_free(&key); + } + #endif + + #ifndef NO_DH + if (!ssl->options.haveDH && ssl->ctx->haveDH) { + ssl->buffers.serverDH_P = ssl->ctx->serverDH_P; + ssl->buffers.serverDH_G = ssl->ctx->serverDH_G; + ssl->options.haveDH = 1; + } + #endif + } ssl->options.side = WOLFSSL_SERVER_END; /* reset suites in case user switched */ @@ -9172,11 +10478,20 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) + { + (void)ctx; + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); + + return 0; + } + + long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) { - /* goahead calls with 0, do nothing */ WOLFSSL_ENTER("SSL_CTX_set_options"); - (void)ctx; + ctx->mask |= opt; return opt; } @@ -9216,12 +10531,37 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) + { + if (ctx == NULL) { + return NULL; + } + + return &(ctx->x509_store); + } + + +#ifndef NO_CERTS + void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) + { + if (ctx == NULL || str == NULL) { + return; + } + + /* free cert manager if have one */ + if (ctx->cm != NULL) { + wolfSSL_CertManagerFree(ctx->cm); + } + ctx->cm = str->cm; + ctx->x509_store.cache = str->cache; + } + WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( WOLFSSL_X509_STORE_CTX* ctx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); - if(ctx) + if (ctx) return ctx->current_cert; return NULL; } @@ -9243,6 +10583,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ctx->error_depth; return SSL_FATAL_ERROR; } +#endif WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) @@ -9265,6 +10606,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void) + { + static WOLFSSL_BIO_METHOD bio_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_bio"); + bio_meth.type = BIO_BIO; + + return &bio_meth; + } + + +#ifndef NO_FILESYSTEM + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) + { + static WOLFSSL_BIO_METHOD file_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_file"); + file_meth.type = BIO_FILE; + + return &file_meth; + } +#endif + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) { static WOLFSSL_BIO_METHOD meth; @@ -9276,6 +10641,17 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_s_socket"); + meth.type = BIO_SOCKET; + + return &meth; + } + + WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) { WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, @@ -9283,15 +10659,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("BIO_new_socket"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = BIO_SOCKET; bio->close = (byte)closeF; - bio->eof = 0; - bio->ssl = 0; bio->fd = sfd; - bio->prev = 0; - bio->next = 0; bio->mem = NULL; - bio->memLen = 0; } return bio; } @@ -9309,28 +10681,41 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) { - WOLFSSL_ENTER("BIO_set_ssl"); - b->ssl = ssl; - b->close = (byte)closeF; + WOLFSSL_ENTER("wolfSSL_BIO_set_ssl"); + + if (b != NULL) { + b->ssl = ssl; + b->close = (byte)closeF; /* add to ssl for bio free if SSL_free called before/instead of free_all? */ + } return 0; } + long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_fd"); + + if (b != NULL) { + b->fd = fd; + b->close = (byte)closeF; + } + + return SSL_SUCCESS; + } + + WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) { WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, DYNAMIC_TYPE_OPENSSL); WOLFSSL_ENTER("BIO_new"); if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); bio->type = method->type; - bio->close = 0; - bio->eof = 0; bio->ssl = NULL; bio->mem = NULL; - bio->memLen = 0; - bio->fd = 0; bio->prev = NULL; bio->next = NULL; } @@ -9338,12 +10723,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) { + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); + if (bio == NULL || p == NULL) return SSL_FATAL_ERROR; - *p = bio->mem; + *(byte **)p = bio->mem; return bio->memLen; } @@ -9384,17 +10771,31 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_BIO_free(WOLFSSL_BIO* bio) { /* unchain?, doesn't matter in goahead since from free all */ - WOLFSSL_ENTER("BIO_free"); + WOLFSSL_ENTER("wolfSSL_BIO_free"); if (bio) { + /* remove from pair by setting the paired bios pair to NULL */ + if (bio->pair != NULL) { + bio->pair->pair = NULL; + } + if (bio->close) { if (bio->ssl) wolfSSL_free(bio->ssl); if (bio->fd) CloseSocket(bio->fd); } + + #ifndef NO_FILESYSTEM + if (bio->type == BIO_FILE && bio->close == BIO_CLOSE) { + if (bio->file) { + XFCLOSE(bio->file); + } + } + #endif + if (bio->mem) - XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + XFREE(bio, bio->heap, DYNAMIC_TYPE_OPENSSL); } return 0; } @@ -9412,15 +10813,46 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) + { + int sz; + char* pt; + + sz = wolfSSL_BIO_nread(bio, &pt, len); + + if (sz > 0) { + XMEMCPY(buf, pt, sz); + } + + return sz; + } + + int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) { int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; - WOLFSSL_ENTER("BIO_read"); + WOLFSSL_ENTER("wolfSSL_BIO_read"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_read(bio, buf, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == BIO_FILE) { + return (int)XFREAD(buf, 1, len, bio->file); + } + #endif + if (bio && bio->type == BIO_MEMORY) { + len = min(len, bio->memLen); + XMEMCPY(buf, bio->mem, len); + return len; + } + /* already got eof, again is error */ - if (front->eof) + if (bio && front->eof) return SSL_FATAL_ERROR; while(bio && ((ssl = bio->ssl) == 0) ) @@ -9440,15 +10872,74 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, + int len) + { + /* internal function where arguments have already been sanity checked */ + int sz; + char* buf; + + sz = wolfSSL_BIO_nwrite(bio, &buf, len); + + /* test space for write */ + if (sz <= 0) { + WOLFSSL_MSG("No room left to write"); + return sz; + } + + XMEMCPY(buf, data, sz); + + return sz; + } + + int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) { int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; + byte* p; + + WOLFSSL_ENTER("wolfSSL_BIO_write"); + + if (bio && bio->type == BIO_BIO) { + return wolfSSL_BIO_BIO_write(bio, data, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == BIO_FILE) { + return (int)XFWRITE(data, 1, len, bio->file); + } + #endif + + if (bio && bio->type == BIO_MEMORY) { + /* Make buffer big enough to hold new data. */ + if (bio->mem == NULL) { + bio->mem = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) + return -1; + p = bio->mem; + } + else { + p = (byte*)XMALLOC(len + bio->memLen, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (p == NULL) + return -1; + XMEMCPY(p, bio->mem, bio->memLen); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = p; + p += bio->memLen; + } + + /* Put data on the end of the buffer. */ + XMEMCPY(p, data, len); + bio->memLen += len; + + return len; + } - WOLFSSL_ENTER("BIO_write"); /* already got eof, again is error */ - if (front->eof) + if (bio && front->eof) return SSL_FATAL_ERROR; while(bio && ((ssl = bio->ssl) == 0) ) @@ -9501,7 +10992,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx, pem_password_cb cb) + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb) { WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb"); if (ctx != NULL) { @@ -9526,8 +11017,18 @@ int wolfSSL_set_compression(WOLFSSL* ssl) unsigned long wolfSSL_ERR_get_error(void) { - /* TODO: */ - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL, + NULL, NULL); + wc_RemoveErrorNode(-1); + return ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } #ifndef NO_MD5 @@ -9558,10 +11059,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (void)type; WOLFSSL_ENTER("wolfSSL_EVP_BytesToKey"); - wc_InitMd5(md5); + + if (wc_InitMd5(md5) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } /* only support MD5 for now */ - if (XSTRNCMP(md, "MD5", 3) != 0) return 0; + if (XSTRNCMP(md, "MD5", 3) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } /* only support CBC DES and AES for now */ #ifndef NO_DES3 @@ -9650,6 +11162,79 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA +#if !defined(NO_WOLFSSL_SERVER) +size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; +} +#endif /* !defined(NO_WOLFSSL_SERVER) */ + + +#if !defined(NO_WOLFSSL_CLIENT) +/* Return the amount of random bytes copied over or error case. + * ssl : ssl struct after handshake + * out : buffer to hold random bytes + * outSz : either 0 (return max buffer sz) or size of out buffer + * + * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. + */ +size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; +} +#endif /* !defined(NO_WOLFSSL_CLIENT) */ + + unsigned long wolfSSLeay(void) { return SSLEAY_VERSION_NUMBER; @@ -9667,11 +11252,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_MD5 void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) { + int ret; typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1]; (void)sizeof(md5_test); WOLFSSL_ENTER("MD5_Init"); - wc_InitMd5((Md5*)md5); + ret = wc_InitMd5((Md5*)md5); + (void)ret; } @@ -9858,12 +11445,89 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #endif /* WOLFSSL_SHA512 */ + static struct s_ent{ + const unsigned char macType; + const char *name; + } md_tbl[] = { + #ifndef NO_MD5 + {MD5, "MD5"}, + #endif /* NO_MD5 */ + + #ifndef NO_SHA + {SHA, "SHA"}, + #endif /* NO_SHA */ + + #ifdef WOLFSSL_SHA224 + {SHA224, "SHA224"}, + #endif /* WOLFSSL_SHA224 */ + + {SHA256, "SHA256"}, + + #ifdef WOLFSSL_SHA384 + {SHA384, "SHA384"}, + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + {SHA512, "SHA512"}, + #endif /* WOLFSSL_SHA512 */ + + {0, NULL} + } ; + +const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) +{ + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"MD5", "ssl3-md5"}, + {"SHA1", "ssl3-sha1"}, + { NULL, NULL} + }; + + const struct alias *al ; + const struct s_ent *ent ; + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (EVP_MD *)ent->name; + } + return NULL; +} + +static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type) +{ + const struct s_ent *ent ; + for( ent = md_tbl; ent->macType != 0; ent++) + if(type == ent->macType) { + return (WOLFSSL_EVP_MD *)ent->name; + } + return 0; +} + +int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + for( ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->macType; + } + return 0; +} + #ifndef NO_MD5 const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) { - static const char* type = "MD5"; + const char* type = EVP_get_digestbyname("MD5"); WOLFSSL_ENTER("EVP_md5"); return type; } @@ -9874,7 +11538,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_SHA const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) { - static const char* type = "SHA"; + const char* type = EVP_get_digestbyname("SHA"); WOLFSSL_ENTER("EVP_sha1"); return type; } @@ -9884,7 +11548,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void) { - static const char* type = "SHA224"; + const char* type = EVP_get_digestbyname("SHA224"); WOLFSSL_ENTER("EVP_sha224"); return type; } @@ -9894,7 +11558,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) { - static const char* type = "SHA256"; + const char* type = EVP_get_digestbyname("SHA256"); WOLFSSL_ENTER("EVP_sha256"); return type; } @@ -9903,7 +11567,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) { - static const char* type = "SHA384"; + const char* type = EVP_get_digestbyname("SHA384"); WOLFSSL_ENTER("EVP_sha384"); return type; } @@ -9914,19 +11578,45 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) { - static const char* type = "SHA512"; + const char* type = EVP_get_digestbyname("SHA512"); WOLFSSL_ENTER("EVP_sha512"); return type; } #endif /* WOLFSSL_SHA512 */ + WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void) + { + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_ENTER("EVP_MD_CTX_new"); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ctx){ + wolfSSL_EVP_MD_CTX_init(ctx); + } + return ctx; + } + + WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_free"); + wolfSSL_EVP_MD_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); - (void)ctx; - /* do nothing */ + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); + } + + const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) + { + if (!ctx) + return NULL; + return (const WOLFSSL_EVP_MD *)wolfSSL_EVP_get_md(ctx->macType); } #ifndef NO_AES @@ -9972,6 +11662,25 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return EVP_AES_256_CTR; } + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); + return EVP_AES_128_ECB; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb"); + return EVP_AES_192_ECB; + } + + + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb"); + return EVP_AES_256_ECB; + } #endif /* NO_AES */ #ifndef NO_DES3 @@ -9980,13 +11689,25 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); return EVP_DES_CBC; } - - +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); + return EVP_DES_ECB; + } +#endif const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) { WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); return EVP_DES_EDE3_CBC; } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb"); + return EVP_DES_EDE3_ECB; + } +#endif #endif /* NO_DES3 */ const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) @@ -10065,13 +11786,19 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("no type set"); return 0; /* failure */ } + ctx->bufUsed = 0; + ctx->lastUsed = 0; + ctx->flags = 0; #ifndef NO_AES + /* printf("cipherType=%d\n", ctx->cipherType); */ if (ctx->cipherType == AES_128_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CBC); + WOLFSSL_MSG("EVP_AES_128_CBC"); ctx->cipherType = AES_128_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10088,9 +11815,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_192_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CBC); + WOLFSSL_MSG("EVP_AES_192_CBC"); ctx->cipherType = AES_192_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10107,9 +11836,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_256_CBC_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CBC); + WOLFSSL_MSG("EVP_AES_256_CBC"); ctx->cipherType = AES_256_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10127,14 +11858,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef WOLFSSL_AES_COUNTER else if (ctx->cipherType == AES_128_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_128_CTR); + WOLFSSL_MSG("EVP_AES_128_CTR"); ctx->cipherType = AES_128_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { - ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10146,14 +11879,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_192_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_192_CTR); + WOLFSSL_MSG("EVP_AES_192_CTR"); ctx->cipherType = AES_192_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10165,14 +11900,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } else if (ctx->cipherType == AES_256_CTR_TYPE || (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_AES_256_CTR); + WOLFSSL_MSG("EVP_AES_256_CTR"); ctx->cipherType = AES_256_CTR_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CTR_MODE; ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, iv, - AES_ENCRYPTION); + AES_ENCRYPTION); if (ret != 0) return ret; } @@ -10183,14 +11920,65 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } } #endif /* WOLFSSL_AES_CTR */ + else if (ctx->cipherType == AES_128_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_ECB"); + ctx->cipherType = AES_128_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + else if (ctx->cipherType == AES_192_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_ECB"); + ctx->cipherType = AES_192_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + if(ctx->enc) + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + else if (ctx->cipherType == AES_256_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_ECB"); + ctx->cipherType = AES_256_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_AesSetKey(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } #endif /* NO_AES */ #ifndef NO_DES3 if (ctx->cipherType == DES_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_CBC); + WOLFSSL_MSG("EVP_DES_CBC"); ctx->cipherType = DES_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10203,12 +11991,32 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (iv && key == NULL) wc_Des_SetIV(&ctx->cipher.des, iv); } +#ifdef WOLFSSL_DES_ECB + else if (ctx->cipherType == DES_ECB_TYPE || + (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_ECB"); + ctx->cipherType = DES_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } +#endif else if (ctx->cipherType == DES_EDE3_CBC_TYPE || (type && XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { - WOLFSSL_MSG(EVP_DES_EDE3_CBC); + WOLFSSL_MSG("EVP_DES_EDE3_CBC"); ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; if (key) { @@ -10224,12 +12032,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return ret; } } + else if (ctx->cipherType == DES_EDE3_ECB_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_ECB"); + ctx->cipherType = DES_EDE3_ECB_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } #endif /* NO_DES3 */ #ifndef NO_RC4 if (ctx->cipherType == ARC4_TYPE || (type && XSTRNCMP(type, "ARC4", 4) == 0)) { WOLFSSL_MSG("ARC4"); ctx->cipherType = ARC4_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_STREAM_CIPHER; if (ctx->keyLen == 0) /* user may have already set */ ctx->keyLen = 16; /* default to 128 */ if (key) @@ -10240,8 +12066,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef HAVE_IDEA if (ctx->cipherType == IDEA_CBC_TYPE || (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { - WOLFSSL_MSG(EVP_IDEA_CBC); + WOLFSSL_MSG("EVP_IDEA_CBC"); ctx->cipherType = IDEA_CBC_TYPE; + ctx->flags = WOLFSSL_EVP_CIPH_CBC_MODE; ctx->keyLen = IDEA_KEY_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -10328,6 +12155,17 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); break; #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif #ifdef WOLFSSL_AES_COUNTER case AES_128_CTR_TYPE : case AES_192_CTR_TYPE : @@ -10345,14 +12183,21 @@ int wolfSSL_set_compression(WOLFSSL* ssl) else wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); break; - case DES_EDE3_CBC_TYPE : if (ctx->enc) ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); else ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); break; +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); + break; #endif +#endif /* !NO_DES3 */ #ifndef NO_RC4 case ARC4_TYPE : @@ -10380,13 +12225,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (ret != 0) { WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); - return 0; /* failuer */ + return 0; /* failure */ } WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); return SSL_SUCCESS; /* success */ } +#include "wolfcrypt/src/evp.c" + /* store for external read of iv, SSL_SUCCESS on success */ int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) @@ -10526,39 +12373,52 @@ int wolfSSL_set_compression(WOLFSSL* ssl) const WOLFSSL_EVP_MD* type) { WOLFSSL_ENTER("EVP_DigestInit"); + + if (ctx == NULL || type == NULL) { + return BAD_FUNC_ARG; + } + + + #ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); + #endif + if (XSTRNCMP(type, "SHA256", 6) == 0) { ctx->macType = SHA256; - wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash); + wolfSSL_SHA256_Init(&(ctx->hash.sha256)); } #ifdef WOLFSSL_SHA224 else if (XSTRNCMP(type, "SHA224", 6) == 0) { ctx->macType = SHA224; - wolfSSL_SHA224_Init((SHA224_CTX*)&ctx->hash); + wolfSSL_SHA224_Init(&(ctx->hash.sha224)); } #endif #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { ctx->macType = SHA384; - wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash); + wolfSSL_SHA384_Init(&(ctx->hash.sha384)); } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { ctx->macType = SHA512; - wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash); + wolfSSL_SHA512_Init(&(ctx->hash.sha512)); } #endif #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { ctx->macType = MD5; - wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash); + wolfSSL_MD5_Init(&(ctx->hash.md5)); } #endif #ifndef NO_SHA /* has to be last since would pick or 224, 256, 384, or 512 too */ else if (XSTRNCMP(type, "SHA", 3) == 0) { ctx->macType = SHA; - wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash); + wolfSSL_SHA_Init(&(ctx->hash.sha)); } #endif /* NO_SHA */ else @@ -10689,6 +12549,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #else Hmac hmac[1]; #endif + void* heap = NULL; WOLFSSL_ENTER("HMAC"); if (!md) @@ -10702,22 +12563,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return NULL; #ifdef WOLFSSL_SMALL_STACK - hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_TMP_BUFFER); if (hmac == NULL) return NULL; #endif - if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) - if (wc_HmacUpdate(hmac, d, n) == 0) - if (wc_HmacFinal(hmac, md) == 0) { - if (md_len) - *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE - : (int)SHA_DIGEST_SIZE; - ret = md; + if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) { + if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) { + if (wc_HmacUpdate(hmac, d, n) == 0) { + if (wc_HmacFinal(hmac, md) == 0) { + if (md_len) + *md_len = (type == MD5) ? (int)MD5_DIGEST_SIZE + : (int)SHA_DIGEST_SIZE; + ret = md; + } } + } + wc_HmacFree(hmac); + } #ifdef WOLFSSL_SMALL_STACK - XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; @@ -10725,7 +12591,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_ERR_clear_error(void) { - /* TODO: */ + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + wc_ClearErrorNodes(); +#endif } @@ -10857,8 +12727,54 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_clear(WOLFSSL* ssl) { - (void)ssl; - /* TODO: GetErrors().Remove(); */ + if (ssl == NULL) { + return SSL_FAILURE; + } + + ssl->options.isClosed = 0; + ssl->options.connReset = 0; + ssl->options.sentNotify = 0; + + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.handShakeDone = 0; + /* ssl->options.processReply = doProcessInit; */ + + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + if (ssl->hsHashes != NULL) { +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_InitMd5(&ssl->hsHashes->hashMd5); +#endif +#ifndef NO_SHA + if (wc_InitSha(&ssl->hsHashes->hashSha) != 0) + return SSL_FAILURE; +#endif +#endif +#ifndef NO_SHA256 + if (wc_InitSha256(&ssl->hsHashes->hashSha256) != 0) + return SSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA384 + if (wc_InitSha384(&ssl->hsHashes->hashSha384) != 0) + return SSL_FAILURE; +#endif +#ifdef WOLFSSL_SHA512 + if (wc_InitSha512(&ssl->hsHashes->hashSha512) != 0) + return SSL_FAILURE; +#endif + } + +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + return SSL_SUCCESS; } @@ -10927,9 +12843,12 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) { - /* TODO: maybe? */ (void)ctx; - return (~0); + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif } unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, @@ -10943,18 +12862,86 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return 0; } + WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb( + WOLFSSL_CTX *ctx) + { + if (ctx == NULL || ctx->passwd_cb == NULL) { + return NULL; + } + + return ctx->passwd_cb; + } + + + WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata( + WOLFSSL_CTX *ctx) + { + if (ctx == NULL) { + return NULL; + } + + return ctx->userdata; + } + #endif /* OPENSSL_EXTRA */ #if defined(KEEP_PEER_CERT) + #ifdef SESSION_CERTS + /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. + * + * x509 WOLFSSL_X509 object to decode into. + * in X509 DER data. + * len Length of the X509 DER data. + * returns the new certificate on success, otherwise NULL. + */ + static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return MEMORY_E; + #endif + + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + #endif + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_peer_certificate"); if (ssl->peerCert.issuer.sz) return &ssl->peerCert; - else - return 0; +#ifdef SESSION_CERTS + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + return &ssl->peerCert; + } + } +#endif + return 0; } #endif /* KEEP_PEER_CERT */ @@ -11012,7 +12999,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("X509_get_issuer_name"); - if(cert) + if (cert && cert->issuer.sz != 0) return &cert->issuer; return NULL; } @@ -11021,7 +13008,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); - if(cert) + if (cert && cert->subject.sz != 0) return &cert->subject; return NULL; } @@ -11255,8 +13242,10 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (buf != NULL && text != NULL) { textSz = min(textSz, len); - XMEMCPY(buf, text, textSz); - buf[textSz] = '\0'; + if (textSz > 0) { + XMEMCPY(buf, text, textSz - 1); + buf[textSz - 1] = '\0'; + } } WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); @@ -11279,7 +13268,8 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) if (name->fullName.fullName && name->fullName.fullNameLen > 0) { switch (nid) { case ASN_COMMON_NAME: - ret = name->fullName.cnIdx; + if (pos != name->fullName.cnIdx) + ret = name->fullName.cnIdx; break; default: WOLFSSL_MSG("NID not yet implemented"); @@ -11636,7 +13626,6 @@ void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) { } #endif /* NO_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) { WOLFSSL_X509 *newX509 = NULL; @@ -11707,8 +13696,8 @@ WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); if (fileBuffer != NULL) { - int ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret > 0) { + int ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret == sz) { newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); } XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -11764,8 +13753,8 @@ WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) return NULL; } - ret = (int)XFREAD(fileBuffer, sz, 1, file); - if (ret < 0) { + ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret != sz) { XFCLOSE(file); if (dynamic) XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); @@ -11902,6 +13891,7 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, ssl->ctx->certificate->buffer, ssl->ctx->certificate->length); + ssl->ctx->ownOurCert = 1; } return ssl->ctx->ourCert; } @@ -11914,6 +13904,149 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ASN1_OBJECT_push(STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || obj == NULL) { + return SSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.obj == NULL) { + sk->data.obj = obj; + sk->num += 1; + return SSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return SSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.obj = sk->data.obj; + node->next = sk->next; + sk->next = node; + sk->data.obj = obj; + sk->num += 1; + + return SSL_SUCCESS; +} + + +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJCET_pop( + STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ASN1_OBJECT* obj; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + obj = sk->data.obj; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.obj = node->data.obj; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { /* last obj in stack */ + sk->data.obj = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return obj; +} + + +#ifndef NO_ASN +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) +{ + WOLFSSL_ASN1_OBJECT* obj; + + obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, + DYNAMIC_TYPE_ASN1); + if (obj == NULL) { + return NULL; + } + + XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); + return obj; +} + + +void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) +{ + if (obj == NULL) { + return; + } + + if (obj->dynamic == 1) { + if (obj->obj != NULL) { + WOLFSSL_MSG("Freeing ASN1 OBJECT data"); + XFREE(obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); + } + } + + XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); +} + + +/* free structure for x509 stack */ +void wolfSSL_sk_ASN1_OBJECT_free(STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_ASN1_OBJECT_free(sk->data.obj); + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) +{ + /* + ASN1_STRING_to_UTF8() converts the string in to UTF8 format, + the converted data is allocated in a buffer in *out. + The length of out is returned or a negative error code. + The buffer *out should be free using OPENSSL_free(). + */ + (void)out; + (void)in; + WOLFSSL_STUB("ASN1_STRING_to_UTF8"); + return -1; +} +#endif /* NO_ASN */ + + int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, unsigned int len) { @@ -11926,8 +14059,23 @@ int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, void wolfSSL_set_connect_state(WOLFSSL* ssl) { - (void)ssl; - /* client by default */ + word16 haveRSA = 1; + word16 havePSK = 0; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.side = WOLFSSL_CLIENT_END; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + InitSuites(ssl->suites, ssl->version, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } } #endif @@ -11949,8 +14097,21 @@ int wolfSSL_session_reused(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + if (session == NULL) + return; + +#ifdef HAVE_EXT_CACHE + if (session->isAlloced) { + #ifdef HAVE_SESSION_TICKET + if (session->isDynamic) + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else /* No need to free since cache is static */ (void)session; +#endif } #endif @@ -11967,6 +14128,8 @@ const char* wolfSSL_get_version(WOLFSSL* ssl) return "TLSv1.1"; case TLSv1_2_MINOR : return "TLSv1.2"; + case TLSv1_3_MINOR : + return "TLSv1.3"; default: return "unknown"; } @@ -12056,15 +14219,264 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) return wolfSSL_get_cipher_name_internal(ssl); } +#ifdef HAVE_ECC +/* Return the name of the curve used for key exchange as a printable string. + * + * ssl The SSL/TLS object. + * returns NULL if ECDH was not used, otherwise the name as a string. + */ +const char* wolfSSL_get_curve_name(WOLFSSL* ssl) +{ + if (ssl == NULL) + return NULL; + if (ssl->specs.kea != ecdhe_psk_kea && + ssl->specs.kea != ecc_diffie_hellman_kea) + return NULL; + if (ssl->ecdhCurveOID == 0) + return NULL; + return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); +} +#endif #ifdef OPENSSL_EXTRA -char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) { - (void)cipher; - (void)in; - (void)len; - return 0; + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + + if (cipher == NULL || in == NULL) + return NULL; + + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; +#ifndef NO_RSA + case rsa_kea: + keaStr = "RSA"; + break; +#endif +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; +#endif + case fortezza_kea: + keaStr = "FZ"; + break; +#ifndef NO_PSK + case psk_kea: + keaStr = "PSK"; + break; + #ifndef NO_DH + case dhe_psk_kea: + keaStr = "DHEPSK"; + break; + #endif + #ifdef HAVE_ECC + case ecdhe_psk_kea: + keaStr = "ECDHEPSK"; + break; + #endif +#endif +#ifdef HAVE_NTRU + case ntru_kea: + keaStr = "NTRU"; + break; +#endif +#ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; +#endif +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif + default: + authStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.bulk_cipher_algorithm) { + case wolfssl_cipher_null: + encStr = "None"; + break; +#ifndef NO_RC4 + case wolfssl_rc4: + encStr = "RC4(128)"; + break; +#endif +#ifndef NO_DES3 + case wolfssl_triple_des: + encStr = "3DES(168)"; + break; +#endif +#ifdef HAVE_IDEA + case wolfssl_idea: + encStr = "IDEA(128)"; + break; +#endif +#ifndef NO_AES + case wolfssl_aes: + if (cipher->ssl->specs.key_size == 128) + encStr = "AES(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESGCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESCCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESCCM(256)"; + else + encStr = "AESCCM(?)"; + break; + #endif +#endif +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (cipher->ssl->specs.key_size == 128) + encStr = "Camellia(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif +#if defined(HAVE_HC128) && !defined(NO_HC128) + case wolfssl_hc128: + encStr = "HC128(128)"; + break; +#endif +#if defined(HAVE_RABBIT) && !defined(NO_RABBIT) + case wolfssl_rabbit: + encStr = "RABBIT(128)"; + break; +#endif + default: + encStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.mac_algorithm) { + case no_mac: + macStr = "None"; + break; +#ifndef NO_MD5 + case md5_mac: + macStr = "MD5"; + break; +#endif +#ifndef NO_SHA + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; +#endif +#ifndef NO_SHA256 + case sha256_mac: + macStr = "SHA256"; + break; +#endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; +#endif +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; +#endif +#ifdef HAVE_BLAKE2 + case blake2b_mac: + macStr = "BLAKE2b"; + break; +#endif + default: + macStr = "unknown"; + break; + } + + /* Build up the string by copying onto the end. */ + XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " ", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Kx=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, keaStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Au=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, authStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Enc=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, encStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; + + return ret; } @@ -12072,6 +14484,10 @@ char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) { + if (ssl == NULL) { + return NULL; + } + /* sessions are stored statically, no need for reference count */ return wolfSSL_get_session(ssl); } @@ -12087,15 +14503,6 @@ void wolfSSL_X509_free(WOLFSSL_X509* x509) #endif /* NO_CERTS */ -/* was do nothing */ -/* -void OPENSSL_free(void* buf) -{ - (void)buf; -} -*/ - - int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) { @@ -12159,7 +14566,8 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) { - (void)bio; + if (bio && bio->type == BIO_MEMORY) + return bio->memLen; return 0; } @@ -12241,7 +14649,6 @@ WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) return 0; } - int wolfSSL_COMP_add_compression_method(int method, void* data) { (void)method; @@ -12290,44 +14697,163 @@ int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long len) + const char* file, long type) { +#ifndef NO_FILESYSTEM + int ret = SSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + byte* curr = NULL; + byte* prev = NULL; + WOLFSSL_X509* x509; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == NULL) + return BAD_FUNC_ARG; + + XFSEEK(fp, 0, XSEEK_END); + sz = XFTELL(fp); + XREWIND(fp); + + if (sz <= 0) + goto end; + + pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ret = MEMORY_ERROR; + goto end; + } + + /* Read in file which may be CRLs or certificates. */ + if (XFREAD(pem, (size_t)sz, 1, fp) != 1) + goto end; + + prev = curr = pem; + do { + if (XSTRNSTR((char*)curr, BEGIN_X509_CRL, (unsigned int)sz) != NULL) { +#ifdef HAVE_CRL + WOLFSSL_CERT_MANAGER* cm = lookup->store->cm; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != SSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + goto end; + } + } + + ret = BufferLoadCRL(cm->crl, curr, sz, SSL_FILETYPE_PEM, 1); + if (ret != SSL_SUCCESS) + goto end; +#endif + curr = (byte*)XSTRNSTR((char*)curr, END_X509_CRL, (unsigned int)sz); + } + else if (XSTRNSTR((char*)curr, BEGIN_CERT, (unsigned int)sz) != NULL) { + x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz, + SSL_FILETYPE_PEM); + if (x509 == NULL) + goto end; + ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); + wolfSSL_X509_free(x509); + if (ret != SSL_SUCCESS) + goto end; + curr = (byte*)XSTRNSTR((char*)curr, END_CERT, (unsigned int)sz); + } + else + goto end; + + if (curr == NULL) + goto end; + + curr++; + sz -= (long)(curr - prev); + prev = curr; + } + while (ret == SSL_SUCCESS); + +end: + if (pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_TMP_BUFFER); + XFCLOSE(fp); + return ret; +#else (void)lookup; (void)file; - (void)len; - return 0; + (void)type; + return SSL_FAILURE; +#endif } WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 }; + return &meth; } - WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 }; + return &meth; } - WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509_LOOKUP_METHOD* m) { - (void)store; + /* Method is a dummy value and is not needed. */ (void)m; - return 0; + /* Make sure the lookup has a back reference to the store. */ + store->lookup.store = store; + return &store->lookup; } #ifndef NO_CERTS +WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) +{ + WOLFSSL_X509* localX509 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + return NULL; + } + size = ret; + + localX509 = wolfSSL_X509_d2i(NULL, mem, size); + if (localX509 == NULL) { + return NULL; + } + + if (x509 != NULL) { + *x509 = localX509; + } + + return localX509; +} + #if !defined(NO_ASN) && !defined(NO_PWDBASED) WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -12416,7 +14942,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WC_DerCertList* current = certList; *ca = (STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(STACK_OF(WOLFSSL_X509)), - heap, DYNAMIC_TYPE_PKCS); + heap, DYNAMIC_TYPE_X509); if (*ca == NULL) { if (pk != NULL) { XFREE(pk, heap, DYNAMIC_TYPE_PKCS); @@ -12442,7 +14968,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, WOLFSSL_X509* x509; x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_X509); InitX509(x509, 1, heap); InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { @@ -12506,7 +15032,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, /* Decode cert and place in X509 struct */ if (certData != NULL) { *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, - DYNAMIC_TYPE_PKCS); + DYNAMIC_TYPE_X509); if (*cert == NULL) { if (pk != NULL) { XFREE(pk, heap, DYNAMIC_TYPE_PKCS); @@ -12542,8 +15068,9 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, /* get key type */ ret = BAD_STATE_E; if (pk != NULL) { /* decode key if present */ + /* using dynamic type public key because of wolfSSL_EVP_PKEY_free */ *pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), - heap, DYNAMIC_TYPE_PKCS); + heap, DYNAMIC_TYPE_PUBLIC_KEY); if (*pkey == NULL) { wolfSSL_X509_free(*cert); *cert = NULL; if (ca != NULL) { @@ -12582,7 +15109,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); return 0; } @@ -12593,7 +15120,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; @@ -12610,7 +15137,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, if (ca != NULL) { wolfSSL_sk_X509_free(*ca); *ca = NULL; } - XFREE(*pkey, heap, DYNAMIC_TYPE_PKCS); *pkey = NULL; + XFREE(*pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY); *pkey = NULL; XFREE(pk, heap, DYNAMIC_TYPE_PKCS); WOLFSSL_MSG("Bad PKCS12 key format"); return 0; @@ -12637,6 +15164,18 @@ void wolfSSL_PKCS12_PBE_add(void) WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); } + + +WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) +{ + if (ctx == NULL) { + return NULL; + } + + return ctx->chain; +} + + int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) { int result = SSL_FATAL_ERROR; @@ -12678,6 +15217,8 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); store = NULL; } + else + store->isDynamic = 1; } return store; @@ -12686,7 +15227,7 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store != NULL) { + if (store != NULL && store->isDynamic) { if (store->cm != NULL) wolfSSL_CertManagerFree(store->cm); XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); @@ -12694,6 +15235,23 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) } +int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) +{ + int ret = SSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags"); + + if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) { + ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag); + } + + (void)store; + (void)flag; + + return ret; +} + + int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) { (void)store; @@ -12732,8 +15290,11 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, if (ctx != NULL) { ctx->store = store; ctx->current_cert = x509; + ctx->chain = sk; ctx->domain = NULL; +#ifdef HAVE_EX_DATA ctx->ex_data = NULL; +#endif ctx->userCtx = NULL; ctx->error = 0; ctx->error_depth = 0; @@ -12751,6 +15312,8 @@ void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) wolfSSL_X509_STORE_free(ctx->store); if (ctx->current_cert != NULL) wolfSSL_FreeX509(ctx->current_cert); + if (ctx->chain != NULL) + wolfSSL_sk_X509_free(ctx->chain); XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); } } @@ -12841,6 +15404,20 @@ void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) } +WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new() +{ + WOLFSSL_EVP_PKEY* pkey; + + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + } + + return pkey; +} + + void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) { if (key != NULL) { @@ -12885,29 +15462,58 @@ WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) { - (void)x509; - return 0; + WOLFSSL_ASN1_INTEGER* a; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (int)(sizeof(WOLFSSL_ASN1_INTEGER) - 2)) { + XFREE(a, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + a->data[i++] = ASN_INTEGER; + a->data[i++] = (unsigned char)x509->serialSz; + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + + return a; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) { - (void)bio; - (void)asnTime; + char buf[MAX_TIME_STRING_SZ]; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, sizeof(buf)); + wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); + return 0; } +#endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) -char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) { int format; int dateLen; - byte* date = (byte*)time; + byte* date = (byte*)t; WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); - if (time == NULL || buf == NULL || len < 5) { + if (t == NULL || buf == NULL || len < 5) { WOLFSSL_MSG("Bad argument"); return NULL; } @@ -12944,11 +15550,10 @@ long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) } - void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ctx != NULL && idx == 0) return ctx->ex_data; #else @@ -12976,12 +15581,23 @@ void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, unsigned long wolfSSL_ERR_peek_error(void) { + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + +#ifdef OPENSSL_EXTRA + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); +#else return 0; +#endif } int wolfSSL_ERR_GET_REASON(unsigned long err) { +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* Nginx looks for this error to know to stop parsing certificates. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE)) + return PEM_R_NO_START_LINE; +#endif (void)err; return 0; } @@ -13018,13 +15634,439 @@ int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) } +unsigned long wolfSSL_set_options(WOLFSSL* ssl, unsigned long op) +{ + WOLFSSL_ENTER("wolfSSL_set_options"); + + if (ssl == NULL) { + return 0; + } + + /* if SSL_OP_ALL then turn all bug workarounds one */ + if ((op & SSL_OP_ALL) == SSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + + op |= SSL_OP_MICROSOFT_SESS_ID_BUG; + op |= SSL_OP_NETSCAPE_CHALLENGE_BUG; + op |= SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + op |= SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; + op |= SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; + op |= SSL_OP_MSIE_SSLV2_RSA_PADDING; + op |= SSL_OP_SSLEAY_080_CLIENT_DH_BUG; + op |= SSL_OP_TLS_D5_BUG; + op |= SSL_OP_TLS_BLOCK_PADDING_BUG; + op |= SSL_OP_TLS_ROLLBACK_BUG; + op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + } + + ssl->options.mask |= op; + + /* by default cookie exchange is on with DTLS */ + if ((ssl->options.mask & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { + WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); + } + + if ((ssl->options.mask & SSL_OP_NO_SSLv2) == SSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + if (ssl->version.minor == TLSv1_2_MINOR) + ssl->version.minor = TLSv1_1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); + } + + if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); + ssl->options.usingCompression = 0; + #else + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); + #endif + } + + return ssl->options.mask; +} + + +unsigned long wolfSSL_get_options(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_options"); + + return ssl->options.mask; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s) +{ + (void)s; + return 0; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s) +{ + (void)s; + return 0; +} + + +#ifndef NO_DH +long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) +{ + int pSz, gSz; + byte *p, *g; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); + + if (!ssl || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if (pSz <= 0 || gSz <= 0) + return SSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + if (!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + if (!g) { + XFREE(p, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if (pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); + + XFREE(p, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(g, ssl->heap, DYNAMIC_TYPE_DH_BUFFER); + + return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; +} +#endif /* !NO_DH */ + + +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +{ + if (ssl == NULL) { + return SSL_FAILURE; + } + + ssl->loggingCtx = arg; + return SSL_SUCCESS; +} +#endif /* HAVE_PK_CALLBACKS */ + +#ifdef WOLFSSL_HAPROXY +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) +{ + const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + return c; +} +#endif + +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) +{ + (void)st; + WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); + //wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); + return SSL_FAILURE; +} + + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +{ + (void)s; + (void)type; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_type"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len) +{ + (void)s; + (void)sid; + (void)sid_len; + WOLFSSL_STUB("SSL_SESSION_set1_id"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + (void)s; + (void)sid_ctx; + (void)sid_ctx_len; + WOLFSSL_STUB("SSL_SESSION_set1_id_context"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x) +{ + (void)x; + WOLFSSL_STUB("X509_get0_tbs_sigalg"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor) +{ + (void)paobj; + (void)pptype; + (void)ppval; + (void)algor; + WOLFSSL_STUB("X509_ALGOR_get0"); +} + +/*** TBD ***/ +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x) +{ + (void)x; + WOLFSSL_STUB("X509_get_X509_PUBKEY"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub) +{ + (void)ppkalg; + (void)pk; + (void)ppklen; + (void)pa; + (void)pub; + WOLFSSL_STUB("X509_PUBKEY_get0_param"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int EVP_PKEY_bits(WOLFSSL_EVP_PKEY *pkey) +{ + (void)pkey; + WOLFSSL_STUB("EVP_PKEY_bits"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API int i2d_X509(WOLFSSL_X509 *x, unsigned char **out) +{ + (void)x; + (void)out; + WOLFSSL_STUB("i2d_X509"); + return -1; +} + +/*** TBD ***/ +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) +{ + (void)buf; + (void)buf_len; + (void)a; + WOLFSSL_STUB("i2t_ASN1_OBJECT"); + return -1; +} + +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_finished"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_peer_finished"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)) +{ + (void)ctx; + (void)dh; + WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback"); +} + +/*** TBD ***/ +WOLFSSL_API STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p) +{ + (void)p; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num"); + return -1; +} + +#if !defined(NO_FILESYSTEM) +/*** TBD ***/ +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_X509(FILE *fp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_X509"); + return NULL; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(FILE *fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_PrivateKey"); + return NULL; +} +#endif + +/*** TBD ***/ +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir) +{ + (void)ctx; + (void)file; + (void)dir; + WOLFSSL_STUB("X509_STORE_load_locations"); + return SSL_FAILURE; +} + +/*** TBD ***/ +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx) +{ + (void)ciphers; + (void)idx; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value"); + return NULL; +} + +WOLFSSL_API void ERR_load_SSL_strings(void) +{ + +} + +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) +{ + if (s == NULL || resp == NULL) + return 0; + + *resp = s->ocspResp; + return s->ocspRespSz; +} + +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, + unsigned char *resp, int len) +{ + if (s == NULL) + return SSL_FAILURE; + + s->ocspResp = resp; + s->ocspRespSz = len; + + return SSL_SUCCESS; +} + + +long wolfSSL_get_verify_result(const WOLFSSL *ssl) +{ + if (ssl == NULL) { + return SSL_FAILURE; + } + + return ssl->peerVerifyRet; +} + + long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) { (void)ctx; return 0; } - long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) { (void)ctx; @@ -13101,14 +16143,156 @@ long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) return 0; } + +#ifndef NO_CERTS +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + byte* chain = NULL; + long chainSz = 0; + int derSz; + const byte* der; + int ret; + int idx = 0; + DerBuffer *derBuffer = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); + + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + WOLFSSL_MSG("Error getting X509 DER"); + return SSL_FAILURE; + } + + if (ctx->certificate == NULL) { + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return SSL_FAILURE; + } + } + else { + /* TODO: Do this elsewhere. */ + ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); + if (ret != 0) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } + XMEMCPY(derBuffer->buffer, der, derSz); + ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return SSL_FAILURE; + } + + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += OPAQUE24_LEN + derSz; + + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } + + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + idx = ctx->certChain->length; + } + c32to24(derSz, chain + idx); + idx += OPAQUE24_LEN, + XMEMCPY(chain + idx, der, derSz); + idx += derSz; + + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chain, idx); + } + } + + /* on success WOLFSSL_X509 memory is responsibility of ctx */ + wolfSSL_X509_free(x509); + if (chain != NULL) + XFREE(chain, ctx->heap, CERT_TYPE); + + return SSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +{ + if (ctx == NULL || ctx->cm == NULL) { + return SSL_FAILURE; + } + + ctx->cm->ocspIOCtx = arg; + return SSL_SUCCESS; +} + +#endif /* NO_CERTS */ + + +/*** TBC ***/ +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +{ + (void)ctx; + return 0; +} + + +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return SSL_FAILURE; + } + + return ctx->readAhead; +} + + +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +{ + if (ctx == NULL) { + return SSL_FAILURE; + } + + ctx->readAhead = (byte)v; + + return SSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) +{ + if (ctx == NULL) { + return SSL_FAILURE; + } + + ctx->userPRFArg = arg; + return SSL_SUCCESS; +} + + #ifndef NO_DES3 -void wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, +/* 0 on success */ +int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, WOLFSSL_DES_key_schedule* key) { #ifdef WOLFSSL_CHECK_DESKEY - wolfSSL_DES_set_key_checked(myDes, key); + return wolfSSL_DES_set_key_checked(myDes, key); #else wolfSSL_DES_set_key_unchecked(myDes, key); + return 0; #endif } @@ -13126,12 +16310,14 @@ static int DES_check(word32 mask, word32 mask2, unsigned char* key) } -/* check that the key is odd parity and is not a weak key */ -void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, +/* check that the key is odd parity and is not a weak key + * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */ +int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, WOLFSSL_DES_key_schedule* key) { if (myDes == NULL || key == NULL) { WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked"); + return -2; } else { word32 i, mask, mask2; @@ -13140,7 +16326,7 @@ void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, /* sanity check before call to DES_check */ if (sz != (sizeof(word32) * 2)) { WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size"); - return; + return -2; } /* check odd parity */ @@ -13155,7 +16341,7 @@ void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, ((c >> 6) & 0x01) ^ ((c >> 7) & 0x01)) != 1) { WOLFSSL_MSG("Odd parity test fail"); - return; + return -1; } } @@ -13166,25 +16352,25 @@ void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, mask = 0x01010101; mask2 = 0x01010101; if (DES_check(mask, mask2, *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE; if (DES_check(mask, mask2, *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1; if (DES_check(mask, mask2, *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E; if (DES_check(mask, mask2, *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } /* semi-weak *key check (list from same Nist paper) */ @@ -13192,39 +16378,41 @@ void wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, if (DES_check(mask, mask2, *key) || DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0x01E001E0; mask2 = 0x01F101F1; if (DES_check(mask, mask2, *key) || DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0x01FE01FE; mask2 = 0x01FE01FE; if (DES_check(mask, mask2, *key) || DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0x1FE01FE0; mask2 = 0x0EF10EF1; if (DES_check(mask, mask2, *key) || DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE; if (DES_check(mask, mask2, *key) || DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { WOLFSSL_MSG("Weak key found"); - return; + return -2; } /* passed tests, now copy over key */ XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + + return 0; } } @@ -13245,15 +16433,34 @@ void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) } +#ifdef WOLFSSL_DES_ECB +/* Encrpyt or decrypt input message desa with key and get output in desb. + * if enc is DES_ENCRYPT,input message is encrypted or + * if enc is DES_DECRYPT,input message is decrypted. + * */ void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, - WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int len) + WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc) { - (void)desa; - (void)desb; - (void)key; - (void)len; - WOLFSSL_STUB("wolfSSL_DES_ecb_encrypt"); + Des myDes; + + WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt"); + + if (desa == NULL || key == NULL || desb == NULL || + (enc != DES_ENCRYPT && enc != DES_DECRYPT)) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt"); + } else { + if (wc_Des_SetKey(&myDes, (const byte*) key, + (const byte*) NULL, !enc) != 0) { + WOLFSSL_MSG("wc_Des_SetKey return error."); + return; + } + if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, + (const byte*)desa, sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbEncrypt return error."); + } + } } +#endif #endif /* NO_DES3 */ @@ -13272,6 +16479,47 @@ int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) return 0; } +/* Return the month as a string. + * + * n The number of the month as a two characters (1 based). + * returns the month as a string. + */ +static INLINE const char* MonthStr(const char* n) +{ + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; +} + +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + const char* p = (const char *)(asnTime->data + 2); + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + /* GetTimeString not always available. */ + wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); + wolfSSL_BIO_write(bio, " ", 1); + /* Day */ + wolfSSL_BIO_write(bio, p + 6, 2); + wolfSSL_BIO_write(bio, " ", 1); + /* Hour */ + wolfSSL_BIO_write(bio, p + 8, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Min */ + wolfSSL_BIO_write(bio, p + 10, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Secs */ + wolfSSL_BIO_write(bio, p + 12, 2); + wolfSSL_BIO_write(bio, " ", 1); + wolfSSL_BIO_write(bio, p, 4); + + return 0; +} int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) { @@ -13292,43 +16540,295 @@ void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) { +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else (void)ctx; (void)f; +#endif } +#ifdef HAVE_EXT_CACHE +/* convert 32 bit integer to opaque */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} +#endif int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) { + int size = 0; +#ifdef HAVE_EXT_CACHE + int idx = 0; +#ifdef SESSION_CERTS + int i; +#endif + unsigned char *data; + + /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + + SECRET_LEN + OPAQUE8_LEN; +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; + /* Protocol version + cipher suite */ + size += OPAQUE16_LEN + OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif + + if (p != NULL) { + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN; + c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN; + data[idx++] = sess->sessionIDSz; + XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz); + idx += sess->sessionIDSz; + XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; + data[idx++] = sess->haveEMS; +#ifdef SESSION_CERTS + data[idx++] = sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa(sess->chain.certs[i].length, data + idx); + idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->chain.certs[i].buffer, + sess->chain.certs[i].length); + idx += sess->chain.certs[i].length; + } + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; + data[idx++] = sess->cipherSuite0; + data[idx++] = sess->cipherSuite; +#endif +#ifndef NO_CLIENT_CACHE + c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->serverID, sess->idLen); + idx += sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->ticket, sess->ticketLen); + idx += sess->ticketLen; +#endif + } +#endif + (void)sess; (void)p; - return sizeof(WOLFSSL_SESSION); +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif + + return size; } +#ifdef HAVE_EXT_CACHE +/* convert opaque to 16 bit integer */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} +/* convert opaque to 32 bit integer */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +#endif + +/* TODO: no function to free new session. */ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, const unsigned char** p, long i) { + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif + (void)p; (void)i; - if (sess) - return *sess; - return NULL; + (void)ret; + + if (sess != NULL) + s = *sess; + +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; + + if (s == NULL) { + s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL) + return NULL; + s->isAlloced = 1; + s->isDynamic = 0; + } + + idx = 0; + data = (byte*)*p; + + /* bornOn | timeout | sessionID len */ + if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; + + /* sessionID | secret | haveEMS */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionID, data + idx, s->sessionIDSz); + idx += s->sessionIDSz; + XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; + s->haveEMS = data[idx++]; + +#ifdef SESSION_CERTS + /* Certificate chain */ + if (i - idx == 0) { + ret = BUFFER_ERROR; + goto end; + } + s->chain.count = data[idx++]; + for (j = 0; j < s->chain.count; j++) { + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &length); idx += OPAQUE16_LEN; + s->chain.certs[j].length = length; + if (i - idx < length) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->chain.certs[j].buffer, data + idx, length); + idx += length; + } + + /* Protocol Version | Cipher suite */ + if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; + s->cipherSuite0 = data[idx++]; + s->cipherSuite = data[idx++]; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN; + + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; + + /* Dispose of ol dynamic ticket and ensure space for new ticket. */ + if (s->isDynamic) + XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (s->ticketLen <= SESSION_TICKET_LEN) + s->ticket = s->staticTicket; + else { + s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (s->ticket == NULL) { + ret = MEMORY_ERROR; + goto end; + } + s->isDynamic = 1; + } + + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif + (void)idx; + + if (sess != NULL) + *sess = s; + + *p += idx; + +end: + if (ret != 0 && (sess == NULL || *sess != s)) + wolfSSL_SESSION_free(s); +#endif + return s; } @@ -13379,7 +16879,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) byte* myBuffer = staticBuffer; int dynamic = 0; XFILE file = XBADFILE; - long sz = 0; + size_t sz = 0; int eccKey = 0; WOLFSSL_CTX* ctx = ssl->ctx; WOLFSSL_X509* peer_cert = &ssl->peerCert; @@ -13413,7 +16913,7 @@ int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) if ((myBuffer != NULL) && (sz > 0) && - (XFREAD(myBuffer, sz, 1, file) > 0) && + (XFREAD(myBuffer, 1, sz, file) == sz) && (PemToDer(myBuffer, sz, CERT_TYPE, &fileDer, ctx->heap, info, &eccKey) == 0) && (fileDer->length != 0) && @@ -13582,7 +17082,7 @@ void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) WOLFSSL_MSG("wolfSSL_BN_free"); if (bn) { if (bn->internal) { - mp_clear((mp_int*)bn->internal); + mp_forcezero((mp_int*)bn->internal); XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); bn->internal = NULL; } @@ -13637,6 +17137,31 @@ int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, } +/* r = (a^p) % m */ +int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); + + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; + } + + if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { + return SSL_SUCCESS; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); + (void)ret; + + return SSL_FAILURE; +} + const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) { static WOLFSSL_BIGNUM* bn_one = NULL; @@ -13645,8 +17170,13 @@ const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) if (bn_one == NULL) { bn_one = wolfSSL_BN_new(); - if (bn_one) - mp_set_int((mp_int*)bn_one->internal, 1); + if (bn_one) { + if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) { + /* handle error by freeing BN and returning NULL */ + wolfSSL_BN_free(bn_one); + bn_one = NULL; + } + } } return bn_one; @@ -14269,7 +17799,7 @@ char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) { (void)bn; - WOLFSSL_MSG("wolfSSL_BN_bn2hex not implemented"); + WOLFSSL_MSG("wolfSSL_BN_bn2hex need WOLFSSL_KEY_GEN or HAVE_COMP_KEY"); return (char*)""; } @@ -14348,7 +17878,12 @@ WOLFSSL_DH* wolfSSL_DH_new(void) } InitwolfSSL_DH(external); - wc_InitDhKey(key); + if (wc_InitDhKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + XFREE(external, NULL, DYNAMIC_TYPE_DH); + return NULL; + } external->internal = key; return external; @@ -14643,7 +18178,11 @@ WOLFSSL_DSA* wolfSSL_DSA_new(void) } InitwolfSSL_DSA(external); - InitDsaKey(key); + if (wc_InitDsaKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + return NULL; + } external->internal = key; return external; @@ -14671,6 +18210,7 @@ void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) dsa = NULL; } } + #endif /* NO_DSA */ #ifndef NO_RSA @@ -14753,10 +18293,18 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) #endif /* NO_RSA */ -#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) \ - || !defined(NO_DSA) || defined(HAVE_ECC) +/* these defines are to make sure the functions SetIndividualExternal is not + * declared and then not used. */ +#if !defined(NO_ASN) || !defined(NO_DSA) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) +/* when calling SetIndividualExternal, mpi should be cleared by caller if no + * longer used. ie mp_clear(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) { + byte dynamic = 0; + WOLFSSL_MSG("Entering SetIndividualExternal"); if (mpi == NULL || bn == NULL) { @@ -14770,10 +18318,14 @@ static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) WOLFSSL_MSG("SetIndividualExternal alloc failed"); return SSL_FATAL_ERROR; } + dynamic = 1; } if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { WOLFSSL_MSG("mp_copy error"); + if (dynamic == 1) { + wolfSSL_BN_free(*bn); + } return SSL_FATAL_ERROR; } @@ -14801,6 +18353,86 @@ static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) return SSL_SUCCESS; } + + +#ifndef NO_ASN +WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn) +{ + mp_int mpi; + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); + + if (ai == NULL) { + return NULL; + } + + if ((ret = GetInt(&mpi, ai->data, &idx, sizeof(ai->data))) != 0) { + /* expecting ASN1 format for INTEGER */ + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret); + return NULL; + } + + /* mp_clear needs called because mpi is copied and causes memory leak with + * --disable-fastmath */ + ret = SetIndividualExternal(&bn, &mpi); + mp_clear(&mpi); + + if (ret != SSL_SUCCESS) { + return NULL; + } + return bn; +} +#endif /* !NO_ASN */ + +#if !defined(NO_DSA) && !defined(NO_DH) +WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) +{ + WOLFSSL_DH* dh; + DhKey* key; + + WOLFSSL_ENTER("wolfSSL_DSA_dup_DH"); + + if (dsa == NULL) { + return NULL; + } + + dh = wolfSSL_DH_new(); + if (dh == NULL) { + return NULL; + } + key = (DhKey*)dh->internal; + + if (dsa->p != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (dsa->g != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + if (SetIndividualExternal(&dh->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (SetIndividualExternal(&dh->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + return dh; +} +#endif /* !defined(NO_DSA) && !defined(NO_DH) */ + #endif /* !NO_RSA && !NO_DSA */ @@ -15497,12 +19129,16 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, WOLFSSL_MSG("Bad Encode Signature"); } else { - *sigLen = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, (RsaKey*)rsa->internal, rng); - if (*sigLen <= 0) + if (ret <= 0) { WOLFSSL_MSG("Bad Rsa Sign"); - else + ret = 0; + } + else { ret = SSL_SUCCESS; + *sigLen = ret; + } } } @@ -15646,11 +19282,23 @@ void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, if (key && keylen) { WOLFSSL_MSG("keying hmac"); - wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, (word32)keylen); + + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, + (word32)keylen); + } /* OpenSSL compat, no error */ } } +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int len, + const EVP_MD* md, void* impl) +{ + (void)impl; + wolfSSL_HMAC_Init(ctx, key, len, md); + return 1; +} + void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len) @@ -15700,9 +19348,10 @@ void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, void wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) { - (void)ctx; - WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); + + if (ctx) + wc_HmacFree(&ctx->hmac); } @@ -15938,7 +19587,47 @@ int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) return 0; } +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); +#ifndef NO_AES + if ((XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)) { + return AES_BLOCK_SIZE; + } +#ifdef WOLFSSL_AES_COUNTER + if ((XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)) { + return AES_BLOCK_SIZE; + } +#endif +#endif + +#ifndef NO_DES3 + if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ void wolfSSL_OPENSSL_free(void* p) { WOLFSSL_MSG("wolfSSL_OPENSSL_free"); @@ -15992,6 +19681,7 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, /* set the cipher name on info */ XSTRNCPY(info->name, cipher, NAME_SZ); + info->name[NAME_SZ-1] = '\0'; /* null term */ /* Generate a random salt */ if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != SSL_SUCCESS) { @@ -16050,6 +19740,74 @@ static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, } #endif /* defined(WOLFSSL_KEY_GEN) */ +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + byte* keyDer; + int pemSz; + int type; + int ret; + + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); + + if (bio == NULL || key == NULL) { + return SSL_FAILURE; + } + + keyDer = (byte*)key->pkey.ptr; + + switch (key->type) { + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; + +#ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; +#endif + + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; + + default: + WOLFSSL_MSG("Unknown Key type!"); + type = PRIVATEKEY_TYPE; + } + + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + bio->memLen = pemSz; + + ret = wc_DerToPemEx(keyDer, key->pkey_sz, bio->mem, bio->memLen, + NULL, type); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ + #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) /* return code compliant with OpenSSL : @@ -16201,7 +19959,7 @@ int wolfSSL_PEM_write_RSAPrivateKey(FILE *fp, WOLFSSL_RSA *rsa, int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, RSA* rsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg) + pem_password_cb* cb, void* arg) { (void)bio; (void)rsa; @@ -16300,7 +20058,8 @@ static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) key = (ecc_key*)eckey->internal; - /* set group (nid and idx) */ + /* set group (OID, nid and idx) */ + eckey->group->curve_oid = ecc_sets[key->idx].oidSum; eckey->group->curve_nid = ecc_sets[key->idx].id; eckey->group->curve_idx = key->idx; @@ -16474,6 +20233,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == key->group->curve_nid) { key->group->curve_idx = x; + key->group->curve_oid = ecc_sets[x].oidSum; break; } @@ -16807,6 +20567,7 @@ WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == g->curve_nid) { g->curve_idx = x; + g->curve_oid = ecc_sets[x].oidSum; break; } @@ -17053,6 +20814,7 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) { mp_int a, prime; + int ret; (void)ctx; (void)n; @@ -17069,43 +20831,40 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, WOLFSSL_MSG("No ECPoint internal set, do it"); if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); + WOLFSSL_MSG("SetECPointInternal q failed"); return SSL_FAILURE; } } /* read the curve prime and a */ if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul init 'prime/A' failed"); - return SSL_FAILURE; - } - if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'prime' curve value failed"); - return SSL_FAILURE; - } - if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'A' curve value failed"); return SSL_FAILURE; } + ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16); + if (ret == MP_OKAY) + ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16); + /* r = q * m % prime */ - if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - (ecc_point*)r->internal, &a, &prime, 1) != MP_OKAY) { - WOLFSSL_MSG("ecc_mulmod failure"); - mp_clear(&prime); - return SSL_FAILURE; - } + if (ret == MP_OKAY) + ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + (ecc_point*)r->internal, &a, &prime, 1); mp_clear(&a); mp_clear(&prime); - /* set the external value for the computed point */ - if (SetECPointInternal(r) != SSL_SUCCESS) { - WOLFSSL_MSG("SetECPointInternal failed"); - return SSL_FAILURE; + if (ret == MP_OKAY) { + /* set the external value for the computed point */ + ret = SetECPointInternal(r); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal r failed"); + } + } + else { + ret = SSL_FAILURE; } - return SSL_SUCCESS; + return ret; } void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) @@ -17319,8 +21078,8 @@ WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, } } - mp_clear(&sig_r); - mp_clear(&sig_s); + mp_free(&sig_r); + mp_free(&sig_s); } } @@ -17444,7 +21203,7 @@ int wolfSSL_PEM_write_EC_PUBKEY(FILE *fp, WOLFSSL_EC_KEY *x) int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg) + pem_password_cb* cb, void* arg) { (void)bio; (void)ecc; @@ -17619,7 +21378,7 @@ int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, const EVP_CIPHER* cipher, unsigned char* passwd, int len, - pem_password_cb cb, void* arg) + pem_password_cb* cb, void* arg) { (void)bio; (void)dsa; @@ -17799,7 +21558,7 @@ int wolfSSL_PEM_write_DSA_PUBKEY(FILE *fp, WOLFSSL_DSA *x) #endif /* #ifndef NO_DSA */ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EVP_PKEY** key, pem_password_cb cb, void* arg) + WOLFSSL_EVP_PKEY** key, pem_password_cb* cb, void* arg) { (void)bio; (void)key; @@ -17814,11 +21573,14 @@ WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, int wolfSSL_EVP_PKEY_type(int type) { - (void)type; + (void) type; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type always returns EVP_PKEY_RSA"); + return EVP_PKEY_RSA; +} - WOLFSSL_MSG("wolfSSL_EVP_PKEY_type not implemented"); - - return SSL_FATAL_ERROR; +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + return EVP_PKEY_type(pkey->type); } @@ -18046,8 +21808,9 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) InitDecodedCert(cert, chain->certs[idx].buffer, chain->certs[idx].length, NULL); - if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) { WOLFSSL_MSG("Failed to parse cert"); + } else { x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, DYNAMIC_TYPE_X509); @@ -18071,6 +21834,7 @@ WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) #endif } } + (void)ret; return x509; } @@ -18338,7 +22102,127 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA /*Lighttp compatibility*/ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) + + #ifndef NO_CERTS + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { +#ifndef NO_FILESYSTEM + WOLFSSL_X509* x509 = NULL; + unsigned char* pem = NULL; + int pemSz; + int pemAlloced = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + if (bp == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG); + return NULL; + } + + if (bp->type == BIO_MEMORY) { + pemSz = wolfSSL_BIO_get_mem_data(bp, &pem); + if (pemSz <= 0 || pem == NULL) { + WOLFSSL_MSG("Issue getting WOLFSSL_BIO mem"); + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", pemSz); + return NULL; + } + } + else if (bp->type == BIO_FILE) { + long i; + long l; + + /* Read in next certificate from file but no more. */ + i = XFTELL(bp->file); + if (i < 0) + return NULL; + XFSEEK(bp->file, 0, SEEK_END); + l = XFTELL(bp->file); + if (l < 0) + return NULL; + XFSEEK(bp->file, i, SEEK_SET); + + /* check calulated length */ + if (l - i <= 0) + return NULL; + + pem = (unsigned char*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) + return NULL; + pemAlloced = 1; + + i = 0; + /* TODO: Inefficient + * reading in one byte at a time until see END_CERT + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], END_CERT, 25) == 0) + break; + } + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (l == 0) + WOLFSSL_ERROR(SSL_NO_PEM_HEADER); + #endif + pemSz = (int)i; + } + else + return NULL; + + x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, + SSL_FILETYPE_PEM); + + if (x != NULL) { + *x = x509; + } + + if (pemAlloced) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + (void)cb; + (void)u; + + return x509; +#else + (void)bp; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif + } + + + /* + * bp : bio to read X509 from + * x : x509 to write to + * cb : password call back for reading PEM + * u : password + * _AUX is for working with a trusted X509 certificate + */ + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp, + WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + /* AUX info is; trusted/rejected uses, friendly name, private key id, + * and potentially a stack of "other" info. wolfSSL does not store + * friendly name or private key id yet in WOLFSSL_X509 for human + * readibility and does not support extra trusted/rejected uses for + * root CA. */ + return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); + } + #endif /* ifndef NO_CERTS */ + + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + FreeX509Name(name, NULL); + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + } + #endif /* NO_CERTS */ + +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(HAVE_POCO_LIB) || defined (WOLFSSL_HAPROXY) unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) { @@ -18349,45 +22233,76 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) { - (void)ctx; - (void)x; + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); - WOLFSSL_STUB("wolfSSL_CTX_use_certificate"); - return 0; + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, + ctx->heap); + if (ret != 0) + return 0; + + XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, + x->derCert->length); +#ifdef KEEP_OUR_CERT + if (ctx->ourCert != NULL && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = x; + ctx->ownOurCert = 0; +#endif + + /* Update the available options with public keys. */ + switch (x->pubKeyOID) { + case RSAk: + ctx->haveRSA = 1; + break; + case ECDSAk: + ctx->haveECC = 1; + ctx->pkCurveOID = x->pkCurveOID; + break; + } + + return SSL_SUCCESS; } - int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) { - (void)ctx; - (void)pkey; - WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); - WOLFSSL_STUB("wolfSSL_CTX_use_PrivateKey"); - - return 0; - } - - int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { - (void)b; + #ifndef NO_FILESYSTEM + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + if ((wolfSSL_BIO_get_fp(b, &fp) == SSL_SUCCESS) && (fp != NULL)) + { + XFCLOSE(fp); + } + + fp = XFOPEN(name, "r"); + if (fp == NULL) + return SSL_BAD_FILE; + + if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != SSL_SUCCESS) { + XFCLOSE(fp); + return SSL_BAD_FILE; + } + + /* file is closed when bio is free'd */ + return SSL_SUCCESS; + #else (void)name; - WOLFSSL_ENTER("wolfSSL_BIO_read_filename"); - WOLFSSL_STUB("wolfSSL_BIO_read_filename"); - - return 0; - } - - WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) { - WOLFSSL_ENTER("wolfSSL_BIO_s_file"); - WOLFSSL_STUB("wolfSSL_BIO_s_file"); - - return NULL; + (void)b; + return SSL_NOT_IMPLEMENTED; + #endif } #ifdef HAVE_ECC - const char * wolf_OBJ_nid2sn(int n) { + const char * wolfSSL_OBJ_nid2sn(int n) { int i; - WOLFSSL_ENTER("wolf_OBJ_nid2sn"); + WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); /* find based on NID and return name */ for (i = 0; i < ecc_sets[i].size; i++) { @@ -18398,18 +22313,23 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) { + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) { (void)o; - WOLFSSL_ENTER("wolf_OBJ_obj2nid"); - WOLFSSL_STUB("wolf_OBJ_obj2nid"); + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); + WOLFSSL_STUB("wolfSSL_OBJ_obj2nid"); return 0; } - int wolf_OBJ_sn2nid(const char *sn) { + int wolfSSL_OBJ_sn2nid(const char *sn) { int i; - WOLFSSL_ENTER("wolf_OBJ_osn2nid"); + WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid"); + /* Nginx uses this OpenSSL string. */ + if (XSTRNCMP(sn, "prime256v1", 10) == 0) + sn = "SECP256R1"; + if (XSTRNCMP(sn, "secp384r1", 10) == 0) + sn = "SECP384R1"; /* find based on name and return NID */ for (i = 0; i < ecc_sets[i].size; i++) { if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { @@ -18421,17 +22341,6 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) #endif /* HAVE_ECC */ - WOLFSSL_X509 *PEM_read_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { - (void)bp; - (void)x; - (void)cb; - (void)u; - WOLFSSL_ENTER("PEM_read_bio_WOLFSSL_X509"); - WOLFSSL_STUB("PEM_read_bio_WOLFSSL_X509"); - - return NULL; - } - void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { (void)ctx; (void)depth; @@ -18440,21 +22349,21 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) } - void* wolfSSL_get_app_data( const WOLFSSL *ssl) - { - /* checkout exdata stuff... */ + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) { (void)ssl; - WOLFSSL_ENTER("wolfSSL_get_app_data"); - WOLFSSL_STUB("wolfSSL_get_app_data"); + (void)depth; + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); + WOLFSSL_STUB("wolfSSL_set_verify_depth"); - return 0; } - void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { - (void)ssl; - (void)arg; - WOLFSSL_ENTER("wolfSSL_set_app_data"); - WOLFSSL_STUB("wolfSSL_set_app_data"); + void* wolfSSL_get_app_data( const WOLFSSL *ssl) { + /* checkout exdata stuff... */ + return wolfSSL_get_ex_data(ssl,0); + } + + int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg) { + return wolfSSL_set_ex_data(ssl,0,(char *)arg); } WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { @@ -18496,14 +22405,6 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } -#ifndef NO_CERTS - void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ - FreeX509Name(name, NULL); - WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); - WOLFSSL_STUB("wolfSSL_X509_NAME_free"); - } -#endif /* NO_CERTS */ - void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ (void) sk; (void) f; @@ -18528,15 +22429,61 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } -#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL */ -#endif +#endif /* HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_EXTRA */ #ifdef OPENSSL_EXTRA + +/* wolfSSL uses negative values for error states. This function returns an + * unsigned type so the value returned is the absolute value of the error. + */ +unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + + (void)line; + (void)file; +#if defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY) + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + #ifdef WOLFSSL_NGINX + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + + +#ifndef NO_CERTS +int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + + if (ctx == NULL || pkey == NULL) { + return SSL_FAILURE; + } + + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, PRIVATEKEY_TYPE); +} +#endif /* !NO_CERTS */ + + void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { return ctx->ex_data[idx]; } @@ -18547,24 +22494,26 @@ void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) return NULL; } - int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c) { + static int ctx_idx = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); (void)idx; (void)arg; (void)a; (void)b; (void)c; - return 0; + + return ctx_idx++; } int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if (ctx != NULL && idx < MAX_EX_DATA) { ctx->ex_data[idx] = data; @@ -18582,7 +22531,7 @@ int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_set_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA) { ssl->ex_data[idx] = data; @@ -18600,20 +22549,23 @@ int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, void* cb3) { + static int ssl_idx = 0; + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); (void)idx; (void)data; (void)cb1; (void)cb2; (void)cb3; - return 0; + + return ssl_idx++; } void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { WOLFSSL_ENTER("wolfSSL_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) return ssl->ex_data[idx]; #else @@ -18622,62 +22574,332 @@ void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) #endif return 0; } + +#ifndef NO_DSA +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, + pem_password_cb *cb, void *u) +{ + WOLFSSL_DSA* dsa; + DsaKey* key; + int length; + unsigned char* buf; + word32 bufSz; + int ret; + word32 idx = 0; + DerBuffer* pDer; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams"); + + ret = wolfSSL_BIO_get_mem_data(bp, &buf); + if (ret <= 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + return NULL; + } + + bufSz = (word32)ret; + + if (cb != NULL || u != NULL) { + /* + * cb is for a call back when encountering encrypted PEM files + * if cb == NULL and u != NULL then u = null terminated password string + */ + WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM"); + } + + if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL, + NULL)) < 0 ) { + WOLFSSL_MSG("Issue converting from PEM to DER"); + return NULL; + } + + if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + FreeDer(&pDer); + return NULL; + } + + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + FreeDer(&pDer); + WOLFSSL_MSG("Error creating DSA struct"); + return NULL; + } + + key = (DsaKey*)dsa->internal; + if (key == NULL) { + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + WOLFSSL_MSG("Error finding DSA key struct"); + return NULL; + } + + if (GetInt(&key->p, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->q, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->g, pDer->buffer, &idx, pDer->length) < 0 ) { + WOLFSSL_MSG("dsa key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->p, &key->p) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->q, &key->q) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != SSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (x != NULL) { + *x = dsa; + } + + FreeDer(&pDer); + return dsa; +} +#endif /* NO_DSA */ + +#include "src/bio.c" + #endif /* OPENSSL_EXTRA */ #if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) -char * wolf_OBJ_nid2ln(int n) { + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_HAPROXY) +char * wolfSSL_OBJ_nid2ln(int n) { (void)n; - WOLFSSL_ENTER("wolf_OBJ_nid2ln"); - WOLFSSL_STUB("wolf_OBJ_nid2ln"); + WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); + WOLFSSL_STUB("wolfSSL_OBJ_nid2ln"); return NULL; } -int wolf_OBJ_txt2nid(const char* s) { +int wolfSSL_OBJ_txt2nid(const char* s) { (void)s; - WOLFSSL_ENTER("wolf_OBJ_txt2nid"); - WOLFSSL_STUB("wolf_OBJ_txt2nid"); + WOLFSSL_ENTER("wolfSSL_OBJ_txt2nid"); + WOLFSSL_STUB("wolfSSL_OBJ_txt2nid"); return 0; } -WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_BIO* bio; + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + fp = XFOPEN(filename, mode); + if (fp == NULL) + return NULL; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) { + XFCLOSE(fp); + return bio; + } + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != SSL_SUCCESS) { + XFCLOSE(fp); + wolfSSL_BIO_free(bio); + bio = NULL; + } + + /* file is closed when BIO is free'd */ + return bio; +#else (void)filename; (void)mode; - WOLFSSL_ENTER("wolfSSL_BIO_new_file"); - WOLFSSL_STUB("wolfSSL_BIO_new_file"); - return NULL; -} - - -WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u) -{ - (void) bp; - (void) x; - (void) cb; - (void) u; - - WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); - WOLFSSL_STUB("wolfSSL_PEM_read_bio_DHparams"); - - return NULL; -} - -int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) { - (void)bp; - (void)x; - WOLFSSL_ENTER("PEM_write_bio_WOLFSSL_X509"); - WOLFSSL_STUB("PEM_write_bio_WOLFSSL_X509"); - - return 0; +#endif } #ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, + pem_password_cb *cb, void *u) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_DH* localDh = NULL; + unsigned char* mem = NULL; + word32 size; + long sz; + int ret; + DerBuffer *der = NULL; + byte* p = NULL; + byte* g = NULL; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + int memAlloced = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); + (void)cb; + (void)u; + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + if (bio->type == BIO_MEMORY) { + /* Use the buffer directly. */ + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + goto end; + } + size = ret; + } + else if (bio->type == BIO_FILE) { + /* Read whole file into a new buffer. */ + XFSEEK(bio->file, 0, SEEK_END); + sz = XFTELL(bio->file); + XFSEEK(bio->file, 0, SEEK_SET); + if (sz <= 0L) + goto end; + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) + goto end; + memAlloced = 1; + + if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0) + goto end; + size = (word32)sz; + } + else { + WOLFSSL_MSG("BIO type not supported for reading DH parameters"); + goto end; + } + + ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL); + if (ret != 0) + goto end; + + /* Use the object passed in, otherwise allocate a new object */ + if (x != NULL) + localDh = *x; + if (localDh == NULL) { + localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (localDh == NULL) + goto end; + XMEMSET(localDh, 0, sizeof(WOLFSSL_DH)); + } + + /* Load data in manually */ + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL || g == NULL) + goto end; + + /* Extract the p and g as data from the DER encoded DH parameters. */ + ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz); + if (ret != 0) { + if (x != NULL && localDh != *x) + XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL); + localDh = NULL; + goto end; + } + + if (x != NULL) + *x = localDh; + + /* Put p and g in as big numbers. */ + if (localDh->p != NULL) { + wolfSSL_BN_free(localDh->p); + localDh->p = NULL; + } + if (localDh->g != NULL) { + wolfSSL_BN_free(localDh->g); + localDh->g = NULL; + } + localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL); + localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL); + if (localDh->p == NULL || localDh->g == NULL) { + if (x != NULL && localDh != *x) + wolfSSL_DH_free(localDh); + localDh = NULL; + } + +end: + if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) FreeDer(&der); + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return localDh; +#else + (void)bio; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif +} +#endif + + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* certDer; + int derSz; + int pemSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); + + if (bio == NULL || cert == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_MEMORY) { + WOLFSSL_MSG("BIO type not supported for writing X509 as PEM"); + return SSL_FAILURE; + } + + certDer = cert->derCert->buffer; + derSz = cert->derCert->length; + + /* Get PEM encoded length and allocate memory for it. */ + pemSz = wc_DerToPem(certDer, derSz, NULL, 0, CERT_TYPE); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + return SSL_FAILURE; + } + bio->memLen = pemSz; + + ret = wc_DerToPemEx(certDer, derSz, bio->mem, bio->memLen, NULL, CERT_TYPE); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", ret); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} + + +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) /* Intialize ctx->dh with dh's params. Return SSL_SUCCESS on ok */ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) { @@ -18697,13 +22919,13 @@ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) if(pSz <= 0 || gSz <= 0) return SSL_FATAL_ERROR; - p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH); + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if(!p) return MEMORY_E; - g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH); + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); if(!g) { - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(p, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); return MEMORY_E; } @@ -18713,31 +22935,38 @@ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) if(pSz >= 0 && gSz >= 0) /* Conversion successful */ ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); - XFREE(p, ctx->heap, DYNAMIC_TYPE_DH); - XFREE(g, ctx->heap, DYNAMIC_TYPE_DH); + XFREE(p, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); + XFREE(g, ctx->heap, DYNAMIC_TYPE_DH_BUFFER); return pSz > 0 && gSz > 0 ? ret : SSL_FATAL_ERROR; } -#endif /* NO_DH */ -#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ +#endif /* OPENSSL_EXTRA && !NO_DH */ +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_HAPROXY */ /* stunnel compatibility functions*/ -#if defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL) +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX)) void WOLFSSL_ERR_remove_thread_state(void* pid) { (void) pid; return; } +/***TBD ***/ +void wolfSSL_print_all_errors_fp(XFILE *fp) +{ + (void)fp; +} int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA if(session != NULL && idx < MAX_EX_DATA) { session->ex_data[idx] = data; return SSL_SUCCESS; } +#endif return SSL_FAILURE; } @@ -18763,8 +22992,10 @@ int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA if (session != NULL && idx < MAX_EX_DATA && idx >= 0) return session->ex_data[idx]; +#endif return NULL; } @@ -18820,11 +23051,23 @@ void wolfSSL_ERR_load_crypto_strings(void) unsigned long wolfSSL_ERR_peek_last_error(void) { - unsigned long l = 0UL; WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - WOLFSSL_STUB("wolfSSL_ERR_peek_last_error"); - return l; +#ifdef WOLFSSL_NGINX + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + if (ret == -SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } @@ -18872,35 +23115,45 @@ int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } -int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* nm, +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, int indent, unsigned long flags) { - (void)bio; - (void)nm; - (void)indent; + int i; (void)flags; WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); - WOLFSSL_STUB("wolfSSL_X509_NAME_print_ex"); - return SSL_FAILURE; + for (i = 0; i < indent; i++) { + if (wolfSSL_BIO_write(bio, " ", 1) != 1) + return SSL_FAILURE; + } + + if (flags == XN_FLAG_RFC2253) { + if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2) + != name->sz - 2) + return SSL_FAILURE; + } + else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz) + return SSL_FAILURE; + + return SSL_SUCCESS; } @@ -18937,23 +23190,27 @@ int wolfSSL_get_state(const WOLFSSL* ssl) void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.name; } void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; } @@ -18967,6 +23224,7 @@ int wolfSSL_version(WOLFSSL* ssl) case TLSv1_MINOR : case TLSv1_1_MINOR : case TLSv1_2_MINOR : + case TLSv1_3_MINOR : return TLS1_VERSION; default: return SSL_FAILURE; @@ -18995,16 +23253,6 @@ STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) } -long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) -{ - (void)ctx; - WOLFSSL_ENTER("wolfSSL_CTX_get_options"); - WOLFSSL_STUB("wolfSSL_CTX_get_options"); - - return 0; -} - - WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) { WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); @@ -19020,18 +23268,6 @@ int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) } -const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) -{ - WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); - WOLFSSL_STUB("wolfSSL_SESSION_get_id"); - if(!sess || !idLen) { - WOLFSSL_MSG("Bad func args. Please provide idLen"); - return NULL; - } - *idLen = sess->sessionIDSz; - return sess->sessionID; -} - #ifdef HAVE_SNI int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) { @@ -19056,10 +23292,9 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) #endif /* NO_WOLFSSL_SERVER */ #endif /* HAVE_SNI */ - WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) { - if (ssl && ctx && SetSSL_CTX(ssl, ctx) == SSL_SUCCESS) + if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == SSL_SUCCESS) return ssl->ctx; return NULL; } @@ -19081,6 +23316,16 @@ void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) ctx->sniRecvCb = cb; } +int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); + if (ctx) { + ctx->sniRecvCb = cb; + return 1; + } + return 0; +} void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) { @@ -19117,7 +23362,7 @@ void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) } -WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, +STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name) { WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); @@ -19135,10 +23380,24 @@ void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*) } #endif /* OPENSSL_EXTRA and HAVE_STUNNEL */ +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX))\ + || defined(WOLFSSL_HAPROXY) +const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + if(!sess || !idLen) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } + *idLen = sess->sessionIDSz; + return sess->sessionID; +} +#endif + #if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) { int mode = 0; @@ -19542,16 +23801,814 @@ int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) return BAD_FUNC_ARG; } - /* not filtering on "ssl", since its the asyncDev */ - ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, NULL, + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, events, sizeof(events)/sizeof(events), flags, &eventCount); - if (ret == 0 && eventCount > 0) { - ret = 1; /* Success */ + if (ret == 0) { + ret = eventCount; } return ret; } + #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef OPENSSL_EXTRA +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + + (void)line; + (void)file; + + /* No data or flags stored - error display only in Nginx. */ + if (data != NULL) { + *data = ""; + } + if (flags != NULL) { + *flags = 0; + } + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + int ret = 0; + + while (1) { + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + ret = -ret; + + if (ret == SSL_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + if (ret != WANT_READ && ret != WANT_WRITE && + ret != ZERO_RETURN && ret != SSL_ERROR_ZERO_RETURN && + ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E) + break; + + wc_RemoveErrorNode(-1); + } + + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} +#endif + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("wolfSSL_get_ciphers_compat"); + return NULL; +} + +void wolfSSL_OPENSSL_config(char *config_name) +{ + WOLFSSL_STUB("wolfSSL_OPENSSL_config"); + (void)config_name; +} + +int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) +{ + static int x509_idx = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return x509_idx++; +} + +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) { + return x509->ex_data[idx]; + } + #else + (void)x509; + (void)idx; + #endif + return NULL; +} +int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA) + { + x509->ex_data[idx] = data; + return SSL_SUCCESS; + } + #else + (void)x509; + (void)idx; + (void)data; + #endif + return SSL_FAILURE; +} +int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_digest"); + + if (name == NULL || type == NULL) + return SSL_FAILURE; + + return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName, + name->fullName.fullNameLen, md, len, type, NULL); +} + +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); + + if (ctx == NULL) + return 0; + + return ctx->timeout; +} + +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); + + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; + + ctx->ecdhCurveOID = ecdh->group->curve_oid; + + return SSL_SUCCESS; +} +#endif + +/* Assumes that the session passed in is from the cache. */ +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + /* Don't remove session just timeout session. */ + s->timeout = 0; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->rem_sess_cb != NULL) + ctx->rem_sess_cb(ctx, s); +#endif + + return 0; +} + +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_wbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} + +int wolfSSL_SSL_do_handshake(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); + + if (s == NULL) + return SSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return wolfSSL_connect(s); + return wolfSSL_accept(s); +} + +int wolfSSL_SSL_in_init(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + if (s == NULL) + return SSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return s->options.connectState < SECOND_REPLY_DONE; + return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} + +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) +{ + WOLFSSL_SESSION *session; + + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); + + if (ssl == NULL) { + return NULL; + } + + session = wolfSSL_get_session((WOLFSSL*)ssl); + +#ifdef HAVE_EXT_CACHE + ((WOLFSSL*)ssl)->extSession = session; +#endif + + return session; +} + +int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + int ret; + DecodedCert dCert; + + WOLFSSL_ENTER("wolfSSL_X509_check_host"); + + /* flags and peername not needed for Nginx. */ + (void)flags; + (void)peername; + + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) + return SSL_FAILURE; + + ret = CheckHostName(&dCert, (char *)chk, chklen); + FreeDecodedCert(&dCert); + if (ret != 0) + return SSL_FAILURE; + return SSL_SUCCESS; +} + +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) +{ + static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + int i; + word32 j; + word32 len = 0; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); + + if (bp == NULL || a == NULL) + return SSL_FAILURE; + + /* Skip ASN.1 INTEGER (type) byte. */ + i = 1; + /* When indefinte length, can't determine length with data available. */ + if (a->data[i] == 0x80) + return 0; + /* One length byte if less than 0x80. */ + if (a->data[i] < 0x80) + len = a->data[i++]; + /* Multiple length byte if greater than 0x80. */ + else if (a->data[i] > 0x80) { + switch (a->data[i++] - 0x80) { + case 4: + len |= a->data[i++] << 24; + FALL_THROUGH; + case 3: + len |= a->data[i++] << 16; + FALL_THROUGH; + case 2: + len |= a->data[i++] << 8; + FALL_THROUGH; + case 1: + len |= a->data[i++]; + break; + default: + /* Not supporting greater than 4 bytes of length. */ + return 0; + } + } + + /* Zero length integer is the value zero. */ + if (len == 0) { + wolfSSL_BIO_write(bp, "00", 2); + return 2; + } + + /* Don't do negative - just write out every byte. */ + for (j = 0; j < len; i++,j++) { + wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1); + wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1); + } + + /* Two nibbles written for each byte. */ + return len * 2; +} + + +#ifdef HAVE_SESSION_TICKET +/* Expected return values from implementations of OpenSSL ticket key callback. + */ +#define TICKET_KEY_CB_RET_FAILURE -1 +#define TICKET_KEY_CB_RET_NOT_FOUND 0 +#define TICKET_KEY_CB_RET_OK 1 +#define TICKET_KEY_CB_RET_RENEW 2 + +/* The ticket key callback as used in OpenSSL is stored here. */ +static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; + +/* Implementation of session ticket encryption/decryption using OpenSSL + * callback to initialize the cipher and HMAC. + * + * ssl The SSL/TLS object. + * keyName The key name - used to identify the key to be used. + * iv The IV to use. + * mac The MAC of the encrypted data. + * enc Encrypt ticket. + * encTicket The ticket data. + * encTicketLen The length of the ticket data. + * encLen The encrypted/decrypted ticket length - output length. + * ctx Ignored. Application specific data. + * returns WOLFSSL_TICKET_RET_OK to indicate success, + * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and + * WOLFSSL_TICKET_RET_FATAL on error. + */ +static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) +{ + byte digest[MAX_DIGEST_SIZE]; + WOLFSSL_EVP_CIPHER_CTX evpCtx; + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + + (void)ctx; + + if (ticketKeyCb == NULL) + return WOLFSSL_TICKET_RET_FATAL; + + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + /* Initialize the cipher and HMAC. */ + res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) + return WOLFSSL_TICKET_RET_FATAL; + + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of encrypted data. */ + encTicketLen += len; + *encLen = encTicketLen; + + /* HMAC the encrypted data into the parameter 'mac'. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz); + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz); + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; + + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of decrypted data. */ + *encLen = encTicketLen + len; + } + + ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE : + WOLFSSL_TICKET_RET_OK; +end: + return ret; +} + +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns SSL_SUCCESS to indicate success. + */ +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +{ + /* Store callback in a global. */ + ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + + return SSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) +{ + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} + +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} + +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return SSL_FAILURE; + + ssl->url = url; + return SSL_SUCCESS; +} + +static INLINE void ato24(const byte* c, word32* u24) +{ + *u24 = (c[0] << 16) | (c[1] << 8) | c[2]; +} + +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, STACK_OF(X509)** chain) +{ + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; + + if (ctx == NULL || chain == NULL) { + chain = NULL; + return SSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return SSL_SUCCESS; + } + + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return SSL_SUCCESS; + } + + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + return SSL_FAILURE; + node->next = NULL; + + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; + + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx, + length); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return SSL_FAILURE; + } + idx += length; + + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } + + last = node; + } + + ctx->x509Chain = *chain; + + return SSL_SUCCESS; +} + +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*cb)(WOLFSSL*, void*)) +{ + if (ctx == NULL || ctx->cm == NULL) + return SSL_FAILURE; + + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); + + if (ctx->cm->ocsp_stapling == NULL) + return SSL_FAILURE; + + ctx->cm->ocsp_stapling->statusCb = cb; + return SSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* node; + Signer* ca = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + if (issuer == NULL || ctx == NULL || x == NULL) + return SSL_FATAL_ERROR; + + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) { + *issuer = x; + return SSL_SUCCESS; + } + } + } + + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return SSL_FAILURE; +#endif + + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(ctx->store->cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(ctx->store->cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(ctx->store->cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ca == NULL) + return SSL_FAILURE; + + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return SSL_FAILURE; + + /* Create an empty certificate as CA doesn't have a certificate. */ + XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509)); + /* TODO: store the full certificate and dup when required. */ + + /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ + + return SSL_SUCCESS; +} + +void wolfSSL_X509_email_free(STACK_OF(WOLFSSL_STRING) *sk) +{ + WOLFSSL_STACK *curr; + + while (sk != NULL) { + curr = sk; + sk = sk->next; + + XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) +{ + WOLFSSL_STACK *list = NULL; + + if (x->authInfoSz == 0) + return NULL; + + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; + + list->data.string = (char*)x->authInfo; + list->next = NULL; + + return list; +} + +int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject) +{ + WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject); + WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer); + + if (issuerName == NULL || subjectName == NULL) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + /* Literal matching of encoded names and key ids. */ + if (issuerName->sz != subjectName->sz || + XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + + if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) { + if (subject->authKeyIdSz != issuer->subjKeyIdSz || + XMEMCMP(subject->authKeyId, issuer->subjKeyId, + issuer->subjKeyIdSz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + } + + return X509_V_OK; +} + +WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) +{ + return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length); +} + +char* wolfSSL_sk_WOLFSSL_STRING_value(STACK_OF(WOLFSSL_STRING)* strings, + int idx) +{ + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; +} +#endif /* HAVE_OCSP */ + +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) +{ + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; + } +} + +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) +{ + unsigned int i, j; + byte lenIn, lenClient; + + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; + + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; + + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } + + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} + +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + if (ctx != NULL) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; + } +} + +void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char + **out, + unsigned int *outlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); +} + +void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); +} + +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len) +{ + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); +} +#endif /* HAVE_ALPN */ + +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#ifdef OPENSSL_EXTRA +int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback"); + (void)ctx; + (void)cb; + return SSL_FAILURE; +} +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) +{ + WOLFSSL_STUB("SSL_set_msg_callback"); + (void)ssl; + (void)cb; + return SSL_FAILURE; +} +int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg"); + (void)ctx; + (void)arg; + return SSL_FAILURE; +} +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) +{ + WOLFSSL_STUB("SSL_set_msg_callback_arg"); + (void)ssl; + (void)arg; + return SSL_FAILURE; +} +#endif + #endif /* WOLFCRYPT_ONLY */ diff --git a/src/tls.c b/src/tls.c old mode 100644 new mode 100755 index c0ca6c151..df8f7c5b5 --- a/src/tls.c +++ b/src/tls.c @@ -40,6 +40,10 @@ #include #endif +#ifdef HAVE_CURVE25519 + #include +#endif + #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #include @@ -47,6 +51,8 @@ #ifdef HAVE_QSH static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name); +#endif +#if defined(HAVE_NTRU) || defined(HAVE_QSH) static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type); #endif @@ -66,23 +72,13 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - #ifdef WOLFSSL_SHA384 #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE #else #define P_HASH_MAX_SIZE SHA256_DIGEST_SIZE #endif + /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ static int p_hash(byte* result, word32 resLen, const byte* secret, word32 secLen, const byte* seed, word32 seedLen, int hash) @@ -157,36 +153,41 @@ static int p_hash(byte* result, word32 resLen, const byte* secret, lastTime = times - 1; - if ((ret = wc_HmacSetKey(hmac, hash, secret, secLen)) == 0) { - if ((ret = wc_HmacUpdate(hmac, seed, seedLen)) == 0) { /* A0 = seed */ - if ((ret = wc_HmacFinal(hmac, previous)) == 0) { /* A1 */ - for (i = 0; i < times; i++) { + ret = wc_HmacInit(hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(hmac, hash, secret, secLen); + if (ret == 0) + ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */ + if (ret == 0) + ret = wc_HmacFinal(hmac, previous); /* A1 */ + if (ret == 0) { + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, seed, seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&result[idx], current, + min(lastLen, P_HASH_MAX_SIZE)); + else { + XMEMCPY(&result[idx], current, len); + idx += len; ret = wc_HmacUpdate(hmac, previous, len); if (ret != 0) break; - ret = wc_HmacUpdate(hmac, seed, seedLen); + ret = wc_HmacFinal(hmac, previous); if (ret != 0) break; - ret = wc_HmacFinal(hmac, current); - if (ret != 0) - break; - - if ((i == lastTime) && lastLen) - XMEMCPY(&result[idx], current, - min(lastLen, P_HASH_MAX_SIZE)); - else { - XMEMCPY(&result[idx], current, len); - idx += len; - ret = wc_HmacUpdate(hmac, previous, len); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, previous); - if (ret != 0) - break; - } } } } + wc_HmacFree(hmac); } ForceZero(previous, P_HASH_MAX_SIZE); @@ -345,7 +346,6 @@ static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, return ret; } - #ifdef WOLFSSL_SHA384 #define HSHASH_SZ SHA384_DIGEST_SIZE #else @@ -399,21 +399,29 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { int ret; const byte* side; - byte handshake_hash[HSHASH_SZ]; + byte* handshake_hash; word32 hashSz = HSHASH_SZ; + /* using allocate here to allow async hardware to use buffer directly */ + handshake_hash = (byte*)XMALLOC(hashSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (handshake_hash == NULL) + return MEMORY_E; + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) - return ret; + if (ret == 0) { + if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; - if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) - side = tls_client; - else - side = tls_server; + ret = PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, + SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + } - return PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, - SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, - IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; } @@ -450,6 +458,21 @@ ProtocolVersion MakeTLSv1_2(void) return pv; } +#ifdef WOLFSSL_TLS13 +/* The TLS v1.3 protocol version. + * + * returns the protocol version data for TLS v1.3. + */ +ProtocolVersion MakeTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + + return pv; +} +#endif + #ifdef HAVE_EXTENDED_MASTER static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = @@ -544,20 +567,27 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) { int ret; #ifdef HAVE_EXTENDED_MASTER - byte handshake_hash[HSHASH_SZ]; - word32 hashSz = HSHASH_SZ; - if (ssl->options.haveEMS) { + byte* handshake_hash; + word32 hashSz = HSHASH_SZ; + + handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (handshake_hash == NULL) + return MEMORY_E; ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) + if (ret < 0) { + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; + } ret = wolfSSL_MakeTlsExtendedMasterSecret( ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm); + + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); } else #endif ret = wolfSSL_MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, @@ -642,7 +672,19 @@ static INLINE void c24to32(const word24 u24, word32* u32) *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; } #endif + +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +/* Convert opaque data to a 32-bit unsigned integer. + * + * c The opaque data holding a 32-bit integer. + * u32 The 32-bit unsigned integer. + */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} #endif +#endif /* HAVE_TLS_EXTENSIONS */ /* convert 32 bit integer to opaque */ static INLINE void c32toa(word32 u32, byte* c) @@ -788,7 +830,7 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int content, int verify) { Hmac hmac; - int ret; + int ret = 0; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; if (ssl == NULL) @@ -801,21 +843,22 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); - ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); - if (ret != 0) - return ret; - ret = wc_HmacUpdate(&hmac, in, sz); /* content */ - if (ret != 0) - return ret; - ret = wc_HmacFinal(&hmac, digest); + ret = wc_HmacInit(&hmac, NULL, ssl->devId); if (ret != 0) return ret; - return 0; + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, verify), ssl->specs.hash_size); + if (ret == 0) { + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, in, sz); /* content */ + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + } + wc_HmacFree(&hmac); + + return ret; } #ifdef HAVE_TLS_EXTENSIONS @@ -871,12 +914,16 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) /** Checks if a specific light (tls extension) is not set in the semaphore. */ #define IS_OFF(semaphore, light) \ - ((semaphore)[(light) / 8] ^ (byte) (0x01 << ((light) % 8))) + (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8))))) /** Turn on a specific light (tls extension) in the semaphore. */ #define TURN_ON(semaphore, light) \ ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) +/** Turn off a specific light (tls extension) in the semaphore. */ +#define TURN_OFF(semaphore, light) \ + ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8))) + /** Creates a new extension. */ static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) { @@ -1106,23 +1153,42 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, TLSX *extension; ALPN *alpn = NULL, *list; + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) extension = TLSX_Find(ssl->ctx->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ssl->alpnSelect != NULL) { + const byte* out; + unsigned char outLen; + + if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size, + ssl->alpnSelectArg) == 0) { + WOLFSSL_MSG("ALPN protocol match"); + if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) + == SSL_SUCCESS) { + if (extension == NULL) { + extension = TLSX_Find(ssl->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + } + } + } + } +#endif + if (extension == NULL || extension->data == NULL) { WOLFSSL_MSG("No ALPN extensions not used or bad"); return isRequest ? 0 /* not using ALPN */ : BUFFER_ERROR; /* unexpected ALPN response */ } - if (OPAQUE16_LEN > length) - return BUFFER_ERROR; - - ato16(input, &size); - offset += OPAQUE16_LEN; - /* validating alpn list length */ if (length != OPAQUE16_LEN + size) return BUFFER_ERROR; @@ -1382,7 +1448,7 @@ static word16 TLSX_SNI_GetSize(SNI* list) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length += XSTRLEN((char*)sni->data.host_name); + length += (word16)XSTRLEN((char*)sni->data.host_name); break; } } @@ -1404,7 +1470,7 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - length = XSTRLEN((char*)sni->data.host_name); + length = (word16)XSTRLEN((char*)sni->data.host_name); c16toa(length, output + offset); /* sni length */ offset += OPAQUE16_LEN; @@ -1525,6 +1591,13 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, switch(type) { case WOLFSSL_SNI_HOST_NAME: { int matchStat; +#ifdef WOLFSSL_TLS13 + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (sni->status != 0) + break; +#endif byte matched = cacheOnly || ((XSTRLEN(sni->data.host_name) == size) && (XSTRNCMP(sni->data.host_name, @@ -1616,7 +1689,7 @@ static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); + TLSX* extension; SNI* sni = NULL; if (extensions == NULL || data == NULL) @@ -1625,6 +1698,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL) return MEMORY_E; + extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); if (!extension) { int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); if (ret != 0) { @@ -1666,8 +1740,10 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - *data = sni->data.host_name; - return XSTRLEN((char*)*data); + if (data) { + *data = sni->data.host_name; + return (word16)XSTRLEN((char*)*data); + } } } @@ -2055,7 +2131,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, /* request extensions */ if (csr->request.ocsp.nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr->request.ocsp, output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2084,20 +2160,21 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (!csr) { /* look at context level */ - extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); - csr = extension ? extension->data : NULL; + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; if (!csr) return BUFFER_ERROR; /* unexpected extension */ /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, - csr->status_type, csr->options, ssl->heap); + csr->status_type, csr->options, ssl->heap, + ssl->devId); if (ret != SSL_SUCCESS) return ret; @@ -2106,7 +2183,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* propagate nonce */ if (csr->request.ocsp.nonceSz) { OcspRequest* request = - TLSX_CSR_GetRequest(ssl->extensions); + (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); if (request) { XMEMCPY(request->nonce, csr->request.ocsp.nonce, @@ -2159,6 +2236,10 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } break; + + /* unknown status type */ + default: + return 0; } /* if using status_request and already sending it, skip this one */ @@ -2169,7 +2250,7 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, - 0, ssl->heap); + 0, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; /* throw error */ @@ -2185,7 +2266,8 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; int ret = 0; if (csr) { @@ -2215,7 +2297,8 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) void* TLSX_CSR_GetRequest(TLSX* extensions) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (csr) { switch (csr->status_type) { @@ -2231,14 +2314,19 @@ void* TLSX_CSR_GetRequest(TLSX* extensions) int TLSX_CSR_ForceRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); - CertificateStatusRequest* csr = extension ? extension->data : NULL; + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + csr->request.ocsp.ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr->request.ocsp, NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2248,7 +2336,7 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { CertificateStatusRequest* csr = NULL; int ret = 0; @@ -2271,11 +2359,13 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, MAX_OCSP_NONCE_SZ) == 0) csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; @@ -2401,7 +2491,7 @@ static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, length = 0; if (csr2->request.ocsp[0].nonceSz) - length = EncodeOcspRequestExtensions( + length = (word16)EncodeOcspRequestExtensions( &csr2->request.ocsp[0], output + offset + OPAQUE16_LEN, OCSP_NONCE_EXT_SZ); @@ -2433,14 +2523,14 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, if (!isRequest) { #ifndef NO_WOLFSSL_CLIENT TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data - : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; if (!csr2) { /* look at context level */ - extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); - csr2 = extension ? extension->data : NULL; + csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; if (!csr2) return BUFFER_ERROR; /* unexpected extension */ @@ -2448,7 +2538,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* enable extension at ssl level */ for (; csr2; csr2 = csr2->next) { ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - csr2->status_type, csr2->options, ssl->heap); + csr2->status_type, csr2->options, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; @@ -2459,7 +2549,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* propagate nonce */ if (csr2->request.ocsp[0].nonceSz) { OcspRequest* request = - TLSX_CSR2_GetRequest(ssl->extensions, + (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, csr2->status_type, 0); if (request) { @@ -2474,7 +2564,6 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, break; } } - } ssl->status_request_v2 = 1; @@ -2548,7 +2637,7 @@ static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, /* accept the first good status_type and return */ ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, - status_type, 0, ssl->heap); + status_type, 0, ssl->heap, ssl->devId); if (ret != SSL_SUCCESS) return ret; /* throw error */ @@ -2567,7 +2656,8 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, void* heap) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; int ret = 0; for (; csr2; csr2 = csr2->next) { @@ -2576,7 +2666,7 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, if (!isPeer || csr2->requests != 0) break; - /* followed by */ + FALL_THROUGH; /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: { if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { @@ -2602,13 +2692,15 @@ int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, } } + (void)cert; return ret; } -void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; for (; csr2; csr2 = csr2->next) { if (csr2->status_type == status_type) { @@ -2618,8 +2710,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) case WOLFSSL_CSR2_OCSP_MULTI: /* requests are initialized in the reverse order */ - return index < csr2->requests - ? &csr2->request.ocsp[csr2->requests - index - 1] + return idx < csr2->requests + ? &csr2->request.ocsp[csr2->requests - idx - 1] : NULL; break; } @@ -2632,7 +2724,8 @@ void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte index) int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); - CertificateStatusRequestItemV2* csr2 = extension ? extension->data : NULL; + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; /* forces only the first one */ if (csr2) { @@ -2641,9 +2734,13 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + csr2->request.ocsp[0].ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr2->request.ocsp[0], NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2653,7 +2750,7 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) } int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, - byte options, void* heap) + byte options, void* heap, int devId) { TLSX* extension = NULL; CertificateStatusRequestItemV2* csr2 = NULL; @@ -2683,11 +2780,13 @@ int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, heap) == 0) { -#else - if (wc_InitRng(&rng) == 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce, MAX_OCSP_NONCE_SZ) == 0) csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ; @@ -2780,7 +2879,8 @@ static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) for (i = 0; i < ssl->suites->suiteSz; i+= 2) if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE) + ssl->suites->suites[i] == CHACHA_BYTE || + ssl->suites->suites[i] == TLS13_BYTE) return; /* turns semaphore on to avoid sending this extension. */ @@ -2856,18 +2956,46 @@ static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, return 0; } +#ifdef WOLFSSL_TLS13 +/* Searches the supported groups extension for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) +{ + TLSX* extension; + EllipticCurve* curve = NULL; + + if ((extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS)) == NULL) + return 0; + + for (curve = (EllipticCurve*)extension->data; curve; curve = curve->next) { + if (curve->name == name) + return 1; + } + return 0; +} +#endif /* WOLFSSL_TLS13 */ + int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { TLSX* extension = (first == ECC_BYTE || first == CHACHA_BYTE) ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) : NULL; EllipticCurve* curve = NULL; word32 oid = 0; + word32 defOid = 0; + word32 defSz = 80; /* Maximum known curve size is 66. */ + word32 nextOid = 0; + word32 nextSz = 80; /* Maximum known curve size is 66. */ + word32 currOid = ssl->ecdhCurveOID; + int ephmSuite = 0; word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ int sig = 0; /* validate signature */ int key = 0; /* validate key */ (void)oid; - (void)octets; if (!extension) return 1; /* no suite restriction */ @@ -2880,155 +3008,234 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { switch (curve->name) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R1: + oid = ECC_SECP160R1_OID; + octets = 20; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 - case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R2: + oid = ECC_SECP160R2_OID; + octets = 20; + break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160K1: + oid = ECC_SECP160K1_OID; + octets = 20; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192R1: + oid = ECC_SECP192R1_OID; + octets = 24; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192K1: + oid = ECC_SECP192K1_OID; + octets = 24; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224R1: + oid = ECC_SECP224R1_OID; + octets = 28; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224K1: + oid = ECC_SECP224K1_OID; + octets = 28; + break; #endif /* HAVE_ECC_KOBLITZ */ #endif - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256R1: + oid = ECC_SECP256R1_OID; + octets = 32; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256K1: + oid = ECC_SECP256K1_OID; + octets = 32; + break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_BRAINPOOLP256R1: + oid = ECC_BRAINPOOLP256R1_OID; + octets = 32; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_SECP384R1: + oid = ECC_SECP384R1_OID; + octets = 48; + break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_BRAINPOOLP384R1: + oid = ECC_BRAINPOOLP384R1_OID; + octets = 48; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; + case WOLFSSL_ECC_BRAINPOOLP512R1: + oid = ECC_BRAINPOOLP512R1_OID; + octets = 64; + break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; octets = 66; break; + case WOLFSSL_ECC_SECP521R1: + oid = ECC_SECP521R1_OID; + octets = 66; + break; #endif /* !NO_ECC_SECP */ #endif default: continue; /* unsupported curve */ } + /* Set default Oid */ + if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { + defOid = oid; + defSz = octets; + } + + if (currOid == 0 && ssl->eccTempKeySz == octets) + currOid = oid; + if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { + nextOid = oid; + nextSz = octets; + } + if (first == ECC_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: - case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: - case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + sig |= ssl->pkCurveOID == oid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_ECDSA */ - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: - sig |= ssl->pkCurveOID == oid; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_ECDSA */ + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + sig |= ssl->pkCurveOID == oid; + key |= ssl->pkCurveOID == oid; + break; #endif /* WOLFSSL_STATIC_DH */ #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifdef WOLFSSL_STATIC_DH - /* ECDH_RSA */ - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - case TLS_ECDH_RSA_WITH_RC4_128_SHA: - case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: - case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: - sig = 1; - key |= ssl->pkCurveOID == oid; - break; + /* ECDH_RSA */ + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->pkCurveOID == oid; + break; #endif /* WOLFSSL_STATIC_DH */ #endif - default: - sig = 1; - key = 1; - break; - } + default: + sig = 1; + key = 1; + break; + } } /* ChaCha20-Poly1305 ECC cipher suites */ if (first == CHACHA_BYTE) { - switch (second) { - /* ECDHE_ECDSA */ - case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; - break; + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig |= ssl->pkCurveOID == oid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #ifndef NO_RSA - /* ECDHE_RSA */ - case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : - case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : - sig = 1; - key |= ssl->eccTempKeySz == octets; - break; + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; #endif - default: - sig = 1; - key = 1; - break; - } + default: + sig = 1; + key = 1; + break; + } } } + /* Choose the default if it is at the required strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) { + key = 1; + ssl->ecdhCurveOID = defOid; + } + /* Choose any curve at the required strength. */ + if (ssl->ecdhCurveOID == 0) { + key = 1; + ssl->ecdhCurveOID = currOid; + } + /* Choose the default if it is at the next highest strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == nextSz) + ssl->ecdhCurveOID = defOid; + /* Choose any curve at the next highest strength. */ + if (ssl->ecdhCurveOID == 0) + ssl->ecdhCurveOID = nextOid; + /* No curve and ephemeral ECC suite requires a matching curve. */ + if (ssl->ecdhCurveOID == 0 && ephmSuite) + key = 0; + return sig && key; } @@ -3036,7 +3243,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); + TLSX* extension; EllipticCurve* curve = NULL; int ret = 0; @@ -3046,6 +3253,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) if ((ret = TLSX_EllipticCurve_Append(&curve, name, heap)) != 0) return ret; + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); if (!extension) { if ((ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap)) != 0) { @@ -3289,10 +3497,12 @@ int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) #ifdef HAVE_SESSION_TICKET +#ifndef NO_WOLFSSL_CLIENT static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) { TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); - SessionTicket* ticket = extension ? extension->data : NULL; + SessionTicket* ticket = extension ? + (SessionTicket*)extension->data : NULL; if (ticket) { /* TODO validate ticket timeout here! */ @@ -3302,6 +3512,7 @@ static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) } } } +#endif /* NO_WOLFSSL_CLIENT */ static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) @@ -3336,7 +3547,9 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, if (length != 0) return BUFFER_ERROR; +#ifndef NO_WOLFSSL_CLIENT ssl->expect_session_ticket = 1; +#endif } #ifndef NO_WOLFSSL_SERVER else { @@ -3434,19 +3647,19 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) return SSL_SUCCESS; } -#define STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest -#define STK_GET_SIZE TLSX_SessionTicket_GetSize -#define STK_WRITE TLSX_SessionTicket_Write -#define STK_PARSE TLSX_SessionTicket_Parse -#define STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) +#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest +#define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize +#define WOLF_STK_WRITE TLSX_SessionTicket_Write +#define WOLF_STK_PARSE TLSX_SessionTicket_Parse +#define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) #else -#define STK_FREE(a, b) -#define STK_VALIDATE_REQUEST(a) -#define STK_GET_SIZE(a, b) 0 -#define STK_WRITE(a, b, c) 0 -#define STK_PARSE(a, b, c, d) 0 +#define WOLF_STK_FREE(a, b) +#define WOLF_STK_VALIDATE_REQUEST(a) +#define WOLF_STK_GET_SIZE(a, b) 0 +#define WOLF_STK_WRITE(a, b, c) 0 +#define WOLF_STK_PARSE(a, b, c, d) 0 #endif /* HAVE_SESSION_TICKET */ @@ -3454,10 +3667,12 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) /* Quantum-Safe-Hybrid */ /******************************************************************************/ -#ifdef HAVE_QSH +#if defined(HAVE_NTRU) && defined(HAVE_QSH) static WC_RNG* rng; static wolfSSL_Mutex* rngMutex; +#endif +#ifdef HAVE_QSH static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap) { QSHScheme* current; @@ -4044,6 +4259,2097 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, #endif /* HAVE_QSH */ +/******************************************************************************/ +/* Supported Versions */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SupportedVersions extension's data. + * + * data The SSL/TLS object. + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SupportedVersions_GetSize(byte* data) +{ + (void)data; + + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; + +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif + + return OPAQUE8_LEN + cnt * OPAQUE16_LEN; +} + +/* Writes the SupportedVersions extension into the buffer. + * + * data The SSL/TLS object. + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SupportedVersions_Write(byte* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + ProtocolVersion pv = ssl->ctx->method->version; + int i; + /* TLS v1.2 and TLS v1.3 */ + int cnt = 2; + +#ifndef NO_OLD_TLS + /* TLS v1 and TLS v1.1 */ + cnt += 2; +#endif + + *(output++) = cnt * OPAQUE16_LEN; + for (i = 0; i < cnt; i++) { + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (pv.minor - i == TLSv1_3_MINOR) { + /* The TLS draft major number. */ + *(output++) = TLS_DRAFT_MAJOR; + /* Version of draft supported. */ + *(output++) = TLS_DRAFT_MINOR; + continue; + } + + *(output++) = pv.major; + *(output++) = pv.minor - i; + } + + return OPAQUE8_LEN + cnt * OPAQUE16_LEN; +} + +/* Parse the SupportedVersions extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SupportedVersions_Parse(WOLFSSL *ssl, byte* input, + word16 length) +{ + ProtocolVersion pv = ssl->ctx->method->version; + int i; + int ret = 0; + int len; + + /* Must contain a length and at least one version. */ + if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1) + return BUFFER_ERROR; + + len = *input; + + /* Protocol version array must fill rest of data. */ + if (length != OPAQUE8_LEN + len) + return BUFFER_ERROR; + + input++; + + /* Find first match. */ + for (i = 0; i < len; i += OPAQUE16_LEN) { + /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + if (input[i] == TLS_DRAFT_MAJOR && + input[i + OPAQUE8_LEN] == TLS_DRAFT_MINOR) { + ssl->version.minor = TLSv1_3_MINOR; + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; + } + + if (input[i] != pv.major) + continue; + +#ifndef NO_OLD_TLS + if (input[i + OPAQUE8_LEN] == TLSv1_MINOR || + input[i + OPAQUE8_LEN] == TLSv1_1_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + break; + } +#endif + if (input[i + OPAQUE8_LEN] == TLSv1_2_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; + } + if (input[i + OPAQUE8_LEN] == TLSv1_3_MINOR) { + ssl->version.minor = input[i + OPAQUE8_LEN]; + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, input, + ssl->heap); + break; + } + } + + return ret; +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap); +} + +#define SV_GET_SIZE TLSX_SupportedVersions_GetSize +#define SV_WRITE TLSX_SupportedVersions_Write +#define SV_PARSE TLSX_SupportedVersions_Parse + +#else + +#define SV_GET_SIZE(a) 0 +#define SV_WRITE(a, b) 0 +#define SV_PARSE(a, b, c) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Sugnature Algorithms */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SignatureAlgorithms_GetSize(byte* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + int cnt = 0; + + (void)data; + +#ifndef NO_RSA + #ifndef NO_SHA1 + cnt++; + #endif + #ifndef NO_SHA256 + cnt++; + #endif + #ifdef HAVE_SHA384 + cnt++; + #endif + #ifdef HAVE_SHA512 + cnt++; + #endif + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_3(ssl->version)) { + #ifndef NO_SHA256 + cnt++; + #endif + #ifdef HAVE_SHA384 + cnt++; + #endif + #ifdef HAVE_SHA512 + cnt++; + #endif + } + #endif +#endif + +#ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif + #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif + #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + cnt++; + #endif + #endif +#endif + + return OPAQUE16_LEN + cnt * OPAQUE16_LEN; +} + +/* Writes the SignatureAlgorithms extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithms_Write(byte* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + int idx = OPAQUE16_LEN; + + +#ifndef NO_RSA + #ifndef NO_SHA1 + output[idx++] = 0x02; + output[idx++] = 0x01; + #endif + #ifndef NO_SHA256 + output[idx++] = 0x04; + output[idx++] = 0x01; + #endif + #ifdef HAVE_SHA384 + output[idx++] = 0x05; + output[idx++] = 0x01; + #endif + #ifdef HAVE_SHA512 + output[idx++] = 0x06; + output[idx++] = 0x01; + #endif + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_3(ssl->version)) { + #ifndef NO_SHA256 + output[idx++] = 0x08; + output[idx++] = 0x04; + #endif + #ifdef HAVE_SHA384 + output[idx++] = 0x08; + output[idx++] = 0x05; + #endif + #ifdef HAVE_SHA512 + output[idx++] = 0x08; + output[idx++] = 0x06; + #endif + } + #endif +#endif + +#ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x04; + output[idx++] = 0x03; + #endif + #endif + #if !defined(NO_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x05; + output[idx++] = 0x03; + #endif + #endif + #if !defined(NO_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + output[idx++] = 0x06; + output[idx++] = 0x03; + #endif + #endif +#endif + + output[0] = (idx - OPAQUE16_LEN) >> 8; + output[1] = idx - OPAQUE16_LEN; + + return idx; +} + +/* Parse the SignatureAlgorithms extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, + word16 length) +{ + int ret = 0; + word16 len; + + (void)ssl; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* Ignore for now. */ + + return ret; +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap); +} + +#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize +#define SA_WRITE TLSX_SignatureAlgorithms_Write +#define SA_PARSE TLSX_SignatureAlgorithms_Parse + +#else + +#define SA_GET_SIZE(a) 0 +#define SA_WRITE(a, b) 0 +#define SA_PARSE(a, b, c) 0 + +#endif + +/******************************************************************************/ +/* Key Share */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#ifndef NO_DH +/* Create a key share entry using named Diffie-Hellman parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData; + void* key = NULL; + word32 keySz; + word32 dataSz; + const DhParams* params; + DhKey dhKey; + + /* TODO: [TLS13] The key size should come from wolfcrypt. */ + /* Pick the parameters from the named group. */ + switch (kse->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + keySz = 29; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + keySz = 34; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + keySz = 39; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + keySz = 46; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + keySz = 52; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Allocate space for the public key. */ + dataSz = params->p_len; + keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + ret = MEMORY_E; + goto end; + } + /* Allocate space for the private key. */ + key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_TLSX); + if (key == NULL) { + ret = MEMORY_E; + goto end; + } + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) + goto end; + + /* Generate a new key pair. */ + ret = wc_DhGenerateKeyPair(&dhKey, ssl->rng, key, &keySz, keyData, &dataSz); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + if (params->p_len != dataSz) { + /* Pad the front of the key data with zeros. */ + XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); + XMEMSET(keyData, 0, params->p_len - dataSz); + } + + kse->ke = keyData; + kse->keLen = params->p_len; + kse->key = key; + kse->keyLen = keySz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(keyData, params->p_len); +#endif + +end: + + wc_FreeDhKey(&dhKey); + + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_TLSX); + if (key != NULL) + XFREE(key, ssl->heap, DYNAMIC_TYPE_TLSX); + } + + return ret; +} +#endif + +#ifndef NO_ECC +/* Create a key share entry using named elliptic curve parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; + byte* keyData = NULL; + word32 dataSize; + word32 keySize; + ecc_key* eccKey = NULL; + word16 curveId; + + /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ + /* Translate named group to a curve id. */ + switch (kse->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + keySize = 32; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + keySize = 48; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + keySize = 66; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key; + /* Allocate an ECC key to hold private key. */ + key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_TLSX); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + dataSize = keySize = 32; + + /* Make an ECC key. */ + ret = wc_curve25519_init(key); + if (ret != 0) + goto end; + ret = wc_curve25519_make_key(ssl->rng, keySize, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + + goto end; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + dataSize = keySize = 56; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + /* Allocate an ECC key to hold private key. */ + eccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_TLSX); + if (eccKey == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* Make an ECC key. */ + ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); + if (ret != 0) + goto end; + ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->ke = keyData; + kse->keLen = dataSize; + kse->key = eccKey; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (eccKey != NULL) + XFREE(eccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_TLSX); + } + return ret; +} +#endif /* !NO_ECC */ + +/* Generate a secret/key using the key share entry. + * + * ssl The SSL/TLS object. + * kse The key share entry holding peer data. + */ +static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) +{ + /* Named FFHE groups have a bit set to identify them. */ + if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) + return TLSX_KeyShare_GenDhKey(ssl, kse); + return TLSX_KeyShare_GenEccKey(ssl, kse); +} + +/* Free the key share dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) +{ + KeyShareEntry* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->key, heap, DYNAMIC_TYPE_TLSX); + XFREE(current->ke, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded key share extension. + * + * list The linked list of key share extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) +{ + int len = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + /* The named group the server wants to use. */ + if (msgType == hello_retry_request) + return OPAQUE16_LEN; + + /* List of key exchange groups. */ + if (isRequest) + len += OPAQUE16_LEN; + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + len += OPAQUE16_LEN + OPAQUE16_LEN + current->keLen; + } + + return len; +} + +/* Writes the key share extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, + byte msgType) +{ + word16 i = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + if (msgType == hello_retry_request) { + c16toa(list->group, output); + return OPAQUE16_LEN; + } + + /* ClientHello has a list but ServerHello is only the chosen. */ + if (isRequest) + i += OPAQUE16_LEN; + + /* Write out all in the list. */ + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + c16toa(current->group, &output[i]); + i += KE_GROUP_LEN; + c16toa(current->keLen, &output[i]); + i += OPAQUE16_LEN; + XMEMCPY(&output[i], current->ke, current->keLen); + i += current->keLen; + } + /* Write the length of the list if required. */ + if (isRequest) + c16toa(i - OPAQUE16_LEN, output); + + return i; +} + +/* Process the DH key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_DH + int ret; + const DhParams* params; + word16 i; + byte b; + DhKey dhKey; + + switch (keyShareEntry->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return PEER_KEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (params->p_len != keyShareEntry->keLen) + return BUFFER_ERROR; + + /* TODO: [TLS13] move this check down into wolfcrypt. */ + /* Check that public DH key is not 0 or 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= keyShareEntry->ke[i]; + if (b == 0 && (keyShareEntry->ke[i] == 0x00 || + keyShareEntry->ke[i] == 0x01)) { + return PEER_KEY_ERROR; + } + /* Check that public DH key is not mod, mod + 1 or mod - 1. */ + b = 0; + for (i = 0; i < params->p_len - 1; i++) + b |= params->p[i] ^ keyShareEntry->ke[i]; + if (b == 0 && (params->p[i] == keyShareEntry->ke[i] || + params->p[i] - 1 == keyShareEntry->ke[i] || + params->p[i] + 1 == keyShareEntry->ke[i])) { + return PEER_KEY_ERROR; + } + + ret = wc_InitDhKey_ex(&dhKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* Set key */ + ret = wc_DhSetKey(&dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) { + wc_FreeDhKey(&dhKey); + return ret; + } + + /* Derive secret from private key and peer's public key. */ + ret = wc_DhAgree(&dhKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + keyShareEntry->key, keyShareEntry->keyLen, + keyShareEntry->ke, keyShareEntry->keLen); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + + wc_FreeDhKey(&dhKey); + + return ret; +#else + return PEER_KEY_ERROR; +#endif +} + +/* Process the ECC key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_ECC + int ret; + int curveId; + ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* find supported curve */ + switch (keyShareEntry->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + { + curve25519_key* key = (curve25519_key*)keyShareEntry->key; + curve25519_key* peerEccKey; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + peerEccKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_TLSX); + if (peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve25519_init(peerEccKey); + if (ret != 0) + return ret; +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_curve25519_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerEccKey, + EC25519_LITTLE_ENDIAN) != 0) { + return ECC_PEERKEY_ERROR; + } + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ret = wc_curve25519_shared_secret_ex(key, peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + EC25519_LITTLE_ENDIAN); + wc_curve25519_free(peerEccKey); + XFREE(peerEccKey, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + break; + #endif + default: + /* unsupported curve */ + return ECC_PEERKEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId) != 0) { + return ECC_PEERKEY_ERROR; + } + + ssl->arrays->preMasterSz = ENCRYPT_LEN; + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); + } while (ret == WC_PENDING_E); + +#if 0 + /* TODO: Switch to support async here and use: */ + ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side, + #ifdef HAVE_PK_CALLBACKS + ssl->EccSharedSecretCtx + #else + NULL + #endif + ); +#endif + + return ret; +#else + return PEER_KEY_ERROR; +#endif +} + +/* Process the key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_SESSION_TICKET + ssl->session.namedGroup = keyShareEntry->group; +#endif + /* Use Key Share Data from server. */ + if (keyShareEntry->group & NAMED_DH_MASK) + ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry); + else + ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); +#endif + + return ret; +} + +/* Parse an entry of the KeyShare extension. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * kse The new key share entry object. + * returns a positive number to indicate amount of data parsed and a negative + * number on error. + */ +static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length, + KeyShareEntry **kse) +{ + int ret; + word16 group; + word16 keLen; + int offset = 0; + byte* ke; + + if (length < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + /* Named group */ + ato16(&input[offset], &group); + offset += OPAQUE16_LEN; + /* Key exchange data - public key. */ + ato16(&input[offset], &keLen); + offset += OPAQUE16_LEN; + if (keLen < 1 || keLen > length - offset) + return BUFFER_ERROR; + + /* Store a copy in the key share object. */ + ke = XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_TLSX); + 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) + return ret; + + /* Total length of the parsed data. */ + return offset + keLen; +} + +/* Searches the groups sent for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) +{ + TLSX* extension; + KeyShareEntry* list; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return 0; + + list = (KeyShareEntry*)extension->data; + while (list != NULL) { + if (list->group == group) { + return 1; + } + list = list->next; + } + + return 0; +} + +/* Parse the KeyShare extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + KeyShareEntry *keyShareEntry; + + if (msgType == client_hello) { + int offset = 0; + word16 len; + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* ClientHello contains zero or more key share entries. */ + ato16(input, &len); + if (len != length - OPAQUE16_LEN) + return BUFFER_ERROR; + offset += OPAQUE16_LEN; + + while (offset < length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length, + &keyShareEntry); + if (ret < 0) + return ret; + + offset += ret; + } + + ret = 0; + } + else if (msgType == server_hello) { + int len; + + /* ServerHello contains one key share entry. */ + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + if (len != length) + return BUFFER_ERROR; + + /* Not in list sent if there isn't a private key. */ + if (keyShareEntry->key == NULL) + return BAD_KEY_SHARE_DATA; + + /* Process the entry to calculate the secret. */ + ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + } + else if (msgType == hello_retry_request) { + word16 group; + + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Try to use the server's group. */ + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + } + else { + /* Not a message type that is allowed to have this extension. */ + return SANITY_MSG_E; + } + + return ret; +} + +/* Create a new key share entry and put it into the list. + * + * list The linked list of key share entries. + * group The named group. + * heap The memory to allocate with. + * keyShareEntry The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, + KeyShareEntry** keyShareEntry) +{ + KeyShareEntry* kse; + + kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, + DYNAMIC_TYPE_TLSX); + if (kse == NULL) + return MEMORY_E; + + XMEMSET(kse, 0, sizeof(*kse)); + kse->group = group; + + /* Add it to the back and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = kse; + *keyShareEntry = kse; + + return 0; +} + +/* Use the data to create a new key share object in the extensions. + * + * ssl The SSL/TLS object. + * group The named group. + * len The length of the public key data. + * data The public key data. + * kse The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, + KeyShareEntry **kse) +{ + int ret = 0; + TLSX* extension; + KeyShareEntry* keyShareEntry = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the key share entry with this group. */ + keyShareEntry = (KeyShareEntry*)extension->data; + while (keyShareEntry != NULL) { + if (keyShareEntry->group == group) + break; + keyShareEntry = keyShareEntry->next; + } + + /* Create a new key share entry if not found. */ + if (keyShareEntry == NULL) { + ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group, + ssl->heap, &keyShareEntry); + if (ret != 0) + return ret; + } + + if (data != NULL) { + /* Keep the public key data and free when finished. */ + if (keyShareEntry->ke != NULL) + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_TLSX); + keyShareEntry->ke = data; + keyShareEntry->keLen = len; + } + else { + /* Generate a key pair. */ + ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry); + if (ret != 0) + return ret; + } + + if (kse != NULL) + *kse = keyShareEntry; + + return 0; +} + +/* Set an empty Key Share extension. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Empty(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + } + else if (extension->data != NULL) { + TLSX_KeyShare_FreeAll(extension->data, ssl->heap); + extension->data = NULL; + } + + return ret; +} + +/* Returns whether this group is supported. + * + * namedGroup The named group to check. + * returns 1 when supported or 0 otherwise. + */ +static int TLSX_KeyShare_IsSupported(int namedGroup) +{ + switch (namedGroup) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + break; + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + break; + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + break; + #endif + default: + return 0; + } + + return 1; +} + +/* Set a key share that is supported by the client into extensions. + * + * ssl The SSL/TLS object. + * returns BAD_KEY_SHARE_DATA if no supported group has a key share, + * 0 if a supported group has a key share and other values indicate an error. + */ +static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) +{ + int ret; + TLSX* extension; + EllipticCurve* curve = NULL; + + /* Use SupportedGroup's order. */ + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) + curve = (EllipticCurve*)extension->data; + for (; curve != NULL; curve = curve->next) { + if (TLSX_KeyShare_IsSupported(curve->name) && + !TLSX_KeyShare_Find(ssl, curve->name)) { + break; + } + } + if (curve == NULL) + return BAD_KEY_SHARE_DATA; + + /* Delete the old key share data list. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) { + TLSX_KeyShare_FreeAll(extension->data, ssl->heap); + extension->data = NULL; + } + + /* Add in the chosen group. */ + ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); + if (ret != 0) + return ret; + + /* Set extension to be in reponse. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension->resp = 1; + + return 0; +} + +/* Establish the secret based on the key shares received from the client. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Establish(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* clientKSE = NULL; + KeyShareEntry* serverKSE; + KeyShareEntry* list = NULL; + byte* ke; + word16 keLen; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + /* TODO: [TLS13] Server's preference and sending back SupportedGroups */ + /* Use client's preference. */ + for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { + /* Check consistency now - extensions in any order. */ + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + return BAD_KEY_SHARE_DATA; + + /* Check if server supports group. */ + if (TLSX_KeyShare_IsSupported(clientKSE->group)) + break; + } + /* No supported group found - send HelloRetryRequest. */ + if (clientKSE == NULL) { + ret = TLSX_KeyShare_SetSupported(ssl); + /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + if (ret == 0) + return KEY_SHARE_ERROR; + return ret; + } + + list = NULL; + /* Generate a new key pair. */ + ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE); + if (ret != 0) + return ret; + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + return ret; + + /* Move private key to client entry. */ + if (clientKSE->key != NULL) + XFREE(clientKSE->key, ssl->heap, DYNAMIC_TYPE_TLSX); + clientKSE->key = serverKSE->key; + serverKSE->key = NULL; + clientKSE->keyLen = serverKSE->keyLen; + + /* Calculate secret. */ + ret = TLSX_KeyShare_Process(ssl, clientKSE); + if (ret != 0) + return ret; + + /* Swap public keys for sending to client. */ + ke = serverKSE->ke; + keLen = serverKSE->keLen; + serverKSE->ke = clientKSE->ke; + serverKSE->keLen = clientKSE->keLen; + clientKSE->ke = ke; + clientKSE->keLen = keLen; + + extension->resp = 1; + + /* Dispose of temporary server extension. */ + TLSX_KeyShare_FreeAll(list, ssl->heap); + + return 0; +} + +#define KS_FREE_ALL TLSX_KeyShare_FreeAll +#define KS_GET_SIZE TLSX_KeyShare_GetSize +#define KS_WRITE TLSX_KeyShare_Write +#define KS_PARSE TLSX_KeyShare_Parse + +#else + +#define KS_FREE_ALL(a, b) +#define KS_GET_SIZE(a, b) 0 +#define KS_WRITE(a, b, c) 0 +#define KS_PARSE(a, b, c, d) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Pre-Shared Key */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Free the pre-shared key dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap) +{ + PreSharedKey* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded pre shared key extension. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +static word16 TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType) +{ + if (msgType == client_hello) { + /* Length of identities + Length of binders. */ + word16 len = OPAQUE16_LEN + OPAQUE16_LEN; + while (list != NULL) { + /* Each entry has: identity, ticket age and binder. */ + len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN + + OPAQUE8_LEN + list->binderLen; + list = list->next; + } + return len; + } + + if (msgType == server_hello) { + return OPAQUE16_LEN; + } + + return 0; +} + +/* The number of bytes to be written for the binders. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType) +{ + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Length of all binders. */ + len = OPAQUE16_LEN; + while (list != NULL) { + len += OPAQUE8_LEN + list->binderLen; + list = list->next; + } + + return len; +} + +/* Writes the pre-shared key extension into the output buffer - binders only. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType) +{ + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Skip length of all binders. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Binder data length. */ + output[idx++] = current->binderLen; + /* Binder data. */ + XMEMCPY(output + idx, current->binder, current->binderLen); + idx += current->binderLen; + + current = current->next; + } + /* Length of the binders. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + return idx; +} + + +/* Writes the pre-shared key extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType) +{ + if (msgType == client_hello) { + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + /* Write identites only. Binders after HMACing over this. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Identity length */ + c16toa(current->identityLen, output + idx); + idx += OPAQUE16_LEN; + /* Identity data */ + XMEMCPY(output + idx, current->identity, current->identityLen); + idx += current->identityLen; + + /* Obfuscated ticket age. */ + c32toa(current->ticketAge, output + idx); + idx += OPAQUE32_LEN; + + current = current->next; + } + /* Length of the identites. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + /* Don't include binders here. + * The binders are based on the hash of all the ClientHello data up to + * and include the identities written above. + */ + idx += TLSX_PreSharedKey_GetSizeBinders(list, msgType); + + return idx; + } + + if (msgType == server_hello) { + word16 i; + + /* Find the index of the chosen identity. */ + for (i=0; list != NULL && !list->chosen; i++) + list = list->next; + if (list == NULL) + return BUILD_MSG_ERROR; + + /* The index of the identity chosen by the server from the list supplied + * by the client. + */ + c16toa(i, output); + return OPAQUE16_LEN; + } + + return 0; +} + +/* Parse the pre-shared key extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + TLSX* extension; + PreSharedKey* list; + + if (msgType == client_hello) { + int ret; + word16 len; + word16 idx = 0; + + /* Length of identities and of binders. */ + if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identities. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_ID_LEN || length - idx < len) + return BUFFER_E; + + /* Create a pre-shared key object for each identity. */ + while (len > 0) { + byte* identity; + word16 identityLen; + word32 age; + + if (len < OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identity. */ + ato16(input + idx, &identityLen); + idx += OPAQUE16_LEN; + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN) + return BUFFER_E; + /* Cache identity pointer. */ + identity = input + idx; + idx += identityLen; + /* Ticket age. */ + ato32(input + idx, &age); + idx += OPAQUE32_LEN; + + ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, 0, 1, + NULL); + if (ret != 0) + return ret; + + /* Done with this identity. */ + len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; + } + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Length of binders. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_BINDERS_LEN || length - idx < len) + return BUFFER_E; + + /* Set binder for each identity. */ + while (list != NULL && len > 0) { + /* Length of binder */ + list->binderLen = input[idx++]; + if (list->binderLen < SHA256_DIGEST_SIZE || + list->binderLen > MAX_DIGEST_SIZE) + return BUFFER_E; + if (len < OPAQUE8_LEN + list->binderLen) + return BUFFER_E; + + /* Copy binder into static buffer. */ + XMEMCPY(list->binder, input + idx, list->binderLen); + idx += list->binderLen; + + /* Done with binder entry. */ + len -= OPAQUE8_LEN + list->binderLen; + + /* Next identity. */ + list = list->next; + } + if (list != NULL || len != 0) + return BUFFER_E; + + return 0; + } + + if (msgType == server_hello) { + word16 idx; + + /* Index of identity chosen by server. */ + if (length != OPAQUE16_LEN) + return BUFFER_E; + ato16(input, &idx); + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Mark the identity as chosen. */ + for (; list != NULL && idx > 0; idx--) + list = list->next; + if (list == NULL) + return PSK_KEY_ERROR; + list->chosen = 1; + + if (list->resumption) { + /* Check that the session's details are the same as the server's. */ + if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || + ssl->options.cipherSuite != ssl->session.cipherSuite || + ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor ) { + return PSK_KEY_ERROR; + } + } + /* TODO: [TLS13] More checks of consistency. + * the "key_share", and "signature_algorithms" extensions are + * consistent with the indicated ke_modes and auth_modes values + */ + + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new pre-shared key and put it into the list. + * + * list The linked list of pre-shared key. + * identity The identity. + * len The length of the identity data. + * heap The memory to allocate with. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity, + word16 len, void *heap, + PreSharedKey** preSharedKey) +{ + PreSharedKey* psk; + + psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX); + if (psk == NULL) + return MEMORY_E; + XMEMSET(psk, 0, sizeof(*psk)); + + /* Make a copy of the identity data. */ + psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX); + if (psk->identity == NULL) { + XFREE(psk, heap, DYNAMIC_TYPE_TLSX); + return MEMORY_E; + } + XMEMCPY(psk->identity, identity, len); + psk->identityLen = len; + + /* Add it to the end and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = psk; + *preSharedKey = psk; + + return 0; +} + +static INLINE byte GetHmacLength(int hmac) +{ + switch (hmac) { + #ifndef NO_SHA256 + case sha256_mac: + return SHA256_DIGEST_SIZE; + #endif + #ifndef NO_SHA384 + case sha384_mac: + return SHA384_DIGEST_SIZE; + #endif + #ifndef NO_SHA512 + case sha512_mac: + return SHA512_DIGEST_SIZE; + #endif + } + return 0; +} + +/* Use the data to create a new pre-shared key object in the extensions. + * + * ssl The SSL/TLS object. + * identity The identity. + * len The length of the identity data. + * age The age of the identity. + * hmac The HMAC algorithm. + * resumption The PSK is for resumption of a session. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, + byte hmac, byte resumption, + PreSharedKey **preSharedKey) +{ + int ret = 0; + TLSX* extension; + PreSharedKey* psk = NULL; + + /* Find the pre-shared key extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) { + /* Push new pre-shared key extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the pre-shared key with this identity. */ + psk = (PreSharedKey*)extension->data; + while (psk != NULL) { + if ((psk->identityLen == len) && + (XMEMCMP(psk->identity, identity, len) == 0)) { + break; + } + psk = psk->next; + } + + /* Create a new pre-shared key object if not found. */ + if (psk == NULL) { + ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity, + len, ssl->heap, &psk); + if (ret != 0) + return ret; + } + + /* Update/set age and HMAC algorithm. */ + psk->ticketAge = age; + psk->hmac = hmac; + psk->resumption = resumption; + psk->binderLen = GetHmacLength(psk->hmac); + + if (preSharedKey != NULL) + *preSharedKey = psk; + + return 0; +} + +#define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll +#define PSK_GET_SIZE TLSX_PreSharedKey_GetSize +#define PSK_WRITE TLSX_PreSharedKey_Write +#define PSK_PARSE TLSX_PreSharedKey_Parse + +#else + +#define PSK_FREE_ALL(a, b) +#define PSK_GET_SIZE(a, b) 0 +#define PSK_WRITE(a, b, c) 0 +#define PSK_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* PSK Key Exchange Modes */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && !defined(NO_PSK) +/* Get the size of the encoded PSK KE modes extension. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_PskKeModes_GetSize(byte modes, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + word16 len = OPAQUE8_LEN; + /* Check whether each possible mode is to be written. */ + if (modes & (1 << PSK_KE)) + len += OPAQUE8_LEN; + if (modes & (1 << PSK_DHE_KE)) + len += OPAQUE8_LEN; + return len; + } + + return SANITY_MSG_E; +} + +/* Writes the PSK KE modes extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = OPAQUE8_LEN; + + /* Write out each possible mode. */ + if (modes & (1 << PSK_KE)) + output[idx++] = PSK_KE; + if (modes & (1 << PSK_DHE_KE)) + output[idx++] = PSK_DHE_KE; + /* Write out length of mode list. */ + output[0] = idx - OPAQUE8_LEN; + + return idx; + } + + return SANITY_MSG_E; +} + +/* Parse the PSK KE modes extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = 0; + int len; + byte modes = 0; + + /* Ensure length byte exists. */ + if (length < OPAQUE8_LEN) + return BUFFER_E; + + /* Get length of mode list and ensure that is the only data. */ + len = input[0]; + if (length - OPAQUE8_LEN != len) + return BUFFER_E; + + idx = OPAQUE8_LEN; + /* Set a bit for each recognized modes. */ + while (len > 0) { + /* Ignore unrecognized modes. */ + if (input[idx] <= PSK_DHE_KE) + modes |= 1 << input[idx]; + idx++; + len--; + } + + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new PSK Key Exchange Modes object in the extensions. + * + * ssl The SSL/TLS object. + * modes The PSK key exchange modes. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) { + /* Push new PSK key exchange modes extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL, + ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) + return MEMORY_E; + } + + extension->val = modes; + + return 0; +} + +#define PKM_GET_SIZE TLSX_PskKeModes_GetSize +#define PKM_WRITE TLSX_PskKeModes_Write +#define PKM_PARSE TLSX_PskKeModes_Parse + +#else + +#define PKM_GET_SIZE(a, b) 0 +#define PKM_WRITE(a, b, c) 0 +#define PKM_PARSE(a, b, c, d) 0 + +#endif + /******************************************************************************/ /* TLS Extensions Framework */ /******************************************************************************/ @@ -4086,11 +6392,12 @@ void TLSX_FreeAll(TLSX* list, void* heap) break; case TLSX_STATUS_REQUEST: - CSR_FREE_ALL(extension->data, heap); + CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap); break; case TLSX_STATUS_REQUEST_V2: - CSR2_FREE_ALL(extension->data, heap); + CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data, + heap); break; case TLSX_RENEGOTIATION_INFO: @@ -4098,7 +6405,7 @@ void TLSX_FreeAll(TLSX* list, void* heap) break; case TLSX_SESSION_TICKET: - STK_FREE(extension->data, heap); + WOLF_STK_FREE(extension->data, heap); break; case TLSX_QUANTUM_SAFE_HYBRID: @@ -4108,6 +6415,27 @@ void TLSX_FreeAll(TLSX* list, void* heap) case TLSX_APPLICATION_LAYER_PROTOCOL: ALPN_FREE_ALL((ALPN*)extension->data, heap); break; + + case TLSX_SIGNATURE_ALGORITHMS: + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + break; + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + PSK_FREE_ALL((PreSharedKey*)extension->data, heap); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + break; + #endif +#endif } XFREE(extension, heap, DYNAMIC_TYPE_TLSX); @@ -4122,10 +6450,11 @@ int TLSX_SupportExtensions(WOLFSSL* ssl) { } /** Tells the buffered size of the extensions in a list. */ -static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) +static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType) { - TLSX* extension; + TLSX* extension; word16 length = 0; + byte isRequest = (msgType == client_hello); while ((extension = list)) { list = extension->next; @@ -4163,19 +6492,24 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) break; case TLSX_STATUS_REQUEST: - length += CSR_GET_SIZE(extension->data, isRequest); + length += CSR_GET_SIZE( + (CertificateStatusRequest*)extension->data, isRequest); break; case TLSX_STATUS_REQUEST_V2: - length += CSR2_GET_SIZE(extension->data, isRequest); + length += CSR2_GET_SIZE( + (CertificateStatusRequestItemV2*)extension->data, + isRequest); break; case TLSX_RENEGOTIATION_INFO: - length += SCR_GET_SIZE(extension->data, isRequest); + length += SCR_GET_SIZE((SecureRenegotiation*)extension->data, + isRequest); break; case TLSX_SESSION_TICKET: - length += STK_GET_SIZE(extension->data, isRequest); + length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data, + isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: @@ -4186,6 +6520,31 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) length += ALPN_GET_SIZE((ALPN*)extension->data); break; + case TLSX_SIGNATURE_ALGORITHMS: +#ifdef WOLFSSL_TLS13 + length += SA_GET_SIZE(extension->data); +#endif + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + length += SV_GET_SIZE(extension->data); + break; + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE(extension->data, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + length += PSK_GET_SIZE(extension->data, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + length += PKM_GET_SIZE(extension->val, msgType); + break; + #endif +#endif } /* marks the extension as processed so ctx level */ @@ -4198,11 +6557,12 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) /** Writes the extensions of a list in a buffer. */ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, - byte isRequest) + byte msgType) { TLSX* extension; word16 offset = 0; word16 length_offset = 0; + byte isRequest = (msgType == client_hello); while ((extension = list)) { list = extension->next; @@ -4223,44 +6583,55 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, /* extension data should be written internally. */ switch (extension->type) { case TLSX_SERVER_NAME: - if (isRequest) + if (isRequest) { + WOLFSSL_MSG("SNI extension to write"); offset += SNI_WRITE((SNI*)extension->data, output + offset); + } break; case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension to write"); offset += MFL_WRITE((byte*)extension->data, output + offset); break; case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension to write"); /* always empty. */ break; case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Elliptic Curves extension to write"); offset += EC_WRITE((EllipticCurve*)extension->data, output + offset); break; case TLSX_STATUS_REQUEST: - offset += CSR_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Certificate Status Request extension to write"); + offset += CSR_WRITE((CertificateStatusRequest*)extension->data, + output + offset, isRequest); break; case TLSX_STATUS_REQUEST_V2: - offset += CSR2_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Certificate Status Request v2 extension to write"); + offset += CSR2_WRITE( + (CertificateStatusRequestItemV2*)extension->data, + output + offset, isRequest); break; case TLSX_RENEGOTIATION_INFO: - offset += SCR_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Secure Renegotiation extension to write"); + offset += SCR_WRITE((SecureRenegotiation*)extension->data, + output + offset, isRequest); break; case TLSX_SESSION_TICKET: - offset += STK_WRITE(extension->data, output + offset, - isRequest); + WOLFSSL_MSG("Session Ticket extension to write"); + offset += WOLF_STK_WRITE((SessionTicket*)extension->data, + output + offset, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write"); if (isRequest) { offset += QSH_WRITE((QSHScheme*)extension->data, output + offset); } @@ -4269,8 +6640,40 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, break; case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension to write"); offset += ALPN_WRITE((ALPN*)extension->data, output + offset); break; + + case TLSX_SIGNATURE_ALGORITHMS: +#ifdef WOLFSSL_TLS13 + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SA_WRITE(extension->data, output + offset); +#endif + break; + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension to write"); + offset += SV_WRITE(extension->data, output + offset); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE(extension->data, output + offset, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension to write"); + offset += PSK_WRITE(extension->data, output + offset, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); + offset += PKM_WRITE(extension->val, output + offset, msgType); + break; + #endif +#endif } /* writes extension data length. */ @@ -4322,6 +6725,8 @@ static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) { int ret; + (void)ssl; + switch (type) { #ifdef HAVE_NTRU case WOLFSSL_NTRU_EESS439: @@ -4370,10 +6775,11 @@ static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) } -#ifdef HAVE_NTRU +#if defined(HAVE_NTRU) || defined(HAVE_QSH) int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) { - int ret; + int ret = -1; +#ifdef HAVE_NTRU int ntruType; /* variable declarations for NTRU*/ @@ -4436,6 +6842,10 @@ int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) temp->next = NULL; TLSX_AddQSHKey(&ssl->QSH_Key, temp); +#endif + + (void)ssl; + (void)type; return ret; } @@ -4470,95 +6880,304 @@ static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) } #endif /* HAVE_QSH */ - int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) { + int ret = 0; byte* public_key = NULL; word16 public_key_len = 0; - #ifdef HAVE_QSH - TLSX* extension; - QSHScheme* qsh; - QSHScheme* next; - #endif - int ret = 0; +#ifdef HAVE_QSH + TLSX* extension; + QSHScheme* qsh; + QSHScheme* next; - #ifdef HAVE_QSH - /* add supported QSHSchemes */ - WOLFSSL_MSG("Adding supported QSH Schemes"); + /* add supported QSHSchemes */ + WOLFSSL_MSG("Adding supported QSH Schemes"); +#endif - /* server will add extension depending on whats parsed from client */ - if (!isServer) { + /* server will add extension depending on whats parsed from client */ + if (!isServer) { +#ifdef HAVE_QSH + /* test if user has set a specific scheme already */ + if (!ssl->user_set_QSHSchemes) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } - /* test if user has set a specific scheme already */ - if (!ssl->user_set_QSHSchemes) { - if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } - if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { - WOLFSSL_MSG("Error creating ntru keys"); - return ret; - } + /* add NTRU 256 */ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS743); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; - /* add NTRU 256 */ + /* add NTRU 196 */ + if (ssl->sendQSHKeys) { public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS743); - } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; - - /* add NTRU 196 */ - if (ssl->sendQSHKeys) { - public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS593); - } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; - - /* add NTRU 128 */ - if (ssl->sendQSHKeys) { - public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, WOLFSSL_NTRU_EESS439); - } - if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, - public_key, public_key_len, ssl->heap) - != SSL_SUCCESS) - ret = -1; + &public_key_len, WOLFSSL_NTRU_EESS593); } - else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { - /* for each scheme make a client key */ - extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); - if (extension) { - qsh = (QSHScheme*)extension->data; + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; - while (qsh) { - if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) - return ret; + /* add NTRU 128 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS439); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, + public_key, public_key_len, ssl->heap) + != SSL_SUCCESS) + ret = -1; + } + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + /* for each scheme make a client key */ + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (extension) { + qsh = (QSHScheme*)extension->data; - /* get next now because qsh could be freed */ - next = qsh->next; + while (qsh) { + if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) + return ret; - /* find the public key created and add to extension*/ - public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, - &public_key_len, qsh->name); - if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, - public_key, public_key_len, - ssl->heap) != SSL_SUCCESS) - ret = -1; - qsh = next; - } + /* get next now because qsh could be freed */ + next = qsh->next; + + /* find the public key created and add to extension*/ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, qsh->name); + if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, + public_key, public_key_len, + ssl->heap) != SSL_SUCCESS) + ret = -1; + qsh = next; } } - } /* is not server */ + } +#endif + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + #ifndef HAVE_FIPS + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_SECPR2 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #ifdef WOLFSSL_TLS13 + #if defined(HAVE_CURVE25519) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != SSL_SUCCESS) return ret; + #endif + #endif + #endif + } +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + } /* is not server */ + + #ifdef WOLFSSL_TLS13 + WOLFSSL_MSG("Adding signature algorithms extension"); + if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, + ssl->heap)) != 0) + return ret; + + if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { + /* Add mandatory TLS v1.3 extension: supported version */ + WOLFSSL_MSG("Adding supported versions extension"); + if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl, + ssl->heap)) != 0) + return ret; + + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_3072 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_4096 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_6144 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + #ifdef HAVE_FFDHE_8192 + ret = TLSX_UseSupportedCurve(&ssl->extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != SSL_SUCCESS) + return ret; + #endif + ret = 0; + + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP256R1, 0, NULL, + NULL); + #elif (!defined(NO_ECC384) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP384R1, 0, NULL, + NULL); + #elif (!defined(NO_ECC521) || defined(HAVE_ALL_CURVES)) && \ + !defined(NO_ECC_SECP) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_ECC_SECP521R1, 0, NULL, + NULL); + #elif defined(HAVE_FFDHE_2048) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_2048, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_3072) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_3072, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_4096) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_4096, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_6144) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_6144, 0, NULL, NULL); + #elif defined(HAVE_FFDHE_8192) + ret = TLSX_KeyShare_Use(ssl, WOLFSSL_FFDHE_8192, 0, NULL, NULL); + #else + ret = KEY_SHARE_ERROR; + #endif + if (ret != 0) + return ret; + } + + #if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + if (ssl->options.resuming) { + WOLFSSL_SESSION* sess = &ssl->session; + word32 milli; + byte modes; + + /* Determine the MAC algorithm for the cipher suite used. */ + ssl->options.cipherSuite0 = sess->cipherSuite0; + ssl->options.cipherSuite = sess->cipherSuite; + SetCipherSpecs(ssl); + milli = TimeNowInMilliseconds() - sess->ticketSeen + + sess->ticketAdd; + /* Pre-shared key is mandatory extension for resumption. */ + ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, + milli, ssl->specs.mac_algorithm, 1, + ssl->heap); + if (ret != 0) + return ret; + + /* Pre-shared key modes: mandatory extension for resumption. */ + modes = 1 << PSK_KE; + #if !defined(NO_DH) || defined(HAVE_ECC) + if (!ssl->options.noPskDheKe) + modes |= 1 << PSK_DHE_KE; + #endif + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + } + #endif + /* TODO: [TLS13] Add PSKs */ + } + #endif (void)isServer; @@ -4566,6 +7185,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) (void)public_key_len; (void)ssl; + if (ret == SSL_SUCCESS) + ret = 0; + return ret; } @@ -4582,17 +7204,33 @@ word16 TLSX_GetRequestSize(WOLFSSL* ssl) EC_VALIDATE_REQUEST(ssl, semaphore); QSH_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + WOLF_STK_VALIDATE_REQUEST(ssl); +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + } +#endif if (ssl->extensions) - length += TLSX_GetSize(ssl->extensions, semaphore, 1); + length += TLSX_GetSize(ssl->extensions, semaphore, client_hello); - if (ssl->ctx && ssl->ctx->extensions) - length += TLSX_GetSize(ssl->ctx->extensions, semaphore, 1); + if (ssl->ctx && ssl->ctx->extensions) { + length += TLSX_GetSize(ssl->ctx->extensions, semaphore, + client_hello); + } +#ifndef WOLFSSL_TLS13 if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) - length += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ + length += HELLO_EXT_SZ + OPAQUE16_LEN + + ssl->suites->hashSigAlgoSz; +#endif #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) @@ -4617,21 +7255,36 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) offset += OPAQUE16_LEN; /* extensions length */ EC_VALIDATE_REQUEST(ssl, semaphore); - STK_VALIDATE_REQUEST(ssl); + WOLF_STK_VALIDATE_REQUEST(ssl); QSH_VALIDATE_REQUEST(ssl, semaphore); +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + } + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif if (ssl->extensions) - offset += TLSX_Write(ssl->extensions, output + offset, - semaphore, 1); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello); if (ssl->ctx && ssl->ctx->extensions) offset += TLSX_Write(ssl->ctx->extensions, output + offset, - semaphore, 1); + semaphore, client_hello); +#ifndef WOLFSSL_TLS13 if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) { int i; /* extension type */ - c16toa(HELLO_EXT_SIG_ALGO, output + offset); + c16toa(TLSX_SIGNATURE_ALGORITHMS, output + offset); offset += HELLO_EXT_TYPE_SZ; /* extension data length */ @@ -4647,6 +7300,7 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) for (i = 0; i < ssl->suites->hashSigAlgoSz; i++, offset++) output[offset] = ssl->suites->hashSigAlgo[i]; } +#endif #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { @@ -4657,6 +7311,16 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) } #endif +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.resuming) { + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello); + } +#endif + if (offset > OPAQUE16_LEN) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } @@ -4669,11 +7333,33 @@ word16 TLSX_WriteRequest(WOLFSSL* ssl, byte* output) #ifndef NO_WOLFSSL_SERVER /** Tells the buffered size of extensions to be sent into the server hello. */ -word16 TLSX_GetResponseSize(WOLFSSL* ssl) +word16 TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType) { word16 length = 0; byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + break; + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + break; + } + #ifdef HAVE_QSH /* change response if not using TLS_QSH */ if (!ssl->options.haveQSH) { @@ -4684,35 +7370,58 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl) #endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) + if (ssl->options.haveEMS && msgType == server_hello) length += HELLO_EXT_SZ; #endif if (TLSX_SupportExtensions(ssl)) - length += TLSX_GetSize(ssl->extensions, semaphore, 0); + length += TLSX_GetSize(ssl->extensions, semaphore, msgType); /* All the response data is set at the ssl object only, so no ctx here. */ - if (length) + if (length || (msgType != server_hello)) length += OPAQUE16_LEN; /* for total length storage. */ return length; } /** Writes the server hello extensions into a buffer. */ -word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) +word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType) { word16 offset = 0; if (TLSX_SupportExtensions(ssl) && output) { byte semaphore[SEMAPHORE_SIZE] = {0}; + switch (msgType) { + case server_hello: +#ifdef WOLFSSL_TLS13 + case hello_retry_request: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + break; + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #ifndef NO_PSK + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + break; + } + offset += OPAQUE16_LEN; /* extensions length */ - offset += TLSX_Write(ssl->extensions, output + offset, semaphore, 0); + offset += TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType); #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS) { + if (ssl->options.haveEMS && msgType == server_hello) { c16toa(HELLO_EXT_EXTMS, output + offset); offset += HELLO_EXT_TYPE_SZ; c16toa(0, output + offset); @@ -4720,7 +7429,7 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) } #endif - if (offset > OPAQUE16_LEN) + if (offset > OPAQUE16_LEN || msgType == encrypted_extensions) c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ } @@ -4730,11 +7439,12 @@ word16 TLSX_WriteResponse(WOLFSSL *ssl, byte* output) #endif /* NO_WOLFSSL_SERVER */ /** Parses a buffer of TLS extensions. */ -int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, +int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, Suites *suites) { int ret = 0; word16 offset = 0; + byte isRequest = (msgType == client_hello); #ifdef HAVE_EXTENDED_MASTER byte pendingEMS = 0; #endif @@ -4762,36 +7472,75 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = SNI_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = THM_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_SUPPORTED_GROUPS: WOLFSSL_MSG("Elliptic Curves extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = EC_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST: WOLFSSL_MSG("Certificate Status Request extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST_V2: WOLFSSL_MSG("Certificate Status Request v2 extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = CSR2_PARSE(ssl, input + offset, size, isRequest); break; @@ -4799,8 +7548,14 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case HELLO_EXT_EXTMS: WOLFSSL_MSG("Extended Master Secret extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif #ifndef NO_WOLFSSL_SERVER - if (isRequest) + if (isRequest && !IsAtLeastTLSv1_3(ssl->version)) ssl->options.haveEMS = 1; #endif pendingEMS = 1; @@ -4816,22 +7571,42 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); - ret = STK_PARSE(ssl, input + offset, size, isRequest); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif + ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_QUANTUM_SAFE_HYBRID: WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return EXT_NOT_ALLOWED; +#endif ret = QSH_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_APPLICATION_LAYER_PROTOCOL: WOLFSSL_MSG("ALPN extension received"); +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif ret = ALPN_PARSE(ssl, input + offset, size, isRequest); break; - case HELLO_EXT_SIG_ALGO: +#ifndef WOLFSSL_TLS13 + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Extended signature algorithm extension received"); + if (isRequest) { /* do not mess with offset inside the switch! */ if (IsAtLeastTLSv1_2(ssl)) { @@ -4850,6 +7625,77 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, } break; +#endif + +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = SV_PARSE(ssl, input + offset, size); + break; + + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension received"); + + if (!IsAtLeastTLSv1_2(ssl)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = SA_PARSE(ssl, input + offset, size); + break; + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; + + #ifndef NO_PSK + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && msgType != server_hello) { + return EXT_NOT_ALLOWED; + } + ret = PSK_PARSE(ssl, input + offset, size, msgType); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } + ret = PKM_PARSE(ssl, input + offset, size, msgType); + break; + #endif +#endif } /* offset should be updated here! */ @@ -4929,6 +7775,35 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 client method data. + * + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method(void) + { + return wolfTLSv1_3_client_method_ex(NULL); + } + + /* The TLS v1.3 client method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) + XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->downgrade = 1; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ + WOLFSSL_METHOD* wolfSSLv23_client_method(void) { @@ -4944,7 +7819,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); @@ -5021,6 +7900,34 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return method; } +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 server method data. + * + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method(void) + { + return wolfTLSv1_3_server_method_ex(NULL); + } + + /* The TLS v1.3 server method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ WOLFSSL_METHOD* wolfSSLv23_server_method(void) { @@ -5035,7 +7942,11 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, (void)heap; if (method) { #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) +#ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); +#else InitSSL_Method(method, MakeTLSv1_2()); +#endif #else #ifndef NO_OLD_TLS InitSSL_Method(method, MakeTLSv1_1()); diff --git a/src/tls13.c b/src/tls13.c new file mode 100644 index 000000000..85a179162 --- /dev/null +++ b/src/tls13.c @@ -0,0 +1,5557 @@ +/* tls13.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#ifdef WOLFSSL_TLS13 +#if defined(HAVE_SESSION_TICKET) +#include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#ifdef HAVE_ERRNO_H + #include +#endif + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#ifdef __sun + #include +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +/* Set ret to error value and jump to label. + * + * err The error value to set. + * eLabel The label to jump to. + */ +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + + +#ifndef WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MIN +/* Return the minimum of the two values. + * + * a First value. + * b Second value. + * returns the minimum of a and b. + */ +static INLINE word32 min(word32 a, word32 b) +{ + return a > b ? b : a; +} +#endif /* WOLFSSL_HAVE_MIN */ + +/* Convert 16-bit integer to opaque data. + * + * u16 Unsigned 16-bit value. + * c The buffer to write to. + */ +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} + +/* Convert 32-bit integer to opaque data. + * + * u32 Unsigned 32-bit value. + * c The buffer to write to. + */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + + +/* Convert 24-bit opaque data into a 32-bit value. + * + * u24 The opaque data holding a 24-bit integer. + * u32 Unsigned 32-bit value. + */ +static INLINE void c24to32(const word24 u24, word32* u32) +{ + *u32 = (u24[0] << 16) | (u24[1] << 8) | u24[2]; +} + + +/* Convert opaque data into a 16-bit value. + * + * c The opaque data. + * u16 Unsigned 16-bit value. + */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} + +#ifndef NO_WOLFSSL_CLIENT +#ifdef HAVE_SESSION_TICKET +/* Convert opaque data into a 32-bit value. + * + * c The opaque data. + * u32 Unsigned 32-bit value. + */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +#endif +#endif + +/* Extract data using HMAC, salt and input. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + * + * prk The generated pseudorandom key. + * salt The salt. + * saltLen The length of the salt. + * ikm The input keying material. + * ikmLen The length of the input keying material. + * mac The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, + byte* ikm, int ikmLen, int mac) +{ + int ret; + int hash; + int len; + + switch (mac) { + #ifndef NO_SHA256 + case sha256_mac: + hash = SHA256; + len = SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = SHA384; + len = SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hash = SHA512; + len = SHA512_DIGEST_SIZE; + break; + #endif + + default: + return BAD_FUNC_ARG; + } + + /* When length is 0 then use zeroed data of digest length. */ + if (ikmLen == 0) { + ikmLen = len; + XMEMSET(ikm, 0, len); + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Salt"); + WOLFSSL_BUFFER(salt, saltLen); + WOLFSSL_MSG("IKM"); + WOLFSSL_BUFFER(ikm, ikmLen); +#endif + + ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("PRK"); + WOLFSSL_BUFFER(prk, len); +#endif + + return ret; +} + +/* Expand data using HMAC, salt and label and info. + * TLS v1.3 defines this function. + * + * okm The generated pseudorandom key - output key material. + * prk The salt - pseudo-random key. + * prkLen The length of the salt - pseudo-random key. + * protocol The TLS protocol label. + * protocolLen The length of the TLS protocol label. + * info The information to expand. + * infoLen The length of the information. + * digest The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int HKDF_Expand_Label(byte* okm, word32 okmLen, + const byte* prk, word32 prkLen, + const byte* protocol, word32 protocolLen, + const byte* label, word32 labelLen, + const byte* info, word32 infoLen, + int digest) +{ + int ret = 0; + int idx = 0; + byte data[MAX_HKDF_LABEL_SZ]; + + /* Output length. */ + data[idx++] = okmLen >> 8; + data[idx++] = okmLen; + /* Length of protocol | label. */ + data[idx++] = protocolLen + labelLen; + /* Protocol */ + XMEMCPY(&data[idx], protocol, protocolLen); + idx += protocolLen; + /* Label */ + XMEMCPY(&data[idx], label, labelLen); + idx += labelLen; + /* Length of hash of messages */ + data[idx++] = infoLen; + /* Hash of messages */ + XMEMCPY(&data[idx], info, infoLen); + idx += infoLen; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("PRK"); + WOLFSSL_BUFFER(prk, prkLen); + WOLFSSL_MSG("Info"); + WOLFSSL_BUFFER(data, idx); +#endif + + ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("OKM"); + WOLFSSL_BUFFER(okm, okmLen); +#endif + + ForceZero(data, idx); + + return ret; +} + +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 9 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, "; + +/* Derive a key from a message. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * msg The message data to derive key from. + * msgLen The length of the message data to derive key from. + * hashAlgo The hash algorithm to use in the HMAC. + * returns 0 on success, otherwise failure. + */ +static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + byte* msg, int msgLen, int hashAlgo) +{ + byte hash[MAX_DIGEST_SIZE]; + Digest digest; + word32 hashSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg; + int ret = BAD_FUNC_ARG; + + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, msg, msgLen); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + digestAlg = SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, msg, msgLen); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + digestAlg = SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + digestAlg = SHA512; + break; +#endif + + default: + return BAD_FUNC_ARG; + } + + if (ret != 0) + return ret; + + switch (ssl->version.minor) { + case TLSv1_3_MINOR: + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + break; + + default: + return VERSION_ERROR; + } + if (outputLen == -1) + outputLen = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashSz, digestAlg); +} + +/* Derive a key. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * hashAlgo The hash algorithm to use in the HMAC. + * includeMsgs Whether to include a hash of the handshake messages so far. + * returns 0 on success, otherwise failure. + */ +static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + int hashAlgo, int includeMsgs) +{ + int ret = 0; + byte hash[MAX_DIGEST_SIZE]; + word32 hashSz = 0; + word32 hashOutSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg; + + switch (hashAlgo) { + #ifndef NO_SHA256 + case sha256_mac: + hashSz = SHA256_DIGEST_SIZE; + digestAlg = SHA256; + if (includeMsgs) + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashSz = SHA384_DIGEST_SIZE; + digestAlg = SHA384; + if (includeMsgs) + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif + + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hashSz = SHA512_DIGEST_SIZE; + digestAlg = SHA512; + if (includeMsgs) + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + if (ret != 0) + return ret; + + /* Only one protocol version defined at this time. */ + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + if (outputLen == -1) + outputLen = hashSz; + if (includeMsgs) + hashOutSz = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashOutSz, digestAlg); +} + + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 23 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "external psk binder key"; +/* Derive the binder key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKey(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyLabel, BINDER_KEY_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} + +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 25 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "resumption psk binder key"; +/* Derive the binder resumption key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key - Resumption"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif + +#ifdef TLS13_SUPPORTS_0RTT +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 27 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "client early traffic secret"; +/* Derive the early traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + + #ifdef TLS13_SUPPORTS_EXPORTERS +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 28 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "early exporter master secret"; +/* Derive the early exporter key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + #endif +#endif + +/* The length of the client hanshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 31 +/* The client hanshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "client handshake traffic secret"; +/* Derive the client handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 31 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "server handshake traffic secret"; +/* Derive the server handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 33 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "client application traffic secret"; +/* Derive the client application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + clientAppLabel, CLIENT_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 33 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "server application traffic secret"; +/* Derive the server application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + serverAppLabel, SERVER_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 22 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exporter master secret"; +/* Derive the exporter secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +#ifndef NO_PSK +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 24 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "resumption master secret"; +/* Derive the resumption secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Resumption Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + resumeMasterLabel, RESUME_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +/* Length of the finished label. */ +#define FINISHED_LABEL_SZ 8 +/* Finished label for generating finished key. */ +static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished"; +/* Derive the finished secret. + * + * ssl The SSL/TLS object. + * key The key to use with the HMAC. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret) +{ + WOLFSSL_MSG("Derive Finished Secret"); + return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 26 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "application traffic secret"; +/* Update the traffic secret. + * + * ssl The SSL/TLS object. + * secret The previous secret and derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) +{ + WOLFSSL_MSG("Derive New Application Traffic Secret"); + return DeriveKeyMsg(ssl, secret, -1, secret, + appTrafficLabel, APP_TRAFFIC_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} + +/* Derive the early secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveEarlySecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Early Secret"); +#ifndef NO_PSK + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->psk_key, ssl->arrays->psk_keySz, + ssl->specs.mac_algorithm); +#else + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +/* Derive the handshake secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveHandshakeSecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Handshake Secret"); + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + ssl->arrays->secret, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +} + +/* Derive the master secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveMasterSecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Master Secret"); + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + ssl->arrays->preMasterSecret, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +} + +/* Calculate the HMAC of message data to this point. + * + * ssl The SSL/TLS object. + * key The HMAC key. + * hash The hash result - verify data. + * returns length of verify data generated. + */ +static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, + word32* pHashSz) +{ + Hmac verifyHmac; + int hashType = SHA256; + int hashSz = SHA256_DIGEST_SIZE; + int ret = BAD_FUNC_ARG; + + /* Get the hash of the previous handshake messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hashType = SHA256; + hashSz = SHA256_DIGEST_SIZE; + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashType = SHA384; + hashSz = SHA384_DIGEST_SIZE; + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + hashType = SHA512; + hashSz = SHA512_DIGEST_SIZE; + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif /* WOLFSSL_SHA512 */ + } + if (ret != 0) + return ret; + + /* Calculate the verify data. */ + ret = wc_HmacInit(&verifyHmac, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size); + if (ret == 0) + ret = wc_HmacUpdate(&verifyHmac, hash, hashSz); + if (ret == 0) + ret = wc_HmacFinal(&verifyHmac, hash); + wc_HmacFree(&verifyHmac); + } + + if (pHashSz) + *pHashSz = hashSz; + + return ret; +} + +/* The length of the label to use when deriving keys. */ +#define WRITE_KEY_LABEL_SZ 3 +/* The length of the label to use when deriving IVs. */ +#define WRITE_IV_LABEL_SZ 2 +/* The label to use when deriving keys. */ +static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key"; +/* The label to use when deriving IVs. */ +static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; + +/* Derive the keys and IVs for TLS v1.3. + * + * ssl The SSL/TLS object. + * sercret handshake_key when deriving keys and IVs for encrypting handshake + * messages. + * traffic_key when deriving first keys and IVs for encrypting + * traffic messages. + * update_traffic_key when deriving next keys and IVs for encrypting + * traffic messages. + * side ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived. + * DECRYPT_SIDE_ONLY when only decryption secret needs to be derived. + * ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived. + * returns 0 on success, otherwise failure. + */ +static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side) +{ + int ret; + int i = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key_data; +#else + byte key_data[MAX_PRF_DIG]; +#endif + int deriveClient = 0; + int deriveServer = 0; + +#ifdef WOLFSSL_SMALL_STACK + key_data = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key_data == NULL) + return MEMORY_E; +#endif + + if (side == ENCRYPT_AND_DECRYPT_SIDE) { + deriveClient = 1; + deriveServer = 1; + } + else { + deriveClient = (ssl->options.side != WOLFSSL_CLIENT_END) ^ + (side == ENCRYPT_SIDE_ONLY); + deriveServer = !deriveClient; + } + + /* Derive the appropriate secret to use in the HKDF. */ + switch (secret) { + case handshake_key: + if (deriveClient) { + ret = DeriveClientHandshakeSecret(ssl, + ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveServerHandshakeSecret(ssl, + ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case traffic_key: + if (deriveClient) { + ret = DeriveClientTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveServerTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + + case update_traffic_key: + if (deriveClient) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->clientSecret); + if (ret != 0) + goto end; + } + if (deriveServer) { + ret = DeriveTrafficSecret(ssl, ssl->arrays->serverSecret); + if (ret != 0) + goto end; + } + break; + } + + /* Key data = client key | server key | client IV | server IV */ + + /* Derive the client key. */ + WOLFSSL_MSG("Derive Client Key"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.key_size, + ssl->arrays->clientSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + + /* Derive the server key. */ + WOLFSSL_MSG("Derive Server Key"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.key_size, + ssl->arrays->serverSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + + /* Derive the client IV. */ + WOLFSSL_MSG("Derive Client IV"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.iv_size, + ssl->arrays->clientSecret, writeIVLabel, WRITE_IV_LABEL_SZ, + ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.iv_size; + + /* Derive the server IV. */ + WOLFSSL_MSG("Derive Server IV"); + ret = DeriveKey(ssl, &key_data[i], ssl->specs.iv_size, + ssl->arrays->serverSecret, writeIVLabel, WRITE_IV_LABEL_SZ, + ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + + /* Store keys and IVs but don't activate them. */ + ret = StoreKeys(ssl, key_data); + +end: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_data, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#if defined(HAVE_SESSION_TICKET) +#if defined(USER_TICKS) +#if 0 + word32 TimeNowInMilliseconds(void) + { + /* + write your own clock tick function if don't want gettimeofday() + needs millisecond accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) XTIME(0) * 1000; + } +#elif defined(USE_WINDOWS_API) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (word32)(count.QuadPart / (freq.QuadPart / 1000)); + } + +#elif defined(HAVE_RTP_SYS) + #include "rtptime.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)rtp_get_system_sec() * 1000; + } +#elif defined(MICRIUM) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + NET_SECURE_OS_TICK clk = 0; + + #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED) + clk = NetSecure_OS_TimeGet(); + #endif + return (word32)clk * 1000; + } +#elif defined(MICROCHIP_TCPIP_V5) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (TickGet() / (TICKS_PER_SECOND / 1000)); + } +#elif defined(MICROCHIP_TCPIP) + #if defined(MICROCHIP_MPLAB_HARMONY) + #include + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (SYS_TMR_TickCountGet() / + (SYS_TMR_TickCounterFrequencyGet() / 1000)); + } + #else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000)); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (word32) mqxTime.SECONDS * 1000; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include "include/task.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (unsigned int)(((float)xTaskGetTickCount()) / + (configTICK_RATE_HZ / 1000)); + } +#elif defined(FREESCALE_KSDK_BM) + #include "lwip/sys.h" /* lwIP */ + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return sys_now(); + } +#elif defined(WOLFSSL_TIRTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) Seconds_get() * 1000; + } +#elif defined(WOLFSSL_UTASKER) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000)); + } +#else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + struct timeval now; + + if (gettimeofday(&now, 0) < 0) + return GETTIME_ERROR; + /* Convert to milliseconds number. */ + return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); + } +#endif +#endif /* HAVE_SESSION_TICKET */ + + +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) && \ + !defined(NO_PSK)) +/* Add input to all handshake hashes. + * + * ssl The SSL/TLS object. + * input The data to hash. + * sz The size of the data to hash. + * returns 0 on success, otherwise failure. + */ +static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) +{ + int ret = BAD_FUNC_ARG; + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + ret = wc_ShaUpdate(&ssl->hsHashes->hashSha, input, sz); + if (ret != 0) + return ret; +#endif +#ifndef NO_MD5 + ret = wc_Md5Update(&ssl->hsHashes->hashMd5, input, sz); + if (ret != 0) + return ret; +#endif +#endif /* !NO_OLD_TLS */ + +#ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz); + if (ret != 0) + return ret; +#endif + + return ret; +} +#endif + +/* Extract the handshake header information. + * + * ssl The SSL/TLS object. + * input The buffer holding the message data. + * inOutIdx On entry, the index into the buffer of the handshake data. + * On exit, the start of the hanshake data. + * type Type of handshake message. + * size The length of the handshake message data. + * totalSz The total size of data in the buffer. + * returns BUFFER_E if there is not enough input data and 0 on success. + */ +static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte *type, word32 *size, word32 totalSz) +{ + const byte *ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} + +/* Add record layer header to message. + * + * output The buffer to write the record layer header into. + * length The length of the record data. + * type The type of record message. + * ssl The SSL/TLS object. + */ +static void AddTls13RecordHeader(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + RecordLayerHeader* rl; + + rl = (RecordLayerHeader*)output; + rl->type = type; + rl->pvMajor = ssl->version.major; + rl->pvMinor = TLSv1_MINOR; + c16toa((word16)length, rl->length); +} + +/* Add handshake header to message. + * + * output The buffer to write the hanshake header into. + * length The length of the handshake data. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * type The type of handshake message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13HandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + hs->type = type; + c32to24(length, hs->length); +} + + +/* Add both record layer and handshake header to message. + * + * output The buffer to write the headers into. + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13Headers(byte* output, word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + + AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} + + +#ifndef NO_CERTS +/* Add both record layer and fragement handshake header to message. + * + * output The buffer to write the headers into. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + + AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz, + type, ssl); +} +#endif /* NO_CERTS */ + +/* Write the sequence number into the buffer. + * No DTLS v1.3 support. + * + * ssl The SSL/TLS object. + * verifyOrder Which set of sequence numbers to use. + * out The buffer to write into. + */ +static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (verifyOrder) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.peer_sequence_number_lo) + ssl->keys.peer_sequence_number_hi++; + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.sequence_number_lo) + ssl->keys.sequence_number_hi++; + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + +/* Build the nonce for TLS v1.3 encryption and decryption. + * + * ssl The SSL/TLS object. + * nonce The nonce data to use when encrypting or decrypting. + * iv The derived IV. + * order The side on which the message is to be or was sent. + */ +static INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte *nonce, const byte* iv, + int order) +{ + int i; + + /* The nonce is the IV with the sequence XORed into the last bytes. */ + WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ); + for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++) + nonce[i] = iv[i]; + for (; i < AEAD_NONCE_SZ; i++) + nonce[i] ^= iv[i]; +} + +/* Encrypt with ChaCha20 and create authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * nonce The nonce to use with ChaCha20. + * tag The authentication tag buffer. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + byte* tag) +{ + int ret = 0; + byte poly[CHACHA20_256_KEY_SIZE]; + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set the nonce for ChaCha and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Create Poly1305 key using ChaCha20 keystream. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + /* Encrypt the plain text. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz); + if (ret != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Add authentication code of encrypted data to end. */ + ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, output, sz, tag, + POLY1305_AUTH_SZ); + + return ret; +} + +/* Encrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * returns 0 on success, otherwise failure. + */ +static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + byte nonce[AEAD_NONCE_SZ]; + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to encrypt"); + WOLFSSL_BUFFER(input, dataSz); +#endif + + BuildTls13Nonce(ssl, nonce, ssl->keys.aead_enc_imp_IV, CUR_ORDER); + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, dataSz, + nonce, AESGCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, dataSz, + nonce, AESCCM_NONCE_SZ, output + dataSz, macSz, NULL, 0); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, nonce, + output + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + return ENCRYPT_ERROR; + } + + ForceZero(nonce, AEAD_NONCE_SZ); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); +#endif + + return ret; +} + +/* Decrypt with ChaCha20 and check authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to decrypt. + * sz The number of bytes to decrypt. + * nonce The nonce to use with ChaCha20. + * tagIn The authentication tag data from packet. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Decrypt(WOLFSSL *ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + const byte* tagIn) +{ + int ret; + byte tag[POLY1305_AUTH_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set nonce and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Use ChaCha20 keystream to get Poly1305 key for tag. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Generate authentication tag for encrypted data. */ + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, NULL, 0, (byte*)input, sz, + tag, sizeof(tag))) != 0) { + return ret; + } + + /* Check tag sent along with packet. */ + if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) { + WOLFSSL_MSG("MAC did not match"); + return VERIFY_MAC_ERROR; + } + + /* If the tag was good decrypt message. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz); + + return ret; +} + +/* Decrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to encrypt and authentication tag. + * sz The length of the encrypted data plus authentication tag. + * returns 0 on success, otherwise failure. + */ +int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + byte nonce[AEAD_NONCE_SZ]; + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to decrypt"); + WOLFSSL_BUFFER(input, dataSz); + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); +#endif + + BuildTls13Nonce(ssl, nonce, ssl->keys.aead_dec_imp_IV, PEER_ORDER); + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, dataSz, + nonce, AESGCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, dataSz, + nonce, AESCCM_NONCE_SZ, input + dataSz, macSz, NULL, 0); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, nonce, + input + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + return DECRYPT_ERROR; + } + + ForceZero(nonce, AEAD_NONCE_SZ); + if (ret < 0 && !ssl->options.dtls) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); +#endif + + return ret; +} + +/* Build SSL Message, encrypted. + * TLS v1.3 encryption is AEAD only. + * + * ssl The SSL/TLS object. + * output The buffer to write record message to. + * outSz Size of the buffer being written into. + * input The record data to encrypt (excluding record header). + * inSz The size of the record data. + * type The recorder header content type. + * hashOutput Whether to hash the unencrypted record data. + * sizeOnly Only want the size of the record message. + * returns the size of the encrypted record message or negative value on error. + */ +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly) +{ + word32 sz = RECORD_HEADER_SZ + inSz; + word32 idx = RECORD_HEADER_SZ; + word32 headerSz = RECORD_HEADER_SZ; + word16 size; + int ret = 0; + int atomicUser = 0; + + if (ssl == NULL) + return BAD_FUNC_ARG; + if (!sizeOnly && (output == NULL || input == NULL)) + return BAD_FUNC_ARG; + /* catch mistaken sizeOnly parameter */ + if (sizeOnly && (output || input)) { + WOLFSSL_MSG("BuildMessage with sizeOnly doesn't need input or output"); + return BAD_FUNC_ARG; + } + + /* Record layer content type at the end of record data. */ + sz++; + /* Authentication data at the end. */ + sz += ssl->specs.aead_mac_size; + + if (sizeOnly) + return sz; + + if (sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + + /* Record data length. */ + size = (word16)(sz - headerSz); + /* Write/update the record header with the new size. + * Always have the content type as application data for encrypted + * messages in TLS v1.3. + */ + AddTls13RecordHeader(output, size, application_data, ssl); + + /* TLS v1.3 can do in place encryption. */ + if (input != output + idx) + XMEMCPY(output + idx, input, inSz); + idx += inSz; + + if (hashOutput) { + ret = HashOutput(ssl, output, headerSz + inSz, 0); + if (ret != 0) + return ret; + } + + /* The real record content type goes at the end of the data. */ + output[idx++] = type; + +#ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) + atomicUser = 1; +#endif + + if (atomicUser) { /* User Record Layer Callback handling */ +#ifdef ATOMIC_USER + byte* mac = output + idx; + output += headerSz; + + if ((ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + output, output, size, ssl->MacEncryptCtx)) != 0) { + return ret; + } +#endif + } + else { + output += headerSz; + if ((ret = EncryptTls13(ssl, output, output, size)) != 0) + return ret; + } + + return sz; +} + +#ifndef NO_WOLFSSL_CLIENT +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Get the size of the message hash. + * + * ssl The SSL/TLS object. + * returns the length of the hash. + */ +static int GetMsgHashSize(WOLFSSL *ssl) +{ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + return SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ + } + return 0; +} + +/* Derive and write the binders into the ClientHello in space left when + * writing the Pre-Shared Key extension. + * + * ssl The SSL/TLS object. + * output The buffer containing the ClientHello. + * idx The index at the end of the completed ClientHello. + * returns 0 on success and otherwise failure. + */ +static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) +{ + int ret; + TLSX* ext; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + word16 len; + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return SANITY_MSG_E; + + /* Get the size of the binders to determine where to write binders. */ + idx -= TLSX_PreSharedKey_GetSizeBinders(ext->data, client_hello); + + /* Hash truncated ClientHello - up to binders. */ + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + current = ext->data; + /* Calculate the binder for each identity based on previous handshake data. + */ + while (current != NULL) { + if (current->resumption) { + /* Set the HMAC to use based on the one for the session (set into + * the extension data at the start of this function based on the + * cipher suite in the session information. + */ + ssl->specs.mac_algorithm = current->hmac; + + /* Resumption PSK is master secret. */ + ssl->arrays->psk_keySz = GetMsgHashSize(ssl); + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else { + /* TODO: [TLS13] Support non-ticket PSK. */ + /* Get the pre-shared key. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char *)current->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Build the HMAC of the handshake message data = binder. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, + current->binder, ¤t->binderLen); + if (ret != 0) + return ret; + + current = current->next; + } + + /* Data entered into extension, now write to message. */ + len = TLSX_PreSharedKey_WriteBinders(ext->data, output + idx, client_hello); + + /* Hash binders to complete the hash of the ClientHello. */ + return HashOutputRaw(ssl, output + idx, len); +} +#endif + +/* Send a ClientHello message to the server. + * Include the information required to start a handshake with servers using + * protocol versions less than TLS v1.3. + * Only a client will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +int SendTls13ClientHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + if (ssl->options.resuming && + (ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor)) { + ssl->version.major = ssl->session.version.major; + ssl->version.minor = ssl->session.version.minor; + return SendClientHello(ssl); + } +#endif + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello"); + return SUITES_ERROR; + } + + /* Version | Random | Session Id | Cipher Suites | Compression | Ext */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; +#ifdef HAVE_QSH + if (QSH_Init(ssl) != 0) + return MEMORY_E; +#endif + /* Include length of TLS extensions. */ + length += TLSX_GetRequestSize(ssl); + + /* Total message size. */ + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, client_hello, ssl); + + /* Protocol version. */ + output[idx++] = SSLv3_MAJOR; + output[idx++] = TLSv1_2_MINOR; + ssl->chVersion = ssl->version; + + /* Client Random */ + if (ssl->options.connectState == CONNECT_BEGIN) { + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + + /* Store random for possible second ClientHello. */ + XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + } + else + XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); + idx += RAN_LEN; + + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; + + /* Cipher suites */ + c16toa(ssl->suites->suiteSz, output + idx); + idx += OPAQUE16_LEN; + XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); + idx += ssl->suites->suiteSz; + + /* Compression not supported in TLS v1.3. */ + output[idx++] = COMP_LEN; + output[idx++] = NO_COMPRESSION; + + /* Write out extensions for a request. */ + idx += TLSX_WriteRequest(ssl, output + idx); + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + /* Resumption has a specific set of extensions and binder is calculated + * for each identity. + */ + if (ssl->options.resuming) + ret = WritePSKBinders(ssl, output, idx); + else +#endif + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ClientHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); +} + +/* Parse and handle a HelloRetryRequest message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * HelloRetryRequest. + * On exit, the index of byte after the HelloRetryRequest message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + ProtocolVersion pv; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo); +#endif + + /* Version info and length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + /* Protocol version. */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + + /* Length of extension data. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (totalExtSz == 0) { + WOLFSSL_MSG("HelloRetryRequest must contain extensions"); + return MISSING_HANDSHAKE_DATA; + } + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + hello_retry_request, NULL))) + return ret; + /* The KeyShare extension parsing fails when not valid. */ + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST; + + return 0; +} + +/* Handle the ServerHello message from the server. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ServerHello. + * On exit, the index of byte after the ServerHello message. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + ProtocolVersion pv; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + word16 totalExtSz; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* Protocol version length check. */ + if (OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) { + ssl->version = pv; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } + + /* Random, cipher suite and extensions length check. */ + if ((i - begin) + RAN_LEN + OPAQUE16_LEN + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Server random - keep for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + /* TODO: [TLS13] Check last 8 bytes. */ + + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + + /* Get extension length and length check. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, server_hello, NULL); + if (ret != 0) + return ret; + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL) { + int secretSz = SECRET_LEN, ret; + ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } +#endif /* HAVE_SECRET_CALLBACK */ + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + +#ifndef NO_PSK + if (ssl->options.resuming) { + PreSharedKey *psk = NULL; + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext != NULL) + psk = (PreSharedKey*)ext->data; + while (psk != NULL && !psk->chosen) + psk = psk->next; + if (psk == NULL) { + ssl->options.resuming = 0; + ssl->arrays->psk_keySz = ssl->specs.hash_size; + XMEMSET(ssl->arrays->psk_key, 0, ssl->arrays->psk_keySz); + } + } +#endif + + ssl->keys.encryptionOn = 1; + + return ret; +} + +/* Parse and handle an EncryptedExtensions message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * EncryptedExtensions. + * On exit, the index of byte after the EncryptedExtensions + * message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("EncryptedExtensions", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo); +#endif + + /* Length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + encrypted_extensions, NULL))) + return ret; + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + return 0; +} + +/* Handle a TLS v1.3 CertificateRequest message. + * This message is always encrypted. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of CertificateRequest. + * On exit, the index of byte after the CertificateRequest message. + * size The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + word16 len; + word32 begin = *inOutIdx; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateRequest", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); + #endif + + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + /* Length of the request context. */ + len = input[(*inOutIdx)++]; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (ssl->options.connectState < FINISHED_DONE && len > 0) + return BUFFER_ERROR; + + /* Request context parsed here. */ + /* TODO: [TLS13] Request context for post-handshake auth. + * Store the value and return it in Certificate message. + * Must be unique in the scope of the connection. + */ + *inOutIdx += len; + + /* Signature and hash algorithms. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + PickHashSigAlgo(ssl, input + *inOutIdx, len); + *inOutIdx += len; + + /* Length of certificate authority data. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + /* Certificate authorities. */ + while (len) { + word16 dnSz; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &dnSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + dnSz > size) + return BUFFER_ERROR; + + *inOutIdx += dnSz; + len -= OPAQUE16_LEN + dnSz; + } + + /* TODO: [TLS13] Add extension handling. */ + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + /* Skip over extensions for now. */ + *inOutIdx += len; + + ssl->options.sendVerify = SEND_CERT; + + /* This message is always encrypted so add encryption padding. */ + *inOutIdx += ssl->keys.padSz; + + return 0; +} + +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) +/* Handle any Pre-Shared Key (PSK) extension. + * Must do this in ClientHello as it requires a hash of the truncated message. + * Don't know size of binders until Pre-Shared Key extension has been parsed. + * + * ssl The SSL/TLS object. + * input The ClientHello message. + * helloSz The size of the ClientHello message (including binders if present). + * usingPSK Indicates handshake is using Pre-Shared Keys. + * returns 0 on success and otherwise failure. + */ +static int DoPreSharedKeys(WOLFSSL *ssl, const byte* input, word32 helloSz, + int* usingPSK) +{ + int ret; + TLSX* ext; + word16 bindersLen; + PreSharedKey* current; + byte binderKey[MAX_DIGEST_SIZE]; + byte binder[MAX_DIGEST_SIZE]; + word32 binderLen; + word16 modes; + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return 0; + + /* Extensions pushed on stack/list and PSK must be last. */ + if (ssl->extensions != ext) + return PSK_KEY_ERROR; + + /* Assume we are going to resume with a pre-shared key. */ + ssl->options.resuming = 1; + + /* Find the pre-shared key extension and calculate hash of truncated + * ClientHello for binders. + */ + bindersLen = TLSX_PreSharedKey_GetSizeBinders(ext->data, client_hello); + + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz - bindersLen); + if (ret != 0) + return ret; + + /* Look through all client's pre-shared keys for a match. */ + current = (PreSharedKey*)ext->data; + while (current != NULL) { + /* TODO: [TLS13] Support non-ticket PSK. */ + /* Decode the identity. */ + ret = DoClientTicket(ssl, current->identity, current->identityLen); + if (ret != WOLFSSL_TICKET_RET_OK) + continue; + + if (current->resumption) { + /* Check the ticket isn't too old or new. */ + int diff = TimeNowInMilliseconds() - ssl->session.ticketSeen; + diff -= current->ticketAge - ssl->session.ticketAdd; + /* TODO: [TLS13] What should the value be? Configurable? */ + if (diff < -1000 || diff > 1000) { + /* Invalid difference, fallback to full handshake. */ + ssl->options.resuming = 0; + break; + } + + /* Use the same cipher suite as before and set up for use. */ + ssl->options.cipherSuite0 = ssl->session.cipherSuite0; + ssl->options.cipherSuite = ssl->session.cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Resumption PSK is resumption master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->specs.hash_size); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else { + /* PSK age is always zero. */ + if (current->ticketAge != ssl->session.ticketAdd) + return PSK_KEY_ERROR; + + /* Get the pre-shared key. */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char*)current->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Derive the binder and compare with the one in the extension. */ + ret = BuildTls13HandshakeHmac(ssl, + ssl->keys.client_write_MAC_secret, binder, &binderLen); + if (ret != 0) + return ret; + if (binderLen != current->binderLen || + XMEMCMP(binder, current->binder, binderLen) != 0) { + return BAD_BINDER; + } + + /* This PSK works, no need to try any more. */ + current->chosen = 1; + ext->resp = 1; + break; + } + + /* Hash the rest of the ClientHello. */ + ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); + if (ret != 0) + return ret; + + /* Get the PSK key exchange modes the client wants to negotiate. */ + ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (ext == NULL) + return MISSING_HANDSHAKE_DATA; + modes = ext->val; + + ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + /* Use (EC)DHE for forward-security if possible. */ + if (ext != NULL && (modes & (1 << PSK_DHE_KE)) != 0 && + !ssl->options.noPskDheKe) { + /* Only use named group used in last session. */ + ssl->namedGroup = ssl->session.namedGroup; + + /* Try to establish a new secret. */ + ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + return PSK_KEY_ERROR; + else if (ret > 0) + ret = 0; + + /* Send new public key to client. */ + ext->resp = 1; + } + else if ((modes & (1 << PSK_KE)) != 0) { + /* Don't send a key share extension back. */ + if (ext != NULL) + ext->resp = 0; + } + else + return PSK_KEY_ERROR; + + *usingPSK = 1; + + return ret; +} +#endif + +/* Handle a ClientHello handshake message. + * If the protocol version in the message is not TLS v1.3 or higher, use + * DoClientHello() + * Only a server will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ClientHello. + * On exit, the index of byte after the ClientHello message and + * padding. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + int ret; + byte b; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + word16 totalExtSz; + int usingPSK = 0; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("ClientHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + ssl->chVersion = pv; /* store */ + i += OPAQUE16_LEN; + + if ((ssl->version.major == SSLv3_MAJOR && + ssl->version.minor < TLSv1_3_MINOR) || ssl->options.dtls) { + return DoClientHello(ssl, input, inOutIdx, helloSz); + } + + /* Client random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("client random"); + WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); +#endif + + + /* Session id - empty in TLS v1.3 */ + b = input[i++]; + if (b != 0) { + WOLFSSL_MSG("Client sent session id - not supported"); + return BUFFER_ERROR; + } + + /* Cipher suites */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &clSuites.suiteSz); + i += OPAQUE16_LEN; + /* suites and compression length check */ + if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; + + /* Compression */ + b = input[i++]; + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + if (b != COMP_LEN) { + WOLFSSL_MSG("Must be one compression type in list"); + return INVALID_PARAMETER; + } + b = input[i++]; + if (b != NO_COMPRESSION) { + WOLFSSL_MSG("Must be no compression type in list"); + return INVALID_PARAMETER; + } + + /* TLS v1.3 ClientHello messages will have extensions. */ + if ((i - begin) >= helloSz) { + WOLFSSL_MSG("ClientHello must have extensions in TLS v1.3"); + return BUFFER_ERROR; + } + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifdef HAVE_QSH + QSH_Init(ssl); +#endif + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; + + /* Parse extensions */ + if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + &clSuites))) { + return ret; + } + +#ifdef HAVE_STUNNEL + if ((ret = SNI_Callback(ssl)) != 0) + return ret; +#endif /*HAVE_STUNNEL*/ + + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_VERSIONS) == NULL) + ssl->version.minor = pv.minor; + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_PSK) + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; +#endif + + if (!usingPSK) { + ret = MatchSuite(ssl, &clSuites); + if (ret < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return ret; + } + +#ifndef NO_PSK + if (ssl->options.resuming) { + ssl->options.resuming = 0; + XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); + /* May or may not have done any hashing. */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } +#endif + + ret = HashInput(ssl, input + begin, helloSz); + if (ret != 0) + return ret; + } + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + return 0; +} + +/* Send the HelloRetryRequest message to indicate the negotiated protocol + * version and security parameters the server is willing to use. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13HelloRetryRequest(WOLFSSL *ssl) +{ + int ret; + byte* output; + word32 length; + word32 len; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + /* Get the length of the extensions that will be written. */ + len = TLSX_GetResponseSize(ssl, hello_retry_request); + /* There must be extensions sent to indicate what client needs to do. */ + if (len == 0) + return MISSING_HANDSHAKE_DATA; + + /* Protocol version + Extensions */ + length = OPAQUE16_LEN + len; + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + /* Add record and hanshake headers. */ + AddTls13Headers(output, length, hello_retry_request, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* Add TLS extensions. */ + TLSX_WriteResponse(ssl, output + idx, hello_retry_request); + idx += len; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("HelloRetryRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("HelloRetryRequest", &ssl->timeoutInfo, output, sendSz, + ssl->heap); +#endif + + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +/* Send TLS v1.3 ServerHello message to client. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13ServerHello(WOLFSSL* ssl) +{ + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + /* Protocol version, server random, cipher suite and extensions. */ + length = VERSION_SZ + RAN_LEN + SUITE_LEN + + TLSX_GetResponseSize(ssl, server_hello); + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, server_hello, ssl); + + /* TODO: [TLS13] Replace existing code with code in comment. + * Use the TLS v1.3 draft version for now. + * + * Change to: + * output[idx++] = ssl->version.major; + * output[idx++] = ssl->version.minor; + */ + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* TODO: [TLS13] Last 8 bytes have special meaning. */ + /* Generate server random. */ + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + /* Store in SSL for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); + idx += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Server random"); + WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); +#endif + + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + + /* Extensions */ + TLSX_WriteResponse(ssl, output + idx, server_hello); + + ssl->buffers.outputBuffer.length += sendSz; + + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("ServerHello", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("ServerHello", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +/* Send the rest of the extensions encrypted under the handshake key. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13EncryptedExtensions(WOLFSSL *ssl) +{ + int ret; + byte* output; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + ssl->keys.encryptionOn = 1; + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + /* Derive the handshake secret now that we are at first message to be + * encrypted under the keys. + */ + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + /* Setup encrypt/decrypt keys for following messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + length = TLSX_GetResponseSize(ssl, encrypted_extensions); + sendSz = idx + length; + /* Encryption always on. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, encrypted_extensions, ssl); + + TLSX_WriteResponse(ssl, output + idx, encrypted_extensions); + idx += length; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("EncryptedExtensions", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("EncryptedExtensions", &ssl->timeoutInfo, output, + sendSz, ssl->heap); +#endif + + /* This handshake message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + if (ssl->options.groupMessages) + return 0; + else + return SendBuffered(ssl); +} + +#ifndef NO_CERTS +/* Send the TLS v1.3 CertificateRequest message. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13CertificateRequest(WOLFSSL* ssl) +{ + byte *output; + int ret; + int sendSz; + int reqCtxLen = 0; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + int reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; + + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + return 0; /* not needed */ + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + /* TODO: [TLS13] Request context for post-handshake auth. + * Must be unique in the scope of the connection. + */ + output[i++] = reqCtxLen; + + /* supported hash/sig */ + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); + i += LENGTH_SZ; + + XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + + /* Certificate authorities not supported yet - empty buffer. */ + c16toa(0, &output[i]); + i += REQ_HEADER_SZ; + + /* Certificate extensions. */ + /* TODO: [TLS13] Add extension handling. */ + c16toa(0, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; + + /* Always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateRequest", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateRequest", &ssl->timeoutInfo, output, + sendSz, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + return SendBuffered(ssl); + return 0; +} +#endif /* NO_CERTS */ +#endif /* NO_WOLFSSL_SERVER */ + +#ifndef NO_CERTS +#if !defined(NO_RSA) || defined(HAVE_ECC) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + output[0] = hashAlgo; + output[1] = rsa_sa_algo; + break; +#endif + /* PSS signatures: 0x080[4-6] */ + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + } +} + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static INLINE void DecodeSigAlg(byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case 0x08: + /* PSS signatures: 0x080[4-6] */ + if (input[1] <= 0x06) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + break; + /* ED25519: 0x0807 */ + /* ED448: 0x0808 */ + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} + +/* Get the hash of the messages so far. + * + * ssl The SSL/TLS object. + * hash The buffer to write the hash to. + * returns the length of the hash. + */ +static INLINE int GetMsgHash(WOLFSSL *ssl, byte* hash) +{ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + return SHA256_DIGEST_SIZE; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + return SHA384_DIGEST_SIZE; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + return SHA512_DIGEST_SIZE; + #endif /* WOLFSSL_SHA512 */ + } + return 0; +} + +/* The length of the certificate verification label - client and server. */ +#define CERT_VFY_LABEL_SZ 34 +/* The server certificate verification label. */ +static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, server CertificateVerify"; +/* The client certificate verification label. */ +static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, client CertificateVerify"; + +/* The number of prefix bytes for signature data. */ +#define SIGNING_DATA_PREFIX_SZ 64 +/* The prefix byte in the signature data. */ +#define SIGNING_DATA_PREFIX_BYTE 0x20 +/* Maximum length of the signature data. */ +#define MAX_SIG_DATA_SZ (SIGNING_DATA_PREFIX_SZ + \ + CERT_VFY_LABEL_SZ + \ + MAX_DIGEST_SIZE) + +/* Create the signature data for TLS v1.3 certificate verification. + * + * ssl The SSL/TLS object. + * sigData The signature data. + * sigDataSz The length of the signature data. + * check Indicates this is a check not create. + */ +static void CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, + int check) +{ + word16 idx; + int side = ssl->options.side; + + /* Signature Data = Prefix | Label | Handshake Hash */ + XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ); + idx = SIGNING_DATA_PREFIX_SZ; + + #ifndef NO_WOLFSSL_SERVER + if ((side == WOLFSSL_SERVER_END && check) || + (side == WOLFSSL_CLIENT_END && !check)) { + XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ); + } + #endif + #ifndef NO_WOLFSSL_CLIENT + if ((side == WOLFSSL_CLIENT_END && check) || + (side == WOLFSSL_SERVER_END && !check)) { + XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ); + } + #endif + idx += CERT_VFY_LABEL_SZ; + + *sigDataSz = idx + GetMsgHash(ssl, &sigData[idx]); +} + +#ifndef NO_RSA +/* Encode the PKCS #1.5 RSA signature. + * + * sig The buffer to place the encoded signature into. + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, + int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int hashOid = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + hashOid = SHA256h; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + hashOid = SHA384h; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + hashOid = SHA512h; + break; +#endif + } + + if (ret != 0) + return ret; + + /* Encode the signature data as per PKCS #1.5 */ + return wc_EncodeSignature(sig, sigData, hashSz, hashOid); +} + +#ifdef HAVE_ECC +/* Encode the ECC signature. + * + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif + + +/* Check that the decrypted signature matches the encoded signature + * based on the digest of the signature data. + * + * ssl The SSL/TLS object. + * hashAlgo The signature algorithm used to generate signature. + * hashAlgo The hash algorithm used to generate signature. + * decSig The decrypted signature. + * decSigSz The size of the decrypted signature. + * returns 0 on success, otherwise failure. + */ +static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, + byte* decSig, word32 decSigSz) +{ + int ret = 0; + byte sigData[MAX_SIG_DATA_SZ]; + word16 sigDataSz; +#ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; +#else + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + word32 sigSz; + + if (sigAlgo == rsa_sa_algo) { +#ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ret = MEMORY_E; + goto end; + } +#endif + + CreateSigData(ssl, sigData, &sigDataSz, 1); + sigSz = CreateRSAEncodedSig(encodedSig, sigData, sigDataSz, hashAlgo); + /* Check the encoded and decrypted signature data match. */ + if (decSigSz != sigSz || decSig == NULL || + XMEMCMP(decSig, encodedSig, sigSz) != 0) { + ret = VERIFY_CERT_ERROR; + } + } + else { + CreateSigData(ssl, sigData, &sigDataSz, 1); + sigSz = CreateECCEncodedSig(sigData, sigDataSz, hashAlgo); + if (decSigSz != sigSz || decSig == NULL) + ret = VERIFY_CERT_ERROR; + else { + decSig -= 2 * decSigSz; + XMEMCPY(decSig, sigData, decSigSz); + decSig -= 8; + XMEMSET(decSig, 0, 8); + CreateECCEncodedSig(decSig, 8 + decSigSz * 2, hashAlgo); + if (XMEMCMP(decSig, decSig + 8 + decSigSz * 2, decSigSz) != 0) + ret = VERIFY_CERT_ERROR; + } + } + +#ifdef WOLFSSL_SMALL_STACK +end: + if (encodedSig != NULL) + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* !NO_RSA */ +#endif /* !NO_RSA || HAVE_ECC */ + +/* Get the next certificate from the list for writing into the TLS v1.3 + * Certificate message. + * + * data The certificate list. + * length The length of the certificate data in the list. + * idx The index of the next certificate. + * returns the length of the certificate data. 0 indicates no more certificates + * in the list. + */ +static word32 NextCert(byte* data, word32 length, word32* idx) +{ + word32 len; + + /* Is index at end of list. */ + if (*idx == length) + return 0; + + /* Length of the current ASN.1 encoded certificate. */ + c24to32(data + *idx, &len); + /* Include the length field. */ + len += 3; + + /* Move index to next certificate and return the current certificate's + * length. + */ + *idx += len; + return len; +} + +/* Add certificate data and empty extension to output up to the fragment size. + * + * cert The certificate data to write out. + * len The length of the certificate data. + * idx The start of the certificate data to write out. + * fragSz The maximum size of this fragment. + * output The buffer to write to. + * returns the number of bytes written. + */ +static word32 AddCertExt(byte* cert, word32 len, word32 idx, word32 fragSz, + byte* output) +{ + word32 i = 0; + word32 copySz = min(len - idx, fragSz); + + if (idx < len) { + XMEMCPY(output, cert + idx, copySz); + i = copySz; + } + + if (copySz + OPAQUE16_LEN <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + + return i; +} + +/* Send the certificate for this end and any CAs that help with validation. + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13Certificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + word32 len = 0; + word32 idx = 0; + word32 offset = OPAQUE16_LEN; + byte* p = NULL; + + + /* TODO: [TLS13] Request context for post-handshake auth. + * Taken from request if post-handshake. + */ + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; + length = CERT_HEADER_SZ; + listSz = 0; + } + else { + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + /* Certificate Data */ + certSz = ssl->buffers.certificate->length; + /* Cert Req Ctx Len | Cert List Len | Cert Data Len */ + headerSz = OPAQUE8_LEN + CERT_HEADER_SZ + CERT_HEADER_SZ; + /* Length of message data with one certificate and empty extensions. */ + length = headerSz + certSz + OPAQUE16_LEN; + /* Length of list data with one certificate and empty extensions. */ + listSz = CERT_HEADER_SZ + certSz + OPAQUE16_LEN; + + /* Send rest of chain if sending cert (chain has leading size/s). */ + if (certSz > 0 && ssl->buffers.certChainCnt > 0) { + /* The pointer to the current spot in the cert chain buffer. */ + p = ssl->buffers.certChain->buffer; + /* Chain length including extensions. */ + certChainSz = ssl->buffers.certChain->length + + OPAQUE16_LEN * ssl->buffers.certChainCnt; + length += certChainSz; + listSz += certChainSz; + } + else + certChainSz = 0; + } + + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = MAX_RECORD_SIZE; + + #ifdef HAVE_MAX_FRAGMENT + if (ssl->max_fragment != 0 && maxFragment >= ssl->max_fragment) + maxFragment = ssl->max_fragment; + #endif /* HAVE_MAX_FRAGMENT */ + + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; + + if (ssl->fragOffset == 0) { + if (headerSz + certSz + OPAQUE16_LEN + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + + fragSz = headerSz + certSz + OPAQUE16_LEN + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + + /* Request context. */ + output[i++] = 0; + length -= 1; + fragSz -= 1; + /* Certificate list length. */ + c32to24(listSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + /* Leaf certificate data length. */ + if (certSz > 0) { + c32to24(certSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + } + } + else + AddTls13RecordHeader(output, fragSz, handshake, ssl); + + /* TODO: [TLS13] Test with fragments and multiple CA certs */ + if (certSz > 0 && ssl->fragOffset < certSz + OPAQUE16_LEN) { + /* Put in the leaf certificate and empty extension. */ + word32 copySz = AddCertExt(ssl->buffers.certificate->buffer, certSz, + ssl->fragOffset, fragSz, output + i); + + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz > 0 && fragSz > 0) { + /* Put in the CA certificates with empty extensions. */ + while (fragSz > 0) { + word32 l; + + if (offset == len + OPAQUE16_LEN) { + /* Find next CA certificate to write out. */ + offset = 0; + len = NextCert(ssl->buffers.certChain->buffer, + ssl->buffers.certChain->length, &idx); + if (len == 0) + break; + } + + /* Write out certificate and empty extension. */ + l = AddCertExt(p, len, offset, fragSz, output + i); + i += l; + ssl->fragOffset += l; + length -= l; + fragSz -= l; + offset += l; + } + } + + if ((int)i - RECORD_HEADER_SZ < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, + output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("Certificate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Certificate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + return ret; +} + +typedef struct Scv13Args { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 sigLen; + int sendSz; + word16 length; + + byte* sigData; + word16 sigDataSz; +} Scv13Args; + +static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) +{ + Scv13Args* args = (Scv13Args*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->verifySig = NULL; + } +#endif + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigData = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->input = NULL; + } +} + +/* Send the TLS v1.3 CertificateVerify message. + * A hash of all the message so far is used. + * The signed data is: + * 0x20 * 64 | context string | 0x00 | hash of messages + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13CertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Scv13Args* args = (Scv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Scv13Args args[1]; +#endif + + WOLFSSL_ENTER("SendTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Scv13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ + } + + args->sendSz = MAX_CERT_VERIFY_SZ; + /* Always encrypted. */ + args->sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* idx is used to track verify pointer offset to output */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) + goto exit_scv; + + /* Add signature algorithm. */ + EncodeSigAlg(ssl->suites->hashAlgo, ssl->hsType, args->verify); + + /* Create the data to be signed. */ + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* build encoded signature buffer */ + sig->length = MAX_ENCODED_SIG_SZ; + sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + /* Digest the signature data and encode. Used in verify too. */ + ret = CreateRSAEncodedSig(sig->buffer, args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + sig->length = ret; + ret = 0; + + /* Maximum size of RSA Signature. */ + args->sigLen = args->length; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + sig->length = args->sendSz - args->idx - HASH_SIG_SIZE - + VERIFY_HEADER; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + args->sigDataSz = ret; + ret = 0; + } + #endif /* HAVE_ECC */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ret = EccSign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + &sig->length, (ecc_key*)ssl->hsKey, + #if defined(HAVE_PK_CALLBACKS) + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->EccSignCtx + #else + NULL, 0, NULL + #endif + ); + args->length = sig->length; + } + #endif /* HAVE_ECC */ + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + ret = RsaSign(ssl, sig->buffer, sig->length, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + (RsaKey*)ssl->hsKey, + ssl->buffers.key->buffer, ssl->buffers.key->length, + #ifdef HAVE_PK_CALLBACKS + ssl->RsaSignCtx + #else + NULL + #endif + ); + args->length = args->sigLen; + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Add signature length. */ + c16toa(args->length, args->verify + HASH_SIG_SIZE); + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigLen, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(args->verifySig, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + args->sigLen); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->verifySig, args->sigLen, + sig->buffer, sig->length, (RsaKey*)ssl->hsKey); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + /* Put the record and handshake headers on. */ + AddTls13Headers(args->output, args->length + HASH_SIG_SIZE + VERIFY_HEADER, + certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + args->length + + HASH_SIG_SIZE + VERIFY_HEADER; + + /* This message is always encrypted. */ + args->sendSz = BuildTls13Message(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ, handshake, + 1, 0); + if (args->sendSz < 0) { + ret = args->sendSz; + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName("CertificateVerify", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("CertificateVerify", &ssl->timeoutInfo, + args->output, args->sendSz, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeScv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + + +/* Parse and handle a TLS v1.3 Certificate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Certificate. + * On exit, the index of byte after the Certificate message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + return ProcessPeerCerts(ssl, input, inOutIdx, totalSz); +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) + +typedef struct Dcv13Args { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + + byte* sigData; + word16 sigDataSz; +} Dcv13Args; + +static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) +{ + Dcv13Args* args = (Dcv13Args*)pArgs; + + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + args->sigData = NULL; + } + + (void)ssl; +} + +/* Parse and handle a TLS v1.3 CertificateVerify message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * CertificateVerify. + * On exit, the index of byte after the CertificateVerify message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Dcv13Args* args = (Dcv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dcv13Args args[1]; +#endif + + WOLFSSL_ENTER("DoTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dcv13Args)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("CertificateVerify", + &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("CertificateVerify", + &ssl->timeoutInfo); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* Signature algorithm. */ + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + DecodeSigAlg(input + args->idx, &args->hashAlgo, &args->sigAlgo); + args->idx += OPAQUE16_LEN; + /* TODO: [TLS13] was it in SignatureAlgorithms extension? */ + + /* Signature length. */ + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; + + /* Signature data. */ + if ((args->idx - args->begin) + args->sz > totalSz || + args->sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + /* Check for public key of required type. */ + if (args->sigAlgo == ecc_dsa_sa_algo && + !ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + if ((args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) && + (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + + sig->buffer = XMALLOC(args->sz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + sig->length = args->sz; + XMEMCPY(sig->buffer, input + args->idx, args->sz); + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, args->hashAlgo); + if (ret < 0) + goto exit_dcv; + args->sigDataSz = ret; + ret = 0; + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo || + args->sigAlgo == rsa_pss_sa_algo) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, sig->buffer, sig->length, &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerRsaKey.buffer, + ssl->buffers.peerRsaKey.length, + ssl->RsaVerifyCtx + #else + NULL, 0, NULL + #endif + ); + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer, + ssl->buffers.peerEccDsaKey.length, + ssl->EccVerifyCtx + #else + NULL, 0, NULL + #endif + ); + } + #endif /* HAVE_ECC */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo, + args->output, args->sendSz); + if (ret != 0) + goto exit_dcv; + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* Encryption is always on: add padding */ + *inOutIdx += ssl->keys.padSz; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + + case TLS_ASYNC_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dcv: + + WOLFSSL_LEAVE("DoTls13CertificateVerify", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not recevied so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeDcv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} +#endif /* !NO_RSA || HAVE_ECC */ + +/* Parse and handle a TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size Length of message data. + * totalSz Length of remaining data in the message buffer. + * sniff Indicates whether we are sniffing packets. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff) +{ + int ret; + word32 finishedSz = 0; + byte* secret; + byte mac[MAX_DIGEST_SIZE]; + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* All the handshake messages have been received to calculate + * client and server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + else + secret = ssl->keys.client_write_MAC_secret; + + ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); + if (ret != 0) + return ret; + if (size != finishedSz) + return BUFFER_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); + #endif + + if (sniff == NO_SNIFF) { + /* Actually check verify data. */ + if (XMEMCMP(input + *inOutIdx, mac, size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + return VERIFY_FINISHED_ERROR; + } + } + + /* Force input exhaustion at ProcessReply by consuming padSz. */ + *inOutIdx += size + ssl->keys.padSz; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Setup keys for application data messages from client. */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } + +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + if (!ssl->options.resuming) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } +#endif +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif + + return 0; +} +#endif /* NO_CERTS */ + +/* Send the TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13Finished(WOLFSSL* ssl) +{ + int sendSz; + int finishedSz = ssl->specs.hash_size; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + byte* secret; + + outputSz = MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + secret = ssl->keys.client_write_MAC_secret; + else { + /* All the handshake messages have been done to calculate client and + * server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->arrays->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->arrays->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL); + if (ret != 0) + return ret; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + finishedSz, handshake, 1, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + if (!ssl->options.resuming) { +#ifndef NO_SESSION_CACHE + AddSession(ssl); /* just try */ +#endif + } + else { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("Finished", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0) + return ret; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Can send application data now. */ + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* Setup keys for application data messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + +#ifndef NO_PSK + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); +#endif + } + + return ret; +} + +/* Send the TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13KeyUpdate(WOLFSSL* ssl) +{ + int sendSz; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl); + + /* If: + * 1. I haven't sent a KeyUpdate requesting a response and + * 2. This isn't responding to peer KeyUpdate requiring a response then, + * I want a response. + */ + ssl->keys.updateResponseReq = output[i++] = + !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond; + /* Sent response, no longer need to respond. */ + ssl->keys.keyUpdateRespond = 0; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + OPAQUE8_LEN, handshake, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName("KeyUpdate", &ssl->handShakeInfo); + if (ssl->toInfoOn) + AddPacketInfo("KeyUpdate", &ssl->timeoutInfo, output, sendSz, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0 && ret != WANT_WRITE) + return ret; + + /* Future traffic uses new encryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY)) + != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + return ret; +} + +/* Parse and handle a TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + word32 i = *inOutIdx; + + /* check against totalSz */ + if (OPAQUE8_LEN != totalSz) + return BUFFER_E; + + switch (input[i]) { + case update_not_requested: + /* This message in response to any oustanding request. */ + ssl->keys.keyUpdateRespond = 0; + ssl->keys.updateResponseReq = 0; + break; + case update_requested: + /* New key update requiring a response. */ + ssl->keys.keyUpdateRespond = 1; + break; + default: + return INVALID_PARAMETER; + break; + } + + /* Move index to byte after message. */ + *inOutIdx += totalSz; + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + /* Future traffic uses new decryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + if (ssl->keys.keyUpdateRespond) + return SendTls13KeyUpdate(ssl); + return 0; +} + +#ifndef NO_WOLFSSL_CLIENT +/* Handle a New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size The length of the current handshake message. + * retuns 0 on success, otherwise failure. + */ +static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ +#ifdef HAVE_SESSION_TICKET + word32 begin = *inOutIdx; + word32 lifetime; + word32 ageAdd; + word16 length; + + /* Lifetime hint. */ + if ((*inOutIdx - begin) + SESSION_HINT_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += SESSION_HINT_SZ; + if (lifetime > MAX_LIFETIME) + return SERVER_HINT_ERROR; + + /* Age add. */ + if ((*inOutIdx - begin) + SESSION_ADD_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &ageAdd); + *inOutIdx += SESSION_ADD_SZ; + + /* Ticket length. */ + if ((*inOutIdx - begin) + LENGTH_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += LENGTH_SZ; + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + /* Free old dynamic ticket if we already had one. */ + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + /* Reset back to static by default. */ + ssl->session.ticket = NULL; + ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session.staticTicket; + } + /* Use dynamic ticket if required.*/ + if (length > sizeof(ssl->session.staticTicket)) { + ssl->session.ticket = (byte*)XMALLOC(length, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (ssl->session.ticket == NULL) + return MEMORY_E; + ssl->session.isDynamic = 1; + } + + /* Copy in ticket data (server identity). */ + XMEMCPY(ssl->session.ticket, input + *inOutIdx, length); + *inOutIdx += length; + ssl->timeout = lifetime; + ssl->session.ticketLen = length; + ssl->session.timeout = lifetime; + ssl->session.ticketAdd = ageAdd; + ssl->session.ticketSeen = TimeNowInMilliseconds(); + if (ssl->session_ticket_cb != NULL) { + ssl->session_ticket_cb(ssl, ssl->session.ticket, + ssl->session.ticketLen, + ssl->session_ticket_ctx); + } + ssl->options.haveSessionId = 1; + XMEMCPY(ssl->arrays->sessionID, ssl->session.ticket + length - ID_LEN, + ID_LEN); + ssl->session.cipherSuite0 = ssl->options.cipherSuite0; + ssl->session.cipherSuite = ssl->options.cipherSuite; + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* No extension support - skip over extensions. */ + if ((*inOutIdx - begin) + EXTS_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += EXTS_SZ; + if ((*inOutIdx - begin) + length != size) + return BUFFER_ERROR; + *inOutIdx += length; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ssl->expect_session_ticket = 0; +#else + (void)ssl; + (void)input; + *inOutIdx += size + ssl->keys.padSz; +#endif /* HAVE_SESSION_TICKET */ + + return 0; +} +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #ifdef HAVE_SESSION_TICKET +/* Send New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * retuns 0 on success, otherwise failure. + */ +int SendTls13NewSessionTicket(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + if (!ssl->options.noTicketTls13) { + ret = CreateTicket(ssl); + if (ret != 0) return ret; + } + + /* Lifetime | Age Add | Ticket | Extensions */ + length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + + ssl->session.ticketLen + EXTS_SZ; + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, session_ticket, ssl); + + /* Lifetime hint */ + c32toa(ssl->ctx->ticketHint, output + idx); + idx += SESSION_HINT_SZ; + /* Age add - obfuscator */ + c32toa(ssl->session.ticketAdd, output + idx); + idx += SESSION_ADD_SZ; + + /* length */ + c16toa(ssl->session.ticketLen, output + idx); + idx += LENGTH_SZ; + /* ticket */ + XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); + idx += ssl->session.ticketLen; + + /* No extension support - empty extensions. */ + c16toa(0, output + idx); + idx += EXTS_SZ; + + ssl->options.haveSessionId = 1; + + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); +} + #endif /* HAVE_SESSION_TICKET */ +#endif /* NO_WOLFSSL_SERVER */ + +/* Make sure no duplicates, no fast forward, or other problems + * + * ssl The SSL/TLS object. + * type Type of handshake message received. + * returns 0 on success, otherwise failure. + */ +static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + if (ssl->msgsReceived.got_client_hello == 2) { + WOLFSSL_MSG("Too many ClientHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_hello++; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + if (ssl->msgsReceived.got_session_ticket) { + WOLFSSL_MSG("Duplicate SessionTicket received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + if (ssl->msgsReceived.got_hello_retry_request) { + WOLFSSL_MSG("Duplicate HelloRetryRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_retry_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case encrypted_extensions: + if (ssl->msgsReceived.got_encrypted_extensions) { + WOLFSSL_MSG("Duplicate EncryptedExtensions received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_encrypted_extensions = 1; + + break; +#endif + + case certificate: + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ( ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if ( ssl->msgsReceived.got_client_hello == 0) { + WOLFSSL_MSG("No ClientHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + + case certificate_verify: + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + break; + + case finished: + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + break; + + case key_update: + if (!ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("No KeyUpdate before Finished"); + return OUT_OF_ORDER_E; + } + break; + + default: + WOLFSSL_MSG("Unknown message type"); + return SANITY_MSG_E; + } + + return 0; +} + +/* Handle a type of handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * size The length of the current handshake message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + (void)totalSz; + word32 inIdx = *inOutIdx; + + WOLFSSL_ENTER("DoTls13HandShakeMsgType"); + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) + return INCOMPLETE_DATA; + + /* sanity check msg received */ + if ( (ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + return ret; + } + +#ifdef WOLFSSL_CALLBACKS + /* add name later, add on record and handshake header part back on */ + if (ssl->toInfoOn) { + int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + AddPacketInfo(0, &ssl->timeoutInfo, input + *inOutIdx - add, + size + add, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } +#endif + + if (ssl->options.handShakeState == HANDSHAKE_DONE && + type != session_ticket && type != certificate_request && + type != key_update) { + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && !ssl->options.dtls && + ssl->options.serverState == NULL_STATE && + type != server_hello && type != hello_retry_request) { + WOLFSSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls && + type == server_hello_done && + ssl->options.serverState < SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("Server hello done received before server hello in DTLS"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + switch (type) { + +#ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + WOLFSSL_MSG("processing hello rety request"); + ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); + break; + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size); + break; + +#ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); + break; +#endif + + case session_ticket: + WOLFSSL_MSG("processing new session ticket"); + ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + break; + + case encrypted_extensions: + WOLFSSL_MSG("processing encrypted extensions"); + ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_CERTS + case certificate: + WOLFSSL_MSG("processing certificate"); + ret = DoTls13Certificate(ssl, input, inOutIdx, size); + break; +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + + case key_update: + WOLFSSL_MSG("processing finished"); + ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); + break; + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_SERVER */ + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + + if (ret == 0 && type != client_hello && type != session_ticket && + type != key_update && ssl->error != WC_PENDING_E) { + ret = HashInput(ssl, input + inIdx, size); + } + + if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) + SendAlert(ssl, alert_fatal, decode_error); + + if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || + ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || + ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + + if (ssl->options.tls1_3) { + if (type == server_hello && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + + /* setup decrypt keys for following messages */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (type == finished && ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + } + +#ifndef NO_PSK + if (type == finished && ssl->options.side == WOLFSSL_SERVER_END) + DeriveResumptionSecret(ssl, ssl->session.masterSecret); +#endif + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async, offset index so this msg will be processed again */ + if (ret == WC_PENDING_E) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + } +#endif + + WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret); + return ret; +} + + +/* Handle a handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoTls13HandShakeMsg()"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) + return PARSE_ERROR; + + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) + return PARSE_ERROR; + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + else { + if (inputLength + ssl->arrays->pendingMsgOffset > + ssl->arrays->pendingMsgSz) { + return BUFFER_ERROR; + } + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = 0; + ret = DoTls13HandShakeMsgType(ssl, + ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, + ssl->arrays->pendingMsgSz); + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + + WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret); + return ret; +} + +/* The client connecting to the server. + * The protocol version is expecting to be TLS v1.3. + * If the server downgrades, and older versions of the protocol are compiled + * in, the client will fallback to wolfSSL_connect(). + * Please see note at top of README if you get an error from connect. + * + * ssl The SSL/TLS object. + * returns SSL_SUCCESS on successful handshake, SSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_connect_TLSv13(WOLFSSL* ssl) +{ + int neededState; + + WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN: + /* Always send client hello first. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; + + case CLIENT_HELLO_SENT: + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state. */ + if (neededState == SERVER_FINISHED_COMPLETE && + !ssl->options.resuming) { + neededState = SERVER_HELLODONE_COMPLETE; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN: + if (ssl->options.certOnly) + return SSL_SUCCESS; + + if (!ssl->options.tls1_3) + return wolfSSL_connect(ssl); + + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + ssl->options.serverState = NULL_STATE; + /* Try again with different security parameters. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY: + if (ssl->options.serverState == NULL_STATE) { + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + + /* Get the response/s from the server. */ + while (ssl->options.serverState < neededState) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) + neededState = SERVER_HELLODONE_COMPLETE; + } + } + } + + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13Certificate(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13CertificateVerify(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; + + case FIRST_REPLY_SECOND: + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb != NULL) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + WOLFSSL_LEAVE("SSL_connect()", SSL_SUCCESS); + return SSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return SSL_FATAL_ERROR; /* unknown connect state */ + } +} + +/* Create a key share entry from group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * group The named group. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) +{ + int ret = BAD_FUNC_ARG; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + if (ret != 0) + return ret; + + return SSL_SUCCESS; +} + +/* Send no key share entries - use HelloRetryRequest to negotiate shared group. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_NoKeyShares(WOLFSSL* ssl) +{ + int ret = BAD_FUNC_ARG; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + return SSL_SUCCESS; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + ctx->noTicketTls13 = 1; +#endif + + return 0; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on + * a client and 0 on success. + */ +int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version) || + ssl->options.side == WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = 1; +#endif + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->noPskDheKe = 1; + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on + * success. + */ +int wolfSSL_no_dhe_psk(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ssl->options.noPskDheKe = 1; + + return 0; +} + +/* Update the keys for encryption and decryption. + * If using non-blocking I/O and SSL_ERROR_WANT_WRITE is returned then + * calling wolfSSL_write() will have the message sent when ready. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write, + * SSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_update_keys(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ret = SendTls13KeyUpdate(ssl); + if (ret == WANT_WRITE) + ret = SSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = SSL_SUCCESS; + return ret; +} + +/* The server accepting a connection from a client. + * The protocol version is expecting to be TLS v1.3. + * If the client downgrades, and older versions of the protocol are compiled + * in, the server will fallback to wolfSSL_accept(). + * Please see note at top of README if you get an error from accept. + * + * ssl The SSL/TLS object. + * returns SSL_SUCCESS on successful handshake, SSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_accept_TLSv13(WOLFSSL* ssl) +{ + word16 havePSK = 0; + word16 haveAnon = 0; + WOLFSSL_ENTER("SSL_accept_TLSv13()"); + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif + (void)havePSK; + +#ifdef HAVE_ANON + haveAnon = ssl->options.haveAnon; +#endif + (void)haveAnon; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return SSL_FATAL_ERROR; + } + +#ifndef NO_CERTS + /* in case used set_accept_state after init */ + if (!havePSK && !haveAnon && + (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer || + !ssl->buffers.key || + !ssl->buffers.key->buffer)) { + WOLFSSL_MSG("accept error: don't have server cert and key"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } +#endif +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } +#endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + + switch (ssl->options.acceptState) { + + case ACCEPT_BEGIN : + /* get response */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; + + case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case ACCEPT_HELLO_RETRY_REQUEST_DONE : + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_FIRST_REPLY_DONE : + if ((ssl->error = SendTls13ServerHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case SERVER_HELLO_SENT : + if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_EXTENSIONS_SENT; + WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT"); + FALL_THROUGH; + + case SERVER_EXTENSIONS_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + ssl->error = SendTls13CertificateRequest(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } + } +#endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case CERT_REQ_SENT : + ssl->options.acceptState = KEY_EXCHANGE_SENT; +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if ((ssl->error = SendTls13Certificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case CERT_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; + + case CERT_VERIFY_SENT : + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; + + case ACCEPT_FINISHED_DONE : +#ifdef HAVE_SESSION_TICKET + /* TODO: [TLS13] Section 4.5.1 Note. */ + if (!ssl->options.resuming && !ssl->options.verifyPeer && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TICKET_SENT: + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_SECOND_REPLY_DONE : +#ifdef HAVE_SESSION_TICKET + if (!ssl->options.resuming && ssl->options.verifyPeer && + !ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_THIRD_REPLY_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return SSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + +#ifdef WOLFSSL_SESSION_EXPORT + if (ssl->dtls_export) { + if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { + WOLFSSL_MSG("Export DTLS session error"); + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; + } + } +#endif + + WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS); + return SSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return SSL_FATAL_ERROR; + } +} + + +#undef ERROR_OUT + +#endif /* WOLFCRYPT_ONLY */ + +#endif /* WOLFSSL_TLS13 */ diff --git a/support/wolfssl.pc b/support/wolfssl.pc index 41636af6d..560a4b984 100644 --- a/support/wolfssl.pc +++ b/support/wolfssl.pc @@ -5,6 +5,6 @@ includedir=${prefix}/include Name: wolfssl Description: wolfssl C library. -Version: 3.10.0 +Version: 3.11.1 Libs: -L${libdir} -lwolfssl Cflags: -I${includedir} diff --git a/tests/api.c b/tests/api.c index 26eea6794..779e27fbe 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36,6 +36,9 @@ #ifdef HAVE_ECC #include /* wc_ecc_fp_free */ #endif +#ifndef NO_ASN + #include +#endif #include #include @@ -43,9 +46,32 @@ #include #include +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifdef WOLFSSL_SHA512 + #include +#endif +#ifdef WOLFSSL_SHA384 + #include +#endif +#ifdef WOLFSSL_RIPEMD + #include +#endif + #ifdef OPENSSL_EXTRA #include #include + #include + #include + #include + #include #ifndef NO_DES3 #include #endif @@ -57,6 +83,16 @@ #endif #include + +typedef struct testVector { + const char* input; + const char* output; + size_t inLen; + size_t outLen; + +} testVector; + + /*----------------------------------------------------------------------------* | Constants *----------------------------------------------------------------------------*/ @@ -70,7 +106,7 @@ static const char* passed = "passed"; static const char* failed = "failed"; #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) - static const char* bogusFile = + static const char* bogusFile = #ifdef _WIN32 "NUL" #else @@ -79,6 +115,12 @@ static const char* failed = "failed"; ; #endif +enum { + TESTING_RSA = 1, + TESTING_ECC = 2 +}; + + /*----------------------------------------------------------------------------* | Setup *----------------------------------------------------------------------------*/ @@ -195,20 +237,20 @@ static void test_wolfSSL_CTX_use_certificate_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCert, + AssertFalse(wolfSSL_CTX_use_certificate_file(NULL, svrCertFile, SSL_FILETYPE_PEM)); /* invalid cert file */ AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* invalid cert type */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert, 9999)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, 9999)); #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCert,SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,SSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -250,21 +292,21 @@ static void test_wolfSSL_CTX_use_PrivateKey_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKey, + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(NULL, svrKeyFile, SSL_FILETYPE_PEM)); /* invalid key file */ AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* invalid key type */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, 9999)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, 9999)); /* success */ #ifdef NO_RSA /* rsa needed */ - AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertFalse(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #else /* success */ - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #endif wolfSSL_CTX_free(ctx); @@ -286,11 +328,11 @@ static void test_wolfSSL_CTX_trust_peer_cert(void) SSL_FILETYPE_PEM) != SSL_SUCCESS); assert(wolfSSL_CTX_trust_peer_cert(ctx, bogusFile, SSL_FILETYPE_PEM) != SSL_SUCCESS); - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, SSL_FILETYPE_ASN1) != SSL_SUCCESS); /* success */ - assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCert, SSL_FILETYPE_PEM) + assert(wolfSSL_CTX_trust_peer_cert(ctx, cliCertFile, SSL_FILETYPE_PEM) == SSL_SUCCESS); /* unload cert */ @@ -331,20 +373,21 @@ static void test_wolfSSL_CTX_load_verify_locations(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); /* invalid context */ - AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCert, 0)); + AssertFalse(wolfSSL_CTX_load_verify_locations(NULL, caCertFile, 0)); /* invalid ca file */ - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); - AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, NULL, 0)); + AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, bogusFile, 0)); + #ifndef WOLFSSL_TIRTOS /* invalid path */ /* not working... investigate! */ - /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCert, bogusFile)); */ + /* AssertFalse(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, bogusFile)); */ #endif /* success */ - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); wolfSSL_CTX_free(ctx); #endif @@ -359,16 +402,16 @@ static void test_wolfSSL_CTX_SetTmpDH_file(void) /* invalid context */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + dhParamFile, SSL_FILETYPE_PEM)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, NULL, SSL_FILETYPE_PEM)); AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, bogusFile, SSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParam, + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_file(ctx, dhParamFile, SSL_FILETYPE_PEM)); wolfSSL_CTX_free(ctx); @@ -386,7 +429,7 @@ static void test_wolfSSL_CTX_SetTmpDH_buffer(void) AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(NULL, NULL, 0, SSL_FILETYPE_ASN1)); AssertIntNE(SSL_SUCCESS, wolfSSL_CTX_SetTmpDH_buffer(ctx, dsa_key_der_2048, @@ -414,8 +457,8 @@ static void test_server_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_server_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -443,7 +486,7 @@ static void test_client_wolfSSL_new(void) AssertNotNull(ctx_nocert = wolfSSL_CTX_new(wolfSSLv23_client_method())); AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); - AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertTrue(wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); /* invalid context */ AssertNull(ssl = wolfSSL_new(NULL)); @@ -469,30 +512,30 @@ static void test_wolfSSL_SetTmpDH_file(void) AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_server_method())); #ifndef NO_RSA - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCert, + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); #else - AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCert, + AssertTrue(wolfSSL_CTX_use_certificate_file(ctx, eccCertFile, SSL_FILETYPE_PEM)); - AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKey, + AssertTrue(wolfSSL_CTX_use_PrivateKey_file(ctx, eccKeyFile, SSL_FILETYPE_PEM)); #endif AssertNotNull(ssl = wolfSSL_new(ctx)); /* invalid ssl */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(NULL, - dhParam, SSL_FILETYPE_PEM)); + dhParamFile, SSL_FILETYPE_PEM)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, NULL, SSL_FILETYPE_PEM)); AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, bogusFile, SSL_FILETYPE_PEM)); /* success */ - AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParam, + AssertIntEQ(SSL_SUCCESS, wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM)); wolfSSL_free(ssl); @@ -517,7 +560,7 @@ static void test_wolfSSL_SetTmpDH_buffer(void) AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, dh_key_der_2048, sizeof_dh_key_der_2048, SSL_FILETYPE_ASN1)); - /* invalid dhParam file */ + /* invalid dhParamFile file */ AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(NULL, NULL, 0, SSL_FILETYPE_ASN1)); AssertIntNE(SSL_SUCCESS, wolfSSL_SetTmpDH_buffer(ssl, dsa_key_der_2048, @@ -529,13 +572,12 @@ static void test_wolfSSL_SetTmpDH_buffer(void) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - printf("SUCCESS4\n"); #endif } /* Test function for wolfSSL_SetMinVersion. Sets the minimum downgrade version - * allowed. + * allowed. * POST: return 1 on success. */ static int test_wolfSSL_SetMinVersion(void) @@ -633,12 +675,17 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_server_method(); + if (((func_args*)args)->callbacks != NULL && + ((func_args*)args)->callbacks->method != NULL) { + method = ((func_args*)args)->callbacks->method(); + } + else { + method = wolfSSLv23_server_method(); + } ctx = wolfSSL_CTX_new(method); #if defined(USE_WINDOWS_API) - /* Generate random port for testing */ - port = GetRandomPort(); + port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ @@ -655,19 +702,19 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0) != SSL_SUCCESS) { /*err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load server cert chain file, " "Please run from wolfSSL home dir");*/ goto done; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load server key file, " @@ -686,7 +733,7 @@ static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args) #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -776,26 +823,32 @@ static void test_client_nofail(void* args) #endif ((func_args*)args)->return_code = TEST_FAIL; - method = wolfSSLv23_client_method(); + if (((func_args*)args)->callbacks != NULL && + ((func_args*)args)->callbacks->method != NULL) { + method = ((func_args*)args)->callbacks->method(); + } + else { + method = wolfSSLv23_client_method(); + } ctx = wolfSSL_CTX_new(method); #ifdef OPENSSL_EXTRA wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - if (wolfSSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS) + if (wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0) != SSL_SUCCESS) { /* err_sys("can't load ca file, Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load client cert file, " "Please run from wolfSSL home dir");*/ goto done2; } - if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM) + if (wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM) != SSL_SUCCESS) { /*err_sys("can't load client key file, " @@ -885,8 +938,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) ((func_args*)args)->return_code = TEST_FAIL; #if defined(USE_WINDOWS_API) - /* Generate random port for testing */ - port = GetRandomPort(); + port = ((func_args*)args)->signal->port; #elif defined(NO_MAIN_DRIVER) && !defined(WOLFSSL_SNIFFER) && \ !defined(WOLFSSL_MDK_SHELL) && !defined(WOLFSSL_TIRTOS) /* Let tcp_listen assign port */ @@ -907,13 +959,13 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0)); + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -939,7 +991,7 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args) #ifdef NO_PSK #if !defined(NO_FILESYSTEM) && !defined(NO_DH) - wolfSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM); + wolfSSL_SetTmpDH_file(ssl, dhParamFile, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* will repick suites with DHE, higher priority than PSK */ #endif @@ -1043,13 +1095,13 @@ static void run_wolfssl_client(void* args) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif - AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCert, 0)); + AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_certificate_file(ctx, cliCert, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); AssertIntEQ(SSL_SUCCESS, - wolfSSL_CTX_use_PrivateKey_file(ctx, cliKey, SSL_FILETYPE_PEM)); + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); if (callbacks->ctx_ready) callbacks->ctx_ready(ctx); @@ -1142,6 +1194,8 @@ static void test_wolfSSL_read_write(void) func_args server_args; THREAD_TYPE serverThread; + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); #ifdef WOLFSSL_TIRTOS fdOpenSession(Task_self()); #endif @@ -1149,6 +1203,11 @@ static void test_wolfSSL_read_write(void) StartTCP(); InitTcpReady(&ready); +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; client_args.signal = &ready; @@ -1186,7 +1245,14 @@ static void test_wolfSSL_dtls_export(void) InitTcpReady(&ready); +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + /* set using dtls */ + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); XMEMSET(&server_cbf, 0, sizeof(callback_functions)); XMEMSET(&client_cbf, 0, sizeof(callback_functions)); server_cbf.method = wolfDTLSv1_2_server_method; @@ -1230,6 +1296,9 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks, func_args server_args; THREAD_TYPE serverThread; + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + StartTCP(); client_args.callbacks = client_callbacks; @@ -1241,6 +1310,12 @@ static void test_wolfSSL_client_server(callback_functions* client_callbacks, /* RUN Server side */ InitTcpReady(&ready); + +#if defined(USE_WINDOWS_API) + /* use RNG to get random port if using windows */ + ready.port = GetRandomPort(); +#endif + server_args.signal = &ready; client_args.signal = &ready; start_thread(run_wolfssl_server, &server_args, &serverThread); @@ -1958,9 +2033,9 @@ static void test_wolfSSL_DisableExtendedMasterSecret(void) *----------------------------------------------------------------------------*/ static void test_wolfSSL_X509_NAME_get_entry(void) { -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_RSA) #if defined(OPENSSL_EXTRA) && (defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)) \ - && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) + && (defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE)) || defined(WOLFSSL_HAPROXY) printf(testingFmt, "wolfSSL_X509_NAME_get_entry()"); { @@ -1973,7 +2048,7 @@ static void test_wolfSSL_X509_NAME_get_entry(void) int idx; #ifndef NO_FILESYSTEM - x509 = wolfSSL_X509_load_certificate_file(cliCert, SSL_FILETYPE_PEM); + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM); AssertNotNull(x509); name = X509_get_subject_name(x509); @@ -2006,7 +2081,7 @@ static void test_wolfSSL_PKCS12(void) { /* .p12 file is encrypted with DES3 */ #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \ - !defined(NO_ASN) && !defined(NO_PWDBASED) + !defined(NO_ASN) && !defined(NO_PWDBASED) && !defined(NO_RSA) byte buffer[5300]; char file[] = "./certs/test-servercert.p12"; FILE *f; @@ -2165,7 +2240,7 @@ static int test_wolfSSL_UseOCSPStapling(void) * check. * PRE: HAVE_CERTIFICATE_STATUS_REQUEST_V2 and HAVE_OCSP defined. */ -static int test_wolfSSL_UseOCSPStaplingV2(void) +static int test_wolfSSL_UseOCSPStaplingV2 (void) { #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && defined(HAVE_OCSP) int ret; @@ -2185,7 +2260,7 @@ static int test_wolfSSL_UseOCSPStaplingV2(void) wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); - if(ret != SSL_SUCCESS){ + if (ret != SSL_SUCCESS){ wolfSSL_Cleanup(); return SSL_FAILURE; } @@ -2197,6 +2272,1461 @@ static int test_wolfSSL_UseOCSPStaplingV2(void) } /*END test_wolfSSL_UseOCSPStaplingV2*/ +/*----------------------------------------------------------------------------* + | Wolfcrypt + *----------------------------------------------------------------------------*/ + +/* + * Unit test for the wc_InitMd5() + */ +static int test_wc_InitMd5 (void) +{ +#ifndef NO_MD5 + + Md5 md5; + int ret, flag; + + printf(testingFmt, "wc_InitMd5()"); + + flag = 0; + + /* Test good arg. */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitMd5(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitMd5 */ + +/* + * Unit test for the wc_InitSha() + */ +static int test_wc_InitSha(void) +{ +#ifndef NO_SHA + Sha sha; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha()"); + + /* Test good arg. */ + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_InitSha */ + +/* + * Unit test for wc_InitSha256() + */ +static int test_wc_InitSha256 (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha256()"); + + /* Test good arg. */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha256(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitSha256 */ + + +/* + * Testing wc_InitSha512() + */ +static int test_wc_InitSha512 (void) +{ +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha512()"); + + /* Test good arg. */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha512(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_InitSha512 */ + +/* + * Testing wc_InitSha384() + */ +static int test_wc_InitSha384 (void) +{ +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha384()"); + + /* Test good arg. */ + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha384(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitSha384 */ + +/* + * Testing wc_InitSha224(); + */ +static int test_wc_InitSha224 (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitSha224()"); + + /* Test good arg. */ + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitSha224(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_InitSha224 */ + + +/* + * Testing wc_InitRipeMd() + */ +static int test_wc_InitRipeMd (void) +{ +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + int ret, flag; + + flag = 0; + + printf(testingFmt, "wc_InitRipeMd()"); + + /* Test good arg. */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + + /* Test bad arg. */ + if (!flag) { + ret = wc_InitRipeMd(NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_InitRipeMd */ + +/* + * Testing wc_UpdateMd5() + */ +static int test_wc_Md5Update (void) +{ + +#ifndef NO_MD5 + Md5 md5; + byte hash[MD5_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Md5Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag){ + ret = wc_Md5Update(&md5, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f" + "\x72"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Md5Update(&md5, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, MD5_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /*Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Md5Update(&md5, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = MD5_DIGEST_SIZE; + + ret = wc_Md5Update(&md5, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Md5Update() */ + +/* + * Tesing wc_ShaUpdate() + */ +static int test_wc_ShaUpdate (void) +{ + +#ifndef NO_SHA + Sha sha; + byte hash[SHA_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha(&sha); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_ShaUpdate()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xA9\x99\x3E\x36\x47\x06\x81\x6A\xBA\x3E\x25\x71\x78\x50\xC2" + "\x6C\x9C\xD0\xD8\x9D"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_ShaUpdate(&sha, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, hash); + if (ret !=0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_ShaUpdate(&sha, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA_DIGEST_SIZE; + + ret = wc_ShaUpdate(&sha, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_ShaUpdate() */ + + +/* + * Unit test for wc_Sha256Update() + */ +static int test_wc_Sha256Update (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + byte hash[SHA256_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha256Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xBA\x78\x16\xBF\x8F\x01\xCF\xEA\x41\x41\x40\xDE\x5D\xAE\x22" + "\x23\xB0\x03\x61\xA3\x96\x17\x7A\x9C\xB4\x10\xFF\x61\xF2\x00" + "\x15\xAD"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha256Update(&sha256, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA256_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha256Update(&sha256, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA256_DIGEST_SIZE; + + ret = wc_Sha256Update(&sha256, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha256Update */ + +/* + * test wc_Sha384Update() + */ +static int test_wc_Sha384Update (void) +{ + +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + byte hash[SHA384_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha384(&sha384); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha384Update()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50" + "\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff" + "\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34" + "\xc8\x25\xa7"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha384Update(&sha384, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA384_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha384Update(&sha384, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA384_DIGEST_SIZE; + + ret = wc_Sha384Update(&sha384, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha384Update */ + +/* + * Testing wc_RipeMdUpdate() + */ +static int test_wc_RipeMdUpdate (void) +{ + +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte hash[RIPEMD_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_RipeMdUpdate()"); + + /* Input */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x8e\xb2\x08\xf7\xe0\x5d\x98\x7a\x9b\x04\x4a\x8e\x98\xc6" + "\xb0\x87\xf1\x5a\x0b\xfc"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_RipeMdUpdate(&ripemd, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, RIPEMD_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = RIPEMD_DIGEST_SIZE; + + ret = wc_RipeMdUpdate(&ripemd, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdUpdate(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_RipeMdUdpate */ + +/* + * wc_Sha512Update() test. + */ +static int test_wc_Sha512Update (void) +{ + +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + byte hash[SHA512_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha512Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha512Update(&sha512, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41" + "\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b" + "\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c" + "\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a" + "\x9a\xc9\x4f\xa5\x4c\xa4\x9f"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha512Update(&sha512, (byte*) a.input, (word32) a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA512_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Try passing in bad values */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha512Update(&sha512, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA512_DIGEST_SIZE; + + ret = wc_Sha512Update(&sha512, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha512Update */ + +/* + * Unit test on wc_Sha224Update + */ +static int test_wc_Sha224Update (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + byte hash[SHA224_DIGEST_SIZE]; + testVector a, b, c; + int ret, flag; + + flag = 0; + + ret = wc_InitSha224(&sha224); + if (ret != 0) { + flag = ret; + } + + printf(testingFmt, "wc_Sha224Update()"); + + /* Input. */ + if (!flag) { + a.input = "a"; + a.inLen = XSTRLEN(a.input); + } + + if (!flag) { + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + /* Update input. */ + if (!flag) { + a.input = "abc"; + a.output = "\x23\x09\x7d\x22\x34\x05\xd8\x22\x86\x42\xa4\x77\xbd\xa2" + "\x55\xb3\x2a\xad\xbc\xe4\xbd\xa0\xb3\xf7\xe3\x6c\x9d\xa7"; + a.inLen = XSTRLEN(a.input); + a.outLen = XSTRLEN(a.output); + + ret = wc_Sha224Update(&sha224, (byte*)a.input, (word32)a.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, hash); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + if (XMEMCMP(hash, a.output, SHA224_DIGEST_SIZE) != 0) { + flag = SSL_FATAL_ERROR; + } + } + + /* Pass in bad values. */ + if (!flag) { + b.input = NULL; + b.inLen = 0; + + ret = wc_Sha224Update(&sha224, (byte*)b.input, (word32)b.inLen); + if (ret != 0) { + flag = ret; + } + } + + if (!flag) { + c.input = NULL; + c.inLen = SHA224_DIGEST_SIZE; + + ret = wc_Sha224Update(&sha224, (byte*)c.input, (word32)c.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Update(NULL, (byte*)a.input, (word32)a.inLen); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + /* If not returned then the unit test passed test vectors. */ + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha224Update */ + +/* + * Unit test on wc_Md5Final() in wolfcrypt/src/md5.c + */ +static int test_wc_Md5Final (void) +{ + +#ifndef NO_MD5 + /* Instantiate */ + Md5 md5; + byte* hash_test[3]; + byte hash1[MD5_DIGEST_SIZE]; + byte hash2[2*MD5_DIGEST_SIZE]; + byte hash3[5*MD5_DIGEST_SIZE]; + int times, i, flag, ret; + + flag = 0; + + /* Initialize */ + ret = wc_InitMd5(&md5); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Test good args. */ + printf(testingFmt, "wc_Md5Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Md5Final(&md5, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Md5Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Md5Final(&md5, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} + +/* + * Unit test on wc_ShaFinal + */ +static int test_wc_ShaFinal (void) +{ +#ifndef NO_SHA + Sha sha; + byte* hash_test[3]; + byte hash1[SHA_DIGEST_SIZE]; + byte hash2[2*SHA_DIGEST_SIZE]; + byte hash3[5*SHA_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /*Initialize*/ + ret = wc_InitSha(&sha); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test)/sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_ShaFinal()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_ShaFinal(&sha, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_ShaFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_ShaFinal(&sha, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_ShaFinal */ + +/* + * Unit test function for wc_Sha256Final() + */ +static int test_wc_Sha256Final (void) +{ +#ifndef NO_SHA256 + Sha256 sha256; + byte* hash_test[3]; + byte hash1[SHA256_DIGEST_SIZE]; + byte hash2[2*SHA256_DIGEST_SIZE]; + byte hash3[5*SHA256_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha256(&sha256); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha256Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha256Final(&sha256, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag ) { + ret = wc_Sha256Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha256Final(&sha256, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha256Final */ + +/* + * Unit test function for wc_Sha512Final() + */ +static int test_wc_Sha512Final (void) +{ +#ifdef WOLFSSL_SHA512 + Sha512 sha512; + byte* hash_test[3]; + byte hash1[SHA512_DIGEST_SIZE]; + byte hash2[2*SHA512_DIGEST_SIZE]; + byte hash3[5*SHA512_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha512(&sha512); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte *); + + /* Good test args. */ + printf(testingFmt, "wc_Sha512Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha512Final(&sha512, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + /* Test bad args. */ + if (!flag) { + ret = wc_Sha512Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + + if (!flag) {} + ret = wc_Sha512Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha512Final(&sha512, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha512Final */ + +/* + * Unit test functionf or wc_Sha384Final(); + */ +static int test_wc_Sha384Final (void) +{ +#ifdef WOLFSSL_SHA384 + Sha384 sha384; + byte* hash_test[3]; + byte hash1[SHA384_DIGEST_SIZE]; + byte hash2[2*SHA384_DIGEST_SIZE]; + byte hash3[5*SHA384_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha384(&sha384); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_Sha384Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha384Final(&sha384, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha384Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha384Final(&sha384, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; + +} /* END test_wc_Sha384Final */ + +/* + * Unit test function for wc_RipeMdFinal() + */ +static int test_wc_RipeMdFinal (void) +{ +#ifdef WOLFSSL_RIPEMD + RipeMd ripemd; + byte* hash_test[3]; + byte hash1[RIPEMD_DIGEST_SIZE]; + byte hash2[2*RIPEMD_DIGEST_SIZE]; + byte hash3[5*RIPEMD_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitRipeMd(&ripemd); + if (ret != 0) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_RipeMdFinal()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_RipeMdFinal(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_RipeMdFinal(&ripemd, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_RipeMdFinal */ + +/* + * Unit test for wc_Sha224Final(); + */ +static int test_wc_Sha224Final (void) +{ +#ifdef WOLFSSL_SHA224 + Sha224 sha224; + byte* hash_test[3]; + byte hash1[SHA224_DIGEST_SIZE]; + byte hash2[2*SHA224_DIGEST_SIZE]; + byte hash3[5*SHA224_DIGEST_SIZE]; + int times, i, ret, flag; + + flag = 0; + + /* Initialize */ + ret = wc_InitSha224(&sha224); + if (ret) { + flag = ret; + } + + if (!flag) { + hash_test[0] = hash1; + hash_test[1] = hash2; + hash_test[2] = hash3; + } + + times = sizeof(hash_test) / sizeof(byte*); + + /* Good test args. */ + printf(testingFmt, "wc_sha224Final()"); + + for (i = 0; i < times; i++) { + if (!flag) { + ret = wc_Sha224Final(&sha224, hash_test[i]); + if (ret != 0) { + flag = SSL_FATAL_ERROR; + } + } + } + + /* Test bad args. */ + if (!flag) { + ret = wc_Sha224Final(NULL, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(NULL, hash1); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + if (!flag) { + ret = wc_Sha224Final(&sha224, NULL); + if (ret != BAD_FUNC_ARG) { + flag = SSL_FATAL_ERROR; + } + } + + printf(resultFmt, flag == 0 ? passed : failed); + +#endif + return 0; +} /* END test_wc_Sha224Final */ + /*----------------------------------------------------------------------------* | Compatibility Tests @@ -2218,12 +3748,12 @@ static void test_wolfSSL_DES(void) /* check, check of odd parity */ XMEMSET(key, 4, sizeof(DES_key_schedule)); key[0] = 3; /*set even parity*/ XMEMSET(myDes, 5, sizeof(const_DES_cblock)); - DES_set_key_checked(&myDes, &key); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -1); AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ /* set odd parity for success case */ key[0] = 4; - DES_set_key_checked(&myDes, &key); + AssertIntEQ(DES_set_key_checked(&myDes, &key), 0); for (i = 0; i < sizeof(DES_key_schedule); i++) { AssertIntEQ(key[i], myDes[i]); } @@ -2231,7 +3761,7 @@ static void test_wolfSSL_DES(void) /* check weak key */ XMEMSET(key, 1, sizeof(DES_key_schedule)); XMEMSET(myDes, 5, sizeof(const_DES_cblock)); - DES_set_key_checked(&myDes, &key); + AssertIntEQ(DES_set_key_checked(&myDes, &key), -2); AssertIntNE(key[0], myDes[0]); /* should not have copied over key */ /* now do unchecked copy of a weak key over */ @@ -2245,6 +3775,1118 @@ static void test_wolfSSL_DES(void) #endif /* defined(OPENSSL_EXTRA) && !defined(NO_DES3) */ } + +static void test_wolfSSL_certs(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + X509* x509; + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + STACK_OF(ASN1_OBJECT)* sk; + int crit; + + printf(testingFmt, "wolfSSL_certs()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + + #ifdef HAVE_PK_CALLBACKS + AssertIntEQ((int)SSL_set_tlsext_debug_arg(ssl, NULL), SSL_SUCCESS); + #endif /* HAVE_PK_CALLBACKS */ + + /* create and use x509 */ + x509 = wolfSSL_X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ(SSL_use_certificate(ssl, x509), SSL_SUCCESS); + + #ifndef HAVE_USER_RSA + /* with loading in a new cert the check on private key should now fail */ + AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + #endif + + + #if defined(USE_CERT_BUFFERS_2048) + AssertIntEQ(SSL_use_certificate_ASN1(ssl, + (unsigned char*)server_cert_der_2048, + sizeof_server_cert_der_2048), SSL_SUCCESS); + #endif + + #if !defined(NO_SHA) && !defined(NO_SHA256) + /************* Get Digest of Certificate ******************/ + { + byte digest[64]; /* max digest size */ + word32 digestSz; + + XMEMSET(digest, 0, sizeof(digest)); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha1(), digest, &digestSz), + SSL_SUCCESS); + AssertIntEQ(X509_digest(x509, wolfSSL_EVP_sha256(), digest, &digestSz), + SSL_SUCCESS); + + AssertIntEQ(X509_digest(NULL, wolfSSL_EVP_sha1(), digest, &digestSz), + SSL_FAILURE); + } + #endif /* !NO_SHA && !NO_SHA256*/ + + /* test and checkout X509 extensions */ + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_basic_constraints, + &crit, NULL); + AssertNotNull(sk); + AssertIntEQ(crit, 0); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_key_usage, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_ext_key_usage, + &crit, NULL); + /* AssertNotNull(sk); no extension set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_authority_key_identifier, &crit, NULL); + AssertNotNull(sk); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_private_key_usage_period, &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_subject_alt_name, + &crit, NULL); + /* AssertNotNull(sk); no alt names set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_issuer_alt_name, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_info_access, &crit, + NULL); + /* AssertNotNull(sk); no auth info set */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_sinfo_access, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_name_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, + NID_certificate_policies, &crit, NULL); + #if !defined(WOLFSSL_SEP) && !defined(WOLFSSL_CERT_EXT) + AssertNull(sk); + #else + /* AssertNotNull(sk); no cert policy set */ + #endif + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_mappings, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_policy_constraints, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_inhibit_any_policy, + &crit, NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, NID_tlsfeature, &crit, + NULL); + /* AssertNotNull(sk); NID not yet supported */ + AssertIntEQ(crit, -1); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + /* test invalid cases */ + crit = 0; + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(x509, -1, &crit, NULL); + AssertNull(sk); + AssertIntEQ(crit, -1); + sk = (STACK_OF(ASN1_OBJECT)*)X509_get_ext_d2i(NULL, NID_tlsfeature, + NULL, NULL); + AssertNull(sk); + + AssertIntEQ(SSL_get_hit(ssl), 0); + X509_free(x509); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_private_keys(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL* ssl; + WOLFSSL_CTX* ctx; + EVP_PKEY* pkey = NULL; + + printf(testingFmt, "wolfSSL_private_keys()"); + + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + +#ifdef USE_CERT_BUFFERS_2048 + { + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + + AssertIntEQ(SSL_use_RSAPrivateKey_ASN1(ssl, + (unsigned char*)client_key_der_2048, + sizeof_client_key_der_2048), SSL_SUCCESS); +#ifndef HAVE_USER_RSA + /* Should missmatch now that a different private key loaded */ + AssertIntNE(wolfSSL_check_private_key(ssl), SSL_SUCCESS); +#endif + + AssertIntEQ(SSL_use_PrivateKey_ASN1(0, ssl, + (unsigned char*)server_key, + sizeof_server_key_der_2048), SSL_SUCCESS); + /* After loading back in DER format of original key, should match */ + AssertIntEQ(wolfSSL_check_private_key(ssl), SSL_SUCCESS); + + /* pkey not set yet, expecting to fail */ + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_FAILURE); + + /* set PKEY and test again */ + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(SSL_use_PrivateKey(ssl, pkey), SSL_SUCCESS); + } +#endif + + + EVP_PKEY_free(pkey); + SSL_free(ssl); /* frees x509 also since loaded into ssl */ + SSL_CTX_free(ctx); + + /* test existence of no-op macros in wolfssl/openssl/ssl.h */ + CONF_modules_free(); + ENGINE_cleanup(); + CONF_modules_unload(); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_PEM_PrivateKey(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) && \ + (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) && \ + defined(USE_CERT_BUFFERS_2048) + const unsigned char* server_key = (const unsigned char*)server_key_der_2048; + EVP_PKEY* pkey = NULL; + BIO* bio; + + printf(testingFmt, "wolfSSL_PEM_PrivateKey()"); + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + AssertNotNull(bio); + + AssertNotNull(wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, &pkey, + &server_key, (long)sizeof_server_key_der_2048)); + AssertIntEQ(PEM_write_bio_PrivateKey(bio, pkey, NULL, NULL, 0, NULL, NULL), + SSL_SUCCESS); + + BIO_free(bio); + EVP_PKEY_free(pkey); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + + +static void test_wolfSSL_tmp_dh(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_DSA) && !defined(NO_RSA) + byte buffer[5300]; + char file[] = "./certs/dsaparams.pem"; + FILE *f; + int bytes; + DSA* dsa; + DH* dh; + BIO* bio; + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_tmp_dh()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + f = fopen(file, "rb"); + AssertNotNull(f); + bytes = (int)fread(buffer, 1, sizeof(buffer), f); + fclose(f); + + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + + dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); + AssertNotNull(dsa); + + dh = wolfSSL_DSA_dup_DH(dsa); + AssertNotNull(dh); + + AssertIntEQ((int)SSL_CTX_set_tmp_dh(ctx, dh), SSL_SUCCESS); + AssertIntEQ((int)SSL_set_tmp_dh(ssl, dh), SSL_SUCCESS); + + BIO_free(bio); + DSA_free(dsa); + DH_free(dh); + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ +} + +static void test_wolfSSL_ctrl(void) +{ + #if defined(OPENSSL_EXTRA) + byte buffer[5300]; + BIO* bio; + int bytes; + BUF_MEM* ptr = NULL; + + printf(testingFmt, "wolfSSL_crtl()"); + + bytes = sizeof(buffer); + bio = BIO_new_mem_buf((void*)buffer, bytes); + AssertNotNull(bio); + AssertNotNull(BIO_s_socket()); + + AssertIntEQ((int)wolfSSL_BIO_get_mem_ptr(bio, &ptr), SSL_SUCCESS); + + /* needs tested after stubs filled out @TODO + SSL_ctrl + SSL_CTX_ctrl + */ + + BIO_free(bio); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) */ +} + + +static void test_wolfSSL_CTX_add_extra_chain_cert(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + char caFile[] = "./certs/client-ca.pem"; + char clientFile[] = "./certs/client-cert.pem"; + SSL_CTX* ctx; + X509* x509 = NULL; + + printf(testingFmt, "wolfSSL_CTX_add_extra_chain_cert()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + + x509 = wolfSSL_X509_load_certificate_file(caFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + x509 = wolfSSL_X509_load_certificate_file(clientFile, SSL_FILETYPE_PEM); + AssertNotNull(x509); + AssertIntEQ((int)SSL_CTX_add_extra_chain_cert(ctx, x509), SSL_SUCCESS); + + AssertNull(SSL_CTX_get_default_passwd_cb(ctx)); + AssertNull(SSL_CTX_get_default_passwd_cb_userdata(ctx)); + + SSL_CTX_free(ctx); + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_ERR_peek_last_error_line(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && defined(DEBUG_WOLFSSL) && \ + !defined(NO_OLD_TLS) && defined(HAVE_IO_TESTS_DEPENDENCIES) + tcp_ready ready; + func_args client_args; + func_args server_args; +#ifndef SINGLE_THREADED + THREAD_TYPE serverThread; +#endif + callback_functions client_cb; + callback_functions server_cb; + int line = 0; + const char* file = NULL; + + printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); + + /* create a failed connection and inspect the error */ +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + + StartTCP(); + InitTcpReady(&ready); + + client_cb.method = wolfTLSv1_1_client_method; + server_cb.method = wolfTLSv1_2_server_method; + + server_args.signal = &ready; + server_args.callbacks = &server_cb; + client_args.signal = &ready; + client_args.callbacks = &client_cb; + +#ifndef SINGLE_THREADED + start_thread(test_server_nofail, &server_args, &serverThread); + wait_tcp_ready(&server_args); + test_client_nofail(&client_args); + join_thread(serverThread); +#endif + + FreeTcpReady(&ready); + + /* check that error code was stored */ + AssertIntNE((int)ERR_peek_last_error_line(NULL, NULL), 0); + ERR_peek_last_error_line(NULL, &line); + AssertIntNE(line, 0); + ERR_peek_last_error_line(&file, NULL); + AssertNotNull(file); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + printf(resultFmt, passed); + + printf("\nTesting error print out\n"); + ERR_print_errors_fp(stdout); + printf("Done testing print out\n\n"); + fflush(stdout); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(DEBUG_WOLFSSL) */ +} + + +static void test_wolfSSL_X509_STORE_set_flags(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + + X509_STORE* store; + X509* x509; + + printf(testingFmt, "wolfSSL_ERR_peek_last_error_line()"); + AssertNotNull((store = wolfSSL_X509_STORE_new())); + AssertNotNull((x509 = + wolfSSL_X509_load_certificate_file(svrCertFile, SSL_FILETYPE_PEM))); + AssertIntEQ(X509_STORE_add_cert(store, x509), SSL_SUCCESS); + +#ifdef HAVE_CRL + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), SSL_SUCCESS); +#else + AssertIntEQ(X509_STORE_set_flags(store, WOLFSSL_CRL_CHECKALL), + NOT_COMPILED_IN); +#endif + + wolfSSL_X509_free(x509); + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_X509_LOOKUP_load_file(void) +{ + #if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + WOLFSSL_X509_STORE* store; + WOLFSSL_X509_LOOKUP* lookup; + + printf(testingFmt, "wolfSSL_X509_LOOKUP_load_file()"); + + AssertNotNull(store = wolfSSL_X509_STORE_new()); + AssertNotNull(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/client-ca.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/crl/crl2.pem", + X509_FILETYPE_PEM), 1); + + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, cliCertFile, + SSL_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + SSL_FILETYPE_PEM), ASN_NO_SIGNER_E); + AssertIntEQ(wolfSSL_X509_LOOKUP_load_file(lookup, "certs/ca-cert.pem", + X509_FILETYPE_PEM), 1); + AssertIntEQ(wolfSSL_CertManagerVerify(store->cm, svrCertFile, + SSL_FILETYPE_PEM), 1); + + wolfSSL_X509_STORE_free(store); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && defined(HAVE_CRL) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_BN(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + BIGNUM* a; + BIGNUM* b; + BIGNUM* c; + BIGNUM* d; + ASN1_INTEGER ai; + unsigned char value[1]; + + printf(testingFmt, "wolfSSL_BN()"); + + AssertNotNull(b = BN_new()); + AssertNotNull(c = BN_new()); + AssertNotNull(d = BN_new()); + + value[0] = 0x03; + + /* at the moment hard setting since no set function */ + ai.data[0] = 0x02; /* tag for ASN_INTEGER */ + ai.data[1] = 0x01; /* length of integer */ + ai.data[2] = value[0]; + + AssertNotNull(a = ASN1_INTEGER_to_BN(&ai, NULL)); + + value[0] = 0x02; + AssertNotNull(BN_bin2bn(value, sizeof(value), b)); + + value[0] = 0x05; + AssertNotNull(BN_bin2bn(value, sizeof(value), c)); + + /* a^b mod c = */ + AssertIntEQ(BN_mod_exp(d, NULL, b, c, NULL), SSL_FAILURE); + AssertIntEQ(BN_mod_exp(d, a, b, c, NULL), SSL_SUCCESS); + + /* check result 3^2 mod 5 */ + value[0] = 0; + AssertIntEQ(BN_bn2bin(d, value), SSL_SUCCESS); + AssertIntEQ((int)(value[0] & 0x04), 4); + + BN_free(a); + BN_free(b); + BN_free(c); + BN_clear_free(d); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ +} + + +static void test_wolfSSL_set_options(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + SSL* ssl; + SSL_CTX* ctx; + + printf(testingFmt, "wolfSSL_set_options()"); + + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_server_method())); + AssertTrue(SSL_CTX_use_certificate_file(ctx, svrCertFile, SSL_FILETYPE_PEM)); + AssertTrue(SSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, SSL_FILETYPE_PEM)); + AssertNotNull(ssl = SSL_new(ctx)); + + AssertTrue(SSL_set_options(ssl, SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1); + AssertTrue(SSL_get_options(ssl) == SSL_OP_NO_TLSv1); + + AssertIntGT((int)SSL_set_options(ssl, (SSL_OP_COOKIE_EXCHANGE | + SSL_OP_NO_SSLv2)), 0); + AssertTrue((SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE) & + SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE); + AssertTrue((SSL_set_options(ssl, SSL_OP_NO_TLSv1_2) & + SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2); + AssertTrue((SSL_set_options(ssl, SSL_OP_NO_COMPRESSION) & + SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION); + + SSL_free(ssl); + SSL_CTX_free(ctx); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + +static void test_wolfSSL_PEM_read_bio(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) + byte buffer[5300]; + FILE *f; + int bytes; + X509* x509; + BIO* bio = NULL; + + printf(testingFmt, "wolfSSL_PEM_read_bio()"); + + AssertNotNull(f = fopen(cliCertFile, "rb")); + bytes = (int)fread(buffer, 1, sizeof(buffer), f); + fclose(f); + + AssertNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertNotNull(bio = BIO_new_mem_buf((void*)buffer, bytes)); + AssertNotNull(x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL)); + AssertIntEQ((int)BIO_set_fd(bio, 0, BIO_NOCLOSE), 1); + + BIO_free(bio); + X509_free(x509); + + printf(resultFmt, passed); + #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ + !defined(NO_FILESYSTEM) && !defined(NO_RSA) */ +} + + +static void test_wolfSSL_BIO(void) +{ + #if defined(OPENSSL_EXTRA) + byte buffer[20]; + BIO* bio1; + BIO* bio2; + BIO* bio3; + char* bufPt; + int i; + + printf(testingFmt, "wolfSSL_BIO()"); + + for (i = 0; i < 20; i++) { + buffer[i] = i; + } + + /* Creating and testing type BIO_s_bio */ + AssertNotNull(bio1 = BIO_new(BIO_s_bio())); + AssertNotNull(bio2 = BIO_new(BIO_s_bio())); + AssertNotNull(bio3 = BIO_new(BIO_s_bio())); + + /* read/write before set up */ + AssertIntEQ(BIO_read(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + AssertIntEQ(BIO_write(bio1, buffer, 2), WOLFSSL_BIO_UNSET); + + AssertIntEQ(BIO_set_write_buf_size(bio1, 20), SSL_SUCCESS); + AssertIntEQ(BIO_set_write_buf_size(bio2, 8), SSL_SUCCESS); + AssertIntEQ(BIO_make_bio_pair(bio1, bio2), SSL_SUCCESS); + + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 10), 10); + XMEMCPY(bufPt, buffer, 10); + AssertIntEQ(BIO_write(bio1, buffer + 10, 10), 10); + /* write buffer full */ + AssertIntEQ(BIO_write(bio1, buffer, 10), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_flush(bio1), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio1), 0); + + /* write the other direction with pair */ + AssertIntEQ((int)BIO_nwrite(bio2, &bufPt, 10), 8); + XMEMCPY(bufPt, buffer, 8); + AssertIntEQ(BIO_write(bio2, buffer, 10), WOLFSSL_BIO_ERROR); + + /* try read */ + AssertIntEQ((int)BIO_ctrl_pending(bio1), 8); + AssertIntEQ((int)BIO_ctrl_pending(bio2), 20); + + AssertIntEQ(BIO_nread(bio2, &bufPt, (int)BIO_ctrl_pending(bio2)), 20); + for (i = 0; i < 20; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio2, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio1, &bufPt, (int)BIO_ctrl_pending(bio1)), 8); + for (i = 0; i < 8; i++) { + AssertIntEQ((int)bufPt[i], i); + } + AssertIntEQ(BIO_nread(bio1, &bufPt, 1), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_ctrl_reset_read_request(bio1), 1); + + /* new pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_FAILURE); + BIO_free(bio2); /* free bio2 and automaticly remove from pair */ + AssertIntEQ(BIO_make_bio_pair(bio1, bio3), SSL_SUCCESS); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 10), WOLFSSL_BIO_ERROR); + + /* test wrap around... */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ(BIO_reset(bio3), 0); + + /* fill write buffer, read only small amount then write again */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 4), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* try writing over read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 5), 4); + XMEMSET(bufPt, 0, 4); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 20); + + /* read and write 0 bytes */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 0), 0); + + /* should read only to end of write buffer then need to read again */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 20), 16); + for (i = 0; i < 16; i++) { + AssertIntEQ(bufPt[i], buffer[4 + i]); + } + + AssertIntEQ(BIO_nread(bio3, NULL, 0), SSL_FAILURE); + AssertIntEQ(BIO_nread0(bio3, &bufPt), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* read index should not have advanced with nread0 */ + AssertIntEQ(BIO_nread(bio3, &bufPt, 5), 4); + for (i = 0; i < 4; i++) { + AssertIntEQ(bufPt[i], 0); + } + + /* write and fill up buffer checking reset of index state */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + + /* test reset on data in bio1 write buffer */ + AssertIntEQ(BIO_reset(bio1), 0); + AssertIntEQ((int)BIO_ctrl_pending(bio3), 0); + AssertIntEQ(BIO_nread(bio3, &bufPt, 3), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 20), 20); + XMEMCPY(bufPt, buffer, 20); + AssertIntEQ(BIO_nread(bio3, &bufPt, 6), 6); + for (i = 0; i < 6; i++) { + AssertIntEQ(bufPt[i], i); + } + + /* test case of writing twice with offset read index */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 3), 3); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 3); /* try overwriting */ + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 0), 0); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + AssertIntEQ(BIO_nread(bio3, &bufPt, 1), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), 1); + AssertIntEQ(BIO_nwrite(bio1, &bufPt, 4), WOLFSSL_BIO_ERROR); + + BIO_free(bio1); + BIO_free(bio3); + + /* BIOs with file pointers */ + #if !defined(NO_FILESYSTEM) + { + XFILE f1; + XFILE f2; + BIO* f_bio1; + BIO* f_bio2; + unsigned char cert[300]; + char testFile[] = "tests/bio_write_test.txt"; + char msg[] = "bio_write_test.txt contains the first 300 bytes of certs/server-cert.pem\ncreated by tests/unit.test\n\n"; + + AssertNotNull(f_bio1 = BIO_new(BIO_s_file())); + AssertNotNull(f_bio2 = BIO_new(BIO_s_file())); + + AssertIntEQ((int)BIO_set_mem_eof_return(f_bio1, -1), 0); + AssertIntEQ((int)BIO_set_mem_eof_return(NULL, -1), 0); + + f1 = XFOPEN(svrCertFile, "rwb"); + AssertIntEQ((int)BIO_set_fp(f_bio1, f1, BIO_CLOSE), SSL_SUCCESS); + AssertIntEQ(BIO_write_filename(f_bio2, testFile), + SSL_SUCCESS); + + AssertIntEQ(BIO_read(f_bio1, cert, sizeof(cert)), sizeof(cert)); + AssertIntEQ(BIO_write(f_bio2, msg, sizeof(msg)), sizeof(msg)); + AssertIntEQ(BIO_write(f_bio2, cert, sizeof(cert)), sizeof(cert)); + + AssertIntEQ((int)BIO_get_fp(f_bio2, &f2), SSL_SUCCESS); + AssertIntEQ(BIO_reset(f_bio2), 0); + AssertIntEQ(BIO_seek(f_bio2, 4), 0); + + BIO_free(f_bio1); + BIO_free(f_bio2); + } + #endif /* !defined(NO_FILESYSTEM) */ + + printf(resultFmt, passed); + #endif +} + +static void test_wolfSSL_DES_ecb_encrypt(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && defined(WOLFSSL_DES_ECB) + WOLFSSL_DES_cblock input1,input2,output1,output2,back1,back2; + WOLFSSL_DES_key_schedule key; + + printf(testingFmt, "wolfSSL_DES_ecb_encrypt()"); + + XMEMCPY(key,"12345678",sizeof(WOLFSSL_DES_key_schedule)); + XMEMCPY(input1, "Iamhuman",sizeof(WOLFSSL_DES_cblock)); + XMEMCPY(input2, "Whoisit?",sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(output2, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back1, 0, sizeof(WOLFSSL_DES_cblock)); + XMEMSET(back2, 0, sizeof(WOLFSSL_DES_cblock)); + + /* Encrypt messages */ + wolfSSL_DES_ecb_encrypt(&input1,&output1,&key,DES_ENCRYPT); + wolfSSL_DES_ecb_encrypt(&input2,&output2,&key,DES_ENCRYPT); + + /* Decrypt messages */ + int ret1 = 0; + int ret2 = 0; + wolfSSL_DES_ecb_encrypt(&output1,&back1,&key,DES_DECRYPT); + ret1 = memcmp((unsigned char *) back1,(unsigned char *) input1,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret1,0); + wolfSSL_DES_ecb_encrypt(&output2,&back2,&key,DES_DECRYPT); + ret2 = memcmp((unsigned char *) back2,(unsigned char *) input2,sizeof(WOLFSSL_DES_cblock)); + AssertIntEQ(ret2,0); + + printf(resultFmt, passed); + #endif +} +/*----------------------------------------------------------------------------* + | wolfCrypt ASN + *----------------------------------------------------------------------------*/ + +static void test_wc_GetPkcs8TraditionalOffset(void) +{ +#if !defined(NO_ASN) && !defined(NO_FILESYSTEM) + int length, derSz; + word32 inOutIdx; + const char* path = "./certs/server-keyPkcs8.der"; + FILE* file; + byte der[2048]; + + printf(testingFmt, "wc_GetPkcs8TraditionalOffset"); + + file = fopen(path, "rb"); + AssertNotNull(file); + derSz = (int)fread(der, 1, sizeof(der), file); + fclose(file); + + /* valid case */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntGT(length, 0); + + /* inOutIdx > sz */ + inOutIdx = 4000; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* null input */ + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(NULL, &inOutIdx, 0); + AssertIntEQ(length, BAD_FUNC_ARG); + + /* invalid input, fill buffer with 1's */ + XMEMSET(der, 1, sizeof(der)); + inOutIdx = 0; + length = wc_GetPkcs8TraditionalOffset(der, &inOutIdx, derSz); + AssertIntEQ(length, ASN_PARSE_E); + + printf(resultFmt, passed); +#endif /* NO_ASN */ +} + + +/*----------------------------------------------------------------------------* + | wolfCrypt ECC + *----------------------------------------------------------------------------*/ + +static void test_wc_ecc_get_curve_size_from_name(void) +{ +#ifdef HAVE_ECC + int ret; + + printf(testingFmt, "wc_ecc_get_curve_size_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + ret = wc_ecc_get_curve_size_from_name("SECP256R1"); + AssertIntEQ(ret, 32); + #endif + + /* invalid case */ + ret = wc_ecc_get_curve_size_from_name("BADCURVE"); + AssertIntEQ(ret, -1); + + /* NULL input */ + ret = wc_ecc_get_curve_size_from_name(NULL); + AssertIntEQ(ret, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_name(void) +{ +#ifdef HAVE_ECC + int id; + + printf(testingFmt, "wc_ecc_get_curve_id_from_name"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case */ + id = wc_ecc_get_curve_id_from_name("BADCURVE"); + AssertIntEQ(id, -1); + + /* NULL input */ + id = wc_ecc_get_curve_id_from_name(NULL); + AssertIntEQ(id, BAD_FUNC_ARG); + + printf(resultFmt, passed); +#endif /* HAVE_ECC */ +} + +static void test_wc_ecc_get_curve_id_from_params(void) +{ +#ifdef HAVE_ECC + int id; + + const byte prime[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF + }; + + const byte primeInvalid[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x01 + }; + + const byte Af[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC + }; + + const byte Bf[] = + { + 0x5A,0xC6,0x35,0xD8,0xAA,0x3A,0x93,0xE7, + 0xB3,0xEB,0xBD,0x55,0x76,0x98,0x86,0xBC, + 0x65,0x1D,0x06,0xB0,0xCC,0x53,0xB0,0xF6, + 0x3B,0xCE,0x3C,0x3E,0x27,0xD2,0x60,0x4B + }; + + const byte order[] = + { + 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xBC,0xE6,0xFA,0xAD,0xA7,0x17,0x9E,0x84, + 0xF3,0xB9,0xCA,0xC2,0xFC,0x63,0x25,0x51 + }; + + const byte Gx[] = + { + 0x6B,0x17,0xD1,0xF2,0xE1,0x2C,0x42,0x47, + 0xF8,0xBC,0xE6,0xE5,0x63,0xA4,0x40,0xF2, + 0x77,0x03,0x7D,0x81,0x2D,0xEB,0x33,0xA0, + 0xF4,0xA1,0x39,0x45,0xD8,0x98,0xC2,0x96 + }; + + const byte Gy[] = + { + 0x4F,0xE3,0x42,0xE2,0xFE,0x1A,0x7F,0x9B, + 0x8E,0xE7,0xEB,0x4A,0x7C,0x0F,0x9E,0x16, + 0x2B,0xCE,0x33,0x57,0x6B,0x31,0x5E,0xCE, + 0xCB,0xB6,0x40,0x68,0x37,0xBF,0x51,0xF5 + }; + + int cofactor = 1; + int fieldSize = 256; + + printf(testingFmt, "wc_ecc_get_curve_id_from_params"); + + #if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_params(fieldSize, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_SECP256R1); + #endif + + /* invalid case, fieldSize = 0 */ + id = wc_ecc_get_curve_id_from_params(0, prime, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + /* invalid case, NULL prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, NULL, sizeof(prime), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, BAD_FUNC_ARG); + + /* invalid case, invalid prime */ + id = wc_ecc_get_curve_id_from_params(fieldSize, + primeInvalid, sizeof(primeInvalid), + Af, sizeof(Af), Bf, sizeof(Bf), order, sizeof(order), + Gx, sizeof(Gx), Gy, sizeof(Gy), cofactor); + AssertIntEQ(id, ECC_CURVE_INVALID); + + printf(resultFmt, passed); +#endif +} + + +/*----------------------------------------------------------------------------* + | Certficate Failure Checks + *----------------------------------------------------------------------------*/ +#ifndef NO_CERTS + /* Use the Cert Manager(CM) API to generate the error ASN_SIG_CONFIRM_E */ + static int verify_sig_cm(const char* ca, byte* cert_buf, size_t cert_sz, + int type) + { + int ret; + WOLFSSL_CERT_MANAGER* cm = NULL; + + switch (type) { + case TESTING_RSA: + #ifdef NO_RSA + printf("RSA disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + case TESTING_ECC: + #ifndef HAVE_ECC + printf("ECC disabled, skipping test\n"); + return ASN_SIG_CONFIRM_E; + #else + break; + #endif + default: + printf("Bad function argument\n"); + return BAD_FUNC_ARG; + } + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) { + printf("wolfSSL_CertManagerNew failed\n"); + return -1; + } + + ret = wolfSSL_CertManagerLoadCA(cm, ca, 0); + if (ret != SSL_SUCCESS) { + printf("wolfSSL_CertManagerLoadCA failed\n"); + wolfSSL_CertManagerFree(cm); + return ret; + } + + ret = wolfSSL_CertManagerVerifyBuffer(cm, cert_buf, cert_sz, SSL_FILETYPE_ASN1); + /* Let AssertIntEQ handle return code */ + + wolfSSL_CertManagerFree(cm); + + return ret; + } + + static int test_RsaSigFailure_cm(void) + { + int ret = 0; + const char* ca_cert = "./certs/ca-cert.pem"; + const char* server_cert = "./certs/server-cert.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_RSA); + } + + printf("Signature failure test: RSA: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + + static int test_EccSigFailure_cm(void) + { + int ret = 0; + /* self-signed ECC cert, so use server cert as CA */ + const char* ca_cert = "./certs/server-ecc.pem"; + const char* server_cert = "./certs/server-ecc.der"; + byte* cert_buf = NULL; + size_t cert_sz = 0; + + ret = load_file(server_cert, &cert_buf, &cert_sz); + if (ret == 0) { + /* corrupt DER - invert last byte, which is signature */ + cert_buf[cert_sz-1] = ~cert_buf[cert_sz-1]; + + /* test bad cert */ + ret = verify_sig_cm(ca_cert, cert_buf, cert_sz, TESTING_ECC); + } + + printf("Signature failure test: ECC: Ret %d\n", ret); + + if (cert_buf) + free(cert_buf); + + return ret; + } + +#endif /* NO_CERTS */ + + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -2254,7 +4896,6 @@ void ApiTest(void) printf(" Begin API Tests\n"); AssertIntEQ(test_wolfSSL_Init(), SSL_SUCCESS); /* wolfcrypt initialization tests */ - AssertFalse(test_wolfCrypt_Init()); test_wolfSSL_Method_Allocators(); test_wolfSSL_CTX_new(wolfSSLv23_server_method()); test_wolfSSL_CTX_use_certificate_file(); @@ -2291,8 +4932,60 @@ void ApiTest(void) /* compatibility tests */ test_wolfSSL_DES(); - + test_wolfSSL_certs(); + test_wolfSSL_private_keys(); + test_wolfSSL_PEM_PrivateKey(); + test_wolfSSL_tmp_dh(); + test_wolfSSL_ctrl(); + test_wolfSSL_CTX_add_extra_chain_cert(); + test_wolfSSL_ERR_peek_last_error_line(); + test_wolfSSL_X509_STORE_set_flags(); + test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_BN(); + test_wolfSSL_set_options(); + test_wolfSSL_PEM_read_bio(); + test_wolfSSL_BIO(); + test_wolfSSL_DES_ecb_encrypt(); AssertIntEQ(test_wolfSSL_Cleanup(), SSL_SUCCESS); + + /* wolfCrypt ASN tests */ + test_wc_GetPkcs8TraditionalOffset(); + + /* wolfCrypt ECC tests */ + test_wc_ecc_get_curve_size_from_name(); + test_wc_ecc_get_curve_id_from_name(); + test_wc_ecc_get_curve_id_from_params(); + +#ifndef NO_CERTS + /* Bad certificate signature tests */ + AssertIntEQ(test_EccSigFailure_cm(), ASN_SIG_CONFIRM_E); + AssertIntEQ(test_RsaSigFailure_cm(), ASN_SIG_CONFIRM_E); +#endif /* NO_CERTS */ + + /*wolfcrypt */ + printf("\n-----------------wolfcrypt unit tests------------------\n"); + AssertFalse(test_wolfCrypt_Init()); + AssertFalse(test_wc_InitMd5()); + AssertFalse(test_wc_Md5Update()); + AssertFalse(test_wc_Md5Final()); + AssertFalse(test_wc_InitSha()); + AssertFalse(test_wc_ShaUpdate()); + AssertFalse(test_wc_ShaFinal()); + AssertFalse(test_wc_InitSha256()); + AssertFalse(test_wc_Sha256Update()); + AssertFalse(test_wc_Sha256Final()); + AssertFalse(test_wc_InitSha512()); + AssertFalse(test_wc_Sha512Update()); + AssertFalse(test_wc_Sha512Final()); + AssertFalse(test_wc_InitSha384()); + AssertFalse(test_wc_Sha384Update()); + AssertFalse(test_wc_Sha384Final()); + AssertFalse(test_wc_InitSha224()); + AssertFalse(test_wc_Sha224Update()); + AssertFalse(test_wc_Sha224Final()); + AssertFalse(test_wc_InitRipeMd()); + AssertFalse(test_wc_RipeMdUpdate()); + AssertFalse(test_wc_RipeMdFinal()); printf(" End API Tests\n"); } diff --git a/tests/hash.c b/tests/hash.c index 9167cda16..5dd0017be 100644 --- a/tests/hash.c +++ b/tests/hash.c @@ -255,6 +255,7 @@ int md4_test(void) int md5_test(void) { Md5 md5; + int ret; byte hash[MD5_DIGEST_SIZE]; testVector a, b, c, d, e; @@ -299,11 +300,22 @@ int md5_test(void) test_md5[3] = d; test_md5[4] = e; - wc_InitMd5(&md5); + ret = wc_InitMd5(&md5); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_Md5Update(&md5, (byte*)test_md5[i].input, (word32)test_md5[i].inLen); - wc_Md5Final(&md5, hash); + ret = wc_Md5Update(&md5, (byte*)test_md5[i].input, + (word32)test_md5[i].inLen); + if (ret) { + return ret; + } + + ret = wc_Md5Final(&md5, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_md5[i].output, MD5_DIGEST_SIZE) != 0) return -5 - i; @@ -578,6 +590,7 @@ int sha384_test() int ripemd_test(void) { RipeMd ripemd; + int ret; byte hash[RIPEMD_DIGEST_SIZE]; testVector a, b, c, d; @@ -614,12 +627,22 @@ int ripemd_test(void) test_ripemd[2] = c; test_ripemd[3] = d; - wc_InitRipeMd(&ripemd); + ret = wc_InitRipeMd(&ripemd); + if (ret) { + return ret; + } for (i = 0; i < times; ++i) { - wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, - (word32)test_ripemd[i].inLen); - wc_RipeMdFinal(&ripemd, hash); + ret = wc_RipeMdUpdate(&ripemd, (byte*)test_ripemd[i].input, + (word32)test_ripemd[i].inLen); + if (ret) { + return ret; + } + + ret = wc_RipeMdFinal(&ripemd, hash); + if (ret) { + return ret; + } if (XMEMCMP(hash, test_ripemd[i].output, RIPEMD_DIGEST_SIZE) != 0) return -10 - i; @@ -673,6 +696,10 @@ int hmac_md5_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -693,6 +720,8 @@ int hmac_md5_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -743,6 +772,10 @@ int hmac_sha_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -763,6 +796,8 @@ int hmac_sha_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -813,6 +848,10 @@ int hmac_sha224_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) || defined(HAVE_CAVIUM) if (i == 1) @@ -831,11 +870,10 @@ int hmac_sha224_test(void) if (XMEMCMP(hash, test_hmac[i].output, SHA224_DIGEST_SIZE) != 0) return -20 - i; -#ifdef WOLFSSL_ASYNC_CRYPT - wc_HmacAsyncFree(&hmac); -#endif } + wc_HmacFree(&hmac); + return 0; } #endif @@ -890,6 +928,10 @@ int hmac_sha256_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -910,6 +952,8 @@ int hmac_sha256_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif @@ -967,6 +1011,10 @@ int hmac_sha384_test(void) test_hmac[1] = b; test_hmac[2] = c; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret != 0) + return -20009; + for (i = 0; i < times; ++i) { #if defined(HAVE_FIPS) if (i == 1) @@ -987,6 +1035,8 @@ int hmac_sha384_test(void) return -20 - i; } + wc_HmacFree(&hmac); + return 0; } #endif diff --git a/tests/include.am b/tests/include.am index 8368b49ce..934454417 100644 --- a/tests/include.am +++ b/tests/include.am @@ -20,6 +20,7 @@ tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h EXTRA_DIST += tests/test.conf \ + tests/test-tls13.conf \ tests/test-qsh.conf \ tests/test-psk-no-id.conf \ tests/test-dtls.conf \ diff --git a/tests/srp.c b/tests/srp.c index 3314a69b6..0ca2a2b70 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -117,8 +117,8 @@ static void test_SrpInit(void) /* invalid params */ AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, 255 )); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, (SrpType)255, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, (SrpSide)255)); /* success */ AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); @@ -240,8 +240,8 @@ static void test_SrpSetPassword(void) static void test_SrpGetPublic(void) { Srp srp; - byte public[64]; - word32 publicSz = 0; + byte pub[64]; + word32 pubSz = 0; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); @@ -250,23 +250,23 @@ static void test_SrpGetPublic(void) salt, sizeof(salt))); /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* fix call order */ AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, public, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, public, NULL)); - AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, pub, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &pubSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, pub, NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* success */ - publicSz = sizeof(public); + pubSz = sizeof(pub); AssertIntEQ(0, wc_SrpSetPrivate(&srp, a, sizeof(a))); - AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); - AssertIntEQ(publicSz, sizeof(A)); - AssertIntEQ(0, XMEMCMP(public, A, publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(A)); + AssertIntEQ(0, XMEMCMP(pub, A, pubSz)); wc_SrpTerm(&srp); @@ -277,16 +277,16 @@ static void test_SrpGetPublic(void) salt, sizeof(salt))); /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, pub, &pubSz)); /* fix call order */ AssertIntEQ(0, wc_SrpSetVerifier(&srp, verifier, sizeof(verifier))); /* success */ AssertIntEQ(0, wc_SrpSetPrivate(&srp, b, sizeof(b))); - AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); - AssertIntEQ(publicSz, sizeof(B)); - AssertIntEQ(0, XMEMCMP(public, B, publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, pub, &pubSz)); + AssertIntEQ(pubSz, sizeof(B)); + AssertIntEQ(0, XMEMCMP(pub, B, pubSz)); wc_SrpTerm(&srp); } diff --git a/tests/suites.c b/tests/suites.c index f23c116cc..289c5ef46 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -35,7 +35,7 @@ #define MAX_ARGS 40 #define MAX_COMMAND_SZ 240 -#define MAX_SUITE_SZ 80 +#define MAX_SUITE_SZ 80 #define NOT_BUILT_IN -123 #if defined(NO_OLD_TLS) || !defined(WOLFSSL_ALLOW_SSLV3) #define VERSION_TOO_OLD -124 @@ -54,6 +54,11 @@ static char flagSep[] = " "; static char portFlag[] = "-p"; static char svrPort[] = "0"; #endif +static char forceDefCipherListFlag[] = "-H"; + +#ifdef WOLFSSL_ASYNC_CRYPT + static int devId = INVALID_DEVID; +#endif #ifndef WOLFSSL_ALLOW_SSLV3 @@ -155,7 +160,8 @@ static int IsValidCipherSuite(const char* line, char* suite) static int execute_test_case(int svr_argc, char** svr_argv, int cli_argc, char** cli_argv, int addNoVerify, int addNonBlocking, - int addDisableEMS) + int addDisableEMS, int forceSrvDefCipherList, + int forceCliDefCipherList) { #ifdef WOLFSSL_TIRTOS func_args cliArgs = {0}; @@ -174,20 +180,22 @@ static int execute_test_case(int svr_argc, char** svr_argv, char commandLine[MAX_COMMAND_SZ]; char cipherSuite[MAX_SUITE_SZ+1]; int i; - size_t added = 0; + size_t added; static int tests = 1; + /* Is Valid Cipher and Version Checks */ + /* build command list for the Is checks below */ commandLine[0] = '\0'; - for (i = 0; i < svr_argc; i++) { + added = 0; + for (i = 0; i < svrArgs.argc; i++) { added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("server command line too long\n"); + printf("server command line too long\n"); break; } strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (IsValidCipherSuite(commandLine, cipherSuite) == 0) { #ifdef DEBUG_SUITE_TESTS printf("cipher suite %s not supported in build\n", cipherSuite); @@ -203,7 +211,6 @@ static int execute_test_case(int svr_argc, char** svr_argv, return VERSION_TOO_OLD; } #endif - #ifdef NO_OLD_TLS if (IsOldTlsVersion(commandLine) == 1) { #ifdef DEBUG_SUITE_TESTS @@ -213,78 +220,52 @@ static int execute_test_case(int svr_argc, char** svr_argv, } #endif + /* Build Client Command */ if (addNoVerify) { - printf("repeating test with client cert request off\n"); - added += 4; /* -d plus space plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with client cert request off\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = noVerifyFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, noVerifyFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = noVerifyFlag; } if (addNonBlocking) { - printf("repeating test with non blocking on\n"); - added += 4; /* -N plus terminator */ - if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS) + printf("repeating test with non blocking on\n"); + if (svrArgs.argc >= MAX_ARGS) printf("server command line too long\n"); - else { - svr_argv[svr_argc++] = nonblockFlag; - svrArgs.argc = svr_argc; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - } + else + svr_argv[svrArgs.argc++] = nonblockFlag; } #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - /* add port 0 */ - if (svr_argc + 2 > MAX_ARGS) + /* add port */ + if (svrArgs.argc + 2 > MAX_ARGS) printf("cannot add the magic port number flag to server\n"); - else - { - svr_argv[svr_argc++] = portFlag; - svr_argv[svr_argc++] = svrPort; - svrArgs.argc = svr_argc; + else { + svr_argv[svrArgs.argc++] = portFlag; + svr_argv[svrArgs.argc++] = svrPort; } #endif - printf("trying server command line[%d]: %s\n", tests, commandLine); + if (forceSrvDefCipherList) { + if (svrArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to server\n"); + else + svr_argv[svrArgs.argc++] = forceDefCipherListFlag; + } + /* update server flags list */ commandLine[0] = '\0'; added = 0; - for (i = 0; i < cli_argc; i++) { - added += XSTRLEN(cli_argv[i]) + 2; + for (i = 0; i < svrArgs.argc; i++) { + added += XSTRLEN(svr_argv[i]) + 2; if (added >= MAX_COMMAND_SZ) { - printf("client command line too long\n"); + printf("server command line too long\n"); break; } - strcat(commandLine, cli_argv[i]); + strcat(commandLine, svr_argv[i]); strcat(commandLine, flagSep); } - if (addNonBlocking) { - added += 4; /* -N plus space plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = nonblockFlag; - strcat(commandLine, nonblockFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - if (addDisableEMS) { - printf("repeating test without extended master secret\n"); - added += 4; /* -n plus terminator */ - if (added >= MAX_COMMAND_SZ) - printf("client command line too long\n"); - else { - cli_argv[cli_argc++] = disableEMSFlag; - strcat(commandLine, disableEMSFlag); - strcat(commandLine, flagSep); - cliArgs.argc = cli_argc; - } - } - printf("trying client command line[%d]: %s\n", tests++, commandLine); + printf("trying server command line[%d]: %s\n", tests, commandLine); + + tests++; /* test count */ InitTcpReady(&ready); @@ -296,31 +277,65 @@ static int execute_test_case(int svr_argc, char** svr_argv, svrArgs.signal = &ready; start_thread(server_test, &svrArgs, &serverThread); wait_tcp_ready(&svrArgs); - #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) - if (ready.port != 0) - { - if (cli_argc + 2 > MAX_ARGS) - printf("cannot add the magic port number flag to client\n"); - else { - char portNumber[8]; - snprintf(portNumber, sizeof(portNumber), "%d", ready.port); - cli_argv[cli_argc++] = portFlag; - cli_argv[cli_argc++] = portNumber; - cliArgs.argc = cli_argc; - } + + + /* Build Client Command */ + if (addNonBlocking) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the non block flag to client\n"); + else + cli_argv[cliArgs.argc++] = nonblockFlag; + } + if (addDisableEMS) { + printf("repeating test without extended master secret\n"); + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the disable EMS flag to client\n"); + else + cli_argv[cliArgs.argc++] = disableEMSFlag; + } +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + if (ready.port != 0) { + if (cliArgs.argc + 2 > MAX_ARGS) + printf("cannot add the magic port number flag to client\n"); + else { + char portNumber[8]; + snprintf(portNumber, sizeof(portNumber), "%d", ready.port); + cli_argv[cliArgs.argc++] = portFlag; + cli_argv[cliArgs.argc++] = portNumber; } - #endif + } +#endif + if (forceCliDefCipherList) { + if (cliArgs.argc >= MAX_ARGS) + printf("cannot add the force def cipher list flag to client\n"); + else + cli_argv[cliArgs.argc++] = forceDefCipherListFlag; + } + + commandLine[0] = '\0'; + added = 0; + for (i = 0; i < cliArgs.argc; i++) { + added += XSTRLEN(cli_argv[i]) + 2; + if (added >= MAX_COMMAND_SZ) { + printf("client command line too long\n"); + break; + } + strcat(commandLine, cli_argv[i]); + strcat(commandLine, flagSep); + } + printf("trying client command line[%d]: %s\n", tests, commandLine); + /* start client */ client_test(&cliArgs); - /* verify results */ + /* verify results */ if (cliArgs.return_code != 0) { printf("client_test failed\n"); exit(EXIT_FAILURE); } join_thread(serverThread); - if (svrArgs.return_code != 0) { + if (svrArgs.return_code != 0) { printf("server_test failed\n"); exit(EXIT_FAILURE); } @@ -329,7 +344,7 @@ static int execute_test_case(int svr_argc, char** svr_argv, fdCloseSession(Task_self()); #endif FreeTcpReady(&ready); - + return 0; } @@ -361,7 +376,7 @@ static void test_harness(void* vargs) fname = args->argv[1]; } - file = fopen(fname, "r"); + file = fopen(fname, "rb"); if (file == NULL) { fprintf(stderr, "unable to open %s\n", fname); args->return_code = 1; @@ -393,7 +408,7 @@ static void test_harness(void* vargs) args->return_code = 1; return; } - + fclose(file); script[sz] = 0; @@ -442,7 +457,7 @@ static void test_harness(void* vargs) else svrArgs[svrArgsSz++] = strsep(&cursor, "\n"); if (*cursor == 0) /* eof */ - do_it = 1; + do_it = 1; } if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) { @@ -452,24 +467,31 @@ static void test_harness(void* vargs) if (do_it) { ret = execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 0); + cliArgsSz, cliArgs, 0, 0, 0, 0, 0); /* don't repeat if not supported in build */ if (ret == 0) { + /* test with default cipher list on server side */ execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 0); + cliArgsSz, cliArgs, 0, 0, 0, 1, 0); + /* test with default cipher list on client side */ execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 0); + cliArgsSz, cliArgs, 0, 0, 0, 0, 1); + execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 0); + cliArgsSz, cliArgs, 0, 1, 0, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 0, 0, 0, 0); + execute_test_case(svrArgsSz, svrArgs, + cliArgsSz, cliArgs, 1, 1, 0, 0, 0); #ifdef HAVE_EXTENDED_MASTER execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 0, 1); + cliArgsSz, cliArgs, 0, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 0, 1, 1); + cliArgsSz, cliArgs, 0, 1, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 0, 1); + cliArgsSz, cliArgs, 1, 0, 1, 0, 0); execute_test_case(svrArgsSz, svrArgs, - cliArgsSz, cliArgs, 1, 1, 1); + cliArgsSz, cliArgs, 1, 1, 1, 0, 0); #endif } svrArgsSz = 1; @@ -515,22 +537,43 @@ int SuiteTest(void) memory, sizeof(memory), 0, 1) != SSL_SUCCESS) { printf("unable to load static memory and create ctx"); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +#ifdef WOLFSSL_ASYNC_CRYPT + if (wolfAsync_DevOpen(&devId) < 0) { + printf("Async device open failed"); + args.return_code = EXIT_FAILURE; + goto exit; + } + wolfSSL_CTX_UseAsync(cipherSuiteCtx, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + /* default case */ args.argc = 1; printf("starting default cipher suite tests\n"); test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } /* any extra cases will need another argument */ args.argc = 2; +#ifdef WOLFSSL_TLS13 + /* add TLSv13 extra suites */ + strcpy(argv0[1], "tests/test-tls13.conf"); + printf("starting TLSv13 extra cipher suite tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + exit(EXIT_FAILURE); + } +#endif #ifdef WOLFSSL_DTLS /* add dtls extra suites */ strcpy(argv0[1], "tests/test-dtls.conf"); @@ -538,7 +581,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifdef WOLFSSL_SCTP @@ -548,7 +592,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif #ifndef WC_STRICT_SIG @@ -559,7 +604,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif /* HAVE_RSA and HAVE_ECC */ #endif /* !WC_STRICT_SIG */ @@ -570,7 +616,8 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif @@ -581,15 +628,21 @@ int SuiteTest(void) test_harness(&args); if (args.return_code != 0) { printf("error from script %d\n", args.return_code); - exit(EXIT_FAILURE); + args.return_code = EXIT_FAILURE; + goto exit; } #endif +exit: printf(" End Cipher Suite Tests\n"); wolfSSL_CTX_free(cipherSuiteCtx); wolfSSL_Cleanup(); +#ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_DevClose(&devId); +#endif + return args.return_code; } diff --git a/tests/test-dtls.conf b/tests/test-dtls.conf index fb4260e62..5bd76c694 100644 --- a/tests/test-dtls.conf +++ b/tests/test-dtls.conf @@ -1,36 +1,3 @@ -# server DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 DHE-RSA-CHACHA20-POLY1305 --u --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client DTLSv1 ECDHE-RSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server DTLSv1 ECDHE-EDCSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1 ECDHE-ECDSA-CHACHA20-POLY1305 --u --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server DTLSv1.2 DHE-RSA-CHACHA20-POLY1305 -u -v 3 @@ -133,26 +100,6 @@ -l ECDHE-ECDSA-CHACHA20-POLY1305-OLD -A ./certs/server-ecc.pem -# server DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# client DTLSv1 RC4-SHA --u --v 2 --l RC4-SHA - -# server DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA - -# client DTLSv1.2 RC4-SHA --u --v 3 --l RC4-SHA - # server DTLSv1 IDEA-CBC-SHA -u -v 2 @@ -263,16 +210,6 @@ -v 3 -l AES256-SHA256 -# server DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1 ECDHE-RSA-RC4 --u --v 2 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.1 ECDHE-RSA-DES3 -u -v 2 @@ -283,12 +220,12 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDHE-RSA-AES128 +# server DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.1 ECDHE-RSA-AES128 +# client DTLSv1.1 ECDHE-RSA-AES128 -u -v 2 -l ECDHE-RSA-AES128-SHA @@ -303,16 +240,6 @@ -v 2 -l ECDHE-RSA-AES256-SHA -# server DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - -# client DTLSv1.2 ECDHE-RSA-RC4 --u --v 3 --l ECDHE-RSA-RC4-SHA - # server DTLSv1.2 ECDHE-RSA-DES3 -u -v 3 @@ -323,12 +250,12 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDHE-RSA-AES128 +# server DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA -# client DTLSv1.2 ECDHE-RSA-AES128 +# client DTLSv1.2 ECDHE-RSA-AES128 -u -v 3 -l ECDHE-RSA-AES128-SHA @@ -338,7 +265,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-SHA256 -u -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -392,19 +319,6 @@ -l ECDHE-ECDSA-NULL-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDHE-EDCSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDHE-ECDSA-RC4 --u --v 2 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.1 ECDHE-ECDSA-DES3 -u -v 2 @@ -418,14 +332,14 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDHE-ECDSA-AES128 +# server DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDHE-ECDSA-AES128 +# client DTLSv1.1 ECDHE-ECDSA-AES128 -u -v 2 -l ECDHE-ECDSA-AES128-SHA @@ -444,19 +358,6 @@ -l ECDHE-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDHE-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.2 ECDHE-ECDSA-DES3 -u -v 3 @@ -470,14 +371,14 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-AES128 +# server DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128 +# client DTLSv1.2 ECDHE-ECDSA-AES128 -u -v 3 -l ECDHE-ECDSA-AES128-SHA @@ -509,18 +410,6 @@ -l ECDHE-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-RSA-RC4 --u --v 2 --l ECDH-RSA-RC4-SHA - # server DTLSv1.1 ECDH-RSA-DES3 -u -v 2 @@ -533,14 +422,14 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.1 ECDH-RSA-AES128 +# server DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-RSA-AES128 +# client DTLSv1.1 ECDH-RSA-AES128 -u -v 2 -l ECDH-RSA-AES128-SHA @@ -557,18 +446,6 @@ -v 2 -l ECDH-RSA-AES256-SHA -# server DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA --c ./certs/server-ecc-rsa.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-RSA-RC4 --u --v 3 --l ECDH-RSA-RC4-SHA - # server DTLSv1.2 ECDH-RSA-DES3 -u -v 3 @@ -581,26 +458,26 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server DTLSv1.2 ECDH-RSA-AES128 +# server DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128 +# client DTLSv1.2 ECDH-RSA-AES128 -u -v 3 -l ECDH-RSA-AES128-SHA -# server DTLSv1.2 ECDH-RSA-AES128-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-SHA256 -u -v 3 -l ECDH-RSA-AES128-SHA256 @@ -617,19 +494,6 @@ -v 3 -l ECDH-RSA-AES256-SHA -# server DTLSv1.1 ECDH-EDCSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.1 ECDH-ECDSA-RC4 --u --v 2 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.1 ECDH-ECDSA-DES3 -u -v 2 @@ -643,14 +507,14 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.1 ECDH-ECDSA-AES128 +# server DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.1 ECDH-ECDSA-AES128 +# client DTLSv1.1 ECDH-ECDSA-AES128 -u -v 2 -l ECDH-ECDSA-AES128-SHA @@ -669,19 +533,6 @@ -l ECDH-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client DTLSv1.2 ECDH-ECDSA-RC4 --u --v 3 --l ECDH-ECDSA-RC4-SHA --A ./certs/server-ecc.pem - # server DTLSv1.2 ECDH-ECDSA-DES3 -u -v 3 @@ -695,14 +546,14 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-ECDSA-AES128 +# server DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128 +# client DTLSv1.2 ECDH-ECDSA-AES128 -u -v 3 -l ECDH-ECDSA-AES128-SHA @@ -715,7 +566,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-SHA256 @@ -734,12 +585,12 @@ -l ECDH-ECDSA-AES256-SHA -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# server DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 -# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 +# client DTLSv1.2 ECDHE-RSA-AES256-SHA384 -u -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -757,14 +608,14 @@ -l ECDHE-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-RSA-AES256-SHA384 +# server DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES256-SHA384 +# client DTLSv1.2 ECDH-RSA-AES256-SHA384 -u -v 3 -l ECDH-RSA-AES256-SHA384 @@ -776,7 +627,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client DTLSv1.2 ECDH-ECDSA-AES256-SHA384 -u -v 3 -l ECDH-ECDSA-AES256-SHA384 @@ -926,14 +777,14 @@ -v 3 -l PSK-AES256-CBC-SHA384 -# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 @@ -952,14 +803,14 @@ -l ECDHE-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 @@ -978,12 +829,12 @@ -l ECDH-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -998,14 +849,14 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client DTLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -u -v 3 -l ECDH-RSA-AES128-GCM-SHA256 diff --git a/tests/test-sig.conf b/tests/test-sig.conf index 4ce46ca83..aa7f3b295 100644 --- a/tests/test-sig.conf +++ b/tests/test-sig.conf @@ -174,6 +174,17 @@ -l ECDHE-ECDSA-AES128-GCM-SHA256 -A ./certs/ca-cert.pem +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-c ./certs/server-ecc-rsa.pem +-k ./certs/ecc-privkey.pem + +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +-v 3 +-l ECDHE-ECDSA-AES128-GCM-SHA256 +-A ./certs/ca-cert.pem + # server TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384 -v 3 -l ECDHE-ECDSA-AES256-GCM-SHA384 diff --git a/tests/test-tls13.conf b/tests/test-tls13.conf new file mode 100644 index 000000000..cf1e9f7f9 --- /dev/null +++ b/tests/test-tls13.conf @@ -0,0 +1,95 @@ +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 + +# server TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-CHACH20-POLY1305-SHA256 +-v 4 +-l TLS13-CHACH20-POLY1305-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-GCM-SHA256 +-v 4 +-l TLS13-AES128-GCM-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES256-GCM-SHA384 +-v 4 +-l TLS13-AES256-GCM-SHA384 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-SHA256 +-v 4 +-l TLS13-AES128-CCM-SHA256 +-A ./certs/server-ecc.pem + +# server TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-c ./certs/server-ecc.pem +-k ./certs/ecc-key.pem + +# client TLSv1.3 TLS13-AES128-CCM-8-SHA256 +-v 4 +-l TLS13-AES128-CCM-8-SHA256 +-A ./certs/server-ecc.pem + diff --git a/tests/test.conf b/tests/test.conf index 37f672ab0..933d001fd 100644 --- a/tests/test.conf +++ b/tests/test.conf @@ -1,30 +1,3 @@ -# server TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 DHE-RSA-CHACHA20-POLY1305 --v 2 --l DHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# client TLSv1.1 ECDHE-RSA-CHACHA20-POLY1305 --v 2 --l ECDHE-RSA-CHACHA20-POLY1305 - -# server TLSv1.1 ECDHE-EDCSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --c ./certs/server-ecc.pem --k ./certs/ecc-key.pem - -# client TLSv1.1 ECDHE-ECDSA-CHACHA20-POLY1305 --v 2 --l ECDHE-ECDSA-CHACHA20-POLY1305 --A ./certs/server-ecc.pem - # server TLSv1.2 DHE-RSA-CHACHA20-POLY1305 -v 3 -l DHE-RSA-CHACHA20-POLY1305 @@ -341,11 +314,11 @@ -v 1 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1 ECDHE-RSA-AES128 +# server TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA -# client TLSv1 ECDHE-RSA-AES128 +# client TLSv1 ECDHE-RSA-AES128 -v 1 -l ECDHE-RSA-AES128-SHA @@ -373,11 +346,11 @@ -v 2 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDHE-RSA-AES128 +# server TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA -# client TLSv1.1 ECDHE-RSA-AES128 +# client TLSv1.1 ECDHE-RSA-AES128 -v 2 -l ECDHE-RSA-AES128-SHA @@ -405,11 +378,11 @@ -v 3 -l ECDHE-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDHE-RSA-AES128 +# server TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA -# client TLSv1.2 ECDHE-RSA-AES128 +# client TLSv1.2 ECDHE-RSA-AES128 -v 3 -l ECDHE-RSA-AES128-SHA @@ -417,7 +390,7 @@ -v 3 -l ECDHE-RSA-AES128-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-SHA256 -v 3 -l ECDHE-RSA-AES128-SHA256 @@ -484,13 +457,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1 ECDHE-ECDSA-AES128 +# server TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDHE-ECDSA-AES128 +# client TLSv1 ECDHE-ECDSA-AES128 -v 1 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -528,13 +501,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.1 ECDHE-ECDSA-AES128 +# server TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDHE-ECDSA-AES128 +# client TLSv1.1 ECDHE-ECDSA-AES128 -v 2 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -572,13 +545,13 @@ -l ECDHE-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.2 ECDHE-ECDSA-AES128 +# server TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128 +# client TLSv1.2 ECDHE-ECDSA-AES128 -v 3 -l ECDHE-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -625,13 +598,13 @@ -v 1 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1 ECDH-RSA-AES128 +# server TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-RSA-AES128 +# client TLSv1 ECDH-RSA-AES128 -v 1 -l ECDH-RSA-AES128-SHA @@ -665,13 +638,13 @@ -v 2 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.1 ECDH-RSA-AES128 +# server TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-RSA-AES128 +# client TLSv1.1 ECDH-RSA-AES128 -v 2 -l ECDH-RSA-AES128-SHA @@ -705,23 +678,23 @@ -v 3 -l ECDH-RSA-DES-CBC3-SHA -# server TLSv1.2 ECDH-RSA-AES128 +# server TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128 +# client TLSv1.2 ECDH-RSA-AES128 -v 3 -l ECDH-RSA-AES128-SHA -# server TLSv1.2 ECDH-RSA-AES128-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-SHA256 -v 3 -l ECDH-RSA-AES128-SHA256 @@ -757,13 +730,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1 ECDH-ECDSA-AES128 +# server TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1 ECDH-ECDSA-AES128 +# client TLSv1 ECDH-ECDSA-AES128 -v 1 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -801,13 +774,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.1 ECDH-ECDSA-AES128 +# server TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.1 ECDH-ECDSA-AES128 +# client TLSv1.1 ECDH-ECDSA-AES128 -v 2 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -845,13 +818,13 @@ -l ECDH-ECDSA-DES-CBC3-SHA -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-ECDSA-AES128 +# server TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128 +# client TLSv1.2 ECDH-ECDSA-AES128 -v 3 -l ECDH-ECDSA-AES128-SHA -A ./certs/server-ecc.pem @@ -862,7 +835,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-SHA256 -v 3 -l ECDH-ECDSA-AES128-SHA256 -A ./certs/server-ecc.pem @@ -882,7 +855,7 @@ -v 3 -l ECDHE-RSA-AES256-SHA384 -# client TLSv1.2 ECDHE-RSA-AES256-SHA384 +# client TLSv1.2 ECDHE-RSA-AES256-SHA384 -v 3 -l ECDHE-RSA-AES256-SHA384 @@ -897,13 +870,13 @@ -l ECDHE-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-RSA-AES256-SHA384 +# server TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES256-SHA384 +# client TLSv1.2 ECDH-RSA-AES256-SHA384 -v 3 -l ECDH-RSA-AES256-SHA384 @@ -913,7 +886,7 @@ -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 +# client TLSv1.2 ECDH-ECDSA-AES256-SHA384 -v 3 -l ECDH-ECDSA-AES256-SHA384 -A ./certs/server-ecc.pem @@ -1664,11 +1637,11 @@ -v 3 -l DHE-RSA-CAMELLIA256-SHA256 -# server TLSv1.2 RSA-AES128-GCM-SHA256 +# server TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 -# client TLSv1.2 RSA-AES128-GCM-SHA256 +# client TLSv1.2 RSA-AES128-GCM-SHA256 -v 3 -l AES128-GCM-SHA256 @@ -1680,13 +1653,13 @@ -v 3 -l AES256-GCM-SHA384 -# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDHE-ECDSA-AES128-GCM-SHA256 -A ./certs/server-ecc.pem @@ -1702,13 +1675,13 @@ -l ECDHE-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-ECDSA-AES128-GCM-SHA256 -v 3 -l ECDH-ECDSA-AES128-GCM-SHA256 -A ./certs/server-ecc.pem @@ -1724,11 +1697,11 @@ -l ECDH-ECDSA-AES256-GCM-SHA384 -A ./certs/server-ecc.pem -# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 -v 3 -l ECDHE-RSA-AES128-GCM-SHA256 @@ -1740,13 +1713,13 @@ -v 3 -l ECDHE-RSA-AES256-GCM-SHA384 -# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# server TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 -c ./certs/server-ecc-rsa.pem -k ./certs/ecc-key.pem -# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 +# client TLSv1.2 ECDH-RSA-AES128-GCM-SHA256 -v 3 -l ECDH-RSA-AES128-GCM-SHA256 @@ -1760,11 +1733,11 @@ -v 3 -l ECDH-RSA-AES256-GCM-SHA384 -# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# server TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 -# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 +# client TLSv1.2 DHE-RSA-AES128-GCM-SHA256 -v 3 -l DHE-RSA-AES128-GCM-SHA256 @@ -2196,3 +2169,12 @@ -v 3 -l NTRU-AES128-SHA +# server TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 + +# client TLSv1.2 verify callback override +-v 3 +-l ECDHE-RSA-AES128-SHA256 +-j + diff --git a/tests/unit.c b/tests/unit.c index dd9846529..39a76ddf2 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -45,7 +45,7 @@ int main(int argc, char** argv) int unit_test(int argc, char** argv) { - int ret; + int ret = 0; (void)argc; (void)argv; @@ -68,24 +68,25 @@ int unit_test(int argc, char** argv) if ( (ret = HashTest()) != 0){ printf("hash test failed with %d\n", ret); - return ret; + goto exit; } #ifndef SINGLE_THREADED if ( (ret = SuiteTest()) != 0){ printf("suite test failed with %d\n", ret); - return ret; + goto exit; } #endif SrpTest(); +exit: #ifdef HAVE_WNR if (wc_FreeNetRandom() < 0) err_sys("Failed to free netRandom context"); #endif /* HAVE_WNR */ - return 0; + return ret; } diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index 3a2bc64ec..144efb140 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -210,7 +210,7 @@ int testsuite_test(int argc, char** argv) #endif /* HAVE_WNR */ printf("\nAll tests passed!\n"); - EXIT_TEST(EXIT_SUCCESS); + return EXIT_SUCCESS; } void simple_test(func_args* args) @@ -405,11 +405,13 @@ int main(int argc, char** argv) server_args.argc = argc; server_args.argv = argv; + wolfSSL_Init(); ChangeToWolfRoot(); wolfcrypt_test(&server_args); if (server_args.return_code != 0) return server_args.return_code; + wolfSSL_Cleanup(); printf("\nAll tests passed!\n"); EXIT_TEST(EXIT_SUCCESS); diff --git a/tirtos/README b/tirtos/README index 6001f5664..dc7fbb114 100644 --- a/tirtos/README +++ b/tirtos/README @@ -7,6 +7,9 @@ library and the example applications. Also read TI-RTOS Getting Started Guide and TI-RTOS User Guide to learn more about TI-RTOS (http://www.ti.com/tool/ti-rtos). +For more information see: +(https://github.com/wolfSSL/wolfssl-examples/blob/master/tirtos_ccs_examples/README.md) + ## Example Application A simple "TCP echo server with TLS" example application is provided with TI-RTOS diff --git a/tirtos/packages/ti/net/wolfssl/package.bld b/tirtos/packages/ti/net/wolfssl/package.bld index 1d506f13f..91b7d79c9 100644 --- a/tirtos/packages/ti/net/wolfssl/package.bld +++ b/tirtos/packages/ti/net/wolfssl/package.bld @@ -41,6 +41,7 @@ var wolfSSLObjList = [ "wolfcrypt/src/sha512.c", "wolfcrypt/src/tfm.c", "wolfcrypt/src/wc_port.c", + "wolfcrypt/src/wolfmath.c", "src/internal.c", "src/io.c", diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 0b5ad6ad7..80018c149 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -32,6 +32,10 @@ /* Macro to disable benchmark */ #ifndef NO_CRYPT_BENCHMARK +#ifdef XMALLOC_USER + #include /* we're using malloc / free direct here */ +#endif + #ifdef WOLFSSL_STATIC_MEMORY #include static WOLFSSL_HEAP_HINT* HEAP_HINT; @@ -48,6 +52,11 @@ #else #include #endif +#elif defined(FREESCALE_KSDK_BM) + #include "fsl_debug_console.h" + #include "fsl_os_abstraction.h" + #undef printf + #define printf PRINTF #else #include #endif @@ -93,40 +102,44 @@ #include #include +/* only for stack size check */ +#ifdef HAVE_STACK_SIZE + #include + #include +#endif + #ifdef WOLFSSL_ASYNC_CRYPT #include #endif -#if defined(WOLFSSL_ASYNC_CRYPT) || defined(HAVE_ECC) - static int devId = INVALID_DEVID; -#endif #ifdef HAVE_WNR const char* wnrConfigFile = "wnr-example.conf"; #endif #if defined(WOLFSSL_MDK_ARM) - extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; + extern FILE * wolfSSL_fopen(const char *fname, const char *mode); #define fopen wolfSSL_fopen #endif #if defined(__GNUC__) && defined(__x86_64__) && !defined(NO_ASM) #define HAVE_GET_CYCLES static INLINE word64 get_intel_cycles(void); - static word64 total_cycles; + static THREAD_LS_T word64 total_cycles; #define INIT_CYCLE_COUNTER #define BEGIN_INTEL_CYCLES total_cycles = get_intel_cycles(); #define END_INTEL_CYCLES total_cycles = get_intel_cycles() - total_cycles; #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + count == 0 ? 0 : \ + (float)total_cycles / (count*BENCH_SIZE)); #elif defined(LINUX_CYCLE_COUNT) #include #include #include - static word64 begin_cycles; - static word64 total_cycles; - static int cycles = -1; - static struct perf_event_attr atr; + static THREAD_LS_T word64 begin_cycles; + static THREAD_LS_T word64 total_cycles; + static THREAD_LS_T int cycles = -1; + static THREAD_LS_T struct perf_event_attr atr; #define INIT_CYCLE_COUNTER do { \ atr.type = PERF_TYPE_HARDWARE; \ @@ -141,7 +154,7 @@ } while (0); #define SHOW_INTEL_CYCLES printf(" Cycles per byte = %6.2f", \ - (float)total_cycles / (numBlocks*sizeof(plain))); + (float)total_cycles / (count*BENCH_SIZE)); #else #define INIT_CYCLE_COUNTER @@ -158,7 +171,7 @@ #if defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048) \ || !defined(NO_DH) /* include test cert and key buffers for use with NO_FILESYSTEM */ - #include + #include #endif @@ -174,43 +187,36 @@ #include "wolfcrypt/benchmark/benchmark.h" -#ifdef USE_WOLFSSL_MEMORY - #include "wolfssl/wolfcrypt/mem_track.h" -#endif - -void bench_des(void); +void bench_des(int); void bench_idea(void); -void bench_arc4(void); +void bench_arc4(int); void bench_hc128(void); void bench_rabbit(void); void bench_chacha(void); void bench_chacha20_poly1305_aead(void); -void bench_aes(int); -void bench_aesgcm(void); +void bench_aescbc(int); +void bench_aesgcm(int); void bench_aesccm(void); void bench_aesctr(void); void bench_poly1305(void); void bench_camellia(void); -void bench_md5(void); -void bench_sha(void); -void bench_sha224(void); -void bench_sha256(void); -void bench_sha384(void); -void bench_sha512(void); -void bench_ripemd(void); +void bench_md5(int); +void bench_sha(int); +void bench_sha224(int); +void bench_sha256(int); +void bench_sha384(int); +void bench_sha512(int); +int bench_ripemd(void); void bench_cmac(void); void bench_scrypt(void); -void bench_rsa(void); -#ifdef WOLFSSL_ASYNC_CRYPT - void bench_rsa_async(void); -#endif -void bench_rsaKeyGen(void); -void bench_dh(void); +void bench_rsaKeyGen(int); +void bench_rsa(int); +void bench_dh(int); #ifdef HAVE_ECC -void bench_eccKeyGen(void); -void bench_eccKeyAgree(void); +void bench_eccMakeKey(int); +void bench_ecc(int); #ifdef HAVE_ECC_ENCRYPT void bench_eccEncrypt(void); #endif @@ -233,37 +239,215 @@ void bench_ntruKeyGen(void); void bench_rng(void); #endif /* WC_NO_RNG */ -double current_time(int); +#ifdef WOLFSSL_CURRTIME_REMAP + #define current_time WOLFSSL_CURRTIME_REMAP +#elif !defined(HAVE_STACK_SIZE) + double current_time(int); +#endif - -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) && \ + !defined(HAVE_STACK_SIZE) WOLFSSL_API int wolfSSL_Debugging_ON(); + WOLFSSL_API void wolfSSL_Debugging_OFF(void); #endif #if !defined(NO_RSA) || !defined(NO_DH) \ || defined(WOLFSSL_KEYGEN) || defined(HAVE_ECC) \ || defined(HAVE_CURVE25519) || defined(HAVE_ED25519) #define HAVE_LOCAL_RNG - static WC_RNG rng; + static THREAD_LS_T WC_RNG rng; #endif -/* use kB instead of mB for embedded benchmarking */ -#ifdef BENCH_EMBEDDED - static byte plain [1024]; + + +/* Asynchronous helper macros */ +static THREAD_LS_T int devId = INVALID_DEVID; + +#ifdef WOLFSSL_ASYNC_CRYPT + static THREAD_LS_T WOLF_EVENT_QUEUE eventQueue; + static THREAD_LS_T int asyncPending; + + #define BENCH_ASYNC_GET_DEV(obj) (&(obj)->asyncDev) + #define BENCH_ASYNC_GET_NAME(doAsync) (doAsync) ? "HW" : "SW" + #define BENCH_ASYNC_IS_PEND() (asyncPending > 0) + #define BENCH_MAX_PENDING (WOLF_ASYNC_MAX_PENDING) + +#ifndef WC_NO_ASYNC_THREADING + typedef struct ThreadData { + pthread_t thread_id; + } ThreadData; + static ThreadData* g_threadData; + static int g_threadCount; +#endif + + static INLINE int bench_async_begin(void) { + /* init event queue */ + asyncPending = 0; + return wolfEventQueue_Init(&eventQueue); + } + + static INLINE void bench_async_end(void) { + /* free event queue */ + wolfEventQueue_Free(&eventQueue); + } + + static INLINE void bench_async_complete(int* ret, WC_ASYNC_DEV* asyncDev, + int* times) + { + *ret = asyncDev->event.ret; + if (*ret >= 0) { + (*times)++; + asyncDev->event.done = 0; /* reset done flag */ + } + } + + static INLINE int bench_async_check(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times, int limit) + { + int allowNext = 0; + + /* if algo doesn't require calling again then use this flow */ + if (!callAgain) { + if (asyncDev->event.done) { + /* operation completed */ + bench_async_complete(ret, asyncDev, times); + } + } + /* if algo does require calling again then use this flow */ + else { + if (asyncDev->event.done) { + allowNext = 1; + } + } + + if (asyncDev->event.pending == 0 && + (*times + asyncPending) < limit) { + allowNext = 1; + } + + return allowNext; + } + + static INLINE int bench_async_handle(int* ret, WC_ASYNC_DEV* asyncDev, + int callAgain, int* times) + { + if (*ret == WC_PENDING_E) { + *ret = wc_AsyncHandle(asyncDev, &eventQueue, + callAgain ? WC_ASYNC_FLAG_CALL_AGAIN : WC_ASYNC_FLAG_NONE); + if (*ret == 0) + asyncPending++; + } + else if (*ret >= 0) { + /* operation completed */ + bench_async_complete(ret, asyncDev, times); + } + + return (*ret >= 0) ? 1 : 0; + } + + static INLINE void bench_async_poll(void) + { + /* poll until there are events done */ + if (asyncPending > 0) { + int ret, asyncDone = 0; + do { + ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, + WOLF_POLL_FLAG_CHECK_HW, &asyncDone); + if (ret != 0) { + printf("Async poll failed %d\n", ret); + return; + } + } while (asyncDone == 0); + asyncPending -= asyncDone; + } + } + #else - static byte plain [1024*1024]; + #define BENCH_MAX_PENDING (1) + #define BENCH_ASYNC_GET_NAME(doAsync) "" + #define BENCH_ASYNC_GET_DEV(obj) NULL + #define BENCH_ASYNC_IS_PEND() (0) + + #define bench_async_begin() + #define bench_async_end() (void)doAsync; + + static INLINE int bench_async_check(int* ret, void* asyncDev, + int callAgain, int* times, int limit) + { + (void)ret; + (void)asyncDev; + (void)callAgain; + (void)times; + (void)limit; + + return 1; + } + + static INLINE int bench_async_handle(int* ret, void* asyncDev, + int callAgain, int* times) + { + (void)asyncDev; + (void)callAgain; + + if (*ret >= 0) { + /* operation completed */ + (*times)++; + return 1; + } + return 0; + } + #define bench_async_poll() +#endif /* WOLFSSL_ASYNC_CRYPT */ + + + +/* maximum runtime for each benchmark */ +#define BENCH_MIN_RUNTIME_SEC 1.0f + + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + #define AES_AUTH_ADD_SZ 13 + #define AES_AUTH_TAG_SZ 16 + #define BENCH_CIPHER_ADD AES_AUTH_TAG_SZ +#endif +#ifndef BENCH_CIPHER_ADD + #define BENCH_CIPHER_ADD 0 #endif /* use kB instead of mB for embedded benchmarking */ #ifdef BENCH_EMBEDDED - static byte cipher[1024]; + enum BenchmarkBounds { + numBlocks = 25, /* how many kB to test (en/de)cryption */ + scryptCnt = 1, + ntimes = 2, + genTimes = BENCH_MAX_PENDING, + agreeTimes = 2 + }; + static const char blockType[] = "kB"; /* used in printf output */ + #define BENCH_SIZE (1024ul) #else - static byte cipher[1024*1024]; + enum BenchmarkBounds { + numBlocks = 5, /* how many megs to test (en/de)cryption */ + scryptCnt = 10, + ntimes = 100, + genTimes = BENCH_MAX_PENDING, /* must be at least BENCH_MAX_PENDING */ + agreeTimes = 100 + }; + static const char blockType[] = "megs"; /* used in printf output */ + #define BENCH_SIZE (1024*1024ul) #endif -static const XGEN_ALIGN byte key[] = +/* globals for cipher tests */ +#ifdef WOLFSSL_ASYNC_CRYPT + static byte* bench_plain = NULL; + static byte* bench_cipher = NULL; +#else + static byte bench_plain[BENCH_SIZE]; + static byte bench_cipher[BENCH_SIZE]; +#endif +static const XGEN_ALIGN byte bench_key_buf[] = { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xde,0xba,0x98,0x76,0x54,0x32,0x10, @@ -271,78 +455,246 @@ static const XGEN_ALIGN byte key[] = 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef }; -static const XGEN_ALIGN byte iv[] = +static const XGEN_ALIGN byte bench_iv_buf[] = { 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x11,0x21,0x31,0x41,0x51,0x61,0x71,0x81 }; - - -/* so embedded projects can pull in tests on their own */ -#if !defined(NO_MAIN_DRIVER) - -int main(int argc, char** argv) - -{ - (void)argc; - (void)argv; -#else -int benchmark_test(void *args) -{ - (void)args; -#endif +static byte* bench_key = (byte*)bench_key_buf; +static byte* bench_iv = (byte*)bench_iv_buf; #ifdef WOLFSSL_STATIC_MEMORY #ifdef BENCH_EMBEDDED - byte memory[50000]; + static byte gBenchMemory[50000]; #else - byte memory[400000]; + static byte gBenchMemory[400000]; #endif +#endif - if (wc_LoadStaticMemory(&HEAP_HINT, memory, sizeof(memory), - WOLFMEM_GENERAL, 1) != 0) { - printf("unable to load static memory"); - exit(EXIT_FAILURE); + +/******************************************************************************/ +/* Begin Stats Functions */ +/******************************************************************************/ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + typedef enum bench_stat_type { + BENCH_STAT_ASYM, + BENCH_STAT_SYM, + } bench_stat_type_t; + typedef struct bench_stats { + struct bench_stats* next; + struct bench_stats* prev; + const char* algo; + const char* desc; + double perfsec; + int strength; + int doAsync; + int finishCount; + bench_stat_type_t type; + } bench_stats_t; + static bench_stats_t* bench_stats_head; + static bench_stats_t* bench_stats_tail; + static pthread_mutex_t bench_lock = PTHREAD_MUTEX_INITIALIZER; + + static bench_stats_t* bench_stats_add(bench_stat_type_t type, + const char* algo, int strength, const char* desc, int doAsync, + double perfsec) + { + bench_stats_t* stat; + + pthread_mutex_lock(&bench_lock); + + /* locate existing in list */ + for (stat = bench_stats_head; stat != NULL; stat = stat->next) { + /* match based on algo, strength and desc */ + if (stat->algo == algo && stat->strength == strength && stat->desc == desc && stat->doAsync == doAsync) { + break; + } + } + + if (stat == NULL) { + /* allocate new and put on list */ + stat = (bench_stats_t*)XMALLOC(sizeof(bench_stats_t), NULL, DYNAMIC_TYPE_INFO); + if (stat) { + XMEMSET(stat, 0, sizeof(bench_stats_t)); + + /* add to list */ + stat->next = NULL; + if (bench_stats_tail == NULL) { + bench_stats_head = stat; + } + else { + bench_stats_tail->next = stat; + stat->prev = bench_stats_tail; + } + bench_stats_tail = stat; /* add to the end either way */ + } + } + + if (stat) { + int isLast = 0; + stat->type = type; + stat->algo = algo; + stat->strength = strength; + stat->desc = desc; + stat->doAsync = doAsync; + stat->perfsec += perfsec; + stat->finishCount++; + + if (stat->finishCount == g_threadCount) { + isLast = 1; + } + + pthread_mutex_unlock(&bench_lock); + + /* wait until remaining are complete */ + while (stat->finishCount < g_threadCount) { + wc_AsyncThreadYield(); + } + + /* print final stat */ + if (isLast) { + if (stat->type == BENCH_STAT_SYM) { + printf("%-8s%s %8.3f MB/s\n", stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + else { + printf("%-5s %4d %-9s %s %.3f ops/sec\n", + stat->algo, stat->strength, stat->desc, + BENCH_ASYNC_GET_NAME(stat->doAsync), stat->perfsec); + } + } + + (void)blockType; + } + else { + pthread_mutex_unlock(&bench_lock); + } + + return stat; } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT && !WC_NO_ASYNC_THREADING */ -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - InitMemoryTracker(); +static INLINE void bench_stats_init(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_head = NULL; + bench_stats_tail = NULL; #endif - - wolfCrypt_Init(); INIT_CYCLE_COUNTER +} -#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) - wolfSSL_Debugging_ON(); +static INLINE void bench_stats_start(int* count, double* start) +{ + *count = 0; + *start = current_time(1); + BEGIN_INTEL_CYCLES +} + +static INLINE int bench_stats_sym_check(double start) +{ + return ((current_time(0) - start) < BENCH_MIN_RUNTIME_SEC); +} + +static void bench_stats_sym_finish(const char* desc, int doAsync, int count, double start) +{ + double total, persec = 0; + + END_INTEL_CYCLES + total = current_time(0) - start; + + if (count > 0) + persec = 1 / total * count; +#ifdef BENCH_EMBEDDED + /* since using kB, convert to MB/s */ + persec = persec / 1024; #endif - (void)plain; - (void)cipher; - (void)key; - (void)iv; + printf("%-8s%s %5d %s took %5.3f seconds, %8.3f MB/s", + desc, BENCH_ASYNC_GET_NAME(doAsync), count, blockType, total, persec); + SHOW_INTEL_CYCLES + printf("\n"); + (void)doAsync; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_SYM, NULL, 0, desc, doAsync, persec); +#endif +} + +/* declare here rather than creating a static function to avoid warning of not + * used in the case of something like a leanpsk only build */ +void bench_stats_asym_finish(const char* algo, int strength, + const char* desc, int doAsync, int count, double start); + +void bench_stats_asym_finish(const char* algo, int strength, + const char* desc, int doAsync, int count, double start) +{ + double total, each = 0, opsSec, milliEach; + + total = current_time(0) - start; + if (count > 0) + each = total / count; /* per second */ + opsSec = count / total; /* ops/per second */ + milliEach = each * 1000; /* milliseconds */ + + printf("%-5s %4d %-9s %s %6d ops took %5.3f sec, avg %5.3f ms," + " %.3f ops/sec\n", algo, strength, desc, BENCH_ASYNC_GET_NAME(doAsync), + count, total, milliEach, opsSec); + (void)doAsync; + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + /* Add to thread stats */ + bench_stats_add(BENCH_STAT_ASYM, algo, strength, desc, doAsync, opsSec); +#endif +} + +static INLINE void bench_stats_free(void) +{ +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) + bench_stats_t* stat; + for (stat = bench_stats_head; stat != NULL; ) { + bench_stats_t* next = stat->next; + XFREE(stat, NULL, DYNAMIC_TYPE_INFO); + stat = next; + } + bench_stats_head = NULL; + bench_stats_tail = NULL; +#endif +} +/******************************************************************************/ +/* End Stats Functions */ +/******************************************************************************/ + + +static void* benchmarks_do(void* args) +{ #ifdef WOLFSSL_ASYNC_CRYPT - if (wolfAsync_DevOpen(&devId) != 0) { - printf("Async device open failed\n"); - exit(-1); +#ifndef WC_NO_ASYNC_THREADING + ThreadData* threadData = (ThreadData*)args; + + if (wolfAsync_DevOpenThread(&devId, &threadData->thread_id) < 0) +#else + if (wolfAsync_DevOpen(&devId) < 0) +#endif + { + printf("Async device open failed\nRunning without async\n"); } #endif /* WOLFSSL_ASYNC_CRYPT */ -#ifdef HAVE_WNR - if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { - printf("Whitewood netRandom config init failed\n"); - exit(-1); - } -#endif /* HAVE_WNR */ + (void)args; #if defined(HAVE_LOCAL_RNG) { - int rngRet = wc_InitRng(&rng); + int rngRet; + +#ifndef HAVE_FIPS + rngRet = wc_InitRng_ex(&rng, HEAP_HINT, INVALID_DEVID); +#else + rngRet = wc_InitRng(&rng); +#endif if (rngRet < 0) { printf("InitRNG failed\n"); - return rngRet; } } #endif @@ -352,11 +704,20 @@ int benchmark_test(void *args) #endif /* WC_NO_RNG */ #ifndef NO_AES #ifdef HAVE_AES_CBC - bench_aes(0); - bench_aes(1); + #ifndef NO_SW_BENCH + bench_aescbc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aescbc(1); + #endif #endif #ifdef HAVE_AESGCM - bench_aesgcm(); + #ifndef NO_SW_BENCH + bench_aesgcm(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + bench_aesgcm(1); + #endif #endif #ifdef WOLFSSL_AES_COUNTER bench_aesctr(); @@ -370,7 +731,12 @@ int benchmark_test(void *args) bench_camellia(); #endif #ifndef NO_RC4 - bench_arc4(); + #ifndef NO_SW_BENCH + bench_arc4(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + bench_arc4(1); + #endif #endif #ifdef HAVE_HC128 bench_hc128(); @@ -385,34 +751,67 @@ int benchmark_test(void *args) bench_chacha20_poly1305_aead(); #endif #ifndef NO_DES3 - bench_des(); + #ifndef NO_SW_BENCH + bench_des(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + bench_des(1); + #endif #endif #ifdef HAVE_IDEA bench_idea(); #endif - printf("\n"); - #ifndef NO_MD5 - bench_md5(); + #ifndef NO_SW_BENCH + bench_md5(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + bench_md5(1); + #endif #endif #ifdef HAVE_POLY1305 bench_poly1305(); #endif #ifndef NO_SHA - bench_sha(); + #ifndef NO_SW_BENCH + bench_sha(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + bench_sha(1); + #endif #endif #ifdef WOLFSSL_SHA224 - bench_sha224(); + #ifndef NO_SW_BENCH + bench_sha224(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + bench_sha224(1); + #endif #endif #ifndef NO_SHA256 - bench_sha256(); + #ifndef NO_SW_BENCH + bench_sha256(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + bench_sha256(1); + #endif #endif #ifdef WOLFSSL_SHA384 - bench_sha384(); + #ifndef NO_SW_BENCH + bench_sha384(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + bench_sha384(1); + #endif #endif #ifdef WOLFSSL_SHA512 - bench_sha512(); + #ifndef NO_SW_BENCH + bench_sha512(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + bench_sha512(1); + #endif #endif #ifdef WOLFSSL_RIPEMD bench_ripemd(); @@ -424,26 +823,37 @@ int benchmark_test(void *args) bench_cmac(); #endif - printf("\n"); - #ifdef HAVE_SCRYPT bench_scrypt(); #endif - printf("\n"); - #ifndef NO_RSA - bench_rsa(); - #ifdef WOLFSSL_ASYNC_CRYPT - bench_rsa_async(); - #endif #ifdef WOLFSSL_KEY_GEN - bench_rsaKeyGen(); + #ifndef NO_SW_BENCH + bench_rsaKeyGen(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_rsaKeyGen(1); + #endif + #endif + #endif + #ifndef NO_SW_BENCH + bench_rsa(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + bench_rsa(1); #endif #endif #ifndef NO_DH - bench_dh(); + #ifndef NO_SW_BENCH + bench_dh(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + bench_dh(1); + #endif #endif #ifdef HAVE_NTRU @@ -452,14 +862,24 @@ int benchmark_test(void *args) #endif #ifdef HAVE_ECC - bench_eccKeyGen(); - bench_eccKeyAgree(); + #ifndef NO_SW_BENCH + bench_eccMakeKey(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* async supported in simulator only */ + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + bench_eccMakeKey(1); + #endif + #endif + #ifndef NO_SW_BENCH + bench_ecc(0); + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + bench_ecc(1); + #endif #ifdef HAVE_ECC_ENCRYPT bench_eccEncrypt(); #endif - #if defined(FP_ECC) - wc_ecc_fp_free(); - #endif #endif #ifdef HAVE_CURVE25519 @@ -482,102 +902,176 @@ int benchmark_test(void *args) wolfAsync_DevClose(&devId); #endif -#ifdef HAVE_WNR - if (wc_FreeNetRandom() < 0) { - printf("Failed to free netRandom context\n"); - exit(-1); - } -#endif - -#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) - ShowMemoryTracker(); -#endif - - EXIT_TEST(0); + return NULL; } -#ifdef BENCH_EMBEDDED -enum BenchmarkBounds { - numBlocks = 25, /* how many kB to test (en/de)cryption */ - scryptCnt = 1, - ntimes = 1, - genTimes = 5, /* public key iterations */ - agreeTimes = 5 -}; -static const char blockType[] = "kB"; /* used in printf output */ +/* so embedded projects can pull in tests on their own */ +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args) #else -enum BenchmarkBounds { - numBlocks = 50, /* how many megs to test (en/de)cryption */ - scryptCnt = 10, +int benchmark_test(void *args) +#endif +{ + int ret = 0; + +#ifdef WOLFSSL_STATIC_MEMORY + ret = wc_LoadStaticMemory(&HEAP_HINT, gBenchMemory, sizeof(gBenchMemory), + WOLFMEM_GENERAL, 1); + if (ret != 0) { + printf("unable to load static memory %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } +#endif /* WOLFSSL_STATIC_MEMORY */ + + (void)args; + + wolfCrypt_Init(); + + bench_stats_init(); + +#if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) + wolfSSL_Debugging_ON(); +#endif + + printf("wolfCrypt Benchmark (min %.1f sec each)\n", BENCH_MIN_RUNTIME_SEC); + +#ifdef HAVE_WNR + ret = wc_InitNetRandom(wnrConfigFile, NULL, 5000); + if (ret != 0) { + printf("Whitewood netRandom config init failed %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } +#endif /* HAVE_WNR */ + + /* setup bench plain, cipher, key and iv globals */ #ifdef WOLFSSL_ASYNC_CRYPT - ntimes = 1000, - genTimes = 1000, - agreeTimes = 1000 + bench_plain = (byte*)XMALLOC(BENCH_SIZE+BENCH_CIPHER_ADD, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_cipher = (byte*)XMALLOC(BENCH_SIZE+BENCH_CIPHER_ADD, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_key = (byte*)XMALLOC(sizeof(bench_key_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + bench_iv = (byte*)XMALLOC(sizeof(bench_iv_buf), HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + if (bench_plain == NULL || bench_cipher == NULL || bench_key == NULL || bench_iv == NULL) { + printf("Benchmark cipher buffer alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); + } + XMEMCPY(bench_key, bench_key_buf, sizeof(bench_key_buf)); + XMEMCPY(bench_iv, bench_iv_buf, sizeof(bench_iv_buf)); + XMEMSET(bench_plain, 0, BENCH_SIZE+BENCH_CIPHER_ADD); + XMEMSET(bench_cipher, 0, BENCH_SIZE+BENCH_CIPHER_ADD); +#endif + (void)bench_plain; + (void)bench_cipher; + (void)bench_key; + (void)bench_iv; + + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_NO_ASYNC_THREADING) +{ + int i; + int numCpus = wc_AsyncGetNumberOfCpus(); + + printf("CPUs: %d\n", numCpus); + + g_threadData = (ThreadData*)XMALLOC(sizeof(ThreadData) * numCpus, + HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (g_threadData == NULL) { + printf("Thread data alloc failed!\n"); + EXIT_TEST(EXIT_FAILURE); + } + g_threadCount = numCpus; + + /* Create threads */ + for (i = 0; i < numCpus; i++) { + ret = wc_AsyncThreadCreate(&g_threadData[i].thread_id, + benchmarks_do, &g_threadData[i]); + if (ret != 0) { + printf("Error creating benchmark thread %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } + } + + /* Start threads */ + for (i = 0; i < numCpus; i++) { + wc_AsyncThreadJoin(&g_threadData[i].thread_id); + } + + XFREE(g_threadData, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +} #else - ntimes = 100, - genTimes = 100, - agreeTimes = 100 + benchmarks_do(NULL); #endif -}; -static const char blockType[] = "megs"; /* used in printf output */ + +#ifdef WOLFSSL_ASYNC_CRYPT + XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_cipher, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_key, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); + XFREE(bench_iv, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); #endif +#ifdef HAVE_WNR + ret = wc_FreeNetRandom(); + if (ret < 0) { + printf("Failed to free netRandom context %d\n", ret); + EXIT_TEST(EXIT_FAILURE); + } +#endif + + bench_stats_free(); + + if (wolfCrypt_Cleanup() != 0) { + printf("error with wolfCrypt_Cleanup\n"); + } + + EXIT_TEST(ret); +} + + #ifndef WC_NO_RNG void bench_rng(void) { - int ret, i; - double start, total, persec; - int pos, len, remain; -#ifndef HAVE_LOCAL_RNG - WC_RNG rng; -#endif + int ret, i, count; + double start; + int pos, len, remain; + WC_RNG myrng; -#ifndef HAVE_LOCAL_RNG - ret = wc_InitRng(&rng); +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&myrng); +#endif if (ret < 0) { - printf("InitRNG failed\n"); + printf("InitRNG failed %d\n", ret); return; } -#endif - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + /* Split request to handle large RNG request */ + pos = 0; + remain = (int)BENCH_SIZE; + while (remain > 0) { + len = remain; + if (len > RNG_MAX_BLOCK_LEN) + len = RNG_MAX_BLOCK_LEN; + ret = wc_RNG_GenerateBlock(&myrng, &bench_plain[pos], len); + if (ret < 0) + goto exit_rng; - for(i = 0; i < numBlocks; i++) { - /* Split request to handle large RNG request */ - pos = 0; - remain = (int)sizeof(plain); - while (remain > 0) { - len = remain; - if (len > RNG_MAX_BLOCK_LEN) - len = RNG_MAX_BLOCK_LEN; - ret = wc_RNG_GenerateBlock(&rng, &plain[pos], len); - if (ret < 0) { - printf("wc_RNG_GenerateBlock failed %d\n", ret); - break; + remain -= len; + pos += len; } - remain -= len; - pos += len; } + count += i; + } while (bench_stats_sym_check(start)); +exit_rng: + bench_stats_sym_finish("RNG", 0, count, start); + + if (ret < 0) { + printf("wc_RNG_GenerateBlock failed %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - printf("RNG %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - -#ifndef HAVE_LOCAL_RNG - wc_FreeRng(&rng); -#endif + wc_FreeRng(&myrng); } #endif /* WC_NO_RNG */ @@ -585,143 +1079,180 @@ void bench_rng(void) #ifndef NO_AES #ifdef HAVE_AES_CBC -void bench_aes(int show) +void bench_aescbc(int doAsync) { - Aes enc; - double start, total, persec; - int i; - int ret; + int ret, i, count = 0, times; + Aes enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesSetKey(&enc[i], bench_key, 16, bench_iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } } -#endif - ret = wc_AesSetKey(&enc, key, 16, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesCbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_enc; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_enc: + bench_stats_sym_finish("AES-Enc", doAsync, count, start); + + if (ret < 0) { + goto exit; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCbcEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - if (show) { - printf("AES enc %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); +#ifdef HAVE_AES_DECRYPT + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_AesSetKey(&enc[i], bench_key, 16, bench_iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed, ret = %d\n", ret); + goto exit; + } } -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); - if ((ret = wc_AesAsyncInit(&enc, devId)) != 0) { - printf("wc_AesAsyncInit failed, ret = %d\n", ret); - return; + + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesCbcDecrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_dec; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_dec: + bench_stats_sym_finish("AES-Dec", doAsync, count, start); + +#endif /* HAVE_AES_DECRYPT */ + +exit: + + if (ret < 0) { + printf("bench_aescbc failed: %d\n", ret); } -#endif - ret = wc_AesSetKey(&enc, key, 16, iv, AES_DECRYPTION); - if (ret != 0) { - printf("AesSetKey failed, ret = %d\n", ret); - return; + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCbcDecrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - if (show) { - printf("AES dec %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - } -#ifdef WOLFSSL_ASYNC_CRYPT - wc_AesAsyncFree(&enc); -#endif + bench_async_end(); } #endif /* HAVE_AES_CBC */ -#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) - static byte additional[13]; - static byte tag[16]; -#endif - - #ifdef HAVE_AESGCM -void bench_aesgcm(void) +void bench_aesgcm(int doAsync) { - Aes enc; - double start, total, persec; - int i; + int ret, i, count = 0, times; + Aes enc[BENCH_MAX_PENDING]; + double start; - wc_AesGcmSetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); - for(i = 0; i < numBlocks; i++) - wc_AesGcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); + bench_async_begin(); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_additional) #endif - - printf("AES-GCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); - -#if 0 - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) - wc_AesGcmDecrypt(&enc, plain, cipher, sizeof(cipher), iv, 12, - tag, 16, additional, 13); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + { XMEMSET(bench_additional, 0, AES_AUTH_ADD_SZ); } +#ifdef WOLFSSL_ASYNC_CRYPT + if (bench_tag) #endif + { XMEMSET(bench_tag, 0, AES_AUTH_TAG_SZ); } - printf("AES-GCM Decrypt %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#endif + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_AesInit(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("AesInit failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_AesGcmSetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("AesGcmSetKey failed, ret = %d\n", ret); + goto exit; + } + } + + /* GCM uses same routine in backend for both encrypt and decrypt */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_AesGcmEncrypt(&enc[i], bench_cipher, + bench_plain, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_aes_gcm; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_aes_gcm: + bench_stats_sym_finish("AES-GCM", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_aesgcm failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_AesFree(&enc[i]); + } + + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); + + bench_async_end(); } #endif /* HAVE_AESGCM */ @@ -730,29 +1261,19 @@ void bench_aesgcm(void) void bench_aesctr(void) { Aes enc; - double start, total, persec; - int i; + double start; + int i, count; - wc_AesSetKeyDirect(&enc, key, AES_BLOCK_SIZE, iv, AES_ENCRYPTION); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_AesSetKeyDirect(&enc, bench_key, AES_BLOCK_SIZE, bench_iv, AES_ENCRYPTION); - for(i = 0; i < numBlocks; i++) - wc_AesCtrEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CTR %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_AesCtrEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CTR", 0, count, start); } #endif /* WOLFSSL_AES_COUNTER */ @@ -761,34 +1282,30 @@ void bench_aesctr(void) void bench_aesccm(void) { Aes enc; - double start, total, persec; - int i; - int ret; + double start; + int ret, i, count; - if ((ret = wc_AesCcmSetKey(&enc, key, 16)) != 0) { + DECLARE_VAR(bench_additional, byte, AES_AUTH_ADD_SZ, HEAP_HINT); + DECLARE_VAR(bench_tag, byte, AES_AUTH_TAG_SZ, HEAP_HINT); + + if ((ret = wc_AesCcmSetKey(&enc, bench_key, 16)) != 0) { printf("wc_AesCcmSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_AesCcmEncrypt(&enc, cipher, plain, sizeof(plain), iv, 12, - tag, 16, additional, 13); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_AesCcmEncrypt(&enc, bench_cipher, bench_plain, BENCH_SIZE, + bench_iv, 12, bench_tag, AES_AUTH_TAG_SZ, + bench_additional, AES_AUTH_ADD_SZ); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CCM", 0, count, start); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CCM %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_VAR(bench_additional, HEAP_HINT); + FREE_VAR(bench_tag, HEAP_HINT); } #endif /* HAVE_AESCCM */ #endif /* !NO_AES */ @@ -797,38 +1314,30 @@ void bench_aesccm(void) #ifdef HAVE_POLY1305 void bench_poly1305() { - Poly1305 enc; - byte mac[16]; - double start, total, persec; - int i; - int ret; + Poly1305 enc; + byte mac[16]; + double start; + int ret, i, count; - - ret = wc_Poly1305SetKey(&enc, key, 32); + ret = wc_Poly1305SetKey(&enc, bench_key, 32); if (ret != 0) { printf("Poly1305SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Poly1305Update(&enc, plain, sizeof(plain)); - - wc_Poly1305Final(&enc, mac); - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("POLY1305 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Poly1305Update(&enc, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Poly1305Update failed: %d\n", ret); + break; + } + } + wc_Poly1305Final(&enc, mac); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("POLY1305", 0, count, start); } #endif /* HAVE_POLY1305 */ @@ -837,178 +1346,197 @@ void bench_poly1305() void bench_camellia(void) { Camellia cam; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_CamelliaSetKey(&cam, key, 16, iv); + ret = wc_CamelliaSetKey(&cam, bench_key, 16, bench_iv); if (ret != 0) { printf("CamelliaSetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_CamelliaCbcEncrypt(&cam, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("Camellia %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_CamelliaCbcEncrypt(&cam, bench_plain, bench_cipher, + BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("Camellia", 0, count, start); } #endif #ifndef NO_DES3 -void bench_des(void) +void bench_des(int doAsync) { - Des3 enc; - double start, total, persec; - int i, ret; + int ret, i, count = 0, times; + Des3 enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Des3AsyncInit(&enc, devId) != 0) - printf("des3 async init failed\n"); -#endif - ret = wc_Des3_SetKey(&enc, key, iv, DES_ENCRYPTION); - if (ret != 0) { - printf("Des3_SetKey failed, ret = %d\n", ret); - return; + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Des3Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Des3Init failed, ret = %d\n", ret); + goto exit; + } + + ret = wc_Des3_SetKey(&enc[i], bench_key, bench_iv, DES_ENCRYPTION); + if (ret != 0) { + printf("Des3_SetKey failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_Des3_CbcEncrypt(&enc, plain, cipher, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - END_INTEL_CYCLES - total = current_time(0) - start; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_Des3_CbcEncrypt(&enc[i], bench_plain, bench_cipher, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_3des; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_3des: + bench_stats_sym_finish("3DES", doAsync, count, start); - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif +exit: - printf("3DES %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Des3AsyncFree(&enc); -#endif + if (ret < 0) { + printf("bench_des failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Des3Free(&enc[i]); + } + + bench_async_end(); } -#endif +#endif /* !NO_DES3 */ #ifdef HAVE_IDEA void bench_idea(void) { Idea enc; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_IdeaSetKey(&enc, key, IDEA_KEY_SIZE, iv, IDEA_ENCRYPTION); + ret = wc_IdeaSetKey(&enc, bench_key, IDEA_KEY_SIZE, bench_iv, + IDEA_ENCRYPTION); if (ret != 0) { printf("Des3_SetKey failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_IdeaCbcEncrypt(&enc, plain, cipher, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("IDEA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_IdeaCbcEncrypt(&enc, bench_plain, bench_cipher, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("IDEA", 0, count, start); } #endif /* HAVE_IDEA */ #ifndef NO_RC4 -void bench_arc4(void) +void bench_arc4(int doAsync) { - Arc4 enc; - double start, total, persec; - int i; + int ret, i, count = 0, times; + Arc4 enc[BENCH_MAX_PENDING]; + double start; -#ifdef WOLFSSL_ASYNC_CRYPT - if (wc_Arc4AsyncInit(&enc, devId) != 0) - printf("arc4 async init failed\n"); -#endif + bench_async_begin(); - wc_Arc4SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES + /* clear for done cleanup */ + XMEMSET(enc, 0, sizeof(enc)); - for(i = 0; i < numBlocks; i++) - wc_Arc4Process(&enc, cipher, plain, sizeof(plain)); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if ((ret = wc_Arc4Init(&enc[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) != 0) { + printf("Arc4Init failed, ret = %d\n", ret); + goto exit; + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif + ret = wc_Arc4SetKey(&enc[i], bench_key, 16); + if (ret != 0) { + printf("Arc4SetKey failed, ret = %d\n", ret); + goto exit; + } + } - printf("ARC4 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); -#ifdef WOLFSSL_ASYNC_CRYPT - wc_Arc4AsyncFree(&enc); -#endif + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×, numBlocks)) { + ret = wc_Arc4Process(&enc[i], bench_cipher, bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&enc[i]), 0, ×)) { + goto exit_arc4; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_arc4: + bench_stats_sym_finish("ARC4", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_arc4 failed: %d\n", ret); + } + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Arc4Free(&enc[i]); + } + + bench_async_end(); } -#endif +#endif /* !NO_RC4 */ #ifdef HAVE_HC128 void bench_hc128(void) { HC128 enc; - double start, total, persec; - int i; + double start; + int i, count; - wc_Hc128_SetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_Hc128_SetKey(&enc, bench_key, bench_iv); - for(i = 0; i < numBlocks; i++) - wc_Hc128_Process(&enc, cipher, plain, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("HC128 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Hc128_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("HC128", 0, count, start); } #endif /* HAVE_HC128 */ @@ -1016,29 +1544,20 @@ void bench_hc128(void) #ifndef NO_RABBIT void bench_rabbit(void) { - Rabbit enc; - double start, total, persec; - int i; + Rabbit enc; + double start; + int i, count; - wc_RabbitSetKey(&enc, key, iv); - start = current_time(1); - BEGIN_INTEL_CYCLES + wc_RabbitSetKey(&enc, bench_key, bench_iv); - for(i = 0; i < numBlocks; i++) - wc_RabbitProcess(&enc, cipher, plain, sizeof(plain)); - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("RABBIT %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_RabbitProcess(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RABBIT", 0, count, start); } #endif /* NO_RABBIT */ @@ -1047,347 +1566,534 @@ void bench_rabbit(void) void bench_chacha(void) { ChaCha enc; - double start, total, persec; - int i; + double start; + int i, count; - wc_Chacha_SetKey(&enc, key, 16); - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) { - wc_Chacha_SetIV(&enc, iv, 0); - wc_Chacha_Process(&enc, cipher, plain, sizeof(plain)); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("CHACHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + wc_Chacha_SetKey(&enc, bench_key, 16); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + wc_Chacha_SetIV(&enc, bench_iv, 0); + wc_Chacha_Process(&enc, bench_cipher, bench_plain, BENCH_SIZE); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHACHA", 0, count, start); } #endif /* HAVE_CHACHA*/ -#if( defined( HAVE_CHACHA ) && defined( HAVE_POLY1305 ) ) +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) void bench_chacha20_poly1305_aead(void) { - double start, total, persec; - int i; + double start; + int ret, i, count; byte authTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; - XMEMSET( authTag, 0, sizeof( authTag ) ); - - start = current_time(1); - BEGIN_INTEL_CYCLES - - for (i = 0; i < numBlocks; i++) - { - wc_ChaCha20Poly1305_Encrypt(key, iv, NULL, 0, plain, sizeof(plain), - cipher, authTag ); - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("CHA-POLY %d %s took %5.3f seconds, %8.3f MB/s", - numBlocks, blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + XMEMSET(authTag, 0, sizeof(authTag)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_ChaCha20Poly1305_Encrypt(bench_key, bench_iv, NULL, 0, + bench_plain, BENCH_SIZE, bench_cipher, authTag); + if (ret < 0) { + printf("wc_ChaCha20Poly1305_Encrypt error: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("CHA-POLY", 0, count, start); } #endif /* HAVE_CHACHA && HAVE_POLY1305 */ #ifndef NO_MD5 -void bench_md5(void) +void bench_md5(int doAsync) { - Md5 hash; - byte digest[MD5_DIGEST_SIZE]; - double start, total, persec; - int i; + Md5 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, MD5_DIGEST_SIZE, HEAP_HINT); - wc_InitMd5(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) - wc_Md5Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); - wc_Md5Final(&hash, digest); + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitMd5_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitMd5_ex failed, ret = %d\n", ret); + goto exit; + } + } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Md5Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_md5; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Md5Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_md5; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_md5: + bench_stats_sym_finish("MD5", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_md5 failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Md5Free(&hash[i]); + } #endif - printf("MD5 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #ifndef NO_SHA -void bench_sha(void) +void bench_sha(int doAsync) { - Sha hash; - byte digest[SHA_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha(&hash); - if (ret != 0) { - printf("InitSha failed, ret = %d\n", ret); - return; + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) { + printf("InitSha failed, ret = %d\n", ret); + goto exit; + } } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) - wc_ShaUpdate(&hash, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - wc_ShaFinal(&hash, digest); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_ShaUpdate(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha; + } + } + } /* for i */ + } /* for times */ + count += times; - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; + times = 0; + do { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_ShaFinal(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha: + bench_stats_sym_finish("SHA", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha failed: %d\n", ret); + } + +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ShaFree(&hash[i]); + } #endif - printf("SHA %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif /* NO_SHA */ #ifdef WOLFSSL_SHA224 -void bench_sha224(void) +void bench_sha224(int doAsync) { - Sha224 hash; - byte digest[SHA224_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha224 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA224_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha224(&hash); - if (ret != 0) { - printf("InitSha224 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha224Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha224_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha224Update failed, ret = %d\n", ret); - return; + printf("InitSha224_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha224Final(&hash, digest); - if (ret != 0) { - printf("Sha224Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha224Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha224; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha224Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha224; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha224: + bench_stats_sym_finish("SHA-224", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha224 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha224Free(&hash[i]); + } #endif - printf("SHA-224 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifndef NO_SHA256 -void bench_sha256(void) +void bench_sha256(int doAsync) { - Sha256 hash; - byte digest[SHA256_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha256 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA256_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha256(&hash); - if (ret != 0) { - printf("InitSha256 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha256Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha256_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha256Update failed, ret = %d\n", ret); - return; + printf("InitSha256_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha256Final(&hash, digest); - if (ret != 0) { - printf("Sha256Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha256Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha256; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha256Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha256; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha256: + bench_stats_sym_finish("SHA-256", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha256 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha256Free(&hash[i]); + } #endif - printf("SHA-256 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_SHA384 -void bench_sha384(void) +void bench_sha384(int doAsync) { - Sha384 hash; - byte digest[SHA384_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha384 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA384_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha384(&hash); - if (ret != 0) { - printf("InitSha384 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha384Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha384_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha384Update failed, ret = %d\n", ret); - return; + printf("InitSha384_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha384Final(&hash, digest); - if (ret != 0) { - printf("Sha384Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha384Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha384; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha384Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha384; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha384: + bench_stats_sym_finish("SHA-384", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha384 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha384Free(&hash[i]); + } #endif - printf("SHA-384 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_SHA512 -void bench_sha512(void) +void bench_sha512(int doAsync) { - Sha512 hash; - byte digest[SHA512_DIGEST_SIZE]; - double start, total, persec; - int i, ret; + Sha512 hash[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, SHA512_DIGEST_SIZE, HEAP_HINT); - ret = wc_InitSha512(&hash); - if (ret != 0) { - printf("InitSha512 failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES + bench_async_begin(); - for(i = 0; i < numBlocks; i++) { - ret = wc_Sha512Update(&hash, plain, sizeof(plain)); + /* clear for done cleanup */ + XMEMSET(hash, 0, sizeof(hash)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + ret = wc_InitSha512_ex(&hash[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); if (ret != 0) { - printf("Sha512Update failed, ret = %d\n", ret); - return; + printf("InitSha512_ex failed, ret = %d\n", ret); + goto exit; } } - ret = wc_Sha512Final(&hash, digest); - if (ret != 0) { - printf("Sha512Final failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (times = 0; times < numBlocks || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha512Update(&hash[i], bench_plain, + BENCH_SIZE); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha512; + } + } + } /* for i */ + } /* for times */ + count += times; + + times = 0; + do { + bench_async_poll(); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×, numBlocks)) { + ret = wc_Sha512Final(&hash[i], digest[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&hash[i]), 0, ×)) { + goto exit_sha512; + } + } + } /* for i */ + } while (BENCH_ASYNC_IS_PEND()); + } while (bench_stats_sym_check(start)); +exit_sha512: + bench_stats_sym_finish("SHA-512", doAsync, count, start); + +exit: + + if (ret < 0) { + printf("bench_sha512 failed: %d\n", ret); } - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; +#ifdef WOLFSSL_ASYNC_CRYPT + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_Sha512Free(&hash[i]); + } #endif - printf("SHA-512 %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } #endif #ifdef WOLFSSL_RIPEMD -void bench_ripemd(void) +int bench_ripemd(void) { RipeMd hash; byte digest[RIPEMD_DIGEST_SIZE]; - double start, total, persec; - int i; + double start; + int i, count, ret; - wc_InitRipeMd(&hash); - start = current_time(1); - BEGIN_INTEL_CYCLES + ret = wc_InitRipeMd(&hash); + if (ret != 0) { + return ret; + } - for(i = 0; i < numBlocks; i++) - wc_RipeMdUpdate(&hash, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_RipeMdUpdate(&hash, bench_plain, BENCH_SIZE); + if (ret != 0) { + return ret; + } + } + ret = wc_RipeMdFinal(&hash, digest); + if (ret != 0) { + return ret; + } - wc_RipeMdFinal(&hash, digest); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("RIPEMD", 0, count, start); - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("RIPEMD %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + return 0; } #endif @@ -1397,43 +2103,32 @@ void bench_blake2(void) { Blake2b b2b; byte digest[64]; - double start, total, persec; - int i, ret; + double start; + int ret, i, count; ret = wc_InitBlake2b(&b2b, 64); if (ret != 0) { printf("InitBlake2b failed, ret = %d\n", ret); return; } - start = current_time(1); - BEGIN_INTEL_CYCLES - for(i = 0; i < numBlocks; i++) { - ret = wc_Blake2bUpdate(&b2b, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + ret = wc_Blake2bUpdate(&b2b, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("Blake2bUpdate failed, ret = %d\n", ret); + return; + } + } + ret = wc_Blake2bFinal(&b2b, digest, 64); if (ret != 0) { - printf("Blake2bUpdate failed, ret = %d\n", ret); + printf("Blake2bFinal failed, ret = %d\n", ret); return; } - } - - ret = wc_Blake2bFinal(&b2b, digest, 64); - if (ret != 0) { - printf("Blake2bFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("BLAKE2b %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("BLAKE2b", 0, count, start); } #endif @@ -1445,43 +2140,33 @@ void bench_cmac(void) Cmac cmac; byte digest[AES_BLOCK_SIZE]; word32 digestSz = sizeof(digest); - double start, total, persec; - int i, ret; + double start; + int ret, i, count; - ret = wc_InitCmac(&cmac, key, 16, WC_CMAC_AES, NULL); - if (ret != 0) { - printf("InitCmac failed, ret = %d\n", ret); - return; - } - start = current_time(1); - BEGIN_INTEL_CYCLES - - for(i = 0; i < numBlocks; i++) { - ret = wc_CmacUpdate(&cmac, plain, sizeof(plain)); + bench_stats_start(&count, &start); + do { + ret = wc_InitCmac(&cmac, bench_key, 16, WC_CMAC_AES, NULL); if (ret != 0) { - printf("CmacUpdate failed, ret = %d\n", ret); + printf("InitCmac failed, ret = %d\n", ret); return; } - } - ret = wc_CmacFinal(&cmac, digest, &digestSz); - if (ret != 0) { - printf("CmacFinal failed, ret = %d\n", ret); - return; - } - - END_INTEL_CYCLES - total = current_time(0) - start; - persec = 1 / total * numBlocks; -#ifdef BENCH_EMBEDDED - /* since using kB, convert to MB/s */ - persec = persec / 1024; -#endif - - printf("AES-CMAC %d %s took %5.3f seconds, %8.3f MB/s", numBlocks, - blockType, total, persec); - SHOW_INTEL_CYCLES - printf("\n"); + for (i = 0; i < numBlocks; i++) { + ret = wc_CmacUpdate(&cmac, bench_plain, BENCH_SIZE); + if (ret != 0) { + printf("CmacUpdate failed, ret = %d\n", ret); + return; + } + } + /* Note: final force zero's the Cmac struct */ + ret = wc_CmacFinal(&cmac, digest, &digestSz); + if (ret != 0) { + printf("CmacFinal failed, ret = %d\n", ret); + return; + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_sym_finish("AES-CMAC", 0, count, start); } #endif /* WOLFSSL_CMAC */ @@ -1491,30 +2176,89 @@ void bench_cmac(void) void bench_scrypt(void) { byte derived[64]; - double start, total, each, milliEach; - int ret, i; + double start; + int ret, i, count; - start = current_time(1); - for (i = 0; i < scryptCnt; i++) { - ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, - (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); - if (ret != 0) { - printf("scrypt failed, ret = %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < scryptCnt; i++) { + ret = wc_scrypt(derived, (byte*)"pleaseletmein", 13, + (byte*)"SodiumChloride", 14, 14, 8, 1, sizeof(derived)); + if (ret != 0) { + printf("scrypt failed, ret = %d\n", ret); + goto exit; + } } - } - total = current_time(0) - start; - each = total / scryptCnt; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("scrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, scryptCnt); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("scrypt", 0, "", 0, count, start); } #endif /* HAVE_SCRYPT */ #ifndef NO_RSA +#if defined(WOLFSSL_KEY_GEN) +void bench_rsaKeyGen(int doAsync) +{ + RsaKey genKey[BENCH_MAX_PENDING]; + double start; + int ret, i, count = 0, times; + int k, keySz; + const int keySizes[2] = {1024, 2048}; + const long rsa_e_val = 65537; + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(genKey, 0, sizeof(genKey)); + + for (k = 0; k < (int)(sizeof(keySizes)/sizeof(int)); k++) { + keySz = keySizes[k]; + + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes)) { + + wc_FreeRsaKey(&genKey[i]); + ret = wc_InitRsaKey_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_MakeRsaKey(&genKey[i], keySz, rsa_e_val, &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); + exit: + bench_stats_asym_finish("RSA", keySz, "key gen", doAsync, count, start); + + if (ret < 0) { + printf("bench_rsaKeyGen failed: %d\n", ret); + break; + } + } + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeRsaKey(&genKey[i]); + } + + bench_async_end(); +} +#endif /* WOLFSSL_KEY_GEN */ #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) @@ -1528,21 +2272,23 @@ void bench_scrypt(void) #endif #endif -void bench_rsa(void) +#define RSA_BUF_SIZE 256 /* for up to 2048 bit */ + +void bench_rsa(int doAsync) { - int i; - int ret; - size_t bytes; - word32 idx = 0; + int ret, i, times, count = 0; + size_t bytes; + word32 idx = 0; const byte* tmp; + const char* messageStr = "Everyone gets Friday off."; + const int len = (int)XSTRLEN((char*)messageStr); + double start = 0.0f; + RsaKey rsaKey[BENCH_MAX_PENDING]; + int rsaKeySz = RSA_BUF_SIZE * 8; /* used in printf */ - const byte message[] = "Everyone gets Friday off."; - byte enc[256]; /* for up to 2048 bit */ - const int len = (int)strlen((char*)message); - double start, total, each, milliEach; - - RsaKey rsaKey; - int rsaKeySz = 2048; /* used in printf */ + DECLARE_VAR_INIT(message, byte, len, messageStr, HEAP_HINT); + DECLARE_ARRAY(enc, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); + DECLARE_ARRAY(out, byte, BENCH_MAX_PENDING, RSA_BUF_SIZE, HEAP_HINT); #ifdef USE_CERT_BUFFERS_1024 tmp = rsa_key_der_1024; @@ -1555,271 +2301,114 @@ void bench_rsa(void) #error "need a cert buffer size" #endif /* USE_CERT_BUFFERS */ - if ((ret = wc_InitRsaKey(&rsaKey, HEAP_HINT)) < 0) { - printf("InitRsaKey failed! %d\n", ret); - return; - } - - /* decode the private key */ - ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey, (word32)bytes); - - start = current_time(1); - - for (i = 0; i < ntimes; i++) { - ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), - &rsaKey, &rng); - if (ret < 0) { - break; - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d public %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - if (ret < 0) { - printf("Rsa Public Encrypt failed! %d\n", ret); - return; - } - -#ifdef WC_RSA_BLINDING - wc_RsaSetRNG(&rsaKey, &rng); -#endif - start = current_time(1); - - /* capture resulting encrypt length */ - idx = ret; - - for (i = 0; i < ntimes; i++) { - byte out[256]; /* for up to 2048 bit */ - - ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), &rsaKey); - if (ret < 0 && ret != WC_PENDING_E) { - break; - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d private %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - - wc_FreeRsaKey(&rsaKey); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT -void bench_rsa_async(void) -{ - int i; - int ret; - size_t bytes; - word32 idx = 0; - const byte* tmp; - - const byte message[] = "Everyone gets Friday off."; - byte enc[256]; /* for up to 2048 bit */ - const int len = (int)strlen((char*)message); - double start, total, each, milliEach; - - RsaKey rsaKey[WOLF_ASYNC_MAX_PENDING]; - int rsaKeySz = 2048; /* used in printf */ - - WOLF_EVENT events[WOLF_ASYNC_MAX_PENDING]; - WOLF_EVENT_QUEUE eventQueue; - int evtNum, asyncDone, asyncPend; - -#ifdef USE_CERT_BUFFERS_1024 - tmp = rsa_key_der_1024; - bytes = sizeof_rsa_key_der_1024; - rsaKeySz = 1024; -#elif defined(USE_CERT_BUFFERS_2048) - tmp = rsa_key_der_2048; - bytes = sizeof_rsa_key_der_2048; -#else - #error "need a cert buffer size" -#endif /* USE_CERT_BUFFERS */ - - /* init event queue */ - ret = wolfEventQueue_Init(&eventQueue); - if (ret != 0) { - return; - } + bench_async_begin(); /* clear for done cleanup */ - XMEMSET(&events, 0, sizeof(events)); - XMEMSET(&rsaKey, 0, sizeof(rsaKey)); + XMEMSET(rsaKey, 0, sizeof(rsaKey)); - /* init events and keys */ - for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { /* setup an async context for each key */ - if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, devId)) < 0) { - goto done; + if ((ret = wc_InitRsaKey_ex(&rsaKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; } + #ifdef WC_RSA_BLINDING - wc_RsaSetRNG(&rsaKey[i], &rng); + ret = wc_RsaSetRNG(&rsaKey[i], &rng); + if (ret != 0) + goto exit; #endif - if ((ret = wolfAsync_EventInit(&events[i], - WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, &rsaKey[i].asyncDev)) != 0) { - goto done; - } - events[i].pending = 0; /* Reset pending flag */ /* decode the private key */ idx = 0; if ((ret = wc_RsaPrivateKeyDecode(tmp, &idx, &rsaKey[i], (word32)bytes)) != 0) { printf("wc_RsaPrivateKeyDecode failed! %d\n", ret); - goto done; + goto exit; } } - /* begin public async RSA */ - start = current_time(1); + /* begin public RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - asyncPend = 0; - for (i = 0; i < ntimes; ) { - - /* while free pending slots in queue, submit RSA operations */ - for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { - if (events[evtNum].done || (events[evtNum].pending == 0 && - (i + asyncPend) < ntimes)) - { - /* check for event error */ - if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { - printf("wc_RsaPublicEncrypt: Async event error: %d\n", events[evtNum].ret); - goto done; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes)) { + ret = wc_RsaPublicEncrypt(message, len, enc[i], + RSA_BUF_SIZE, &rsaKey[i], &rng); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×)) { + goto exit_rsa_pub; + } } - - ret = wc_RsaPublicEncrypt(message, len, enc, sizeof(enc), - &rsaKey[evtNum], &rng); - if (ret == WC_PENDING_E) { - ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, - &events[evtNum]); - if (ret != 0) goto done; - asyncPend++; - } - else if (ret >= 0) { - /* operation completed */ - i++; - asyncPend--; - events[evtNum].done = 0; - } - else { - printf("wc_RsaPublicEncrypt failed: %d\n", ret); - goto done; - } - } - } /* for evtNum */ - - /* poll until there are events done */ - if (asyncPend > 0) { - do { - ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, - WOLF_POLL_FLAG_CHECK_HW, &asyncDone); - if (ret != 0) goto done; - } while (asyncDone == 0); - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d public async %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_rsa_pub: + bench_stats_asym_finish("RSA", rsaKeySz, "public", doAsync, count, start); if (ret < 0) { - goto done; + goto exit; } - - /* begin private async RSA */ - start = current_time(1); +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&rsaKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif /* capture resulting encrypt length */ - idx = sizeof(enc); /* fixed at 2048 bit */ + idx = RSA_BUF_SIZE; /* fixed at 2048 bit */ - asyncPend = 0; - for (i = 0; i < ntimes; ) { - byte out[256]; /* for up to 2048 bit */ + /* begin private async RSA */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < ntimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - /* while free pending slots in queue, submit RSA operations */ - for (evtNum = 0; evtNum < WOLF_ASYNC_MAX_PENDING; evtNum++) { - if (events[evtNum].done || (events[evtNum].pending == 0 && - (i + asyncPend) < ntimes)) - { - /* check for event error */ - if (events[evtNum].ret != WC_PENDING_E && events[evtNum].ret < 0) { - printf("wc_RsaPrivateDecrypt: Async event error: %d\n", events[evtNum].ret); - goto done; + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×, ntimes)) { + ret = wc_RsaPrivateDecrypt(enc[i], idx, out[i], + RSA_BUF_SIZE, &rsaKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&rsaKey[i]), 1, ×)) { + goto exit; + } } - - ret = wc_RsaPrivateDecrypt(enc, idx, out, sizeof(out), - &rsaKey[evtNum]); - if (ret == WC_PENDING_E) { - ret = wc_RsaAsyncHandle(&rsaKey[evtNum], &eventQueue, - &events[evtNum]); - if (ret != 0) goto done; - asyncPend++; - } - else if (ret >= 0) { - /* operation completed */ - i++; - asyncPend--; - events[evtNum].done = 0; - } - else { - printf("wc_RsaPrivateDecrypt failed: %d\n", ret); - goto done; - } - } - } /* for evtNum */ - - /* poll until there are events done */ - if (asyncPend > 0) { - do { - ret = wolfAsync_EventQueuePoll(&eventQueue, NULL, NULL, 0, - WOLF_POLL_FLAG_CHECK_HW, &asyncDone); - if (ret != 0) goto done; - } while (asyncDone == 0); - } - } /* for ntimes */ - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("RSA %d private async %6.3f milliseconds, avg over %d" - " iterations\n", rsaKeySz, milliEach, ntimes); - -done: + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("RSA", rsaKeySz, "private", doAsync, count, start); if (ret < 0) { - printf("bench_rsa_async failed: %d\n", ret); + printf("bench_rsa failed: %d\n", ret); } /* cleanup */ - for (i = 0; i < WOLF_ASYNC_MAX_PENDING; i++) { + for (i = 0; i < BENCH_MAX_PENDING; i++) { wc_FreeRsaKey(&rsaKey[i]); } - /* free event queue */ - wolfEventQueue_Free(&eventQueue); + FREE_ARRAY(enc, BENCH_MAX_PENDING, HEAP_HINT); + FREE_ARRAY(out, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(message, HEAP_HINT); + + bench_async_end(); } -#endif /* WOLFSSL_ASYNC_CRYPT */ #endif /* !NO_RSA */ #ifndef NO_DH - #if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) #if defined(WOLFSSL_MDK_SHELL) static char *certDHname = "certs/dh2048.der"; @@ -1834,27 +2423,35 @@ done: #endif #endif -void bench_dh(void) +#define BENCH_DH_KEY_SIZE 256 /* for 2048 bit */ +#define BENCH_DH_PRIV_SIZE (BENCH_DH_KEY_SIZE/8) + +void bench_dh(int doAsync) { - int i ; - size_t bytes; - word32 idx = 0, pubSz, privSz = 0, pubSz2, privSz2, agreeSz; + int ret, i; + int count = 0, times; const byte* tmp = NULL; - - byte pub[256]; /* for 2048 bit */ - byte pub2[256]; /* for 2048 bit */ - byte agree[256]; /* for 2048 bit */ - byte priv[32]; /* for 2048 bit */ - byte priv2[32]; /* for 2048 bit */ - - double start, total, each, milliEach; - DhKey dhKey; + double start = 0.0f; + DhKey dhKey[BENCH_MAX_PENDING]; int dhKeySz = 2048; /* used in printf */ +#ifndef NO_ASN + size_t bytes; + word32 idx; +#endif + word32 pubSz[BENCH_MAX_PENDING]; + word32 privSz[BENCH_MAX_PENDING]; + word32 pubSz2; + word32 privSz2; + word32 agreeSz[BENCH_MAX_PENDING]; + + DECLARE_ARRAY(pub, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_VAR(pub2, byte, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(agree, byte, BENCH_MAX_PENDING, BENCH_DH_KEY_SIZE, HEAP_HINT); + DECLARE_ARRAY(priv, byte, BENCH_MAX_PENDING, BENCH_DH_PRIV_SIZE, HEAP_HINT); + DECLARE_VAR(priv2, byte, BENCH_DH_PRIV_SIZE, HEAP_HINT); - (void)idx; (void)tmp; - #if defined(NO_ASN) dhKeySz = 1024; /* do nothing, but don't use default FILE */ @@ -1869,86 +2466,112 @@ void bench_dh(void) #error "need to define a cert buffer size" #endif /* USE_CERT_BUFFERS */ + bench_async_begin(); - wc_InitDhKey(&dhKey); -#ifdef NO_ASN - bytes = wc_DhSetKey(&dhKey, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); -#else - bytes = wc_DhKeyDecode(tmp, &idx, &dhKey, (word32)bytes); -#endif - if (bytes != 0) { - printf("dhekydecode failed, can't benchmark\n"); - return; + /* clear for done cleanup */ + XMEMSET(dhKey, 0, sizeof(dhKey)); + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an async context for each key */ + ret = wc_InitDhKey_ex(&dhKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID); + if (ret != 0) + goto exit; + + /* setup key */ + #ifdef NO_ASN + ret = wc_DhSetKey(&dhKey[i], dh_p, sizeof(dh_p), dh_g, sizeof(dh_g)); + #else + idx = 0; + ret = wc_DhKeyDecode(tmp, &idx, &dhKey[i], (word32)bytes); + #endif + if (ret != 0) { + printf("DhKeyDecode failed %d, can't benchmark\n", ret); + goto exit; + } } - start = current_time(1); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - for (i = 0; i < ntimes; i++) - wc_DhGenerateKeyPair(&dhKey, &rng, priv, &privSz, pub, &pubSz); + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, genTimes)) { + privSz[i] = 0; + ret = wc_DhGenerateKeyPair(&dhKey[i], &rng, priv[i], &privSz[i], + pub[i], &pubSz[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×)) { + goto exit_dh_gen; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_dh_gen: + bench_stats_asym_finish("DH", dhKeySz, "key gen", doAsync, count, start); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ + if (ret < 0) { + goto exit; + } - printf("DH %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); + /* Generate key to use as other public */ + ret = wc_DhGenerateKeyPair(&dhKey[0], &rng, priv2, &privSz2, pub2, &pubSz2); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &dhKey[0].asyncDev, WC_ASYNC_FLAG_NONE); - wc_DhGenerateKeyPair(&dhKey, &rng, priv2, &privSz2, pub2, &pubSz2); - start = current_time(1); - - for (i = 0; i < ntimes; i++) - wc_DhAgree(&dhKey, agree, &agreeSz, priv, privSz, pub2, pubSz2); - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("DH %d key agreement %6.3f milliseconds, avg over %d" - " iterations\n", dhKeySz, milliEach, ntimes); - - wc_FreeDhKey(&dhKey); -} + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&dhKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; #endif -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) -void bench_rsaKeyGen(void) -{ - RsaKey genKey; - double start, total, each, milliEach; - int i; + /* Key Agree */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); - /* 1024 bit */ - start = current_time(1); + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×, agreeTimes)) { + ret = wc_DhAgree(&dhKey[i], agree[i], &agreeSz[i], priv[i], privSz[i], + pub2, pubSz2); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&dhKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("DH", dhKeySz, "key agree", doAsync, count, start); - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 1024, 65537, &rng); - wc_FreeRsaKey(&genKey); + if (ret < 0) { + printf("bench_dh failed: %d\n", ret); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("RSA 1024 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); - - /* 2048 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_InitRsaKey(&genKey, HEAP_HINT); - wc_MakeRsaKey(&genKey, 2048, 65537, &rng); - wc_FreeRsaKey(&genKey); + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_FreeDhKey(&dhKey[i]); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("RSA 2048 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + FREE_ARRAY(pub, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(pub2, HEAP_HINT); + FREE_ARRAY(priv, BENCH_MAX_PENDING, HEAP_HINT); + FREE_VAR(priv2, HEAP_HINT); + FREE_ARRAY(agree, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } -#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_DH */ + #ifdef HAVE_NTRU byte GetEntropy(ENTROPY_CMD cmd, byte* out); @@ -1974,7 +2597,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) void bench_ntru(void) { int i; - double start, total, each, milliEach; + double start; byte public_key[1027]; word16 public_key_len = sizeof(public_key); @@ -1999,7 +2622,6 @@ void bench_ntru(void) 'w', 'o', 'l', 'f', 'S', 'S', 'L', ' ', 'N', 'T', 'R', 'U' }; - printf("\n"); for (ntruBits = 128; ntruBits < 257; ntruBits += 64) { switch (ntruBits) { case 128: @@ -2054,8 +2676,8 @@ void bench_ntru(void) printf("NTRU error occurred requesting the buffer size needed\n"); return; } - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_encrypt(drbg, public_key_len, public_key, sizeof(aes_key), aes_key, &ciphertext_len, ciphertext); @@ -2064,21 +2686,14 @@ void bench_ntru(void) return; } } - ret = ntru_crypto_drbg_uninstantiate(drbg); + bench_stats_asym_finish("NTRU", ntruBits, "encryption", 0, i, start); + ret = ntru_crypto_drbg_uninstantiate(drbg); if (ret != DRBG_OK) { printf("NTRU error occurred uninstantiating the DRBG\n"); return; } - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d encryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); - - ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, &plaintext_len, NULL); @@ -2088,8 +2703,8 @@ void bench_ntru(void) } plaintext_len = sizeof(plaintext); - start = current_time(1); + bench_stats_start(&i, &start); for (i = 0; i < ntimes; i++) { ret = ntru_crypto_ntru_decrypt(private_key_len, private_key, ciphertext_len, ciphertext, @@ -2100,20 +2715,14 @@ void bench_ntru(void) return; } } - - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - - printf("NTRU %d decryption took %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, ntimes); + bench_stats_asym_finish("NTRU", ntruBits, "decryption", 0, i, start); } } void bench_ntruKeyGen(void) { - double start, total, each, milliEach; + double start; int i; byte public_key[1027]; @@ -2152,15 +2761,14 @@ void bench_ntruKeyGen(void) /* set key sizes */ ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, NULL, &private_key_len, NULL); - start = current_time(1); - for(i = 0; i < genTimes; i++) { + bench_stats_start(&i, &start); + for (i = 0; i < genTimes; i++) { ret = ntru_crypto_ntru_encrypt_keygen(drbg, type, &public_key_len, public_key, &private_key_len, private_key); } - - total = current_time(0) - start; + bench_stats_asym_finish("NTRU", ntruBits, "key gen", 0, i, start); if (ret != NTRU_OK) { printf("keygen failed\n"); @@ -2173,182 +2781,332 @@ void bench_ntruKeyGen(void) printf("NTRU drbg uninstantiate failed\n"); return; } - - each = total / genTimes; - milliEach = each * 1000; - - printf("NTRU %d key generation %6.3f milliseconds, avg over %d" - " iterations\n", ntruBits, milliEach, genTimes); } } #endif #ifdef HAVE_ECC -void bench_eccKeyGen(void) +#define BENCH_ECC_SIZE 32 + +void bench_eccMakeKey(int doAsync) { - ecc_key genKey; - double start, total, each, milliEach; - int i; + int ret, i, times, count; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; + double start; - /* 256 bit */ - start = current_time(1); + bench_async_begin(); - for(i = 0; i < genTimes; i++) { - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_make_key(&rng, 32, &genKey); - wc_ecc_free(&genKey); + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); + + /* ECC Make Key */ + bench_stats_start(&count, &start); + do { + /* while free pending slots in queue, submit ops */ + for (times = 0; times < genTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×, genTimes)) { + + wc_ecc_free(&genKey[i]); + ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, doAsync ? devId : INVALID_DEVID); + if (ret < 0) { + goto exit; + } + + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 0, ×)) { + goto exit; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("ECC", keySize * 8, "key gen", doAsync, count, start); + + if (ret < 0) { + printf("bench_eccMakeKey failed: %d\n", ret); } - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ECC 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + } + + bench_async_end(); +} + +void bench_ecc(int doAsync) +{ + int ret, i, times, count; + const int keySize = BENCH_ECC_SIZE; + ecc_key genKey[BENCH_MAX_PENDING]; +#ifdef HAVE_ECC_DHE + ecc_key genKey2[BENCH_MAX_PENDING]; +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) +#ifdef HAVE_ECC_VERIFY + int verify[BENCH_MAX_PENDING]; +#endif +#endif + word32 x[BENCH_MAX_PENDING]; + double start; + +#ifdef HAVE_ECC_DHE + DECLARE_ARRAY(shared, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + DECLARE_ARRAY(sig, byte, BENCH_MAX_PENDING, ECC_MAX_SIG_SIZE, HEAP_HINT); +#endif + DECLARE_ARRAY(digest, byte, BENCH_MAX_PENDING, BENCH_ECC_SIZE, HEAP_HINT); + + bench_async_begin(); + + /* clear for done cleanup */ + XMEMSET(&genKey, 0, sizeof(genKey)); +#ifdef HAVE_ECC_DHE + XMEMSET(&genKey2, 0, sizeof(genKey2)); +#endif + + /* init keys */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + /* setup an context for each key */ + if ((ret = wc_ecc_init_ex(&genKey[i], HEAP_HINT, + doAsync ? devId : INVALID_DEVID)) < 0) { + goto exit; + } + ret = wc_ecc_make_key(&rng, keySize, &genKey[i]); + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &genKey[i].asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret < 0) { + goto exit; + } + + #ifdef HAVE_ECC_DHE + if ((ret = wc_ecc_init_ex(&genKey2[i], HEAP_HINT, INVALID_DEVID)) < 0) { + goto exit; + } + if ((ret = wc_ecc_make_key(&rng, keySize, &genKey2[i])) > 0) { + goto exit; + } + #endif + } + +#ifdef HAVE_ECC_DHE +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif + + /* ECC Shared Secret */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + x[i] = keySize; + ret = wc_ecc_shared_secret(&genKey[i], &genKey2[i], shared[i], &x[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdhe; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdhe: + bench_stats_asym_finish("ECDHE", keySize * 8, "agree", doAsync, count, start); + + if (ret < 0) { + goto exit; + } +#endif /* HAVE_ECC_DHE */ + +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif + + /* Init digest to sign */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + for (count = 0; count < keySize; count++) { + digest[i][count] = (byte)count; + } + } + + /* ECC Sign */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + if (genKey[i].state == 0) + x[i] = ECC_MAX_SIG_SIZE; + ret = wc_ecc_sign_hash(digest[i], keySize, sig[i], &x[i], + &rng, &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdsa_sign; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_sign: + bench_stats_asym_finish("ECDSA", keySize * 8, "sign", doAsync, count, start); + + if (ret < 0) { + goto exit; + } + +#ifdef HAVE_ECC_VERIFY +#ifdef WOLFSSL_ASYNC_CRYPT + /* Clear events */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + XMEMSET(&genKey[i].asyncDev.event, 0, sizeof(WOLF_EVENT)); + } + asyncPending = 0; +#endif + + /* ECC Verify */ + bench_stats_start(&count, &start); + do { + for (times = 0; times < agreeTimes || BENCH_ASYNC_IS_PEND(); ) { + bench_async_poll(); + + /* while free pending slots in queue, submit ops */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + if (bench_async_check(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×, agreeTimes)) { + if (genKey[i].state == 0) + verify[i] = 0; + ret = wc_ecc_verify_hash(sig[i], x[i], digest[i], + keySize, &verify[i], &genKey[i]); + if (!bench_async_handle(&ret, BENCH_ASYNC_GET_DEV(&genKey[i]), 1, ×)) { + goto exit_ecdsa_verify; + } + } + } /* for i */ + } /* for times */ + count += times; + } while (bench_stats_sym_check(start)); +exit_ecdsa_verify: + bench_stats_asym_finish("ECDSA", keySize * 8, "verify", doAsync, count, start); +#endif /* HAVE_ECC_VERIFY */ +#endif /* !NO_ASN && HAVE_ECC_SIGN */ + +exit: + + if (ret < 0) { + printf("bench_ecc failed: %d\n", ret); + } + + /* cleanup */ + for (i = 0; i < BENCH_MAX_PENDING; i++) { + wc_ecc_free(&genKey[i]); + #ifdef HAVE_ECC_DHE + wc_ecc_free(&genKey2[i]); + #endif + } + +#ifdef HAVE_ECC_DHE + FREE_ARRAY(shared, BENCH_MAX_PENDING, HEAP_HINT); +#endif +#if !defined(NO_ASN) && defined(HAVE_ECC_SIGN) + FREE_ARRAY(sig, BENCH_MAX_PENDING, HEAP_HINT); +#endif + FREE_ARRAY(digest, BENCH_MAX_PENDING, HEAP_HINT); + + bench_async_end(); } -void bench_eccKeyAgree(void) -{ - ecc_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; - byte shared[32]; -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - byte sig[64+16]; /* der encoding too */ -#endif - byte digest[32]; - word32 x = 0; - - wc_ecc_init_ex(&genKey, HEAP_HINT, devId); - wc_ecc_init_ex(&genKey2, HEAP_HINT, devId); - - ret = wc_ecc_make_key(&rng, 32, &genKey); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } - ret = wc_ecc_make_key(&rng, 32, &genKey2); - if (ret != 0) { - printf("ecc_make_key failed\n"); - return; - } - - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_ecc_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("ecc_shared_secret failed\n"); - return; - } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DHE key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - /* make dummy digest */ - for (i = 0; i < (int)sizeof(digest); i++) - digest[i] = (byte)i; - - -#if !defined(NO_ASN) && !defined(NO_ECC_SIGN) - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &genKey); - if (ret != 0) { - printf("ecc_sign_hash failed\n"); - return; - } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &genKey); - if (ret != 0) { - printf("ecc_verify_hash failed\n"); - return; - } - } -#endif - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("EC-DSA verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); - - wc_ecc_free(&genKey2); - wc_ecc_free(&genKey); -} #ifdef HAVE_ECC_ENCRYPT void bench_eccEncrypt(void) { ecc_key userA, userB; + const int keySize = BENCH_ECC_SIZE; byte msg[48]; byte out[80]; word32 outSz = sizeof(out); - word32 plainSz = sizeof(plain); - int ret, i; - double start, total, each, milliEach; + word32 bench_plainSz = BENCH_SIZE; + int ret, i, count; + double start; - wc_ecc_init_ex(&userA, HEAP_HINT, devId); + ret = wc_ecc_init_ex(&userA, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key A failed: %d\n", ret); + return; + } wc_ecc_init_ex(&userB, HEAP_HINT, devId); + if (ret != 0) { + printf("wc_ecc_encrypt make key B failed: %d\n", ret); + wc_ecc_free(&userA); + return; + } - wc_ecc_make_key(&rng, 32, &userA); - wc_ecc_make_key(&rng, 32, &userB); + ret = wc_ecc_make_key(&rng, keySize, &userA); + if (ret != 0) + goto exit; + ret = wc_ecc_make_key(&rng, keySize, &userB); + if (ret != 0) + goto exit; for (i = 0; i < (int)sizeof(msg); i++) msg[i] = i; - start = current_time(1); - - for(i = 0; i < ntimes; i++) { - /* encrypt msg to B */ - ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); - if (ret != 0) { - printf("wc_ecc_encrypt failed! %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* encrypt msg to B */ + ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL); + if (ret != 0) { + printf("wc_ecc_encrypt failed! %d\n", ret); + goto exit_enc; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_enc: + bench_stats_asym_finish("ECC", keySize * 8, "encrypt", 0, count, start); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC encrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); - - start = current_time(1); - - for(i = 0; i < ntimes; i++) { - /* decrypt msg from A */ - ret = wc_ecc_decrypt(&userB, &userA, out, outSz, plain, &plainSz, NULL); - if (ret != 0) { - printf("wc_ecc_decrypt failed! %d\n", ret); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < ntimes; i++) { + /* decrypt msg from A */ + ret = wc_ecc_decrypt(&userB, &userA, out, outSz, bench_plain, &bench_plainSz, NULL); + if (ret != 0) { + printf("wc_ecc_decrypt failed! %d\n", ret); + goto exit_dec; + } } - } + count += i; + } while (bench_stats_sym_check(start)); +exit_dec: + bench_stats_asym_finish("ECC", keySize * 8, "decrypt", 0, count, start); - total = current_time(0) - start; - each = total / ntimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ECC decrypt %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, ntimes); +exit: + + if (ret != 0) { + printf("bench_eccEncrypt failed! %d\n", ret); + } /* cleanup */ wc_ecc_free(&userB); @@ -2361,31 +3119,31 @@ void bench_eccEncrypt(void) void bench_curve25519KeyGen(void) { curve25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int ret, i, count; - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_curve25519_make_key(&rng, 32, &genKey); - wc_curve25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("CURVE25519 256 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + ret = wc_curve25519_make_key(&rng, 32, &genKey); + wc_curve25519_free(&genKey); + if (ret != 0) { + printf("wc_curve25519_make_key failed: %d\n", ret); + break; + } + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("CURVE", 25519, "key gen", 0, count, start); } #ifdef HAVE_CURVE25519_SHARED_SECRET void bench_curve25519KeyAgree(void) { curve25519_key genKey, genKey2; - double start, total, each, milliEach; - int i, ret; + double start; + int ret, i, count; byte shared[32]; word32 x = 0; @@ -2399,27 +3157,26 @@ void bench_curve25519KeyAgree(void) } ret = wc_curve25519_make_key(&rng, 32, &genKey2); if (ret != 0) { - printf("curve25519_make_key failed\n"); + printf("curve25519_make_key failed: %d\n", ret); + wc_curve25519_free(&genKey); return; } - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(shared); - ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); - if (ret != 0) { - printf("curve25519_shared_secret failed\n"); - return; + /* Shared secret */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(shared); + ret = wc_curve25519_shared_secret(&genKey, &genKey2, shared, &x); + if (ret != 0) { + printf("curve25519_shared_secret failed: %d\n", ret); + goto exit; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("CURVE25519 key agreement %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit: + bench_stats_asym_finish("CURVE", 25519, "key agree", 0, count, start); wc_curve25519_free(&genKey2); wc_curve25519_free(&genKey); @@ -2431,24 +3188,20 @@ void bench_curve25519KeyAgree(void) void bench_ed25519KeyGen(void) { ed25519_key genKey; - double start, total, each, milliEach; - int i; + double start; + int i, count; - /* 256 bit */ - start = current_time(1); - - for(i = 0; i < genTimes; i++) { - wc_ed25519_init(&genKey); - wc_ed25519_make_key(&rng, 32, &genKey); - wc_ed25519_free(&genKey); - } - - total = current_time(0) - start; - each = total / genTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("\n"); - printf("ED25519 key generation %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, genTimes); + /* Key Gen */ + bench_stats_start(&count, &start); + do { + for (i = 0; i < genTimes; i++) { + wc_ed25519_init(&genKey); + wc_ed25519_make_key(&rng, 32, &genKey); + wc_ed25519_free(&genKey); + } + count += i; + } while (bench_stats_sym_check(start)); + bench_stats_asym_finish("ED", 25519, "key gen", 0, count, start); } @@ -2457,8 +3210,8 @@ void bench_ed25519KeySign(void) int ret; ed25519_key genKey; #ifdef HAVE_ED25519_SIGN - double start, total, each, milliEach; - int i; + double start; + int i, count; byte sig[ED25519_SIG_SIZE]; byte msg[512]; word32 x = 0; @@ -2477,41 +3230,37 @@ void bench_ed25519KeySign(void) for (i = 0; i < (int)sizeof(msg); i++) msg[i] = (byte)i; - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - x = sizeof(sig); - ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); - if (ret != 0) { - printf("ed25519_sign_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + x = sizeof(sig); + ret = wc_ed25519_sign_msg(msg, sizeof(msg), sig, &x, &genKey); + if (ret != 0) { + printf("ed25519_sign_msg failed\n"); + goto exit_ed_sign; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 sign time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_sign: + bench_stats_asym_finish("ED", 25519, "sign", 0, count, start); #ifdef HAVE_ED25519_VERIFY - start = current_time(1); - - for(i = 0; i < agreeTimes; i++) { - int verify = 0; - ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, - &genKey); - if (ret != 0 || verify != 1) { - printf("ed25519_verify_msg failed\n"); - return; + bench_stats_start(&count, &start); + do { + for (i = 0; i < agreeTimes; i++) { + int verify = 0; + ret = wc_ed25519_verify_msg(sig, x, msg, sizeof(msg), &verify, + &genKey); + if (ret != 0 || verify != 1) { + printf("ed25519_verify_msg failed\n"); + goto exit_ed_verify; + } } - } - - total = current_time(0) - start; - each = total / agreeTimes; /* per second */ - milliEach = each * 1000; /* milliseconds */ - printf("ED25519 verify time %6.3f milliseconds, avg over %d" - " iterations\n", milliEach, agreeTimes); + count += i; + } while (bench_stats_sym_check(start)); +exit_ed_verify: + bench_stats_asym_finish("ED", 25519, "verify", 0, count, start); #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN */ @@ -2519,8 +3268,8 @@ void bench_ed25519KeySign(void) } #endif /* HAVE_ED25519 */ - -#ifdef _WIN32 +#ifndef HAVE_STACK_SIZE +#if defined(_WIN32) && !defined(INTIME_RTOS) #define WIN32_LEAN_AND_MEAN #include @@ -2567,8 +3316,9 @@ void bench_ed25519KeySign(void) return ( ns / CLOCK * 2.0); } -#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || defined(WOLFSSL_USER_CURRTIME) - /* declared above at line 189 */ +#elif defined(WOLFSSL_IAR_ARM_TIME) || defined (WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_USER_CURRTIME) || defined(WOLFSSL_CURRTIME_REMAP) + /* declared above at line 239 */ /* extern double current_time(int reset); */ #elif defined FREERTOS @@ -2598,6 +3348,13 @@ void bench_ed25519KeySign(void) return (double)tv.SECONDS + (double)tv.MILLISECONDS / 1000; } +#elif defined(FREESCALE_KSDK_BM) + + double current_time(int reset) + { + return (double)OSA_TimeGetMsec() / 1000; + } + #elif defined(WOLFSSL_EMBOS) #include "RTOS.h" @@ -2630,6 +3387,7 @@ void bench_ed25519KeySign(void) } #endif /* _WIN32 */ +#endif /* !HAVE_STACK_SIZE */ #if defined(HAVE_GET_CYCLES) @@ -2646,6 +3404,26 @@ static INLINE word64 get_intel_cycles(void) } #endif /* HAVE_GET_CYCLES */ + +#ifndef NO_MAIN_DRIVER + +int main(int argc, char** argv) +{ + int ret = 0; + +#ifdef HAVE_STACK_SIZE + ret = StackSizeCheck(NULL, benchmark_test); +#else + ret = benchmark_test(NULL); +#endif + + (void)argc; + (void)argv; + + return ret; +} +#endif /* !NO_MAIN_DRIVER */ + #else #ifndef NO_MAIN_DRIVER int main() { return 0; } diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 20feeb45d..4c67bd12d 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -28,7 +28,11 @@ extern "C" { #endif -int benchmark_test(void* args); +#ifdef HAVE_STACK_SIZE +THREAD_RETURN WOLFSSL_THREAD benchmark_test(void* args); +#else +int benchmark_test(void *args); +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c old mode 100644 new mode 100755 index c1f1f74e8..12ded2384 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -30,176 +30,175 @@ #include +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS -int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, - int dir) -{ - return AesSetKey_fips(aes, key, len, iv, dir); -} + int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) + { + return AesSetKey_fips(aes, key, len, iv, dir); + } + int wc_AesSetIV(Aes* aes, const byte* iv) + { + return AesSetIV_fips(aes, iv); + } + #ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return AesCbcEncrypt_fips(aes, out, in, sz); + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return AesCbcDecrypt_fips(aes, out, in, sz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + /* AES-CTR */ + #ifdef WOLFSSL_AES_COUNTER + void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + AesCtrEncrypt(aes, out, in, sz); + } + #endif -int wc_AesSetIV(Aes* aes, const byte* iv) -{ - return AesSetIV_fips(aes, iv); -} + /* AES-DIRECT */ + #if defined(WOLFSSL_AES_DIRECT) + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + AesEncryptDirect(aes, out, in); + } + #ifdef HAVE_AES_DECRYPT + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + AesDecryptDirect(aes, out, in); + } + #endif /* HAVE_AES_DECRYPT */ -#ifdef HAVE_AES_CBC -int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcEncrypt_fips(aes, out, in, sz); -} + int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) + { + return AesSetKeyDirect(aes, key, len, iv, dir); + } + #endif /* WOLFSSL_AES_DIRECT */ -#ifdef HAVE_AES_DECRYPT -int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - return AesCbcDecrypt_fips(aes, out, in, sz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ + /* AES-GCM */ + #ifdef HAVE_AESGCM + int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) + { + return AesGcmSetKey_fips(aes, key, len); + } + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } -/* AES-CTR */ -#ifdef WOLFSSL_AES_COUNTER -void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) -{ - AesCtrEncrypt(aes, out, in, sz); -} -#endif + #ifdef HAVE_AES_DECRYPT + int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ -/* AES-DIRECT */ -#if defined(WOLFSSL_AES_DIRECT) -void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesEncryptDirect(aes, out, in); -} + int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) + { + return GmacSetKey(gmac, key, len); + } + int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) + { + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); + } + #endif /* HAVE_AESGCM */ -#ifdef HAVE_AES_DECRYPT -void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) -{ - AesDecryptDirect(aes, out, in); -} -#endif /* HAVE_AES_DECRYPT */ + /* AES-CCM */ + #ifdef HAVE_AESCCM + void wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) + { + AesCcmSetKey(aes, key, keySz); + } + int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; -int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, - const byte* iv, int dir) -{ - return AesSetKeyDirect(aes, key, len, iv, dir); -} -#endif + AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, + authTagSz, authIn, authInSz); + return 0; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, + authTag, authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESCCM */ -#ifdef HAVE_AESGCM -int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) -{ - return AesGcmSetKey_fips(aes, key, len); -} + int wc_AesInit(Aes* aes, void* h, int i) + { + (void)aes; + (void)h; + (void)i; + /* FIPS doesn't support: + return AesInit(aes, h, i); */ + return 0; + } + void wc_AesFree(Aes* aes) + { + (void)aes; + /* FIPS doesn't support: + AesFree(aes); */ + } - -int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} - -#ifdef HAVE_AES_DECRYPT -int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, - const byte* iv, word32 ivSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ - -int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) -{ - return GmacSetKey(gmac, key, len); -} - - -int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, - const byte* authIn, word32 authInSz, - byte* authTag, word32 authTagSz) -{ - return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, - authTag, authTagSz); -} - -#endif /* HAVE_AESGCM */ -#ifdef HAVE_AESCCM -int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) -{ - AesCcmSetKey(aes, key, keySz); - return 0; -} - - -int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - /* sanity check on arguments */ - if (aes == NULL || out == NULL || in == NULL || nonce == NULL - || authTag == NULL || nonceSz < 7 || nonceSz > 13) - return BAD_FUNC_ARG; - - AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); - return 0; -} - -#ifdef HAVE_AES_DECRYPT -int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, - const byte* nonce, word32 nonceSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz) -{ - return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, authTag, authTagSz, - authIn, authInSz); -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AESCCM */ - -#ifdef WOLFSSL_ASYNC_CRYPT -int wc_AesAsyncInit(Aes* aes, int i) -{ - return AesAsyncInit(aes, i); -} - -void wc_AesAsyncFree(Aes* aes) -{ - AesAsyncFree(aes); -} -#endif #else /* HAVE_FIPS */ -#ifdef WOLFSSL_TI_CRYPT -#include + +#if defined(WOLFSSL_TI_CRYPT) + #include #else #include #include + #ifdef NO_INLINE #include #else #define WOLFSSL_MISC_INCLUDED #include #endif + #ifdef DEBUG_AESNI #include #endif - #ifdef _MSC_VER /* 4127 warning constant while(1) */ #pragma warning(disable: 4127) #endif + /* Define AES implementation includes and functions */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) /* STM32F2/F4 hardware AES support for CBC, CTR modes */ @@ -210,6 +209,7 @@ void wc_AesAsyncFree(Aes* aes) int ret = 0; #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { @@ -225,8 +225,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -324,13 +322,13 @@ void wc_AesAsyncFree(Aes* aes) #endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */ #ifdef HAVE_AES_DECRYPT - #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) + #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { int ret = 0; #ifdef WOLFSSL_STM32_CUBEMX CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -345,8 +343,6 @@ void wc_AesAsyncFree(Aes* aes) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -364,7 +360,7 @@ void wc_AesAsyncFree(Aes* aes) #endif /* WOLFSSL_STM32_CUBEMX */ return ret; } - #endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */ #endif /* HAVE_AES_DECRYPT */ #elif defined(HAVE_COLDFIRE_SEC) @@ -382,12 +378,12 @@ void wc_AesAsyncFree(Aes* aes) #else /* if LTC doesn't have GCM, use software with LTC AES ECB mode */ static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesEncryptDirect(aes, outBlock, inBlock); return 0; } static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) - { + { wc_AesDecryptDirect(aes, outBlock, inBlock); return 0; } @@ -419,13 +415,12 @@ void wc_AesAsyncFree(Aes* aes) return ret; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) /* NOTE: no support for AES-CCM/Direct */ #define DEBUG_WOLFSSL #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" -#elif defined(HAVE_CAVIUM) - /* still leave SW crypto available */ - #define NEED_AES_TABLES + #elif defined(WOLFSSL_NRF51_AES) /* Use built-in AES hardware - AES 128 ECB Encrypt Only */ #include "wolfssl/wolfcrypt/port/nrf51.h" @@ -434,9 +429,176 @@ void wc_AesAsyncFree(Aes* aes) { return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); } + #ifdef HAVE_AES_DECRYPT #error nRF51 AES Hardware does not support decrypt #endif /* HAVE_AES_DECRYPT */ + + +#elif defined(WOLFSSL_AESNI) + + #define NEED_AES_TABLES + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef AESNI_ALIGN + #define AESNI_ALIGN 16 + #endif + + #ifndef _MSC_VER + #define cpuid(reg, func)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (func)); + + #define XASM_LINK(f) asm(f) + #else + + #include + #define cpuid(a,b) __cpuid((int*)a,b) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + + static int Check_CPU_support_AES(void) + { + unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ + cpuid(reg, 1); /* query info 1 */ + + if (reg[2] & 0x2000000) + return 1; + + return 0; + } + + static int checkAESNI = 0; + static int haveAESNI = 0; + + + /* tell C compiler these are asm functions in case any mix up of ABI underscore + prefix between clang/gcc/llvm etc */ + #ifdef HAVE_AES_CBC + void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_encrypt"); + + #ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AESNI_BY4) + void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by4"); + #elif defined(WOLFSSL_AESNI_BY6) + void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by6"); + #else /* WOLFSSL_AESNI_BYx */ + void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by8"); + #endif /* WOLFSSL_AESNI_BYx */ + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_encrypt"); + + #ifdef HAVE_AES_DECRYPT + void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_decrypt"); + #endif + + void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_128_Key_Expansion"); + + void AES_192_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_192_Key_Expansion"); + + void AES_256_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_256_Key_Expansion"); + + + static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + Aes* aes) + { + int ret; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + switch (bits) { + case 128: + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + case 192: + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + case 256: + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + default: + ret = BAD_FUNC_ARG; + } + + return ret; + } + + #ifdef HAVE_AES_DECRYPT + static int AES_set_decrypt_key(const unsigned char* userKey, + const int bits, Aes* aes) + { + int nr; + Aes temp_key; + __m128i *Key_Schedule = (__m128i*)aes->key; + __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) + return BAD_FUNC_ARG; + + nr = temp_key.rounds; + aes->rounds = nr; + + Key_Schedule[nr] = Temp_Key_Schedule[0]; + Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); + Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); + Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); + Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); + Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); + Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); + Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); + Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); + Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); + + if (nr>10) { + Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); + Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); + } + + if (nr>12) { + Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); + Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); + } + + Key_Schedule[0] = Temp_Key_Schedule[nr]; + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ + #else /* using wolfCrypt software AES implementation */ @@ -444,6 +606,7 @@ void wc_AesAsyncFree(Aes* aes) #endif + #ifdef NEED_AES_TABLES static const word32 rcon[] = { @@ -720,6 +883,7 @@ static const word32 Te[4][256] = { } }; +#ifdef HAVE_AES_DECRYPT static const word32 Td[4][256] = { { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, @@ -1024,170 +1188,13 @@ static const byte Td4[256] = 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; +#endif /* HAVE_AES_DECRYPT */ #define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) -#ifdef WOLFSSL_AESNI - -/* Each platform needs to query info type 1 from cpuid to see if aesni is - * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts - */ - -#ifndef _MSC_VER - - #define cpuid(reg, func)\ - __asm__ __volatile__ ("cpuid":\ - "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ - "a" (func)); - - #define XASM_LINK(f) asm(f) -#else - - #include - #define cpuid(a,b) __cpuid((int*)a,b) - - #define XASM_LINK(f) - -#endif /* _MSC_VER */ - - -static int Check_CPU_support_AES(void) -{ - unsigned int reg[4]; /* put a,b,c,d into 0,1,2,3 */ - cpuid(reg, 1); /* query info 1 */ - - if (reg[2] & 0x2000000) - return 1; - - return 0; -} - -static int checkAESNI = 0; -static int haveAESNI = 0; - - -/* tell C compiler these are asm functions in case any mix up of ABI underscore - prefix between clang/gcc/llvm etc */ -#ifdef HAVE_AES_CBC -void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_encrypt"); - -#ifdef HAVE_AES_DECRYPT - #if defined(WOLFSSL_AESNI_BY4) - void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by4"); - #elif defined(WOLFSSL_AESNI_BY6) - void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by6"); - #else /* WOLFSSL_AESNI_BYx */ - void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, - unsigned char* ivec, unsigned long length, - const unsigned char* KS, int nr) - XASM_LINK("AES_CBC_decrypt_by8"); - #endif /* WOLFSSL_AESNI_BYx */ -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ - -void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_encrypt"); - -#ifdef HAVE_AES_DECRYPT -void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, - unsigned long length, const unsigned char* KS, int nr) - XASM_LINK("AES_ECB_decrypt"); -#endif - -void AES_128_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_128_Key_Expansion"); - -void AES_192_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_192_Key_Expansion"); - -void AES_256_Key_Expansion(const unsigned char* userkey, - unsigned char* key_schedule) - XASM_LINK("AES_256_Key_Expansion"); - - -static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, - Aes* aes) -{ - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (bits == 128) { - AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; - return 0; - } - else if (bits == 192) { - AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; - return 0; - } - else if (bits == 256) { - AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; - return 0; - } - return BAD_FUNC_ARG; -} - -#ifdef HAVE_AES_DECRYPT -static int AES_set_decrypt_key(const unsigned char* userKey, const int bits, - Aes* aes) -{ - int nr; - Aes temp_key; - __m128i *Key_Schedule = (__m128i*)aes->key; - __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; - - if (!userKey || !aes) - return BAD_FUNC_ARG; - - if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) - return BAD_FUNC_ARG; - - nr = temp_key.rounds; - aes->rounds = nr; - - Key_Schedule[nr] = Temp_Key_Schedule[0]; - Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); - Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); - Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); - Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); - Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); - Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); - Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); - Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); - Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); - - if(nr>10) { - Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); - Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); - } - - if(nr>12) { - Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); - Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); - } - - Key_Schedule[0] = Temp_Key_Schedule[nr]; - - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* WOLFSSL_AESNI */ - -#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) ||\ - defined(HAVE_AESGCM) +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) #ifndef WC_CACHE_LINE_SZ #if defined(__x86_64__) || defined(_M_X64) || \ @@ -1221,12 +1228,13 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) word32 s0, s1, s2, s3; word32 t0, t1, t2, t3; word32 r = aes->rounds >> 1; - const word32* rk = aes->key; + if (r > 7 || r == 0) { WOLFSSL_MSG("AesEncrypt encountered improper key, set it up"); return; /* stop instead of segfaulting, set up your keys! */ } + #ifdef WOLFSSL_AESNI if (haveAESNI && aes->use_aesni) { #ifdef DEBUG_AESNI @@ -1239,16 +1247,19 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)inBlock % 16) { + if ((wolfssl_word)inBlock % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return; - XMEMCPY(tmp, inBlock, AES_BLOCK_SIZE); - AES_ECB_encrypt(tmp, tmp, AES_BLOCK_SIZE, (byte*)aes->key, + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + + XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE); + AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE, (byte*)aes->key, aes->rounds); - XMEMCPY(outBlock, tmp, AES_BLOCK_SIZE); + XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return; #else @@ -1278,12 +1289,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1384,12 +1395,12 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); @@ -1399,6 +1410,7 @@ static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) } #endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + #ifdef HAVE_AES_DECRYPT #if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) @@ -1417,7 +1429,6 @@ static INLINE word32 PreFetchTd(void) return x; } - /* load Td Table4 into cache by cache line stride */ static INLINE word32 PreFetchTd4(void) { @@ -1430,7 +1441,6 @@ static INLINE word32 PreFetchTd4(void) return x; } - static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) { word32 s0, s1, s2, s3; @@ -1464,7 +1474,7 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) printf("Skipping AES-NI\n"); #endif } -#endif +#endif /* WOLFSSL_AESNI */ /* * map byte array block to cipher state @@ -1475,12 +1485,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif s0 ^= rk[0]; s1 ^= rk[1]; @@ -1582,12 +1592,12 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) rk[3]; /* write out */ - #ifdef LITTLE_ENDIAN_ORDER - s0 = ByteReverseWord32(s0); - s1 = ByteReverseWord32(s1); - s2 = ByteReverseWord32(s2); - s3 = ByteReverseWord32(s3); - #endif +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif XMEMCPY(outBlock, &s0, sizeof(s0)); XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); @@ -1599,10 +1609,11 @@ static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) #endif /* NEED_AES_TABLES */ + /* wc_AesSetKey */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) -int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { word32 *rk = aes->key; @@ -1612,6 +1623,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); #ifndef WOLFSSL_STM32_CUBEMX @@ -1648,28 +1660,28 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, extern volatile unsigned char __MBAR[]; - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { if (AESBuffIn == NULL) { - #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, - AES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, - AES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, - AES_BLOCK_SIZE*2, TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, - AES_BLOCK_SIZE, TX_NO_WAIT); + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, + AES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, + AES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, + AES_BLOCK_SIZE*2, TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, + AES_BLOCK_SIZE, TX_NO_WAIT); - if(s1 || s2 || s3 || s4 || s5) - return BAD_FUNC_ARG; - #else - #warning "Allocate non-Cache buffers" - #endif + if (s1 || s2 || s3 || s4 || s5) + return BAD_FUNC_ARG; + #else + #warning "Allocate non-Cache buffers" + #endif wc_InitMutex(&Mutex_AesSEC); } @@ -1680,6 +1692,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (aes == NULL) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); @@ -1697,7 +1710,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, aes->rounds = keylen/4 + 6; XMEMCPY(aes->key, userKey, keylen); - + #ifdef WOLFSSL_AES_COUNTER aes->left = 0; #endif /* WOLFSSL_AES_COUNTER */ @@ -1711,8 +1724,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return wc_AesSetKey(aes, userKey, keylen, iv, dir); } #elif defined(FREESCALE_MMCAU) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; byte *rk = (byte*)aes->key; @@ -1728,7 +1741,8 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, #ifdef WOLFSSL_AES_COUNTER aes->left = 0; #endif /* WOLFSSL_AES_COUNTER */ - + + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = wolfSSL_CryptHwMutexLock(); @@ -1747,9 +1761,10 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #elif defined(WOLFSSL_NRF51_AES) - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { int ret; @@ -1759,6 +1774,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, if (keylen != 16) return BAD_FUNC_ARG; + aes->keylen = keylen; aes->rounds = keylen/4 + 6; ret = nrf51_aes_set_key(userKey); @@ -1770,6 +1786,7 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, { return wc_AesSetKey(aes, userKey, keylen, iv, dir); } + #else static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) @@ -1777,25 +1794,25 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, word32 temp, *rk = aes->key; unsigned int i = 0; - #ifdef WOLFSSL_AESNI - aes->use_aesni = 0; - #endif /* WOLFSSL_AESNI */ - #ifdef WOLFSSL_AES_COUNTER - aes->left = 0; - #endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AESNI + aes->use_aesni = 0; + #endif /* WOLFSSL_AESNI */ + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + aes->keylen = keylen; aes->rounds = keylen/4 + 6; XMEMCPY(rk, userKey, keylen); - #ifdef LITTLE_ENDIAN_ORDER - ByteReverseWords(rk, rk, keylen); - #endif + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(rk, rk, keylen); + #endif #ifdef WOLFSSL_PIC32MZ_CRYPT { word32 *akey1 = aes->key_ce; - word32 *areg = aes->iv_ce ; - aes->keylen = keylen ; + word32 *areg = aes->iv_ce; XMEMCPY(akey1, userKey, keylen); if (iv) XMEMCPY(areg, iv, AES_BLOCK_SIZE); @@ -1925,20 +1942,24 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff]; } } +#else + (void)dir; #endif /* HAVE_AES_DECRYPT */ return wc_AesSetIV(aes, iv); } - int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, - int dir) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) { #if defined(AES_MAX_KEY_SIZE) const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); #endif - if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { return BAD_FUNC_ARG; + } #if defined(AES_MAX_KEY_SIZE) /* Check key length */ @@ -1946,12 +1967,15 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, return BAD_FUNC_ARG; } #endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { - return NitroxAesSetKey(aes, userKey, keylen, iv); + aes->asyncKey = userKey; + aes->asyncIv = iv; } - #endif + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (checkAESNI == 0) { @@ -1959,6 +1983,9 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, checkAESNI = 1; } if (haveAESNI) { + #ifdef WOLFSSL_AES_COUNTER + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ aes->use_aesni = 1; if (iv) XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); @@ -1975,14 +2002,12 @@ int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, } #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) - - /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ - int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, - const byte* iv, int dir) - { - return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); - } - + /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + } #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ #endif /* wc_AesSetKey block */ @@ -2001,21 +2026,6 @@ int wc_AesSetIV(Aes* aes, const byte* iv) return 0; } - -/* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - aes->heap = h; - - return 0; -} - - - - /* AES-DIRECT */ #if defined(WOLFSSL_AES_DIRECT) #if defined(HAVE_COLDFIRE_SEC) @@ -2077,7 +2087,7 @@ int wc_InitAes_h(Aes* aes, void* h) { int ret = 0; CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2092,8 +2102,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2125,7 +2133,7 @@ int wc_InitAes_h(Aes* aes, void* h) { int ret = 0; CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2140,8 +2148,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = (uint8_t*)aes->key; @@ -2400,7 +2406,7 @@ int wc_InitAes_h(Aes* aes, void* h) #elif defined(HAVE_COLDFIRE_SEC) static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz, - word32 descHeader) + word32 descHeader) { #ifdef DEBUG_WOLFSSL int i; int stat1, stat2; int ret; @@ -2422,9 +2428,9 @@ int wc_InitAes_h(Aes* aes, void* h) secDesc->pointer2 = (byte *)secReg; /* Initial Vector */ switch(aes->rounds) { - case 10: secDesc->length3 = 16 ; break ; - case 12: secDesc->length3 = 24 ; break ; - case 14: secDesc->length3 = 32 ; break ; + case 10: secDesc->length3 = 16; break; + case 12: secDesc->length3 = 24; break; + case 14: secDesc->length3 = 32; break; } XMEMCPY(secKey, aes->key, secDesc->length3); @@ -2503,8 +2509,8 @@ int wc_InitAes_h(Aes* aes, void* h) return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT)); } #endif /* HAVE_AES_DECRYPT */ - -#elif defined(FREESCALE_LTC) + +#elif defined(FREESCALE_LTC) int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { uint32_t keySize; @@ -2609,21 +2615,22 @@ int wc_InitAes_h(Aes* aes, void* h) return 0; } #endif /* HAVE_AES_DECRYPT */ + #elif defined(WOLFSSL_PIC32MZ_CRYPT) /* core hardware crypt engine driver */ static void wc_AesCrypt(Aes *aes, byte* out, const byte* in, word32 sz, int dir, int algo, int cryptoalgo) { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; + securityAssociation *sa_p; + bufferDescriptor *bd_p; volatile securityAssociation sa __attribute__((aligned (8))); volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; + volatile int k; /* get uncached address */ - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; + sa_p = KVA0_TO_KVA1(&sa); + bd_p = KVA0_TO_KVA1(&bd); /* Sync cache and physical memory */ if(PIC32MZ_IF_RAM(in)) { @@ -2632,27 +2639,27 @@ int wc_InitAes_h(Aes* aes, void* h) XMEMSET((void *)KVA0_TO_KVA1(out), 0, sz); /* Set up the Security Association */ XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; /* AES */ + sa_p->SA_CTRL.ALGO = algo; /* AES */ sa_p->SA_CTRL.LNC = 1; sa_p->SA_CTRL.LOADIV = 1; sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.ENCTYPE = dir; /* Encryption/Decryption */ sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM){ switch(aes->keylen) { case 32: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_256; + break; case 24: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_192; + break; case 16: - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; - break ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128; + break; } } else - sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128 ; + sa_p->SA_CTRL.KEYSIZE = PIC32_AES_KEYSIZE_128; ByteReverseWords( (word32 *)KVA0_TO_KVA1(sa.SA_ENCKEY + 8 - aes->keylen/sizeof(word32)), @@ -2665,27 +2672,27 @@ int wc_InitAes_h(Aes* aes, void* h) bd_p->BD_CTRL.BUFLEN = sz; if(cryptoalgo == PIC32_CRYPTOALGO_AES_GCM) { if(sz % 0x10) - bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10 ; + bd_p->BD_CTRL.BUFLEN = (sz/0x10 + 1) * 0x10; } bd_p->BD_CTRL.LIFM = 1; bd_p->BD_CTRL.SA_FETCH_EN = 1; bd_p->BD_CTRL.LAST_BD = 1; bd_p->BD_CTRL.DESC_EN = 1; - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa); + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in); bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); - bd_p->MSGLEN = sz ; + bd_p->MSGLEN = sz; CECON = 1 << 6; while (CECON); /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd); CEINTEN = 0x07; CECON = 0x27; - WAIT_ENGINE ; + WAIT_ENGINE; if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| @@ -2694,14 +2701,14 @@ int wc_InitAes_h(Aes* aes, void* h) if(dir == PIC32_ENCRYPTION) { XMEMCPY((void *)aes->iv_ce, (void*)KVA0_TO_KVA1(out + sz - AES_BLOCK_SIZE), - AES_BLOCK_SIZE) ; + AES_BLOCK_SIZE); } else { ByteReverseWords((word32*)aes->iv_ce, (word32 *)KVA0_TO_KVA1(in + sz - AES_BLOCK_SIZE), AES_BLOCK_SIZE); } } - XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz) ; + XMEMCPY((byte *)out, (byte *)KVA0_TO_KVA1(out), sz); ByteReverseWords((word32*)out, (word32 *)out, sz); } @@ -2709,14 +2716,14 @@ int wc_InitAes_h(Aes* aes, void* h) { wc_AesCrypt(aes, out, in, sz, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC ); - return 0 ; + return 0; } #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { wc_AesCrypt(aes, out, in, sz, PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); - return 0 ; + return 0; } #endif /* HAVE_AES_DECRYPT */ @@ -2725,10 +2732,28 @@ int wc_InitAes_h(Aes* aes, void* h) { word32 blocks = sz / AES_BLOCK_SIZE; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcEncrypt(aes, out, in, sz); - #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_CBC_ENCRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { @@ -2743,22 +2768,25 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* check alignment, decrypt doesn't need alignment */ - if ((wolfssl_word)in % 16) { + if ((wolfssl_word)in % AESNI_ALIGN) { #ifndef NO_WOLFSSL_ALLOC_ALIGN - byte* tmp = (byte*)XMALLOC(sz, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); + byte* tmp = (byte*)XMALLOC(sz + AESNI_ALIGN, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; if (tmp == NULL) return MEMORY_E; - XMEMCPY(tmp, in, sz); - AES_CBC_encrypt(tmp, tmp, (byte*)aes->reg, sz, (byte*)aes->key, + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + XMEMCPY(tmp_align, in, sz); + AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz, (byte*)aes->key, aes->rounds); /* store iv for next call */ - XMEMCPY(aes->reg, tmp + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - XMEMCPY(out, tmp, sz); + XMEMCPY(out, tmp_align, sz); XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); return 0; #else + WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); return BAD_ALIGN_E; #endif } @@ -2787,11 +2815,28 @@ int wc_InitAes_h(Aes* aes, void* h) #ifdef HAVE_AES_DECRYPT int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - word32 blocks = sz / AES_BLOCK_SIZE; + word32 blocks; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) return NitroxAesCbcDecrypt(aes, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_CBC_DECRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif } #endif @@ -2825,6 +2870,7 @@ int wc_InitAes_h(Aes* aes, void* h) } #endif + blocks = sz / AES_BLOCK_SIZE; while (blocks--) { XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); wc_AesDecrypt(aes, (byte*)aes->tmp, out); @@ -2842,6 +2888,33 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* AES-CBC block */ #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (sz>0) { + wc_AesEncryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + } + return 0; +} +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (sz>0) { + wc_AesDecryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + } + return 0; +} +#endif + /* AES-CTR */ #ifdef WOLFSSL_AES_COUNTER @@ -2850,7 +2923,7 @@ int wc_InitAes_h(Aes* aes, void* h) void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { CRYP_HandleTypeDef hcryp; - + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); /* load key into correct registers */ switch(aes->rounds) { case 10: /* 128-bit key */ @@ -2865,8 +2938,6 @@ int wc_InitAes_h(Aes* aes, void* h) default: break; } - - XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); hcryp.Instance = CRYP; hcryp.Init.DataType = CRYP_DATATYPE_8B; hcryp.Init.pKey = aes->key; @@ -2987,58 +3058,58 @@ int wc_InitAes_h(Aes* aes, void* h) #elif defined(WOLFSSL_PIC32MZ_CRYPT) void wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) { - int i ; - char out_block[AES_BLOCK_SIZE] ; - int odd ; - int even ; - char *tmp ; /* (char *)aes->tmp, for short */ + int i; + char out_block[AES_BLOCK_SIZE]; + int odd; + int even; + char *tmp; /* (char *)aes->tmp, for short */ - tmp = (char *)aes->tmp ; + tmp = (char *)aes->tmp; if(aes->left) { if((aes->left + sz) >= AES_BLOCK_SIZE){ - odd = AES_BLOCK_SIZE - aes->left ; + odd = AES_BLOCK_SIZE - aes->left; } else { - odd = sz ; + odd = sz; } - XMEMCPY(tmp+aes->left, in, odd) ; + XMEMCPY(tmp+aes->left, in, odd); if((odd+aes->left) == AES_BLOCK_SIZE){ wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left, odd) ; - aes->left = 0 ; - XMEMSET(tmp, 0x0, AES_BLOCK_SIZE) ; + XMEMCPY(out, out_block+aes->left, odd); + aes->left = 0; + XMEMSET(tmp, 0x0, AES_BLOCK_SIZE); /* Increment IV */ for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++((byte *)aes->iv_ce)[i]) - break ; + break; } } - in += odd ; - out+= odd ; - sz -= odd ; + in += odd; + out+= odd; + sz -= odd; } - odd = sz % AES_BLOCK_SIZE ; /* if there is tail fragment */ + odd = sz % AES_BLOCK_SIZE; /* if there is tail fragment */ if(sz / AES_BLOCK_SIZE) { - even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE ; + even = (sz/AES_BLOCK_SIZE)*AES_BLOCK_SIZE; wc_AesCrypt(aes, out, in, even, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - out += even ; - in += even ; + out += even; + in += even; do { /* Increment IV */ for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { if (++((byte *)aes->iv_ce)[i]) - break ; + break; } - even -= AES_BLOCK_SIZE ; - } while((int)even > 0) ; + even -= AES_BLOCK_SIZE; + } while((int)even > 0); } if(odd) { - XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left) ; - XMEMCPY(tmp+aes->left, in, odd) ; + XMEMSET(tmp+aes->left, 0x0, AES_BLOCK_SIZE - aes->left); + XMEMCPY(tmp+aes->left, in, odd); wc_AesCrypt(aes, out_block, tmp, AES_BLOCK_SIZE, PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); - XMEMCPY(out, out_block+aes->left,odd) ; - aes->left += odd ; + XMEMCPY(out, out_block+aes->left,odd); + aes->left += odd; } } @@ -3051,7 +3122,7 @@ int wc_InitAes_h(Aes* aes, void* h) uint32_t keySize; byte *iv, *enc_key; byte* tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; - + /* consume any unused bytes left in aes->tmp */ while (aes->left && sz) { *(out++) = *(in++) ^ *(tmp++); @@ -3126,6 +3197,7 @@ int wc_InitAes_h(Aes* aes, void* h) #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AESGCM /* @@ -3722,8 +3794,8 @@ static void GMULT(byte* X, byte* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3871,8 +3943,8 @@ static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { byte x[AES_BLOCK_SIZE]; byte scratch[AES_BLOCK_SIZE]; @@ -3931,9 +4003,9 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word64* X, word64* Y) { word64 Z[2] = {0,0}; - word64 V[2] ; + word64 V[2]; int i, j; - V[0] = X[0] ; V[1] = X[1] ; + V[0] = X[0]; V[1] = X[1]; for (i = 0; i < 2; i++) { @@ -3947,13 +4019,15 @@ static void GMULT(word64* X, word64* Y) if (V[1] & 0x0000000000000001) { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; V[0] ^= 0xE100000000000000ULL; } else { V[1] >>= 1; - V[1] |= ((V[0] & 0x0000000000000001) ? 0x8000000000000000ULL : 0); + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); V[0] >>= 1; } y <<= 1; @@ -3963,8 +4037,9 @@ static void GMULT(word64* X, word64* Y) X[1] = Z[1]; } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) + +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word64 x[2] = {0,0}; word32 blocks, partial; @@ -4031,8 +4106,8 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, /* Hash in the lengths in bits of A and C */ { - word64 len[2] ; - len[0] = aSz ; len[1] = cSz; + word64 len[2]; + len[0] = aSz; len[1] = cSz; /* Lengths are in bytes. Convert to bits. */ len[0] *= 8; @@ -4055,7 +4130,7 @@ static void GHASH(Aes* aes, const byte* a, word32 aSz, static void GMULT(word32* X, word32* Y) { word32 Z[4] = {0,0,0,0}; - word32 V[4] ; + word32 V[4]; int i, j; V[0] = X[0]; V[1] = X[1]; V[2] = X[2]; V[3] = X[3]; @@ -4100,8 +4175,8 @@ static void GMULT(word32* X, word32* Y) } -static void GHASH(Aes* aes, const byte* a, word32 aSz, - const byte* c, word32 cSz, byte* s, word32 sSz) +static void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) { word32 x[4] = {0,0,0,0}; word32 blocks, partial; @@ -4209,6 +4284,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, uint32_t keySize; status_t status; + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + key = (byte*)aes->key; status = wc_AesGetKeySize(aes, &keySize); @@ -4229,13 +4309,47 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* c = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; /* Sanity check for XMEMCPY in GHASH function and local xorbuf call */ if (authTagSz > AES_BLOCK_SIZE) return BAD_FUNC_ARG; + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_GCM_ENCRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLFSSL_AESNI if (haveAESNI) { AES_GCM_encrypt(in, out, authIn, iv, authTag, @@ -4245,9 +4359,9 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif #ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; + ctr = (char *)aes->iv_ce; #else - ctr = counter ; + ctr = counter; #endif XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); @@ -4293,7 +4407,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, } -#ifdef HAVE_AES_DECRYPT +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, const byte* iv, word32 ivSz, const byte* authTag, word32 authTagSz, @@ -4324,12 +4438,44 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, byte* p = out; byte counter[AES_BLOCK_SIZE]; byte initialCounter[AES_BLOCK_SIZE]; - byte *ctr ; + byte *ctr; byte scratch[AES_BLOCK_SIZE]; - /* Sanity check for local ConstantCompare call */ - if (authTagSz > AES_BLOCK_SIZE) + /* argument checks */ + if (aes == NULL || out == NULL || in == NULL || sz == 0 || iv == NULL || + authTag == NULL || authTagSz > AES_BLOCK_SIZE) { return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM) { + #if defined(HAVE_CAVIUM) + /* Not yet supported, contact wolfSSL if interested in using */ + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, + aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_AES_GCM_DECRYPT; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = (byte*)authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_AESNI if (haveAESNI) { @@ -4341,9 +4487,9 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif #ifdef WOLFSSL_PIC32MZ_CRYPT - ctr = (char *)aes->iv_ce ; + ctr = (char *)aes->iv_ce; #else - ctr = counter ; + ctr = counter; #endif XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); @@ -4397,7 +4543,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif /* FREESCALE_LTC_AES_GCM */ } -#endif /* HAVE_AES_DECRYPT */ +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) { @@ -4887,28 +5033,36 @@ int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, #endif /* HAVE_AES_KEYWRAP */ -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) +/* Initialize Aes for use with async hardware */ +int wc_AesInit(Aes* aes, void* heap, int devId) { + int ret = 0; + if (aes == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, devId); + aes->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, + aes->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } - -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) +/* Free Aes from use with async hardware */ +void wc_AesFree(Aes* aes) { if (aes == NULL) return; - wolfAsync_DevCtxFree(&aes->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES); #endif /* WOLFSSL_ASYNC_CRYPT */ +} int wc_AesGetKeySize(Aes* aes, word32* keySize) diff --git a/wolfcrypt/src/arc4.c b/wolfcrypt/src/arc4.c index 6922089de..160c36a91 100644 --- a/wolfcrypt/src/arc4.c +++ b/wolfcrypt/src/arc4.c @@ -32,12 +32,14 @@ #include -void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) +int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) { + int ret = 0; word32 i; word32 keyIndex = 0, stateIndex = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4SetKey(arc4, key, length); } @@ -59,6 +61,8 @@ void wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) if (++keyIndex >= length) keyIndex = 0; } + + return ret; } @@ -76,12 +80,14 @@ static INLINE byte MakeByte(word32* x, word32* y, byte* s) } -void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) { + int ret = 0; word32 x; word32 y; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { return NitroxArc4Process(arc4, out, in, length); } @@ -95,31 +101,41 @@ void wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) arc4->x = (byte)x; arc4->y = (byte)y; + + return ret; } - -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Arc4 for use with Nitrox device */ -int wc_Arc4AsyncInit(Arc4* arc4, int devId) +/* Initialize Arc4 for use with async device */ +int wc_Arc4Init(Arc4* arc4, void* heap, int devId) { + int ret = 0; + if (arc4 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, devId); + arc4->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, + arc4->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; } -/* Free Arc4 from use with Nitrox device */ -void wc_Arc4AsyncFree(Arc4* arc4) +/* Free Arc4 from use with async device */ +void wc_Arc4Free(Arc4* arc4) { if (arc4 == NULL) return; - wolfAsync_DevCtxFree(&arc4->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* NO_RC4 */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c old mode 100755 new mode 100644 index 665199aeb..bd478ffba --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -31,6 +31,9 @@ ASN Options: * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC or wishing to save space. * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks. + * ASN_DUMP_OID: Allows dump of OID information for debugging. + * RSA_DECODE_EXTRA: Decodes extra information in RSA public key. + * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName. */ #ifndef NO_ASN @@ -78,6 +81,10 @@ ASN Options: #include #endif +#ifndef NO_RSA + #include +#endif + #ifdef WOLFSSL_DEBUG_ENCODING #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) #if MQX_USE_IO_OLD @@ -95,26 +102,24 @@ ASN Options: #pragma warning(disable: 4996) #endif - -#ifndef TRUE - #define TRUE 1 -#endif -#ifndef FALSE - #define FALSE 0 -#endif +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } #ifndef NO_ASN_TIME #if defined(USER_TIME) - /* user time, and gmtime compatible functions, there is a gmtime - implementation here that WINCE uses, so really just need some ticks - since the EPOCH + /* Use our gmtime and time_t/struct tm types. + Only needs seconds since EPOCH using XTIME function. + time_t XTIME(time_t * timer) {} */ #define WOLFSSL_GMTIME #define USE_WOLF_TM #define USE_WOLF_TIME_T #elif defined(TIME_OVERRIDES) - /* user would like to override time() and gmtime() functionality */ + /* Override XTIME() and XGMTIME() functionality. + Requires user to provide these functions: + time_t XTIME(time_t * timer) {} + struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {} + */ #ifndef HAVE_TIME_T_TYPE #define USE_WOLF_TIME_T #endif @@ -234,6 +239,10 @@ ASN Options: struct tm* gmtime(const time_t* timer); #endif +#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + /* extern time_t ksdk_time(time_t* timer); */ +#endif /* FREESCALE_KSDK_BM || FREESCALE_FREE_RTOS */ + #if defined(_WIN32_WCE) time_t windows_time(time_t* timer) @@ -363,7 +372,7 @@ time_t pic32_time(time_t* timer) return *timer; } -#endif /* MICROCHIP_TCPIP */ +#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) @@ -382,14 +391,8 @@ time_t mqx_time(time_t* timer) return *timer; } -#endif /* FREESCALE_MQX */ +#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ -#if defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) - -/* */ -//extern time_t ksdk_time(time_t* timer); - -#endif /* FREESCALE_KSDK_BM */ #if defined(WOLFSSL_TIRTOS) @@ -484,6 +487,7 @@ CPU_INT32S NetSecure_ValidateDateHandler(CPU_INT08U *date, CPU_INT08U format, #endif /* MICRIUM */ + #if defined(IDIRECT_DEV_TIME) extern time_t getTimestamp(); @@ -502,43 +506,44 @@ time_t idirect_time(time_t * timer) #endif /* !NO_ASN_TIME */ + WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { int length = 0; - word32 i = *inOutIdx; + word32 idx = *inOutIdx; byte b; *len = 0; /* default length */ - if ( (i+1) > maxIdx) { /* for first read */ + if ((idx + 1) > maxIdx) { /* for first read */ WOLFSSL_MSG("GetLength bad index on input"); return BUFFER_E; } - b = input[i++]; + b = input[idx++]; if (b >= ASN_LONG_LENGTH) { word32 bytes = b & 0x7F; - if ( (i+bytes) > maxIdx) { /* for reading bytes */ + if ((idx + bytes) > maxIdx) { /* for reading bytes */ WOLFSSL_MSG("GetLength bad long length"); return BUFFER_E; } while (bytes--) { - b = input[i++]; + b = input[idx++]; length = (length << 8) | b; } } else length = b; - if ( (i+length) > maxIdx) { /* for user of length */ + if ((idx + length) > maxIdx) { /* for user of length */ WOLFSSL_MSG("GetLength value exceeds buffer length"); return BUFFER_E; } - *inOutIdx = i; + *inOutIdx = idx; if (length > 0) *len = length; @@ -546,39 +551,317 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } -WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, - word32 maxIdx) +/* Get the DER/BER encoding of an ASN.1 header. + * + * input Buffer holding DER/BER encoded data. + * tag ASN.1 tag value expected in header. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the expected tag is not found or length is invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; + word32 idx = *inOutIdx; + byte b; + int length; - if (input[idx++] != (ASN_SEQUENCE | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != tag) + return ASN_PARSE_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; *len = length; *inOutIdx = idx; - return length; } +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { - int length = -1; - word32 idx = *inOutIdx; - - if (input[idx++] != (ASN_SET | ASN_CONSTRUCTED) || - GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - *len = length; - *inOutIdx = idx; - - return length; + return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); } +/* Get the DER/BER encoded ASN.1 NULL element. + * Ensure that the all fields are as expected and move index past the element. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_TAG_NULL_E when the NULL tag is not found. + * ASN_EXPECT_0_E when the length is not zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 2) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_TAG_NULL) + return ASN_TAG_NULL_E; + + if (input[idx++] != 0) + return ASN_EXPECT_0_E; + + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 NULL element. + * + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNNull(byte* output) +{ + output[0] = ASN_TAG_NULL; + output[1] = 0; + + return 2; +} + +/* Get the DER/BER encoding of an ASN.1 BOOLEAN. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1. + * Otherwise, 0 to indicate the value was false and 1 to indicate true. + */ +static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_BOOLEAN) + return ASN_PARSE_E; + + if (input[idx++] != 1) + return ASN_PARSE_E; + + b = input[idx++] != 0; + + *inOutIdx = idx; + return b; +} + +#ifdef ASN1_SET_BOOLEAN +/* Set the DER/BER encoding of the ASN.1 NULL element. + * Note: Function not required as yet. + * + * val Boolean value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetBoolean(int val, byte* output) +{ + output[0] = ASN_BOOLEAN; + output[1] = 1; + output[2] = val ? -1 : 0; + + return 3; +} +#endif + +/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the OCTET_STRING tag is not found or length is + * invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetOctetString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx); +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER header. + * Removes the leading zero byte when found. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data (excluding any leading zero). + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found, length is invalid, + * or invalid use of or missing leading zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNInt(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int ret; + + ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx); + if (ret < 0) + return ret; + + if (*len > 0) { + /* remove leading zero, unless there is only one 0x00 byte */ + if ((input[*inOutIdx] == 0x00) && (*len > 1)) { + (*inOutIdx)++; + (*len)--; + + if (*len > 0 && (input[*inOutIdx] & 0x80) == 0) + return ASN_PARSE_E; + } + else if ((input[*inOutIdx] & 0x80) == 0x80) + return ASN_PARSE_E; + } + + return 0; +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than + * 7 bits. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found or length is invalid. + * Otherwise, the 7-bit value. + */ +static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + if (input[idx++] != 1) + return ASN_PARSE_E; + b = input[idx++]; + + *inOutIdx = idx; + return b; +} + +#if !defined(NO_DSA) || defined(HAVE_ECC) || (!defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA)))) +/* Set the DER/BER encoding of the ASN.1 INTEGER header. + * + * len Length of data to encode. + * firstByte First byte of data, most significant byte of integer, to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNInt(int len, byte firstByte, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_INTEGER; + if (firstByte & 0x80) + len++; + idx += SetLength(len, output + idx); + if (firstByte & 0x80) + output[idx++] = 0x00; + + return idx; +} +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) || (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * maxSz Maximum size of the encoded integer. + * A negative value indicates no check of length requested. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntMP(mp_int* n, int maxSz, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = mp_leading_bit(n); + length = mp_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if (maxSz >= 0 && (idx + length) > maxSz) + return BUFFER_E; + + err = mp_to_unsigned_bin(n, output + idx); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif + +#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && defined(WOLFSSL_CERT_GEN) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from + * an RSA key. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntRSA(mp_int* n, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = wc_Rsa_leading_bit(n); + length = wc_Rsa_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if ((idx + length) > MAX_RSA_INT_SZ) + return BUFFER_E; + + err = wc_Rsa_to_unsigned_bin(n, output + idx, length); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ /* Windows header clash for WinCE using GetVersion */ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, @@ -586,10 +869,8 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, { word32 idx = *inOutIdx; - WOLFSSL_ENTER("GetMyVersion"); - - if (idx + MIN_VERSION_SZ > maxIdx) - return ASN_PARSE_E; + if ((idx + MIN_VERSION_SZ) > maxIdx) + return ASN_PARSE_E; if (input[idx++] != ASN_INTEGER) return ASN_PARSE_E; @@ -613,8 +894,9 @@ int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) *number = 0; - if (idx + 2 > maxIdx) /*one for type and one for length */ - return ASN_PARSE_E; + /* check for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; if (input[idx++] != ASN_INTEGER) return ASN_PARSE_E; @@ -636,7 +918,6 @@ int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) } #endif /* !NO_PWDBASED */ -#ifndef NO_ASN_TIME /* May not have one, not an error */ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, word32 maxIdx) @@ -644,8 +925,12 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, word32 idx = *inOutIdx; WOLFSSL_ENTER("GetExplicitVersion"); + + if ((idx + 1) > maxIdx) + return BUFFER_E; + if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { - *inOutIdx = ++idx; /* eat header */ + *inOutIdx = ++idx; /* skip header */ return GetMyVersion(input, inOutIdx, version, maxIdx); } @@ -654,96 +939,146 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, return 0; } -#endif /* !NO_ASN_TIME */ -int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, - word32 maxIdx) +int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { - word32 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; + int ret; int length; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; if (mp_init(mpi) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { + if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { mp_clear(mpi); return ASN_GETINT_E; } - *inOutIdx = i + length; +#ifdef HAVE_WOLF_BIGINT + if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + *inOutIdx = idx + length; + return 0; } -#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) -static int GetIntRsa(RsaKey* key, mp_int* mpi, const byte* input, - word32* inOutIdx, word32 maxIdx) +static int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits) { - word32 i = *inOutIdx; - byte b = input[i++]; + word32 idx = *inOutIdx; int length; + byte b; - (void)key; + if ((idx + 1) > maxIdx) + return BUFFER_E; - if (b != ASN_INTEGER) + if (input[idx++] != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) return ASN_PARSE_E; - if (GetLength(input, &i, &length, maxIdx) < 0) + /* extra sanity check that length is greater than 0 */ + if (length <= 0) { + WOLFSSL_MSG("Error length was 0 in CheckBitString"); + return BUFFER_E; + } + + if (idx + 1 > maxIdx) { + WOLFSSL_MSG("Attempted buffer read larger than input buffer"); + return BUFFER_E; + } + + b = input[idx]; + if (zeroBits && b != 0x00) + return ASN_EXPECT_0_E; + if (b >= 0x08) return ASN_PARSE_E; - - if (length > 0) { - /* remove leading zero */ - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + if (b != 0) { + if ((byte)(input[idx + length - 1] << (8 - b)) != 0) + return ASN_PARSE_E; } + idx++; + length--; /* length has been checked for greater than 0 */ -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - XMEMSET(mpi, 0, sizeof(mp_int)); - mpi->used = length; - #ifdef USE_FAST_MATH - if (length > (FP_SIZE * (int)sizeof(fp_digit))) { - return MEMORY_E; - } - mpi->dpraw = (byte*)mpi->dp; - #else - mpi->dpraw = (byte*)XMALLOC(length, key->heap, DYNAMIC_TYPE_ASYNC_RSA); - #endif - if (mpi->dpraw == NULL) { - return MEMORY_E; - } + *inOutIdx = idx; + if (len != NULL) + *len = length; + if (unusedBits != NULL) + *unusedBits = b; - XMEMCPY(mpi->dpraw, input + i, length); - } - else -#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM */ - { - if (mp_init(mpi) != MP_OKAY) - return MP_INIT_E; - - if (mp_read_unsigned_bin(mpi, (byte*)input + i, length) != 0) { - mp_clear(mpi); - return ASN_GETINT_E; - } - } - - *inOutIdx = i + length; return 0; } -#endif /* !NO_RSA && !HAVE_USER_RSA */ + +#if (!defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ + (defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_USER_RSA)))) || \ + (defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN))) +/* Set the DER/BER encoding of the ASN.1 BIT_STRING header. + * + * len Length of data to encode. + * unusedBits The number of unused bits in the last byte of data. + * That is, the number of least significant zero bits before a one. + * The last byte is the most-significant non-zero byte of a number. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString(word32 len, byte unusedBits, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_BIT_STRING; + idx += SetLength(len + 1, output + idx); + output[idx++] = unusedBits; + + return idx; +} + +#ifdef WOLFSSL_CERT_EXT +/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value. + * + * val 16-bit value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString16Bit(word16 val, byte* output) +{ + word32 idx; + int len; + byte lastByte; + byte unusedBits = 0; + + if ((val >> 8) != 0) { + len = 2; + lastByte = (byte)(val >> 8); + } + else { + len = 1; + lastByte = (byte)val; + } + + while (((lastByte >> unusedBits) & 0x01) == 0x00) + unusedBits++; + + idx = SetBitString(len, unusedBits, output); + output[idx++] = (byte)val; + output[idx++] = (byte)(val >> 8); + + return idx; +} +#endif /* WOLFSSL_CERT_EXT */ +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA)) */ + /* hashType */ @@ -1312,52 +1647,100 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) } #endif /* HAVE_OID_DECODING */ +/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found. + * ASN_PARSE_E when length is invalid. + * Otherwise, 0 to indicate success. + */ +static int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header. + * + * len Length of the OBJECT_ID data. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetObjectId(int len, byte* output) +{ + int idx = 0; + + output[idx++] = ASN_OBJECT_ID; + idx += SetLength(len, output + idx); + + return idx; +} + int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx) { - int length; - word32 i = *inOutIdx; + int ret = 0, length; + word32 idx = *inOutIdx; #ifndef NO_VERIFY_OID word32 actualOidSz = 0; const byte* actualOid; #endif /* NO_VERIFY_OID */ - byte b; (void)oidType; WOLFSSL_ENTER("GetObjectId()"); *oid = 0; - b = input[i++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, &i, &length, maxIdx) < 0) - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; #ifndef NO_VERIFY_OID - actualOid = &input[i]; + actualOid = &input[idx]; if (length > 0) actualOidSz = (word32)length; #endif /* NO_VERIFY_OID */ - while(length--) { - /* odd HC08 compiler behavior here when input[i++] */ - *oid += input[i]; - i++; + while (length--) { + /* odd HC08 compiler behavior here when input[idx++] */ + *oid += (word32)input[idx]; + idx++; } /* just sum it up for now */ - *inOutIdx = i; + *inOutIdx = idx; #ifndef NO_VERIFY_OID { const byte* checkOid = NULL; word32 checkOidSz; + #ifdef ASN_DUMP_OID + int i; + #endif if (oidType != oidIgnoreType) { checkOid = OidFromId(*oid, oidType, &checkOidSz); - #if 0 + #ifdef ASN_DUMP_OID /* support for dumping OID information */ printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid); for (i=0; i type = RSA_PRIVATE; - if (GetIntRsa(key, &key->n, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->e, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->d, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->p, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->q, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->dP, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->dQ, input, inOutIdx, inSz) < 0 || - GetIntRsa(key, &key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + GetInt(&key->d, input, inOutIdx, inSz) < 0 || + GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->dP, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || + GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; return 0; } #endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) +{ + word32 idx, oid; + int version, length; + int ret; + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, &idx, &version, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &idx, &oid, oidKeyType, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == ASN_OBJECT_ID) { + if (SkipObjectId(input, &idx, sz) < 0) + return ASN_PARSE_E; + } + + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; + + *inOutIdx = idx; + + return length; +} + /* Remove PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditional(byte* input, word32 sz) { - word32 inOutIdx = 0, oid; - int version, length; + word32 inOutIdx = 0; + int length; - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (input == NULL) + return BAD_FUNC_ARG; - if (GetMyVersion(input, &inOutIdx, &version, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKeyType, sz) < 0) - return ASN_PARSE_E; - - if (input[inOutIdx] == ASN_OBJECT_ID) { - /* pkcs8 ecc uses slightly different format */ - inOutIdx++; /* past id */ - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - inOutIdx += length; /* over sub id, key input will verify */ - } - - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + length = ToTraditionalInline(input, &inOutIdx, sz); + if (length < 0) + return length; XMEMMOVE(input, input + inOutIdx, length); @@ -1515,6 +1911,134 @@ int ToTraditional(byte* input, word32 sz) } +/* find beginning of traditional key inside PKCS#8 unencrypted buffer + * return traditional length on success, with inOutIdx at beginning of + * traditional + * return negative on failure/error */ +int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) +{ + int length; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline(input, inOutIdx, sz); + + return length; +} + + +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + oidSz = 0; /* with no curveOID oid size must be 0 */ + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + sz = SetObjectId(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += oidSz; + } + + sz = SetOctetString(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + + /* check that the private key is a pair for the public key in certificate * return 1 (true) on match * return 0 or negative value on failure/error @@ -1630,11 +2154,11 @@ static int CheckAlgo(int first, int second, int* id, int* version) switch (second) { case 1: *id = PBE_SHA1_RC4_128; - *version = PKCS12; + *version = PKCS12v1; return 0; case 3: *id = PBE_SHA1_DES3; - *version = PKCS12; + *version = PKCS12v1; return 0; default: return ALGO_ID_E; @@ -1742,7 +2266,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, ret = wc_PBKDF1(key, (byte*)password, passwordSz, salt, saltSz, iterations, derivedLen, typeH); #endif - else if (version == PKCS12) { + else if (version == PKCS12v1) { int i, idx = 0; byte unicodePasswd[MAX_UNICODE_SZ]; @@ -1788,7 +2312,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, Des dec; byte* desIv = key + 8; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; ret = wc_Des_SetKey(&dec, key, desIv, DES_DECRYPTION); @@ -1808,7 +2332,7 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, Des3 dec; byte* desIv = key + 24; - if (version == PKCS5v2 || version == PKCS12) + if (version == PKCS5v2 || version == PKCS12v1) desIv = cbcIv; ret = wc_Des3_SetKey(&dec, key, desIv, DES_DECRYPTION); if (ret != 0) { @@ -1853,12 +2377,88 @@ static int DecryptKey(const char* password, int passwordSz, byte* salt, } +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) +{ + word32 tmpIdx = 0; +#ifdef HAVE_ECC + ecc_key ecc; +#endif +#ifndef NO_RSA + RsaKey rsa; +#endif + + if (algoID == NULL) { + return BAD_FUNC_ARG; + } + *algoID = 0; + +#ifndef NO_RSA + if (wc_InitRsaKey(&rsa, heap) == 0) { + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + } + else { + WOLFSSL_MSG("GetKeyOID wc_InitRsaKey failed"); + } +#endif /* NO_RSA */ +#ifdef HAVE_ECC + if (*algoID != RSAk) { + tmpIdx = 0; + if (wc_ecc_init_ex(&ecc, heap, INVALID_DEVID) == 0) { + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* sanity check on arguments */ + if (curveOID == NULL || oidSz == NULL) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + + /* now find oid */ + if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(&ecc); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ecc_init_ex failed"); + } + } +#endif /* HAVE_ECC */ + + /* if flag is not set then is neither RSA or ECC key that could be + * found */ + if (*algoID == 0) { + WOLFSSL_MSG("Bad key DER or compile options"); + return BAD_FUNC_ARG; + } + + (void)curveOID; + (void)oidSz; + + return 1; +} + + /* Remove Encrypted PKCS8 header, move beginning of traditional to beginning of input */ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) { word32 inOutIdx = 0, oid; - int first, second, length, version, saltSz, id; + int ret = 0, first, second, length = 0, version, saltSz, id; int iterations = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; @@ -1868,63 +2468,65 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) byte cbcIv[MAX_IV_SIZE]; #endif - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ - if (CheckAlgo(first, second, &id, &version) < 0) - return ASN_INPUT_E; /* Algo ID error */ - - if (version == PKCS5v2) { - - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) - return ASN_PARSE_E; - - if (oid != PBKDF2_OID) - return ASN_PARSE_E; + if (CheckAlgo(first, second, &id, &version) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */ } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) - return ASN_PARSE_E; + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } - if (saltSz > MAX_SALT_SIZE) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_tte; + + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (salt == NULL) - return MEMORY_E; + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_tte); + } #endif XMEMCPY(salt, &input[inOutIdx], saltSz); inOutIdx += saltSz; if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_tte); } #endif @@ -1932,89 +2534,52 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) /* get encryption algo */ /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } if (CheckAlgoV2(oid, &id) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; /* PKCS v2 algo id error */ + ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; if (length > MAX_IV_SIZE) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_tte); } XMEMCPY(cbcIv, &input[inOutIdx], length); inOutIdx += length; } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (DecryptKey(password, passwordSz, salt, saltSz, iterations, id, - input + inOutIdx, length, version, cbcIv) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_INPUT_E; /* decrypt failure */ - } + ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv); +exit_tte: #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - XMEMMOVE(input, input + inOutIdx, length); - return ToTraditional(input, length); + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = ToTraditional(input, length); + } + + return ret; } /* decrypt PKCS */ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) { word32 inOutIdx = 0, oid; - int ret; - int first, second, length, version, saltSz, id; + int ret = 0; + int first, second, length = 0, version, saltSz, id; int iterations = 0; #ifdef WOLFSSL_SMALL_STACK byte* salt = NULL; @@ -2024,60 +2589,61 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) byte cbcIv[MAX_IV_SIZE]; #endif - if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ - if (CheckAlgo(first, second, &id, &version) < 0) - return ASN_INPUT_E; /* Algo ID error */ - - if (version == PKCS5v2) { - - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; - - if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) - return ASN_PARSE_E; - - if (oid != PBKDF2_OID) - return ASN_PARSE_E; + if (CheckAlgo(first, second, &id, &version) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */ } - if (GetSequence(input, &inOutIdx, &length, sz) < 0) - return ASN_PARSE_E; + if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (input[inOutIdx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } - if (GetLength(input, &inOutIdx, &saltSz, sz) < 0) - return ASN_PARSE_E; + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } - if (saltSz > MAX_SALT_SIZE) - return ASN_PARSE_E; + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_dc; + + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } #ifdef WOLFSSL_SMALL_STACK salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (salt == NULL) - return MEMORY_E; + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_dc); + } #endif XMEMCPY(salt, &input[inOutIdx], saltSz); inOutIdx += saltSz; if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; + ERROR_OUT(MEMORY_E, exit_dc); } #endif @@ -2085,73 +2651,45 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) /* get encryption algo */ /* JOHN: New type. Need a little more research. */ if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } if (CheckAlgoV2(oid, &id) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; /* PKCS v2 algo id error */ + ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */ } - if (input[inOutIdx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_dc; XMEMCPY(cbcIv, &input[inOutIdx], length); inOutIdx += length; } - if (input[inOutIdx++] != ASN_LONG_LENGTH) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + ERROR_OUT(ASN_PARSE_E, exit_dc); } if (GetLength(input, &inOutIdx, &length, sz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; + ERROR_OUT(ASN_PARSE_E, exit_dc); } - if ((ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, - input + inOutIdx, length, version, cbcIv)) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; /* decrypt failure */ - } + ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv); + +exit_dc: #ifdef WOLFSSL_SMALL_STACK XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - XMEMMOVE(input, input + inOutIdx, length); - return length; + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = length; + } + + return ret; } #endif /* NO_PWDBASED */ @@ -2161,11 +2699,14 @@ int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz) int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { - int length; + int length; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif + int ret; - if (input == NULL || inOutIdx == NULL || key == NULL) { + if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; - } if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -2173,8 +2714,10 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, key->type = RSA_PUBLIC; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; + if ((*inOutIdx + 1) > inSz) + return BUFFER_E; + + b = input[*inOutIdx]; if (b != ASN_INTEGER) { /* not from decoded cert, will have algo id, skip past */ if (GetSequence(input, inOutIdx, &length, inSz) < 0) @@ -2183,39 +2726,29 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, if (SkipObjectId(input, inOutIdx, inSz) < 0) return ASN_PARSE_E; - /* could have NULL tag and 0 terminator, but may not */ - b = input[(*inOutIdx)++]; - - if (b == ASN_TAG_NULL) { - b = input[(*inOutIdx)++]; - if (b != 0) - return ASN_EXPECT_0_E; + /* Option NULL ASN.1 tag */ + if (input[*inOutIdx] == ASN_TAG_NULL) { + ret = GetASNNull(input, inOutIdx, inSz); + if (ret != 0) + return ret; } - else - /* go back, didn't have it */ - (*inOutIdx)--; /* should have bit tag length and seq next */ - b = input[(*inOutIdx)++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - /* could have 0 */ - b = input[(*inOutIdx)++]; - if (b != 0) - (*inOutIdx)--; + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - } /* end if */ - } /* openssl var block */ + } #endif /* OPENSSL_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; + if (GetInt(&key->n, input, inOutIdx, inSz) < 0) + return ASN_RSA_KEY_E; + if (GetInt(&key->e, input, inOutIdx, inSz) < 0) { + mp_clear(&key->n); + return ASN_RSA_KEY_E; + } return 0; } @@ -2263,7 +2796,9 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) return ASN_PARSE_E; if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->g, input, inOutIdx, inSz) < 0 ) return ASN_DH_KEY_E; + GetInt(&key->g, input, inOutIdx, inSz) < 0) { + return ASN_DH_KEY_E; + } return 0; } @@ -2272,47 +2807,37 @@ int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz) { - word32 i = 0; - byte b; + word32 idx = 0; + int ret; int length; - if (GetSequence(input, &i, &length, inSz) < 0) + if (GetSequence(input, &idx, &length, inSz) <= 0) return ASN_PARSE_E; - b = input[i++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; - - if ( (b = input[i++]) == 0x00) - length--; - else - i--; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*pInOutSz) { - XMEMCPY(p, &input[i], length); + XMEMCPY(p, &input[idx], length); *pInOutSz = length; } - else + else { return BUFFER_E; + } + idx += length; - i += length; - - b = input[i++]; - if (b != ASN_INTEGER) - return ASN_PARSE_E; - - if (GetLength(input, &i, &length, inSz) < 0) - return ASN_PARSE_E; + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; if (length <= (int)*gInOutSz) { - XMEMCPY(g, &input[i], length); + XMEMCPY(g, &input[idx], length); *gInOutSz = length; } - else + else { return BUFFER_E; + } return 0; } @@ -2396,7 +2921,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[DSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -2415,10 +2940,7 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) for (i = 0; i < DSA_INTS; i++) { mp_int* keyInt = GetDsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_DSA); if (tmps[i] == NULL) { @@ -2426,30 +2948,12 @@ int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, -1, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -2488,6 +2992,7 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->publicKey = 0; cert->pubKeySize = 0; cert->pubKeyStored = 0; + cert->keyOID = 0; cert->version = 0; cert->signature = 0; cert->subjectCN = 0; @@ -2560,6 +3065,10 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) #ifdef OPENSSL_EXTRA XMEMSET(&cert->issuerName, 0, sizeof(DecodedName)); XMEMSET(&cert->subjectName, 0, sizeof(DecodedName)); + cert->extCRLdistSet = 0; + cert->extCRLdistCrit = 0; + cert->extAuthInfoSet = 0; + cert->extAuthInfoCrit = 0; cert->extBasicConstSet = 0; cert->extBasicConstCrit = 0; cert->extSubjAltNameSet = 0; @@ -2598,6 +3107,9 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) XMEMSET(cert->extCertPolicies, 0, MAX_CERTPOL_NB*MAX_CERTPOL_SZ); cert->extCertPoliciesNb = 0; #endif + + cert->ca = NULL; + InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID); } @@ -2658,9 +3170,9 @@ void FreeDecodedCert(DecodedCert* cert) if (cert->subjectName.fullName != NULL) XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509); #endif /* OPENSSL_EXTRA */ + FreeSignatureCtx(&cert->sigCtx); } -#ifndef NO_ASN_TIME static int GetCertHeader(DecodedCert* cert) { int ret = 0, len; @@ -2707,9 +3219,7 @@ static int StoreRsaKey(DecodedCert* cert) return 0; } -#endif -#endif /* !NO_ASN_TIME */ - +#endif /* !NO_RSA */ #ifdef HAVE_ECC @@ -2730,7 +3240,6 @@ static int StoreRsaKey(DecodedCert* cert) #endif /* HAVE_ECC */ -#ifndef NO_ASN_TIME static int GetKey(DecodedCert* cert) { int length; @@ -2749,15 +3258,11 @@ static int GetKey(DecodedCert* cert) #ifndef NO_RSA case RSAk: { - byte b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) - return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, NULL, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; return StoreRsaKey(cert); } @@ -2830,7 +3335,7 @@ static int GetKey(DecodedCert* cert) #ifdef HAVE_ECC case ECDSAk: { - byte b; + int ret; if (GetObjectId(cert->source, &cert->srcIdx, &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) @@ -2840,18 +3345,10 @@ static int GetKey(DecodedCert* cert) return ECC_CURVE_OID_E; /* key header */ - b = cert->source[cert->srcIdx++]; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source,&cert->srcIdx,&length,cert->maxIdx) < 0) - return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; - - /* actual key, use length - 1 since ate preceding 0 */ - length -= 1; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; cert->publicKey = (byte*) XMALLOC(length, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); @@ -2871,7 +3368,6 @@ static int GetKey(DecodedCert* cert) } } - /* process NAME, either issuer or subject */ static int GetName(DecodedCert* cert, int nameType) { @@ -2900,10 +3396,8 @@ static int GetName(DecodedCert* cert, int nameType) if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { WOLFSSL_MSG("Trying optional prefix..."); - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0) return ASN_PARSE_E; - - cert->srcIdx += length; WOLFSSL_MSG("Got optional prefix"); } @@ -2949,14 +3443,15 @@ static int GetName(DecodedCert* cert, int nameType) WOLFSSL_MSG("Cert name lacks set header, trying sequence"); } - if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) + if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) <= 0) return ASN_PARSE_E; - b = cert->source[cert->srcIdx++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx); + if (ret != 0) + return ret; - if (GetLength(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx) < 0) + /* make sure there is room for joint */ + if ((cert->srcIdx + sizeof(joint)) > cert->maxIdx) return ASN_PARSE_E; XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); @@ -3351,6 +3846,7 @@ static int GetName(DecodedCert* cert, int nameType) } +#ifndef NO_ASN_TIME #if !defined(NO_TIME_H) && defined(USE_WOLF_VALIDDATE) /* to the second */ @@ -3390,7 +3886,7 @@ static INLINE int DateLessThan(const struct tm* a, const struct tm* b) } -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) int GetTimeString(byte* date, int format, char* buf, int len) { struct tm t; @@ -3432,7 +3928,7 @@ int GetTimeString(byte* date, int format, char* buf, int len) return 1; } -#endif /* MYSQL compatibility */ +#endif /* WOLFSSL_MYSQL_COMPATIBLE */ int ExtractDate(const unsigned char* date, unsigned char format, struct tm* certTime, int* idx) @@ -3483,6 +3979,21 @@ int ValidateDate(const byte* date, byte format, int dateType) #endif ltime = XTIME(0); + +#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW + if (dateType == BEFORE) { + WOLFSSL_MSG("Skewing local time for before date check"); + ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW; + } +#endif + +#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW + if (dateType == AFTER) { + WOLFSSL_MSG("Skewing local time for after date check"); + ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW; + } +#endif + if (!ExtractDate(date, format, &certTime, &i)) { WOLFSSL_MSG("Error extracting the date"); return 0; @@ -3508,12 +4019,17 @@ int ValidateDate(const byte* date, byte format, int dateType) } if (dateType == BEFORE) { - if (DateLessThan(localTime, &certTime)) + if (DateLessThan(localTime, &certTime)) { + WOLFSSL_MSG("Date BEFORE check failed"); return 0; + } } - else - if (DateGreaterThan(localTime, &certTime)) + else { /* dateType == AFTER */ + if (DateGreaterThan(localTime, &certTime)) { + WOLFSSL_MSG("Date AFTER check failed"); return 0; + } + } return 1; } @@ -3536,6 +4052,8 @@ int wc_GetTime(void* timePtr, word32 timeSize) return 0; } +#endif /* !NO_ASN_TIME */ + static int GetDate(DecodedCert* cert, int dateType) { int length; @@ -3544,6 +4062,7 @@ static int GetDate(DecodedCert* cert, int dateType) word32 startIdx = 0; XMEMSET(date, 0, MAX_DATE_SIZE); + if (dateType == BEFORE) cert->beforeDate = &cert->source[cert->srcIdx]; else @@ -3568,17 +4087,18 @@ static int GetDate(DecodedCert* cert, int dateType) else cert->afterDateLen = cert->srcIdx - startIdx; +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(date, b, dateType)) { if (dateType == BEFORE) return ASN_BEFORE_DATE_E; else return ASN_AFTER_DATE_E; } +#endif return 0; } - static int GetValidity(DecodedCert* cert, int verify) { int length; @@ -3638,39 +4158,35 @@ int DecodeToKey(DecodedCert* cert, int verify) return ret; } - static int GetSignature(DecodedCert* cert) { - int length; - byte b = cert->source[cert->srcIdx++]; - - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) - return ASN_PARSE_E; + int length; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, + NULL); + if (ret != 0) + return ret; cert->sigLength = length; - - b = cert->source[cert->srcIdx++]; - if (b != 0x00) - return ASN_EXPECT_0_E; - - cert->sigLength--; cert->signature = &cert->source[cert->srcIdx]; cert->srcIdx += cert->sigLength; return 0; } -#endif /* !NO_ASN_TIME */ + +static word32 SetOctetString8Bit(word32 len, byte* output) +{ + output[0] = ASN_OCTET_STRING; + output[1] = (byte)len; + return 2; +} static word32 SetDigest(const byte* digest, word32 digSz, byte* output) { - output[0] = ASN_OCTET_STRING; - output[1] = (byte)digSz; - XMEMCPY(&output[2], digest, digSz); + word32 idx = SetOctetString8Bit(digSz, output); + XMEMCPY(&output[idx], digest, digSz); - return digSz + 2; + return idx + digSz; } @@ -3742,7 +4258,9 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) static int SetCurve(ecc_key* key, byte* output) { +#ifdef HAVE_OID_ENCODING int ret; +#endif int idx = 0; word32 oidSz = 0; @@ -3760,11 +4278,7 @@ static int SetCurve(ecc_key* key, byte* output) oidSz = key->dp->oidSz; #endif - output[0] = ASN_OBJECT_ID; - idx++; - - ret = SetLength(oidSz, output+idx); - idx += ret; + idx += SetObjectId(oidSz, output); #ifdef HAVE_OID_ENCODING ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz); @@ -3797,7 +4311,7 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) { word32 tagSz, idSz, seqSz, algoSz = 0; const byte* algoName = 0; - byte ID_Length[MAX_LENGTH_SZ]; + byte ID_Length[1 + MAX_LENGTH_SZ]; byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ tagSz = (type == oidHashType || @@ -3811,18 +4325,14 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) return 0; } - idSz = SetLength(algoSz, ID_Length); - seqSz = SetSequence(idSz + algoSz + 1 + tagSz + curveSz, seqArray); - /* +1 for object id, curveID of curveSz follows for ecc */ - seqArray[seqSz++] = ASN_OBJECT_ID; + idSz = SetObjectId(algoSz, ID_Length); + seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray); XMEMCPY(output, seqArray, seqSz); XMEMCPY(output + seqSz, ID_Length, idSz); XMEMCPY(output + seqSz + idSz, algoName, algoSz); - if (tagSz == 2) { - output[seqSz + idSz + algoSz] = ASN_TAG_NULL; - output[seqSz + idSz + algoSz + 1] = 0; - } + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); return seqSz + idSz + algoSz + tagSz; @@ -3885,275 +4395,347 @@ int wc_GetCTC_HashOID(int type) }; } -#ifndef NO_ASN_TIME -/* return true (1) or false (0) for Confirmation */ -static int ConfirmSignature(const byte* buf, word32 bufSz, - const byte* key, word32 keySz, word32 keyOID, - const byte* sig, word32 sigSz, word32 sigOID, - void* heap) +void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId) { - int typeH = 0, digestSz = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; -#endif + if (sigCtx) { + XMEMSET(sigCtx, 0, sizeof(SignatureCtx)); + sigCtx->devId = devId; + sigCtx->heap = heap; + } +} -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ +void FreeSignatureCtx(SignatureCtx* sigCtx) +{ + if (sigCtx == NULL) + return; + + if (sigCtx->digest) { + XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + sigCtx->digest = NULL; + } +#ifndef NO_RSA + if (sigCtx->plain) { + XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + sigCtx->plain = NULL; + } #endif + if (sigCtx->key.ptr) { + switch (sigCtx->keyOID) { + #ifndef NO_RSA + case RSAk: + wc_FreeRsaKey(sigCtx->key.rsa); + XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA); + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + wc_ecc_free(sigCtx->key.ecc); + XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); + break; + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ + sigCtx->key.ptr = NULL; + } + + /* reset state, we are done */ + sigCtx->state = SIG_STATE_BEGIN; +} + +/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ +static int ConfirmSignature(SignatureCtx* sigCtx, + const byte* buf, word32 bufSz, + const byte* key, word32 keySz, word32 keyOID, + const byte* sig, word32 sigSz, word32 sigOID) +{ + int ret = 0; + + if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || + keySz == 0 || sig == NULL || sigSz == 0) { + return BAD_FUNC_ARG; + } (void)key; (void)keySz; (void)sig; (void)sigSz; - (void)heap; - switch (sigOID) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if (wc_Md5Hash(buf, bufSz, digest) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; - } - break; - #endif - #if defined(WOLFSSL_MD2) - case CTC_MD2wRSA: - if (wc_Md2Hash(buf, bufSz, digest) == 0) { - typeH = MD2h; - digestSz = MD2_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwDSA: - case CTC_SHAwECDSA: - if (wc_ShaHash(buf, bufSz, digest) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if (wc_Sha224Hash(buf, bufSz, digest) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; - } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if (wc_Sha256Hash(buf, bufSz, digest) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if (wc_Sha512Hash(buf, bufSz, digest) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; - } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if (wc_Sha384Hash(buf, bufSz, digest) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; - } - break; - #endif - default: - WOLFSSL_MSG("Verify Signature has unsupported type"); - } + WOLFSSL_ENTER("ConfirmSignature"); - if (typeH == 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return 0; /* not confirmed */ - } - - switch (keyOID) { - #ifndef NO_RSA - case RSAk: + switch (sigCtx->state) { + case SIG_STATE_BEGIN: { - word32 idx = 0; - int encodedSigSz, verifySz; - byte* out; -#ifdef WOLFSSL_SMALL_STACK - RsaKey* pubKey; - byte* plain; - byte* encodedSig; -#else - RsaKey pubKey[1]; - byte plain[MAX_ENCODED_SIG_SZ]; - byte encodedSig[MAX_ENCODED_SIG_SZ]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (pubKey == NULL || plain == NULL || encodedSig == NULL) { - WOLFSSL_MSG("Failed to allocate memory at ConfirmSignature"); - - if (pubKey) - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (plain) - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encodedSig) - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - break; /* not confirmed */ + sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sigCtx->digest == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); } -#endif - if (wc_InitRsaKey(pubKey, heap) != 0) { - WOLFSSL_MSG("InitRsaKey failed"); - } - else if (sigSz > MAX_ENCODED_SIG_SZ) { - WOLFSSL_MSG("Verify Signature is too big"); - } - else if (wc_RsaPublicKeyDecode(key, &idx, pubKey, keySz) < 0) { - WOLFSSL_MSG("ASN Key decode error RSA"); - } - else { - XMEMCPY(plain, sig, sigSz); - ret = 0; - do { - #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, pubKey); + sigCtx->state = SIG_STATE_HASH; + } /* SIG_STATE_BEGIN */ + FALL_THROUGH; + + case SIG_STATE_HASH: + { + switch (sigOID) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = MD5h; + sigCtx->digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if ((ret = wc_Md2Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = MD2h; + sigCtx->digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHAh; + sigCtx->digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA224h; + sigCtx->digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA256h; + sigCtx->digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA512h; + sigCtx->digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buf, bufSz, sigCtx->digest)) == 0) { + sigCtx->typeH = SHA384h; + sigCtx->digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + default: + ret = HASH_TYPE_E; + WOLFSSL_MSG("Verify Signature has unsupported type"); + } + + if (ret != 0) { + goto exit_cs; + } + + sigCtx->state = SIG_STATE_KEY; + } /* SIG_STATE_HASH */ + FALL_THROUGH; + + case SIG_STATE_KEY: + { + sigCtx->keyOID = keyOID; + + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + + sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), + sigCtx->heap, DYNAMIC_TYPE_RSA); + sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + + if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap, + sigCtx->devId)) != 0) { + goto exit_cs; + } + + if (sigSz > MAX_ENCODED_SIG_SZ) { + WOLFSSL_MSG("Verify Signature is too big"); + ERROR_OUT(BUFFER_E, exit_cs); + } + + if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa, + keySz)) != 0) { + WOLFSSL_MSG("ASN Key decode error RSA"); + goto exit_cs; + } + + XMEMCPY(sigCtx->plain, sig, sigSz); + sigCtx->out = NULL; + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + sigCtx->verify = 0; + sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), + sigCtx->heap, DYNAMIC_TYPE_ECC); + if (sigCtx->key.ecc == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + + if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap, + sigCtx->devId)) < 0) { + goto exit_cs; + } + if ((ret = wc_ecc_import_x963(key, keySz, + sigCtx->key.ecc)) < 0) { + WOLFSSL_MSG("ASN Key import error ECC"); + goto exit_cs; + } + break; + } + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Verify Key type unknown"); + ret = ASN_UNKNOWN_OID_E; + break; + } /* switch (keyOID) */ + + if (ret != 0) { + goto exit_cs; + } + + sigCtx->state = SIG_STATE_DO; + } /* SIG_STATE_KEY */ + FALL_THROUGH; + + case SIG_STATE_DO: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz, + &sigCtx->out, sigCtx->key.rsa); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev; #endif - if (ret >= 0) { - ret = wc_RsaSSL_VerifyInline(plain, sigSz, &out, - pubKey); - } - } while (ret == WC_PENDING_E); - - if (ret < 0) { - WOLFSSL_MSG("Rsa SSL verify error"); + break; } - else { - verifySz = ret; - /* make sure we're right justified */ - encodedSigSz = - wc_EncodeSignature(encodedSig, digest, digestSz, typeH); - if (encodedSigSz != verifySz || - XMEMCMP(out, encodedSig, encodedSigSz) != 0) { - WOLFSSL_MSG("Rsa SSL verify match encode error"); - } - else - ret = 1; /* match */ - - #ifdef WOLFSSL_DEBUG_ENCODING - { - int x; - - printf("wolfssl encodedSig:\n"); - - for (x = 0; x < encodedSigSz; x++) { - printf("%02x ", encodedSig[x]); - if ( (x % 16) == 15) - printf("\n"); - } - - printf("\n"); - printf("actual digest:\n"); - - for (x = 0; x < verifySz; x++) { - printf("%02x ", out[x]); - if ( (x % 16) == 15) - printf("\n"); - } - - printf("\n"); - } - #endif /* WOLFSSL_DEBUG_ENCODING */ - + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest, + sigCtx->digestSz, &sigCtx->verify, sigCtx->key.ecc); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; } + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ + if (ret < 0) { + /* treat all non async RSA errors as ASN_SIG_CONFIRM_E */ + if (ret != WC_PENDING_E) + ret = ASN_SIG_CONFIRM_E; + goto exit_cs; } - wc_FreeRsaKey(pubKey); + sigCtx->state = SIG_STATE_CHECK; + } /* SIG_STATE_DO */ + FALL_THROUGH; -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - break; - } - - #endif /* NO_RSA */ - #ifdef HAVE_ECC - case ECDSAk: + case SIG_STATE_CHECK: { - int verify = 0; -#ifdef WOLFSSL_SMALL_STACK - ecc_key* pubKey; -#else - ecc_key pubKey[1]; -#endif + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + int encodedSigSz, verifySz; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif -#ifdef WOLFSSL_SMALL_STACK - pubKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (pubKey == NULL) { - WOLFSSL_MSG("Failed to allocate pubKey"); - break; /* not confirmed */ - } -#endif + verifySz = ret; - if (wc_ecc_init(pubKey) < 0) { - WOLFSSL_MSG("Failed to initialize key"); - break; /* not confirmed */ - } - if (wc_ecc_import_x963(key, keySz, pubKey) < 0) { - WOLFSSL_MSG("ASN Key import error ECC"); - } - else { - if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, - pubKey) != 0) { - WOLFSSL_MSG("ECC verify hash error"); + /* make sure we're right justified */ + encodedSigSz = wc_EncodeSignature(encodedSig, + sigCtx->digest, sigCtx->digestSz, sigCtx->typeH); + if (encodedSigSz == verifySz && + XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) { + ret = 0; + } + else { + WOLFSSL_MSG("RSA SSL verify match encode error"); + ret = ASN_SIG_CONFIRM_E; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + break; } - else if (1 != verify) { - WOLFSSL_MSG("ECC Verify didn't match"); - } else - ret = 1; /* match */ + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ECC Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ECC */ + default: + break; + } /* switch (keyOID) */ - } - wc_ecc_free(pubKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif break; - } - #endif /* HAVE_ECC */ - default: - WOLFSSL_MSG("Verify Key type unknown"); - } + } /* SIG_STATE_CHECK */ + } /* switch (sigCtx->state) */ - (void)digestSz; -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif +exit_cs: + + WOLFSSL_LEAVE("ConfirmSignature", ret); + + if (ret != WC_PENDING_E) { + FreeSignatureCtx(sigCtx); + } return ret; } @@ -4327,7 +4909,6 @@ static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) #endif /* IGNORE_NAME_CONSTRAINTS */ - static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; @@ -4343,7 +4924,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->weOwnAltNames = 1; while (length > 0) { - byte b = input[idx++]; + byte b = input[idx++]; length--; @@ -4384,7 +4965,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#ifndef IGNORE_NAME_CONSTRAINTS + #ifndef IGNORE_NAME_CONSTRAINTS else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) { DNS_entry* emailEntry; int strLen; @@ -4420,13 +5001,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) length -= strLen; idx += strLen; } -#endif /* IGNORE_NAME_CONSTRAINTS */ -#ifdef WOLFSSL_SEP + #endif /* IGNORE_NAME_CONSTRAINTS */ + #ifdef WOLFSSL_SEP else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) { int strLen; word32 lenStartIdx = idx; word32 oid = 0; + int ret; if (GetLength(input, &idx, &strLen, sz) < 0) { WOLFSSL_MSG("\tfail: other name length"); @@ -4460,14 +5042,10 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\texpected OID"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; } cert->hwType = (byte*)XMALLOC(strLen, cert->heap, @@ -4481,15 +5059,9 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwTypeSz = strLen; idx += strLen; - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\texpected Octet String"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &strLen, sz) < 0) { - WOLFSSL_MSG("\tfailed: str len"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, DYNAMIC_TYPE_X509_EXT); @@ -4503,7 +5075,7 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) cert->hwSerialNumSz = strLen; idx += strLen; } -#endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_SEP */ else { int strLen; word32 lenStartIdx = idx; @@ -4521,13 +5093,14 @@ static int DecodeAltNames(byte* input, int sz, DecodedCert* cert) return 0; } - static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length = 0; + int ret; WOLFSSL_ENTER("DecodeBasicCaConstraint"); + if (GetSequence(input, &idx, &length, sz) < 0) { WOLFSSL_MSG("\tfail: bad SEQUENCE"); return ASN_PARSE_E; @@ -4539,37 +5112,23 @@ static int DecodeBasicCaConstraint(byte* input, int sz, DecodedCert* cert) /* If the basic ca constraint is false, this extension may be named, but * left empty. So, if the length is 0, just return. */ - if (input[idx++] != ASN_BOOLEAN) - { - WOLFSSL_MSG("\tfail: constraint not BOOLEAN"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN"); + return ret; } - if (GetLength(input, &idx, &length, sz) < 0) - { - WOLFSSL_MSG("\tfail: length"); - return ASN_PARSE_E; - } - - if (input[idx++]) - cert->isCA = 1; + cert->isCA = (byte)ret; /* If there isn't any more data, return. */ if (idx >= (word32)sz) return 0; - /* Anything left should be the optional pathlength */ - if (input[idx++] != ASN_INTEGER) { - WOLFSSL_MSG("\tfail: pathlen not INTEGER"); - return ASN_PARSE_E; - } + ret = GetInteger7Bit(input, &idx, sz); + if (ret < 0) + return ret; - if (input[idx++] != 1) { - WOLFSSL_MSG("\tfail: pathlen too long"); - return ASN_PATHLEN_SIZE_E; - } - - cert->pathLength = input[idx]; + cert->pathLength = (byte)ret; cert->pathLengthSet = 1; return 0; @@ -4626,9 +5185,10 @@ static int DecodeCrlDist(byte* input, int sz, DecodedCert* cert) /* This isn't a URI, skip it. */ idx += length; } - else + else { /* This isn't a FULLNAME, skip it. */ idx += length; + } } /* Check for reasonFlags */ @@ -4687,6 +5247,7 @@ static int DecodeAuthInfo(byte* input, int sz, DecodedCert* cert) if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0) return ASN_PARSE_E; + /* Only supporting URIs right now. */ b = input[idx++]; if (GetLength(input, &idx, &length, sz) < 0) @@ -4723,15 +5284,15 @@ static int DecodeAuthKeyId(byte* input, int sz, DecodedCert* cert) return 0; } - if (GetLength(input, &idx, &length, sz) < 0) { + if (GetLength(input, &idx, &length, sz) <= 0) { WOLFSSL_MSG("\tfail: extension data length"); return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extAuthKeyIdSrc = &input[idx]; - cert->extAuthKeyIdSz = length; - #endif /* OPENSSL_EXTRA */ +#ifdef OPENSSL_EXTRA + cert->extAuthKeyIdSrc = &input[idx]; + cert->extAuthKeyIdSz = length; +#endif /* OPENSSL_EXTRA */ if (length == KEYID_SIZE) { XMEMCPY(cert->extAuthKeyId, input + idx, length); @@ -4755,15 +5316,12 @@ static int DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert) WOLFSSL_ENTER("DecodeSubjKeyId"); - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); + if (sz <= 0) return ASN_PARSE_E; - } - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; #ifdef OPENSSL_EXTRA cert->extSubjKeyIdSrc = &input[idx]; @@ -4789,20 +5347,12 @@ static int DecodeKeyUsage(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; int length; + int ret; WOLFSSL_ENTER("DecodeKeyUsage"); - if (input[idx++] != ASN_BIT_STRING) { - WOLFSSL_MSG("\tfail: key usage expected bit string"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: key usage bad length"); - return ASN_PARSE_E; - } - - /* pass the unusedBits value */ - idx++; length--; + ret = CheckBitString(input, &idx, &length, sz, 0, NULL); + if (ret != 0) + return ret; cert->extKeyUsage = (word16)(input[idx]); if (length == 2) @@ -4824,10 +5374,10 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) return ASN_PARSE_E; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageSrc = input + idx; - cert->extExtKeyUsageSz = length; - #endif +#ifdef OPENSSL_EXTRA + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; +#endif while (idx < (word32)sz) { if (GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz) < 0) @@ -4848,9 +5398,9 @@ static int DecodeExtKeyUsage(byte* input, int sz, DecodedCert* cert) break; } - #ifdef OPENSSL_EXTRA - cert->extExtKeyUsageCount++; - #endif + #ifdef OPENSSL_EXTRA + cert->extExtKeyUsageCount++; + #endif } return 0; @@ -4953,7 +5503,7 @@ static int DecodeNameConstraints(byte* input, int sz, DecodedCert* cert) return 0; } #endif /* IGNORE_NAME_CONSTRAINTS */ -#endif /* NO_ASN_TIME */ + #if defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP) @@ -5047,7 +5597,13 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) static int DecodeCertPolicy(byte* input, int sz, DecodedCert* cert) { word32 idx = 0; + word32 oldIdx; + int ret; int total_length = 0, policy_length = 0, length = 0; + #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \ + !defined(WOLFSSL_DUP_CERTPOL) + int i; + #endif WOLFSSL_ENTER("DecodeCertPolicy"); @@ -5069,17 +5625,11 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) return ASN_PARSE_E; } - if (input[idx++] != ASN_OBJECT_ID) { - WOLFSSL_MSG("\tCertPolicy isn't OID"); - return ASN_PARSE_E; - } - policy_length--; - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tGet CertPolicy length failed"); - return ASN_PARSE_E; - } - policy_length--; + oldIdx = idx; + ret = GetASNObjectId(input, &idx, &length, sz); + if (ret != 0) + return ret; + policy_length -= idx - oldIdx; if (length > 0) { /* Verify length won't overrun buffer */ @@ -5105,6 +5655,22 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) WOLFSSL_MSG("\tCouldn't decode CertPolicy"); return ASN_PARSE_E; } + #ifndef WOLFSSL_DUP_CERTPOL + /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST + * NOT appear more than once in a certificate policies + * extension". This is a sanity check for duplicates. + * extCertPolicies should only have OID values, additional + * qualifiers need to be stored in a seperate array. */ + for (i = 0; i < cert->extCertPoliciesNb; i++) { + if (XMEMCMP(cert->extCertPolicies[i], + cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ) == 0) { + WOLFSSL_MSG("Duplicate policy OIDs not allowed"); + WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted"); + return CERTPOLICIES_E; + } + } + #endif /* !defined(WOLFSSL_DUP_CERTPOL) */ cert->extCertPoliciesNb++; #else WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); @@ -5123,7 +5689,6 @@ static int DecodePolicyOID(char *out, word32 outSz, byte *in, word32 inSz) } #endif /* WOLFSSL_SEP */ -#ifndef NO_ASN_TIME static int DecodeCertExtensions(DecodedCert* cert) /* * Processing the Certificate Extensions. This does not modify the current @@ -5174,25 +5739,20 @@ static int DecodeCertExtensions(DecodedCert* cert) /* check for critical flag */ critical = 0; if (input[idx] == ASN_BOOLEAN) { - int boolLength = 0; - idx++; - if (GetLength(input, &idx, &boolLength, sz) < 0) { - WOLFSSL_MSG("\tfail: critical boolean length"); - return ASN_PARSE_E; + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; } - if (input[idx++]) - critical = 1; + + critical = (byte)ret; } /* process the extension based on the OID */ - if (input[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: bad OCTET STRING"); + return ret; } switch (oid) { @@ -5206,11 +5766,19 @@ static int DecodeCertExtensions(DecodedCert* cert) break; case CRL_DIST_OID: + #ifdef OPENSSL_EXTRA + cert->extCRLdistSet = 1; + cert->extCRLdistCrit = critical; + #endif if (DecodeCrlDist(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; case AUTH_INFO_OID: + #ifdef OPENSSL_EXTRA + cert->extAuthInfoSet = 1; + cert->extAuthInfoCrit = critical; + #endif if (DecodeAuthInfo(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; @@ -5238,6 +5806,18 @@ static int DecodeCertExtensions(DecodedCert* cert) #ifdef OPENSSL_EXTRA cert->extSubjKeyIdCrit = critical; #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.2 + * stating that conforming CA's must mark this extension + * as non-critical. When parsing extensions check that + * certificate was made in compliance with this. */ + if (critical) { + WOLFSSL_MSG("Critical Subject Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif + if (DecodeSubjKeyId(&input[idx], length, cert) < 0) return ASN_PARSE_E; break; @@ -5306,7 +5886,6 @@ static int DecodeCertExtensions(DecodedCert* cert) return criticalFail ? ASN_CRIT_EXT_E : 0; } - int ParseCert(DecodedCert* cert, int type, int verify, void* cm) { int ret; @@ -5340,8 +5919,6 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } -#endif /* !NO_ASN_TIME */ - /* from SSL proper, for locking can't do find here anymore */ #ifdef __cplusplus @@ -5377,130 +5954,143 @@ Signer* GetCAByName(void* signers, byte* hash) #endif /* WOLFCRYPT_ONLY || NO_CERTS */ -#ifndef NO_ASN_TIME int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) { - word32 confirmOID; - int ret; - int badDate = 0; + int ret = 0; + int badDate = 0; int criticalExt = 0; + word32 confirmOID; - if ((ret = DecodeToKey(cert, verify)) < 0) { - if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) - badDate = ret; - else - return ret; + if (cert == NULL) { + return BAD_FUNC_ARG; } - WOLFSSL_MSG("Parsed Past Key"); - - if (cert->srcIdx < cert->sigIndex) { - #ifndef ALLOW_V1_EXTENSIONS - if (cert->version < 2) { - WOLFSSL_MSG(" v1 and v2 certs not allowed extensions"); - return ASN_VERSION_E; - } - #endif - /* save extensions */ - cert->extensions = &cert->source[cert->srcIdx]; - cert->extensionsSz = cert->sigIndex - cert->srcIdx; - cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - - if ((ret = DecodeCertExtensions(cert)) < 0) { - if (ret == ASN_CRIT_EXT_E) - criticalExt = ret; + if (cert->sigCtx.state == SIG_STATE_BEGIN) { + if ((ret = DecodeToKey(cert, verify)) < 0) { + if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) + badDate = ret; else return ret; } - /* advance past extensions */ - cert->srcIdx = cert->sigIndex; - } + WOLFSSL_MSG("Parsed Past Key"); - if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, - oidSigType, cert->maxIdx)) < 0) - return ret; + if (cert->srcIdx < cert->sigIndex) { + #ifndef ALLOW_V1_EXTENSIONS + if (cert->version < 2) { + WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions"); + return ASN_VERSION_E; + } + #endif - if ((ret = GetSignature(cert)) < 0) - return ret; + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = cert->sigIndex - cert->srcIdx; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ - if (confirmOID != cert->signatureOID) - return ASN_SIG_OID_E; + if ((ret = DecodeCertExtensions(cert)) < 0) { + if (ret == ASN_CRIT_EXT_E) + criticalExt = ret; + else + return ret; + } + + /* advance past extensions */ + cert->srcIdx = cert->sigIndex; + } + + if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, + oidSigType, cert->maxIdx)) < 0) + return ret; + + if ((ret = GetSignature(cert)) < 0) + return ret; + + if (confirmOID != cert->signatureOID) + return ASN_SIG_OID_E; #ifndef NO_SKID - if (cert->extSubjKeyIdSet == 0 - && cert->publicKey != NULL && cert->pubKeySize > 0) { + if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL && + cert->pubKeySize > 0) { #ifdef NO_SHA ret = wc_Sha256Hash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); #else ret = wc_ShaHash(cert->publicKey, cert->pubKeySize, cert->extSubjKeyId); - #endif + #endif /* NO_SHA */ if (ret != 0) return ret; } - #endif + #endif /* !NO_SKID */ - if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { - Signer* ca = NULL; + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + cert->ca = NULL; #ifndef NO_SKID if (cert->extAuthKeyIdSet) - ca = GetCA(cm, cert->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, cert->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, cert->issuerHash); - #endif /* NO SKID */ - WOLFSSL_MSG("About to verify certificate signature"); + cert->ca = GetCA(cm, cert->extAuthKeyId); + if (cert->ca == NULL) + cert->ca = GetCAByName(cm, cert->issuerHash); + #else + cert->ca = GetCA(cm, cert->issuerHash); + #endif /* !NO_SKID */ - if (ca) { - if (cert->isCA) { - if (ca->pathLengthSet) { - if (ca->pathLength == 0) { - WOLFSSL_MSG("CA with path length 0 signing a CA"); - return ASN_PATHLEN_INV_E; - } - if (cert->pathLengthSet && - cert->pathLength >= ca->pathLength) { + WOLFSSL_MSG("About to verify certificate signature"); + if (cert->ca) { + if (cert->isCA) { + if (cert->ca->pathLengthSet) { + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("CA with path length 0 signing a CA"); + return ASN_PATHLEN_INV_E; + } + if (cert->pathLengthSet && + cert->pathLength >= cert->ca->pathLength) { - WOLFSSL_MSG("CA signing CA with longer path length"); - return ASN_PATHLEN_INV_E; + WOLFSSL_MSG("CA signing CA with longer path length"); + return ASN_PATHLEN_INV_E; + } } } + + #ifdef HAVE_OCSP + /* Need the CA's public key hash for OCSP */ + #ifdef NO_SHA + ret = wc_Sha256Hash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #else + ret = wc_ShaHash(cert->ca->publicKey, cert->ca->pubKeySize, + cert->issuerKeyHash); + #endif /* NO_SHA */ + if (ret != 0) + return ret; + #endif /* HAVE_OCSP */ } + } + } -#ifdef HAVE_OCSP - /* Need the ca's public key hash for OCSP */ - #ifdef NO_SHA - ret = wc_Sha256Hash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #else /* NO_SHA */ - ret = wc_ShaHash(ca->publicKey, ca->pubKeySize, - cert->issuerKeyHash); - #endif /* NO_SHA */ - if (ret != 0) - return ret; -#endif /* HAVE_OCSP */ - + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + if (cert->ca) { if (verify == VERIFY) { /* try to confirm/verify signature */ - if (!ConfirmSignature(cert->source + cert->certBegin, - cert->sigIndex - cert->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - cert->signature, cert->sigLength, cert->signatureOID, - cert->heap)) { - WOLFSSL_MSG("Confirm signature failed"); - return ASN_SIG_CONFIRM_E; + if ((ret = ConfirmSignature(&cert->sigCtx, + cert->source + cert->certBegin, + cert->sigIndex - cert->certBegin, + cert->ca->publicKey, cert->ca->pubKeySize, + cert->ca->keyOID, cert->signature, + cert->sigLength, cert->signatureOID)) != 0) { + if (ret != WC_PENDING_E) { + WOLFSSL_MSG("Confirm signature failed"); + } + return ret; } - #ifndef IGNORE_NAME_CONSTRAINTS + #ifndef IGNORE_NAME_CONSTRAINTS /* check that this cert's name is permitted by the signer's * name constraints */ - if (!ConfirmNameConstraints(ca, cert)) { + if (!ConfirmNameConstraints(cert->ca, cert)) { WOLFSSL_MSG("Confirm name constraint failed"); return ASN_NAME_INVALID_E; } - #endif /* IGNORE_NAME_CONSTRAINTS */ + #endif /* IGNORE_NAME_CONSTRAINTS */ } } else { @@ -5516,9 +6106,8 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (criticalExt != 0) return criticalExt; - return 0; + return ret; } -#endif /* !NO_ASN_TIME */ /* Create and init an new signer */ Signer* MakeSigner(void* heap) @@ -5630,7 +6219,7 @@ WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) if (header) { output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; - output[i++] = ASN_BIT_STRING; + output[i++] = 3; } output[i++] = ASN_INTEGER; output[i++] = 0x01; @@ -5673,7 +6262,7 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, byte* serial, int* serialSz, word32 maxIdx) { int result = 0; - byte b; + int ret; WOLFSSL_ENTER("GetSerialNumber"); @@ -5686,42 +6275,19 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, WOLFSSL_MSG("Bad idx first"); return BUFFER_E; } - b = input[*inOutIdx]; - *inOutIdx += 1; - if (b != ASN_INTEGER) { - WOLFSSL_MSG("Expecting Integer"); - return ASN_PARSE_E; - } + ret = GetASNInt(input, inOutIdx, serialSz, maxIdx); + if (ret != 0) + return ret; - if (GetLength(input, inOutIdx, serialSz, maxIdx) < 0) { - return ASN_PARSE_E; - } - - /* serial size check */ - if (*serialSz < 0 || *serialSz > EXTERNAL_SERIAL_SIZE) { + if (*serialSz > EXTERNAL_SERIAL_SIZE) { WOLFSSL_MSG("Serial size bad"); return ASN_PARSE_E; } - /* serial size check against max index */ - if ((*inOutIdx + *serialSz) > maxIdx) { - WOLFSSL_MSG("Bad idx serial"); - return BUFFER_E; - } - - /* only check padding and return serial if length is greater than 1 */ - if (*serialSz > 0) { - /* skip padding */ - if (input[*inOutIdx] == 0x00) { - *serialSz -= 1; - *inOutIdx += 1; - } - - /* return serial */ - XMEMCPY(serial, &input[*inOutIdx], *serialSz); - *inOutIdx += *serialSz; - } + /* return serial */ + XMEMCPY(serial, &input[*inOutIdx], *serialSz); + *inOutIdx += *serialSz; return result; } @@ -5734,6 +6300,8 @@ const char* BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; const char* END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; const char* BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; const char* END_DH_PARAM = "-----END DH PARAMETERS-----"; +const char* BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----"; +const char* END_DSA_PARAM = "-----END DSA PARAMETERS-----"; const char* BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; const char* END_X509_CRL = "-----END X509 CRL-----"; const char* BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; @@ -5749,7 +6317,7 @@ const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) /* Used for compatibility API */ int wc_DerToPem(const byte* der, word32 derSz, @@ -5853,15 +6421,33 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, /* extra header information for encrypted key */ if (cipher_info != NULL) { + size_t cipherInfoStrLen = XSTRLEN((char*)cipher_info); + if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (23+10+2)) + cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (23+10+2); + XSTRNCAT(header, "Proc-Type: 4,ENCRYPTED\n", 23); XSTRNCAT(header, "DEK-Info: ", 10); - XSTRNCAT(header, (char*)cipher_info, XSTRLEN((char*)cipher_info)); + XSTRNCAT(header, (char*)cipher_info, cipherInfoStrLen); XSTRNCAT(header, "\n\n", 2); } headerLen = (int)XSTRLEN(header); footerLen = (int)XSTRLEN(footer); + /* if null output and 0 size passed in then return size needed */ + if (!output && outSz == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + outLen = 0; + if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) + != LENGTH_ONLY_E) { + return err; + } + return headerLen + footerLen + outLen; + } + if (!der || !output) { #ifdef WOLFSSL_SMALL_STACK XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -5930,15 +6516,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte e[MAX_RSA_E_SZ]; #endif byte seq[MAX_SEQ_SZ]; - byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + byte bitString[1 + MAX_LENGTH_SZ + 1]; int nSz; int eSz; int seqSz; - int lenSz; + int bitStringSz; int idx; - int rawLen; - int leadingBit; - int err; if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) return BAD_FUNC_ARG; @@ -5951,37 +6534,15 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->n); - rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; + nSz = SetASNIntRSA(key->n, n); #else - leadingBit = mp_leading_bit(&key->n); - rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); #endif - n[0] = ASN_INTEGER; - nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ - - if ( (nSz + rawLen) <= MAX_RSA_INT_SZ) { - if (leadingBit) - n[nSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); -#else - err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); -#endif - if (err == MP_OKAY) - nSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MP_TO_E; - } - } - else { + if (nSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return nSz; } /* e */ @@ -5996,39 +6557,16 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, #endif #ifdef HAVE_USER_RSA - leadingBit = wc_Rsa_leading_bit(key->e); - rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; + eSz = SetASNIntRSA(key->e, e); #else - leadingBit = mp_leading_bit(&key->e); - rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); #endif - e[0] = ASN_INTEGER; - eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ - - if ( (eSz + rawLen) < MAX_RSA_E_SZ) { - if (leadingBit) - e[eSz] = 0; -#ifdef HAVE_USER_RSA - err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); -#else - err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); -#endif - if (err == MP_OKAY) - eSz += rawLen; - else { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MP_TO_E; - } - } - else { + if (eSz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BUFFER_E; + return eSz; } seqSz = SetSequence(nSz + eSz, seq); @@ -6058,14 +6596,12 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, byte algo[MAX_ALGO_SZ]; #endif algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); - lenSz = SetLength(seqSz + nSz + eSz + 1, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); /* check output size */ - if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { #ifdef WOLFSSL_SMALL_STACK XFREE(n, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(e, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -6079,10 +6615,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, XMEMCPY(output + idx, algo, algoSz); idx += algoSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; #ifdef WOLFSSL_SMALL_STACK XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -6107,8 +6641,8 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, return idx; } -#endif /* !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || - defined(WOLFSSL_KEY_GEN)) */ +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) @@ -6155,7 +6689,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) { word32 seqSz, verSz, rawLen, intTotalLen = 0; word32 sizes[RSA_INTS]; - int i, j, outLen, ret = 0, lbit; + int i, j, outLen, ret = 0, mpSz; byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -6174,10 +6708,7 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) for (i = 0; i < RSA_INTS; i++) { mp_int* keyInt = GetRsaInt(key, i); - /* leading zero */ - lbit = mp_leading_bit(keyInt); - rawLen = mp_unsigned_bin_size(keyInt) + lbit; - + rawLen = mp_unsigned_bin_size(keyInt) + 1; tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_RSA); if (tmps[i] == NULL) { @@ -6185,30 +6716,12 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) break; } - tmps[i][0] = ASN_INTEGER; - sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ - - if (sizes[i] <= MAX_SEQ_SZ) { - int err; - - /* leading zero */ - if (lbit) - tmps[i][sizes[i]-1] = 0x00; - - err = mp_to_unsigned_bin(keyInt, tmps[i] + sizes[i]); - if (err == MP_OKAY) { - sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ - intTotalLen += sizes[i]; - } - else { - ret = err; - break; - } - } - else { - ret = ASN_INPUT_E; + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); + if (mpSz < 0) { + ret = mpSz; break; } + intTotalLen += (sizes[i] = mpSz); } if (ret != 0) { @@ -6247,23 +6760,11 @@ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) return SetRsaPublicKey(output, key, inLen, 1); } -#endif /* WOLFSSL_KEY_GEN && !NO_RSA */ +#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */ #if defined(WOLFSSL_CERT_GEN) && !defined(NO_RSA) - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - /* Initialize and Set Certificate defaults: version = 3 (0x2) serial = 0 @@ -6421,10 +6922,10 @@ static int SetSerial(const byte* serial, byte* output) /* Write a public ECC key to output */ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) { - byte len[MAX_LENGTH_SZ + TRAILING_ZERO]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; int algoSz; int curveSz; - int lenSz; + int bitStringSz; int idx; word32 pubSz = ECC_BUFSIZE; #ifdef WOLFSSL_SMALL_STACK @@ -6479,11 +6980,9 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) #endif algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz); - lenSz = SetLength(pubSz + TRAILING_ZERO, len); - len[lenSz++] = 0; /* trailing 0 */ + bitStringSz = SetBitString(pubSz, 0, bitString); - /* write, 1 is for ASN_BIT_STRING */ - idx = SetSequence(pubSz + curveSz + lenSz + 1 + algoSz, output); + idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output); /* algo */ XMEMCPY(output + idx, algo, algoSz); idx += algoSz; @@ -6491,10 +6990,8 @@ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) XMEMCPY(output + idx, curve, curveSz); idx += curveSz; /* bit string */ - output[idx++] = ASN_BIT_STRING; - /* length */ - XMEMCPY(output + idx, len, lenSz); - idx += lenSz; + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; } else idx = 0; @@ -6897,7 +7394,7 @@ static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, /* sequence, + 1 => byte to put value size */ idx = SetSequence(inSz + oidSz + 1, out); - if (outSz < idx + inSz + oidSz + 1) + if ((idx + inSz + oidSz + 1) > outSz) return BUFFER_E; XMEMCPY(out+idx, oid, oidSz); @@ -6910,9 +7407,9 @@ static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, /* encode Subject Key Identifier, return total bytes written * RFC5280 : non-critical */ -static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) +static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length) { - byte skid_len[MAX_LENGTH_SZ]; + byte skid_len[1 + MAX_LENGTH_SZ]; byte skid_enc_len[MAX_LENGTH_SZ]; int idx = 0, skid_lenSz, skid_enc_lenSz; static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; @@ -6920,20 +7417,19 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) if (output == NULL || input == NULL) return BAD_FUNC_ARG; - /* length of value */ - skid_lenSz = SetLength(length, skid_len); + /* Octet String header */ + skid_lenSz = SetOctetString(length, skid_len); /* length of encoded value */ - skid_enc_lenSz = SetLength(length + skid_lenSz + 1, skid_enc_len); + skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len); if (outSz < 3) return BUFFER_E; - /* sequence, + 1 => byte to put type size */ - idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz+1, + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz, output); - if (outSz < length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz + 1) + if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz) return BUFFER_E; /* put oid */ @@ -6944,10 +7440,7 @@ static int SetSKID(byte* output, word32 outSz, byte *input, word32 length) XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz); idx += skid_enc_lenSz; - /* put type */ - output[idx++] = ASN_OCTET_STRING; - - /* put value len */ + /* put octet header */ XMEMCPY(output+idx, skid_len, skid_lenSz); idx += skid_lenSz; @@ -6965,27 +7458,26 @@ static int SetAKID(byte* output, word32 outSz, { byte *enc_val; int ret, enc_valSz; - static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04}; + static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 }; static const byte akid_cs[] = { 0x80 }; if (output == NULL || input == NULL) return BAD_FUNC_ARG; - enc_val = (byte *)XMALLOC(length+3+sizeof(akid_cs), heap, - DYNAMIC_TYPE_TMP_BUFFER); + enc_valSz = length + 3 + sizeof(akid_cs); + enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (enc_val == NULL) return MEMORY_E; /* sequence for ContentSpec & value */ - enc_valSz = SetOidValue(enc_val, length+3+sizeof(akid_cs), - akid_cs, sizeof(akid_cs), input, length); - if (enc_valSz == 0) { - XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } + ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs), + input, length); + if (ret > 0) { + enc_valSz = ret; - ret = SetOidValue(output, outSz, akid_oid, - sizeof(akid_oid), enc_val, enc_valSz); + ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid), + enc_val, enc_valSz); + } XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; @@ -6996,42 +7488,16 @@ static int SetAKID(byte* output, word32 outSz, static int SetKeyUsage(byte* output, word32 outSz, word16 input) { byte ku[5]; - int unusedBits = 0; + int idx; static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04}; if (output == NULL) return BAD_FUNC_ARG; - /* Key Usage is a BitString */ - ku[0] = ASN_BIT_STRING; - - /* put the Bit String size */ - if (input > 255) { - ku[1] = (byte)3; - - /* compute unused bits */ - while (((((input >> 8) & 0xff) >> unusedBits) & 0x01) == 0) - unusedBits++; - } - else { - ku[1] = (byte)2; - - /* compute unused bits */ - while (((input >> unusedBits) & 0x01) == 0) - unusedBits++; - } - - /* put unused bits value */ - ku[2] = (byte)unusedBits; - - /* compute byte value */ - ku[3] = (byte)(input & 0xff); - if (input > 255) - ku[4] = (byte)((input >> 8) & 0xff); - + idx = SetBitString16Bit(input, ku); return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), - ku, (int)ku[1]+2); + ku, idx); } /* Encode OID string representation to ITU-T X.690 format */ @@ -7217,7 +7683,7 @@ int SetName(byte* output, word32 outputSz, CertName* name) const char* nameStr = GetOneName(name, i); if (nameStr) { /* bottom up */ - byte firstLen[MAX_LENGTH_SZ]; + byte firstLen[1 + MAX_LENGTH_SZ]; byte secondLen[MAX_LENGTH_SZ]; byte sequence[MAX_SEQ_SZ]; byte set[MAX_SET_SZ]; @@ -7245,16 +7711,15 @@ int SetName(byte* output, word32 outputSz, CertName* name) if (email) { thisLen += EMAIL_JOINT_LEN; thisLen ++; /* id type */ - firstSz = SetLength(EMAIL_JOINT_LEN, firstLen); + firstSz = SetObjectId(EMAIL_JOINT_LEN, firstLen); } else { thisLen++; /* str type */ thisLen++; /* id type */ thisLen += JOINT_LEN; - firstSz = SetLength(JOINT_LEN + 1, firstLen); + firstSz = SetObjectId(JOINT_LEN + 1, firstLen); } thisLen += firstSz; - thisLen++; /* object id */ seqSz = SetSequence(thisLen, sequence); thisLen += seqSz; @@ -7277,8 +7742,6 @@ int SetName(byte* output, word32 outputSz, CertName* name) XMEMCPY(names[i].encoded + idx, sequence, seqSz); idx += seqSz; /* asn object id */ - names[i].encoded[idx++] = ASN_OBJECT_ID; - /* first length */ XMEMCPY(names[i].encoded + idx, firstLen, firstSz); idx += firstSz; if (email) { @@ -7480,6 +7943,8 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, if (cert->skidSz > (int)sizeof(der->skid)) return SKID_E; + /* Note: different skid buffers sizes for der (MAX_KID_SZ) and + cert (CTC_MAX_SKID_SIZE). */ der->skidSz = SetSKID(der->skid, sizeof(der->skid), cert->skid, cert->skidSz); if (der->skidSz <= 0) @@ -7651,28 +8116,14 @@ static int WriteCertBody(DerCert* der, byte* buffer) /* Make RSA signature from buffer (sz), write to sig (sigSz) */ -static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, - RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, - int sigAlgoType) +static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, + int sigAlgoType, void* heap) { - int encSigSz, digestSz, typeH = 0, ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* digest; -#else - byte digest[WC_MAX_DIGEST_SIZE]; /* max size */ -#endif -#ifdef WOLFSSL_SMALL_STACK - byte* encSig; -#else - byte encSig[MAX_DER_DIGEST_SZ]; -#endif + int digestSz = 0, typeH = 0, ret = 0; - (void)digest; (void)digestSz; - (void)encSig; - (void)encSigSz; (void)typeH; - (void)buffer; (void)sz; (void)sig; @@ -7681,119 +8132,141 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, (void)eccKey; (void)rng; -#ifdef WOLFSSL_SMALL_STACK - digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) - return 0; /* not confirmed */ -#endif + switch (certSignCtx->state) { + case CERTSIGN_STATE_BEGIN: + case CERTSIGN_STATE_DIGEST: - switch (sigAlgoType) { - #ifndef NO_MD5 - case CTC_MD5wRSA: - if ((ret = wc_Md5Hash(buffer, sz, digest)) == 0) { - typeH = MD5h; - digestSz = MD5_DIGEST_SIZE; + certSignCtx->state = CERTSIGN_STATE_DIGEST; + certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->digest == NULL) { + ret = MEMORY_E; goto exit_ms; } - break; - #endif - #ifndef NO_SHA - case CTC_SHAwRSA: - case CTC_SHAwECDSA: - if ((ret = wc_ShaHash(buffer, sz, digest)) == 0) { - typeH = SHAh; - digestSz = SHA_DIGEST_SIZE; + + switch (sigAlgoType) { + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = MD5h; + digestSz = MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHAh; + digestSz = SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA224h; + digestSz = SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA256h; + digestSz = SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA384h; + digestSz = SHA384_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buffer, sz, certSignCtx->digest)) == 0) { + typeH = SHA512h; + digestSz = SHA512_DIGEST_SIZE; + } + break; + #endif + default: + WOLFSSL_MSG("MakeSignautre called with unsupported type"); + ret = ALGO_ID_E; } - break; - #endif - #ifdef WOLFSSL_SHA224 - case CTC_SHA224wRSA: - case CTC_SHA224wECDSA: - if ((ret = wc_Sha224Hash(buffer, sz, digest)) == 0) { - typeH = SHA224h; - digestSz = SHA224_DIGEST_SIZE; + + /* set next state, since WC_PENDING rentry for these are not "call again" */ + certSignCtx->state = CERTSIGN_STATE_ENCODE; + if (ret != 0) { + goto exit_ms; } - break; - #endif - #ifndef NO_SHA256 - case CTC_SHA256wRSA: - case CTC_SHA256wECDSA: - if ((ret = wc_Sha256Hash(buffer, sz, digest)) == 0) { - typeH = SHA256h; - digestSz = SHA256_DIGEST_SIZE; + FALL_THROUGH; + + case CERTSIGN_STATE_ENCODE: + #ifndef NO_RSA + if (rsaKey) { + certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->encSig == NULL) { + ret = MEMORY_E; goto exit_ms; + } + + /* signature */ + certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig, + certSignCtx->digest, digestSz, typeH); } - break; - #endif - #ifdef WOLFSSL_SHA384 - case CTC_SHA384wRSA: - case CTC_SHA384wECDSA: - if ((ret = wc_Sha384Hash(buffer, sz, digest)) == 0) { - typeH = SHA384h; - digestSz = SHA384_DIGEST_SIZE; + #endif /* !NO_RSA */ + FALL_THROUGH; + + case CERTSIGN_STATE_DO: + certSignCtx->state = CERTSIGN_STATE_DO; + ret = ALGO_ID_E; /* default to error */ + + #ifndef NO_RSA + if (rsaKey) { + /* signature */ + ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz, + sig, sigSz, rsaKey, rng); } - break; - #endif - #ifdef WOLFSSL_SHA512 - case CTC_SHA512wRSA: - case CTC_SHA512wECDSA: - if ((ret = wc_Sha512Hash(buffer, sz, digest)) == 0) { - typeH = SHA512h; - digestSz = SHA512_DIGEST_SIZE; + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + if (!rsaKey && eccKey) { + word32 outSz = sigSz; + + ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz, + sig, &outSz, rng, eccKey); + if (ret == 0) + ret = outSz; } + #endif /* HAVE_ECC */ break; - #endif - default: - WOLFSSL_MSG("MakeSignautre called with unsupported type"); - ret = ALGO_ID_E; } - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif +exit_ms: + + if (ret == WC_PENDING_E) { return ret; } -#ifdef WOLFSSL_SMALL_STACK - encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (encSig == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - ret = ALGO_ID_E; - #ifndef NO_RSA if (rsaKey) { - /* signature */ - encSigSz = wc_EncodeSignature(encSig, digest, digestSz, typeH); - ret = 0; - do { -#if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_RsaAsyncWait(ret, rsaKey); -#endif - if (ret >= 0) { - ret = wc_RsaSSL_Sign(encSig, encSigSz, sig, sigSz, rsaKey, rng); - } - } while (ret == WC_PENDING_E); + XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER); } -#endif +#endif /* !NO_RSA */ -#ifdef HAVE_ECC - if (!rsaKey && eccKey) { - word32 outSz = sigSz; - ret = wc_ecc_sign_hash(digest, digestSz, sig, &outSz, rng, eccKey); + XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->digest = NULL; - if (ret == 0) - ret = outSz; - } -#endif - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* reset state */ + certSignCtx->state = CERTSIGN_STATE_BEGIN; return ret; } @@ -7810,10 +8283,7 @@ static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, /* algo */ idx += SetAlgoID(sigAlgoType, buffer + idx, oidSigType, 0); /* bit string */ - buffer[idx++] = ASN_BIT_STRING; - /* length */ - idx += SetLength(sigSz + 1, buffer + idx); - buffer[idx++] = 0; /* trailing 0 */ + idx += SetBitString(sigSz, 0, buffer + idx); /* signature */ XMEMCPY(buffer + idx, sig, sigSz); idx += sigSz; @@ -8122,7 +8592,7 @@ static int WriteCertReqBody(DerCert* der, byte* buffer) /* extensions */ if (der->extensionsSz) { XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, - sizeof(der->extensions))); + (int)sizeof(der->extensions))); idx += der->extensionsSz; } @@ -8170,35 +8640,59 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) { - int sigSz; -#ifdef WOLFSSL_SMALL_STACK - byte* sig; -#else - byte sig[MAX_ENCODED_SIG_SZ]; + int sigSz = 0; + void* heap = NULL; + CertSignCtx* certSignCtx = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + CertSignCtx certSignCtx_lcl; + certSignCtx = &certSignCtx_lcl; + XMEMSET(certSignCtx, 0, sizeof(CertSignCtx)); #endif if (requestSz < 0) return requestSz; -#ifdef WOLFSSL_SMALL_STACK - sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sig == NULL) - return MEMORY_E; + /* locate ctx */ + if (rsaKey) { + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &rsaKey->certSignCtx; + #endif + heap = rsaKey->heap; + } + else if (eccKey) { + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &eccKey->certSignCtx; + #endif + heap = eccKey->heap; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + if (certSignCtx == NULL) { + return BAD_FUNC_ARG; + } #endif - sigSz = MakeSignature(buffer, requestSz, sig, MAX_ENCODED_SIG_SZ, rsaKey, - eccKey, rng, sType); + if (certSignCtx->sig == NULL) { + certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->sig == NULL) + return MEMORY_E; + } + + sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, rng, sType, heap); + if (sigSz == WC_PENDING_E) + return sigSz; if (sigSz >= 0) { if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) sigSz = BUFFER_E; else - sigSz = AddSignature(buffer, requestSz, sig, sigSz, sType); + sigSz = AddSignature(buffer, requestSz, certSignCtx->sig, sigSz, sType); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->sig = NULL; return sigSz; } @@ -8436,22 +8930,31 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) #endif /* decode certificate and get SKID that will be AKID of current cert */ - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); if (ret != 0) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } /* Subject Key Id not found !! */ if (decoded->extSubjKeyIdSet == 0) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ASN_NO_SKID; } /* SKID invalid size */ if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return MEMORY_E; } @@ -8460,6 +8963,10 @@ int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) cert->akidSz = KEYID_SIZE; FreeDecodedCert(decoded); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; } @@ -8500,6 +9007,7 @@ int wc_SetAuthKeyId(Cert *cert, const char* file) /* Set KeyUsage from human readable string */ int wc_SetKeyUsage(Cert *cert, const char *value) { + int ret = 0; char *token, *str, *ptr; word32 len; @@ -8541,14 +9049,16 @@ int wc_SetKeyUsage(Cert *cert, const char *value) cert->keyUsage |= KEYUSE_ENCIPHER_ONLY; else if (!XSTRNCASECMP(token, "decipherOnly", len)) cert->keyUsage |= KEYUSE_DECIPHER_ONLY; - else - return KEYUSAGE_E; + else { + ret = KEYUSAGE_E; + break; + } token = XSTRTOK(NULL, ",", &ptr); } XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - return 0; + return ret; } #endif /* WOLFSSL_CERT_EXT */ @@ -8575,7 +9085,7 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8671,7 +9181,7 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8727,7 +9237,7 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return MEMORY_E; #endif - InitDecodedCert(decoded, (byte*)der, derSz, 0); + InitDecodedCert(decoded, (byte*)der, derSz, NULL); ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { @@ -8906,8 +9416,8 @@ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) { word32 idx = 0; - word32 rSz; /* encoding size */ - word32 sSz; + int rSz; /* encoding size */ + int sSz; word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ /* If the leading bit on the INTEGER is a 1, add a leading zero */ @@ -8915,33 +9425,24 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) int sLeadingZero = mp_leading_bit(s); int rLen = mp_unsigned_bin_size(r); /* big int size */ int sLen = mp_unsigned_bin_size(s); - int err; if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ - return BAD_FUNC_ARG; + return BUFFER_E; - idx = SetSequence(rLen+rLeadingZero+sLen+sLeadingZero+headerSz, out); + idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out); /* store r */ - out[idx++] = ASN_INTEGER; - rSz = SetLength(rLen + rLeadingZero, &out[idx]); + rSz = SetASNIntMP(r, -1, &out[idx]); + if (rSz < 0) + return rSz; idx += rSz; - if (rLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(r, &out[idx]); - if (err != MP_OKAY) return err; - idx += rLen; /* store s */ - out[idx++] = ASN_INTEGER; - sSz = SetLength(sLen + sLeadingZero, &out[idx]); + sSz = SetASNIntMP(s, -1, &out[idx]); + if (sSz < 0) + return sSz; idx += sSz; - if (sLeadingZero) - out[idx++] = 0; - err = mp_to_unsigned_bin(s, &out[idx]); - if (err != MP_OKAY) return err; - idx += sLen; *outLen = idx; @@ -8955,17 +9456,21 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) word32 idx = 0; int len = 0; - if (GetSequence(sig, &idx, &len, sigLen) < 0) + if (GetSequence(sig, &idx, &len, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if ((word32)len > (sigLen - idx)) + if ((word32)len > (sigLen - idx)) { return ASN_ECC_KEY_E; + } - if (GetInt(r, sig, &idx, sigLen) < 0) + if (GetInt(r, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } - if (GetInt(s, sig, &idx, sigLen) < 0) + if (GetInt(s, sig, &idx, sigLen) < 0) { return ASN_ECC_KEY_E; + } return 0; } @@ -8974,9 +9479,9 @@ int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { - word32 oidSum = 0; + word32 oidSum; int version, length; - int privSz, pubSz; + int privSz, pubSz = 0; byte b; int ret = 0; int curve_id = ECC_CURVE_DEF; @@ -8987,6 +9492,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, byte priv[ECC_MAXSIZE+1]; byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ #endif + byte* pubData = NULL; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9027,32 +9533,26 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, XMEMCPY(priv, &input[*inOutIdx], privSz); *inOutIdx += length; + if ((*inOutIdx + 1) > inSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + /* prefix 0, may have */ b = input[*inOutIdx]; if (b == ECC_PREFIX_0) { *inOutIdx += 1; - if (GetLength(input, inOutIdx, &length, inSz) < 0) + if (GetLength(input, inOutIdx, &length, inSz) <= 0) ret = ASN_PARSE_E; else { - /* object id */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_OBJECT_ID) { - ret = ASN_OBJECT_ID_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { - ret = ASN_PARSE_E; - } - else { - while(length--) { - oidSum += input[*inOutIdx]; - *inOutIdx += 1; - } - if ((ret = CheckCurve(oidSum)) < 0) { + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret == 0) { + if ((ret = CheckCurve(oidSum)) < 0) ret = ECC_CURVE_OID_E; - } else { curve_id = ret; ret = 0; @@ -9061,7 +9561,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, } } - if (ret == 0) { + if (ret == 0 && (*inOutIdx + 1) < inSz) { /* prefix 1 */ b = input[*inOutIdx]; *inOutIdx += 1; @@ -9069,46 +9569,30 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, if (b != ECC_PREFIX_1) { ret = ASN_ECC_KEY_E; } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { + else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { ret = ASN_PARSE_E; } else { /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_BIT_STRING) { - ret = ASN_BITSTR_E; - } - else if (GetLength(input, inOutIdx, &length, inSz) < 0) { - ret = ASN_PARSE_E; - } - else if (length <= 0) { - /* pubkey needs some size */ - ret = ASN_INPUT_E; - } - else { - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != 0x00) { - ret = ASN_EXPECT_0_E; - } - else { - /* pub key */ - pubSz = length - 1; /* null prefix */ - if (pubSz < 2*(ECC_MAXSIZE+1)) { - XMEMCPY(pub, &input[*inOutIdx], pubSz); - *inOutIdx += length; - ret = wc_ecc_import_private_key_ex(priv, privSz, pub, - pubSz, key, curve_id); - } else - ret = BUFFER_E; + ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL); + if (ret == 0) { + /* pub key */ + pubSz = length; + if (pubSz < 2*(ECC_MAXSIZE+1)) { + XMEMCPY(pub, &input[*inOutIdx], pubSz); + *inOutIdx += length; } + else + ret = BUFFER_E; } } } + if (ret == 0) { + ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key, + curve_id); + } + #ifdef WOLFSSL_SMALL_STACK XFREE(priv, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -9117,11 +9601,15 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, return ret; } + int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) { int length; - int ret = 0; + int ret; +#ifdef ECC_CHECK_PUBLIC_KEY_OID + word32 oidSum; +#endif if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; @@ -9129,68 +9617,50 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; -#if defined(OPENSSL_EXTRA) || defined(ECC_DECODE_EXTRA) - { - byte b = input[*inOutIdx]; - if (b != ASN_INTEGER) { - /* not from decoded cert, will have algo id, skip past */ - if (GetSequence(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; + /* ecc params information */ +#ifdef ECC_CHECK_PUBLIC_KEY_OID + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret != 0) + return ret; + if (CheckCurve(oidSum) < 0) + return ECC_CURVE_OID_E; +#else + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; +#endif - *inOutIdx += length; /* skip past */ + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; - /* ecc params information */ - b = input[(*inOutIdx)++]; - if (b != ASN_OBJECT_ID) - return ASN_OBJECT_ID_E; - - if (GetLength(input, inOutIdx, &length, inSz) < 0) - return ASN_PARSE_E; - - *inOutIdx += length; /* skip past */ - - /* key header */ - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != ASN_BIT_STRING) - ret = ASN_BITSTR_E; - else if (GetLength(input, inOutIdx, &length, inSz) < 0) - ret = ASN_PARSE_E; - else { - b = input[*inOutIdx]; - *inOutIdx += 1; - - if (b != 0x00) - ret = ASN_EXPECT_0_E; - } - } - } /* openssl var block */ -#endif /* OPENSSL_EXTRA */ - - if (wc_ecc_import_x963(input+*inOutIdx, inSz - *inOutIdx, key) != 0) + /* This is the raw point data compressed or uncompressed. */ + if (wc_ecc_import_x963(input + *inOutIdx, inSz - *inOutIdx, key) != 0) return ASN_ECC_KEY_E; - return ret; + return 0; } #ifdef WOLFSSL_KEY_GEN -/* Write a Private ecc key to DER format, length on success else < 0 */ -int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +/* build DER formatted ECC key, include optional public key if requested, + * return length on success, negative on error */ +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, + int pubIn) { byte curve[MAX_ALGO_SZ+2]; byte ver[MAX_VERSION_SZ]; byte seq[MAX_SEQ_SZ]; - byte *prv, *pub; + byte *prv = NULL, *pub = NULL; int ret, totalSz, curveSz, verSz; int privHdrSz = ASN_ECC_HEADER_SZ; int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; @@ -9218,8 +9688,7 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) if (prv == NULL) { return MEMORY_E; } - prv[prvidx++] = ASN_OCTET_STRING; - prv[prvidx++] = (byte)key->dp->size; + prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]); ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); if (ret < 0) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -9227,35 +9696,37 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) } prvidx += privSz; - /* public */ - ret = wc_ecc_export_x963(key, NULL, &pubSz); - if (ret != LENGTH_ONLY_E) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + /* pubIn */ + if (pubIn) { + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } - pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, - key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } - pub[pubidx++] = ECC_PREFIX_1; - if (pubSz > 128) /* leading zero + extra size byte */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); - else /* leading zero */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); - pub[pubidx++] = ASN_BIT_STRING; - pubidx += SetLength(pubSz + 1, pub+pubidx); - pub[pubidx++] = (byte)0; /* leading zero */ - ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); - if (ret != 0) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + pub[pubidx++] = ECC_PREFIX_1; + if (pubSz > 128) /* leading zero + extra size byte */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); + else /* leading zero */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); + + /* SetBitString adds leading zero */ + pubidx += SetBitString(pubSz, 0, pub + pubidx); + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pubidx += pubSz; } - pubidx += pubSz; /* make headers */ verSz = SetMyVersion(1, ver, FALSE); @@ -9264,7 +9735,9 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) totalSz = prvidx + pubidx + curveidx + verSz + seqSz; if (totalSz > (int)inLen) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return BAD_FUNC_ARG; } @@ -9286,14 +9759,32 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) XMEMCPY(output + idx, curve, curveidx); idx += curveidx; - /* public */ - XMEMCPY(output + idx, pub, pubidx); - /* idx += pubidx; not used after write, if more data remove comment */ - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + /* pubIn */ + if (pubIn) { + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return totalSz; } + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 1); +} + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 0); +} + #endif /* WOLFSSL_KEY_GEN */ #endif /* HAVE_ECC */ @@ -9363,6 +9854,7 @@ static int DecodeSingleResponse(byte* source, word32 idx = *ioIndex, prevIndex, oid; int length, wrapperSz; CertStatus* cs = resp->status; + int ret; WOLFSSL_ENTER("DecodeSingleResponse"); @@ -9386,17 +9878,15 @@ static int DecodeSingleResponse(byte* source, if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0) return ASN_PARSE_E; /* Save reference to the hash of CN */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerHash = source + idx; idx += length; /* Save reference to the hash of the issuer public key */ - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; resp->issuerKeyHash = source + idx; idx += length; @@ -9425,11 +9915,17 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; } +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->thisDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) return ASN_BEFORE_DATE_E; +#endif /* The following items are optional. Only check for them if there is more * unprocessed data in the singleResponse wrapper. */ @@ -9440,11 +9936,17 @@ static int DecodeSingleResponse(byte* source, idx++; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->nextDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->nextDate, &cs->nextDateFormat, size) < 0) return ASN_PARSE_E; + +#ifndef NO_ASN_TIME if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) return ASN_AFTER_DATE_E; +#endif } if (((int)(idx - prevIndex) < wrapperSz) && (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) @@ -9467,15 +9969,21 @@ static int DecodeOcspRespExtensions(byte* source, int length; int ext_bound; /* boundary index for the sequence of extensions */ word32 oid; + int ret; WOLFSSL_ENTER("DecodeOcspRespExtensions"); + if ((idx + 1) > sz) + return BUFFER_E; + if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) return ASN_PARSE_E; - if (GetLength(source, &idx, &length, sz) < 0) return ASN_PARSE_E; + if (GetLength(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; - if (GetSequence(source, &idx, &length, sz) < 0) return ASN_PARSE_E; + if (GetSequence(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; ext_bound = idx + length; @@ -9494,31 +10002,20 @@ static int DecodeOcspRespExtensions(byte* source, /* check for critical flag */ if (source[idx] == ASN_BOOLEAN) { WOLFSSL_MSG("\tfound optional critical flag, moving past"); - idx += (ASN_BOOL_SIZE + 1); + ret = GetBoolean(source, &idx, sz); + if (ret < 0) + return ret; } - /* process the extension based on the OID */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; if (oid == OCSP_NONCE_OID) { /* get data inside extra OCTET_STRING */ - if (source[idx++] != ASN_OCTET_STRING) { - WOLFSSL_MSG("\tfail: should be an OCTET STRING"); - return ASN_PARSE_E; - } - - if (GetLength(source, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: extension data length"); - return ASN_PARSE_E; - } + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; resp->nonce = source + idx; resp->nonceSz = length; @@ -9592,6 +10089,8 @@ static int DecodeResponseData(byte* source, } +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS + static int DecodeCerts(byte* source, word32* ioIndex, OcspResponse* resp, word32 size) { @@ -9618,15 +10117,20 @@ static int DecodeCerts(byte* source, return 0; } +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + + static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, - OcspResponse* resp, word32 size, void* cm, void* heap) + OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify) { - int length; + int length; word32 idx = *ioIndex; word32 end_index; - int ret = -1; + int ret; + int sigLength; WOLFSSL_ENTER("DecodeBasicOcspResponse"); + (void)heap; if (GetSequence(source, &idx, &length, size) < 0) return ASN_PARSE_E; @@ -9642,21 +10146,19 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0) return ASN_PARSE_E; - /* Obtain pointer to the start of the signature, and save the size */ - if (source[idx++] == ASN_BIT_STRING) - { - int sigLength = 0; - if (GetLength(source, &idx, &sigLength, size) < 0) - return ASN_PARSE_E; - resp->sigSz = sigLength; - resp->sig = source + idx; - idx += sigLength; - } + ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL); + if (ret != 0) + return ret; + + resp->sigSz = sigLength; + resp->sig = source + idx; + idx += sigLength; /* * Check the length of the BasicOcspResponse against the current index to * see if there are certificates, they are optional. */ +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS if (idx < end_index) { DecodedCert cert; @@ -9665,27 +10167,49 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, return ASN_PARSE_E; InitDecodedCert(&cert, resp->cert, resp->certSz, heap); - ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); - if (ret < 0) + /* Don't verify if we don't have access to Cert Manager. */ + ret = ParseCertRelative(&cert, CERT_TYPE, noVerify ? NO_VERIFY : VERIFY, + cm); + if (ret < 0) { + WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); + FreeDecodedCert(&cert); return ret; + } - ret = ConfirmSignature(resp->response, resp->responseSz, - cert.publicKey, cert.pubKeySize, cert.keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL); + /* ConfirmSignature is blocking here */ + ret = ConfirmSignature(&cert.sigCtx, + resp->response, resp->responseSz, + cert.publicKey, cert.pubKeySize, cert.keyOID, + resp->sig, resp->sigSz, resp->sigOID); FreeDecodedCert(&cert); - if (ret == 0) - { + if (ret != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } } - else { - Signer* ca = GetCA(cm, resp->issuerKeyHash); + else +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + { + Signer* ca = NULL; + int sigValid = -1; - if (!ca || !ConfirmSignature(resp->response, resp->responseSz, - ca->publicKey, ca->pubKeySize, ca->keyOID, - resp->sig, resp->sigSz, resp->sigOID, NULL)) { + #ifndef NO_SKID + ca = GetCA(cm, resp->issuerKeyHash); + #else + ca = GetCA(cm, resp->issuerHash); + #endif + + if (ca) { + SignatureCtx sigCtx; + InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); + + /* ConfirmSignature is blocking here */ + sigValid = ConfirmSignature(&sigCtx, resp->response, + resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID); + } + if (ca == NULL || sigValid != 0) { WOLFSSL_MSG("\tOCSP Confirm signature failed"); return ASN_OCSP_CONFIRM_E; } @@ -9711,8 +10235,9 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, } -int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) +int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) { + int ret; int length = 0; word32 idx = 0; byte* source = resp->source; @@ -9749,14 +10274,13 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) return ASN_PARSE_E; if (oid != OCSP_BASIC_OID) return ASN_PARSE_E; - if (source[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; - if (GetLength(source, &idx, &length, size) < 0) - return ASN_PARSE_E; - - if (DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap) < 0) - return ASN_PARSE_E; + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify); + if (ret < 0) + return ret; return 0; } @@ -9766,8 +10290,8 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; - byte seqArray[6][MAX_SEQ_SZ]; - word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId); + byte seqArray[5][MAX_SEQ_SZ]; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); @@ -9777,20 +10301,15 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) totalSz += req->nonceSz; totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]); - seqArray[2][0] = ASN_OBJECT_ID; - totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]); + totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]); totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); - totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); if (totalSz > size) return 0; totalSz = 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); - totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; @@ -9841,8 +10360,14 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) snSz = SetSerialNumber(req->serial, req->serialSz, snArray); extSz = 0; - if (req->nonceSz) - extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); + if (req->nonceSz) { + /* TLS Extensions use this function too - put extensions after + * ASN.1: Context Specific [2]. + */ + extSz = EncodeOcspRequestExtensions(req, extArray + 2, + OCSP_NONCE_EXT_SZ); + extSz += SetExplicit(2, extSz, extArray); + } totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { @@ -9851,6 +10376,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) if (i == 2) totalSz += extSz; } + if (output == NULL) + return totalSz; if (totalSz > size) return BUFFER_E; @@ -9884,6 +10411,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, void* heap) { + int ret; + WOLFSSL_ENTER("InitOcspRequest"); if (req == NULL) @@ -9915,17 +10444,17 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); req->urlSz = cert->extAuthInfoSz; } - } if (useNonce) { WC_RNG rng; -#ifdef WOLFSSL_STATIC_MEMORY - if (wc_InitRng_ex(&rng, req->heap) != 0) { -#else - if (wc_InitRng(&rng) != 0) { -#endif + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) { WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); } else { if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) @@ -9974,7 +10503,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) /* Nonces are not critical. The responder may not necessarily add * the nonce to the response. */ - if (req->nonceSz && resp->nonceSz != 0) { + if (resp->nonceSz != 0) { cmp = req->nonceSz - resp->nonceSz; if (cmp != 0) { @@ -10160,40 +10689,51 @@ static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl, int maxIdx) { int length; - byte b; + int ret; WOLFSSL_ENTER("GetCRL_Signature"); - b = source[*idx]; - *idx += 1; - if (b != ASN_BIT_STRING) - return ASN_BITSTR_E; - - if (GetLength(source, idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - + ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL); + if (ret != 0) + return ret; dcrl->sigLength = length; - b = source[*idx]; - *idx += 1; - if (b != 0x00) - return ASN_EXPECT_0_E; - - dcrl->sigLength--; dcrl->signature = (byte*)&source[*idx]; - *idx += dcrl->sigLength; return 0; } +int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, + word32 tbsSz, const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, void* heap) +{ + /* try to confirm/verify signature */ +#ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, + ca->pubKeySize, ca->keyOID, signature, sigSz, + signatureOID) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} /* prase crl buffer into decoded state, 0 on success */ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) { - int version, len, doNextDate = 1; - word32 oid, idx = 0, dateIdx; - Signer* ca = NULL; + int version, len, doNextDate = 1; + word32 oid, idx = 0, dateIdx; + Signer* ca = NULL; + SignatureCtx sigCtx; WOLFSSL_MSG("ParseCRL"); @@ -10242,10 +10782,13 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) #endif } - if (doNextDate && !XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, - AFTER)) { - WOLFSSL_MSG("CRL after date is no longer valid"); - return ASN_AFTER_DATE_E; + if (doNextDate) { +#ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL after date is no longer valid"); + return ASN_AFTER_DATE_E; + } +#endif } if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { @@ -10271,46 +10814,34 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) /* openssl doesn't add skid by default for CRLs cause firefox chokes we're not assuming it's available yet */ - #if !defined(NO_SKID) && defined(CRL_SKID_READY) - if (dcrl->extAuthKeyIdSet) - ca = GetCA(cm, dcrl->extAuthKeyId); - if (ca == NULL) - ca = GetCAByName(cm, dcrl->issuerHash); - #else /* NO_SKID */ - ca = GetCA(cm, dcrl->issuerHash); - #endif /* NO_SKID */ +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (dcrl->extAuthKeyIdSet) + ca = GetCA(cm, dcrl->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, dcrl->issuerHash); +#else + ca = GetCA(cm, dcrl->issuerHash); +#endif /* !NO_SKID && CRL_SKID_READY */ WOLFSSL_MSG("About to verify CRL signature"); - if (ca) { - WOLFSSL_MSG("Found CRL issuer CA"); - /* try to confirm/verify signature */ - #ifndef IGNORE_KEY_EXTENSIONS - if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { - WOLFSSL_MSG("CA cannot sign CRLs"); - return ASN_CRL_NO_SIGNER_E; - } - #endif /* IGNORE_KEY_EXTENSIONS */ - if (!ConfirmSignature(buff + dcrl->certBegin, - dcrl->sigIndex - dcrl->certBegin, - ca->publicKey, ca->pubKeySize, ca->keyOID, - dcrl->signature, dcrl->sigLength, dcrl->signatureOID, NULL)) { - WOLFSSL_MSG("CRL Confirm signature failed"); - return ASN_CRL_CONFIRM_E; - } - } - else { + if (ca == NULL) { WOLFSSL_MSG("Did NOT find CRL issuer CA"); return ASN_CRL_NO_SIGNER_E; } - return 0; + WOLFSSL_MSG("Found CRL issuer CA"); + return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength, + dcrl->signatureOID, ca, dcrl->heap); } #endif /* HAVE_CRL */ + +#undef ERROR_OUT + #endif /* !NO_ASN */ #ifdef WOLFSSL_SEP - #endif /* WOLFSSL_SEP */ diff --git a/wolfcrypt/src/blake2b.c b/wolfcrypt/src/blake2b.c index 4ed71b44a..f30b685af 100644 --- a/wolfcrypt/src/blake2b.c +++ b/wolfcrypt/src/blake2b.c @@ -126,6 +126,7 @@ int blake2b_init( blake2b_state *S, const byte outlen ) if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = 0; P->fanout = 1; @@ -137,6 +138,12 @@ int blake2b_init( blake2b_state *S, const byte outlen ) XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->fanout = 1; + P->depth = 1; +#endif return blake2b_init_param( S, P ); } @@ -150,6 +157,7 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD P->digest_length = outlen; P->key_length = keylen; P->fanout = 1; @@ -161,6 +169,13 @@ int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); XMEMSET( P->salt, 0, sizeof( P->salt ) ); XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; +#endif if( blake2b_init_param( S, P ) < 0 ) return -1; diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index 6c7c88dc9..79b13fc43 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -40,17 +40,6 @@ #include -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - static void ShiftAndXorRb(byte* out, byte* in) { int i, j, xorRb; diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index f144b1130..43cb45d06 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -347,7 +347,8 @@ int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) #endif /* defined(WOLFSSL_BASE64_ENCODE) */ -#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) \ + || defined(HAVE_ECC_CDH) static const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c old mode 100644 new mode 100755 index 4fc510154..739fb62d6 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -26,91 +26,78 @@ #include + #ifndef NO_DES3 #include +/* fips wrapper calls, user can call direct */ #ifdef HAVE_FIPS + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + return Des_SetKey(des, key, iv, dir); + } + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + return Des3_SetKey_fips(des, key, iv, dir); + } + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcEncrypt(des, out, in, sz); + } + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcDecrypt(des, out, in, sz); + } + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_CbcEncrypt_fips(des, out, in, sz); + } + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_CbcDecrypt_fips(des, out, in, sz); + } -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - return Des_SetKey(des, key, iv, dir); -} + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_EcbEncrypt(des, out, in, sz); + } + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_EcbEncrypt(des, out, in, sz); + } + #endif /* WOLFSSL_DES_ECB */ + void wc_Des_SetIV(Des* des, const byte* iv) + { + Des_SetIV(des, iv); + } + int wc_Des3_SetIV(Des3* des, const byte* iv) + { + return Des3_SetIV_fips(des, iv); + } -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - return Des3_SetKey_fips(des, key, iv, dir); -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcEncrypt(des, out, in, sz); -} - - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_CbcDecrypt(des, out, in, sz); -} - - -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcEncrypt_fips(des, out, in, sz); -} - - -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - return Des3_CbcDecrypt_fips(des, out, in, sz); -} - - -#ifdef WOLFSSL_DES_ECB - -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - return Des_EcbEncrypt(des, out, in, sz); -} - -#endif /* WOLFSSL_DES_ECB */ - - -void wc_Des_SetIV(Des* des, const byte* iv) -{ - Des_SetIV(des, iv); -} - - -int wc_Des3_SetIV(Des3* des, const byte* iv) -{ - return Des3_SetIV_fips(des, iv); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) -{ - return Des3AsyncInit(des3, devId); -} - - -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) -{ - Des3AsyncFree(des3); -} - - -#endif /* WOLFSSL_ASYNC_CRYPT */ + int wc_Des3Init(Des3* des3, void* heap, int devId) + { + (void)des3; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return Des3Init(des3, heap, devId); */ + return 0; + } + void wc_Des3Free(Des3* des3) + { + (void)des3; + /* FIPS doesn't support: + Des3Free(des3); */ + } #else /* build without fips */ + #if defined(WOLFSSL_TI_CRYPT) #include #else @@ -126,6 +113,7 @@ void wc_Des3AsyncFree(Des3* des3) #endif +/* Hardware Acceleration */ #if defined(STM32F2_CRYPTO) || defined(STM32F4_CRYPTO) /* @@ -442,227 +430,224 @@ void wc_Des3AsyncFree(Des3* des3) #elif defined(HAVE_COLDFIRE_SEC) -#include + #include -#include "sec.h" -#include "mcf5475_sec.h" -#include "mcf5475_siu.h" + #include "sec.h" + #include "mcf5475_sec.h" + #include "mcf5475_siu.h" -#if defined (HAVE_THREADX) -#include "memory_pools.h" -extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ -#endif - -#define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) -static unsigned char *desBuffIn = NULL ; -static unsigned char *desBuffOut = NULL ; -static byte *secIV ; -static byte *secKey ; -static volatile SECdescriptorType *secDesc ; - -static wolfSSL_Mutex Mutex_DesSEC ; - -#define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 -#define SEC_DESC_DES_CBC_DECRYPT 0x20400010 -#define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 -#define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 - -#define DES_IVLEN 8 -#define DES_KEYLEN 8 -#define DES3_IVLEN 8 -#define DES3_KEYLEN 24 - -extern volatile unsigned char __MBAR[]; - -static void wc_Des_Cbc(byte* out, const byte* in, word32 sz, - byte *key, byte *iv, word32 desc) -{ - #ifdef DEBUG_WOLFSSL - int ret ; int stat1,stat2 ; + #if defined (HAVE_THREADX) + #include "memory_pools.h" + extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ #endif - int size ; - volatile int v ; - wc_LockMutex(&Mutex_DesSEC) ; + #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) + static unsigned char *desBuffIn = NULL; + static unsigned char *desBuffOut = NULL; + static byte *secIV; + static byte *secKey; + static volatile SECdescriptorType *secDesc; - secDesc->length1 = 0x0; - secDesc->pointer1 = NULL; - if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ - secDesc->length2 = DES_IVLEN ; - secDesc->length3 = DES_KEYLEN ; - } else { - secDesc->length2 = DES3_IVLEN ; - secDesc->length3 = DES3_KEYLEN ; - } - secDesc->pointer2 = secIV ; - secDesc->pointer3 = secKey; - secDesc->pointer4 = desBuffIn ; - secDesc->pointer5 = desBuffOut ; - secDesc->length6 = 0; - secDesc->pointer6 = NULL; - secDesc->length7 = 0x0; - secDesc->pointer7 = NULL; - secDesc->nextDescriptorPtr = NULL ; + static wolfSSL_Mutex Mutex_DesSEC; - while(sz) { - XMEMCPY(secIV, iv, secDesc->length2) ; - if((sz%DES_BUFFER_SIZE) == sz) { - size = sz ; - sz = 0 ; - } else { - size = DES_BUFFER_SIZE ; - sz -= DES_BUFFER_SIZE ; - } + #define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 + #define SEC_DESC_DES_CBC_DECRYPT 0x20400010 + #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 + #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 - XMEMCPY(desBuffIn, in, size) ; - XMEMCPY(secKey, key, secDesc->length3) ; + #define DES_IVLEN 8 + #define DES_KEYLEN 8 + #define DES3_IVLEN 8 + #define DES3_KEYLEN 24 - secDesc->header = desc ; - secDesc->length4 = size; - secDesc->length5 = size; - /* Point SEC to the location of the descriptor */ - MCF_SEC_FR0 = (uint32)secDesc; - /* Initialize SEC and wait for encryption to complete */ - MCF_SEC_CCCR0 = 0x0000001a; - /* poll SISR to determine when channel is complete */ - v=0 ; - while((secDesc->header>> 24) != 0xff) { - if(v++ > 1000)break ; - } + extern volatile unsigned char __MBAR[]; -#ifdef DEBUG_WOLFSSL - ret = MCF_SEC_SISRH; - stat1 = MCF_SEC_DSR ; - stat2 = MCF_SEC_DISR ; - if(ret & 0xe0000000) { - /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2) ; */ - } -#endif - - XMEMCPY(out, desBuffOut, size) ; - - if((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { - XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2) ; - } else { - XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2) ; - } - - in += size ; - out += size ; - - } - wc_UnLockMutex(&Mutex_DesSEC) ; - -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT) ; - return 0; -} - -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT) ; - return 0; -} - -int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT) ; - return 0; -} - - -int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) -{ - wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT) ; - return 0; -} - -static void setParity(byte *buf, int len) -{ - int i, j ; - byte v ; - int bits ; - - for(i=0; i > 1 ; - buf[i] = v << 1 ; - bits = 0 ; - for(j=0; j<7; j++) - { - bits += (v&0x1) ; - v = v >> 1 ; + #ifdef DEBUG_WOLFSSL + int ret; int stat1,stat2; + #endif + int size; + volatile int v; + + wc_LockMutex(&Mutex_DesSEC) ; + + secDesc->length1 = 0x0; + secDesc->pointer1 = NULL; + if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ + secDesc->length2 = DES_IVLEN; + secDesc->length3 = DES_KEYLEN; + } else { + secDesc->length2 = DES3_IVLEN; + secDesc->length3 = DES3_KEYLEN; } - buf[i] |= (1 - (bits&0x1)) ; - } + secDesc->pointer2 = secIV; + secDesc->pointer3 = secKey; + secDesc->pointer4 = desBuffIn; + secDesc->pointer5 = desBuffOut; + secDesc->length6 = 0; + secDesc->pointer6 = NULL; + secDesc->length7 = 0x0; + secDesc->pointer7 = NULL; + secDesc->nextDescriptorPtr = NULL; -} + while(sz) { + XMEMCPY(secIV, iv, secDesc->length2); + if((sz%DES_BUFFER_SIZE) == sz) { + size = sz; + sz = 0; + } else { + size = DES_BUFFER_SIZE; + sz -= DES_BUFFER_SIZE; + } + XMEMCPY(desBuffIn, in, size); + XMEMCPY(secKey, key, secDesc->length3); -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - if(desBuffIn == NULL) { - #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - /* Don't know des or des3 to be used. Allocate larger buffers */ - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); - #else - #warning "Allocate non-Cache buffers" + secDesc->header = desc; + secDesc->length4 = size; + secDesc->length5 = size; + /* Point SEC to the location of the descriptor */ + MCF_SEC_FR0 = (uint32)secDesc; + /* Initialize SEC and wait for encryption to complete */ + MCF_SEC_CCCR0 = 0x0000001a; + /* poll SISR to determine when channel is complete */ + v=0; + while((secDesc->header>> 24) != 0xff) { + if(v++ > 1000)break; + } + + #ifdef DEBUG_WOLFSSL + ret = MCF_SEC_SISRH; + stat1 = MCF_SEC_DSR; + stat2 = MCF_SEC_DISR; + if(ret & 0xe0000000) { + /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */ + } #endif - wc_InitMutex(&Mutex_DesSEC) ; + XMEMCPY(out, desBuffOut, size); + + if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { + XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2); + } else { + XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2); + } + + in += size; + out += size; + + } + wc_UnLockMutex(&Mutex_DesSEC) ; + } - XMEMCPY(des->key, key, DES_KEYLEN); - setParity((byte *)des->key, DES_KEYLEN) ; - if (iv) { - XMEMCPY(des->reg, iv, DES_IVLEN); - } else { - XMEMSET(des->reg, 0x0, DES_IVLEN) ; + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT); + return 0; } - return 0; -} -int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) -{ + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT); + return 0; + } - if(desBuffIn == NULL) { + int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT); + return 0; + } + + + int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT); + return 0; + } + + static void setParity(byte *buf, int len) + { + int i, j; + byte v; + int bits; + + for (i=0; i > 1; + buf[i] = v << 1; + bits = 0; + for (j=0; j<7; j++) { + bits += (v&0x1); + v = v >> 1; + } + buf[i] |= (1 - (bits&0x1)); + } + + } + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + if(desBuffIn == NULL) { #if defined (HAVE_THREADX) - int s1, s2, s3, s4, s5 ; - s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, - sizeof(SECdescriptorType), TX_NO_WAIT); - s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); - s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); - s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); - s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + /* Don't know des or des3 to be used. Allocate larger buffers */ + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); #else - #warning "Allocate non-Cache buffers" + #warning "Allocate non-Cache buffers" #endif - wc_InitMutex(&Mutex_DesSEC) ; + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des->key, key, DES_KEYLEN); + setParity((byte *)des->key, DES_KEYLEN); + + if (iv) { + XMEMCPY(des->reg, iv, DES_IVLEN); + } else { + XMEMSET(des->reg, 0x0, DES_IVLEN); + } + return 0; } - XMEMCPY(des3->key[0], key, DES3_KEYLEN); - setParity((byte *)des3->key[0], DES3_KEYLEN) ; + int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) + { + + if(desBuffIn == NULL) { + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + #else + #warning "Allocate non-Cache buffers" + #endif + + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des3->key[0], key, DES3_KEYLEN); + setParity((byte *)des3->key[0], DES3_KEYLEN); + + if (iv) { + XMEMCPY(des3->reg, iv, DES3_IVLEN); + } else { + XMEMSET(des3->reg, 0x0, DES3_IVLEN); + } + return 0; - if (iv) { - XMEMCPY(des3->reg, iv, DES3_IVLEN); - } else { - XMEMSET(des3->reg, 0x0, DES3_IVLEN) ; } - return 0; - -} #elif (defined FREESCALE_LTC_DES) #include "fsl_ltc.h" @@ -749,7 +734,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) return -1; } -#elif defined FREESCALE_MMCAU +#elif defined(FREESCALE_MMCAU) /* * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library. * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU @@ -757,8 +742,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) */ #include "fsl_mmcau.h" - const unsigned char parityLookup[128] = - { + const unsigned char parityLookup[128] = { 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, @@ -820,7 +804,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -893,7 +877,7 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) byte temp_block[DES_BLOCK_SIZE]; iv = (byte*)des->reg; - + while (len > 0) { XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); @@ -965,13 +949,10 @@ int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) #include "wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h" -void wc_Des_SetIV(Des* des, const byte* iv); -int wc_Des3_SetIV(Des3* des, const byte* iv); - int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { - word32 *dkey = des->key ; - word32 *dreg = des->reg ; + word32 *dkey = des->key; + word32 *dreg = des->reg; XMEMCPY((byte *)dkey, (byte *)key, 8); ByteReverseWords(dkey, dkey, 8); @@ -984,12 +965,12 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) { word32 *dkey1 = des->key[0]; - word32 *dreg = des->reg ; + word32 *dreg = des->reg; XMEMCPY(dkey1, key, 24); ByteReverseWords(dkey1, dkey1, 24); XMEMCPY(dreg, iv, 8); - ByteReverseWords(dreg, dreg, 8) ; + ByteReverseWords(dreg, dreg, 8); return 0; } @@ -997,21 +978,21 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); void DesCrypt(word32 *key, word32 *iv, byte* out, const byte* in, word32 sz, int dir, int algo, int cryptoalgo) { - securityAssociation *sa_p ; - bufferDescriptor *bd_p ; - const byte *in_p, *in_l ; - byte *out_p, *out_l ; + securityAssociation *sa_p; + bufferDescriptor *bd_p; + const byte *in_p, *in_l; + byte *out_p, *out_l; volatile securityAssociation sa __attribute__((aligned (8))); volatile bufferDescriptor bd __attribute__((aligned (8))); - volatile int k ; + volatile int k; /* get uncached address */ in_l = in; - out_l = out ; - sa_p = KVA0_TO_KVA1(&sa) ; - bd_p = KVA0_TO_KVA1(&bd) ; - in_p = KVA0_TO_KVA1(in_l) ; + out_l = out; + sa_p = KVA0_TO_KVA1(&sa); + bd_p = KVA0_TO_KVA1(&bd); + in_p = KVA0_TO_KVA1(in_l); out_p= KVA0_TO_KVA1(out_l); if(PIC32MZ_IF_RAM(in_p)) @@ -1020,13 +1001,13 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); /* Set up the Security Association */ XMEMSET((byte *)KVA0_TO_KVA1(&sa), 0, sizeof(sa)); - sa_p->SA_CTRL.ALGO = algo ; + sa_p->SA_CTRL.ALGO = algo; sa_p->SA_CTRL.LNC = 1; sa_p->SA_CTRL.LOADIV = 1; sa_p->SA_CTRL.FB = 1; - sa_p->SA_CTRL.ENCTYPE = dir ; /* Encryption/Decryption */ + sa_p->SA_CTRL.ENCTYPE = dir; /* Encryption/Decryption */ sa_p->SA_CTRL.CRYPTOALGO = cryptoalgo; - sa_p->SA_CTRL.KEYSIZE = 1 ; /* KEY is 192 bits */ + sa_p->SA_CTRL.KEYSIZE = 1; /* KEY is 192 bits */ XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCKEY[algo==PIC32_ALGO_TDES ? 2 : 6]), (byte *)key, algo==PIC32_ALGO_TDES ? 24 : 8); XMEMCPY((byte *)KVA0_TO_KVA1(&sa.SA_ENCIV[2]), (byte *)iv, 8); @@ -1039,30 +1020,30 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); bd_p->BD_CTRL.LAST_BD = 1; bd_p->BD_CTRL.DESC_EN = 1; - bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa) ; /* (unsigned int)sa_p; */ - bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in) ; /* (unsigned int)in_p; */ + bd_p->SA_ADDR = (unsigned int)KVA_TO_PA(&sa); /* (unsigned int)sa_p; */ + bd_p->SRCADDR = (unsigned int)KVA_TO_PA(in); /* (unsigned int)in_p; */ bd_p->DSTADDR = (unsigned int)KVA_TO_PA(out); /* (unsigned int)out_p; */ bd_p->NXTPTR = (unsigned int)KVA_TO_PA(&bd); - bd_p->MSGLEN = sz ; + bd_p->MSGLEN = sz; /* Fire in the hole! */ CECON = 1 << 6; while (CECON); /* Run the engine */ - CEBDPADDR = (unsigned int)KVA_TO_PA(&bd) ; /* (unsigned int)bd_p ; */ + CEBDPADDR = (unsigned int)KVA_TO_PA(&bd); /* (unsigned int)bd_p; */ CEINTEN = 0x07; CECON = 0x27; - WAIT_ENGINE ; + WAIT_ENGINE; if((cryptoalgo == PIC32_CRYPTOALGO_CBC) || (cryptoalgo == PIC32_CRYPTOALGO_TCBC)|| (cryptoalgo == PIC32_CRYPTOALGO_RCBC)) { /* set iv for the next call */ if(dir == PIC32_ENCRYPTION) { - XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN) ; - } else { + XMEMCPY((void *)iv, (void*)&(out_p[sz-DES_IVLEN]), DES_IVLEN); + } else { ByteReverseWords((word32*)iv, (word32 *)&(in_p[sz-DES_IVLEN]), DES_IVLEN); } @@ -1099,536 +1080,575 @@ int wc_Des3_SetIV(Des3* des, const byte* iv); return 0; } -#else /* Begin wolfCrypt software implementation */ - -/* permuted choice table (key) */ -static const byte pc1[] = { - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 -}; - -/* number left rotations of pc1 */ -static const byte totrot[] = { - 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 -}; - -/* permuted choice key (table) */ -static const byte pc2[] = { - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 -}; - -/* End of DES-defined tables */ - -/* bit 0 is left-most in byte */ -static const int bytebit[] = { - 0200,0100,040,020,010,04,02,01 -}; - -static const word32 Spbox[8][64] = { -{ -0x01010400,0x00000000,0x00010000,0x01010404, -0x01010004,0x00010404,0x00000004,0x00010000, -0x00000400,0x01010400,0x01010404,0x00000400, -0x01000404,0x01010004,0x01000000,0x00000004, -0x00000404,0x01000400,0x01000400,0x00010400, -0x00010400,0x01010000,0x01010000,0x01000404, -0x00010004,0x01000004,0x01000004,0x00010004, -0x00000000,0x00000404,0x00010404,0x01000000, -0x00010000,0x01010404,0x00000004,0x01010000, -0x01010400,0x01000000,0x01000000,0x00000400, -0x01010004,0x00010000,0x00010400,0x01000004, -0x00000400,0x00000004,0x01000404,0x00010404, -0x01010404,0x00010004,0x01010000,0x01000404, -0x01000004,0x00000404,0x00010404,0x01010400, -0x00000404,0x01000400,0x01000400,0x00000000, -0x00010004,0x00010400,0x00000000,0x01010004}, -{ -0x80108020,0x80008000,0x00008000,0x00108020, -0x00100000,0x00000020,0x80100020,0x80008020, -0x80000020,0x80108020,0x80108000,0x80000000, -0x80008000,0x00100000,0x00000020,0x80100020, -0x00108000,0x00100020,0x80008020,0x00000000, -0x80000000,0x00008000,0x00108020,0x80100000, -0x00100020,0x80000020,0x00000000,0x00108000, -0x00008020,0x80108000,0x80100000,0x00008020, -0x00000000,0x00108020,0x80100020,0x00100000, -0x80008020,0x80100000,0x80108000,0x00008000, -0x80100000,0x80008000,0x00000020,0x80108020, -0x00108020,0x00000020,0x00008000,0x80000000, -0x00008020,0x80108000,0x00100000,0x80000020, -0x00100020,0x80008020,0x80000020,0x00100020, -0x00108000,0x00000000,0x80008000,0x00008020, -0x80000000,0x80100020,0x80108020,0x00108000}, -{ -0x00000208,0x08020200,0x00000000,0x08020008, -0x08000200,0x00000000,0x00020208,0x08000200, -0x00020008,0x08000008,0x08000008,0x00020000, -0x08020208,0x00020008,0x08020000,0x00000208, -0x08000000,0x00000008,0x08020200,0x00000200, -0x00020200,0x08020000,0x08020008,0x00020208, -0x08000208,0x00020200,0x00020000,0x08000208, -0x00000008,0x08020208,0x00000200,0x08000000, -0x08020200,0x08000000,0x00020008,0x00000208, -0x00020000,0x08020200,0x08000200,0x00000000, -0x00000200,0x00020008,0x08020208,0x08000200, -0x08000008,0x00000200,0x00000000,0x08020008, -0x08000208,0x00020000,0x08000000,0x08020208, -0x00000008,0x00020208,0x00020200,0x08000008, -0x08020000,0x08000208,0x00000208,0x08020000, -0x00020208,0x00000008,0x08020008,0x00020200}, -{ -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802080,0x00800081,0x00800001,0x00002001, -0x00000000,0x00802000,0x00802000,0x00802081, -0x00000081,0x00000000,0x00800080,0x00800001, -0x00000001,0x00002000,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002001,0x00002080, -0x00800081,0x00000001,0x00002080,0x00800080, -0x00002000,0x00802080,0x00802081,0x00000081, -0x00800080,0x00800001,0x00802000,0x00802081, -0x00000081,0x00000000,0x00000000,0x00802000, -0x00002080,0x00800080,0x00800081,0x00000001, -0x00802001,0x00002081,0x00002081,0x00000080, -0x00802081,0x00000081,0x00000001,0x00002000, -0x00800001,0x00002001,0x00802080,0x00800081, -0x00002001,0x00002080,0x00800000,0x00802001, -0x00000080,0x00800000,0x00002000,0x00802080}, -{ -0x00000100,0x02080100,0x02080000,0x42000100, -0x00080000,0x00000100,0x40000000,0x02080000, -0x40080100,0x00080000,0x02000100,0x40080100, -0x42000100,0x42080000,0x00080100,0x40000000, -0x02000000,0x40080000,0x40080000,0x00000000, -0x40000100,0x42080100,0x42080100,0x02000100, -0x42080000,0x40000100,0x00000000,0x42000000, -0x02080100,0x02000000,0x42000000,0x00080100, -0x00080000,0x42000100,0x00000100,0x02000000, -0x40000000,0x02080000,0x42000100,0x40080100, -0x02000100,0x40000000,0x42080000,0x02080100, -0x40080100,0x00000100,0x02000000,0x42080000, -0x42080100,0x00080100,0x42000000,0x42080100, -0x02080000,0x00000000,0x40080000,0x42000000, -0x00080100,0x02000100,0x40000100,0x00080000, -0x00000000,0x40080000,0x02080100,0x40000100}, -{ -0x20000010,0x20400000,0x00004000,0x20404010, -0x20400000,0x00000010,0x20404010,0x00400000, -0x20004000,0x00404010,0x00400000,0x20000010, -0x00400010,0x20004000,0x20000000,0x00004010, -0x00000000,0x00400010,0x20004010,0x00004000, -0x00404000,0x20004010,0x00000010,0x20400010, -0x20400010,0x00000000,0x00404010,0x20404000, -0x00004010,0x00404000,0x20404000,0x20000000, -0x20004000,0x00000010,0x20400010,0x00404000, -0x20404010,0x00400000,0x00004010,0x20000010, -0x00400000,0x20004000,0x20000000,0x00004010, -0x20000010,0x20404010,0x00404000,0x20400000, -0x00404010,0x20404000,0x00000000,0x20400010, -0x00000010,0x00004000,0x20400000,0x00404010, -0x00004000,0x00400010,0x20004010,0x00000000, -0x20404000,0x20000000,0x00400010,0x20004010}, -{ -0x00200000,0x04200002,0x04000802,0x00000000, -0x00000800,0x04000802,0x00200802,0x04200800, -0x04200802,0x00200000,0x00000000,0x04000002, -0x00000002,0x04000000,0x04200002,0x00000802, -0x04000800,0x00200802,0x00200002,0x04000800, -0x04000002,0x04200000,0x04200800,0x00200002, -0x04200000,0x00000800,0x00000802,0x04200802, -0x00200800,0x00000002,0x04000000,0x00200800, -0x04000000,0x00200800,0x00200000,0x04000802, -0x04000802,0x04200002,0x04200002,0x00000002, -0x00200002,0x04000000,0x04000800,0x00200000, -0x04200800,0x00000802,0x00200802,0x04200800, -0x00000802,0x04000002,0x04200802,0x04200000, -0x00200800,0x00000000,0x00000002,0x04200802, -0x00000000,0x00200802,0x04200000,0x00000800, -0x04000002,0x04000800,0x00000800,0x00200002}, -{ -0x10001040,0x00001000,0x00040000,0x10041040, -0x10000000,0x10001040,0x00000040,0x10000000, -0x00040040,0x10040000,0x10041040,0x00041000, -0x10041000,0x00041040,0x00001000,0x00000040, -0x10040000,0x10000040,0x10001000,0x00001040, -0x00041000,0x00040040,0x10040040,0x10041000, -0x00001040,0x00000000,0x00000000,0x10040040, -0x10000040,0x10001000,0x00041040,0x00040000, -0x00041040,0x00040000,0x10041000,0x00001000, -0x00000040,0x10040040,0x00001000,0x00041040, -0x10001000,0x00000040,0x10000040,0x10040000, -0x10040040,0x10000000,0x00040000,0x10001040, -0x00000000,0x10041040,0x00040040,0x10000040, -0x10040000,0x10001000,0x10001040,0x00000000, -0x10041040,0x00041000,0x00041000,0x00001040, -0x00001040,0x00040040,0x10000000,0x10041000} -}; - - -static INLINE void IPERM(word32* left, word32* right) -{ - word32 work; - - *right = rotlFixed(*right, 4U); - work = (*left ^ *right) & 0xf0f0f0f0; - *left ^= work; - - *right = rotrFixed(*right^work, 20U); - work = (*left ^ *right) & 0xffff0000; - *left ^= work; - - *right = rotrFixed(*right^work, 18U); - work = (*left ^ *right) & 0x33333333; - *left ^= work; - - *right = rotrFixed(*right^work, 6U); - work = (*left ^ *right) & 0x00ff00ff; - *left ^= work; - - *right = rotlFixed(*right^work, 9U); - work = (*left ^ *right) & 0xaaaaaaaa; - *left = rotlFixed(*left^work, 1U); - *right ^= work; -} - - -static INLINE void FPERM(word32* left, word32* right) -{ - word32 work; - - *right = rotrFixed(*right, 1U); - work = (*left ^ *right) & 0xaaaaaaaa; - *right ^= work; - - *left = rotrFixed(*left^work, 9U); - work = (*left ^ *right) & 0x00ff00ff; - *right ^= work; - - *left = rotlFixed(*left^work, 6U); - work = (*left ^ *right) & 0x33333333; - *right ^= work; - - *left = rotlFixed(*left^work, 18U); - work = (*left ^ *right) & 0xffff0000; - *right ^= work; - - *left = rotlFixed(*left^work, 20U); - work = (*left ^ *right) & 0xf0f0f0f0; - *right ^= work; - - *left = rotrFixed(*left^work, 4U); -} - - -static int DesSetKey(const byte* key, int dir, word32* out) -{ -#ifdef WOLFSSL_SMALL_STACK - byte* buffer = (byte*)XMALLOC(56+56+8, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - if (buffer == NULL) - return MEMORY_E; #else - byte buffer[56+56+8]; + #define NEED_SOFT_DES + #endif + +#ifdef NEED_SOFT_DES + + /* permuted choice table (key) */ + static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; + + /* number left rotations of pc1 */ + static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 + }; + + /* permuted choice key (table) */ + static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + }; + + /* End of DES-defined tables */ + + /* bit 0 is left-most in byte */ + static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 + }; + + static const word32 Spbox[8][64] = { + { 0x01010400,0x00000000,0x00010000,0x01010404, + 0x01010004,0x00010404,0x00000004,0x00010000, + 0x00000400,0x01010400,0x01010404,0x00000400, + 0x01000404,0x01010004,0x01000000,0x00000004, + 0x00000404,0x01000400,0x01000400,0x00010400, + 0x00010400,0x01010000,0x01010000,0x01000404, + 0x00010004,0x01000004,0x01000004,0x00010004, + 0x00000000,0x00000404,0x00010404,0x01000000, + 0x00010000,0x01010404,0x00000004,0x01010000, + 0x01010400,0x01000000,0x01000000,0x00000400, + 0x01010004,0x00010000,0x00010400,0x01000004, + 0x00000400,0x00000004,0x01000404,0x00010404, + 0x01010404,0x00010004,0x01010000,0x01000404, + 0x01000004,0x00000404,0x00010404,0x01010400, + 0x00000404,0x01000400,0x01000400,0x00000000, + 0x00010004,0x00010400,0x00000000,0x01010004}, + { 0x80108020,0x80008000,0x00008000,0x00108020, + 0x00100000,0x00000020,0x80100020,0x80008020, + 0x80000020,0x80108020,0x80108000,0x80000000, + 0x80008000,0x00100000,0x00000020,0x80100020, + 0x00108000,0x00100020,0x80008020,0x00000000, + 0x80000000,0x00008000,0x00108020,0x80100000, + 0x00100020,0x80000020,0x00000000,0x00108000, + 0x00008020,0x80108000,0x80100000,0x00008020, + 0x00000000,0x00108020,0x80100020,0x00100000, + 0x80008020,0x80100000,0x80108000,0x00008000, + 0x80100000,0x80008000,0x00000020,0x80108020, + 0x00108020,0x00000020,0x00008000,0x80000000, + 0x00008020,0x80108000,0x00100000,0x80000020, + 0x00100020,0x80008020,0x80000020,0x00100020, + 0x00108000,0x00000000,0x80008000,0x00008020, + 0x80000000,0x80100020,0x80108020,0x00108000}, + { 0x00000208,0x08020200,0x00000000,0x08020008, + 0x08000200,0x00000000,0x00020208,0x08000200, + 0x00020008,0x08000008,0x08000008,0x00020000, + 0x08020208,0x00020008,0x08020000,0x00000208, + 0x08000000,0x00000008,0x08020200,0x00000200, + 0x00020200,0x08020000,0x08020008,0x00020208, + 0x08000208,0x00020200,0x00020000,0x08000208, + 0x00000008,0x08020208,0x00000200,0x08000000, + 0x08020200,0x08000000,0x00020008,0x00000208, + 0x00020000,0x08020200,0x08000200,0x00000000, + 0x00000200,0x00020008,0x08020208,0x08000200, + 0x08000008,0x00000200,0x00000000,0x08020008, + 0x08000208,0x00020000,0x08000000,0x08020208, + 0x00000008,0x00020208,0x00020200,0x08000008, + 0x08020000,0x08000208,0x00000208,0x08020000, + 0x00020208,0x00000008,0x08020008,0x00020200}, + { 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802080,0x00800081,0x00800001,0x00002001, + 0x00000000,0x00802000,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00800080,0x00800001, + 0x00000001,0x00002000,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002001,0x00002080, + 0x00800081,0x00000001,0x00002080,0x00800080, + 0x00002000,0x00802080,0x00802081,0x00000081, + 0x00800080,0x00800001,0x00802000,0x00802081, + 0x00000081,0x00000000,0x00000000,0x00802000, + 0x00002080,0x00800080,0x00800081,0x00000001, + 0x00802001,0x00002081,0x00002081,0x00000080, + 0x00802081,0x00000081,0x00000001,0x00002000, + 0x00800001,0x00002001,0x00802080,0x00800081, + 0x00002001,0x00002080,0x00800000,0x00802001, + 0x00000080,0x00800000,0x00002000,0x00802080}, + { 0x00000100,0x02080100,0x02080000,0x42000100, + 0x00080000,0x00000100,0x40000000,0x02080000, + 0x40080100,0x00080000,0x02000100,0x40080100, + 0x42000100,0x42080000,0x00080100,0x40000000, + 0x02000000,0x40080000,0x40080000,0x00000000, + 0x40000100,0x42080100,0x42080100,0x02000100, + 0x42080000,0x40000100,0x00000000,0x42000000, + 0x02080100,0x02000000,0x42000000,0x00080100, + 0x00080000,0x42000100,0x00000100,0x02000000, + 0x40000000,0x02080000,0x42000100,0x40080100, + 0x02000100,0x40000000,0x42080000,0x02080100, + 0x40080100,0x00000100,0x02000000,0x42080000, + 0x42080100,0x00080100,0x42000000,0x42080100, + 0x02080000,0x00000000,0x40080000,0x42000000, + 0x00080100,0x02000100,0x40000100,0x00080000, + 0x00000000,0x40080000,0x02080100,0x40000100}, + { 0x20000010,0x20400000,0x00004000,0x20404010, + 0x20400000,0x00000010,0x20404010,0x00400000, + 0x20004000,0x00404010,0x00400000,0x20000010, + 0x00400010,0x20004000,0x20000000,0x00004010, + 0x00000000,0x00400010,0x20004010,0x00004000, + 0x00404000,0x20004010,0x00000010,0x20400010, + 0x20400010,0x00000000,0x00404010,0x20404000, + 0x00004010,0x00404000,0x20404000,0x20000000, + 0x20004000,0x00000010,0x20400010,0x00404000, + 0x20404010,0x00400000,0x00004010,0x20000010, + 0x00400000,0x20004000,0x20000000,0x00004010, + 0x20000010,0x20404010,0x00404000,0x20400000, + 0x00404010,0x20404000,0x00000000,0x20400010, + 0x00000010,0x00004000,0x20400000,0x00404010, + 0x00004000,0x00400010,0x20004010,0x00000000, + 0x20404000,0x20000000,0x00400010,0x20004010}, + { 0x00200000,0x04200002,0x04000802,0x00000000, + 0x00000800,0x04000802,0x00200802,0x04200800, + 0x04200802,0x00200000,0x00000000,0x04000002, + 0x00000002,0x04000000,0x04200002,0x00000802, + 0x04000800,0x00200802,0x00200002,0x04000800, + 0x04000002,0x04200000,0x04200800,0x00200002, + 0x04200000,0x00000800,0x00000802,0x04200802, + 0x00200800,0x00000002,0x04000000,0x00200800, + 0x04000000,0x00200800,0x00200000,0x04000802, + 0x04000802,0x04200002,0x04200002,0x00000002, + 0x00200002,0x04000000,0x04000800,0x00200000, + 0x04200800,0x00000802,0x00200802,0x04200800, + 0x00000802,0x04000002,0x04200802,0x04200000, + 0x00200800,0x00000000,0x00000002,0x04200802, + 0x00000000,0x00200802,0x04200000,0x00000800, + 0x04000002,0x04000800,0x00000800,0x00200002}, + { 0x10001040,0x00001000,0x00040000,0x10041040, + 0x10000000,0x10001040,0x00000040,0x10000000, + 0x00040040,0x10040000,0x10041040,0x00041000, + 0x10041000,0x00041040,0x00001000,0x00000040, + 0x10040000,0x10000040,0x10001000,0x00001040, + 0x00041000,0x00040040,0x10040040,0x10041000, + 0x00001040,0x00000000,0x00000000,0x10040040, + 0x10000040,0x10001000,0x00041040,0x00040000, + 0x00041040,0x00040000,0x10041000,0x00001000, + 0x00000040,0x10040040,0x00001000,0x00041040, + 0x10001000,0x00000040,0x10000040,0x10040000, + 0x10040040,0x10000000,0x00040000,0x10001040, + 0x00000000,0x10041040,0x00040040,0x10000040, + 0x10040000,0x10001000,0x10001040,0x00000000, + 0x10041040,0x00041000,0x00041000,0x00001040, + 0x00001040,0x00040040,0x10000000,0x10041000} + }; + + static INLINE void IPERM(word32* left, word32* right) { - byte* const pc1m = buffer; /* place to modify pc1 into */ - byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ - byte* const ks = pcr + 56; - register int i, j, l; - int m; + word32 work; - for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ - l = pc1[j] - 1; /* integer bit location */ - m = l & 07; /* find bit */ - pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ - bytebit[m]) /* and which bit of that byte */ - ? 1 : 0; /* and store 1-bit result */ - } + *right = rotlFixed(*right, 4U); + work = (*left ^ *right) & 0xf0f0f0f0; + *left ^= work; - for (i = 0; i < 16; i++) { /* key chunk for each iteration */ - XMEMSET(ks, 0, 8); /* Clear key schedule */ + *right = rotrFixed(*right^work, 20U); + work = (*left ^ *right) & 0xffff0000; + *left ^= work; - for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ - pcr[j] = - pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; + *right = rotrFixed(*right^work, 18U); + work = (*left ^ *right) & 0x33333333; + *left ^= work; - /* rotate left and right halves independently */ - for (j = 0; j < 48; j++) { /* select bits individually */ - if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ - l= j % 6; /* mask it in if it's there */ - ks[j/6] |= bytebit[l] >> 2; + *right = rotrFixed(*right^work, 6U); + work = (*left ^ *right) & 0x00ff00ff; + *left ^= work; + + *right = rotlFixed(*right^work, 9U); + work = (*left ^ *right) & 0xaaaaaaaa; + *left = rotlFixed(*left^work, 1U); + *right ^= work; + } + + static INLINE void FPERM(word32* left, word32* right) + { + word32 work; + + *right = rotrFixed(*right, 1U); + work = (*left ^ *right) & 0xaaaaaaaa; + *right ^= work; + + *left = rotrFixed(*left^work, 9U); + work = (*left ^ *right) & 0x00ff00ff; + *right ^= work; + + *left = rotlFixed(*left^work, 6U); + work = (*left ^ *right) & 0x33333333; + *right ^= work; + + *left = rotlFixed(*left^work, 18U); + work = (*left ^ *right) & 0xffff0000; + *right ^= work; + + *left = rotlFixed(*left^work, 20U); + work = (*left ^ *right) & 0xf0f0f0f0; + *right ^= work; + + *left = rotrFixed(*left^work, 4U); + } + + static int DesSetKey(const byte* key, int dir, word32* out) + { + #define DES_KEY_BUFFER_SIZE (56+56+8) + #ifdef WOLFSSL_SMALL_STACK + byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (buffer == NULL) + return MEMORY_E; + #else + byte buffer[DES_KEY_BUFFER_SIZE]; + #endif + + { + byte* const pc1m = buffer; /* place to modify pc1 into */ + byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ + byte* const ks = pcr + 56; + register int i, j, l; + int m; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + XMEMSET(ks, 0, 8); /* Clear key schedule */ + + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = + pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; + + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++) { /* select bits individually */ + if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ + l= j % 6; /* mask it in if it's there */ + ks[j/6] |= bytebit[l] >> 2; + } + } + + /* Now convert to odd/even interleaved form for use in F */ + out[2*i] = ((word32) ks[0] << 24) + | ((word32) ks[2] << 16) + | ((word32) ks[4] << 8) + | ((word32) ks[6]); + + out[2*i + 1] = ((word32) ks[1] << 24) + | ((word32) ks[3] << 16) + | ((word32) ks[5] << 8) + | ((word32) ks[7]); + } + + /* reverse key schedule order */ + if (dir == DES_DECRYPTION) { + for (i = 0; i < 16; i += 2) { + word32 swap = out[i]; + out[i] = out[DES_KS_SIZE - 2 - i]; + out[DES_KS_SIZE - 2 - i] = swap; + + swap = out[i + 1]; + out[i + 1] = out[DES_KS_SIZE - 1 - i]; + out[DES_KS_SIZE - 1 - i] = swap; } } - /* Now convert to odd/even interleaved form for use in F */ - out[2*i] = ((word32) ks[0] << 24) - | ((word32) ks[2] << 16) - | ((word32) ks[4] << 8) - | ((word32) ks[6]); - - out[2*i + 1] = ((word32) ks[1] << 24) - | ((word32) ks[3] << 16) - | ((word32) ks[5] << 8) - | ((word32) ks[7]); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif } - /* reverse key schedule order */ - if (dir == DES_DECRYPTION) { - for (i = 0; i < 16; i += 2) { - word32 swap = out[i]; - out[i] = out[DES_KS_SIZE - 2 - i]; - out[DES_KS_SIZE - 2 - i] = swap; - - swap = out[i + 1]; - out[i + 1] = out[DES_KS_SIZE - 1 - i]; - out[DES_KS_SIZE - 1 - i] = swap; - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + return 0; } - return 0; -} - - -static INLINE int Reverse(int dir) -{ - return !dir; -} - - -int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) -{ - wc_Des_SetIV(des, iv); - - return DesSetKey(key, dir, des->key); -} - - -int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) -{ - int ret; - -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3SetKey(des, key, iv); - } -#endif - - ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); - if (ret != 0) - return ret; - - ret = DesSetKey(key + 8, Reverse(dir), des->key[1]); - if (ret != 0) - return ret; - - ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); - if (ret != 0) - return ret; - - return wc_Des3_SetIV(des, iv); -} - - -static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) -{ - word32 l = *lIn, r = *rIn, i; - - for (i=0; i<8; i++) + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { - word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; - l ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = r ^ kptr[4*i+1]; - l ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; + wc_Des_SetIV(des, iv); - work = rotrFixed(l, 4U) ^ kptr[4*i+2]; - r ^= Spbox[6][(work) & 0x3f] - ^ Spbox[4][(work >> 8) & 0x3f] - ^ Spbox[2][(work >> 16) & 0x3f] - ^ Spbox[0][(work >> 24) & 0x3f]; - work = l ^ kptr[4*i+3]; - r ^= Spbox[7][(work) & 0x3f] - ^ Spbox[5][(work >> 8) & 0x3f] - ^ Spbox[3][(work >> 16) & 0x3f] - ^ Spbox[1][(work >> 24) & 0x3f]; + return DesSetKey(key, dir, des->key); } - *lIn = l; *rIn = r; -} + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + /* key_raw holds orignal key copy */ + des->key_raw = key; + des->iv_raw = iv; -static void DesProcessBlock(Des* des, const byte* in, byte* out) -{ - word32 l, r; + /* continue on to set normal key for smaller DES operations */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); + ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); + if (ret != 0) + return ret; - DesRawProcessBlock(&l, &r, des->key); + ret = DesSetKey(key + 8, !dir, des->key[1]); + if (ret != 0) + return ret; - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} + ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); + if (ret != 0) + return ret; - -static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) -{ - word32 l, r; - - XMEMCPY(&l, in, sizeof(l)); - XMEMCPY(&r, in + sizeof(l), sizeof(r)); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - IPERM(&l,&r); - - DesRawProcessBlock(&l, &r, des->key[0]); - DesRawProcessBlock(&r, &l, des->key[1]); - DesRawProcessBlock(&l, &r, des->key[2]); - - FPERM(&l,&r); - #ifdef LITTLE_ENDIAN_ORDER - l = ByteReverseWord32(l); - r = ByteReverseWord32(r); - #endif - XMEMCPY(out, &r, sizeof(r)); - XMEMCPY(out + sizeof(r), &l, sizeof(l)); -} - - -int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; - - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + return wc_Des3_SetIV(des, iv); } - return 0; -} + static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) + { + word32 l = *lIn, r = *rIn, i; -int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; + for (i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - DesProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + *lIn = l; *rIn = r; } - return 0; -} + static void DesProcessBlock(Des* des, const byte* in, byte* out) + { + word32 l, r; -int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcEncrypt(des, out, in, sz); + DesRawProcessBlock(&l, &r, des->key); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); } -#endif - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); - XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) + { + word32 l, r; - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + + DesRawProcessBlock(&l, &r, des->key[0]); + DesRawProcessBlock(&r, &l, des->key[1]); + DesRawProcessBlock(&l, &r, des->key[2]); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); } - return 0; -} + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; -int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks; + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { - return NitroxDes3CbcDecrypt(des, out, in, sz); + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } -#endif - blocks = sz / DES_BLOCK_SIZE; - while (blocks--) { - XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); - Des3ProcessBlock(des, (byte*)des->tmp, out); - xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); - XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } - return 0; -} -#ifdef WOLFSSL_DES_ECB + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; -/* One block, compatibility only */ -int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) -{ - word32 blocks = sz / DES_BLOCK_SIZE; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcEncrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DES3_CBC_ENCRYPT; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ - while (blocks--) { - DesProcessBlock(des, in, out); + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); - out += DES_BLOCK_SIZE; - in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; } - return 0; -} -#endif /* WOLFSSL_DES_ECB */ -#endif /* End wolfCrypt software implementation */ + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + #if defined(WOLFSSL_ASYNC_CRYPT) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcDecrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DES3_CBC_DECRYPT; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + DesProcessBlock(des, in, out); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + /* printf("wc_Des3_EcbEncrypt(%016x, %016x, %d)\n", + *(unsigned long *)in, *(unsigned long *)out, sz) ; */ + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + Des3ProcessBlock(des, in, out); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + #endif /* WOLFSSL_DES_ECB */ + +#endif /* NEED_SOFT_DES */ void wc_Des_SetIV(Des* des, const byte* iv) @@ -1639,7 +1659,6 @@ void wc_Des_SetIV(Des* des, const byte* iv) XMEMSET(des->reg, 0, DES_BLOCK_SIZE); } - int wc_Des3_SetIV(Des3* des, const byte* iv) { if (des && iv) @@ -1651,28 +1670,35 @@ int wc_Des3_SetIV(Des3* des, const byte* iv) } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Des3 for use with Nitrox device */ -int wc_Des3AsyncInit(Des3* des3, int devId) +/* Initialize Des3 for use with async device */ +int wc_Des3Init(Des3* des3, void* heap, int devId) { + int ret = 0; if (des3 == NULL) return BAD_FUNC_ARG; - return wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, devId); + des3->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, + des3->heap, devId); +#else + (void)devId; +#endif + + return ret; } - -/* Free Des3 from use with Nitrox device */ -void wc_Des3AsyncFree(Des3* des3) +/* Free Des3 from use with async device */ +void wc_Des3Free(Des3* des3) { if (des3 == NULL) return; - wolfAsync_DevCtxFree(&des3->asyncDev); -} - +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES); #endif /* WOLFSSL_ASYNC_CRYPT */ +} #endif /* WOLFSSL_TI_CRYPT */ #endif /* HAVE_FIPS */ diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c old mode 100644 new mode 100755 index b300e5e0d..f6e2caf21 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -30,6 +30,15 @@ #include #include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + #if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST) #include @@ -39,48 +48,502 @@ /* user's own math lib */ #endif +#ifdef HAVE_FFDHE_2048 +static const byte dh_ffdhe2048_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe2048_g[] = { 0x02 }; -#if !defined(WOLFSSL_HAVE_MIN) && !defined(WOLFSSL_DH_CONST) -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitDhKey(DhKey* key) +const DhParams* wc_Dh_ffdhe2048_Get(void) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = NULL; - key->g.dp = NULL; + static const DhParams ffdhe2048 = { + dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p), + dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g) + }; + return &ffdhe2048; +} #endif + +#ifdef HAVE_FFDHE_3072 +static const byte dh_ffdhe3072_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe3072_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe3072_Get(void) +{ + static const DhParams ffdhe3072 = { + dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p), + dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g) + }; + return &ffdhe3072; +} +#endif + +#ifdef HAVE_FFDHE_4096 +static const byte dh_ffdhe4096_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe4096_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe4096_Get(void) +{ + static const DhParams ffdhe4096 = { + dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p), + dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g) + }; + return &ffdhe4096; +} +#endif + +#ifdef HAVE_FFDHE_6144 +static const byte dh_ffdhe6144_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe6144_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe6144_Get(void) +{ + static const DhParams ffdhe6144 = { + dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p), + dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g) + }; + return &ffdhe6144; +} +#endif + +#ifdef HAVE_FFDHE_8192 +static const byte dh_ffdhe8192_p[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const byte dh_ffdhe8192_g[] = { 0x02 }; + +const DhParams* wc_Dh_ffdhe8192_Get(void) +{ + static const DhParams ffdhe8192 = { + dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p), + dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g) + }; + return &ffdhe8192; +} +#endif + +int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + key->heap = heap; /* for XMALLOC/XFREE in future */ + + if (mp_init_multi(&key->p, &key->g, NULL, NULL, NULL, NULL) != MP_OKAY) + return MEMORY_E; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH, + key->heap, devId); +#else + (void)devId; +#endif + + return ret; +} + +int wc_InitDhKey(DhKey* key) +{ + return wc_InitDhKey_ex(key, NULL, INVALID_DEVID); } void wc_FreeDhKey(DhKey* key) { - (void)key; - mp_clear(&key->p); - mp_clear(&key->g); + if (key) { + mp_clear(&key->p); + mp_clear(&key->g); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); + #endif + } } /* if defined to not use floating point values do not compile in */ #ifndef WOLFSSL_DH_CONST -static word32 DiscreteLogWorkFactor(word32 n) -{ - /* assuming discrete log takes about the same time as factoring */ - if (n<5) - return 0; - else - return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * - XPOW(XLOG((double)n), 2.0/3.0) - 5); -} + static word32 DiscreteLogWorkFactor(word32 n) + { + /* assuming discrete log takes about the same time as factoring */ + if (n < 5) + return 0; + else + return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * + XPOW(XLOG((double)n), 2.0/3.0) - 5); + } #endif /* WOLFSSL_DH_CONST*/ @@ -100,9 +563,9 @@ static word32 DiscreteLogWorkFactor(word32 n) #endif -static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) +static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) { - int ret; + int ret = 0; word32 sz = mp_unsigned_bin_size(&key->p); /* Table of predetermined values from the operation @@ -120,33 +583,31 @@ static int GeneratePrivate(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz) case 896: sz = 49; break; case 1024: sz = 52; break; default: - #ifndef WOLFSSL_DH_CONST - /* if using floating points and size of p is not in table */ - sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / - WOLFSSL_BIT_SIZE + 1); - break; - #else - return BAD_FUNC_ARG; - #endif + #ifndef WOLFSSL_DH_CONST + /* if using floating points and size of p is not in table */ + sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1); + break; + #else + return BAD_FUNC_ARG; + #endif } ret = wc_RNG_GenerateBlock(rng, priv, sz); - if (ret != 0) - return ret; - priv[0] |= 0x0C; + if (ret == 0) { + priv[0] |= 0x0C; + *privSz = sz; + } - *privSz = sz; - - return 0; + return ret; } -static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, - byte* pub, word32* pubSz) +static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, + byte* pub, word32* pubSz) { int ret = 0; - mp_int x; mp_int y; @@ -171,24 +632,163 @@ static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz, return ret; } - -int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, word32* privSz, - byte* pub, word32* pubSz) +static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) { - int ret = GeneratePrivate(key, rng, priv, privSz); + int ret; - return (ret != 0) ? ret : GeneratePublic(key, priv, *privSz, pub, pubSz); + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + + ret = GeneratePrivateDh(key, rng, priv, privSz); + + return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz); } -int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, - word32 privSz, const byte* otherPub, word32 pubSz) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + +#if defined(HAVE_INTEL_QA) + mp_int x; + + ret = mp_init(&x); + if (ret != MP_OKAY) + return ret; + + ret = GeneratePrivateDh(key, rng, priv, privSz); + if (ret == 0) + ret = mp_read_unsigned_bin(&x, priv, *privSz); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&x, &x.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->g, &key->g.raw); + if (ret == MP_OKAY) + ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw, + &x.raw, pub, pubSz); + mp_clear(&x); + +#else + + #if defined(HAVE_CAVIUM) + /* TODO: Not implemented - use software for now */ + + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DH_GEN; + testDev->dhGen.key = key; + testDev->dhGen.rng = rng; + testDev->dhGen.priv = priv; + testDev->dhGen.privSz = privSz; + testDev->dhGen.pub = pub; + testDev->dhGen.pubSz = pubSz; + return WC_PENDING_E; + } + #endif + + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + +#endif /* HAVE_INTEL_QA */ + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */ + + +/* Check DH Public Key for invalid numbers + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) { int ret = 0; - mp_int x; + mp_int x; + mp_int y; + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + + if (mp_init_multi(&x, &y, NULL, NULL, NULL, NULL) != MP_OKAY) { + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&x, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + /* pub should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(&x, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, &y) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(&y, 2, &y) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(&x, &y) == MP_GT) { + ret = MP_CMP_E; + } + + mp_clear(&y); + mp_clear(&x); + + return ret; +} + + +int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz); + } + else +#endif + { + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + } + + return ret; +} + + +static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + mp_int x; mp_int y; mp_int z; + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } + if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY) return MP_INIT_E; @@ -209,7 +809,65 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, mp_clear(&z); mp_clear(&y); - mp_clear(&x); + mp_forcezero(&x); + + return ret; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + +#elif defined(HAVE_INTEL_QA) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw, + agree, agreeSz, priv, privSz, otherPub, pubSz); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_DH_AGREE; + testDev->dhAgree.key = key; + testDev->dhAgree.agree = agree; + testDev->dhAgree.agreeSz = agreeSz; + testDev->dhAgree.priv = priv; + testDev->dhAgree.privSz = privSz; + testDev->dhAgree.otherPub = otherPub; + testDev->dhAgree.pubSz = pubSz; + return WC_PENDING_E; + } + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); +#endif + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, + word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + + if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL || + otherPub == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } + else +#endif + { + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } return ret; } @@ -219,8 +877,9 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) { - if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) { return BAD_FUNC_ARG; + } /* may have leading 0 */ if (p[0] == 0) { @@ -251,6 +910,4 @@ int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, return 0; } - #endif /* NO_DH */ - diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index d9ba8ac03..8719b4a56 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -35,6 +35,13 @@ #include #include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + enum { DSA_HALF_SIZE = 20, /* r and s size */ @@ -42,50 +49,49 @@ enum { }; -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - -void wc_InitDsaKey(DsaKey* key) +int wc_InitDsaKey(DsaKey* key) { + if (key == NULL) + return BAD_FUNC_ARG; + key->type = -1; /* haven't decided yet */ key->heap = NULL; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH - key->p.dp = 0; /* public alloc parts */ - key->q.dp = 0; - key->g.dp = 0; - key->y.dp = 0; + return mp_init_multi( + /* public alloc parts */ + &key->p, + &key->q, + &key->g, + &key->y, - key->x.dp = 0; /* private alloc parts */ -#endif + /* private alloc parts */ + &key->x, + NULL + ); } int wc_InitDsaKey_h(DsaKey* key, void* h) { - wc_InitDsaKey(key); - key->heap = h; + int ret = wc_InitDsaKey(key); + if (ret == 0) + key->heap = h; - return 0; + return ret; } void wc_FreeDsaKey(DsaKey* key) { - (void)key; -/* TomsFastMath doesn't use memory allocation */ -#ifndef USE_FAST_MATH + if (key == NULL) + return; + if (key->type == DSA_PRIVATE) - mp_clear(&key->x); + mp_forcezero(&key->x); + +#ifndef USE_FAST_MATH + mp_clear(&key->x); mp_clear(&key->y); mp_clear(&key->g); mp_clear(&key->q); @@ -151,7 +157,7 @@ int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) } dsa->type = DSA_PRIVATE; - + return MP_OKAY; } @@ -315,7 +321,13 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) } /* find a value g for which g^tmp2 != 1 */ - mp_set(&dsa->g, 1); + if (mp_set(&dsa->g, 1) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } do { err = mp_add_d(&dsa->g, 1, &dsa->g); @@ -359,7 +371,7 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) byte* tmp = out; /* initial output pointer */ sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); - + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) return MP_INIT_E; @@ -373,12 +385,12 @@ int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) ret = MP_READ_E; - + /* k is a random numnber and it should be less than q * if k greater than repeat */ } while (mp_cmp(&k, &key->q) != MP_LT); - + if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) ret = MP_CMP_E; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c old mode 100644 new mode 100755 index ecdc408a2..3fb8287c4 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -35,14 +35,21 @@ Possible ECC enable options: * HAVE_ECC_SIGN: ECC sign default: on * HAVE_ECC_VERIFY: ECC verify default: on * HAVE_ECC_DHE: ECC build shared secret default: on + * HAVE_ECC_CDH: ECC cofactor DH shared secret default: off * HAVE_ECC_KEY_IMPORT: ECC Key import default: on * HAVE_ECC_KEY_EXPORT: ECC Key export default: on * ECC_SHAMIR: Enables Shamir calc method default: on * HAVE_COMP_KEY: Enables compressed key default: off * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import default: off + * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen default: off * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off * Includes the curve "a" variable in calculation - * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + default: off + * FP_ECC: ECC Fixed Point Cache default: off + * USE_ECC_B_PARAM: Enable ECC curve B param default: off + (on for HAVE_COMP_KEY) */ /* @@ -118,6 +125,22 @@ ECC Curve Sizes: #endif +/* internal ECC states */ +enum { + ECC_STATE_NONE = 0, + + ECC_STATE_SHARED_SEC_GEN, + ECC_STATE_SHARED_SEC_RES, + + ECC_STATE_SIGN_DO, + ECC_STATE_SIGN_ENCODE, + + ECC_STATE_VERIFY_DECODE, + ECC_STATE_VERIFY_DO, + ECC_STATE_VERIFY_RES, +}; + + /* map ptmul -> mulmod */ @@ -912,6 +935,7 @@ const ecc_set_type ecc_sets[] = { NULL, 0, 0, 0 } }; +#define ECC_SET_COUNT (sizeof(ecc_sets)/sizeof(ecc_set_type)) #ifdef HAVE_OID_ENCODING /* encoded OID cache */ @@ -919,20 +943,16 @@ const ecc_set_type ecc_sets[] = { word32 oidSz; byte oid[ECC_MAX_OID_LEN]; } oid_cache_t; - static oid_cache_t ecc_oid_cache[sizeof(ecc_sets)/sizeof(ecc_set_type)]; + static oid_cache_t ecc_oid_cache[ECC_SET_COUNT]; #endif + #ifdef HAVE_COMP_KEY static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); #endif #ifndef WOLFSSL_ATECC508A -int ecc_map(ecc_point*, mp_int*, mp_digit); -int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, - mp_int* a, mp_int* modulus, mp_digit mp); -int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, - mp_int* modulus, mp_digit mp); static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, mp_int* order); #ifdef ECC_SHAMIR static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, @@ -942,10 +962,276 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, int mp_jacobi(mp_int* a, mp_int* n, int* c); int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); + +/* Curve Specs */ +typedef struct ecc_curve_spec { + const ecc_set_type* dp; + + mp_int* prime; + mp_int* Af; + #ifdef USE_ECC_B_PARAM + mp_int* Bf; + #endif + mp_int* order; + mp_int* Gx; + mp_int* Gy; + +#ifdef ECC_CACHE_CURVE + mp_int prime_lcl; + mp_int Af_lcl; + #ifdef USE_ECC_B_PARAM + mp_int Bf_lcl; + #endif + mp_int order_lcl; + mp_int Gx_lcl; + mp_int Gy_lcl; +#else + mp_int* spec_ints; + word32 spec_count; + word32 spec_use; +#endif + + byte load_mask; +} ecc_curve_spec; + +enum ecc_curve_load_mask { + ECC_CURVE_FIELD_NONE = 0x00, + ECC_CURVE_FIELD_PRIME = 0x01, + ECC_CURVE_FIELD_AF = 0x02, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_BF = 0x04, +#endif + ECC_CURVE_FIELD_ORDER = 0x08, + ECC_CURVE_FIELD_GX = 0x10, + ECC_CURVE_FIELD_GY = 0x20, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_ALL = 0x3F, + ECC_CURVE_FIELD_COUNT = 6, +#else + ECC_CURVE_FIELD_ALL = 0x3B, + ECC_CURVE_FIELD_COUNT = 5, +#endif +}; + +#ifdef ECC_CACHE_CURVE + /* cache (mp_int) of the curve parameters */ + static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT]; + #ifndef SINGLE_THREADED + static wolfSSL_Mutex ecc_curve_cache_mutex; + #endif + + #define DECLARE_CURVE_SPECS(intcount) ecc_curve_spec* curve = NULL; +#else + #define DECLARE_CURVE_SPECS(intcount) \ + mp_int spec_ints[(intcount)]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ + curve->spec_count = intcount; +#endif /* ECC_CACHE_CURVE */ + +static void _wc_ecc_curve_free(ecc_curve_spec* curve) +{ + if (curve == NULL) { + return; + } + + if (curve->load_mask & ECC_CURVE_FIELD_PRIME) + mp_clear(curve->prime); + if (curve->load_mask & ECC_CURVE_FIELD_AF) + mp_clear(curve->Af); +#ifdef USE_ECC_B_PARAM + if (curve->load_mask & ECC_CURVE_FIELD_BF) + mp_clear(curve->Bf); +#endif + if (curve->load_mask & ECC_CURVE_FIELD_ORDER) + mp_clear(curve->order); + if (curve->load_mask & ECC_CURVE_FIELD_GX) + mp_clear(curve->Gx); + if (curve->load_mask & ECC_CURVE_FIELD_GY) + mp_clear(curve->Gy); + + curve->load_mask = 0; +} + +static void wc_ecc_curve_free(ecc_curve_spec* curve) +{ + /* don't free cached curves */ +#ifndef ECC_CACHE_CURVE + _wc_ecc_curve_free(curve); +#endif + (void)curve; +} + +static int wc_ecc_curve_load_item(const char* src, mp_int** dst, + ecc_curve_spec* curve, byte mask) +{ + int err; + +#ifndef ECC_CACHE_CURVE + /* get mp_int from temp */ + if (curve->spec_use >= curve->spec_count) { + WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count"); + return ECC_BAD_ARG_E; + } + *dst = &curve->spec_ints[curve->spec_use++]; +#endif + + err = mp_init(*dst); + if (err == MP_OKAY) { + curve->load_mask |= mask; + + err = mp_read_radix(*dst, src, 16); + + #ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(*dst, &(*dst)->raw); + #endif + } + return err; +} + +static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, + byte load_mask) +{ + int ret = 0, x; + ecc_curve_spec* curve; + byte load_items = 0; /* mask of items to load */ + + if (dp == NULL || pCurve == NULL) + return BAD_FUNC_ARG; + +#ifdef ECC_CACHE_CURVE + x = wc_ecc_get_curve_idx(dp->id); + if (x == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + + /* make sure cache has been allocated */ + if (ecc_curve_spec_cache[x] == NULL) { + ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC( + sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC); + if (ecc_curve_spec_cache[x] == NULL) + return MEMORY_E; + XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec)); + } + + /* set curve pointer to cache */ + *pCurve = ecc_curve_spec_cache[x]; + +#endif /* ECC_CACHE_CURVE */ + curve = *pCurve; + + /* make sure the curve is initialized */ + if (curve->dp != dp) { + curve->load_mask = 0; + + #ifdef ECC_CACHE_CURVE + curve->prime = &curve->prime_lcl; + curve->Af = &curve->Af_lcl; + #ifdef USE_ECC_B_PARAM + curve->Bf = &curve->Bf_lcl; + #endif + curve->order = &curve->order_lcl; + curve->Gx = &curve->Gx_lcl; + curve->Gy = &curve->Gy_lcl; + #endif + } + curve->dp = dp; /* set dp info */ + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_LockMutex(&ecc_curve_cache_mutex); + if (ret != 0) { + return MEMORY_E; + } +#endif + + /* determine items to load */ + load_items = (~curve->load_mask & load_mask); + curve->load_mask |= load_items; + + /* load items */ + x = 0; + if (load_items & ECC_CURVE_FIELD_PRIME) + x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve, + ECC_CURVE_FIELD_PRIME); + if (load_items & ECC_CURVE_FIELD_AF) + x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve, + ECC_CURVE_FIELD_AF); +#ifdef USE_ECC_B_PARAM + if (load_items & ECC_CURVE_FIELD_BF) + x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve, + ECC_CURVE_FIELD_BF); +#endif + if (load_items & ECC_CURVE_FIELD_ORDER) + x += wc_ecc_curve_load_item(dp->order, &curve->order, curve, + ECC_CURVE_FIELD_ORDER); + if (load_items & ECC_CURVE_FIELD_GX) + x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve, + ECC_CURVE_FIELD_GX); + if (load_items & ECC_CURVE_FIELD_GY) + x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve, + ECC_CURVE_FIELD_GY); + + /* check for error */ + if (x != 0) { + wc_ecc_curve_free(curve); + ret = MP_READ_E; + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); +#endif + + return ret; +} + +#ifdef ECC_CACHE_CURVE +int wc_ecc_curve_cache_init(void) +{ + int ret = 0; +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_InitMutex(&ecc_curve_cache_mutex); +#endif + return ret; +} + +void wc_ecc_curve_cache_free(void) +{ + int x; + + /* free all ECC curve caches */ + for (x = 0; x < (int)ECC_SET_COUNT; x++) { + if (ecc_curve_spec_cache[x]) { + _wc_ecc_curve_free(ecc_curve_spec_cache[x]); + XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC); + ecc_curve_spec_cache[x] = NULL; + } + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_FreeMutex(&ecc_curve_cache_mutex); +#endif +} +#endif /* ECC_CACHE_CURVE */ + #endif /* WOLFSSL_ATECC508A */ -static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) +/* Retrieve the curve name for the ECC curve id. + * + * curve_id The id of the curve. + * returns the name stored from the curve if available, otherwise NULL. + */ +const char* wc_ecc_get_name(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return NULL; + return ecc_sets[curve_idx].name; +} + +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) { if (keysize <= 0 && curve_id <= 0) { return BAD_FUNC_ARG; @@ -970,7 +1256,8 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) } } if (ecc_sets[x].size == 0) { - return ECC_BAD_ARG_E; + WOLFSSL_MSG("ECC Curve not found"); + return ECC_CURVE_OID_E; } key->idx = x; @@ -982,24 +1269,6 @@ static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) #ifndef WOLFSSL_ATECC508A -/* helper for either lib */ -static int get_digit_count(mp_int* a) -{ - if (a == NULL) - return 0; - - return a->used; -} - -/* helper for either lib */ -static mp_digit get_digit(mp_int* a, int n) -{ - if (a == NULL) - return 0; - - return (n >= a->used || n < 0) ? 0 : a->dp[n]; -} - /** Add two ECC points P The point to add @@ -1042,10 +1311,8 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if ( (mp_cmp(P->x, Q->x) == MP_EQ) && (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return ecc_projective_dbl_point(P, R, a, modulus, mp); } } @@ -1271,11 +1538,10 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, #endif done: -#ifndef USE_FAST_MATH + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1333,10 +1599,8 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, z = &rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - #ifndef USE_FAST_MATH mp_clear(&t1); mp_clear(&t2); - #endif return err; } #else @@ -1543,11 +1807,9 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, err = mp_copy(z, R->z); #endif -#ifndef USE_FAST_MATH /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -1574,10 +1836,12 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) /* special case for point at infinity */ if (mp_cmp_d(P->z, 0) == MP_EQ) { - mp_set(P->x, 0); - mp_set(P->y, 0); - mp_set(P->z, 1); - return MP_OKAY; + err = mp_set(P->x, 0); + if (err == MP_OKAY) + err = mp_set(P->y, 0); + if (err == MP_OKAY) + err = mp_set(P->z, 1); + return err; } if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { @@ -1600,6 +1864,10 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_copy(P->y, y); if (err == MP_OKAY) err = mp_copy(P->z, z); + + if (err != MP_OKAY) { + goto done; + } #else /* Use destination directly */ x = P->x; @@ -1607,10 +1875,6 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) z = P->z; #endif - if (err != MP_OKAY) { - goto done; - } - /* first map z back to normal */ err = mp_montgomery_reduce(z, modulus, mp); @@ -1639,32 +1903,29 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) err = mp_montgomery_reduce(y, modulus, mp); if (err == MP_OKAY) - mp_set(z, 1); + err = mp_set(z, 1); #ifdef ALT_ECC_SIZE /* return result */ - mp_copy(x, P->x); - mp_copy(y, P->y); - mp_copy(z, P->z); -#endif + if (err == MP_OKAY) + err = mp_copy(x, P->x); + if (err == MP_OKAY) + err = mp_copy(y, P->y); + if (err == MP_OKAY) + err = mp_copy(z, P->z); done: - /* clean up */ -#ifndef USE_FAST_MATH +#endif + + /* clean up */ mp_clear(&t1); mp_clear(&t2); -#endif return err; } #if !defined(FREESCALE_LTC_ECC) -#ifndef ECC_TIMING_RESISTANT - -/* size of sliding window, don't change this! */ -#define WINSIZE 4 - /** Perform a point multiplication k The scalar to multiply by @@ -1678,22 +1939,33 @@ done: */ #ifdef FP_ECC static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, + void* heap) #else int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, + void* heap) #endif { - ecc_point *tG, *M[8]; - int i, j, err; +#ifndef ECC_TIMING_RESISTANT + /* size of sliding window, don't change this! */ + #define WINSIZE 4 + #define M_POINTS 8 + int first = 1, bitbuf = 0, bitcpy = 0, j; +#else + #define M_POINTS 3 +#endif + + ecc_point *tG, *M[M_POINTS]; + int i, err; mp_int mu; mp_digit mp; mp_digit buf; - int first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0, - digidx = 0; + int bitcnt = 0, mode = 0, digidx = 0; - if (k == NULL || G == NULL || R == NULL || modulus == NULL) + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; + } /* init variables */ tG = NULL; @@ -1703,6 +1975,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { return err; } + if ((err = mp_init(&mu)) != MP_OKAY) { return err; } @@ -1712,16 +1985,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } /* alloc ram for window temps */ - for (i = 0; i < 8; i++) { + for (i = 0; i < M_POINTS; i++) { M[i] = wc_ecc_new_point_h(heap); if (M[i] == NULL) { - for (j = 0; j < i; j++) { - wc_ecc_del_point_h(M[j], heap); - } - #ifndef USE_FAST_MATH mp_clear(&mu); - #endif - return MEMORY_E; + err = MEMORY_E; goto exit; } } @@ -1747,10 +2015,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } } -#ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); -#endif + +#ifndef ECC_TIMING_RESISTANT /* calc the M tab, which holds kG for k==8..15 */ /* M[0] == 8G */ @@ -1764,7 +2032,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* now find (8+k)G for k=1..7 */ if (err == MP_OKAY) for (j = 9; j < 16; j++) { - err = ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus, mp); + err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, + modulus, mp); if (err != MP_OKAY) break; } @@ -1812,13 +2081,13 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* if this is the first window we do a simple copy */ if (first == 1) { /* R = kG [k = first window] */ - err = mp_copy(M[bitbuf-8]->x, R->x); + err = mp_copy(M[bitbuf-M_POINTS]->x, R->x); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->y, R->y); + err = mp_copy(M[bitbuf-M_POINTS]->y, R->y); if (err != MP_OKAY) break; - err = mp_copy(M[bitbuf-8]->z, R->z); + err = mp_copy(M[bitbuf-M_POINTS]->z, R->z); first = 0; } else { /* normal window */ @@ -1831,7 +2100,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (err != MP_OKAY) break; /* out of first for(;;) */ /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ - err = ecc_projective_add_point(R, M[bitbuf-8], R, a, + err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a, modulus, mp); } if (err != MP_OKAY) break; @@ -1877,127 +2146,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } } - /* map R back from projective space */ - if (err == MP_OKAY && map) - err = ecc_map(R, modulus, mp); - - wc_ecc_del_point_h(tG, heap); - for (i = 0; i < 8; i++) { - wc_ecc_del_point_h(M[i], heap); - } - return err; -} - -#ifndef FP_ECC -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) -{ - return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); -} -#endif /* !FP_ECC */ -#undef WINSIZE + #undef WINSIZE #else /* ECC_TIMING_RESISTANT */ - -#ifndef WC_NO_CACHE_RESISTANT -#if defined(TFM_TIMING_RESISTANT) && defined(USE_FAST_MATH) && \ - !defined(__cplusplus) - /* let's use the one we already have */ - extern const wolfssl_word wc_off_on_addr[2]; -#else - static const wolfssl_word wc_off_on_addr[2] = - { - #if defined(WC_64BIT_CPU) - W64LIT(0x0000000000000000), - W64LIT(0xffffffffffffffff) - #elif defined(WC_16BIT_CPU) - 0x0000U, - 0xffffU - #else - /* 32 bit */ - 0x00000000U, - 0xffffffffU - #endif - }; -#endif /* TFM_TIMING_RESISTANT && USE_FAST_MATH */ -#endif /* WC_NO_CACHE_RESISTANT */ - -/** - Perform a point multiplication (timing resistant) - k The scalar to multiply by - G The base point - R [out] Destination for kG - a ECC curve parameter a - modulus The modulus of the field the ECC curve is in - map Boolean whether to map back to affine or not - (1==map, 0 == leave in projective) - return MP_OKAY on success -*/ -#ifdef FP_ECC -static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) -#else -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* a, mp_int* modulus, int map, void* heap) -#endif -{ - ecc_point *tG, *M[3]; - int i, j, err; - mp_int mu; - mp_digit mp; - mp_digit buf; - int bitcnt = 0, mode = 0, digidx = 0; - - if (k == NULL || G == NULL || R == NULL || modulus == NULL) - return ECC_BAD_ARG_E; - - /* init variables */ - tG = NULL; - XMEMSET(M, 0, sizeof(M)); - - /* init montgomery reduction */ - if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { - return err; - } - if ((err = mp_init(&mu)) != MP_OKAY) { - return err; - } - if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - mp_clear(&mu); - return err; - } - - /* alloc ram for window temps */ - for (i = 0; i < 3; i++) { - M[i] = wc_ecc_new_point_h(heap); - if (M[i] == NULL) { - for (j = 0; j < i; j++) { - wc_ecc_del_point_h(M[j], heap); - } - mp_clear(&mu); - return MEMORY_E; - } - } - - /* make a copy of G in case R==G */ - tG = wc_ecc_new_point_h(heap); - if (tG == NULL) - err = MEMORY_E; - - /* tG = G and convert to montgomery */ - if (err == MP_OKAY) - err = mp_mulmod(G->x, &mu, modulus, tG->x); - if (err == MP_OKAY) - err = mp_mulmod(G->y, &mu, modulus, tG->y); - if (err == MP_OKAY) - err = mp_mulmod(G->z, &mu, modulus, tG->z); - -#ifndef USE_FAST_MATH - /* done with mu */ - mp_clear(&mu); -#endif - /* calc the M tab */ /* M[0] == G */ if (err == MP_OKAY) @@ -2114,27 +2266,38 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (err == MP_OKAY) err = mp_copy(M[0]->z, R->z); +#endif /* ECC_TIMING_RESISTANT */ + /* map R back from projective space */ if (err == MP_OKAY && map) - err = ecc_map(R, modulus, mp); + err = ecc_map(R, modulus, mp); + +exit: /* done */ wc_ecc_del_point_h(tG, heap); - for (i = 0; i < 3; i++) { + for (i = 0; i < M_POINTS; i++) { wc_ecc_del_point_h(M[i], heap); } + return err; } - -#ifndef FP_ECC +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine co-ordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) + mp_int* modulus, int map) { return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } -#endif /* ! FP_ECC */ -#endif /* ECC_TIMING_RESISTANT */ #endif /* !FREESCALE_LTC_ECC */ @@ -2164,12 +2327,6 @@ ecc_point* wc_ecc_new_point_h(void* heap) } XMEMSET(p, 0, sizeof(ecc_point)); -#ifndef USE_FAST_MATH - p->x->dp = NULL; - p->y->dp = NULL; - p->z->dp = NULL; -#endif - #ifndef ALT_ECC_SIZE if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) { XFREE(p, heap, DYNAMIC_TYPE_ECC); @@ -2294,6 +2451,203 @@ int wc_ecc_is_valid_idx(int n) return 0; } +int wc_ecc_get_curve_idx(int curve_id) +{ + int curve_idx; + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (curve_id == ecc_sets[curve_idx].id) + break; + } + if (ecc_sets[curve_idx].size == 0) { + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +int wc_ecc_get_curve_id(int curve_idx) +{ + if (wc_ecc_is_valid_idx(curve_idx)) { + return ecc_sets[curve_idx].id; + } + return ECC_CURVE_INVALID; +} + +/* Returns the curve size that corresponds to a given ecc_curve_id identifier + * + * id curve id, from ecc_curve_id enum in ecc.h + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_id(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + return ecc_sets[curve_idx].size; +} + +/* Returns the curve index that corresponds to a given curve name in + * ecc_sets[] of ecc.c + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve index in ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_idx_from_name(const char* curveName) +{ + int curve_idx; + word32 len; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(curveName); + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +/* Returns the curve size that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].size; +} + +/* Returns the curve id that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].id; +} + +/* Compares a curve parameter (hex, from ecc_sets[]) to given input + * parameter (byte array) for equality. + * + * Returns MP_EQ on success, negative on error */ +static int wc_ecc_cmp_param(const char* curveParam, + const byte* param, word32 paramSz) +{ + int err = MP_OKAY; + mp_int a, b; + + if (param == NULL || curveParam == NULL) + return BAD_FUNC_ARG; + + if ((err = mp_init_multi(&a, &b, NULL, NULL, NULL, NULL)) != MP_OKAY) + return err; + + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&a, param, paramSz); + + if (err == MP_OKAY) + err = mp_read_radix(&b, curveParam, 16); + + if (err == MP_OKAY) { + if (mp_cmp(&a, &b) != MP_EQ) { + err = -1; + } else { + err = MP_EQ; + } + } + +#ifndef USE_FAST_MATH + mp_clear(&a); + mp_clear(&b); +#endif + + return err; +} + +/* Returns the curve id in ecc_sets[] that corresponds to a given set of + * curve parameters. + * + * fieldSize the field size in bits + * prime prime of the finite field + * primeSz size of prime in octets + * Af first coefficient a of the curve + * AfSz size of Af in octets + * Bf second coefficient b of the curve + * BfSz size of Bf in octets + * order curve order + * orderSz size of curve in octets + * Gx affine x coordinate of base point + * GxSz size of Gx in octets + * Gy affine y coordinate of base point + * GySz size of Gy in octets + * cofactor curve cofactor + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor) +{ + int idx; + int curveSz; + + if (prime == NULL || Af == NULL || Bf == NULL || order == NULL || + Gx == NULL || Gy == NULL) + return BAD_FUNC_ARG; + + curveSz = (fieldSize + 1) / 8; /* round up */ + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (curveSz == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime, + primeSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, order, + orderSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz) == MP_EQ) && + (cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + + #ifdef HAVE_ECC_DHE /** Create an ECC shared secret between two keys @@ -2307,13 +2661,7 @@ int wc_ecc_is_valid_idx(int n) int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32* outlen) { - int err = 0; -#ifndef WOLFSSL_ATECC508A - word32 x = 0; - ecc_point* result; - mp_int prime; - mp_int a; -#endif /* !WOLFSSL_ATECC508A */ + int err; if (private_key == NULL || public_key == NULL || out == NULL || outlen == NULL) { @@ -2331,84 +2679,167 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return ECC_BAD_ARG_E; } - /* Verify curve name matches */ - if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0) { + /* Verify curve id matches */ + if (private_key->dp->id != public_key->dp->id) { return ECC_BAD_ARG_E; } -#ifdef WOLFSSL_ASYNC_CRYPT - if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &private_key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_SHARED_SEC; - testDev->eccSharedSec.private_key = private_key; - testDev->eccSharedSec.public_key = public_key; - testDev->eccSharedSec.out = out; - testDev->eccSharedSec.outLen = outlen; - return WC_PENDING_E; - } - #endif - } -#endif - #ifdef WOLFSSL_ATECC508A err = atcatls_ecdh(private_key->slot, public_key->pubkey, out); if (err != ATCA_SUCCESS) { err = BAD_COND_E; } *outlen = private_key->dp->size; - #else - - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } - - if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - wc_ecc_del_point_h(result, private_key->heap); - return err; - } - - /* read in the specs for this curve */ - err = mp_read_radix(&prime, private_key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, private_key->dp->Af, 16); - - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&private_key->k, &public_key->pubkey, result, &a, - &prime, 1, private_key->heap); - - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&prime); - if (*outlen < x) - err = BUFFER_E; - } - - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x,out + (x - - mp_unsigned_bin_size(result->x))); - *outlen = x; - } - -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); -#endif - wc_ecc_del_point_h(result, private_key->heap); - + err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen); #endif /* WOLFSSL_ATECC508A */ return err; } + #ifndef WOLFSSL_ATECC508A +static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen, ecc_curve_spec* curve) +{ + int err; + ecc_point* result = NULL; + word32 x = 0; + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; + + /* if cofactor flag has been set */ + if (private_key->flags & WC_ECC_FLAG_COFACTOR) { + mp_digit cofactor = (mp_digit)private_key->dp->cofactor; + /* only perform cofactor calc if not equal to 1 */ + if (cofactor != 1) { + k = &k_lcl; + if (mp_init(k) != MP_OKAY) + return MEMORY_E; + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } + } + } +#endif + + /* make new point */ + result = wc_ecc_new_point_h(private_key->heap); + if (result == NULL) { +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + return MEMORY_E; + } + + err = wc_ecc_mulmod_ex(k, point, result, + curve->Af, curve->prime, 1, private_key->heap); + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(curve->prime); + if (*outlen < x) { + err = BUFFER_E; + } + } + + if (err == MP_OKAY) { + XMEMSET(out, 0, x); + err = mp_to_unsigned_bin(result->x,out + + (x - mp_unsigned_bin_size(result->x))); + } + *outlen = x; + + wc_ecc_del_point_h(result, private_key->heap); +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + + return err; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, + ecc_point* point, byte* out, word32 *outlen, + ecc_curve_spec* curve) +{ + int err; + +#ifdef HAVE_CAVIUM + /* TODO: Not implemented - use software for now */ + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); + +#elif defined(HAVE_INTEL_QA) + /* sync public key x/y */ + err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&private_key->k, &private_key->k.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->x, &point->x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(point->y, &point->y->raw); + if (err == MP_OKAY) + err = IntelQaEcdh(&private_key->asyncDev, + &private_key->k.raw, &point->x->raw, &point->y->raw, + out, outlen, + &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, + private_key->dp->cofactor); +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + WC_ASYNC_TEST* testDev = &private_key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SHARED_SEC; + testDev->eccSharedSec.private_key = private_key; + testDev->eccSharedSec.public_point = point; + testDev->eccSharedSec.out = out; + testDev->eccSharedSec.outLen = outlen; + return WC_PENDING_E; + } + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); +#endif + + return err; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + DECLARE_CURVE_SPECS(2) + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + /* load curve info */ + err = wc_ecc_curve_load(private_key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + if (err != MP_OKAY) + return err; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + err = wc_ecc_shared_secret_gen_async(private_key, point, + out, outlen, curve); + } + else +#endif + { + err = wc_ecc_shared_secret_gen_sync(private_key, point, + out, outlen, curve); + } + + wc_ecc_curve_free(curve); + + return err; +} + /** Create an ECC shared secret between private key and public point private_key The private ECC key (heap hint based on private key) @@ -2418,14 +2849,10 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, outlen [in/out] The max size and resulting size of the shared secret return MP_OKAY if successful */ -int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, - byte* out, word32 *outlen) +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) { - word32 x = 0; - ecc_point* result; - mp_int prime; - mp_int a; - int err; + int err; if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) { @@ -2441,50 +2868,47 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, if (wc_ecc_is_valid_idx(private_key->idx) == 0) return ECC_BAD_ARG_E; - /* make new point */ - result = wc_ecc_new_point_h(private_key->heap); - if (result == NULL) { - return MEMORY_E; - } + switch(private_key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SHARED_SEC_GEN: + private_key->state = ECC_STATE_SHARED_SEC_GEN; - if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - wc_ecc_del_point_h(result, private_key->heap); + err = wc_ecc_shared_secret_gen(private_key, point, out, outlen); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_SHARED_SEC_RES: + private_key->state = ECC_STATE_SHARED_SEC_RES; + err = 0; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM) || defined(HAVE_INTEL_QA) + err = private_key->asyncDev.event.ret; + #endif + } + #endif + break; + + default: + err = BAD_STATE_E; + } /* switch */ + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + private_key->state++; return err; } - /* read in the specs for this curve */ - err = mp_read_radix(&prime, private_key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, private_key->dp->Af, 16); - - if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&private_key->k, point, result, &a, &prime, 1, - private_key->heap); - - if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&prime); - if (*outlen < x) - err = BUFFER_E; - } - - if (err == MP_OKAY) { - XMEMSET(out, 0, x); - err = mp_to_unsigned_bin(result->x,out + - (x - mp_unsigned_bin_size(result->x))); - *outlen = x; - } - -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); -#endif - wc_ecc_del_point_h(result, private_key->heap); + private_key->state = ECC_STATE_NONE; return err; } #endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_DHE */ + #ifndef WOLFSSL_ATECC508A /* return 1 if point is at infinity, 0 if not, < 0 on error */ int wc_ecc_point_is_at_infinity(ecc_point* p) @@ -2498,39 +2922,85 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) return 0; } -#endif /* WOLFSSL_ATECC508A */ +/* generate random and ensure its greater than 0 and less than order */ +static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) +{ + int err; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_MAXSIZE_GEN]; +#endif +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ + /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + size += 8; + + /* make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, size); + + /* load random buffer data into k */ + if (err == 0) + err = mp_read_unsigned_bin(k, (byte*)buf, size); + + /* quick sanity check to make sure we're not dealing with a 0 key */ + if (err == MP_OKAY) { + if (mp_iszero(k) == MP_YES) + err = MP_ZERO_E; + } + + /* the key should be smaller than the order of base point */ + if (err == MP_OKAY) { + if (mp_cmp(k, order) != MP_LT) { + err = mp_mod(k, order, k); + } + } + + ForceZero(buf, ECC_MAXSIZE); +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* !WOLFSSL_ATECC508A */ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) { int err; #ifndef WOLFSSL_ATECC508A ecc_point* base = NULL; - mp_int prime; - mp_int a; - mp_int order; -#ifdef WOLFSSL_SMALL_STACK - byte* buf; -#else - byte buf[ECC_MAXSIZE_GEN]; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) #endif -#endif /* !WOLFSSL_ATECC508A */ if (key == NULL || rng == NULL) { return BAD_FUNC_ARG; } + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; + key->idx = 0; + key->dp = NULL; + err = wc_ecc_set_curve(key, keysize, curve_id); if (err != 0) { return err; } -#ifdef WOLFSSL_ASYNC_CRYPT +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { #ifdef HAVE_CAVIUM /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; + WC_ASYNC_TEST* testDev = &key->asyncDev.test; if (testDev->type == ASYNC_TEST_NONE) { testDev->type = ASYNC_TEST_ECC_MAKE; testDev->eccMake.rng = rng; @@ -2541,7 +3011,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) } #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_ATECC508A key->type = ECC_PRIVATEKEY; @@ -2552,99 +3022,53 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) #else -#ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) - return MEMORY_E; -#endif - - /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ - /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ - keysize = key->dp->size + 8; - - /* make up random string */ - err = wc_RNG_GenerateBlock(rng, buf, keysize); - if (err != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return err; - } - /* setup the key variables */ - err = mp_init_multi(&key->k, &prime, &order, &a, NULL, NULL); - if (err != MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err = mp_init(&key->k); + if (err == MP_OKAY) { + #ifndef ALT_ECC_SIZE + err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL, NULL); + #else + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); #endif - return err; } -#ifndef ALT_ECC_SIZE - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, - NULL, NULL, NULL); -#else - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; - key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; - key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; - alt_fp_init(key->pubkey.x); - alt_fp_init(key->pubkey.y); - alt_fp_init(key->pubkey.z); -#endif - if (err == MP_OKAY) { base = wc_ecc_new_point_h(key->heap); if (base == NULL) err = MEMORY_E; } - /* read in the specs for this curve */ + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); /* read in the x/y for this key */ if (err == MP_OKAY) - err = mp_read_radix(base->x, key->dp->Gx, 16); + err = mp_copy(curve->Gx, base->x); if (err == MP_OKAY) - err = mp_read_radix(base->y, key->dp->Gy, 16); + err = mp_copy(curve->Gy, base->y); if (err == MP_OKAY) - mp_set(base->z, 1); + err = mp_set(base->z, 1); - /* load random buffer data into k */ + /* generate k */ if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); - - /* quick sanity check to make sure we're not dealing with a 0 key */ - if (err == MP_OKAY) { - if (mp_iszero(&key->k) == MP_YES) - err = MP_ZERO_E; - } - - /* the key should be smaller than the order of base point */ - if (err == MP_OKAY) { - if (mp_cmp(&key->k, &order) != MP_LT) - err = mp_mod(&key->k, &order, &key->k); - } - - /* the key should be smaller than the order of base point */ - if (err == MP_OKAY) { - if (mp_cmp(&key->k, &order) != MP_LT) - err = mp_mod(&key->k, &order, &key->k); - } + err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order); /* make the public key */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, &a, &prime, 1, - key->heap); + err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, + curve->Af, curve->prime, 1, key->heap); #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN /* validate the public key, order * pubkey = point at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &a, &prime, &order); + err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); #endif /* WOLFSSL_VALIDATE_KEYGEN */ if (err == MP_OKAY) @@ -2652,24 +3076,19 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) /* cleanup these on failure case only */ if (err != MP_OKAY) { + /* clean up */ + #ifndef ALT_ECC_SIZE mp_clear(key->pubkey.x); mp_clear(key->pubkey.y); mp_clear(key->pubkey.z); + #endif mp_forcezero(&key->k); } /* cleanup allocations */ wc_ecc_del_point_h(base, key->heap); -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&prime); - mp_clear(&order); -#endif + wc_ecc_curve_free(curve); - ForceZero(buf, ECC_MAXSIZE); -#ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif #endif /* WOLFSSL_ATECC508A */ return err; @@ -2745,6 +3164,65 @@ int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key) return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF); } +static INLINE int wc_ecc_alloc_rs(ecc_key* key, mp_int** r, mp_int** s) +{ + int err = 0; + +#ifndef WOLFSSL_ASYNC_CRYPT + (void)key; +#endif + + if (*r == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*r == NULL) { + return MEMORY_E; + } + key->r = *r; + #endif + } + if (*s == NULL) { + #ifdef WOLFSSL_ASYNC_CRYPT + *s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*s == NULL) { + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); + return MEMORY_E; + } + key->s = *s; + #endif + } + + /* initialize mp_int */ + if (*r) + XMEMSET(*r, 0, sizeof(mp_int)); + if (*s) + XMEMSET(*s, 0, sizeof(mp_int)); + + return err; +} + +static INLINE void wc_ecc_free_rs(ecc_key* key, mp_int** r, mp_int** s) +{ + if (*r) { + mp_clear(*r); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*r, key->heap, DYNAMIC_TYPE_BIGINT); + key->r = NULL; + #endif + *r = NULL; + } + if (*s) { + mp_clear(*s); + + #ifdef WOLFSSL_ASYNC_CRYPT + XFREE(*s, key->heap, DYNAMIC_TYPE_BIGINT); + key->s = NULL; + #endif + *s = NULL; + } + (void)key; +} /* Setup dynamic pointers if using normal math for proper freeing */ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) @@ -2755,14 +3233,12 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) return BAD_FUNC_ARG; } - (void)devId; - #ifdef ECC_DUMP_OID wc_ecc_dump_oids(); #endif - key->dp = NULL; - key->idx = 0; + XMEMSET(key, 0, sizeof(ecc_key)); + key->state = ECC_STATE_NONE; #ifdef WOLFSSL_ATECC508A key->slot = atmel_ecc_alloc(); @@ -2770,28 +3246,21 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) return ECC_BAD_ARG_E; } #else - -#ifndef USE_FAST_MATH - key->pubkey.x->dp = NULL; - key->pubkey.y->dp = NULL; - key->pubkey.z->dp = NULL; - - key->k.dp = NULL; -#endif - #ifdef ALT_ECC_SIZE - if (mp_init(&key->k) != MP_OKAY) { - return MEMORY_E; - } - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; alt_fp_init(key->pubkey.x); alt_fp_init(key->pubkey.y); alt_fp_init(key->pubkey.z); -#endif - + ret = mp_init(&key->k); +#else + ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); +#endif /* ALT_ECC_SIZE */ + if (ret != MP_OKAY) { + return MEMORY_E; + } #endif /* WOLFSSL_ATECC508A */ #ifdef WOLFSSL_HEAP_TEST @@ -2800,12 +3269,12 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) key->heap = heap; #endif -#ifdef WOLFSSL_ASYNC_CRYPT - if (devId != INVALID_DEVID) { - /* handle as async */ - ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, - devId); - } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + key->heap, devId); +#else + (void)devId; #endif return ret; @@ -2816,6 +3285,14 @@ int wc_ecc_init(ecc_key* key) return wc_ecc_init_ex(key, NULL, INVALID_DEVID); } +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; + return 0; +} #ifdef HAVE_ECC_SIGN @@ -2832,119 +3309,128 @@ int wc_ecc_init(ecc_key* key) int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, WC_RNG* rng, ecc_key* key) { - mp_int r; - mp_int s; - int err; + int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; +#endif - if (in == NULL || out == NULL || outlen == NULL || - key == NULL || rng == NULL) { + if (in == NULL || out == NULL || outlen == NULL || key == NULL || + rng == NULL) { return ECC_BAD_ARG_E; } + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SIGN_DO: + key->state = ECC_STATE_SIGN_DO; -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_SIGN; - testDev->eccSign.in = in; - testDev->eccSign.inSz = inlen; - testDev->eccSign.out = out; - testDev->eccSign.outSz = outlen; - testDev->eccSign.rng = rng; - testDev->eccSign.key = key; - return WC_PENDING_E; - } - #endif + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ + break; + } + + #ifdef WOLFSSL_ATECC508A + /* Check args */ + if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { + return ECC_BAD_ARG_E; + } + + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atcatls_sign(key->slot, in, out); + if (err != ATCA_SUCCESS) { + return BAD_COND_E; + } + + /* Load R and S */ + err = mp_read_unsigned_bin(r, &out[0], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + return err; + } + err = mp_read_unsigned_bin(s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); + if (err != MP_OKAY) { + return err; + } + + /* Check for zeros */ + if (mp_iszero(r) || mp_iszero(s)) { + return MP_ZERO_E; + } + + #else + + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + if (err < 0) { + break; + } + + #endif /* WOLFSSL_ATECC508A */ + FALL_THROUGH; + + case ECC_STATE_SIGN_ENCODE: + key->state = ECC_STATE_SIGN_ENCODE; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* restore r/s */ + r = key->r; + s = key->s; + + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + /* only do this if not simulator, since it overwrites result */ + #ifndef WOLFSSL_ASYNC_CRYPT_TEST + wc_bigint_to_mp(&r->raw, r); + wc_bigint_to_mp(&s->raw, s); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* encoded with DSA header */ + err = StoreECC_DSA_Sig(out, outlen, r, s); + + /* always free r/s */ + mp_clear(r); + mp_clear(s); + break; + + default: + err = BAD_STATE_E; } -#endif - /* is this a private key? */ - if (key->type != ECC_PRIVATEKEY) - return ECC_BAD_ARG_E; - - /* is the IDX valid ? */ - if (wc_ecc_is_valid_idx(key->idx) != 1) - return ECC_BAD_ARG_E; - - if ((err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL)) != MP_OKAY) { + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; return err; } -#ifdef WOLFSSL_ATECC508A - /* Check args */ - if (inlen != ATECC_KEY_SIZE || *outlen < SIGN_RSP_SIZE) { - err = ECC_BAD_ARG_E; - goto exit_sign; - } - - /* Sign: Result is 32-bytes of R then 32-bytes of S */ - err = atcatls_sign(key->slot, in, out); - if (err != ATCA_SUCCESS) { - err = BAD_COND_E; - goto exit_sign; - } - - /* Load R and S */ - err = mp_read_unsigned_bin(&r, &out[0], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - goto exit_sign; - } - err = mp_read_unsigned_bin(&s, &out[ATECC_KEY_SIZE], ATECC_KEY_SIZE); - if (err != MP_OKAY) { - goto exit_sign; - } - - /* Check for zeros */ - if (mp_iszero(&r) || mp_iszero(&s)) { - err = MP_ZERO_E; - goto exit_sign; - } - -#else - - err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s); - if (err != MP_OKAY) { - goto exit_sign; - } - - err = StoreECC_DSA_Sig(out, outlen, &r, &s); - -#endif /* WOLFSSL_ATECC508A */ - -exit_sign: - -#ifndef USE_FAST_MATH - mp_clear(&r); - mp_clear(&s); -#endif + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); + key->state = ECC_STATE_NONE; return err; } #endif /* !NO_ASN */ #ifndef WOLFSSL_ATECC508A - /** Sign a message digest in The message digest to sign inlen The length of the digest - out [out] The destination for the signature - outlen [in/out] The max size and resulting size of the signature key A private ECC key r [out] The destination for r component of the signature - s [out] The destination for s component of the signature + s [out] The destination for s component of the signature return MP_OKAY if successful */ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, ecc_key* key, mp_int *r, mp_int *s) { - mp_int e; - mp_int p; - int err; + int err; + mp_int e; + DECLARE_CURVE_SPECS(1) if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) return ECC_BAD_ARG_E; @@ -2959,20 +3445,40 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, return ECC_BAD_ARG_E; } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_SIGN; + testDev->eccSign.in = in; + testDev->eccSign.inSz = inlen; + testDev->eccSign.rng = rng; + testDev->eccSign.key = key; + testDev->eccSign.r = r; + testDev->eccSign.s = s; + return WC_PENDING_E; + } + } +#endif + /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ - if ((err = mp_init_multi(&p, &e, NULL, NULL, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init(&e)) != MP_OKAY) { return err; } - err = mp_read_radix(&p, key->dp->order, 16); + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + + /* load digest into e */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - word32 orderBits = mp_count_bits(&p); + word32 orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ - if ( (WOLFSSL_BIT_SIZE * inlen) > orderBits) - inlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; + if ((WOLFSSL_BIT_SIZE * inlen) > orderBits) + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; err = mp_read_unsigned_bin(&e, (byte*)in, inlen); /* may still need bit truncation too */ @@ -2984,7 +3490,48 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err == MP_OKAY) { int loop_check = 0; ecc_key pubkey; - if (wc_ecc_init(&pubkey) == MP_OKAY) { + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + mp_int k; + + err = mp_init(&k); + /* make sure r and s are allocated */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->s->raw, key->dp->size); + /* load e and k */ + if (err == MP_OKAY) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->k, &key->k.raw); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, &k, curve->order); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&k, &k.raw); + if (err == MP_OKAY) + err = IntelQaEcdsaSign(&key->asyncDev, &e.raw, &key->k.raw, + &k.raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, + &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, + &curve->Gy->raw); + + mp_clear(&e); + mp_clear(&k); + wc_ecc_curve_free(curve); + + return err; + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* don't use async for key, since we don't support async return here */ + if (wc_ecc_init_ex(&pubkey, key->heap, INVALID_DEVID) == MP_OKAY) { for (;;) { if (++loop_check > 64) { err = RNG_FAILURE_E; @@ -2995,31 +3542,36 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err != MP_OKAY) break; /* find r = x1 mod n */ - err = mp_mod(pubkey.pubkey.x, &p, r); + err = mp_mod(pubkey.pubkey.x, curve->order, r); if (err != MP_OKAY) break; if (mp_iszero(r) == MP_YES) { + #ifndef ALT_ECC_SIZE mp_clear(pubkey.pubkey.x); mp_clear(pubkey.pubkey.y); mp_clear(pubkey.pubkey.z); - mp_clear(&pubkey.k); + #endif + mp_forcezero(&pubkey.k); } else { /* find s = (e + xr)/k */ - err = mp_invmod(&pubkey.k, &p, &pubkey.k); + err = mp_invmod(&pubkey.k, curve->order, &pubkey.k); if (err != MP_OKAY) break; - err = mp_mulmod(&key->k, r, &p, s); /* s = xr */ + /* s = xr */ + err = mp_mulmod(&key->k, r, curve->order, s); if (err != MP_OKAY) break; - err = mp_add(&e, s, s); /* s = e + xr */ + /* s = e + xr */ + err = mp_add(&e, s, s); if (err != MP_OKAY) break; - err = mp_mod(s, &p, s); /* s = e + xr */ + /* s = e + xr */ + err = mp_mod(s, curve->order, s); if (err != MP_OKAY) break; - err = mp_mulmod(s, &pubkey.k, &p, s); /* s = (e + xr)/k */ - if (err != MP_OKAY) break; + /* s = (e + xr)/k */ + err = mp_mulmod(s, &pubkey.k, curve->order, s); if (mp_iszero(s) == MP_NO) break; @@ -3029,14 +3581,12 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } } -#ifndef USE_FAST_MATH - mp_clear(&p); mp_clear(&e); -#endif + wc_ecc_curve_free(curve); return err; } -#endif /* !WOLFSSL_ATECC508A */ +#endif /* WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_SIGN */ /** @@ -3045,14 +3595,13 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, */ void wc_ecc_free(ecc_key* key) { - if (key == NULL) { - return; - } - -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { - wolfAsync_DevCtxFree(&key->asyncDev); + if (key == NULL) { + return; } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC); + wc_ecc_free_rs(key, &key->r, &key->s); #endif #ifdef WOLFSSL_ATECC508A @@ -3060,15 +3609,14 @@ void wc_ecc_free(ecc_key* key) key->slot = -1; #else - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_forcezero(&key->k); -#endif /* !WOLFSSL_ATECC508A */ + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + + mp_forcezero(&key->k); +#endif /* WOLFSSL_ATECC508A */ } - -#ifndef WOLFSSL_ATECC508A #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -3178,10 +3726,8 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); - #ifndef USE_FAST_MATH /* done with mu */ mp_clear(&mu); - #endif } } @@ -3295,7 +3841,6 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } #endif /* ECC_SHAMIR */ -#endif /* !WOLFSSL_ATECC508A */ #ifdef HAVE_ECC_VERIFY @@ -3316,157 +3861,176 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, siglen The length of the signature (octets) hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { - mp_int r; - mp_int s; - int err; -#ifdef WOLFSSL_ATECC508A - byte sigRS[ATECC_KEY_SIZE*2]; + int err; + mp_int *r = NULL, *s = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + mp_int r_lcl, s_lcl; + r = &r_lcl; + s = &s_lcl; #endif - if (sig == NULL || hash == NULL || stat == NULL || key == NULL) { + if (sig == NULL || hash == NULL || res == NULL || key == NULL) { return ECC_BAD_ARG_E; } - /* default to invalid signature */ - *stat = 0; + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_VERIFY_DECODE: + key->state = ECC_STATE_VERIFY_DECODE; -#ifdef WOLFSSL_ASYNC_CRYPT - if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { - #ifdef HAVE_CAVIUM - /* TODO: Not implemented */ - #else - AsyncCryptTestDev* testDev = &key->asyncDev.dev; - if (testDev->type == ASYNC_TEST_NONE) { - testDev->type = ASYNC_TEST_ECC_VERIFY; - testDev->eccVerify.in = sig; - testDev->eccVerify.inSz = siglen; - testDev->eccVerify.out = hash; - testDev->eccVerify.outSz = hashlen; - testDev->eccVerify.stat = stat; - testDev->eccVerify.key = key; - return WC_PENDING_E; - } - #endif - } -#endif + /* default to invalid signature */ + *res = 0; - /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. - * If either of those don't allocate correctly, none of - * the rest of this function will execute, and everything - * gets cleaned up at the end. */ - XMEMSET(&r, 0, sizeof(r)); - XMEMSET(&s, 0, sizeof(s)); + /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. + * If either of those don't allocate correctly, none of + * the rest of this function will execute, and everything + * gets cleaned up at the end. */ + err = wc_ecc_alloc_rs(key, &r, &s); + if (err != 0) + break; - err = DecodeECC_DSA_Sig(sig, siglen, &r, &s); - if (err != 0) { - goto exit_verify; + /* decode DSA header */ + err = DecodeECC_DSA_Sig(sig, siglen, r, s); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_DO: + key->state = ECC_STATE_VERIFY_DO; + + err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_RES: + key->state = ECC_STATE_VERIFY_RES; + err = 0; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* restore r/s */ + r = key->r; + s = key->s; + #endif + + /* done with R/S */ + mp_clear(r); + mp_clear(s); + break; + + default: + err = BAD_STATE_E; } -#ifdef WOLFSSL_ATECC508A - /* Extract R and S */ - err = mp_to_unsigned_bin(&r, &sigRS[0]); - if (err != MP_OKAY) { - goto exit_verify; - } - err = mp_to_unsigned_bin(&s, &sigRS[ATECC_KEY_SIZE]); - if (err != MP_OKAY) { - goto exit_verify; + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; } - err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)stat); - if (err != ATCA_SUCCESS) { - err = BAD_COND_E; - } - -#else - - err = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, stat, key); - -#endif /* WOLFSSL_ATECC508A */ - -exit_verify: - -#ifndef USE_FAST_MATH - mp_clear(&r); - mp_clear(&s); -#endif + /* cleanup */ + wc_ecc_free_rs(key, &r, &s); + key->state = ECC_STATE_NONE; return err; } #endif /* !NO_ASN */ -#ifndef WOLFSSL_ATECC508A - /** Verify an ECC signature r The signature R component to verify s The signature S component to verify hash The hash (message digest) that was signed hashlen The length of the hash (octets) - stat Result of signature, 1==valid, 0==invalid + res Result of signature, 1==valid, 0==invalid key The corresponding public ECC key return MP_OKAY if successful (even if the signature is not valid) */ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, - word32 hashlen, int* stat, ecc_key* key) + word32 hashlen, int* res, ecc_key* key) { + int err; +#ifndef WOLFSSL_ATECC508A + int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; mp_int v; mp_int w; mp_int u1; mp_int u2; mp_int e; - mp_int order; - mp_int modulus; - mp_int a; - int err; + DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#else + byte sigRS[ATECC_KEY_SIZE*2]; +#endif - if (r == NULL || s == NULL || hash == NULL || stat == NULL || key == NULL) + if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) return ECC_BAD_ARG_E; /* default to invalid signature */ - *stat = 0; + *res = 0; /* is the IDX valid ? */ if (wc_ecc_is_valid_idx(key->idx) != 1) { return ECC_BAD_ARG_E; } - /* allocate ints */ - if ((err = mp_init_multi(&v, &w, &u1, &u2, &order, &e)) != MP_OKAY) { +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + if (testDev->type == ASYNC_TEST_NONE) { + testDev->type = ASYNC_TEST_ECC_VERIFY; + testDev->eccVerify.r = r; + testDev->eccVerify.s = s; + testDev->eccVerify.hash = hash; + testDev->eccVerify.hashlen = hashlen; + testDev->eccVerify.stat = res; + testDev->eccVerify.key = key; + return WC_PENDING_E; + } + } +#endif + +#ifdef WOLFSSL_ATECC508A + /* Extract R and S */ + err = mp_to_unsigned_bin(r, &sigRS[0]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[ATECC_KEY_SIZE]); + if (err != MP_OKAY) { + return err; + } + + err = atcatls_verify(hash, sigRS, key->pubkey, (bool*)res); + if (err != ATCA_SUCCESS) { + return BAD_COND_E; + } + +#else + + err = mp_init(&e); + if (err != MP_OKAY) return MEMORY_E; - } - - if ((err = mp_init_multi(&modulus, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { - err = MEMORY_E; goto done; - } - - /* allocate points */ - mG = wc_ecc_new_point_h(key->heap); - mQ = wc_ecc_new_point_h(key->heap); - if (mQ == NULL || mG == NULL) - err = MEMORY_E; /* read in the specs for this curve */ - if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); - if (err == MP_OKAY) - err = mp_read_radix(&modulus, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); /* check for zero */ if (err == MP_OKAY) { if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || - mp_cmp(r, &order) != MP_LT || mp_cmp(s, &order) != MP_LT) { + mp_cmp(r, curve->order) != MP_LT || + mp_cmp(s, curve->order) != MP_LT) { err = MP_ZERO_E; } } @@ -3474,11 +4038,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* read hash */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - unsigned int orderBits = mp_count_bits(&order); + unsigned int orderBits = mp_count_bits(curve->order); /* truncate down to byte size, may be all that's needed */ if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) - hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE; + hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; err = mp_read_unsigned_bin(&e, hash, hashlen); /* may still need bit truncation too */ @@ -3486,26 +4050,67 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); } + /* check for async hardware acceleration */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + err = wc_mp_to_bigint(&e, &e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw); + if (err == MP_OKAY) + err = IntelQaEcdsaVerify(&key->asyncDev, &e.raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, + &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, + &curve->Gx->raw, &curve->Gy->raw, res); + + mp_clear(&e); + + wc_ecc_curve_free(curve); + + return err; + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* allocate ints */ + if (err == MP_OKAY) { + if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) { + err = MEMORY_E; + } + did_init = 1; + } + + /* allocate points */ + if (err == MP_OKAY) { + mG = wc_ecc_new_point_h(key->heap); + mQ = wc_ecc_new_point_h(key->heap); + if (mQ == NULL || mG == NULL) + err = MEMORY_E; + } + /* w = s^-1 mod n */ if (err == MP_OKAY) - err = mp_invmod(s, &order, &w); + err = mp_invmod(s, curve->order, &w); /* u1 = ew */ if (err == MP_OKAY) - err = mp_mulmod(&e, &w, &order, &u1); + err = mp_mulmod(&e, &w, curve->order, &u1); /* u2 = rw */ if (err == MP_OKAY) - err = mp_mulmod(r, &w, &order, &u2); + err = mp_mulmod(r, &w, curve->order, &u2); /* find mG and mQ */ if (err == MP_OKAY) - err = mp_read_radix(mG->x, key->dp->Gx, 16); - + err = mp_copy(curve->Gx, mG->x); if (err == MP_OKAY) - err = mp_read_radix(mG->y, key->dp->Gy, 16); + err = mp_copy(curve->Gy, mG->y); if (err == MP_OKAY) - mp_set(mG->z, 1); + err = mp_set(mG->z, 1); if (err == MP_OKAY) err = mp_copy(key->pubkey.x, mQ->x); @@ -3517,11 +4122,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #ifdef FREESCALE_LTC_ECC /* use PKHA to compute u1*mG + u2*mQ */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u1, mG, mG, &a, &modulus, 0, NULL); + err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, &a, &modulus, 0, NULL); + err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_point_add(mG, mQ, mG, &modulus); + err = wc_ecc_point_add(mG, mQ, mG, curve->prime); #else /* FREESCALE_LTC_ECC */ #ifndef ECC_SHAMIR { @@ -3529,57 +4134,58 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* compute u1*mG + u2*mQ = mG */ if (err == MP_OKAY) - err = wc_ecc_mulmod(&u1, mG, mG, &a, &modulus, 0); + err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_mulmod(&u2, mQ, mQ, &a, &modulus, 0); + err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); /* find the montgomery mp */ if (err == MP_OKAY) - err = mp_montgomery_setup(&modulus, &mp); + err = mp_montgomery_setup(curve->prime, &mp); /* add them */ if (err == MP_OKAY) - err = ecc_projective_add_point(mQ, mG, mG, &a, &modulus, mp); + err = ecc_projective_add_point(mQ, mG, mG, curve->Af, + curve->prime, mp); /* reduce */ if (err == MP_OKAY) - err = ecc_map(mG, &modulus, mp); + err = ecc_map(mG, curve->prime, mp); } #else /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ if (err == MP_OKAY) - err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &a, &modulus, key->heap); + err = ecc_mul2add(mG, &u1, mQ, &u2, mG, curve->Af, curve->prime, + key->heap); #endif /* ECC_SHAMIR */ #endif /* FREESCALE_LTC_ECC */ /* v = X_x1 mod n */ if (err == MP_OKAY) - err = mp_mod(mG->x, &order, &v); + err = mp_mod(mG->x, curve->order, &v); /* does v == r */ if (err == MP_OKAY) { if (mp_cmp(&v, r) == MP_EQ) - *stat = 1; + *res = 1; } -done: /* cleanup */ wc_ecc_del_point_h(mG, key->heap); wc_ecc_del_point_h(mQ, key->heap); -#ifndef USE_FAST_MATH - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); - mp_clear(&order); mp_clear(&e); - mp_clear(&modulus); - mp_clear(&a); -#endif + if (did_init) { + mp_clear(&v); + mp_clear(&w); + mp_clear(&u1); + mp_clear(&u2); + } + + wc_ecc_curve_free(curve); + +#endif /* WOLFSSL_ATECC508A */ return err; } -#endif /* !WOLFSSL_ATECC508A */ #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_KEY_IMPORT @@ -3633,62 +4239,58 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2, prime, a, b; int did_init = 0; + mp_int t1, t2; + DECLARE_CURVE_SPECS(3) - if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; else did_init = 1; - /* read in the specs for this curve */ + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&prime, ecc_sets[curve_idx].prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, ecc_sets[curve_idx].Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&b, ecc_sets[curve_idx].Bf, 16); + err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(point->x, &t1); if (err == MP_OKAY) - err = mp_mulmod(&t1, point->x, &prime, &t1); + err = mp_mulmod(&t1, point->x, curve->prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&a, point->x, &prime, &t2); + err = mp_mulmod(curve->Af, point->x, curve->prime, &t2); if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); /* compute x^3 + a*x + b */ if (err == MP_OKAY) - err = mp_add(&t1, &b, &t1); + err = mp_add(&t1, curve->Bf, &t1); /* compute sqrt(x^3 + a*x + b) */ if (err == MP_OKAY) - err = mp_sqrtmod_prime(&t1, &prime, &t2); + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); /* adjust y */ if (err == MP_OKAY) { if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, point->y); + err = mp_mod(&t2, curve->prime, point->y); } else { - err = mp_submod(&prime, &t2, &prime, point->y); + err = mp_submod(curve->prime, &t2, curve->prime, point->y); } } if (did_init) { - #ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); - mp_clear(&prime); mp_clear(&t2); mp_clear(&t1); - #endif } + + wc_ecc_curve_free(curve); } #endif @@ -3696,7 +4298,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, err = mp_read_unsigned_bin(point->y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(point->z, 1); + err = mp_set(point->z, 1); if (err != MP_OKAY) { mp_clear(point->x); @@ -3790,15 +4392,16 @@ done: /* export public ECC key in ANSI X9.63 format */ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) { - word32 numlen; int ret = MP_OKAY; + word32 numlen; #ifndef WOLFSSL_ATECC508A #ifdef WOLFSSL_SMALL_STACK byte* buf; #else byte buf[ECC_BUFSIZE]; #endif -#endif + word32 pubxlen, pubylen; +#endif /* WOLFSSL_ATECC508A */ /* return length needed only */ if (key != NULL && out == NULL && outLen != NULL) { @@ -3815,6 +4418,7 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) } numlen = key->dp->size; + /* verify room in out buffer */ if (*outLen < (1 + 2*numlen)) { *outLen = 1 + 2*numlen; return BUFFER_E; @@ -3826,6 +4430,14 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) #else + /* verify public key length is less than key size */ + pubxlen = mp_unsigned_bin_size(key->pubkey.x); + pubylen = mp_unsigned_bin_size(key->pubkey.y); + if ((pubxlen > numlen) || (pubylen > numlen)) { + WOLFSSL_MSG("Public key x/y invalid!"); + return BUFFER_E; + } + /* store byte 0x04 */ out[0] = 0x04; @@ -3835,23 +4447,21 @@ int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) return MEMORY_E; #endif - /* pad and store x */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.x, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.x))); - if (ret != MP_OKAY) - goto done; - XMEMCPY(out+1, buf, numlen); + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); - /* pad and store y */ - XMEMSET(buf, 0, ECC_BUFSIZE); - ret = mp_to_unsigned_bin(key->pubkey.y, - buf + (numlen - mp_unsigned_bin_size(key->pubkey.y))); - if (ret != MP_OKAY) - goto done; - XMEMCPY(out+1+numlen, buf, numlen); + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); - *outLen = 1 + 2*numlen; + *outLen = 1 + 2*numlen; done: #ifdef WOLFSSL_SMALL_STACK @@ -3873,9 +4483,9 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, #ifdef HAVE_COMP_KEY else return wc_ecc_export_x963_compressed(key, out, outLen); -#endif - +#else return NOT_COMPILED_IN; +#endif } #endif /* HAVE_ECC_KEY_EXPORT */ @@ -3883,20 +4493,15 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, #ifndef WOLFSSL_ATECC508A /* is ecc point on curve described by dp ? */ -static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) { - mp_int a, b, t1, t2; int err; + mp_int t1, t2; - if ((err = mp_init_multi(&a, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { return err; } - /* read in the specs for this curve */ - err = mp_read_radix(&a, dp->Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&b, dp->Bf, 16); - /* compute y^2 */ if (err == MP_OKAY) err = mp_sqr(ecp->y, &t1); @@ -3917,8 +4522,9 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) #ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { /* Use a and prime to determine if a == 3 */ - mp_set(&t2, 0); - err = mp_submod(prime, &a, prime, &t2); + err = mp_set(&t2, 0); + if (err == MP_OKAY) + err = mp_submod(prime, a, prime, &t2); } if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) { /* compute y^2 - x^3 + a*x */ @@ -3954,19 +4560,15 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* compare to b */ if (err == MP_OKAY) { - if (mp_cmp(&t1, &b) != MP_EQ) { + if (mp_cmp(&t1, b) != MP_EQ) { err = MP_VAL; } else { err = MP_OKAY; } } -#ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); mp_clear(&t1); mp_clear(&t2); -#endif return err; } @@ -3975,9 +4577,10 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* validate privkey * generator == pubkey, 0 on success */ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { - int err = MP_OKAY; + int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; + DECLARE_CURVE_SPECS(2) if (key == NULL) return BAD_FUNC_ARG; @@ -3986,12 +4589,17 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) if (base == NULL) return MEMORY_E; + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + /* set up base generator */ - err = mp_read_radix(base->x, key->dp->Gx, 16); if (err == MP_OKAY) - err = mp_read_radix(base->y, key->dp->Gy, 16); + err = mp_copy(curve->Gx, base->x); if (err == MP_OKAY) - mp_set(base->z, 1); + err = mp_copy(curve->Gy, base->y); + if (err == MP_OKAY) + err = mp_set(base->z, 1); if (err == MP_OKAY) { res = wc_ecc_new_point_h(key->heap); @@ -4011,23 +4619,22 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) } } + wc_ecc_curve_free(curve); wc_ecc_del_point_h(res, key->heap); wc_ecc_del_point_h(base, key->heap); return err; } - #ifdef WOLFSSL_VALIDATE_ECC_IMPORT /* check privkey generator helper, creates prime needed */ static int ecc_check_privkey_gen_helper(ecc_key* key) { - int err = MP_OKAY; + int err; #ifndef WOLFSSL_ATECC508A - mp_int prime; - mp_int a; -#endif /* !WOLFSSL_ATECC508A */ + DECLARE_CURVE_SPECS(2) +#endif if (key == NULL) return BAD_FUNC_ARG; @@ -4038,22 +4645,15 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) #else - err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; - - err = mp_read_radix(&prime, key->dp->prime, 16); + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); - if (err == MP_OKAY) - err = ecc_check_privkey_gen(key, &a, &prime); + wc_ecc_curve_free(curve); -#ifndef USE_FAST_MATH - mp_clear(&prime); - mp_clear(&a); -#endif #endif /* WOLFSSL_ATECC508A */ return err; @@ -4076,8 +4676,7 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, if (inf == NULL) err = MEMORY_E; else { - err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, - key->heap); + err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, key->heap); if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) err = ECC_INF_E; } @@ -4093,12 +4692,18 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, /* perform sanity checks on ecc key validity, 0 on success */ int wc_ecc_check_key(ecc_key* key) { - int err = MP_OKAY; + int err; #ifndef WOLFSSL_ATECC508A - mp_int prime; /* used by multiple calls so let's cache */ - mp_int a; - mp_int order; /* other callers have, so let's gen here */ -#endif /* !WOLFSSL_ATECC508A */ + mp_int* b; +#ifdef USE_ECC_B_PARAM + DECLARE_CURVE_SPECS(4) +#else + mp_int b_lcl; + DECLARE_CURVE_SPECS(3) + b = &b_lcl; + XMEMSET(b, 0, sizeof(mp_int)); +#endif +#endif /* WOLFSSL_ATECC508A */ if (key == NULL) return BAD_FUNC_ARG; @@ -4113,35 +4718,50 @@ int wc_ecc_check_key(ecc_key* key) if (wc_ecc_point_is_at_infinity(&key->pubkey)) return ECC_INF_E; - err = mp_init_multi(&prime, &a, &order, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | + ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER +#ifdef USE_ECC_B_PARAM + | ECC_CURVE_FIELD_BF +#endif + )); - /* read in the specs for this curve */ +#ifndef USE_ECC_B_PARAM + /* load curve b parameter */ if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); + err = mp_init(b); if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&order, key->dp->order, 16); + err = mp_read_radix(b, key->dp->Bf, 16); +#else + b = curve->Bf; +#endif + + /* Qx must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + + /* Qy must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; /* make sure point is actually on curve */ if (err == MP_OKAY) - err = ecc_is_point(key->dp, &key->pubkey, &prime); + err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime); /* pubkey * order must be at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &a, &prime, &order); + err = ecc_check_pubkey_order(key, curve->Af, curve->prime, curve->order); /* private * base generator must equal pubkey */ if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) - err = ecc_check_privkey_gen(key, &a, &prime); + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); -#ifndef USE_FAST_MATH - mp_clear(&order); - mp_clear(&a); - mp_clear(&prime); + wc_ecc_curve_free(curve); + +#ifndef USE_ECC_B_PARAM + mp_clear(b); #endif + #endif /* WOLFSSL_ATECC508A */ return err; @@ -4156,6 +4776,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #ifndef WOLFSSL_ATECC508A int compressed = 0; #endif /* !WOLFSSL_ATECC508A */ + void* heap; if (in == NULL || key == NULL) return BAD_FUNC_ARG; @@ -4165,6 +4786,10 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, return ECC_BAD_ARG_E; } + heap = key->heap; /* save heap */ + XMEMSET(key, 0, sizeof(ecc_key)); + key->heap = heap; /* restore heap */ + #ifdef WOLFSSL_ATECC508A /* TODO: Implement equiv call to ATECC508A */ err = BAD_COND_E; @@ -4181,8 +4806,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, + key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; @@ -4202,9 +4827,11 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, if (err == MP_OKAY) { int keysize; + #ifdef HAVE_COMP_KEY /* adjust inLen if compressed */ if (compressed) inLen = (inLen-1)*2 + 1; /* used uncompressed len */ + #endif /* determine key size */ keysize = ((inLen-1)>>1); @@ -4218,63 +4845,61 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, #ifdef HAVE_COMP_KEY if (err == MP_OKAY && compressed == 1) { /* build y */ - mp_int t1, t2, prime, a, b; + mp_int t1, t2; int did_init = 0; - if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) + DECLARE_CURVE_SPECS(3) + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; else did_init = 1; - /* read in the specs for this curve */ + /* load curve info */ if (err == MP_OKAY) - err = mp_read_radix(&prime, key->dp->prime, 16); - if (err == MP_OKAY) - err = mp_read_radix(&a, key->dp->Af, 16); - if (err == MP_OKAY) - err = mp_read_radix(&b, key->dp->Bf, 16); + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(key->pubkey.x, &t1); if (err == MP_OKAY) - err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1); + err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&a, key->pubkey.x, &prime, &t2); + err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2); if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); /* compute x^3 + a*x + b */ if (err == MP_OKAY) - err = mp_add(&t1, &b, &t1); + err = mp_add(&t1, curve->Bf, &t1); /* compute sqrt(x^3 + a*x + b) */ if (err == MP_OKAY) - err = mp_sqrtmod_prime(&t1, &prime, &t2); + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); /* adjust y */ if (err == MP_OKAY) { if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, &t2); + err = mp_mod(&t2, curve->prime, &t2); } else { - err = mp_submod(&prime, &t2, &prime, &t2); + err = mp_submod(curve->prime, &t2, curve->prime, &t2); } - mp_copy(&t2, key->pubkey.y); + if (err == MP_OKAY) + err = mp_copy(&t2, key->pubkey.y); } if (did_init) { - #ifndef USE_FAST_MATH - mp_clear(&a); - mp_clear(&b); - mp_clear(&prime); mp_clear(&t2); mp_clear(&t1); - #endif } + + wc_ecc_curve_free(curve); } #endif /* HAVE_COMP_KEY */ @@ -4282,7 +4907,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT if (err == MP_OKAY) @@ -4339,13 +4964,131 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) mp_unsigned_bin_size(&key->k))); #endif /* WOLFSSL_ATECC508A */ } + + +/* export ecc key to component form, d is optional if only exporting public + * return MP_OKAY on success */ +static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + int err; + byte exportPriv = 0; + word32 numLen; + + if (key == NULL || qx == NULL || qxLen == NULL || qy == NULL || + qyLen == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numLen = key->dp->size; + + if (d != NULL) { + if (dLen == NULL || key->type != ECC_PRIVATEKEY) + return BAD_FUNC_ARG; + exportPriv = 1; + } + + /* check public buffer sizes */ + if ((*qxLen < numLen) || (*qyLen < numLen)) { + *qxLen = numLen; + *qyLen = numLen; + return BUFFER_E; + } + + *qxLen = numLen; + *qyLen = numLen; + + XMEMSET(qx, 0, *qxLen); + XMEMSET(qy, 0, *qyLen); + + /* private d component */ + if (exportPriv == 1) { + + /* check private buffer size */ + if (*dLen < numLen) { + *dLen = numLen; + return BUFFER_E; + } + + *dLen = numLen; + XMEMSET(d, 0, *dLen); + + /* private key, d */ + err = mp_to_unsigned_bin(&key->k, d + + (numLen - mp_unsigned_bin_size(&key->k))); + if (err != MP_OKAY) + return err; + } + + /* public x component */ + err = mp_to_unsigned_bin(key->pubkey.x, qx + + (numLen - mp_unsigned_bin_size(key->pubkey.x))); + if (err != MP_OKAY) + return err; + + /* public y component */ + err = mp_to_unsigned_bin(key->pubkey.y, qy + + (numLen - mp_unsigned_bin_size(key->pubkey.y))); + if (err != MP_OKAY) + return err; + + return 0; +} + + +/* export public key to raw elements including public (Qx,Qy) + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen) +{ + return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, NULL, NULL); +} + + +/* export ecc key to raw elements including public (Qx,Qy) and private (d) + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + /* sanitize d and dLen, other args are checked later */ + if (d == NULL || dLen == NULL) + return BAD_FUNC_ARG; + + return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, d, dLen); +} + #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_IMPORT -int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, const byte* pub, - word32 pubSz, ecc_key* key, int curve_id) +/* import private key, public part optional if (pub) passed as NULL */ +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, + int curve_id) { - int ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + int ret; + + /* public optional, NULL if only importing private */ + if (pub != NULL) { + + ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + + } else { + + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; + key->idx = 0; + key->dp = NULL; + + /* set key size */ + ret = wc_ecc_set_curve(key, privSz, curve_id); + } + if (ret != 0) return ret; @@ -4413,10 +5156,62 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) err = MP_ZERO_E; } -#ifndef USE_FAST_MATH mp_clear(&rtmp); mp_clear(&stmp); -#endif + + return err; +} + + +/** + Convert ECC signature to R,S + sig DER-encoded ECDSA signature + sigLen length of signature in octets + r R component of signature + rLen [in/out] output "r" buffer size, output "r" size + s S component of signature + sLen [in/out] output "s" buffer size, output "s" size + return MP_OKAY on success, negative on error +*/ +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen) +{ + int err; + word32 x = 0; + mp_int rtmp; + mp_int stmp; + + if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) + return ECC_BAD_ARG_E; + + err = DecodeECC_DSA_Sig(sig, sigLen, &rtmp, &stmp); + + /* extract r */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&rtmp); + if (*rLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *rLen = x; + err = mp_to_unsigned_bin(&rtmp, r); + } + } + + /* extract s */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&stmp); + if (*sLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *sLen = x; + err = mp_to_unsigned_bin(&stmp, s); + } + } + + mp_clear(&rtmp); + mp_clear(&stmp); return err; } @@ -4427,11 +5222,17 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, const char* qy, const char* d, int curve_id) { int err = MP_OKAY; + void* heap; - if (key == NULL || qx == NULL || qy == NULL || d == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { return BAD_FUNC_ARG; } + heap = key->heap; /* save heap */ + XMEMSET(key, 0, sizeof(ecc_key)); + key->heap = heap; /* restore heap */ + /* set curve type and index */ err = wc_ecc_set_curve(key, 0, curve_id); if (err != 0) { @@ -4454,8 +5255,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, alt_fp_init(key->pubkey.z); err = mp_init(&key->k); #else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); + err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); #endif if (err != MP_OKAY) return MEMORY_E; @@ -4469,12 +5270,16 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, err = mp_read_radix(key->pubkey.y, qy, 16); if (err == MP_OKAY) - mp_set(key->pubkey.z, 1); + err = mp_set(key->pubkey.z, 1); /* import private key */ if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - err = mp_read_radix(&key->k, d, 16); + if (d != NULL) { + key->type = ECC_PRIVATEKEY; + err = mp_read_radix(&key->k, d, 16); + } else { + key->type = ECC_PUBLICKEY; + } } #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -4498,7 +5303,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only dp Custom ecc_set_type return MP_OKAY on success */ @@ -4514,7 +5320,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only curveName ECC curve name, from ecc_sets[] return MP_OKAY on success */ @@ -4523,8 +5330,8 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, { int err, x; - if (key == NULL || qx == NULL || qy == NULL || d == NULL || - curveName == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) { return BAD_FUNC_ARG; } @@ -5239,7 +6046,8 @@ static int add_entry(int idx, ecc_point *g) static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, mp_int* mu) { - unsigned x, y, err, bitlen, lut_gap; + int err; + unsigned x, y, bitlen, lut_gap; mp_int tmp; if (mp_init(&tmp) != MP_OKAY) @@ -5304,8 +6112,6 @@ static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, if (err != MP_OKAY) break; for (y = 0; y < (1UL< z); } -#ifndef USE_FAST_MATH mp_clear(&tmp); -#endif if (err == MP_OKAY) return MP_OKAY; @@ -5385,8 +6189,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, #else unsigned char kb[KB_SIZE]; #endif - int x; - unsigned y, z = 0, err, bitlen, bitpos, lut_gap, first; + int x, err; + unsigned y, z = 0, bitlen, bitpos, lut_gap, first; mp_int tk, order; if (mp_init_multi(&tk, &order, NULL, NULL, NULL, NULL) != MP_OKAY) @@ -5413,10 +6217,14 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, goto done; } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(k, &tk); + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -5506,10 +6314,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&order); mp_clear(&tk); -#endif #ifdef WOLFSSL_SMALL_STACK XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -5534,8 +6340,8 @@ static int accel_fp_mul2add(int idx1, int idx2, #else unsigned char kb[2][KB_SIZE]; #endif - int x; - unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB; + int x, err; + unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB; mp_int tka, tkb, order; if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY) @@ -5562,10 +6368,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kA, &tka); + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } } /* if it's smaller than modulus we fine */ @@ -5589,10 +6399,14 @@ static int accel_fp_mul2add(int idx1, int idx2, goto done; } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } } else { - mp_copy(kB, &tkb); + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } } /* get bitlen and round up to next multiple of FP_LUT */ @@ -5722,15 +6536,17 @@ static int accel_fp_mul2add(int idx1, int idx2, done: /* cleanup */ -#ifndef USE_FAST_MATH mp_clear(&tkb); mp_clear(&tka); mp_clear(&order); -#endif +#ifdef WOLFSSL_SMALL_STACK if (kb[0]) +#endif ForceZero(kb[0], KB_SIZE); +#ifdef WOLFSSL_SMALL_STACK if (kb[1]) +#endif ForceZero(kb[1], KB_SIZE); #ifdef WOLFSSL_SMALL_STACK @@ -5865,15 +6681,12 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } #endif /* ECC_SHAMIR */ -#if !defined(FREESCALE_LTC_TFM) /** ECC Fixed Point mulmod global k The multiplicand G Base point to multiply @@ -5884,22 +6697,6 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, - mp_int* modulus, int map) -{ - return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); -} -#endif /* !FREESCALE_LTC_TFM */ - -/** ECC Fixed Point mulmod global - k The multiplicand - G Base point to multiply - R [out] Destination of product - modulus The modulus for the curve - map [boolean] If non-zero maps the point back to affine co-ordinates, - otherwise it's left in jacobian-montgomery form - return MP_OKAY if successful -*/ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, mp_int* modulus, int map, void* heap) { @@ -5972,9 +6769,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, #ifndef HAVE_THREAD_LS wc_UnLockMutex(&ecc_fp_lock); #endif /* HAVE_THREAD_LS */ -#ifndef USE_FAST_MATH mp_clear(&mu); -#endif return err; } @@ -6347,8 +7142,15 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = 0; + #endif + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : @@ -6377,6 +7179,9 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; @@ -6391,16 +7196,17 @@ int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, case ecHMAC_SHA256: { Hmac hmac; - ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, out, msgSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, out+msgSz); + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, out, msgSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out+msgSz); + wc_HmacFree(&hmac); + } } break; @@ -6499,8 +7305,15 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, } #endif - ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); - + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = 0; + #endif + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); if (ret == 0) { switch (ctx->kdfAlgo) { case ecHKDF_SHA256 : @@ -6522,25 +7335,28 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, switch (ctx->macAlgo) { case ecHMAC_SHA256: - { - byte verify[SHA256_DIGEST_SIZE]; - Hmac hmac; + { + byte verify[SHA256_DIGEST_SIZE]; + Hmac hmac; + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); - if (ret != 0) - break; - ret = wc_HmacFinal(&hmac, verify); - if (ret != 0) - break; - if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) - ret = -1; + if (ret == 0) + ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, verify); + if (ret == 0) { + if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) + ret = -1; + } + + wc_HmacFree(&hmac); } break; + } default: ret = BAD_FUNC_ARG; @@ -6559,6 +7375,9 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, if (ret != 0) break; ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz); + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif } break; #endif @@ -6586,15 +7405,12 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, #ifdef HAVE_COMP_KEY #ifndef WOLFSSL_ATECC508A -/* computes the jacobi c = (a | n) (or Legendre if n is prime) - * HAC pp. 73 Algorithm 2.149 - * HAC is wrong here, as the special case of (0 | 1) is not - * handled correctly. - */ -int mp_jacobi(mp_int* a, mp_int* n, int* c) +int do_mp_jacobi(mp_int* a, mp_int* n, int* c); + +int do_mp_jacobi(mp_int* a, mp_int* n, int* c) { - mp_int a1, p1; - int k, s, r, res; + int k, s, res; + int r = 0; /* initialize to help static analysis out */ mp_digit residue; /* if a < 0 return MP_VAL */ @@ -6627,18 +7443,9 @@ int mp_jacobi(mp_int* a, mp_int* n, int* c) /* default */ s = 0; - /* step 3. write a = a1 * 2**k */ - if ((res = mp_init_multi(&a1, &p1, NULL, NULL, NULL, NULL)) != MP_OKAY) { - return res; - } - - if ((res = mp_copy(a, &a1)) != MP_OKAY) { - goto done; - } - /* divide out larger power of two */ - k = mp_cnt_lsb(&a1); - res = mp_div_2d(&a1, k, &a1, NULL); + k = mp_cnt_lsb(a); + res = mp_div_2d(a, k, a, NULL); if (res == MP_OKAY) { /* step 4. if e is even set s=1 */ @@ -6655,33 +7462,60 @@ int mp_jacobi(mp_int* a, mp_int* n, int* c) } } - /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ - if ( ((n->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + /* step 5. if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */ + if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) { s = -s; } } if (res == MP_OKAY) { - /* if a1 == 1 we're done */ - if (mp_cmp_d (&a1, 1) == MP_EQ) { + /* if a == 1 we're done */ + if (mp_cmp_d(a, 1) == MP_EQ) { *c = s; } else { - /* n1 = n mod a1 */ - res = mp_mod (n, &a1, &p1); + /* n1 = n mod a */ + res = mp_mod (n, a, n); if (res == MP_OKAY) - res = mp_jacobi (&p1, &a1, &r); + res = do_mp_jacobi(n, a, &r); if (res == MP_OKAY) *c = s * r; } } + return res; +} + + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + * HAC is wrong here, as the special case of (0 | 1) is not + * handled correctly. + */ +int mp_jacobi(mp_int* a, mp_int* n, int* c) +{ + mp_int a1, n1; + int res; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) { + return res; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto done; + } + + if ((res = mp_copy(n, &n1)) != MP_OKAY) { + goto done; + } + + res = do_mp_jacobi(&a1, &n1, c); + done: /* cleanup */ -#ifndef USE_FAST_MATH - mp_clear(&p1); + mp_clear(&n1); mp_clear(&a1); -#endif return res; } @@ -6704,8 +7538,7 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) return MP_OKAY; } if (mp_cmp_d(n, 1) == MP_EQ) { - mp_set(ret, 1); - return MP_OKAY; + return mp_set(ret, 1); } /* prime must be odd */ @@ -6856,12 +7689,11 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) /* M = i */ if (res == MP_OKAY) - mp_set(&M, i); + res = mp_set(&M, i); } } } -#ifndef USE_FAST_MATH /* done */ mp_clear(&t1); mp_clear(&C); @@ -6872,7 +7704,6 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) mp_clear(&T); mp_clear(&R); mp_clear(&two); -#endif return res; } @@ -6982,16 +7813,6 @@ int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp) #ifdef HAVE_X963_KDF -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - static INLINE void IncrementX963KdfCounter(byte* inOutCtr) { int i; @@ -7104,51 +7925,4 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #endif /* HAVE_X963_KDF */ - -#ifdef WOLFSSL_ASYNC_CRYPT - -int wc_ecc_async_handle(ecc_key* key, WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) -{ - int ret; - - if (key == NULL || queue == NULL || event == NULL) { - return BAD_FUNC_ARG; - } - - /* make sure this ECC context had "wc_EccAsyncInit" called on it */ - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) { - return ASYNC_INIT_E; - } - - /* setup the event and push to queue */ - ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = wolfEventQueue_Push(queue, event); - } - - /* check for error (helps with debugging) */ - if (ret != 0) { - WOLFSSL_MSG("wc_EccAsyncHandle failed"); - } - return ret; -} - -int wc_ecc_async_wait(int ret, ecc_key* key) -{ - if (ret == WC_PENDING_E) { - WOLF_EVENT event; - XMEMSET(&event, 0, sizeof(event)); - ret = wolfAsync_EventInit(&event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, &key->asyncDev); - if (ret == 0) { - ret = wolfAsync_EventWait(&event); - if (ret == 0 && event.ret >= 0) { - ret = event.ret; - } - } - } - return ret; -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ - #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 310b6cfd6..258631b00 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -207,11 +207,11 @@ int wc_ed25519_sign_msg(const byte* in, word32 inlen, byte* out, siglen is the length of sig byte array msg the array of bytes containing the message msglen length of msg array - stat will be 1 on successful verify and 0 on unsuccessful - return 0 and stat of 1 on success + res will be 1 on successful verify and 0 on unsuccessful + return 0 and res of 1 on success */ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, - word32 msglen, int* stat, ed25519_key* key) + word32 msglen, int* res, ed25519_key* key) { byte rcheck[ED25519_KEY_SIZE]; byte h[SHA512_DIGEST_SIZE]; @@ -223,11 +223,11 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, Sha512 sha; /* sanity check on arguments */ - if (sig == NULL || msg == NULL || stat == NULL || key == NULL) + if (sig == NULL || msg == NULL || res == NULL || key == NULL) return BAD_FUNC_ARG; /* set verification failed by default */ - *stat = 0; + *res = 0; /* check on basics needed to verify signature */ if (siglen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) @@ -279,7 +279,7 @@ int wc_ed25519_verify_msg(byte* sig, word32 siglen, const byte* msg, return SIG_VERIFY_E; /* set the verification status */ - *stat = 1; + *res = 1; return ret; } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 2de4e7c0a..b5b578d5a 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -204,7 +204,7 @@ const char* wc_GetErrorString(int error) return "ASN NTRU key decode error, invalid input"; case ASN_CRIT_EXT_E: - return "X.509 Critical extension ignored"; + return "X.509 Critical extension ignored or invalid"; case ECC_BAD_ARG_E : return "ECC input argument wrong type, invalid input"; @@ -338,6 +338,9 @@ const char* wc_GetErrorString(int error) case ECC_INF_E: return " ECC point at infinity error"; + case ECC_OUT_OF_RANGE_E: + return " ECC Qx or Qy out of range error"; + case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; @@ -407,6 +410,21 @@ const char* wc_GetErrorString(int error) case BAD_KEYWRAP_IV_E: return "Decrypted AES key wrap IV does not match expected"; + case WC_CLEANUP_E: + return "wolfcrypt cleanup failed"; + + case ECC_CDH_KAT_FIPS_E: + return "wolfcrypt FIPS ECC CDH Known Answer Test Failure"; + + case DH_CHECK_PUB_E: + return "DH Check Public Key failure"; + + case BAD_PATH_ERROR: + return "Bad path for opendir error"; + + case ASYNC_OP_E: + return "Async operation error"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c new file mode 100644 index 000000000..3dcac0c02 --- /dev/null +++ b/wolfcrypt/src/evp.c @@ -0,0 +1,539 @@ +/* evp.c + * + * Copyright (C) 2006-2016 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); + +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv) +{ + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv) +{ + (void) impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + unsigned char* key, unsigned char* iv) +{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 0); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit"); + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, 0); +} + +WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) +{ + WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ctx){ + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); + wolfSSL_EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return 0; + return ctx->flags & WOLFSSL_EVP_CIPH_MODE; +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc){ + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return 0; +} + + +WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + unsigned char* key, unsigned char* iv, + int enc) +{ + (void)impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc){ + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return 0; +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) + return 0; + else{ + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) + return 0; + else{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } +} + + +WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex"); + return wolfSSL_EVP_DigestInit(ctx, type); +} + +#ifdef DEBUG_WOLFSSL_EVP +#define PRINT_BUF(b, sz) { int i; for(i=0; i<(sz); i++){printf("%02x(%c),", (b)[i], (b)[i]); if((i+1)%8==0)printf("\n");}} +#else +#define PRINT_BUF(b, sz) +#endif + +static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz) +{ + int fill; + + if (sz > 0) { + if ((sz+ctx->bufUsed) > ctx->block_size) { + fill = ctx->block_size - ctx->bufUsed; + } else { + fill = sz; + } + XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill); + ctx->bufUsed += fill; + return fill; + } else return 0; +} + +static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, int inl) +{ + int ret = 0; + + switch (ctx->cipherType) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + if (ctx->enc) + wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + else + wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + if (ctx->enc) + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + else + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_CBC_TYPE: + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + break; + #if defined(WOLFSSL_DES_ECB) + case DES_ECB_TYPE: + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_ECB_TYPE: + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + break; + #endif /* WOLFSSL_DES_ECB */ + #endif /* !NO_DES3 */ + default: + return 0; + } + + if (ret != 0) + return 0; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return 1; /* success */ +} + +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int blocks; + int fill; + + if (ctx == NULL) return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + *outl = 0; + if (ctx->bufUsed > 0) { /* concatinate them if there is anything */ + fill = fillBuff(ctx, in, inl); + inl -= fill; + in += fill; + } + if((ctx->enc == 0)&& (ctx->lastUsed == 1)){ + PRINT_BUF(ctx->lastBlock, ctx->block_size); + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl+= ctx->block_size; + out += ctx->block_size; + } + if ((ctx->bufUsed == ctx->block_size) || (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING)){ + /* the buff is full, flash out */ + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return 0; + PRINT_BUF(out, ctx->block_size); + if(ctx->enc == 0){ + ctx->lastUsed = 1; + XMEMCPY(ctx->lastBlock, out, ctx->block_size); + } else { + *outl+= ctx->block_size; + out += ctx->block_size; + } + ctx->bufUsed = 0; + } + + blocks = inl / ctx->block_size; + if (blocks > 0) { + /* process blocks */ + if (evpCipherBlock(ctx, out, in, blocks*ctx->block_size) == 0) + return 0; + PRINT_BUF(ctx->buf, ctx->block_size); + PRINT_BUF(out, ctx->block_size); + inl -= ctx->block_size * blocks; + in += ctx->block_size * blocks; + if(ctx->enc == 0){ + ctx->lastUsed = 1; + XMEMCPY(ctx->lastBlock, &out[ctx->block_size * (blocks-1)], ctx->block_size); + *outl+= ctx->block_size * (blocks-1); + } else { + *outl+= ctx->block_size * blocks; + } + } + if (inl > 0) { + /* put fraction into buff */ + fillBuff(ctx, in, inl); + /* no increase of outl */ + } + + (void)out; /* silence warning in case not read */ + + return 1; +} + +static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int i; + for (i = ctx->bufUsed; i < ctx->block_size; i++) + ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed); +} + +static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) +{ + int i; + int n; + n = buff[ctx->block_size-1]; + + if (n > ctx->block_size) return FALSE; + for (i = 0; i < n; i++){ + if (buff[ctx->block_size-i-1] != n) + return FALSE; + } + return ctx->block_size - n; +} + +WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl ; + if (ctx == NULL || out == NULL) return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); + if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + *outl = 0; + return 1; + } + if (ctx->enc) { + if (ctx->bufUsed > 0) { + padBlock(ctx); + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return 0; + PRINT_BUF(out, ctx->block_size); + *outl = ctx->block_size; + } + } else { + if (ctx->lastUsed){ + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { + XMEMCPY(out, ctx->lastBlock, fl); + *outl = fl; + } else return 0; + } + } + return 1; +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + switch (ctx->cipherType) { + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: +#endif +#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: +#endif +#if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_ECB_TYPE: + case DES_EDE3_CBC_TYPE: + case DES_EDE3_ECB_TYPE: +#endif + return ctx->block_size; + default: + return 0; + } +} + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; /* dummy for #ifdef */ + #ifndef NO_DES3 + else if (XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0) + return DES_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_CBC_TYPE; + #if !defined(NO_DES3) + else if (XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0) + return DES_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_ECB_TYPE; + #endif /* NO_DES3 && HAVE_AES_ECB */ + #endif + + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + else if (XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + return AES_128_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + return AES_192_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + return AES_256_CBC_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + else if (XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0) + return AES_128_CTR_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0) + return AES_192_CTR_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0) + return AES_256_CTR_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + else if (XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0) + return AES_128_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0) + return AES_192_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0) + return AES_256_ECB_TYPE; + #endif /* !NO_AES && HAVE_AES_CBC */ + else return 0; +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return BAD_FUNC_ARG; + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return AES_BLOCK_SIZE; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 8; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 8; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE ; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return WOLFSSL_EVP_CIPH_CTR_MODE ; + #endif + #if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE ; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_EDE3_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE ; + case DES_ECB_TYPE: + case DES_EDE3_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE ; + #endif + default: + return 0; + } +} + +WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags = flags; + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + if (padding) { + ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING; + } + else { + ctx->flags |= WOLFSSL_EVP_CIPH_NO_PADDING; + } + return 1; +} + +WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) +{ + (void)digest; + /* nothing to do */ + return 0; +} diff --git a/wolfcrypt/src/fe_low_mem.c b/wolfcrypt/src/fe_low_mem.c index 9caffa81f..aa6a44996 100644 --- a/wolfcrypt/src/fe_low_mem.c +++ b/wolfcrypt/src/fe_low_mem.c @@ -183,7 +183,7 @@ static void raw_add(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c += ((word16)x[i]) + ((word16)p[i]); - x[i] = c; + x[i] = (byte)c; c >>= 8; } } @@ -197,11 +197,11 @@ static void raw_try_sub(byte *x, const byte *p) for (i = 0; i < F25519_SIZE; i++) { c = ((word16)x[i]) - ((word16)p[i]) - c; - minusp[i] = c; + minusp[i] = (byte)c; c = (c >> 8) & 1; } - fprime_select(x, minusp, x, c); + fprime_select(x, minusp, x, (byte)c); } @@ -271,7 +271,7 @@ void fprime_mul(byte *r, const byte *a, const byte *b, for (j = 0; j < F25519_SIZE; j++) { c |= ((word16)r[j]) << 1; - r[j] = c; + r[j] = (byte)c; c >>= 8; } raw_try_sub(r, modulus); @@ -310,7 +310,7 @@ void fe_normalize(byte *x) for (i = 0; i < F25519_SIZE; i++) { c += x[i]; - x[i] = c; + x[i] = (byte)c; c >>= 8; } @@ -322,12 +322,12 @@ void fe_normalize(byte *x) for (i = 0; i + 1 < F25519_SIZE; i++) { c += x[i]; - minusp[i] = c; + minusp[i] = (byte)c; c >>= 8; } c += ((word16)x[i]) - 128; - minusp[31] = c; + minusp[31] = (byte)c; /* Load x-p if no underflow */ fe_select(x, minusp, x, (c >> 15) & 1); @@ -355,7 +355,7 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c >>= 8; c += ((word16)a[i]) + ((word16)b[i]); - r[i] = c; + r[i] = (byte)c; } /* Reduce with 2^255 = 19 mod p */ @@ -364,7 +364,7 @@ void fe_add(fe r, const fe a, const fe b) for (i = 0; i < F25519_SIZE; i++) { c += r[i]; - r[i] = c; + r[i] = (byte)c; c >>= 8; } } diff --git a/wolfcrypt/src/fe_operations.c b/wolfcrypt/src/fe_operations.c old mode 100644 new mode 100755 index 9dfeab093..285f6c0cf --- a/wolfcrypt/src/fe_operations.c +++ b/wolfcrypt/src/fe_operations.c @@ -41,6 +41,9 @@ #include #endif +#ifdef HAVE___UINT128_T +#include "fe_x25519_128.i" +#else /* fe means field element. Here the field is \Z/(2^255-19). @@ -942,7 +945,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cswap(fe f,fe g,unsigned int b) +void fe_cswap(fe f, fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1353,7 +1356,7 @@ replace (f,g) with (f,g) if b == 0. Preconditions: b in {0,1}. */ -void fe_cmov(fe f,const fe g,unsigned int b) +void fe_cmov(fe f, const fe g, int b) { int32_t f0 = f[0]; int32_t f1 = f[1]; @@ -1407,6 +1410,7 @@ void fe_cmov(fe f,const fe g,unsigned int b) f[8] = f8 ^ x8; f[9] = f9 ^ x9; } +#endif #endif /* HAVE ED25519 or CURVE25519 */ #endif /* not defined CURVED25519_SMALL */ diff --git a/wolfcrypt/src/fe_x25519_128.i b/wolfcrypt/src/fe_x25519_128.i new file mode 100644 index 000000000..d7297a260 --- /dev/null +++ b/wolfcrypt/src/fe_x25519_128.i @@ -0,0 +1,612 @@ +/* fp_mont_small.i + * + * Copyright (C) 2006-2017 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Convert a number represented as an array of bytes to an array of words with + * 51-bits of data in each word. + * + * in An array of bytes. + * out An array of words. + */ +void fe_frombytes(fe out, const unsigned char *in) +{ + out[0] = (((int64_t)((in[ 0] ) )) ) + | (((int64_t)((in[ 1] ) )) << 8) + | (((int64_t)((in[ 2] ) )) << 16) + | (((int64_t)((in[ 3] ) )) << 24) + | (((int64_t)((in[ 4] ) )) << 32) + | (((int64_t)((in[ 5] ) )) << 40) + | (((int64_t)((in[ 6] ) & 0x07)) << 48); + out[1] = (((int64_t)((in[ 6] >> 3) & 0x1f)) ) + | (((int64_t)((in[ 7] ) )) << 5) + | (((int64_t)((in[ 8] ) )) << 13) + | (((int64_t)((in[ 9] ) )) << 21) + | (((int64_t)((in[10] ) )) << 29) + | (((int64_t)((in[11] ) )) << 37) + | (((int64_t)((in[12] ) & 0x3f)) << 45); + out[2] = (((int64_t)((in[12] >> 6) & 0x03)) ) + | (((int64_t)((in[13] ) )) << 2) + | (((int64_t)((in[14] ) )) << 10) + | (((int64_t)((in[15] ) )) << 18) + | (((int64_t)((in[16] ) )) << 26) + | (((int64_t)((in[17] ) )) << 34) + | (((int64_t)((in[18] ) )) << 42) + | (((int64_t)((in[19] ) & 0x01)) << 50); + out[3] = (((int64_t)((in[19] >> 1) & 0x7f)) ) + | (((int64_t)((in[20] ) )) << 7) + | (((int64_t)((in[21] ) )) << 15) + | (((int64_t)((in[22] ) )) << 23) + | (((int64_t)((in[23] ) )) << 31) + | (((int64_t)((in[24] ) )) << 39) + | (((int64_t)((in[25] ) & 0x0f)) << 47); + out[4] = (((int64_t)((in[25] >> 4) & 0x0f)) ) + | (((int64_t)((in[26] ) )) << 4) + | (((int64_t)((in[27] ) )) << 12) + | (((int64_t)((in[28] ) )) << 20) + | (((int64_t)((in[29] ) )) << 28) + | (((int64_t)((in[30] ) )) << 36) + | (((int64_t)((in[31] ) & 0x7f)) << 44); +} + +/* Convert a number represented as an array of words to an array of bytes. + * The array of words is normalized to an array of 51-bit data words and if + * greater than the mod, modulo reduced by the prime 2^255 - 1. + * + * n An array of words. + * out An array of bytes. + */ +void fe_tobytes(unsigned char *out, const fe n) +{ + fe in; + int64_t c; + + in[0] = n[0]; + in[1] = n[1]; + in[2] = n[2]; + in[3] = n[3]; + in[4] = n[4]; + + /* Normalize to 51-bits of data per word. */ + in[0] += (in[4] >> 51) * 19; in[4] &= 0x7ffffffffffff; + + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[0] += (in[4] >> 51) * 19; + in[4] &= 0x7ffffffffffff; + + c = (in[0] + 19) >> 51; + c = (in[1] + c) >> 51; + c = (in[2] + c) >> 51; + c = (in[3] + c) >> 51; + c = (in[4] + c) >> 51; + in[0] += c * 19; + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[4] &= 0x7ffffffffffff; + + out[ 0] = (((byte)((in[0] ) )) ); + out[ 1] = (((byte)((in[0] >> 8) )) ); + out[ 2] = (((byte)((in[0] >> 16) )) ); + out[ 3] = (((byte)((in[0] >> 24) )) ); + out[ 4] = (((byte)((in[0] >> 32) )) ); + out[ 5] = (((byte)((in[0] >> 40) )) ); + out[ 6] = (((byte)((in[0] >> 48) & 0x07)) ) + | (((byte)((in[1] ) & 0x1f)) << 3); + out[ 7] = (((byte)((in[1] >> 5) )) ); + out[ 8] = (((byte)((in[1] >> 13) )) ); + out[ 9] = (((byte)((in[1] >> 21) )) ); + out[10] = (((byte)((in[1] >> 29) )) ); + out[11] = (((byte)((in[1] >> 37) )) ); + out[12] = (((byte)((in[1] >> 45) & 0x3f)) ) + | (((byte)((in[2] ) & 0x03)) << 6); + out[13] = (((byte)((in[2] >> 2) )) ); + out[14] = (((byte)((in[2] >> 10) )) ); + out[15] = (((byte)((in[2] >> 18) )) ); + out[16] = (((byte)((in[2] >> 26) )) ); + out[17] = (((byte)((in[2] >> 34) )) ); + out[18] = (((byte)((in[2] >> 42) )) ); + out[19] = (((byte)((in[2] >> 50) & 0x01)) ) + | (((byte)((in[3] ) & 0x7f)) << 1); + out[20] = (((byte)((in[3] >> 7) )) ); + out[21] = (((byte)((in[3] >> 15) )) ); + out[22] = (((byte)((in[3] >> 23) )) ); + out[23] = (((byte)((in[3] >> 31) )) ); + out[24] = (((byte)((in[3] >> 39) )) ); + out[25] = (((byte)((in[3] >> 47) & 0x0f)) ) + | (((byte)((in[4] ) & 0x0f)) << 4); + out[26] = (((byte)((in[4] >> 4) )) ); + out[27] = (((byte)((in[4] >> 12) )) ); + out[28] = (((byte)((in[4] >> 20) )) ); + out[29] = (((byte)((in[4] >> 28) )) ); + out[30] = (((byte)((in[4] >> 36) )) ); + out[31] = (((byte)((in[4] >> 44) & 0x7f)) ); +} + +/* Set the field element to 1. + * + * n The field element number. + */ +void fe_1(fe n) +{ + n[0] = 0x0000000000001; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Set the field element to 0. + * + * n The field element number. + */ +void fe_0(fe n) +{ + n[0] = 0x0000000000000; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Copy field element a into field element r. + * + * r Field element to copy into. + * a Field element to copy. + */ +void fe_copy(fe r, const fe a) +{ + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; + r[4] = a[4]; +} + +/* Constant time, conditional swap of field elements a and b. + * + * a A field element. + * b A field element. + * c If 1 then swap and if 0 then don't swap. + */ +void fe_cswap(fe a, fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; +} + +/* Subtract b from a into r. (r = a - b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sub(fe r, const fe a, const fe b) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; + r[3] = a[3] - b[3]; + r[4] = a[4] - b[4]; +} + +/* Add b to a into r. (r = a + b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_add(fe r, const fe a, const fe b) +{ + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; + r[3] = a[3] + b[3]; + r[4] = a[4] + b[4]; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul(fe r, const fe a, const fe b) +{ + __int128_t t0 = ((__int128_t)a[0]) * b[0]; + __int128_t t1 = ((__int128_t)a[0]) * b[1] + + ((__int128_t)a[1]) * b[0]; + __int128_t t2 = ((__int128_t)a[0]) * b[2] + + ((__int128_t)a[1]) * b[1] + + ((__int128_t)a[2]) * b[0]; + __int128_t t3 = ((__int128_t)a[0]) * b[3] + + ((__int128_t)a[1]) * b[2] + + ((__int128_t)a[2]) * b[1] + + ((__int128_t)a[3]) * b[0]; + __int128_t t4 = ((__int128_t)a[0]) * b[4] + + ((__int128_t)a[1]) * b[3] + + ((__int128_t)a[2]) * b[2] + + ((__int128_t)a[3]) * b[1] + + ((__int128_t)a[4]) * b[0]; + __int128_t t5 = ((__int128_t)a[1]) * b[4] + + ((__int128_t)a[2]) * b[3] + + ((__int128_t)a[3]) * b[2] + + ((__int128_t)a[4]) * b[1]; + __int128_t t6 = ((__int128_t)a[2]) * b[4] + + ((__int128_t)a[3]) * b[3] + + ((__int128_t)a[4]) * b[2]; + __int128_t t7 = ((__int128_t)a[3]) * b[4] + + ((__int128_t)a[4]) * b[3]; + __int128_t t8 = ((__int128_t)a[4]) * b[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq(fe r, const fe a) +{ + __int128_t t0 = ((__int128_t)a[0]) * a[0]; + __int128_t t1 = ((__int128_t)a[0]) * a[1] * 2; + __int128_t t2 = ((__int128_t)a[0]) * a[2] * 2 + + ((__int128_t)a[1]) * a[1]; + __int128_t t3 = ((__int128_t)a[0]) * a[3] * 2 + + ((__int128_t)a[1]) * a[2] * 2; + __int128_t t4 = ((__int128_t)a[0]) * a[4] * 2 + + ((__int128_t)a[1]) * a[3] * 2 + + ((__int128_t)a[2]) * a[2]; + __int128_t t5 = ((__int128_t)a[1]) * a[4] * 2 + + ((__int128_t)a[2]) * a[3] * 2; + __int128_t t6 = ((__int128_t)a[2]) * a[4] * 2 + + ((__int128_t)a[3]) * a[3]; + __int128_t t7 = ((__int128_t)a[3]) * a[4] * 2; + __int128_t t8 = ((__int128_t)a[4]) * a[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Multiply a by 121666 and put result in r. (r = 121666 * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul121666(fe r, fe a) +{ + __int128_t t0 = ((__int128_t)a[0]) * (int64_t)121666; + __int128_t t1 = ((__int128_t)a[1]) * (int64_t)121666; + __int128_t t2 = ((__int128_t)a[2]) * (int64_t)121666; + __int128_t t3 = ((__int128_t)a[3]) * (int64_t)121666; + __int128_t t4 = ((__int128_t)a[4]) * (int64_t)121666; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +void fe_invert(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); + fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul( r, t1, t0); +} + +/* Scalar multiply the field element a by n using Montgomery Ladder and places + * result in r. + * + * r A field element as an array of bytes. + * n The scalar as an array of bytes. + * a A field element as an array of bytes. + */ +int curve25519(byte* r, byte* n, byte* a) +{ + fe x1, x2, z2, x3, z3; + fe t0, t1; + int pos; + unsigned int swap; + unsigned int b; + + fe_frombytes(x1, a); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + swap = 0; + for (pos = 254;pos >= 0;--pos) { + b = n[pos / 8] >> (pos & 7); + b &= 1; + swap ^= b; + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + swap = b; + + fe_sub(t0, x3, z3); + fe_sub(t1, x2, z2); + fe_add(x2, x2, z2); + fe_add(z2, x3, z3); + fe_mul(z3, t0, x2); + fe_mul(z2, z2, t1); + fe_sq(t0, t1); + fe_sq(t1, x2); + fe_add(x3, z3, z2); + fe_sub(z2, z3, z2); + fe_mul(x2, t1, t0); + fe_sub(t1, t1, t0); + fe_sq(z2, z2); + fe_mul121666(z3, t1); + fe_sq(x3, x3); + fe_add(t0, t0, z3); + fe_mul(z3, x1, z2); + fe_mul(z2, t1, t0); + } + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + + fe_invert(z2, z2); + fe_mul(x2, x2, z2); + fe_tobytes(r, x2); + + return 0; +} + +/* The field element value 0 as an array of bytes. */ +static const unsigned char zero[32] = {0}; + +/* Constant time check as to whether a is a not 0. + * + * a A field element. + */ +int fe_isnonzero(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return ConstantCompare(s, zero, 32); +} + +/* Checks whether a is negative. + * + * a A field element. + */ +int fe_isnegative(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return s[0] & 1; +} + +/* Negates field element a and stores the result in r. + * + * r A field element. + * a A field element. + */ +void fe_neg(fe r, const fe a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; +} + +/* Constant time, conditional move of b into a. + * a is not changed if the condition is 0. + * + * a A field element. + * b A field element. + * c If 1 then copy and if 0 then don't copy. + */ +void fe_cmov(fe a, const fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; +} + +void fe_pow22523(fe r, const fe a) +{ + fe t0, t1, t2; + int i; + + /* a ^ (2^255 - 23) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 20; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 100; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t0, t0); for (i = 1; i < 2; ++i) fe_sq(t0, t0); fe_mul( r, t0, a); + + return; +} + +/* Double the square of a and put result in r. (r = 2 * a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq2(fe r, const fe a) +{ + __int128_t t0 = 2 * (((__int128_t)a[0]) * a[0]); + __int128_t t1 = 2 * (((__int128_t)a[0]) * a[1] * 2); + __int128_t t2 = 2 * (((__int128_t)a[0]) * a[2] * 2 + + ((__int128_t)a[1]) * a[1]); + __int128_t t3 = 2 * (((__int128_t)a[0]) * a[3] * 2 + + ((__int128_t)a[1]) * a[2] * 2); + __int128_t t4 = 2 * (((__int128_t)a[0]) * a[4] * 2 + + ((__int128_t)a[1]) * a[3] * 2 + + ((__int128_t)a[2]) * a[2]); + __int128_t t5 = 2 * (((__int128_t)a[1]) * a[4] * 2 + + ((__int128_t)a[2]) * a[3] * 2); + __int128_t t6 = 2 * (((__int128_t)a[2]) * a[4] * 2 + + ((__int128_t)a[3]) * a[3]); + __int128_t t7 = 2 * (((__int128_t)a[3]) * a[4] * 2); + __int128_t t8 = 2 * (((__int128_t)a[4]) * a[4]); + + /* Modulo reduce double long word. */ + t0 += t5 * 19; + t1 += t6 * 19; + t2 += t7 * 19; + t3 += t8 * 19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * 19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * 19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Load 3 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16)); + + return result; +} + +/* Load 4 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24)); + + return result; +} + diff --git a/wolfcrypt/src/ge_operations.c b/wolfcrypt/src/ge_operations.c index 99eaeb2dc..bf9b2eee4 100644 --- a/wolfcrypt/src/ge_operations.c +++ b/wolfcrypt/src/ge_operations.c @@ -274,38 +274,38 @@ void sc_reduce(byte* s) carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; + s[0] = (byte)(s0 >> 0); + s[1] = (byte)(s0 >> 8); + s[2] = (byte)((s0 >> 16) | (s1 << 5)); + s[3] = (byte)(s1 >> 3); + s[4] = (byte)(s1 >> 11); + s[5] = (byte)((s1 >> 19) | (s2 << 2)); + s[6] = (byte)(s2 >> 6); + s[7] = (byte)((s2 >> 14) | (s3 << 7)); + s[8] = (byte)(s3 >> 1); + s[9] = (byte)(s3 >> 9); + s[10] = (byte)((s3 >> 17) | (s4 << 4)); + s[11] = (byte)(s4 >> 4); + s[12] = (byte)(s4 >> 12); + s[13] = (byte)((s4 >> 20) | (s5 << 1)); + s[14] = (byte)(s5 >> 7); + s[15] = (byte)((s5 >> 15) | (s6 << 6)); + s[16] = (byte)(s6 >> 2); + s[17] = (byte)(s6 >> 10); + s[18] = (byte)((s6 >> 18) | (s7 << 3)); + s[19] = (byte)(s7 >> 5); + s[20] = (byte)(s7 >> 13); + s[21] = (byte)(s8 >> 0); + s[22] = (byte)(s8 >> 8); + s[23] = (byte)((s8 >> 16) | (s9 << 5)); + s[24] = (byte)(s9 >> 3); + s[25] = (byte)(s9 >> 11); + s[26] = (byte)((s9 >> 19) | (s10 << 2)); + s[27] = (byte)(s10 >> 6); + s[28] = (byte)((s10 >> 14) | (s11 << 7)); + s[29] = (byte)(s11 >> 1); + s[30] = (byte)(s11 >> 9); + s[31] = (byte)(s11 >> 17); /* hush warnings after setting values to 0 */ (void)s12; @@ -640,38 +640,38 @@ void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) carry9 = s9 >> 21; s10 += carry9; s9 -= carry9 << 21; carry10 = s10 >> 21; s11 += carry10; s10 -= carry10 << 21; - s[0] = s0 >> 0; - s[1] = s0 >> 8; - s[2] = (s0 >> 16) | (s1 << 5); - s[3] = s1 >> 3; - s[4] = s1 >> 11; - s[5] = (s1 >> 19) | (s2 << 2); - s[6] = s2 >> 6; - s[7] = (s2 >> 14) | (s3 << 7); - s[8] = s3 >> 1; - s[9] = s3 >> 9; - s[10] = (s3 >> 17) | (s4 << 4); - s[11] = s4 >> 4; - s[12] = s4 >> 12; - s[13] = (s4 >> 20) | (s5 << 1); - s[14] = s5 >> 7; - s[15] = (s5 >> 15) | (s6 << 6); - s[16] = s6 >> 2; - s[17] = s6 >> 10; - s[18] = (s6 >> 18) | (s7 << 3); - s[19] = s7 >> 5; - s[20] = s7 >> 13; - s[21] = s8 >> 0; - s[22] = s8 >> 8; - s[23] = (s8 >> 16) | (s9 << 5); - s[24] = s9 >> 3; - s[25] = s9 >> 11; - s[26] = (s9 >> 19) | (s10 << 2); - s[27] = s10 >> 6; - s[28] = (s10 >> 14) | (s11 << 7); - s[29] = s11 >> 1; - s[30] = s11 >> 9; - s[31] = s11 >> 17; + s[0] = (byte)(s0 >> 0); + s[1] = (byte)(s0 >> 8); + s[2] = (byte)((s0 >> 16) | (s1 << 5)); + s[3] = (byte)(s1 >> 3); + s[4] = (byte)(s1 >> 11); + s[5] = (byte)((s1 >> 19) | (s2 << 2)); + s[6] = (byte)(s2 >> 6); + s[7] = (byte)((s2 >> 14) | (s3 << 7)); + s[8] = (byte)(s3 >> 1); + s[9] = (byte)(s3 >> 9); + s[10] = (byte)((s3 >> 17) | (s4 << 4)); + s[11] = (byte)(s4 >> 4); + s[12] = (byte)(s4 >> 12); + s[13] = (byte)((s4 >> 20) | (s5 << 1)); + s[14] = (byte)(s5 >> 7); + s[15] = (byte)((s5 >> 15) | (s6 << 6)); + s[16] = (byte)(s6 >> 2); + s[17] = (byte)(s6 >> 10); + s[18] = (byte)((s6 >> 18) | (s7 << 3)); + s[19] = (byte)(s7 >> 5); + s[20] = (byte)(s7 >> 13); + s[21] = (byte)(s8 >> 0); + s[22] = (byte)(s8 >> 8); + s[23] = (byte)((s8 >> 16) | (s9 << 5)); + s[24] = (byte)(s9 >> 3); + s[25] = (byte)(s9 >> 11); + s[26] = (byte)((s9 >> 19) | (s10 << 2)); + s[27] = (byte)(s10 >> 6); + s[28] = (byte)((s10 >> 14) | (s11 << 7)); + s[29] = (byte)(s11 >> 1); + s[30] = (byte)(s11 >> 9); + s[31] = (byte)(s11 >> 17); /* hush warnings after setting values to 0 */ (void)s12; @@ -754,7 +754,7 @@ static unsigned char negative(signed char b) unsigned long long x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ x >>= 63; /* 1: yes; 0: no */ - return x; + return (unsigned char)x; } @@ -765,7 +765,1354 @@ static void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b) fe_cmov(t->xy2d,u->xy2d,b); } - +#ifdef HAVE___UINT128_T +static const ge_precomp base[32][8] = { +{ + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2 }, + { 0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92 }, + { 0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58 }, + { 0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a }, + { 0x3fbe9c476ff09, 0x0af6b982e4b42, 0x0ad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553 }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3 }, + { 0x006b67b7d8ca4, 0x084fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417 }, + { 0x4326702ea4b71, 0x06834376030b5, 0x0ef0512f9c380, 0x0f1a9f2512584, 0x10b8e91a9f0d6 }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x0915e76061bce }, + { 0x75dedf39234d9, 0x01c36ab1f3c54, 0x0f08fee58f5da, 0x0e19613a0d637, 0x3a9024a1320e0 }, + { 0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4 }, + }, +}, +{ + { + { 0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee }, + { 0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31 }, + { 0x444172106e4c7, 0x01251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864 }, + }, + { + { 0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x03bf9baf55080 }, + { 0x3c4277dbe5fde, 0x5a335afd44c92, 0x0c1164099753e, 0x70487006fe423, 0x25e61cabed66f }, + { 0x3e128cc586604, 0x5968b2e8fc7e2, 0x049a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e }, + }, + { + { 0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b }, + { 0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3 }, + { 0x746166985f7d4, 0x09939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5 }, + }, + { + { 0x70b2f4e71ecb8, 0x728148efc643c, 0x0753e03995b76, 0x5bf5fb2ab6767, 0x05fc3bc4535d7 }, + { 0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0x0b9cf062eb09e, 0x2fd9c71e5f758 }, + { 0x0b3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651 }, + }, + { + { 0x095cb14246590, 0x002d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907 }, + { 0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f }, + { 0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x02521cf67a635 }, + }, + { + { 0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x001753d9f7cd6 }, + { 0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382 }, + { 0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e }, + }, + { + { 0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c }, + { 0x0fbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x037e9023930ff, 0x749b76f96fb12 }, + { 0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0x0a8b0d4045af7, 0x0fcec10f01e02 }, + }, + { + { 0x2d29dc4244e45, 0x6927b1bc147be, 0x0308534ac0839, 0x4853664033f41, 0x413779166feab }, + { 0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0x0f981220e2d44, 0x4901aa7183c51 }, + { 0x1b7548c1af8f0, 0x7848c53368116, 0x01b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1 }, + }, +}, +{ + { + { 0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0x0a871e070c6a9 }, + { 0x07d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb }, + { 0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d }, + }, + { + { 0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x01850832f0ef1, 0x7d47c6a2cfb89 }, + { 0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912 }, + { 0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e }, + }, + { + { 0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0x0dccfe885b6b4, 0x278febad4eaea }, + { 0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db }, + { 0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6 }, + }, + { + { 0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x0165b5a48efca }, + { 0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5 }, + { 0x0a474a0846a76, 0x099a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec }, + }, + { + { 0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301 }, + { 0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7 }, + { 0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb }, + }, + { + { 0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0x0adc8d1a97b28, 0x06a1a6c288675 }, + { 0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6 }, + { 0x0d1d47c1764b6, 0x01c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274 }, + }, + { + { 0x4278b85eaec2e, 0x0ef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059 }, + { 0x777fd3a2dcc7f, 0x594a9fb124932, 0x01f8e80ca15f0, 0x714d13cec3269, 0x0403ed1d0ca67 }, + { 0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303 }, + }, + { + { 0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f }, + { 0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a }, + { 0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x0690c11b03bcd, 0x740dca6d58f0e }, + }, +}, +{ + { + { 0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0 }, + { 0x0ee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea }, + { 0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b }, + }, + { + { 0x53de66aa91948, 0x045f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2 }, + { 0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905 }, + { 0x6134b925112e1, 0x6bb942bb406ed, 0x070c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032 }, + }, + { + { 0x1fec6f0e7f04c, 0x3cebc692c477d, 0x077986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab }, + { 0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb }, + { 0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43 }, + }, + { + { 0x4431ca596cf14, 0x015da7c801405, 0x03c9b6f8f10b5, 0x0346922934017, 0x201f33139e457 }, + { 0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd }, + { 0x27f6b08039d51, 0x4802f8000dfaa, 0x09692a062c525, 0x1baea91075817, 0x397cba8862460 }, + }, + { + { 0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c }, + { 0x13093f05959b2, 0x1bd352f2ec618, 0x075789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6 }, + { 0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971 }, + }, + { + { 0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a }, + { 0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf }, + { 0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x088fe4eb8c225, 0x612436341f08b }, + }, + { + { 0x349e31a2d2638, 0x0137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90 }, + { 0x541db874e898d, 0x62d80fb841b33, 0x03e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef }, + { 0x02f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x036746419c8db, 0x45fe70f505243 }, + }, + { + { 0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2 }, + { 0x075a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39 }, + { 0x74a4401a308fd, 0x06ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3 }, + }, +}, +{ + { + { 0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8 }, + { 0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd }, + { 0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe }, + }, + { + { 0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd }, + { 0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0 }, + { 0x3b0cf4a465030, 0x022b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82 }, + }, + { + { 0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6 }, + { 0x004468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0x0bc3d08194a31 }, + { 0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19 }, + }, + { + { 0x0c172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x0770c9e824e1a }, + { 0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de }, + { 0x1d99a45b5b5fd, 0x523674f2499ec, 0x0f8fa26182613, 0x58f7398048c98, 0x39f264fd41500 }, + }, + { + { 0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0x0a761e4844a16, 0x65c621272c35f }, + { 0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889 }, + { 0x389f8ce3193dd, 0x2d424b8177ce5, 0x073fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce }, + }, + { + { 0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c }, + { 0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762 }, + { 0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0x0d5fde948eed6, 0x508214fa574bd }, + }, + { + { 0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb }, + { 0x269153ed6fe4b, 0x72a23aef89840, 0x052be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba }, + { 0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f }, + }, + { + { 0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9 }, + { 0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb }, + { 0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb }, + }, +}, +{ + { + { 0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x0844bdee2adf3, 0x4cbad279663ab }, + { 0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345 }, + { 0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007 }, + }, + { + { 0x45dc5f3c29094, 0x3455220b579af, 0x070c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d }, + { 0x71e6a266b2801, 0x09aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75 }, + { 0x297d86a7b3768, 0x4835a2f4c6332, 0x070305f434160, 0x183dd014e56ae, 0x7ccdd084387a0 }, + }, + { + { 0x484186760cc93, 0x7435665533361, 0x02f686336b801, 0x5225446f64331, 0x3593ca848190c }, + { 0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c }, + { 0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6 }, + }, + { + { 0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3 }, + { 0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3 }, + { 0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc }, + }, + { + { 0x615520fbf6363, 0x0b9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1 }, + { 0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f }, + { 0x0c938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647 }, + }, + { + { 0x08bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f }, + { 0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6 }, + { 0x6b517a751b13b, 0x0cfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e }, + }, + { + { 0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0x0fe9877824cde }, + { 0x3d2e0c30d0cd9, 0x3f597686671bb, 0x0aa587eb63999, 0x0e3c7b592c619, 0x6b2916c05448c }, + { 0x334d10aba913b, 0x045cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00 }, + }, + { + { 0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0x0ea89850aafe1, 0x416b151ab706a }, + { 0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0x0d61b8f78b2ab }, + { 0x0d7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e }, + }, +}, +{ + { + { 0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545 }, + { 0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc }, + { 0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115 }, + }, + { + { 0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x00731fbc78f89 }, + { 0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x021142e9c2b1c }, + { 0x0c71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15 }, + }, + { + { 0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9 }, + { 0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47 }, + { 0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4 }, + }, + { + { 0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e }, + { 0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189 }, + { 0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x022183510be8d }, + }, + { + { 0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404 }, + { 0x766385ead2d14, 0x0194f8b06095e, 0x08478f6823b62, 0x6018689d37308, 0x6a071ce17b806 }, + { 0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed }, + }, + { + { 0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424 }, + { 0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08 }, + { 0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924 }, + }, + { + { 0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7 }, + { 0x28e665ca59cc7, 0x165c715940dd9, 0x0785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84 }, + { 0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57 }, + }, + { + { 0x6706efc7c3484, 0x6987839ec366d, 0x0731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6 }, + { 0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64 }, + { 0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21 }, + }, +}, +{ + { + { 0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da }, + { 0x1214fe194961a, 0x0e1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917 }, + { 0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a }, + }, + { + { 0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66 }, + { 0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc }, + { 0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f }, + }, + { + { 0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52 }, + { 0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0x0d8cc1c48bc16 }, + { 0x402d36eb419a9, 0x7cef68c14a052, 0x0f1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16 }, + }, + { + { 0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53 }, + { 0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948 }, + { 0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4 }, + }, + { + { 0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c }, + { 0x094e7d7dced2a, 0x068fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99 }, + { 0x26c422e3622f4, 0x0f3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952 }, + }, + { + { 0x00c2af5f85c6b, 0x0609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0x0d1d2af9ffeb5 }, + { 0x0ed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x004475ea1a1bb, 0x0fee3e871e188 }, + { 0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531 }, + }, + { + { 0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161 }, + { 0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302 }, + { 0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f }, + }, + { + { 0x780f1680c3a94, 0x2a35d3cfcd453, 0x005e5cdc7ddf8, 0x6ee888078ac24, 0x054aa4b316b38 }, + { 0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1 }, + { 0x0468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da }, + }, +}, +{ + { + { 0x265e777d1f515, 0x0f1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc }, + { 0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d }, + { 0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0x0ad725db29ecb }, + }, + { + { 0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399 }, + { 0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03 }, + { 0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0x0bccbb72a2a86 }, + }, + { + { 0x55e4c50fe1296, 0x05fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3 }, + { 0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b }, + { 0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4 }, + }, + { + { 0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423 }, + { 0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d }, + { 0x0ba651c5b2b47, 0x5862363701027, 0x0c4d6c219c6db, 0x0f03dff8658de, 0x745d2ffa9c0cf }, + }, + { + { 0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x06e15be54c1dc }, + { 0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf }, + { 0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0x0fbbee20aa4ed, 0x58ded861278ec }, + }, + { + { 0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x08ba696b531d5 }, + { 0x73793f266c55c, 0x0b988a9c93b02, 0x09b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f }, + { 0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf }, + }, + { + { 0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x07433be3cb393 }, + { 0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0x0c2b85f39caca, 0x35d30a99b4d59 }, + { 0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d }, + }, + { + { 0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x0543618a01600 }, + { 0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa }, + { 0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079 }, + }, +}, +{ + { + { 0x454e91c529ccb, 0x24c98c6bf72cf, 0x0486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66 }, + { 0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6 }, + { 0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0x0c2a1c4bcda28 }, + }, + { + { 0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d }, + { 0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64 }, + { 0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x0404a5ca0afba }, + }, + { + { 0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e }, + { 0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9 }, + { 0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0x00b77ea5f78aa, 0x76579a29e822d }, + }, + { + { 0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x02c514bb2a277 }, + { 0x68e7e49c02a17, 0x45795346fe8b6, 0x089306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b }, + { 0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x02c989c8b6bd4, 0x1160920961548 }, + }, + { + { 0x05616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x0213ee10dfcea, 0x2f637d7491e6e }, + { 0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698 }, + { 0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2 }, + }, + { + { 0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5 }, + { 0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9 }, + { 0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0x0dea56e50e364, 0x556d1c8312ad7 }, + }, + { + { 0x06756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x097abe38cc8c7 }, + { 0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824 }, + { 0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8 }, + }, + { + { 0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009 }, + { 0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78 }, + { 0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635 }, + }, +}, +{ + { + { 0x0aaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7 }, + { 0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23 }, + { 0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895 }, + }, + { + { 0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x0408cc9469953, 0x50af7aed84afa }, + { 0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313 }, + { 0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x0033c0102c085, 0x1921a316baebd }, + }, + { + { 0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c }, + { 0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a }, + { 0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950 }, + }, + { + { 0x6eebe6084034b, 0x6cf01f70a8d7b, 0x0b41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647 }, + { 0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a }, + { 0x2b6e7a128b071, 0x5b27511755dcf, 0x08584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b }, + }, + { + { 0x048dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b }, + { 0x043c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0 }, + { 0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x079bfa9b08792 }, + }, + { + { 0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706 }, + { 0x03a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0x0ca769e789685, 0x038c77f684817 }, + { 0x65ee65b167bec, 0x052da19b850a9, 0x0408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf }, + }, + { + { 0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5 }, + { 0x080908a182fcf, 0x0532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f }, + { 0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x050eca52651e4 }, + }, + { + { 0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a }, + { 0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f }, + { 0x55c0dfdf05d96, 0x405569dcf475e, 0x05c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0 }, + }, +}, +{ + { + { 0x2aff530976b86, 0x0d85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340 }, + { 0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x09f56900584fd, 0x544d49292fc86 }, + { 0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316 }, + }, + { + { 0x3f635d32a7627, 0x0cbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06 }, + { 0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a }, + { 0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0x00f94051ee040 }, + }, + { + { 0x793bb07af9753, 0x1e7b6ecd4fafd, 0x02c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40 }, + { 0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x086d9b618b637, 0x07d79c7e8beab }, + { 0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64 }, + }, + { + { 0x06f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12 }, + { 0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee }, + { 0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x0621e2c7d3304 }, + }, + { + { 0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002 }, + { 0x060cc8259838d, 0x038d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x0007d6097bd3a }, + { 0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb }, + }, + { + { 0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55 }, + { 0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x02459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8 }, + { 0x094265066e80d, 0x0a60f918d61a5, 0x0444bf7f30fde, 0x1c40da9ed3c06, 0x079c170bd843b }, + }, + { + { 0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8 }, + { 0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f }, + { 0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5 }, + }, + { + { 0x147ab2bbea455, 0x1f240f2253126, 0x0c3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd }, + { 0x02b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929 }, + { 0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9 }, + }, +}, +{ + { + { 0x0639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x07a195152e095 }, + { 0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32 }, + { 0x68f02389e5fc8, 0x059f1bc877506, 0x504990e410cec, 0x09bd7d0feaee2, 0x3e8fe83d032f0 }, + }, + { + { 0x04c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258 }, + { 0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x003ef0e2d70b0, 0x75ba3b797fac4 }, + { 0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x0904d07b87779 }, + }, + { + { 0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72 }, + { 0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd }, + { 0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40 }, + }, + { + { 0x0d36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x03aa31507e1e5 }, + { 0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741 }, + { 0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4 }, + }, + { + { 0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x02b4d5e242940 }, + { 0x31e1988bb79bb, 0x7b82f46b3bcab, 0x0f7a8ce827b41, 0x5e15816177130, 0x326055cf5b276 }, + { 0x155cb28d18df2, 0x0c30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3 }, + }, + { + { 0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2 }, + { 0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0x0bf79176fd18a, 0x2cb67174ff60a }, + { 0x6cdf9390be1d0, 0x08e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f }, + }, + { + { 0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x01ed95554468f, 0x68698245d352e }, + { 0x2f2e0b3b2a224, 0x0c56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5 }, + { 0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0x0e7a25d714087, 0x46cf4c473daf0 }, + }, + { + { 0x46ea7f1498140, 0x70725690a8427, 0x0a73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc }, + { 0x525ed9ec4e5f9, 0x022d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5 }, + { 0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce }, + }, +}, +{ + { + { 0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f }, + { 0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0x0dfcefaa53320, 0x7369e6a92493a }, + { 0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4 }, + }, + { + { 0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0x0e0e9d86d24d3, 0x31e83b4161d08 }, + { 0x0bd1e249dd197, 0x00bcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a }, + { 0x0c7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550 }, + }, + { + { 0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x099dec18e71a4, 0x1a56fbaa62ba0 }, + { 0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0x0ea712017d489, 0x669a656457089 }, + { 0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58 }, + }, + { + { 0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b }, + { 0x25d465ab3e1b9, 0x0f8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b }, + { 0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd }, + }, + { + { 0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30 }, + { 0x47ff83362127d, 0x08e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0x0e645912219f7 }, + { 0x72f31d8394627, 0x07bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a }, + }, + { + { 0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950 }, + { 0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5 }, + { 0x06edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x05bff02328a11 }, + }, + { + { 0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a }, + { 0x2137023cae00b, 0x15a3599eb26c6, 0x0687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4 }, + { 0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b }, + }, + { + { 0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c }, + { 0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96 }, + { 0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb }, + }, +}, +{ + { + { 0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x058d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2 }, + { 0x42b256768d593, 0x2e88459427b4f, 0x02b3876630701, 0x34878d405eae5, 0x29cdd1adc088a }, + { 0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049 }, + }, + { + { 0x59a5fd67ff163, 0x3a998ead0352b, 0x083c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072 }, + { 0x0fd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0x0a4a26e2e2182, 0x5be8cc57092a7 }, + { 0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791 }, + }, + { + { 0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018 }, + { 0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030 }, + { 0x0172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x0728b6bfe6e91, 0x08420edd5fcdf }, + }, + { + { 0x0c34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x04d654f321db8 }, + { 0x720ab8362fa4a, 0x29c4347cdd9bf, 0x0e798ad5f8463, 0x4fef18bcb0bfe, 0x0d9a53efbc176 }, + { 0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991 }, + }, + { + { 0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e }, + { 0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31 }, + { 0x0274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc }, + }, + { + { 0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595 }, + { 0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0x0f3690d04eb8e, 0x73fcdd14b71c0 }, + { 0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0x0eb26573b10af, 0x389e740c9a9ce }, + }, + { + { 0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263 }, + { 0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6 }, + { 0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484 }, + }, + { + { 0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0x0f65320ef019b }, + { 0x21f74c3d2f773, 0x024b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1 }, + { 0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330 }, + }, +}, +{ + { + { 0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x010f93bc5fe67, 0x7ee498165acb2 }, + { 0x69624089c0a2e, 0x0075fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8 }, + { 0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0x0edf493c85b60 }, + }, + { + { 0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x04c00c54d1dfa }, + { 0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4 }, + { 0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617 }, + }, + { + { 0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a }, + { 0x664cc7493bbf4, 0x33d94761874e3, 0x0179e1796f613, 0x1890535e2867d, 0x0f9b8132182ec }, + { 0x059c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175 }, + }, + { + { 0x65d50c85066b0, 0x6167453361f7c, 0x06ba3818bb312, 0x6aff29baa7522, 0x08fea02ce8d48 }, + { 0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0x00b89b8576469 }, + { 0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d }, + }, + { + { 0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d }, + { 0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c }, + { 0x0cf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4 }, + }, + { + { 0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3 }, + { 0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813 }, + { 0x6a4d400a2509b, 0x041791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6 }, + }, + { + { 0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a }, + { 0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879 }, + { 0x0a0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e }, + }, + { + { 0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce }, + { 0x193434934d643, 0x0d4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9 }, + { 0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9 }, + }, +}, +{ + { + { 0x304bfacad8ea2, 0x502917d108b07, 0x043176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b }, + { 0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d }, + { 0x014d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd }, + }, + { + { 0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247 }, + { 0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b }, + { 0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2 }, + }, + { + { 0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4 }, + { 0x6cfab8de73e68, 0x3e6efced4bd21, 0x0056609500dbe, 0x71b7824ad85df, 0x577629c4a7f41 }, + { 0x0024509c6a888, 0x2696ab12e6644, 0x0cca27f4b80d8, 0x0c7c1f11b119e, 0x701f25bb0caec }, + }, + { + { 0x0f6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955 }, + { 0x0b0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40 }, + { 0x709439b805a35, 0x6ec48557f8187, 0x08a4d1ba13a2c, 0x076348a0bf9ae, 0x0e9b9cbb144ef }, + }, + { + { 0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3 }, + { 0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337 }, + { 0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593 }, + }, + { + { 0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed }, + { 0x39d2876f62700, 0x001cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552 }, + { 0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6 }, + }, + { + { 0x0e28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690 }, + { 0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x08fc3a4c677d5 }, + { 0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x068f1199f11fb, 0x4f2fad0116b90 }, + }, + { + { 0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e }, + { 0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef }, + { 0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289 }, + }, +}, +{ + { + { 0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4 }, + { 0x147499718289c, 0x0a48a67e4c7ab, 0x30fbc544bafe3, 0x0c701315fe58a, 0x20b878d577b75 }, + { 0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c }, + }, + { + { 0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154 }, + { 0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c }, + { 0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0x00ba739e2ae39 }, + }, + { + { 0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d }, + { 0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x03283a3e67ad7 }, + { 0x41dc7be0cb939, 0x1b16c66100904, 0x0a24c20cbc66d, 0x4a2e9efe48681, 0x05e1296846271 }, + }, + { + { 0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c }, + { 0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698 }, + { 0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x006b52076b3ff }, + }, + { + { 0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7 }, + { 0x0cfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x0912bef9ce9b8, 0x4d57e3443bc76 }, + { 0x0d4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602 }, + }, + { + { 0x3f3245bb2d80a, 0x0e5f720f36efd, 0x3b9cccf60c06d, 0x084e323f37926, 0x465812c8276c2 }, + { 0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3 }, + { 0x3beb22a1062d9, 0x6a7063b82c9a8, 0x0a5a35dc197ed, 0x3c80c06a53def, 0x05b32c2b1cb16 }, + }, + { + { 0x4a42c7ad58195, 0x5c8667e799eff, 0x02e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730 }, + { 0x05eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471 }, + { 0x0c524e14dd482, 0x283457496c656, 0x0ad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733 }, + }, + { + { 0x48b440c86c50d, 0x139929cca3b86, 0x0f8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c }, + { 0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98 }, + { 0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x006a573a83075, 0x3f8612966c870 }, + }, +}, +{ + { + { 0x0fcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1 }, + { 0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x09ebfb1432d98, 0x504aa77679736 }, + { 0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x034c2e0ad1a27, 0x4041943d9dba3 }, + }, + { + { 0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0x00ce58ea7bd01, 0x12d931429800d }, + { 0x0eeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843 }, + { 0x67799d337594f, 0x01647548f6018, 0x57fce5578f145, 0x009220c142a71, 0x1b4f92314359a }, + }, + { + { 0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2 }, + { 0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132 }, + { 0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x020c526a758f3 }, + }, + { + { 0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c }, + { 0x034f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x02aacc4615313 }, + { 0x0f7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8 }, + }, + { + { 0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3 }, + { 0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075 }, + { 0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592 }, + }, + { + { 0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614 }, + { 0x4a74cb50f9e56, 0x531d1c2640192, 0x0c03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a }, + { 0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25 }, + }, + { + { 0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d }, + { 0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce }, + { 0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1 }, + }, + { + { 0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2 }, + { 0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172 }, + { 0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d }, + }, +}, +{ + { + { 0x08d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d }, + { 0x0071b276d01c9, 0x0b0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db }, + { 0x00f1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x06e1cd13b19ea }, + }, + { + { 0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837 }, + { 0x0ad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16 }, + { 0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x03f3466bc182c, 0x30d0fded2e513 }, + }, + { + { 0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58 }, + { 0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0x0a9214202c099 }, + { 0x019c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5 }, + }, + { + { 0x08eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28 }, + { 0x031bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1 }, + { 0x5460af1cad202, 0x0b4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca }, + }, + { + { 0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4 }, + { 0x090f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d }, + { 0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf }, + }, + { + { 0x04a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018 }, + { 0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x08f338d0c85ee }, + { 0x3a821991a73bd, 0x03be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078 }, + }, + { + { 0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0x0db3e7e00cbfb }, + { 0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x05ce3a41191e6, 0x65ea753f10177 }, + { 0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0x0ed87df022109, 0x02a4ec1921e1a }, + }, + { + { 0x06162f1cf795f, 0x324ddcafe5eb9, 0x018d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067 }, + { 0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780 }, + { 0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82 }, + }, +}, +{ + { + { 0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x04af87a96e3a3, 0x57968290bb3a0 }, + { 0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a }, + { 0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa }, + }, + { + { 0x02a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x044fb81d82d50 }, + { 0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x097e37046fc77, 0x7ef72016758cc }, + { 0x718c5a907e3d9, 0x3b9c98c6b383b, 0x006ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d }, + }, + { + { 0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d }, + { 0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0x0a4e0373d784d }, + { 0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x071a7d0ace183 }, + }, + { + { 0x4355220e14431, 0x0e1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775 }, + { 0x72daac887ba0b, 0x0b7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7 }, + { 0x0d7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca }, + }, + { + { 0x1d4eba3d944be, 0x0100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x02ab9680ee8d3 }, + { 0x1000c2f41c6c5, 0x0219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a }, + { 0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b }, + }, + { + { 0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x09f20459f5168, 0x16fb869c03dd3 }, + { 0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0x0ae333f685277 }, + { 0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x03aa408fbf684, 0x3f81e38b8f70d }, + }, + { + { 0x37f355f17c824, 0x07ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0x0ad3e2d34cded }, + { 0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50 }, + { 0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1 }, + }, + { + { 0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d }, + { 0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4 }, + { 0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392 }, + }, +}, +{ + { + { 0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x0302f0cb36a3c, 0x0edc5f5eb426d }, + { 0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca }, + { 0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb }, + }, + { + { 0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122 }, + { 0x02abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x09d8eddeaa591, 0x2177bfa36dcb7 }, + { 0x01bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab }, + }, + { + { 0x17e44985bfb83, 0x54e32c626cc22, 0x096412ff38118, 0x6b241d61a246a, 0x75685abe5ba43 }, + { 0x3f6aa5344a32e, 0x69683680f11bb, 0x04c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3 }, + { 0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e }, + }, + { + { 0x716bce22e83fe, 0x33d0130b83eb8, 0x0952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a }, + { 0x0dbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3 }, + { 0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3 }, + }, + { + { 0x0443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a }, + { 0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638 }, + { 0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c }, + }, + { + { 0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x055dc39b6dea1 }, + { 0x7937ff7f927c2, 0x0c2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2 }, + { 0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2 }, + }, + { + { 0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3 }, + { 0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e }, + { 0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a }, + }, + { + { 0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x0473d308a7639 }, + { 0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e }, + { 0x6792603589e05, 0x248db9892595d, 0x006a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043 }, + }, +}, +{ + { + { 0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x096cc0f9baefa, 0x3f6bd725da4ea }, + { 0x0b9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x09edb93896d16, 0x36597d25ea5c0 }, + { 0x58d7b106058ac, 0x3cdf8d20bee69, 0x00a4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d }, + }, + { + { 0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x03bedc661bf5c }, + { 0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743 }, + { 0x0cb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0x0e7ce2b0cdf06 }, + }, + { + { 0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece }, + { 0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46 }, + { 0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d }, + }, + { + { 0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a }, + { 0x06ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0x0d1f8dbcf8eed }, + { 0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x00011b44a31bf }, + }, + { + { 0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x01308d46ebfcd, 0x63d988a2d2851 }, + { 0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835 }, + { 0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x0337c0b34d9c2, 0x33fad52b2368a }, + }, + { + { 0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0x0f151ff5b7376, 0x3cc355ccb90a7 }, + { 0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d }, + { 0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7 }, + }, + { + { 0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x05aa9b2c79399, 0x431f2c7f665f8 }, + { 0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91 }, + { 0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253 }, + }, + { + { 0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde }, + { 0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65 }, + { 0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3 }, + }, +}, +{ + { + { 0x19cd61ff38640, 0x060c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9 }, + { 0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x00311d00a9ff4, 0x2cdfdfecd5d05 }, + { 0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4 }, + }, + { + { 0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x07eb1f28bbe70, 0x03c935afc4b03 }, + { 0x65517fd181bae, 0x3e5772c76816d, 0x019189640898a, 0x1ed2a84de7499, 0x578edd74f63c1 }, + { 0x276c6492b0c3d, 0x09bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c }, + }, + { + { 0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x07aaca43cae1f, 0x62f05d7526374, 0x0e1bf66c6adba }, + { 0x0d27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc }, + { 0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88 }, + }, + { + { 0x3094ba1d6e334, 0x6e126a7e3300b, 0x089c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784 }, + { 0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db }, + { 0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9 }, + }, + { + { 0x073a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f }, + { 0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84 }, + { 0x12f5c6f136c7c, 0x0fedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f }, + }, + { + { 0x153d8f5e08181, 0x08533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f }, + { 0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3 }, + { 0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212 }, + }, + { + { 0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6 }, + { 0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38 }, + { 0x44ead1be8f7d6, 0x5759d4f31f466, 0x0378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6 }, + }, + { + { 0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x03a134ced89df, 0x7dcf843ce405f }, + { 0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f }, + { 0x0d6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271 }, + }, +}, +{ + { + { 0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7 }, + { 0x02014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x059a668f5a82e, 0x46115aba1d4dc }, + { 0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674 }, + }, + { + { 0x628d3a0a643b9, 0x01cd8640c93d2, 0x0b7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c }, + { 0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1 }, + { 0x63f06eda6e133, 0x233342758070f, 0x098e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e }, + }, + { + { 0x129126699b2e3, 0x0ee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8 }, + { 0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f }, + { 0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0x0bcd601a4e930, 0x0eafb03790e52 }, + }, + { + { 0x0805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435 }, + { 0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c }, + { 0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946 }, + }, + { + { 0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x01bd28338402c, 0x14f29a5383922 }, + { 0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754 }, + { 0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0 }, + }, + { + { 0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734 }, + { 0x3fc074571217f, 0x3a0d29b2b6aeb, 0x06478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e }, + { 0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x02522333bc2af, 0x0e34398f4a064 }, + }, + { + { 0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379 }, + { 0x522d93ecebde8, 0x024f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362 }, + { 0x0123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d }, + }, + { + { 0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58 }, + { 0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0x0eb28bf671928 }, + { 0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2 }, + }, +}, +{ + { + { 0x6f4bd567ae7a9, 0x65ac89317b783, 0x07d3b20fd8932, 0x000f208326916, 0x2ef9c5a5ba384 }, + { 0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c }, + { 0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f }, + }, + { + { 0x0918b1d61dc94, 0x0d350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0x0a738027f639d }, + { 0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7 }, + { 0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a }, + }, + { + { 0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3 }, + { 0x5318832b0ba78, 0x6f24b9ff17cec, 0x0a47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae }, + { 0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd }, + }, + { + { 0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d }, + { 0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f }, + { 0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b }, + }, + { + { 0x190b1829825d5, 0x0e7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2 }, + { 0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x04321adf49d75 }, + { 0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70 }, + }, + { + { 0x64624cfccb1ed, 0x257ab8072b6c1, 0x0120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d }, + { 0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d }, + { 0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621 }, + }, + { + { 0x18e3cc676e542, 0x26079d995a990, 0x04a7c217908b2, 0x1dc7603e6655a, 0x0dedfa10b2444 }, + { 0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615 }, + { 0x367d5b82b522a, 0x0d3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9 }, + }, + { + { 0x72836afb62874, 0x0af3c2094b240, 0x0c285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663 }, + { 0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d }, + { 0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05 }, + }, +}, +{ + { + { 0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320 }, + { 0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b }, + { 0x5fdcb41446a8e, 0x5286926ff2a71, 0x0f231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0 }, + }, + { + { 0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067 }, + { 0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed }, + { 0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d }, + }, + { + { 0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb }, + { 0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0x0a3b6063214f2, 0x5065f158c9fd2 }, + { 0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f }, + }, + { + { 0x5dfa56de66fde, 0x0058809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1 }, + { 0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x07e9d42d4a28a, 0x38dc083705acd }, + { 0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2 }, + }, + { + { 0x1fd11ed0c84a7, 0x021b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64 }, + { 0x36b15b807cba6, 0x3f78a9e1afed7, 0x0a59c2c608f1f, 0x52bdd8ecb81b7, 0x0b24f48847ed4 }, + { 0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481 }, + }, + { + { 0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x0119a3042fb37 }, + { 0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6 }, + { 0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20 }, + }, + { + { 0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x038b7ea483590 }, + { 0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x09674c6b99108 }, + { 0x6f82199316ff8, 0x05d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e }, + }, + { + { 0x4fb0e63066222, 0x130f59747e660, 0x041868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838 }, + { 0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x08f5114789a8d }, + { 0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d }, + }, +}, +{ + { + { 0x68549af3f666e, 0x09e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3 }, + { 0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x07fea2aba5132, 0x1926e1dc6401e }, + { 0x74e8aea17cea0, 0x0c743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5 }, + }, + { + { 0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0x0f2bf89f49f7e, 0x73fced18ee9a0 }, + { 0x055947d599832, 0x346fe2aa41990, 0x0164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c }, + { 0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864 }, + }, + { + { 0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0x0b76bb1b3fa7e }, + { 0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x0482c3aed35f9, 0x4e1af5271d31b }, + { 0x0c1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a }, + }, + { + { 0x0abf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6 }, + { 0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2 }, + { 0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61 }, + }, + { + { 0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30 }, + { 0x3d16733e248f3, 0x0e2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191 }, + { 0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd }, + }, + { + { 0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e }, + { 0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f }, + { 0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba }, + }, + { + { 0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x094707842cf44, 0x7dd73f960725d }, + { 0x42ddf2845ab2c, 0x6214ffd3276bb, 0x00b8d181a5246, 0x268a6d579eb20, 0x093ff26e58647 }, + { 0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x05209b3929d5a, 0x2f59bcbc86b47 }, + }, + { + { 0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082 }, + { 0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a }, + { 0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768 }, + }, +}, +{ + { + { 0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9 }, + { 0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce }, + { 0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e }, + }, + { + { 0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a }, + { 0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252 }, + { 0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459 }, + }, + { + { 0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340 }, + { 0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f }, + { 0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0x0f8893f02210c, 0x15596b3ae5710 }, + }, + { + { 0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x09c1495be913f, 0x3aa4e241afb6d }, + { 0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0x0d2237687b5f4 }, + { 0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a }, + }, + { + { 0x7a4732787ccdf, 0x11e427c7f0640, 0x03659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600 }, + { 0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6 }, + { 0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66 }, + }, + { + { 0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd }, + { 0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f }, + { 0x232cda2b4e554, 0x0422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x02c70bf52b68e }, + }, + { + { 0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43 }, + { 0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef }, + { 0x0f04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2 }, + }, + { + { 0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196 }, + { 0x7565a5cc7324f, 0x01ca0d5244a11, 0x116b067418713, 0x0a57d8c55edae, 0x6c6809c103803 }, + { 0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x05911b9f6ef7c }, + }, +}, +{ + { + { 0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2 }, + { 0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270 }, + { 0x770ba3b73bd08, 0x11475f7e186d4, 0x0251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817 }, + }, + { + { 0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3 }, + { 0x452036b1782fc, 0x02d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c }, + { 0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda }, + }, + { + { 0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b }, + { 0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db }, + { 0x2aa650dfa5ce7, 0x54916a8f19415, 0x00dc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091 }, + }, + { + { 0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a }, + { 0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x0040f3d945441 }, + { 0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254 }, + }, + { + { 0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7 }, + { 0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78 }, + { 0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c }, + }, + { + { 0x6d317e820107c, 0x090815d2ca3ca, 0x03ff1eb1499a1, 0x23960f050e319, 0x5373669c91611 }, + { 0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78 }, + { 0x014ab9a0e5257, 0x09939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87 }, + }, + { + { 0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x02f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6 }, + { 0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743 }, + { 0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1 }, + }, + { + { 0x0bc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5 }, + { 0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d }, + { 0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287 }, + }, +}, +{ + { + { 0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x087ed7e3bc55f, 0x7deb10149c726 }, + { 0x048478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a }, + { 0x2af6a8766ee7a, 0x08aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x08e68e9ff62ce }, + }, + { + { 0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71 }, + { 0x5500a4bc130ad, 0x127a17a938695, 0x02a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3 }, + { 0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2 }, + }, + { + { 0x172cdd596bdbd, 0x0731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a }, + { 0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3 }, + { 0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa }, + }, + { + { 0x55261e293eac6, 0x06426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x0760bb8d195ad }, + { 0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2 }, + { 0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac }, + }, + { + { 0x469656571f2d3, 0x0aa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x01b9c7b62e6dd }, + { 0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d }, + { 0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x08af5b784e4ba }, + }, + { + { 0x314d289cc2c4b, 0x23450e2f1bc4e, 0x0cd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98 }, + { 0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1 }, + { 0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2 }, + }, + { + { 0x14ce442ce221f, 0x18980a72516cc, 0x072f80db86677, 0x703331fda526e, 0x24b31d47691c8 }, + { 0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b }, + { 0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x04a7857b309a7, 0x545b585d14dda }, + }, + { + { 0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x038858667fead, 0x4d22dc3e64c8d }, + { 0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0x0f62f9c332ba5 }, + { 0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371 }, + }, +}, +{ + { + { 0x02b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0x0a037db9f2a62, 0x4005419b1d2bc }, + { 0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0x0fa3614f3b1ca }, + { 0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a }, + }, + { + { 0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0x0eae41ce355cc, 0x6c535d13ff776 }, + { 0x49448fac8f53e, 0x34f74c6e8356a, 0x0ad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86 }, + { 0x534e93e8a35af, 0x08b10fd02c997, 0x26ac2acb81e05, 0x09d8c98ce3b79, 0x25e17fe4d50ac }, + }, + { + { 0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698 }, + { 0x09bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb }, + { 0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7 }, + }, + { + { 0x091e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd }, + { 0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x01ab12d5807e3 }, + { 0x5189041e32d96, 0x05b062b090231, 0x0c91766e7b78f, 0x0aa0f55a138ec, 0x4a3961e2c918a }, + }, + { + { 0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x08fc1dad38b79, 0x68aceead9bd41 }, + { 0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db }, + { 0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f }, + }, + { + { 0x2cbebfd022790, 0x0b8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515 }, + { 0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0x0d49fc5e044be, 0x709fa43edcb29 }, + { 0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81 }, + }, + { + { 0x2afaa5e10b0b9, 0x61de08355254d, 0x0eb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd }, + { 0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0x0b7d5d8a6c314 }, + { 0x448327b95d543, 0x0146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de }, + }, + { + { 0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x053713fe3b7e6, 0x19735fd7f6bc2 }, + { 0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc }, + { 0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0x0fef911191df8 }, + }, +}, +}; +#else /* base[i][j] = (j+1)*256^i*B */ static const ge_precomp base[32][8] = { { @@ -2113,6 +3460,7 @@ static const ge_precomp base[32][8] = { }, }, } ; +#endif static void ge_select(ge_precomp *t,int pos,signed char b) @@ -2221,7 +3569,50 @@ static void slide(signed char *r,const unsigned char *a) } } - +#ifdef HAVE___UINT128_T +static const ge_precomp Bi[8] = { + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7 }, + { 0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9 }, + { 0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008 }, + }, + { + { 0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8 }, + { 0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c }, + { 0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df }, + }, + { + { 0x0c222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f }, + { 0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x0267882d17602 }, + { 0x0a119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097 }, + }, + { + { 0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de }, + { 0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05 }, + { 0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d }, + }, +}; +#else static const ge_precomp Bi[8] = { { { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, @@ -2264,6 +3655,7 @@ static const ge_precomp Bi[8] = { { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, }, } ; +#endif /* @@ -2272,7 +3664,7 @@ where a = a[0]+256*a[1]+...+256^31 a[31]. and b = b[0]+256*b[1]+...+256^31 b[31]. B is the Ed25519 base point (x,4/5) with x positive. */ -int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, +int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) { signed char aslide[256]; @@ -2327,17 +3719,30 @@ int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, return 0; } - +#ifdef HAVE___UINT128_T +static const fe d = { + 0x34dca135978a3, 0x1a8283b156ebd, 0x5e7a26001c029, 0x739c663a03cbb, + 0x52036cee2b6ff +}; +#else static const fe d = { -10913610,13857413,-15372611,6949391,114729, -8787816,-6275908,-3247719,-18696448,-12055116 } ; +#endif +#ifdef HAVE___UINT128_T +static const fe sqrtm1 = { + 0x61b274a0ea0b0, 0x0d5a5fc8f189d, 0x7ef5e9cbd0c60, 0x78595a6804c9e, + 0x2b8324804fc1d +}; +#else static const fe sqrtm1 = { -32595792,-7943725,9377950,3500415,12389472, -272473,-25146209,-2005654,326686,11406482 } ; +#endif int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) @@ -2516,10 +3921,17 @@ void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) r = p */ +#ifdef HAVE___UINT128_T +static const fe d2 = { + 0x69b9426b2f159, 0x35050762add7a, 0x3cf44c0038052, 0x6738cc7407977, + 0x2406d9dc56dff +}; +#else static const fe d2 = { -21827239,-5839606,-30745221,13898782,229458, 15978800,-12551817,-6495438,29715968,9444199 } ; +#endif extern void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 87d4d0fe1..58a9c2251 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -166,7 +166,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, if (hash_len < dig_size) { return BUFFER_E; } - + /* Suppress possible unused arg if all hashing is disabled */ (void)data; (void)data_len; @@ -236,41 +236,32 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_InitMd5(&hash->md5); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_InitSha(&hash->sha); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_InitSha224(&hash->sha224); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_InitSha256(&hash->sha256); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_InitSha384(&hash->sha384); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_InitSha512(&hash->sha512); - if (ret != 0) - return ret; #endif break; @@ -280,10 +271,10 @@ int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, @@ -298,41 +289,34 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Update(&hash->md5, data, dataSz); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaUpdate(&hash->sha, data, dataSz); if (ret != 0) -#endif return ret; +#endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Update(&hash->sha224, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Update(&hash->sha256, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Update(&hash->sha384, data, dataSz); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Update(&hash->sha512, data, dataSz); - if (ret != 0) - return ret; #endif break; @@ -342,10 +326,10 @@ int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) @@ -359,41 +343,32 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD5: #ifndef NO_MD5 wc_Md5Final(&hash->md5, out); + ret = 0; #endif break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA ret = wc_ShaFinal(&hash->sha, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 ret = wc_Sha224Final(&hash->sha224, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 ret = wc_Sha256Final(&hash->sha256, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 ret = wc_Sha384Final(&hash->sha384, out); - if (ret != 0) - return ret; #endif break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 ret = wc_Sha512Final(&hash->sha512, out); - if (ret != 0) - return ret; #endif break; @@ -403,92 +378,80 @@ int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) case WC_HASH_TYPE_MD4: case WC_HASH_TYPE_NONE: default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; }; - return 0; + return ret; } #if !defined(WOLFSSL_TI_HASH) #if !defined(NO_MD5) -void wc_Md5GetHash(Md5* md5, byte* hash) -{ - Md5 save = *md5 ; - wc_Md5Final(md5, hash) ; - *md5 = save ; -} + int wc_Md5Hash(const byte* data, word32 len, byte* hash) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + Md5* md5; + #else + Md5 md5[1]; + #endif -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - *m1 = *m2 ; -} + #ifdef WOLFSSL_SMALL_STACK + md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; + #endif -#endif + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_Md5Update(md5, data, len); + if (ret == 0) { + ret = wc_Md5Final(md5, hash); + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -int wc_ShaGetHash(Sha* sha, byte* hash) -{ - int ret ; - Sha save = *sha ; - ret = wc_ShaFinal(sha, hash) ; - *sha = save ; - return ret ; -} + int wc_ShaHash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha* sha; + #else + Sha sha[1]; + #endif -void wc_ShaRestorePos(Sha* s1, Sha* s2) { - *s1 = *s2 ; -} + #ifdef WOLFSSL_SMALL_STACK + sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; + #endif -int wc_ShaHash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha* sha; -#else - Sha sha[1]; -#endif + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("wc_InitSha failed"); + } + else { + wc_ShaUpdate(sha, data, len); + wc_ShaFinal(sha, hash); + } -#ifdef WOLFSSL_SMALL_STACK - sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha == NULL) - return MEMORY_E; -#endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - if ((ret = wc_InitSha(sha)) != 0) { - WOLFSSL_MSG("wc_InitSha failed"); + return ret; } - else { - wc_ShaUpdate(sha, data, len); - wc_ShaFinal(sha, hash); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; - -} - -#endif /* !defined(NO_SHA) */ +#endif /* !NO_SHA */ #if defined(WOLFSSL_SHA224) -int wc_Sha224GetHash(Sha224* sha224, byte* hash) -{ - int ret; - Sha224 save; - - if (sha224 == NULL || hash == NULL) - return BAD_FUNC_ARG; - - save= *sha224; - ret = wc_Sha224Final(sha224, hash); - *sha224 = save; - - return ret; -} - int wc_Sha224Hash(const byte* data, word32 len, byte* hash) { int ret = 0; @@ -520,154 +483,109 @@ int wc_Sha224Hash(const byte* data, word32 len, byte* hash) return ret; } - -#endif /* defined(WOLFSSL_SHA224) */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -int wc_Sha256GetHash(Sha256* sha256, byte* hash) -{ - int ret ; - Sha256 save = *sha256 ; - ret = wc_Sha256Final(sha256, hash) ; - *sha256 = save ; - return ret ; -} + int wc_Sha256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha256* sha256; + #else + Sha256 sha256[1]; + #endif -void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - *s1 = *s2 ; -} + #ifdef WOLFSSL_SMALL_STACK + sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; + #endif -int wc_Sha256Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha256* sha256; -#else - Sha256 sha256[1]; -#endif + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } -#ifdef WOLFSSL_SMALL_STACK - sha256 = (Sha256*)XMALLOC(sizeof(Sha256), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha256 == NULL) - return MEMORY_E; -#endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - if ((ret = wc_InitSha256(sha256)) != 0) { - WOLFSSL_MSG("InitSha256 failed"); + return ret; } - else if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { - WOLFSSL_MSG("Sha256Update failed"); - } - else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { - WOLFSSL_MSG("Sha256Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#endif /* !defined(NO_SHA256) */ +#endif /* !NO_SHA256 */ #endif /* !defined(WOLFSSL_TI_HASH) */ + #if defined(WOLFSSL_SHA512) -int wc_Sha512GetHash(Sha512* sha512, byte* hash) -{ - int ret; - Sha512 save; + int wc_Sha512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha512* sha512; + #else + Sha512 sha512[1]; + #endif - if (sha512 == NULL || hash == NULL) - return BAD_FUNC_ARG; + #ifdef WOLFSSL_SMALL_STACK + sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL) + return MEMORY_E; + #endif - save= *sha512; - ret = wc_Sha512Final(sha512, hash); - *sha512 = save; + if ((ret = wc_InitSha512(sha512)) != 0) { + WOLFSSL_MSG("InitSha512 failed"); + } + else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { + WOLFSSL_MSG("Sha512Update failed"); + } + else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { + WOLFSSL_MSG("Sha512Final failed"); + } - return ret; -} + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif -int wc_Sha512Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha512* sha512; -#else - Sha512 sha512[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha512 = (Sha512*)XMALLOC(sizeof(Sha512), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha512 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha512(sha512)) != 0) { - WOLFSSL_MSG("InitSha512 failed"); - } - else if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { - WOLFSSL_MSG("Sha512Update failed"); - } - else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { - WOLFSSL_MSG("Sha512Final failed"); + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif + #if defined(WOLFSSL_SHA384) + int wc_Sha384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + Sha384* sha384; + #else + Sha384 sha384[1]; + #endif - return ret; -} + #ifdef WOLFSSL_SMALL_STACK + sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) + return MEMORY_E; + #endif -#if defined(WOLFSSL_SHA384) -int wc_Sha384GetHash(Sha384* sha384, byte* hash) -{ - int ret; - Sha384 save; + if ((ret = wc_InitSha384(sha384)) != 0) { + WOLFSSL_MSG("InitSha384 failed"); + } + else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { + WOLFSSL_MSG("Sha384Update failed"); + } + else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { + WOLFSSL_MSG("Sha384Final failed"); + } - if (sha384 == NULL || hash == NULL) - return BAD_FUNC_ARG; + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif - save= *sha384; - ret = wc_Sha384Final(sha384, hash); - *sha384 = save; - - return ret; -} - -int wc_Sha384Hash(const byte* data, word32 len, byte* hash) -{ - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - Sha384* sha384; -#else - Sha384 sha384[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - sha384 = (Sha384*)XMALLOC(sizeof(Sha384), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (sha384 == NULL) - return MEMORY_E; -#endif - - if ((ret = wc_InitSha384(sha384)) != 0) { - WOLFSSL_MSG("InitSha384 failed"); - } - else if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { - WOLFSSL_MSG("Sha384Update failed"); - } - else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { - WOLFSSL_MSG("Sha384Final failed"); - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret; -} - -#endif /* defined(WOLFSSL_SHA384) */ -#endif /* defined(WOLFSSL_SHA512) */ + return ret; + } + #endif /* WOLFSSL_SHA384 */ +#endif /* WOLFSSL_SHA512 */ diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c old mode 100644 new mode 100755 index a699b6542..0dc745361 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -30,83 +30,87 @@ #include -#ifdef HAVE_FIPS -/* does init */ -int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) -{ - return HmacSetKey_fips(hmac, type, key, keySz); -} - - -int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) -{ - return HmacUpdate_fips(hmac, in, sz); -} - - -int wc_HmacFinal(Hmac* hmac, byte* out) -{ - return HmacFinal_fips(hmac, out); -} - - -#ifdef WOLFSSL_ASYNC_CRYPT - int wc_HmacAsyncInit(Hmac* hmac, int i) - { - return HmacAsyncInit(hmac, i); - } - - - void wc_HmacAsyncFree(Hmac* hmac) - { - HmacAsyncFree(hmac); - } +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include #endif -int wolfSSL_GetHmacMaxSize(void) -{ - return CyaSSL_GetHmacMaxSize(); -} -#ifdef HAVE_HKDF +/* fips wrapper calls, user can call direct */ +#ifdef HAVE_FIPS + /* does init */ + int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) + { + return HmacSetKey_fips(hmac, type, key, keySz); + } + int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) + { + return HmacUpdate_fips(hmac, in, sz); + } + int wc_HmacFinal(Hmac* hmac, byte* out) + { + return HmacFinal_fips(hmac, out); + } + int wolfSSL_GetHmacMaxSize(void) + { + return CyaSSL_GetHmacMaxSize(); + } -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + int wc_HmacInit(Hmac* hmac, void* heap, int devId) + { + (void)hmac; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return HmacInit(hmac, heap, devId); */ + return 0; + } + void wc_HmacFree(Hmac* hmac) + { + (void)hmac; + /* FIPS doesn't support: + HmacFree(hmac); */ + } + + #ifdef HAVE_HKDF + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, const byte* salt, word32 saltSz, const byte* info, word32 infoSz, byte* out, word32 outSz) -{ - return HKDF(type, inKey, inKeySz, salt, saltSz, info, infoSz, out, outSz); -} + { + return HKDF(type, inKey, inKeySz, salt, saltSz, + info, infoSz, out, outSz); + } + #endif /* HAVE_HKDF */ - -#endif /* HAVE_HKDF */ #else /* else build without fips */ -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw - -#define wc_InitSha wc_InitSha_sw -#define wc_ShaUpdate wc_ShaUpdate_sw -#define wc_ShaFinal wc_ShaFinal_sw - -#define wc_InitSha256 wc_InitSha256_sw -#define wc_Sha256Update wc_Sha256Update_sw -#define wc_Sha256Final wc_Sha256Final_sw - -#endif - -#ifdef HAVE_FIPS - /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ - #define FIPS_NO_WRAPPERS -#endif #include +#ifdef WOLFSSL_PIC32MZ_HASH + #define wc_InitMd5 wc_InitMd5_sw + #define wc_Md5Update wc_Md5Update_sw + #define wc_Md5Final wc_Md5Final_sw + + #define wc_InitSha wc_InitSha_sw + #define wc_ShaUpdate wc_ShaUpdate_sw + #define wc_ShaFinal wc_ShaFinal_sw + + #define wc_InitSha256 wc_InitSha256_sw + #define wc_Sha256Update wc_Sha256Update_sw + #define wc_Sha256Final wc_Sha256Final_sw +#endif /* WOLFSSL_PIC32MZ_HASH */ + + + int wc_HmacSizeByType(int type) { + int ret; + if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 || type == SHA512 || type == BLAKE2B_ID || type == SHA224)) { @@ -116,121 +120,151 @@ int wc_HmacSizeByType(int type) switch (type) { #ifndef NO_MD5 case MD5: - return MD5_DIGEST_SIZE; - #endif + ret = MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ #ifndef NO_SHA case SHA: - return SHA_DIGEST_SIZE; - #endif + ret = SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ - #ifdef WOLF_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: - return SHA224_DIGEST_SIZE; - #endif + ret = SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ #ifndef NO_SHA256 case SHA256: - return SHA256_DIGEST_SIZE; - #endif - - #ifdef WOLFSSL_SHA384 - case SHA384: - return SHA384_DIGEST_SIZE; - #endif + ret = SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case SHA384: + ret = SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - return SHA512_DIGEST_SIZE; - #endif + ret = SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - return BLAKE2B_OUTBYTES; - #endif + ret = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + + return ret; } -static int InitHmac(Hmac* hmac, int type) +static int _InitHmac(Hmac* hmac, int type, void* heap) { int ret = 0; - hmac->innerHashKeyed = 0; - hmac->macType = (byte)type; - - if (!(type == MD5 || type == SHA || type == SHA256 || type == SHA384 - || type == SHA512 || type == BLAKE2B_ID - || type == SHA224)) - return BAD_FUNC_ARG; - switch (type) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_InitMd5(&hmac->hash.md5); - break; - #endif + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: ret = wc_InitSha(&hmac->hash.sha); - break; - #endif + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: ret = wc_InitSha224(&hmac->hash.sha224); - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: ret = wc_InitSha256(&hmac->hash.sha256); - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: ret = wc_InitSha384(&hmac->hash.sha384); - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: ret = wc_InitSha512(&hmac->hash.sha512); - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - return BAD_FUNC_ARG; + ret = BAD_FUNC_ARG; + break; } + /* default to NULL heap hint or test value */ +#ifdef WOLFSSL_HEAP_TEST + hmac->heap = (void)WOLFSSL_HEAP_TEST; +#else + hmac->heap = heap; +#endif /* WOLFSSL_HEAP_TEST */ + return ret; } int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) { - byte* ip = (byte*) hmac->ipad; - byte* op = (byte*) hmac->opad; + byte* ip; + byte* op; word32 i, hmac_block_size = 0; - int ret; + int ret = 0; + void* heap = NULL; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) - if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacSetKey(hmac, type, key, length); + if (hmac == NULL || (key == NULL && length != 0) || + !(type == MD5 || type == SHA || type == SHA256 || type == SHA384 + || type == SHA512 || type == BLAKE2B_ID + || type == SHA224)) { + return BAD_FUNC_ARG; } -#endif - ret = InitHmac(hmac, type); + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) || defined(HAVE_INTEL_QA) + if (length > HMAC_BLOCK_SIZE) { + return WC_KEY_SIZE_E; + } + + if (key != NULL) { + XMEMCPY(hmac->keyRaw, key, length); + } + hmac->keyLen = (word16)length; + + return 0; /* nothing to do here */ + #endif /* HAVE_CAVIUM || HAVE_INTEL_QA */ + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = _InitHmac(hmac, type, heap); if (ret != 0) return ret; @@ -239,160 +273,172 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) return HMAC_MIN_KEYLEN_E; #endif + ip = (byte*)hmac->ipad; + op = (byte*)hmac->opad; + switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - { hmac_block_size = MD5_BLOCK_SIZE; if (length <= MD5_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_Md5Update(&hmac->hash.md5, key, length); - wc_Md5Final(&hmac->hash.md5, ip); + ret = wc_Md5Update(&hmac->hash.md5, key, length); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, ip); + if (ret != 0) + break; length = MD5_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - { hmac_block_size = SHA_BLOCK_SIZE; if (length <= SHA_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { - wc_ShaUpdate(&hmac->hash.sha, key, length); - wc_ShaFinal(&hmac->hash.sha, ip); + ret = wc_ShaUpdate(&hmac->hash.sha, key, length); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, ip); + if (ret != 0) + break; + length = SHA_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: { hmac_block_size = SHA224_BLOCK_SIZE; if (length <= SHA224_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha224Update(&hmac->hash.sha224, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha224Final(&hmac->hash.sha224, ip); if (ret != 0) - return ret; + break; length = SHA224_DIGEST_SIZE; } } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - { hmac_block_size = SHA256_BLOCK_SIZE; if (length <= SHA256_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha256Update(&hmac->hash.sha256, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, ip); if (ret != 0) - return ret; + break; length = SHA256_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - { hmac_block_size = SHA384_BLOCK_SIZE; if (length <= SHA384_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha384Update(&hmac->hash.sha384, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, ip); if (ret != 0) - return ret; + break; length = SHA384_DIGEST_SIZE; } - } - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - { hmac_block_size = SHA512_BLOCK_SIZE; if (length <= SHA512_BLOCK_SIZE) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Sha512Update(&hmac->hash.sha512, key, length); if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, ip); if (ret != 0) - return ret; + break; length = SHA512_DIGEST_SIZE; } - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { hmac_block_size = BLAKE2B_BLOCKBYTES; if (length <= BLAKE2B_BLOCKBYTES) { - XMEMCPY(ip, key, length); + if (key != NULL) { + XMEMCPY(ip, key, length); + } } else { ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); if (ret != 0) - return ret; + break; length = BLAKE2B_256; } - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: return BAD_FUNC_ARG; } - if (length < hmac_block_size) - XMEMSET(ip + length, 0, hmac_block_size - length); - for(i = 0; i < hmac_block_size; i++) { - op[i] = ip[i] ^ OPAD; - ip[i] ^= IPAD; + if (ret == 0) { + if (length < hmac_block_size) + XMEMSET(ip + length, 0, hmac_block_size - length); + + for(i = 0; i < hmac_block_size; i++) { + op[i] = ip[i] ^ OPAD; + ip[i] ^= IPAD; + } } - return 0; + + return ret; } @@ -401,68 +447,60 @@ static int HmacKeyInnerHash(Hmac* hmac) int ret = 0; switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->ipad, MD5_BLOCK_SIZE); - break; - #endif + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad, + MD5_BLOCK_SIZE); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->ipad, SHA_BLOCK_SIZE); - break; - #endif + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad, + SHA_BLOCK_SIZE); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->ipad, SHA224_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad, + SHA224_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->ipad, SHA256_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad, + SHA256_BLOCK_SIZE); + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->ipad, SHA384_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif - - #ifdef WOLFSSL_SHA512 + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad, + SHA384_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->ipad, SHA512_BLOCK_SIZE); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad, + SHA512_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); - if (ret != 0) - return ret; - break; - #endif + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad, + BLAKE2B_BLOCKBYTES); + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - hmac->innerHashKeyed = 1; + if (ret == 0) + hmac->innerHashKeyed = 1; return ret; } @@ -470,13 +508,18 @@ static int HmacKeyInnerHash(Hmac* hmac) int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) { - int ret; + int ret = 0; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) return NitroxHmacUpdate(hmac, msg, length); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + hmac->keyRaw, hmac->keyLen, NULL, msg, length); + #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -485,63 +528,52 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) } switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - wc_Md5Update(&hmac->hash.md5, msg, length); - break; - #endif + ret = wc_Md5Update(&hmac->hash.md5, msg, length); + break; + #endif /* !NO_MD5 */ - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - wc_ShaUpdate(&hmac->hash.sha, msg, length); - break; - #endif + ret = wc_ShaUpdate(&hmac->hash.sha, msg, length); + break; + #endif /* !NO_SHA */ - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: ret = wc_Sha224Update(&hmac->hash.sha224, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: ret = wc_Sha256Update(&hmac->hash.sha256, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: ret = wc_Sha384Update(&hmac->hash.sha384, msg, length); - if (ret != 0) - return ret; - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: ret = wc_Sha512Update(&hmac->hash.sha512, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); - if (ret != 0) - return ret; - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + break; } - return 0; + return ret; } @@ -549,11 +581,20 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) { int ret; -#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM) +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { - return NitroxHmacFinal(hmac, hash); + int hashLen = wc_HmacSizeByType(hmac->macType); + if (hashLen <= 0) + return hashLen; + + #if defined(HAVE_CAVIUM) + return NitroxHmacFinal(hmac, hmac->macType, hash, hashLen); + #elif defined(HAVE_INTEL_QA) + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + hmac->keyRaw, hmac->keyLen, hash, NULL, hashLen); + #endif } -#endif +#endif /* WOLFSSL_ASYNC_CRYPT */ if (!hmac->innerHashKeyed) { ret = HmacKeyInnerHash(hmac); @@ -562,216 +603,184 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) } switch (hmac->macType) { - #ifndef NO_MD5 + #ifndef NO_MD5 case MD5: - { - wc_Md5Final(&hmac->hash.md5, (byte*) hmac->innerHash); + ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad, + MD5_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash, + MD5_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, hash); + break; + #endif /* !NO_MD5 */ - wc_Md5Update(&hmac->hash.md5, (byte*) hmac->opad, MD5_BLOCK_SIZE); - wc_Md5Update(&hmac->hash.md5, - (byte*) hmac->innerHash, MD5_DIGEST_SIZE); - - wc_Md5Final(&hmac->hash.md5, hash); - } - break; - #endif - - #ifndef NO_SHA + #ifndef NO_SHA case SHA: - { - wc_ShaFinal(&hmac->hash.sha, (byte*) hmac->innerHash); + ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad, + SHA_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash, + SHA_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ - wc_ShaUpdate(&hmac->hash.sha, (byte*) hmac->opad, SHA_BLOCK_SIZE); - wc_ShaUpdate(&hmac->hash.sha, - (byte*) hmac->innerHash, SHA_DIGEST_SIZE); - - wc_ShaFinal(&hmac->hash.sha, hash); - } - break; - #endif - - #ifdef WOLFSSL_SHA224 + #ifdef WOLFSSL_SHA224 case SHA224: { - ret = wc_Sha224Final(&hmac->hash.sha224, (byte*) hmac->innerHash); + ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->opad, SHA224_BLOCK_SIZE); + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad, + SHA224_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha224Update(&hmac->hash.sha224, - (byte*) hmac->innerHash, SHA224_DIGEST_SIZE); + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash, + SHA224_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha224Final(&hmac->hash.sha224, hash); if (ret != 0) - return ret; + break; } break; - #endif + #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 + #ifndef NO_SHA256 case SHA256: - { - ret = wc_Sha256Final(&hmac->hash.sha256, (byte*) hmac->innerHash); + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->opad, SHA256_BLOCK_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, + SHA256_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*) hmac->innerHash, SHA256_DIGEST_SIZE); + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash, + SHA256_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha256Final(&hmac->hash.sha256, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA384 + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 case SHA384: - { - ret = wc_Sha384Final(&hmac->hash.sha384, (byte*) hmac->innerHash); + ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->opad, SHA384_BLOCK_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad, + SHA384_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*) hmac->innerHash, SHA384_DIGEST_SIZE); + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash, + SHA384_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha384Final(&hmac->hash.sha384, hash); - if (ret != 0) - return ret; - } - break; - #endif - - #ifdef WOLFSSL_SHA512 + break; + #endif /* WOLFSSL_SHA384 */ case SHA512: - { - ret = wc_Sha512Final(&hmac->hash.sha512, (byte*) hmac->innerHash); + ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->opad, SHA512_BLOCK_SIZE); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad, + SHA512_BLOCK_SIZE); if (ret != 0) - return ret; - - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*) hmac->innerHash, SHA512_DIGEST_SIZE); + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash, + SHA512_DIGEST_SIZE); if (ret != 0) - return ret; - + break; ret = wc_Sha512Final(&hmac->hash.sha512, hash); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* WOLFSSL_SHA512 */ - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: - { - ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, - BLAKE2B_256); + ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->opad, BLAKE2B_BLOCKBYTES); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad, + BLAKE2B_BLOCKBYTES); if (ret != 0) - return ret; - - ret = wc_Blake2bUpdate(&hmac->hash.blake2b, - (byte*) hmac->innerHash, BLAKE2B_256); + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); if (ret != 0) - return ret; - + break; ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); - if (ret != 0) - return ret; - } - break; - #endif + break; + #endif /* HAVE_BLAKE2 */ default: - break; + ret = BAD_FUNC_ARG; + break; } - hmac->innerHashKeyed = 0; + if (ret == 0) { + hmac->innerHashKeyed = 0; + } - return 0; + return ret; } -#ifdef WOLFSSL_ASYNC_CRYPT - -/* Initialize Hmac for use with Nitrox device */ -int wc_HmacAsyncInit(Hmac* hmac, int devId) +/* Initialize Hmac for use with async device */ +int wc_HmacInit(Hmac* hmac, void* heap, int devId) { int ret = 0; if (hmac == NULL) - return -1; + return BAD_FUNC_ARG; - ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, devId); - if (ret != 0) { - return ret; - } + XMEMSET(hmac, 0, sizeof(Hmac)); + hmac->heap = heap; -#ifdef HAVE_CAVIUM - hmac->keyLen = 0; - hmac->dataLen = 0; - hmac->type = 0; - hmac->data = NULL; /* buffered input data */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + hmac->keyLen = 0; + #ifdef HAVE_CAVIUM + hmac->dataLen = 0; + hmac->data = NULL; /* buffered input data */ + #endif /* HAVE_CAVIUM */ - hmac->innerHashKeyed = 0; -#endif /* HAVE_CAVIUM */ - - /* default to NULL heap hint or test value */ -#ifdef WOLFSSL_HEAP_TEST - hmac->heap = (void)WOLFSSL_HEAP_TEST; + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, + hmac->heap, devId); #else - hmac->heap = NULL; -#endif /* WOLFSSL_HEAP_TEST */ + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ - return 0; + return ret; } - -/* Free Hmac from use with Nitrox device */ -void wc_HmacAsyncFree(Hmac* hmac) +/* Free Hmac from use with async device */ +void wc_HmacFree(Hmac* hmac) { if (hmac == NULL) return; - wolfAsync_DevCtxFree(&hmac->asyncDev); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC); #ifdef HAVE_CAVIUM - XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_ASYNC_TMP); + XFREE(hmac->data, hmac->heap, DYNAMIC_TYPE_HMAC); hmac->data = NULL; -#endif -} - +#endif /* HAVE_CAVIUM */ #endif /* WOLFSSL_ASYNC_CRYPT */ - +} int wolfSSL_GetHmacMaxSize(void) { @@ -779,76 +788,73 @@ int wolfSSL_GetHmacMaxSize(void) } #ifdef HAVE_HKDF - -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + /* HMAC-KDF-Extract. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * salt The optional salt value. + * saltSz The size of the salt. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * out The pseudorandom key with the length that of the hash. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out) { - return a > b ? b : a; + byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper */ + Hmac myHmac; + int ret; + const byte* localSalt; /* either points to user input or tmp */ + int hashSz; + + ret = wc_HmacSizeByType(type); + if (ret < 0) + return ret; + + hashSz = ret; + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } + + ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret == 0) + ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + if (ret == 0) + ret = wc_HmacFinal(&myHmac, out); + + return ret; } -#endif /* WOLFSSL_HAVE_MIN */ + /* HMAC-KDF-Expand. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input key. + * inKeySz The size of the input key. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, byte* out, word32 outSz) + { + byte tmp[MAX_DIGEST_SIZE]; + Hmac myHmac; + int ret = 0; + word32 outIdx = 0; + word32 hashSz = wc_HmacSizeByType(type); + byte n = 0x1; - -/* HMAC-KDF with hash type, optional salt and info, return 0 on success */ -int wc_HKDF(int type, const byte* inKey, word32 inKeySz, - const byte* salt, word32 saltSz, - const byte* info, word32 infoSz, - byte* out, word32 outSz) -{ - Hmac myHmac; -#ifdef WOLFSSL_SMALL_STACK - byte* tmp; - byte* prk; -#else - byte tmp[MAX_DIGEST_SIZE]; /* localSalt helper and T */ - byte prk[MAX_DIGEST_SIZE]; -#endif - const byte* localSalt; /* either points to user input or tmp */ - int hashSz = wc_HmacSizeByType(type); - word32 outIdx = 0; - byte n = 0x1; - int ret; - - if (hashSz < 0) - return BAD_FUNC_ARG; - -#ifdef WOLFSSL_SMALL_STACK - tmp = (byte*)XMALLOC(MAX_DIGEST_SIZE, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) - return MEMORY_E; - - prk = (byte*)XMALLOC(MAX_DIGEST_SIZE, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - if (prk == NULL) { - XFREE(tmp, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - localSalt = salt; - if (localSalt == NULL) { - XMEMSET(tmp, 0, hashSz); - localSalt = tmp; - saltSz = hashSz; - } - - do { - ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); - if (ret != 0) - break; - ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); - if (ret != 0) - break; - ret = wc_HmacFinal(&myHmac, prk); - } while (0); - - if (ret == 0) { while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; - ret = wc_HmacSetKey(&myHmac, type, prk, hashSz); + ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); if (ret != 0) break; ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); @@ -864,21 +870,47 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, if (ret != 0) break; - left = min(left, (word32)hashSz); + left = min(left, hashSz); XMEMCPY(out+outIdx, tmp, left); outIdx += hashSz; n++; } + + return ret; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmp, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(prk, myHmac.heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif + /* HMAC-KDF. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * salt The optional salt value. + * saltSz The size of the salt. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) + { + byte prk[MAX_DIGEST_SIZE]; + int hashSz = wc_HmacSizeByType(type); + int ret; - return ret; -} + if (hashSz < 0) + return BAD_FUNC_ARG; + + ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk); + if (ret != 0) + return ret; + + return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz); + } #endif /* HAVE_HKDF */ diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 714d5d434..3b895934b 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -1,7 +1,9 @@ # vim:ft=automake # All paths should be given relative to the root +EXTRA_DIST += src/bio.c EXTRA_DIST += wolfcrypt/src/misc.c +EXTRA_DIST += wolfcrypt/src/evp.c EXTRA_DIST += wolfcrypt/src/asm.c EXTRA_DIST += wolfcrypt/src/aes_asm.asm @@ -37,7 +39,8 @@ EXTRA_DIST += \ wolfcrypt/src/fp_sqr_comba_7.i \ wolfcrypt/src/fp_sqr_comba_8.i \ wolfcrypt/src/fp_sqr_comba_9.i \ - wolfcrypt/src/fp_sqr_comba_small_set.i + wolfcrypt/src/fp_sqr_comba_small_set.i \ + wolfcrypt/src/fe_x25519_128.i EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ wolfcrypt/src/port/ti/ti-des3.c \ @@ -56,3 +59,10 @@ src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c EXTRA_DIST += wolfcrypt/src/port/cavium/README.md endif + +if BUILD_INTEL_QA +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_mem.c + +EXTRA_DIST += wolfcrypt/src/port/intel/README.md +endif diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 7e0c59820..c91d8331a 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -47,6 +47,9 @@ #include +#if defined(FREESCALE_LTC_TFM) + #include +#endif #ifdef WOLFSSL_DEBUG_MATH #include #endif @@ -142,29 +145,21 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, /* init a new mp_int */ int mp_init (mp_int * a) { - int i; - /* Safeguard against passing in a null pointer */ if (a == NULL) return MP_VAL; - /* allocate memory required and clear it */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC, 0, - DYNAMIC_TYPE_BIGINT); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the digits to zero */ - for (i = 0; i < MP_PREC; i++) { - a->dp[i] = 0; - } + /* defer allocation until mp_grow */ + a->dp = NULL; /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; - a->alloc = MP_PREC; + a->alloc = 0; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif return MP_OKAY; } @@ -186,15 +181,28 @@ void mp_clear (mp_int * a) } /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } +void mp_free (mp_int * a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + a->dp = NULL; + } + +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#endif +} + void mp_forcezero(mp_int * a) { if (a == NULL) @@ -206,10 +214,9 @@ void mp_forcezero(mp_int * a) ForceZero(a->dp, a->used * sizeof(mp_digit)); /* free ram */ - XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + mp_free(a); /* reset members to make debugging easier */ - a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } @@ -272,6 +279,22 @@ int mp_leading_bit (mp_int * a) return bit; } +int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b) +{ + int res = 0; + while (mp_iszero(t) == MP_NO) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t->dp[0] & 255); +#else + b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) { + return res; + } + res = x; + } + return res; +} /* store in unsigned [big endian] format */ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) @@ -283,21 +306,15 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) return res; } - x = 0; - while (mp_iszero (&t) == MP_NO) { -#ifndef MP_8BIT - b[x++] = (unsigned char) (t.dp[0] & 255); -#else - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); -#endif - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } + x = mp_to_unsigned_bin_at_pos(0, &t, b); + if (x < 0) { + mp_clear(&t); + return x; } + bn_reverse (b, x); mp_clear (&t); - return MP_OKAY; + return res; } @@ -328,7 +345,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* grow dest */ - if (b->alloc < a->used) { + if (b->alloc < a->used || b->alloc == 0) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } @@ -352,7 +369,7 @@ int mp_copy (mp_int * a, mp_int * b) } /* clear high digits */ - for (; n < b->used; n++) { + for (; n < b->used && b->dp; n++) { *tmpb++ = 0; } } @@ -371,7 +388,7 @@ int mp_grow (mp_int * a, int size) mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { + if (a->alloc < size || size == 0) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); @@ -381,8 +398,8 @@ int mp_grow (mp_int * a, int size) * in case the operation failed we don't want * to overwrite the dp member of a. */ - tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, 0, - DYNAMIC_TYPE_BIGINT); + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL, + DYNAMIC_TYPE_BIGINT); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; @@ -467,6 +484,9 @@ void mp_zero (mp_int * a) a->sign = MP_ZPOS; a->used = 0; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif tmp = a->dp; for (n = 0; n < a->alloc; n++) { @@ -540,6 +560,7 @@ void mp_rshb (mp_int *c, int x) /* set the carry to the carry bits of the current word found above */ r = rr; } + mp_clamp(c); } @@ -781,7 +802,11 @@ int mp_lshd (mp_int * a, int b) * embedded in the normal function but that wasted a lot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif { int dr; @@ -892,7 +917,11 @@ int mp_abs (mp_int * a, mp_int * b) /* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif { /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { @@ -950,7 +979,9 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&D, 1); + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1104,8 +1135,12 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } - mp_set (&A, 1); - mp_set (&D, 1); + if ((res = mp_set (&A, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } top: /* 4. while u is even do */ @@ -1288,8 +1323,12 @@ int mp_cmp (mp_int * a, mp_int * b) /* compare a digit */ int mp_cmp_d(mp_int * a, mp_digit b) { + /* special case for zero*/ + if (a->used == 0 && b == 0) + return MP_EQ; + /* compare based on sign */ - if (a->sign == MP_NEG) { + if ((b && a->used == 0) || a->sign == MP_NEG) { return MP_LT; } @@ -1310,11 +1349,16 @@ int mp_cmp_d(mp_int * a, mp_digit b) /* set to a digit */ -void mp_set (mp_int * a, mp_digit b) +int mp_set (mp_int * a, mp_digit b) { + int res; mp_zero (a); - a->dp[0] = (mp_digit)(b & MP_MASK); - a->used = (a->dp[0] != 0) ? 1 : 0; + res = mp_grow (a, 1); + if (res == MP_OKAY) { + a->dp[0] = (mp_digit)(b & MP_MASK); + a->used = (a->dp[0] != 0) ? 1 : 0; + } + return res; } /* chek if a bit is set */ @@ -1327,7 +1371,11 @@ int mp_is_bit_set (mp_int *a, mp_digit b) } /* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c) +#else int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif { mp_int t; int res; @@ -1382,8 +1430,9 @@ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) return res; } - - mp_set(&tq, 1); + if ((res = mp_set(&tq, 1)) != MP_OKAY) { + return res; + } n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || @@ -1509,31 +1558,31 @@ int mp_add (mp_int * a, mp_int * b, mp_int * c) int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; - int olduse, res, min, max; + int olduse, res, min_ab, max_ab; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { - min = b->used; - max = a->used; + min_ab = b->used; + max_ab = a->used; x = a; } else { - min = a->used; - max = b->used; + min_ab = a->used; + max_ab = b->used; x = b; } /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + if (c->alloc < max_ab + 1) { + if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; - c->used = max + 1; + c->used = max_ab + 1; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1552,7 +1601,7 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* zero the carry */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_ab; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; @@ -1566,8 +1615,8 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ - if (min != max) { - for (; i < max; i++) { + if (min_ab != max_ab) { + for (; i < max_ab; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; @@ -1596,20 +1645,25 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { - int olduse, res, min, max; + int olduse, res, min_b, max_a; /* find sizes */ - min = b->used; - max = a->used; + min_b = b->used; + max_a = a->used; /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { + if (c->alloc < max_a) { + if ((res = mp_grow (c, max_a)) != MP_OKAY) { return res; } } + + /* sanity check on destination */ + if (c->dp == NULL) + return MP_VAL; + olduse = c->used; - c->used = max; + c->used = max_a; { mp_digit u, *tmpa, *tmpb, *tmpc; @@ -1622,7 +1676,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* set carry to zero */ u = 0; - for (i = 0; i < min; i++) { + for (i = 0; i < min_b; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; @@ -1638,7 +1692,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) } /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { + for (; i < max_a; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; @@ -1941,7 +1995,9 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, goto LBL_RES; } } else { - mp_set(&res, 1); + if ((err = mp_set(&res, 1)) != MP_OKAY) { + goto LBL_RES; + } if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } @@ -2169,7 +2225,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } #ifdef WOLFSSL_SMALL_STACK - W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -2296,7 +2352,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) mp_clamp (x); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif /* if A >= m then A = A - m */ @@ -2647,7 +2703,11 @@ int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) /* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +#else int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif { int res; mp_int t; @@ -2732,7 +2792,11 @@ int mp_sqr (mp_int * a, mp_int * b) /* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c) +#else int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; @@ -2893,7 +2957,7 @@ int mp_init_size (mp_int * a, int size) size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ - a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, 0, + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL, DYNAMIC_TYPE_BIGINT); if (a->dp == NULL) { return MP_MEM; @@ -2903,6 +2967,9 @@ int mp_init_size (mp_int * a, int size) a->used = 0; a->alloc = size; a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif /* zero the digits */ for (x = 0; x < size; x++) { @@ -2946,7 +3013,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3019,7 +3086,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) mp_clamp (b); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3065,7 +3132,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3123,7 +3190,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; @@ -3283,7 +3350,9 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) return res; } } else { - mp_set(a, 1); + if ((res = mp_set(a, 1)) != MP_OKAY) { + return res; + } bits = 1; } @@ -3422,7 +3491,9 @@ int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_MU; } - mp_set (&res, 1); + if ((err = mp_set (&res, 1)) != MP_OKAY) { + goto LBL_MU; + } /* set initial mode and bit cnt */ mode = 0; @@ -3609,7 +3680,8 @@ int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) /* If x < 0, add b**(k+1) to it */ if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); + if ((res = mp_set (&q, 1)) != MP_OKAY) + goto CLEANUP; if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) goto CLEANUP; if ((res = mp_add (x, &q, x)) != MP_OKAY) @@ -3722,7 +3794,7 @@ int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) pa = a->used; pb = b->used; - for (ix = 0; ix < pa; ix++) { + for (ix = 0; ix < pa && a->dp; ix++) { /* clear the carry */ u = 0; @@ -3787,7 +3859,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, 0, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3795,7 +3867,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* number of output digits to produce */ pa = a->used + b->used; _W = 0; - for (ix = digs; ix < pa; ix++) { + for (ix = digs; ix < pa && a->dp; ix++) { int tx, ty, iy; mp_digit *tmpx, *tmpy; @@ -3845,32 +3917,40 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) mp_clamp (c); #ifdef WOLFSSL_SMALL_STACK - XFREE(W, 0, DYNAMIC_TYPE_BIGINT); + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); #endif return MP_OKAY; } -/* set a 32-bit const */ +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif int mp_set_int (mp_int * a, unsigned long b) { - int x, res; + int x, res; + + /* use direct mp_set if b is less than mp_digit max */ + if (b < MP_DIGIT_MAX) { + return mp_set (a, (mp_digit)b); + } mp_zero (a); - /* set four bits at a time */ - for (x = 0; x < 8; x++) { - /* shift the number up four bits */ - if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + /* shift the number up chunk bits */ + if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) { return res; } - /* OR in the top four bits of the source */ - a->dp[0] |= (b >> 28) & 15; + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); - /* shift the source up to the next four bits */ - b <<= 4; + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; /* ensure that digits are not clamped off */ a->used += 1; @@ -4083,7 +4163,7 @@ static const int lnz[16] = { int mp_cnt_lsb(mp_int *a) { int x; - mp_digit q, qq; + mp_digit q = 0, qq; /* easy out */ if (mp_iszero(a) == MP_YES) { @@ -4092,7 +4172,8 @@ int mp_cnt_lsb(mp_int *a) /* scan lower digits until non-zero */ for (x = 0; x < a->used && a->dp[x] == 0; x++) {} - q = a->dp[x]; + if (a->dp) + q = a->dp[x]; x *= DIGIT_BIT; /* now scan this digit until a 1 is found */ @@ -4172,12 +4253,18 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) /* no easy answer [c'est la vie]. Just division */ if (c != NULL) { if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { - return res; + return res; } q.used = a->used; q.sign = a->sign; } + else { + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + } + w = 0; for (ix = a->used - 1; ix >= 0; ix--) { @@ -4200,8 +4287,8 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) if (c != NULL) { mp_clamp(&q); mp_exch(&q, c); - mp_clear(&q); } + mp_clear(&q); return res; } @@ -4476,7 +4563,9 @@ int mp_prime_is_prime (mp_int * a, int t, int *result) for (ix = 0; ix < t; ix++) { /* set the prime */ - mp_set (&b, ltm_prime_tab[ix]); + if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) { + goto LBL_B; + } if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { goto LBL_B; diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index 9a4fac5f4..1a7b6ff39 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -38,14 +38,35 @@ WOLFSSL_API int wolfSSL_Debugging_ON(void); WOLFSSL_API void wolfSSL_Debugging_OFF(void); #ifdef __cplusplus - } + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ + +/* accessing any node from the queue should be wrapped in a lock of + * debug_mutex */ +static void* wc_error_heap; +struct wc_error_queue { + void* heap; /* the heap hint used with nodes creation */ + struct wc_error_queue* next; + struct wc_error_queue* prev; + char error[WOLFSSL_MAX_ERROR_SZ]; + char file[WOLFSSL_MAX_ERROR_SZ]; + int value; + int line; +}; +volatile struct wc_error_queue* wc_errors; +static struct wc_error_queue* wc_last_node; +/* pointer to last node in queue to make insertion O(1) */ #endif -#ifdef DEBUG_WOLFSSL + +#if defined(DEBUG_WOLFSSL) /* Set these to default values initially. */ -static wolfSSL_Logging_cb log_function = 0; +static wolfSSL_Logging_cb log_function = NULL; static int loggingEnabled = 0; #endif /* DEBUG_WOLFSSL */ @@ -140,7 +161,7 @@ void WOLFSSL_MSG(const char* msg) } -void WOLFSSL_BUFFER(byte* buffer, word32 length) +void WOLFSSL_BUFFER(const byte* buffer, word32 length) { #define LINE_LEN 16 @@ -196,15 +217,319 @@ void WOLFSSL_LEAVE(const char* msg, int ret) wolfssl_log(LEAVE_LOG , buffer); } } +#endif /* DEBUG_WOLFSSL */ - +/* + * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is + * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function + * name where WOLFSSL_ERROR is called at. + */ +#if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY) + #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) +void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line, + const char* file, void* usrCtx) + #else void WOLFSSL_ERROR(int error) + #endif { - if (loggingEnabled) { + #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_NGINX) + if (loggingEnabled && error != WC_PENDING_E) + #endif + { char buffer[80]; - sprintf(buffer, "wolfSSL error occurred, error = %d", error); + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + (void)usrCtx; /* a user ctx for future flexibility */ + (void)func; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + sprintf(buffer, "wolfSSL error occurred, error = %d", error); + } + else { + if (error < 0) error = error - (2*error); /*get absolute value*/ + sprintf(buffer, "wolfSSL error occurred, error = %d line:%d file:%s", + error, line, file); + if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) { + WOLFSSL_MSG("Error creating logging node"); + /* with void function there is no return here, continue on + * to unlock mutex and log what buffer was created. */ + } + + wc_UnLockMutex(&debug_mutex); + } + #else + sprintf(buffer, "wolfSSL error occurred, error = %d", error); + #endif + #ifdef DEBUG_WOLFSSL wolfssl_log(ERROR_LOG , buffer); + #endif } } -#endif /* DEBUG_WOLFSSL */ +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +/* Internal function that is called by wolfCrypt_Init() */ +int wc_LoggingInit(void) +{ + if (wc_InitMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex"); + return BAD_MUTEX_E; + } + wc_errors = NULL; + wc_last_node = NULL; + + return 0; +} + + +/* internal function that is called by wolfCrypt_Cleanup */ +int wc_LoggingCleanup(void) +{ + /* clear logging entries */ + wc_ClearErrorNodes(); + + /* free mutex */ + if (wc_FreeMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Mutex free"); + return BAD_MUTEX_E; + } + return 0; +} + + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +/* peek at an error node + * + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + * file : pointer to internal file string + * reason : pointer to internal error reason + * line : line number that error happened at + * + * Returns a negative value in error case, on success returns the nodes error + * value which is positve (absolute value) + */ +int wc_PeekErrorNode(int idx, const char **file, const char **reason, + int *line) +{ + struct wc_error_queue* err; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + if (idx < 0) { + err = wc_last_node; + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + } + else { + int i; + + err = (struct wc_error_queue*)wc_errors; + for (i = 0; i < idx; i++) { + if (err == NULL) { + WOLFSSL_MSG("Error node not found. Bad index?"); + wc_UnLockMutex(&debug_mutex); + return BAD_FUNC_ARG; + } + err = err->next; + } + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + wc_UnLockMutex(&debug_mutex); + + return err->value; +} + + +/* create new error node and add it to the queue + * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal + * function. debug_mutex should be locked before a call to this function. */ +int wc_AddErrorNode(int error, int line, char* buf, char* file) +{ + + struct wc_error_queue* err; + + err = (struct wc_error_queue*)XMALLOC( + sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG); + if (err == NULL) { + WOLFSSL_MSG("Unable to create error node for log"); + return MEMORY_E; + } + else { + int sz; + + XMEMSET(err, 0, sizeof(struct wc_error_queue)); + err->heap = wc_error_heap; + sz = (int)XSTRLEN(buf); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->error, buf, sz); + } + + sz = (int)XSTRLEN(file); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->file, file, sz); + } + + err->value = error; + err->line = line; + + /* make sure is terminated */ + err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + err->file[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + + + /* since is queue place new node at last of the list */ + if (wc_last_node == NULL) { + /* case of first node added to queue */ + if (wc_errors != NULL) { + /* check for unexpected case before over writing wc_errors */ + WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n"); + } + else { + wc_errors = err; + wc_last_node = err; + } + } + else { + wc_last_node->next = err; + err->prev = wc_last_node; + wc_last_node = err; + } + } + + return 0; +} + +/* Removes the error node at the specified index. + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + */ +void wc_RemoveErrorNode(int idx) +{ + struct wc_error_queue* current; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + if (idx == -1) + current = wc_last_node; + else { + current = (struct wc_error_queue*)wc_errors; + for (; current != NULL && idx > 0; idx--) + current = current->next; + } + if (current != NULL) { + if (current->prev != NULL) + current->prev->next = current->next; + if (wc_last_node == current) + wc_last_node = current->prev; + if (wc_errors == current) + wc_errors = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + } + + wc_UnLockMutex(&debug_mutex); +} + +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */ + +/* Clears out the list of error nodes. + */ +void wc_ClearErrorNodes(void) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + /* free all nodes from error queue */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + } + + wc_errors = NULL; + wc_last_node = NULL; + wc_UnLockMutex(&debug_mutex); +} + +int wc_SetLoggingHeap(void* h) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + wc_error_heap = h; + wc_UnLockMutex(&debug_mutex); + return 0; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* empties out the error queue into the file */ +void wc_ERR_print_errors_fp(FILE* fp) +{ + WOLFSSL_ENTER("wc_ERR_print_errors_fp"); + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + } + else { + /* free all nodes from error queue and print them to file */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + fprintf(fp, "%s\n", current->error); + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + + /* set global pointers to match having been freed */ + wc_errors = NULL; + wc_last_node = NULL; + } + + wc_UnLockMutex(&debug_mutex); + } +} +#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */ + +#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ + diff --git a/wolfcrypt/src/md4.c b/wolfcrypt/src/md4.c index 3b3ae9555..bac424065 100644 --- a/wolfcrypt/src/md4.c +++ b/wolfcrypt/src/md4.c @@ -37,17 +37,6 @@ #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - - void wc_InitMd4(Md4* md4) { md4->digest[0] = 0x67452301L; diff --git a/wolfcrypt/src/md5.c b/wolfcrypt/src/md5.c old mode 100644 new mode 100755 index fdde46ff7..aab311797 --- a/wolfcrypt/src/md5.c +++ b/wolfcrypt/src/md5.c @@ -31,13 +31,8 @@ #if defined(WOLFSSL_TI_HASH) /* #include included by wc_port.c */ -#else -#ifdef WOLFSSL_PIC32MZ_HASH -#define wc_InitMd5 wc_InitMd5_sw -#define wc_Md5Update wc_Md5Update_sw -#define wc_Md5Final wc_Md5Final_sw -#endif +#else #include #include @@ -49,22 +44,21 @@ #include #endif -#ifdef FREESCALE_MMCAU_SHA - #include "fsl_mmcau.h" - #define XTRANSFORM(S,B) Transform((S), (B)) -#else - #define XTRANSFORM(S,B) Transform((S)) -#endif - +/* Hardware Acceleration */ #if defined(STM32F2_HASH) || defined(STM32F4_HASH) /* * STM32F2/F4 hardware MD5 support through the standard peripheral * library. (See note in README). */ - void wc_InitMd5(Md5* md5) + #define HAVE_MD5_CUST_API + + int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { + (void)heap; + (void)devId; + /* STM32 struct notes: * md5->buffer = first 4 bytes used to hold partial block if needed * md5->buffLen = num bytes currently stored in md5->buffer @@ -85,9 +79,11 @@ /* reset HASH processor */ HASH->CR |= HASH_CR_INIT; + + return 0; } - void wc_Md5Update(Md5* md5, const byte* data, word32 len) + int wc_Md5Update(Md5* md5, const byte* data, word32 len) { word32 i = 0; word32 fill = 0; @@ -110,7 +106,7 @@ /* append partial to existing stored block */ XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); md5->buffLen += len; - return; + return 0; } } @@ -131,9 +127,11 @@ /* keep track of total data length thus far */ md5->loLen += (len - md5->buffLen); + + return 0; } - void wc_Md5Final(Md5* md5, byte* hash) + int wc_Md5Final(Md5* md5, byte* hash) { __IO uint16_t nbvalidbitsdata = 0; @@ -165,23 +163,148 @@ XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + return wc_InitMd5(md5); /* reset state */ } -#else /* Begin wolfCrypt software implementation */ +#elif defined(FREESCALE_MMCAU_SHA) + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) + static int Transform(Md5* md5, byte* data) { - return a > b ? b : a; + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; } -#endif /* WOLFSSL_HAVE_MIN */ +#elif defined(WOLFSSL_PIC32MZ_HASH) + #define wc_InitMd5 wc_InitMd5_sw + #define wc_Md5Update wc_Md5Update_sw + #define wc_Md5Final wc_Md5Final_sw -void wc_InitMd5(Md5* md5) + #define NEED_SOFT_MD5 + +#else + #define NEED_SOFT_MD5 + +#endif /* End Hardware Acceleration */ + + +#ifdef NEED_SOFT_MD5 + + #define XTRANSFORM(S,B) Transform((S)) + + #define F1(x, y, z) (z ^ (x & (y ^ z))) + #define F2(x, y, z) F1(z, x, y) + #define F3(x, y, z) (x ^ y ^ z) + #define F4(x, y, z) (y ^ (x | ~z)) + + #define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + static int Transform(Md5* md5) + { + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; + + return 0; + } +#endif /* NEED_SOFT_MD5 */ + + +#ifndef HAVE_MD5_CUST_API +static INLINE void AddMd5Length(Md5* md5, word32 len) { + word32 tmp = md5->loLen; + if ((md5->loLen += len) < tmp) { + md5->hiLen++; /* carry low to high */ + } +} + +static int _InitMd5(Md5* md5) +{ + int ret = 0; + md5->digest[0] = 0x67452301L; md5->digest[1] = 0xefcdab89L; md5->digest[2] = 0x98badcfeL; @@ -190,128 +313,55 @@ void wc_InitMd5(Md5* md5) md5->buffLen = 0; md5->loLen = 0; md5->hiLen = 0; -} -#ifdef FREESCALE_MMCAU_SHA -static int Transform(Md5* md5, byte* data) -{ - int ret = wolfSSL_CryptHwMutexLock(); - if(ret == 0) { - MMCAU_MD5_HashN(data, 1, (uint32_t*)(md5->digest)); - wolfSSL_CryptHwMutexUnLock(); - } return ret; } -#endif /* FREESCALE_MMCAU_SHA */ -#ifndef FREESCALE_MMCAU_SHA - -static void Transform(Md5* md5) +int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) + int ret = 0; -#define MD5STEP(f, w, x, y, z, data, s) \ - w = rotlFixed(w + f(x, y, z) + data, s) + x + if (md5 == NULL) + return BAD_FUNC_ARG; - /* Copy context->state[] to working vars */ - word32 a = md5->digest[0]; - word32 b = md5->digest[1]; - word32 c = md5->digest[2]; - word32 d = md5->digest[3]; + md5->heap = heap; - MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + ret = _InitMd5(md5); + if (ret != 0) + return ret; - MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); - - /* Add the working vars back into digest state[] */ - md5->digest[0] += a; - md5->digest[1] += b; - md5->digest[2] += c; - md5->digest[3] += d; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5, + md5->heap, devId); +#else + (void)devId; +#endif + return ret; } -#endif /* End Software implementation */ - - -static INLINE void AddLength(Md5* md5, word32 len) +int wc_Md5Update(Md5* md5, const byte* data, word32 len) { - word32 tmp = md5->loLen; - if ( (md5->loLen += len) < tmp) - md5->hiLen++; /* carry low to high */ -} + int ret = 0; + byte* local; + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ -void wc_Md5Update(Md5* md5, const byte* data, word32 len) -{ /* do block size increments */ - byte* local = (byte*)md5->buffer; + local = (byte*)md5->buffer; + + /* check that internal buffLen is valid */ + if (md5->buffLen >= MD5_BLOCK_SIZE) + return BUFFER_E; while (len) { word32 add = min(len, MD5_BLOCK_SIZE - md5->buffLen); @@ -322,23 +372,36 @@ void wc_Md5Update(Md5* md5, const byte* data, word32 len) len -= add; if (md5->buffLen == MD5_BLOCK_SIZE) { - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); - AddLength(md5, MD5_BLOCK_SIZE); + AddMd5Length(md5, MD5_BLOCK_SIZE); md5->buffLen = 0; } } + return ret; } - -void wc_Md5Final(Md5* md5, byte* hash) +int wc_Md5Final(Md5* md5, byte* hash) { - byte* local = (byte*)md5->buffer; + byte* local; - AddLength(md5, md5->buffLen); /* before adding pads */ + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, hash, NULL, MD5_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + local = (byte*)md5->buffer; + + AddMd5Length(md5, md5->buffLen); /* before adding pads */ local[md5->buffLen++] = 0x80; /* add 1 */ /* pad with zeros */ @@ -346,9 +409,9 @@ void wc_Md5Final(Md5* md5, byte* hash) XMEMSET(&local[md5->buffLen], 0, MD5_BLOCK_SIZE - md5->buffLen); md5->buffLen += MD5_BLOCK_SIZE - md5->buffLen; - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); + #endif XTRANSFORM(md5, local); md5->buffLen = 0; } @@ -360,50 +423,72 @@ void wc_Md5Final(Md5* md5, byte* hash) md5->loLen = md5->loLen << 3; /* store lengths */ - #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) - ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); - #endif +#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, MD5_BLOCK_SIZE); +#endif /* ! length ordering dependent on digest endian type ! */ XMEMCPY(&local[MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); XMEMCPY(&local[MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); XTRANSFORM(md5, local); - #ifdef BIG_ENDIAN_ORDER - ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); - #endif +#ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); +#endif XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); - wc_InitMd5(md5); /* reset state */ + return _InitMd5(md5); /* reset state */ +} +#endif /* !HAVE_MD5_CUST_API */ + + +int wc_InitMd5(Md5* md5) +{ + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); } -#endif /* End wolfCrypt software implementation */ - - -int wc_Md5Hash(const byte* data, word32 len, byte* hash) +void wc_Md5Free(Md5* md5) { -#ifdef WOLFSSL_SMALL_STACK - Md5* md5; -#else - Md5 md5[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (md5 == NULL) - return MEMORY_E; + return; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +int wc_Md5GetHash(Md5* md5, byte* hash) +{ + int ret; + Md5 tmpMd5; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Md5Copy(md5, &tmpMd5); + if (ret == 0) { + ret = wc_Md5Final(&tmpMd5, hash); + } + + return ret; +} + +int wc_Md5Copy(Md5* src, Md5* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Md5)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); #endif - wc_InitMd5(md5); - wc_Md5Update(md5, data, len); - wc_Md5Final(md5, hash); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; + return ret; } #endif /* WOLFSSL_TI_HASH */ - #endif /* NO_MD5 */ diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index 470b09cf9..927b0c4ad 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -74,6 +74,16 @@ int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, return res; } +int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, + wolfSSL_Free_cb* ff, + wolfSSL_Realloc_cb* rf) +{ + if (mf) *mf = malloc_function; + if (ff) *ff = free_function; + if (rf) *rf = realloc_function; + return 0; +} + #ifndef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) @@ -389,10 +399,19 @@ int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) /* creating only IO buffers from memory passed in, max TLS is 16k */ if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { - ava = sz % (memSz + padSz + WOLFMEM_IO_SZ); + if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { + return 0; /* not enough room for even one bucket */ + } + + ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); } else { int i, k; + + if (ava < (bucketSz[0] + padSz + memSz)) { + return 0; /* not enough room for even one bucket */ + } + while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { /* start at largest and move to smaller buckets */ for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { @@ -530,7 +549,9 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) } /* case of using fixed IO buffers */ - if (mem->flag & WOLFMEM_IO_POOL_FIXED) { + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { if (type == DYNAMIC_TYPE_OUT_BUFFER) { pt = hint->outBuf; } @@ -538,25 +559,26 @@ void* wolfSSL_Malloc(size_t size, void* heap, int type) pt = hint->inBuf; } } - - /* check if using IO pool flag */ - if (mem->flag & WOLFMEM_IO_POOL && pt == NULL && + else { + /* check if using IO pool flag */ + if (mem->flag & WOLFMEM_IO_POOL && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { - if (mem->io != NULL) { - pt = mem->io; - mem->io = pt->next; + if (mem->io != NULL) { + pt = mem->io; + mem->io = pt->next; + } } - } - /* general static memory */ - if (pt == NULL) { - for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { - if ((word32)size < mem->sizeList[i]) { - if (mem->ava[i] != NULL) { - pt = mem->ava[i]; - mem->ava[i] = pt->next; - break; + /* general static memory */ + if (pt == NULL) { + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((word32)size < mem->sizeList[i]) { + if (mem->ava[i] != NULL) { + pt = mem->ava[i]; + mem->ava[i] = pt->next; + break; + } } } } @@ -663,7 +685,7 @@ void wolfSSL_Free(void *ptr, void* heap, int type) /* fixed IO pools are free'd at the end of SSL lifetime using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */ } - else if (mem->flag & WOLFMEM_IO_POOL && + else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ && (type == DYNAMIC_TYPE_OUT_BUFFER || type == DYNAMIC_TYPE_IN_BUFFER)) { pt->next = mem->io; diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index cbd63c959..08ba55e86 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -31,7 +31,7 @@ #include -/* inlining these functions is a huge speed increase and a small size decrease, +/* inlining these functions is a huge speed increase and a small size decrease, because the functions are smaller than function call setup/cleanup, e.g., md5 benchmark is twice as fast with inline. If you don't want it, then define NO_INLINE and compile this file into wolfssl, otherwise it's used as @@ -50,6 +50,12 @@ #else + +#if defined(__ICCARM__) + #include +#endif + + #ifdef INTEL_INTRINSICS #include /* get intrinsic definitions */ @@ -73,7 +79,7 @@ STATIC INLINE word32 rotlFixed(word32 x, word32 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); - } + } STATIC INLINE word32 rotrFixed(word32 x, word32 y) @@ -122,7 +128,7 @@ STATIC INLINE void ByteReverseWords(word32* out, const word32* in, STATIC INLINE word64 rotlFixed64(word64 x, word64 y) { return (x << y) | (x >> (sizeof(y) * 8 - y)); -} +} STATIC INLINE word64 rotrFixed64(word64 x, word64 y) @@ -133,8 +139,8 @@ STATIC INLINE word64 rotrFixed64(word64 x, word64 y) STATIC INLINE word64 ByteReverseWord64(word64 value) { -#ifdef WOLFCRYPT_SLOW_WORD64 - return (word64)(ByteReverseWord32((word32)value)) << 32 | +#if defined(WOLFCRYPT_SLOW_WORD64) + return (word64)(ByteReverseWord32((word32)value)) << 32 | ByteReverseWord32((word32)(value>>32)); #else value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | @@ -210,8 +216,31 @@ STATIC INLINE int ConstantCompare(const byte* a, const byte* b, int length) return compareSum; } -#undef STATIC +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + STATIC INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* !WOLFSSL_HAVE_MIN */ + +#ifndef WOLFSSL_HAVE_MAX + #define WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + STATIC INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } +#endif /* !WOLFSSL_HAVE_MAX */ + + +#undef STATIC #endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 9e7453f11..b96d2a636 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -200,7 +200,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(input, &localIdx, &size, maxIdx)) < 0) { + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { freeSafe(safe, pkcs12->heap); return ret; } @@ -218,7 +218,7 @@ static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, freeSafe(safe, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(input, &localIdx, &size, maxIdx)) < 0) { + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { freeSafe(safe, pkcs12->heap); return ret; } @@ -367,7 +367,7 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, return ASN_PARSE_E; } - if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); return ret; } @@ -398,7 +398,7 @@ static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, return ASN_PARSE_E; } - if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_PKCS); XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); return ret; @@ -527,15 +527,19 @@ static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, } /* now that key has been created use it to get HMAC hash on data */ - if ((ret = wc_HmacSetKey(&hmac, typeH, key, kLen)) != 0) { + if ((ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID)) != 0) { return ret; } - if ((ret = wc_HmacUpdate(&hmac, data, dataSz)) != 0) { + ret = wc_HmacSetKey(&hmac, typeH, key, kLen); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, data, dataSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + wc_HmacFree(&hmac); + + if (ret != 0) return ret; - } - if ((ret = wc_HmacFinal(&hmac, digest)) != 0) { - return ret; - } + #ifdef WOLFSSL_DEBUG_PKCS12 { byte* p; @@ -709,6 +713,10 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, } } + if (pkcs12->safe == NULL) { + WOLFSSL_MSG("No PKCS12 safes to parse"); + return BAD_FUNC_ARG; + } /* Decode content infos */ ci = pkcs12->safe->CI; @@ -800,7 +808,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ret; @@ -851,7 +859,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; } - if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ASN_PARSE_E; @@ -987,7 +995,7 @@ int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, return ASN_PARSE_E; } if ((ret = GetLength(data, &idx, &size, ci->dataSz)) - < 0) { + <= 0) { freeBuffers(*pkey, buf, pkcs12->heap); freeCertList(certList, pkcs12->heap); return ret; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index d5eb9d022..428e55b0f 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -31,6 +31,13 @@ #include #include #include +#include +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif #ifdef NO_INLINE #include #else @@ -38,16 +45,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - /* direction for processing, encoding or decoding */ typedef enum { @@ -55,6 +52,9 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; +#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + /* placed ASN.1 contentType OID into *output, return idx on success, * 0 upon failure */ @@ -96,7 +96,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) typeSz = sizeof(signedData); typeName = signedData; break; - + case ENVELOPED_DATA: typeSz = sizeof(envelopedData); typeName = envelopedData; @@ -350,9 +350,10 @@ typedef struct EncodedAttrib { typedef struct ESD { - Sha sha; - byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ - byte contentAttribsDigest[SHA_DIGEST_SIZE]; + wc_HashAlg hash; + enum wc_HashType hashType; + byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; byte encContentDigest[512]; byte outerSeq[MAX_SEQ_SZ]; @@ -438,6 +439,435 @@ static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 idx; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey stack_privKey; + RsaKey* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey(privKey, pkcs7->heap); + + if (ret == 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz, idx; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key stack_privKey; + ecc_key* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, INVALID_DEVID); + + if (ret == 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* builds up SignedData signed attributes, including default ones. + * + * pkcs7 - pointer to initialized PKCS7 structure + * esd - pointer to initialized ESD structure, used for output + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, + byte* contentTypeOid, word32 contentTypeOidSz, + byte* contentType, word32 contentTypeSz, + byte* messageDigestOid, word32 messageDigestOidSz) +{ + int hashSz; + + PKCS7Attrib cannedAttribs[2]; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || + contentType == NULL || messageDigestOid == NULL) + return BAD_FUNC_ARG; + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[0].oid = contentTypeOid; + cannedAttribs[0].oidSz = contentTypeOidSz; + cannedAttribs[0].value = contentType; + cannedAttribs[0].valueSz = contentTypeSz; + cannedAttribs[1].oid = messageDigestOid; + cannedAttribs[1].oidSz = messageDigestOidSz; + cannedAttribs[1].value = esd->contentDigest; + cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + cannedAttribs, cannedAttribsCount); + + esd->signedAttribsCount += pkcs7->signedAttribsSz; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either RSAk or + * CTC_ wECDSA, from pkcs7->publicKeyOID. + * + * pkcs7 - pointer to PKCS7 structure + * digEncAlgoId - [OUT] output int to store correct algo ID in + * digEncAlgoType - [OUT] output for algo ID type + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, + int* digEncAlgoType) +{ + int algoId = 0; + int algoType = 0; + + if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->publicKeyOID == RSAk) { + + algoId = pkcs7->encryptOID; + algoType = oidKeyType; + + } else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + case SHAh: + algoId = CTC_SHAwECDSA; + break; + + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + } + } + + if (algoId == 0) { + WOLFSSL_MSG("Invalid signature algorithm type"); + return BAD_FUNC_ARG; + } + + *digEncAlgoId = algoId; + *digEncAlgoType = algoType; + + return 0; +} + + +/* build SignedData DigestInfo for use with PKCS#7/RSA + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttrbsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * digestInfo - [OUT] output array for DigestInfo + * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, + word32 flatSignedAttribsSz, ESD* esd, + byte* digestInfo, word32* digestInfoSz) +{ + int ret, hashSz, digIdx = 0; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte attribSet[MAX_SET_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 attribSetSz; + + if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || + digestInfoSz == NULL) { + return BAD_FUNC_ARG; + } + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + if (pkcs7->signedAttribsSz != 0) { + + if (flatSignedAttribs == NULL) + return BAD_FUNC_ARG; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + attribSet, attribSetSz); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret < 0) + return ret; + + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + if (ret < 0) + return ret; + + } else { + /* when no attrs, digest is contentDigest without tag and length */ + XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); + } + + /* set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { + return BUFFER_E; + } + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); + digIdx += hashSz; + + *digestInfoSz = digIdx; + + return 0; +} + + +/* build SignedData signature over DigestInfo or content digest + * + * pkcs7 - pointer to initizlied PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttribsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * + * returns length of signature on success, negative on error */ +static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, + byte* flatSignedAttribs, + word32 flatSignedAttribsSz, + ESD* esd) +{ + int ret; +#ifdef HAVE_ECC + int hashSz; +#endif + word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + /* CMS with ECDSA does not sign DigestInfo structure + * like PKCS#7 with RSA does */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } + + ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, + hashSz, esd); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* sets the wc_HashType in ESD struct based on pkcs7->hashOID + * + * pkcs7 - pointer to initialized PKCS7 struct + * type - [OUT] pointer to wc_HashType for output + * + * returns hash digest size on success, negative on error */ +static int wc_PKCS7_SetHashType(PKCS7* pkcs7, enum wc_HashType* type) +{ + if (pkcs7 == NULL || type == NULL) + return BAD_FUNC_ARG; + + switch (pkcs7->hashOID) { + +#ifndef NO_SHA + case SHAh: + *type = WC_HASH_TYPE_SHA; + break; +#endif +#ifdef WOLFSSL_SHA224 + case SHA224h: + *type = WC_HASH_TYPE_SHA224; + break; +#endif +#ifndef NO_SHA256 + case SHA256h: + *type = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + *type = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + *type = WC_HASH_TYPE_SHA512; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return wc_HashGetDigestSize(*type); +} + + /* build PKCS#7 signedData content type */ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -448,6 +878,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 }; + byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + byte contentType[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01 }; + byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + #ifdef WOLFSSL_SMALL_STACK ESD* esd = NULL; #else @@ -458,6 +898,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) word32 signerInfoSz = 0; word32 totalSz = 0; int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType, hashSz; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; word32 innerOidSz = sizeof(innerOid); @@ -477,7 +918,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif XMEMSET(esd, 0, sizeof(ESD)); - ret = wc_InitSha(&esd->sha); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &esd->hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + ret = wc_HashInit(&esd->hash, esd->hashType); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -487,10 +937,24 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->contentSz != 0) { - wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = SHA_DIGEST_SIZE; - wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + esd->contentDigest[1] = hashSz; + ret = wc_HashFinal(&esd->hash, esd->hashType, + &esd->contentDigest[2]); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } } esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); @@ -512,40 +976,33 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, oidHashType, 0); signerInfoSz += esd->signerDigAlgoIdSz; - esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, - oidKeyType, 0); + + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); signerInfoSz += esd->digEncAlgoIdSz; if (pkcs7->signedAttribsSz != 0) { - byte contentTypeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, - 0x09, 0x03 }; - byte contentType[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; - byte messageDigestOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x04 }; - PKCS7Attrib cannedAttribs[2] ; - - word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); - cannedAttribs[0].oid = contentTypeOid ; - cannedAttribs[0].oidSz = sizeof(contentTypeOid) ; - cannedAttribs[0].value = contentType ; - cannedAttribs[0].valueSz = sizeof(contentType) ; - cannedAttribs[1].oid = messageDigestOid ; - cannedAttribs[1].oidSz = sizeof(messageDigestOid) ; - cannedAttribs[1].value = esd->contentDigest ; - cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ; - - esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, - cannedAttribs, cannedAttribsCount); - - esd->signedAttribsCount += pkcs7->signedAttribsSz; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, - pkcs7->signedAttribs, pkcs7->signedAttribsSz); + /* build up signed attributes */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, + contentTypeOid, sizeof(contentTypeOid), + contentType, sizeof(contentType), + messageDigestOid, sizeof(messageDigestOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS); @@ -556,130 +1013,25 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif return MEMORY_E; } + FlattenAttributes(flatSignedAttribs, esd->signedAttribs, esd->signedAttribsCount); esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, esd->signedAttribSet); } + /* Calculate the final hash and encrypt it. */ - { - int result; - word32 scratch = 0; - + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); #ifdef WOLFSSL_SMALL_STACK - byte* digestInfo; - RsaKey* privKey; -#else - RsaKey stack_privKey; - RsaKey* privKey = &stack_privKey; - byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - byte digestInfoSeq[MAX_SEQ_SZ]; - byte digestStr[MAX_OCTET_STR_SZ]; - word32 digestInfoSeqSz, digestStrSz; - int digIdx = 0; - - if (pkcs7->signedAttribsSz != 0) { - byte attribSet[MAX_SET_SZ]; - word32 attribSetSz; - - attribSetSz = SetSet(flatSignedAttribsSz, attribSet); - - ret = wc_InitSha(&esd->sha); - if (ret < 0) { - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); - wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); - wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); - } else { - /* when no attrs, digest is contentDigest without tag and length */ - XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, - SHA_DIGEST_SIZE); - } - - digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); - digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz + - digestStrSz + SHA_DIGEST_SIZE, - digestInfoSeq); - -#ifdef WOLFSSL_SMALL_STACK - digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digestInfo == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); - digIdx += digestInfoSeqSz; - XMEMCPY(digestInfo + digIdx, - esd->signerDigAlgoId, esd->signerDigAlgoIdSz); - digIdx += esd->signerDigAlgoIdSz; - XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); - digIdx += digestStrSz; - XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, - SHA_DIGEST_SIZE); - digIdx += SHA_DIGEST_SIZE; - -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - result = wc_InitRsaKey(privKey, pkcs7->heap); - if (result == 0) - result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, - pkcs7->privateKeySz); - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - result = wc_RsaSSL_Sign(digestInfo, digIdx, - esd->encContentDigest, - sizeof(esd->encContentDigest), - privKey, pkcs7->rng); - - wc_FreeRsaKey(privKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return result; - } - esd->encContentDigestSz = (word32)result; + return ret; } + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, @@ -769,7 +1121,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += esd->signerDigAlgoIdSz; /* SignerInfo:Attributes */ - if (pkcs7->signedAttribsSz != 0) { + if (flatSignedAttribsSz > 0) { XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); idx += esd->signedAttribSetSz; XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); @@ -792,15 +1144,398 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + word32 scratch = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey stack_key; + RsaKey* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_InitRsaKey(key, pkcs7->heap); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + + wc_FreeRsaKey(key); + + if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0; + int res = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key stack_key; + ecc_key* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_ecc_init_ex(key, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_ecc_import_x963(pkcs7->publicKey, pkcs7->publicKeySz, key) < 0) { + WOLFSSL_MSG("ASN ECDSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + + wc_ecc_free(key); + + if (ret == 0 && res != 1) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* build SignedData digest, both in PKCS#7 DigestInfo format and + * as plain digest for CMS. + * + * pkcs7 - pointer to initialized PKCS7 struct + * signedAttrib - signed attributes + * signedAttribSz - size of signedAttrib, octets + * pkcs7Digest - [OUT] PKCS#7 DigestInfo + * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest + * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest + * plainDigestSz - [OUT] size of digest at plainDigest + * + * returns 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, + word32 signedAttribSz, byte* pkcs7Digest, + word32* pkcs7DigestSz, byte** plainDigest, + word32* plainDigestSz) +{ + int ret = 0, digIdx = 0, hashSz; + word32 attribSetSz; + byte attribSet[MAX_SET_SZ]; + byte digest[WC_MAX_DIGEST_SIZE]; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + wc_HashAlg hash; + enum wc_HashType hashType; + + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); + XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + /* calculate digest */ + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (signedAttribSz > 0) { + + if (signedAttrib == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + attribSetSz = SetSet(signedAttribSz, attribSet); + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + } else { + + if (pkcs7->content == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + + /* Set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, digest, hashSz); + digIdx += hashSz; + + XMEMCPY(pkcs7Digest, digestInfo, digIdx); + *pkcs7DigestSz = digIdx; + + /* set plain digest pointer */ + *plainDigest = pkcs7Digest + digIdx - hashSz; + *plainDigestSz = hashSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} + + +/* verifies SignedData signature, over either PKCS#7 DigestInfo or + * content digest. + * + * pkcs7 - pointer to initialized PKCS7 struct + * sig - signature to verify + * sigSz - size of sig + * signedAttrib - signed attributes, or null if empty + * signedAttribSz - size of signedAttributes + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz) +{ + int ret = 0; + word32 plainDigestSz = 0, pkcs7DigestSz; + byte* plainDigest = NULL; /* offset into pkcs7Digest */ +#ifdef WOLFSSL_SMALL_STACK + byte* pkcs7Digest; +#else + byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + /* build hash to verify against */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + pkcs7DigestSz); + if (ret < 0) { + WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + } + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + + /* Finds the certificates in the message and saves it. */ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) { - word32 idx, contentType; + word32 idx, contentType, hashOID; int length, version, ret; byte* content = NULL; byte* sig = NULL; byte* cert = NULL; - int contentSz = 0, sigSz = 0, certSz = 0; + byte* signedAttrib = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) return BAD_FUNC_ARG; @@ -863,7 +1598,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) <= 0) return ASN_PARSE_E; if (pkiMsg[idx++] != ASN_OCTET_STRING) @@ -943,11 +1678,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) idx += length; /* Get the sequence of digestAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) { return ASN_PARSE_E; - - /* Skip it */ - idx += length; + } + pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { @@ -956,6 +1690,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + /* save pointer and length */ + signedAttrib = &pkiMsg[idx]; + signedAttribSz = length; + idx += length; } @@ -983,72 +1721,18 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) pkcs7->content = content; pkcs7->contentSz = contentSz; - { - word32 scratch = 0; - int plainSz = 0; - #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE) - -#ifdef WOLFSSL_SMALL_STACK - byte* digest; - RsaKey* key; - - digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (digest == NULL) - return MEMORY_E; - - key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#else - byte digest[MAX_PKCS7_DIGEST_SZ]; - RsaKey stack_key; - RsaKey* key = &stack_key; -#endif - - XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - - ret = wc_InitRsaKey(key, pkcs7->heap); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN RSA key decode error"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, - key); - wc_FreeRsaKey(key); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (plainSz < 0) - return plainSz; - } + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz); + if (ret < 0) + return ret; } return 0; } +#ifdef HAVE_ECC + /* KARI == KeyAgreeRecipientInfo (key agreement) */ typedef struct WC_PKCS7_KARI { DecodedCert* decoded; /* decoded recip cert */ @@ -1137,7 +1821,7 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->decoded == NULL) { WOLFSSL_MSG("Failed to allocate DecodedCert"); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1145,8 +1829,8 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->recipKey == NULL) { WOLFSSL_MSG("Failed to allocate recipient ecc_key"); - XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1154,9 +1838,9 @@ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) DYNAMIC_TYPE_PKCS7); if (kari->senderKey == NULL) { WOLFSSL_MSG("Failed to allocate sender ecc_key"); - XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); - XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return NULL; } @@ -1292,7 +1976,7 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, /* create ephemeral ECC key, places ecc_key in kari->senderKey, * DER encoded in kari->senderKeyExport. return 0 on success, * negative on error */ -static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, RNG* rng) +static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) { int ret; @@ -1308,7 +1992,7 @@ static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, RNG* rng) kari->senderKeyExportSz = kari->decoded->pubKeySize; - ret = wc_ecc_init(kari->senderKey); + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -1336,6 +2020,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) int keyInfoSz = 0; int suppPubInfoSeqSz = 0; int entityUInfoOctetSz = 0; + int entityUInfoExplicitSz = 0; int kekOctetSz = 0; int sharedInfoSz = 0; @@ -1345,6 +2030,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) byte keyInfo[MAX_ALGO_SZ]; byte suppPubInfoSeq[MAX_SEQ_SZ]; byte entityUInfoOctet[MAX_OCTET_STR_SZ]; + byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; byte kekOctet[MAX_OCTET_STR_SZ]; if (kari == NULL) @@ -1367,6 +2053,11 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) if (kari->ukmSz > 0) { entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); + + entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + + kari->ukmSz, + entityUInfoExplicitSeq); + sharedInfoSz += entityUInfoExplicitSz; } /* keyInfo */ @@ -1389,6 +2080,9 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); idx += keyInfoSz; if (kari->ukmSz > 0) { + XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, + entityUInfoExplicitSz); + idx += entityUInfoExplicitSz; XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); idx += entityUInfoOctetSz; XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); @@ -1415,7 +2109,8 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, int keyWrapOID, int keyEncOID) { int ret; - int kSz, kdfType; + int kSz; + enum wc_HashType kdfType; byte* secret; word32 secretSz; @@ -1474,7 +2169,7 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, kdfType = WC_HASH_TYPE_SHA; break; #endif - #ifndef WOLF_SHA224 + #ifndef WOLFSSL_SHA224 case dhSinglePass_stdDH_sha224kdf_scheme: kdfType = WC_HASH_TYPE_SHA224; break; @@ -1763,6 +2458,8 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, return idx; } +#endif /* HAVE_ECC */ + /* create ASN.1 formatted RecipientInfo structure, returns sequence size */ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, @@ -2116,32 +2813,32 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, static int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz) { int ret; - WC_RNG* random = NULL; + WC_RNG* rnd = NULL; if (iv == NULL || ivSz == 0) return BAD_FUNC_ARG; /* input RNG is optional, init local one if input rng is NULL */ if (rng == NULL) { - random = XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (random == NULL) + rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rnd == NULL) return MEMORY_E; - ret = wc_InitRng(random); + ret = wc_InitRng(rnd); if (ret != 0) { - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + XFREE(rnd, NULL, DYNAMIC_TYPE_RNG); return ret; } } else { - random = rng; + rnd = rng; } - ret = wc_RNG_GenerateBlock(random, iv, ivSz); + ret = wc_RNG_GenerateBlock(rnd, iv, ivSz); if (rng == NULL) { - wc_FreeRng(random); - XFREE(random, NULL, DYNAMIC_TYPE_RNG); + wc_FreeRng(rnd); + XFREE(rnd, NULL, DYNAMIC_TYPE_RNG); } return ret; @@ -2258,7 +2955,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* generate random content encryption key */ - ret = wc_InitRng(&rng); + ret = wc_InitRng_ex(&rng, pkcs7->heap, INVALID_DEVID); if (ret != 0) return ret; @@ -2293,6 +2990,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) MAX_RECIP_SZ, pkcs7->heap); break; +#ifdef HAVE_ECC case ECDSAk: recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, @@ -2302,6 +3000,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentKeyPlain, contentKeyEnc, &contentKeyEncSz, recip, MAX_RECIP_SZ); break; +#endif default: WOLFSSL_MSG("Unsupported RecipientInfo public key type"); @@ -2318,7 +3017,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("Failed to create RecipientInfo"); wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return recipSz; } @@ -2329,7 +3028,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) wc_FreeRng(&rng); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } @@ -2338,7 +3037,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); if (contentTypeSz == 0) { #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BAD_FUNC_ARG; } @@ -2367,7 +3066,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (encryptedContent == NULL) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return MEMORY_E; } @@ -2434,7 +3133,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return BUFFER_E; } @@ -2474,7 +3173,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK - XFREE(recip, NULL, DYNAMMIC_TYPE_TMP_BUFFER); + XFREE(recip, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return idx; @@ -2645,6 +3344,8 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } +#ifdef HAVE_ECC + /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx) @@ -2744,14 +3445,18 @@ static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, return 0; } - kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); - if (kari->ukm == NULL) - return MEMORY_E; + kari->ukm = NULL; + if (length > 0) { + kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->ukm == NULL) + return MEMORY_E; + + XMEMCPY(kari->ukm, pkiMsg + (*idx), length); + kari->ukmOwner = 1; + } - XMEMCPY(kari->ukm, pkiMsg + (*idx), length); (*idx) += length; kari->ukmSz = length; - kari->ukmOwner = 1; return 0; } @@ -2850,6 +3555,8 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, return 0; } +#endif /* HAVE_ECC */ + /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ @@ -2857,6 +3564,7 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { +#ifdef HAVE_ECC int ret, keySz; int encryptedKeySz; int direction = 0; @@ -2990,6 +3698,17 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif return 0; +#else + (void)pkcs7; + (void)pkiMsg; + (void)pkiMsgSz; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ } @@ -3138,7 +3857,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, /* walk through RecipientInfo set, find correct recipient */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - + #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, NULL, DYNAMIC_TYPE_PKCS7); @@ -3172,7 +3891,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, #endif return ASN_PARSE_E; } - + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); @@ -3210,14 +3929,14 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, #endif return ASN_PARSE_E; } - + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); #endif return ASN_PARSE_E; } - + if (length != expBlockSz) { WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); #ifdef WOLFSSL_SMALL_STACK @@ -3237,7 +3956,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, return ASN_PARSE_E; } - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) { + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, NULL, DYNAMIC_TYPE_PKCS7); #endif @@ -3387,8 +4106,11 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* encrypt content */ ret = wc_PKCS7_GenerateIV(NULL, tmpIv, blockSz); - if (ret != 0) + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; + } ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz, @@ -3468,7 +4190,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("PKCS#7 output buffer too small"); if (pkcs7->unprotectedAttribsSz != 0) { XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); - XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); } XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3571,9 +4293,9 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, /* save attribute value bytes and size */ if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) { - return ASN_PARSE_E; XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS); XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; } if ((pkiMsgSz - idx) < (word32)length) { @@ -3691,7 +4413,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0) + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) return ASN_PARSE_E; encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, diff --git a/wolfcrypt/src/poly1305.c b/wolfcrypt/src/poly1305.c index 637106b63..4badc05b7 100644 --- a/wolfcrypt/src/poly1305.c +++ b/wolfcrypt/src/poly1305.c @@ -592,26 +592,28 @@ int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, return BAD_FUNC_ARG; } - if (additional == NULL && addSz > 0) { - return BAD_FUNC_ARG; - } + /* additional allowed to be 0 */ + if (addSz > 0) { + if (additional == NULL) + return BAD_FUNC_ARG; - /* additional data plus padding */ - if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { - return ret; - } - paddingLen = -addSz & (WC_POLY1305_PAD_SZ - 1); - if (paddingLen) { - if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + /* additional data plus padding */ + if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { return ret; } + paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen) { + if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + return ret; + } + } } /* input plus padding */ if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { return ret; } - paddingLen = -sz & (WC_POLY1305_PAD_SZ - 1); + paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); if (paddingLen) { if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { return ret; diff --git a/wolfcrypt/src/port/arm/armv8-aes.c b/wolfcrypt/src/port/arm/armv8-aes.c index e59bd2571..0dc43e4e4 100644 --- a/wolfcrypt/src/port/arm/armv8-aes.c +++ b/wolfcrypt/src/port/arm/armv8-aes.c @@ -301,16 +301,22 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* set the heap hint for aes struct */ -int wc_InitAes_h(Aes* aes, void* h) +int wc_AesInit(Aes* aes, void* heap, int devId) { if (aes == NULL) return BAD_FUNC_ARG; - aes->heap = h; + aes->heap = heap; + (void)devId; return 0; } +void wc_AesFree(Aes* aes) +{ + (void)aes; +} + #ifdef __aarch64__ /* AES CCM/GCM use encrypt direct but not decrypt */ @@ -2532,6 +2538,11 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, return BAD_FUNC_ARG; } + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + switch (aes->rounds) { case 10: return Aes128GcmEncrypt(aes, out, in, sz, iv, ivSz, @@ -4547,26 +4558,7 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif /* HAVE_AES_DECRYPT */ #endif /* HAVE_AESCCM */ -#ifdef WOLFSSL_ASYNC_CRYPT -/* Initialize Aes for use with Nitrox device */ -int wc_AesAsyncInit(Aes* aes, int devId) -{ - WOLFSSL_STUB("wc_AesAsyncInit"); - (void)aes; - (void)devId; - return 0; -} - - -/* Free Aes from use with Nitrox device */ -void wc_AesAsyncFree(Aes* aes) -{ - WOLFSSL_STUB("wc_AesAsyncFree"); - (void)aes; -} - -#endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_AESGCM /* common GCM functions 32 and 64 bit */ WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) @@ -4653,5 +4645,31 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) #endif /* HAVE_AES_DECRYPT */ #endif /* WOLFSSL_AES_DIRECT */ +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } + + switch (aes->rounds) { + case 10: + *keySize = 16; + break; + case 12: + *keySize = 24; + break; + case 14: + *keySize = 32; + break; + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + #endif /* NO_AES */ diff --git a/wolfcrypt/src/port/arm/armv8-sha256.c b/wolfcrypt/src/port/arm/armv8-sha256.c index fdf2634bf..48d7230ef 100644 --- a/wolfcrypt/src/port/arm/armv8-sha256.c +++ b/wolfcrypt/src/port/arm/armv8-sha256.c @@ -38,27 +38,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - -#if !defined (ALIGN32) - #if defined (__GNUC__) - #define ALIGN32 __attribute__ ( (aligned (32))) - #elif defined(_MSC_VER) - /* disable align warning, we want alignment ! */ - #pragma warning(disable: 4324) - #define ALIGN32 __declspec (align (32)) - #else - #define ALIGN32 - #endif -#endif static const ALIGN32 word32 K[64] = { 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, @@ -76,7 +55,8 @@ static const ALIGN32 word32 K[64] = { 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L }; -int wc_InitSha256(Sha256* sha256) + +int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { int ret = 0; @@ -97,9 +77,21 @@ int wc_InitSha256(Sha256* sha256) sha256->loLen = 0; sha256->hiLen = 0; + (void)heap; + (void)devId; + return ret; } +int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(Sha256* sha256) +{ + (void)sha256; +} static INLINE void AddLength(Sha256* sha256, word32 len) { @@ -1308,7 +1300,35 @@ int wc_Sha256Final(Sha256* sha256, byte* hash) return wc_InitSha256(sha256); /* reset state */ } + #endif /* __aarch64__ */ -#endif /* NO_SHA256 and WOLFSSL_ARMASM */ +int wc_Sha256GetHash(Sha256* sha256, byte* hash) +{ + int ret; + Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); + } + return ret; +} + +int wc_Sha256Copy(Sha256* src, Sha256* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(Sha256)); + + return ret; +} + +#endif /* NO_SHA256 and WOLFSSL_ARMASM */ diff --git a/wolfcrypt/src/port/cavium/README.md b/wolfcrypt/src/port/cavium/README.md index 982a938b9..b98d866dd 100644 --- a/wolfcrypt/src/port/cavium/README.md +++ b/wolfcrypt/src/port/cavium/README.md @@ -1,32 +1,3 @@ -# Cavium Nitrox V Support +# Cavium Nitrox III/V Support -## Directory Structure: -`/` - `/CNN55XX-SDK` - `/wolfssl` - -## Cavium Driver - -Tested again `CNN55XX-Driver-Linux-KVM-XEN-PF-SDK-0.2-04.tar` -From inside `CNN55XX-SDK`: -1. `make` - Note: To resolve warnings in `CNN55XX-SDK/include/vf_defs.h`: - a. Changed `vf_config_mode_str` to return `const char*` and modify `vf_mode_str` to be `const char*`. - b. In `vf_config_mode_to_num_vfs` above `default:` add `case PF:`. - -2. `sudo make load` - -## wolfSSL - -Currently the AES and DES3 benchmark tests causes the kernel to crash, so they are disabled for now, even though the wolfCrypt tests pass for those. - -From inside `wolfssl`: -1. `./configure --with-cavium-v=../CNN55XX-SDK --enable-asynccrypt --enable-aesni --enable-intelasm --disable-aes --disable-aesgcm --disable-des3` -2. `make` - -## Usage - -Note: Must run applications with sudo to access device. - -`sudo ./wolfcrypt/benchmark/benchmark` -`sudo ./wolfcrypt/test/testwolfcrypt` +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/cavium/cavium_nitrox.c b/wolfcrypt/src/port/cavium/cavium_nitrox.c deleted file mode 100644 index 1acc49644..000000000 --- a/wolfcrypt/src/port/cavium/cavium_nitrox.c +++ /dev/null @@ -1,778 +0,0 @@ -/* cavium-nitrox.c - * - * Copyright (C) 2006-2016 wolfSSL Inc. - * - * This file is part of wolfSSL. (formerly known as CyaSSL) - * - * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * wolfSSL is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include - -#ifdef HAVE_CAVIUM - -#include -#include -#include -#include -#ifndef NO_RSA - #include -#endif -#ifndef NO_AES - #include -#endif - -#include -#include /* For ntohs */ - -static CspHandle mLastDevHandle = INVALID_DEVID; - -int NitroxTranslateResponseCode(int ret) -{ - switch (ret) { - case EAGAIN: - case ERR_REQ_PENDING: - ret = WC_PENDING_E; - break; - case ERR_REQ_TIMEOUT: - ret = WC_TIMEOUT_E; - break; - case 0: - /* leave as-is */ - break; - default: - printf("NitroxTranslateResponseCode Unknown ret=%x\n", ret); - ret = ASYNC_INIT_E; - } - return ret; -} - - -CspHandle NitroxGetDeviceHandle(void) -{ - return mLastDevHandle; -} - -CspHandle NitroxOpenDevice(int dma_mode, int dev_id) -{ - mLastDevHandle = INVALID_DEVID; - -#ifdef HAVE_CAVIUM_V - (void)dma_mode; - - if (CspInitialize(dev_id, &mLastDevHandle)) { - return -1; - } - -#else - Csp1CoreAssignment core_assign; - Uint32 device; - - if (CspInitialize(CAVIUM_DIRECT, CAVIUM_DEV_ID)) { - return -1; - } - if (Csp1GetDevType(&device)) { - return -1; - } - if (device != NPX_DEVICE) { - if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT, - (Uint32 *)&core_assign)!= 0) { - return -1; - } - } - CspShutdown(CAVIUM_DEV_ID); - - mLastDevHandle = CspInitialize(dma_mode, dev_id); - if (mLastDevHandle == 0) { - mLastDevHandle = dev_id; - } - -#endif /* HAVE_CAVIUM_V */ - - return mLastDevHandle; -} - - -int NitroxAllocContext(CaviumNitroxDev* nitrox, CspHandle devId, - ContextType type) -{ - int ret; - - if (nitrox == NULL) { - return -1; - } - - /* If invalid handle provided, use last open one */ - if (devId == INVALID_DEVID) { - devId = NitroxGetDeviceHandle(); - } - -#ifdef HAVE_CAVIUM_V - ret = CspAllocContext(devId, type, &nitrox->contextHandle); -#else - ret = CspAllocContext(type, &nitrox->contextHandle, devId); -#endif - if (ret != 0) { - return -1; - } - - nitrox->type = type; - nitrox->devId = devId; - - return 0; -} - -void NitroxFreeContext(CaviumNitroxDev* nitrox) -{ - if (nitrox == NULL) { - return; - } - -#ifdef HAVE_CAVIUM_V - CspFreeContext(nitrox->devId, nitrox->type, nitrox->contextHandle); -#else - CspFreeContext(nitrox->type, nitrox->contextHandle, nitrox->devId); -#endif -} - -void NitroxCloseDevice(CspHandle devId) -{ - if (devId >= 0) { - CspShutdown(devId); - } -} - -#if defined(WOLFSSL_ASYNC_CRYPT) - -int NitroxCheckRequest(CspHandle devId, CavReqId reqId) -{ - int ret = CspCheckForCompletion(devId, reqId); - return NitroxTranslateResponseCode(ret); -} - -int NitroxCheckRequests(CspHandle devId, CspMultiRequestStatusBuffer* req_stat_buf) -{ - int ret = CspGetAllResults(req_stat_buf, devId); - return NitroxTranslateResponseCode(ret); -} - - -#ifndef NO_RSA - -int NitroxRsaExptMod(const byte* in, word32 inLen, - byte* exponent, word32 expLen, - byte* modulus, word32 modLen, - byte* out, word32* outLen, RsaKey* key) -{ - int ret; - - if (key == NULL || in == NULL || inLen == 0 || exponent == NULL || - modulus == NULL || out == NULL) { - return BAD_FUNC_ARG; - } - - (void)outLen; - -#ifdef HAVE_CAVIUM_V - ret = CspMe(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, - CAVIUM_DPORT, modLen, expLen, inLen, - modulus, exponent, (Uint8*)in, out, - &key->asyncDev.dev.reqId); - #if 0 - /* TODO: Try MeCRT */ - ret = CspMeCRT(); - #endif -#else - /* Not implemented/supported */ - ret = NOT_COMPILED_IN; -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return ret; -} - -int NitroxRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - - if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15Enc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT2, key->n.used, key->e.used, - (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, - &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15Enc(CAVIUM_REQ_MODE, BT2, key->n.used, key->e.used, - (word16)inLen, key->n.dpraw, key->e.dpraw, (byte*)in, out, - &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return key->n.used; -} - - -static INLINE void ato16(const byte* c, word16* u16) -{ - *u16 = (c[0] << 8) | (c[1]); -} - -int NitroxRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || - inLen != (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15CrtDec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT2, key->n.used, key->q.dpraw, - key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, &outSz, out, &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15CrtDec(CAVIUM_REQ_MODE, BT2, key->n.used, key->q.dpraw, - key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, &outSz, out, &key->asyncDev.dev.reqId, - key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - ato16((const byte*)&outSz, &outSz); - - return outSz; -} - - -int NitroxRsaSSL_Sign(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - - if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < - (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15CrtEnc(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT1, key->n.used, (word16)inLen, - key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, out, &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15CrtEnc(CAVIUM_REQ_MODE, BT1, key->n.used, (word16)inLen, - key->q.dpraw, key->dQ.dpraw, key->p.dpraw, key->dP.dpraw, key->u.dpraw, - (byte*)in, out, &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - return key->n.used; -} - - -int NitroxRsaSSL_Verify(const byte* in, word32 inLen, byte* out, - word32 outLen, RsaKey* key) -{ - word32 ret; - word16 outSz = (word16)outLen; - - if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->n.used) { - return BAD_FUNC_ARG; - } - -#ifdef HAVE_CAVIUM_V - ret = CspPkcs1v15Dec(key->asyncDev.dev.devId, CAVIUM_REQ_MODE, CAVIUM_SSL_GRP, CAVIUM_DPORT, - BT1, key->n.used, key->e.used, - key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, - &key->asyncDev.dev.reqId); -#else - ret = CspPkcs1v15Dec(CAVIUM_REQ_MODE, BT1, key->n.used, key->e.used, - key->n.dpraw, key->e.dpraw, (byte*)in, &outSz, out, - &key->asyncDev.dev.reqId, key->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - outSz = ntohs(outSz); - - return outSz; -} -#endif /* !NO_RSA */ - - -#ifndef NO_AES -int NitroxAesSetKey(Aes* aes, const byte* key, word32 length, const byte* iv) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - XMEMCPY(aes->key, key, length); /* key still holds key, iv still in reg */ - if (length == 16) - aes->type = AES_128_BIT; - else if (length == 24) - aes->type = AES_192_BIT; - else if (length == 32) - aes->type = AES_256_BIT; - - return wc_AesSetIV(aes, iv); -} - -#ifdef HAVE_AES_CBC -int NitroxAesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 length) -{ - int ret; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, - (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, - out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - #ifdef HAVE_CAVIUM_V - ret = CspEncryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, - (byte*)aes->reg, 0, NULL, slen, (byte*)in + offset, - out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspEncryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(aes->reg, out + offset+length - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - } - return 0; -} - -#ifdef HAVE_AES_DECRYPT -int NitroxAesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, - 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(aes->tmp, in + offset + slen - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecryptAes(aes->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, aes->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, AES_CBC, aes->type, (byte*)aes->key, (byte*)aes->reg, - 0, NULL, slen, (byte*)in + offset, out + offset, &aes->asyncDev.dev.reqId); - #else - ret = CspDecryptAes(CAVIUM_BLOCKING, aes->asyncDev.dev.contextHandle, CAVIUM_NO_UPDATE, - aes->type, slen, (byte*)in + offset, out + offset, - (byte*)aes->reg, (byte*)aes->key, &aes->asyncDev.dev.reqId, - aes->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); - } - return 0; -} -#endif /* HAVE_AES_DECRYPT */ -#endif /* HAVE_AES_CBC */ -#endif /* !NO_AES */ - - -#if !defined(NO_ARC4) && !defined(HAVE_CAVIUM_V) -void NitroxArc4SetKey(Arc4* arc4, const byte* key, word32 length) -{ - if (CspInitializeRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, length, - (byte*)key, &arc4->asyncDev.dev.reqId, arc4->devId) != 0) { - WOLFSSL_MSG("Bad Cavium Arc4 Init"); - } -} - -void NitroxArc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) -{ - int ret; - wolfssl_word offset = 0; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, - CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, - &arc4->asyncDev.dev.reqId, arc4->devId); - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (length) { - word16 slen = (word16)length; - ret = CspEncryptRc4(CAVIUM_BLOCKING, arc4->asyncDev.dev.contextHandle, - CAVIUM_UPDATE, slen, (byte*)in + offset, out + offset, - &arc4->asyncDev.dev.reqId, arc4->devId); - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - } -} -#endif /* !NO_ARC4 && !HAVE_CAVIUM_V */ - - -#ifndef NO_DES3 -int NitroxDes3SetKey(Des3* des3, const byte* key, const byte* iv) -{ - if (des3 == NULL) - return BAD_FUNC_ARG; - - /* key[0] holds key, iv in reg */ - XMEMCPY(des3->key[0], key, DES_BLOCK_SIZE*3); - - return wc_Des3_SetIV(des3, iv); -} - -int NitroxDes3CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], - (byte*)des3->reg, slen, (byte*)in + offset, - out + offset, &des3->asyncDev.dev.reqId); - #else - ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - #ifdef HAVE_CAVIUM_V - ret = CspEncrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspEncrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, - out + offset, (byte*)des3->reg, (byte*)des3->key[0], - &des3->asyncDev.dev.reqId, des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(des3->reg, out+offset+length - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - } - return 0; -} - -int NitroxDes3CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 length) -{ - wolfssl_word offset = 0; - int ret; - - while (length > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE, DES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, - (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, - des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - length -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - if (length) { - word16 slen = (word16)length; - XMEMCPY(des3->tmp, in + offset + slen - DES_BLOCK_SIZE,DES_BLOCK_SIZE); - #ifdef HAVE_CAVIUM_V - ret = CspDecrypt3Des(des3->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, des3->asyncDev.dev.contextHandle, - FROM_DPTR, FROM_CTX, DES3_CBC, (byte*)des3->key[0], (byte*)des3->reg, - slen, (byte*)in + offset, out + offset, - &des3->asyncDev.dev.reqId); - #else - ret = CspDecrypt3Des(CAVIUM_BLOCKING, des3->asyncDev.dev.contextHandle, - CAVIUM_NO_UPDATE, slen, (byte*)in + offset, out + offset, - (byte*)des3->reg, (byte*)des3->key[0], &des3->asyncDev.dev.reqId, - des3->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - XMEMCPY(des3->reg, des3->tmp, DES_BLOCK_SIZE); - } - return 0; -} -#endif /* !NO_DES3 */ - - -#ifndef NO_HMAC -int NitroxHmacFinal(Hmac* hmac, byte* hash) -{ - int ret = -1; - -#ifdef HAVE_CAVIUM_V - word16 hashLen = wc_HmacSizeByType(hmac->macType); - ret = CspHmac(hmac->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, hmac->type, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hashLen, - hash, &hmac->asyncDev.dev.reqId); -#else - ret = CspHmac(CAVIUM_BLOCKING, hmac->type, NULL, hmac->keyLen, - (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, - &hmac->asyncDev.dev.reqId, hmac->asyncDev.dev.devId); -#endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - - hmac->innerHashKeyed = 0; /* tell update to start over if used again */ - - return 0; -} - -int NitroxHmacUpdate(Hmac* hmac, const byte* msg, word32 length) -{ - word16 add = (word16)length; - word32 total; - byte* tmp; - - if (length > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - if (hmac->innerHashKeyed == 0) { /* starting new */ - hmac->dataLen = 0; - hmac->innerHashKeyed = 1; - } - - total = add + hmac->dataLen; - if (total > WOLFSSL_MAX_16BIT) { - WOLFSSL_MSG("Too big msg for cavium hmac"); - return -1; - } - - tmp = XMALLOC(hmac->dataLen + add, NULL, DYNAMIC_TYPE_ASYNC_TMP); - if (tmp == NULL) { - WOLFSSL_MSG("Out of memory for cavium update"); - return -1; - } - if (hmac->dataLen) - XMEMCPY(tmp, hmac->data, hmac->dataLen); - XMEMCPY(tmp + hmac->dataLen, msg, add); - - hmac->dataLen += add; - XFREE(hmac->data, NULL, DYNAMIC_TYPE_ASYNC_TMP); - hmac->data = tmp; - - return 0; -} - -int NitroxHmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) -{ - hmac->macType = (byte)type; - - /* Determine Cavium HashType */ - switch(type) { - #ifndef NO_MD5 - case MD5: - hmac->type = MD5_TYPE; - break; - #endif - #ifndef NO_SHA - case SHA: - hmac->type = SHA1_TYPE; - break; - #endif - #ifndef NO_SHA256 - case SHA256: - #ifdef HAVE_CAVIUM_V - hmac->type = SHA2_SHA256; - #else - hmac->type = SHA256_TYPE; - #endif - break; - #endif - #ifdef HAVE_CAVIUM_V - #ifndef WOLFSSL_SHA512 - case SHA512: - hmac->type = SHA2_SHA512; - break; - #endif - #ifndef WOLFSSL_SHA384 - case SHA384: - hmac->type = SHA2_SHA384; - break; - #endif - #endif /* HAVE_CAVIUM_V */ - default: - WOLFSSL_MSG("unsupported cavium hmac type"); - break; - } - - hmac->innerHashKeyed = 0; /* should we key Startup flag */ - - hmac->keyLen = (word16)length; - /* store key in ipad */ - XMEMCPY(hmac->ipad, key, length); - - return 0; -} -#endif /* !NO_HMAC */ - - -#if !defined(HAVE_HASHDRBG) && !defined(NO_RC4) -void NitroxRngGenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - wolfssl_word offset = 0; - word32 requestId; - - while (sz > WOLFSSL_MAX_16BIT) { - word16 slen = (word16)WOLFSSL_MAX_16BIT; - #ifdef HAVE_CAVIUM_V - ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); - #else - ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - sz -= WOLFSSL_MAX_16BIT; - offset += WOLFSSL_MAX_16BIT; - } - if (sz) { - word16 slen = (word16)sz; - #ifdef HAVE_CAVIUM_V - ret = CspTrueRandom(rng->asyncDev.dev.devId, CAVIUM_BLOCKING, DMA_DIRECT_DIRECT, - CAVIUM_SSL_GRP, CAVIUM_DPORT, slen, output + offset, &requestId); - #else - ret = CspRandom(CAVIUM_BLOCKING, slen, output + offset, &requestId, - rng->asyncDev.dev.devId); - #endif - ret = NitroxTranslateResponseCode(ret); - if (ret != 0) { - return ret; - } - } -} -#endif /* !defined(HAVE_HASHDRBG) && !defined(NO_RC4) */ - - -#endif /* WOLFSSL_ASYNC_CRYPT */ - -#endif /* HAVE_CAVIUM */ diff --git a/wolfcrypt/src/port/intel/README.md b/wolfcrypt/src/port/intel/README.md new file mode 100644 index 000000000..4b5d971ba --- /dev/null +++ b/wolfcrypt/src/port/intel/README.md @@ -0,0 +1,3 @@ +# Intel QuickAssist Adapter Asynchronous Support + +Please contact wolfSSL at info@wolfssl.com to request an evaluation. diff --git a/wolfcrypt/src/port/nxp/ksdk_port.c b/wolfcrypt/src/port/nxp/ksdk_port.c index ac4d579b2..4c5853d7b 100644 --- a/wolfcrypt/src/port/nxp/ksdk_port.c +++ b/wolfcrypt/src/port/nxp/ksdk_port.c @@ -23,7 +23,6 @@ #include #endif -/* in case user set USE_FAST_MATH there */ #include #ifdef NO_INLINE #include @@ -33,8 +32,7 @@ #endif /* If FREESCALE_LTC_TFM or FREESCALE_LTC_ECC */ -#if (defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM)) ||\ - defined(FREESCALE_LTC_ECC) +#if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) #include #include @@ -42,12 +40,12 @@ #include #include -#define ERROR_OUT(err) { ret = (err); goto done; } +#define ERROR_OUT(res) { ret = (res); goto done; } int ksdk_port_init(void) { -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) +#if defined(FREESCALE_LTC_TFM) LTC_Init(LTC0); #endif @@ -56,8 +54,7 @@ int ksdk_port_init(void) /* LTC TFM */ -#if defined(USE_FAST_MATH) && defined(FREESCALE_LTC_TFM) -#include +#if defined(FREESCALE_LTC_TFM) /* Reverse array in memory (in place) */ static void ltc_reverse_array(uint8_t *src, size_t src_len) @@ -73,39 +70,52 @@ static void ltc_reverse_array(uint8_t *src, size_t src_len) } } -/* same as fp_to_unsigned_bin() with fp_reverse() skipped */ -static void fp_to_unsigned_lsb_bin(fp_int *a, unsigned char *b) +/* same as mp_to_unsigned_bin() with mp_reverse() skipped */ +static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b) { - fp_int t; + int res; + mp_int t; - fp_init_copy(&t, a); + res = mp_init_copy(&t, a); + if (res == MP_OKAY) { + res = mp_to_unsigned_bin_at_pos(0, &t, b); + if (res >= 0) + res = 0; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif + } - (void)fp_to_unsigned_bin_at_pos(0, &t, b); + return res; } -static void ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) +static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz) { + int res; uint16_t sz; sz = mp_unsigned_bin_size(A); - fp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ + res = mp_to_unsigned_lsb_bin(A, dst); /* result is lsbyte at lowest addr as required by LTC */ *psz = sz; + + return res; } /* these function are used by wolfSSL upper layers (like RSA) */ /* c = a * b */ -void fp_mul(fp_int *A, fp_int *B, fp_int *C) +int mp_mul(mp_int *A, mp_int *B, mp_int *C) { + int res = MP_OKAY; int szA, szB; - szA = fp_unsigned_bin_size(A); - szB = fp_unsigned_bin_size(B); + szA = mp_unsigned_bin_size(A); + szB = mp_unsigned_bin_size(B); /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call software mul */ if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) { int neg; - neg = (A->sign == B->sign) ? FP_ZPOS : FP_NEG; + neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG; /* unsigned multiply */ uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -115,16 +125,19 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB; - ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); - XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); + res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB); + if (res == MP_OKAY) { + XMEMSET(ptrC, 0xFF, LTC_MAX_INT_BYTES); - LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, - kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, - kLTC_PKHA_TimingEqualized); + LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, LTC_MAX_INT_BYTES, ptrB, &sizeB, + kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, + kLTC_PKHA_TimingEqualized); - ltc_reverse_array(ptrB, sizeB); - mp_read_unsigned_bin(C, ptrB, sizeB); + ltc_reverse_array(ptrB, sizeB); + res = mp_read_unsigned_bin(C, ptrB, sizeB); + } } /* fix sign */ @@ -138,52 +151,53 @@ void fp_mul(fp_int *A, fp_int *B, fp_int *C) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return; } else { - wolfcrypt_fp_mul(A, B, C); + res = wolfcrypt_mp_mul(A, B, C); } + return res; } /* c = a mod b, 0 <= c < b */ -int fp_mod(fp_int *a, fp_int *b, fp_int *c) +int mp_mod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; int neg; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* get sign for the result */ - neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* get remainder of unsigned a divided by unsigned b */ if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } /* fix sign */ @@ -198,26 +212,25 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mod(a, b, c); + res = wolfcrypt_mp_mod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* c = 1/a (mod b) for odd b only */ -int fp_invmod(fp_int *a, fp_int *b, fp_int *c) +int mp_invmod(mp_int *a, mp_int *b, mp_int *c) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) { #endif - int res = FP_OKAY; - uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -225,21 +238,23 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrA && ptrB && ptrC) { uint16_t sizeA, sizeB, sizeC; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - - if (kStatus_Success == - LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) - { - ltc_reverse_array(ptrC, sizeC); - mp_read_unsigned_bin(c, ptrC, sizeC); - } - else { - res = FP_VAL; + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) { + if (kStatus_Success == + LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, &sizeC, kLTC_PKHA_IntegerArith)) + { + ltc_reverse_array(ptrC, sizeC); + res = mp_read_unsigned_bin(c, ptrC, sizeC); + } + else { + res = MP_VAL; + } } } else { - res = FP_MEM; + res = MP_MEM; } c->sign = a->sign; @@ -252,85 +267,91 @@ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) if (ptrC) { XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT); } - return res; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_invmod(a, b, c); + res = wolfcrypt_mp_invmod(a, b, c); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* d = a * b (mod c) */ -int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - szA = fp_unsigned_bin_size(a); - szB = fp_unsigned_bin_size(b); - szC = fp_unsigned_bin_size(c); + szA = mp_unsigned_bin_size(a); + szB = mp_unsigned_bin_size(b); + szC = mp_unsigned_bin_size(c); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint8_t *ptrA = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrB = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrC = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); uint8_t *ptrD = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT); - /* if A or B is negative, substracta abs(A) or abs(B) from modulus to get positive integer representation of the + /* if A or B is negative, subtract abs(A) or abs(B) from modulus to get positive integer representation of the * same number */ - fp_init(&t); + res = mp_init(&t); if (a->sign) { - fp_add(a, c, &t); - fp_copy(&t, a); + if (res == MP_OKAY) + res = mp_add(a, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, a); } if (b->sign) { - fp_add(b, c, &t); - fp_copy(&t, b); + if (res == MP_OKAY) + res = mp_add(b, c, &t); + if (res == MP_OKAY) + res = mp_copy(&t, b); } - if (ptrA && ptrB && ptrC && ptrD) { + if (res == MP_OKAY && ptrA && ptrB && ptrC && ptrD) { uint16_t sizeA, sizeB, sizeC, sizeD; - ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); - ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); - ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); + res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC); /* (A*B)mod C = ((A mod C) * (B mod C)) mod C */ - if (LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrC, sizeC) >= 0) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrC, sizeC, ptrA, &sizeA, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if ((FP_OKAY == res) && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) + if (res == MP_OKAY && (LTC_PKHA_CompareBigNum(ptrB, sizeB, ptrC, sizeC) >= 0)) { if (kStatus_Success != LTC_PKHA_ModRed(LTC_BASE, ptrB, sizeB, ptrC, sizeC, ptrB, &sizeB, kLTC_PKHA_IntegerArith)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { if (kStatus_Success != LTC_PKHA_ModMul(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC, sizeC, ptrD, &sizeD, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized)) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { ltc_reverse_array(ptrD, sizeD); - mp_read_unsigned_bin(d, ptrD, sizeD); + res = mp_read_unsigned_bin(d, ptrD, sizeD); } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrA) { @@ -345,41 +366,45 @@ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) if (ptrD) { XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return wolfcrypt_fp_mulmod(a, b, c, d); + res = wolfcrypt_mp_mulmod(a, b, c, d); } #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } /* Y = G^X mod P */ -int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) +int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y) { + int res = MP_OKAY; #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) int szA, szB, szC; - fp_int tmp; - int err; + mp_int tmp; /* if G cannot fit into LTC_PKHA, reduce it */ - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); if (szA > LTC_MAX_INT_BYTES) { - fp_init(&tmp); - if ((err = fp_mod(G, P, &tmp)) != FP_OKAY) { - return err; + res = mp_init(&tmp); + if (res != MP_OKAY) + return res; + if ((res = mp_mod(G, P, &tmp)) != MP_OKAY) { + return res; } G = &tmp; - szA = fp_unsigned_bin_size(G); + szA = mp_unsigned_bin_size(G); } - szB = fp_unsigned_bin_size(X); - szC = fp_unsigned_bin_size(P); + szB = mp_unsigned_bin_size(X); + szC = mp_unsigned_bin_size(P); if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES) && (szC <= LTC_MAX_INT_BYTES)) { #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ - int res = FP_OKAY; - fp_int t; + mp_int t; uint16_t sizeG, sizeX, sizeP; uint8_t *ptrG = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); @@ -387,16 +412,20 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) uint8_t *ptrP = (uint8_t *)XMALLOC(LTC_MAX_INT_BYTES, 0, DYNAMIC_TYPE_BIGINT); /* if G is negative, add modulus to convert to positive number for LTC */ - fp_init(&t); + res = mp_init(&t); if (G->sign) { - fp_add(G, P, &t); - fp_copy(&t, G); + if (res == MP_OKAY) + res = mp_add(G, P, &t); + if (res == MP_OKAY) + res = mp_copy(&t, G); } - if (ptrG && ptrX && ptrP) { - ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); - ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); - ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); + if (res == MP_OKAY && ptrG && ptrX && ptrP) { + res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX); + if (res == MP_OKAY) + res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP); /* if number if greater that modulo, we must first reduce due to LTC requirement on modular exponentiaton */ /* it needs number less than modulus. */ @@ -405,29 +434,29 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) and then the modular exponentiation. */ /* if G >= P then */ - if (LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { + if (res == MP_OKAY && LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) { res = (int)LTC_PKHA_ModRed(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrG, &sizeG, kLTC_PKHA_IntegerArith); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } } - if (FP_OKAY == res) { + if (res == MP_OKAY) { res = (int)LTC_PKHA_ModExp(LTC_BASE, ptrG, sizeG, ptrP, sizeP, ptrX, sizeX, ptrP, &sizeP, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized); if (res != kStatus_Success) { - res = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(ptrP, sizeP); - mp_read_unsigned_bin(Y, ptrP, sizeP); + res = mp_read_unsigned_bin(Y, ptrP, sizeP); } } } else { - res = FP_MEM; + res = MP_MEM; } if (ptrG) { @@ -439,16 +468,24 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) if (ptrP) { XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT); } - return res; + #ifndef USE_FAST_MATH + mp_clear(&t); + #endif #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE) } else { - return _wolfcrypt_fp_exptmod(G, X, P, Y); + res = wolfcrypt_mp_exptmod(G, X, P, Y); } + +#ifndef USE_FAST_MATH + if (szA > LTC_MAX_INT_BYTES) + mp_clear(&tmp); +#endif #endif /* FREESCALE_LTC_TFM_RSA_4096_ENABLE */ + return res; } -#endif /* USE_FAST_MATH && FREESCALE_LTC_TFM */ +#endif /* FREESCALE_LTC_TFM */ /* ECC */ @@ -457,11 +494,12 @@ int _fp_exptmod(fp_int *G, fp_int *X, fp_int *P, fp_int *Y) /* convert from mp_int to LTC integer, as array of bytes of size sz. * if mp_int has less bytes than sz, add zero bytes at most significant byte positions. * This is when for example modulus is 32 bytes (P-256 curve) - * and mp_int has only 31 bytes, we add leading zeroes + * and mp_int has only 31 bytes, we add leading zeros * so that result array has 32 bytes, same as modulus (sz). */ -static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) +static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) { + int res; int szbin; int offset; @@ -480,10 +518,14 @@ static void ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz) XMEMSET(dst, 0, offset); /* convert mp_int to array of bytes */ - mp_to_unsigned_bin(a, dst + offset); + res = mp_to_unsigned_bin(a, dst + offset); - /* reverse array for LTC direct use */ - ltc_reverse_array(dst, sz); + if (res == MP_OKAY) { + /* reverse array for LTC direct use */ + ltc_reverse_array(dst, sz); + } + + return res; } /* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA driver functions */ @@ -636,8 +678,10 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, int szkbin; bool point_of_infinity; status_t status; + int res; (void)a; + (void)heap; uint8_t Gxbin[LTC_MAX_ECC_BITS / 8]; uint8_t Gybin[LTC_MAX_ECC_BITS / 8]; @@ -655,9 +699,14 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, szModulus = mp_unsigned_bin_size(modulus); szkbin = mp_unsigned_bin_size(k); - ltc_get_from_mp_int(kbin, k, szkbin); - ltc_get_from_mp_int(Gxbin, G->x, szModulus); - ltc_get_from_mp_int(Gybin, G->y, szModulus); + res = ltc_get_from_mp_int(kbin, k, szkbin); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gxbin, G->x, szModulus); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, G->y, szModulus); + + if (res != MP_OKAY) + return res; size = szModulus; /* find LTC friendly parameters for the selected curve */ @@ -671,25 +720,28 @@ int wc_ecc_mulmod_ex(mp_int *k, ecc_point *G, ecc_point *R, mp_int* a, status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith, &B, &point_of_infinity); if (status != kStatus_Success) { - return FP_VAL; + return MP_VAL; } ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(R->x, Gxbin, size); - mp_read_unsigned_bin(R->y, Gybin, size); - /* if k is negative, we compute the multiplication with abs(-k) - * with result (x, y) and modify the result to (x, -y) - */ - R->y->sign = k->sign; - mp_set(R->z, 1); + res = mp_read_unsigned_bin(R->x, Gxbin, size); + if (res == MP_OKAY) { + res = mp_read_unsigned_bin(R->y, Gybin, size); + /* if k is negative, we compute the multiplication with abs(-k) + * with result (x, y) and modify the result to (x, -y) + */ + R->y->sign = k->sign; + } + if (res == MP_OKAY) + res = mp_set(R->z, 1); - return MP_OKAY; + return res; } int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) { - int err; + int res; ltc_pkha_ecc_point_t A, B; int size; status_t status; @@ -704,15 +756,22 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) const uint8_t *r2modn; size = mp_unsigned_bin_size(m); + /* find LTC friendly parameters for the selected curve */ - if (0 != ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size)) { - err = ECC_BAD_ARG_E; + if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam, size) != 0) { + res = ECC_BAD_ARG_E; } else { - ltc_get_from_mp_int(Gxbin, mG->x, size); - ltc_get_from_mp_int(Gybin, mG->y, size); - ltc_get_from_mp_int(Qxbin, mQ->x, size); - ltc_get_from_mp_int(Qybin, mQ->y, size); + res = ltc_get_from_mp_int(Gxbin, mG->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Gybin, mG->y, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qxbin, mQ->x, size); + if (res == MP_OKAY) + res = ltc_get_from_mp_int(Qybin, mQ->y, size); + + if (res != MP_OKAY) + return res; A.X = Gxbin; A.Y = Gybin; @@ -723,18 +782,19 @@ int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m) status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn, aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A); if (status != kStatus_Success) { - err = FP_VAL; + res = MP_VAL; } else { ltc_reverse_array(Gxbin, size); ltc_reverse_array(Gybin, size); - mp_read_unsigned_bin(mR->x, Gxbin, size); - mp_read_unsigned_bin(mR->y, Gybin, size); - mp_set(mR->z, 1); - err = MP_OKAY; + res = mp_read_unsigned_bin(mR->x, Gxbin, size); + if (res == MP_OKAY) + res = mp_read_unsigned_bin(mR->y, Gybin, size); + if (res == MP_OKAY) + res = mp_set(mR->z, 1); } } - return err; + return res; } #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519) @@ -852,7 +912,7 @@ status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA, * * X mod 2 get from LSB bit0 */ - if ((status == kStatus_Success) && + if ((status == kStatus_Success) && ((bool)sign != (bool)(res[0] & 0x01u))) { status = LTC_PKHA_ModSub1(LTC_BASE, modbin, sizeof(modbin), res, @@ -1036,7 +1096,7 @@ int wc_curve25519(ECPoint *q, byte *n, const ECPoint *p, fsl_ltc_ecc_coordinate_ ltcPoint.X = &pIn.point[0]; ltcPoint.Y = &pIn.pointY[0]; - /* if input point P is on Curve25519 Montgomery curve, transform + /* if input point P is on Curve25519 Montgomery curve, transform it to Weierstrass equivalent */ if (type == kLTC_Curve25519) { LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint); @@ -1197,7 +1257,7 @@ status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn, Mx = (1 + Ey) * ModularArithmetic.invert(1 - Ey, prime) % prime My = (1 + Ey) * ModularArithmetic.invert((1 - Ey)*Ex, prime) % prime */ - /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + + /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) + (A * ModularArithmetic.invert(3*B, prime))) % prime Gy = (My * ModularArithmetic.invert(B, prime)) % prime */ @@ -1497,7 +1557,7 @@ status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a, uint8_t tempB[32] = {0}; status_t status; - /* Assume only b can be larger than modulus. It is called durind + /* Assume only b can be larger than modulus. It is called durind * wc_ed25519_sign_msg() where hram (=a) and nonce(=c) * have been reduced by LTC_PKHA_sc_reduce() * Thus reducing b only. @@ -1622,4 +1682,4 @@ status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn, #undef ERROR_OUT -#endif /* (USE_FAST_MATH && FREESCALE_LTC_TFM) || FREESCALE_LTC_ECC */ +#endif /* FREESCALE_LTC_TFM || FREESCALE_LTC_ECC */ diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 5b982c41d..cd8d2eed9 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -490,6 +490,9 @@ WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz) { + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + return BAD_FUNC_ARG; + } return AesAuthEncrypt(aes, out, in, sz, iv, ivSz, authTag, authTagSz, authIn, authInSz, AES_CFG_MODE_GCM_HY0CALC) ; } diff --git a/wolfcrypt/src/port/ti/ti-ccm.c b/wolfcrypt/src/port/ti/ti-ccm.c index abf4d602d..f4a4c6595 100644 --- a/wolfcrypt/src/port/ti/ti-ccm.c +++ b/wolfcrypt/src/port/ti/ti-ccm.c @@ -32,52 +32,63 @@ #include #include +#ifndef TI_DUMMY_BUILD #include "driverlib/sysctl.h" #include "driverlib/rom_map.h" #include "driverlib/rom.h" #ifndef SINGLE_THREADED #include - static wolfSSL_Mutex TI_CCM_Mutex ; + static wolfSSL_Mutex TI_CCM_Mutex; #endif +#endif /* TI_DUMMY_BUILD */ #define TIMEOUT 500000 -#define WAIT(stat) { volatile int i ; for(i=0; i #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -59,67 +59,68 @@ #define SHAMD5_ALGO_MD5 1 #define SHAMD5_ALGO_SHA1 2 #define SHAMD5_ALGO_SHA256 3 -bool wolfSSL_TI_CCMInit(void) { return true ; } +#define SHAMD5_ALGO_SHA224 4 #endif static int hashInit(wolfssl_TI_Hash *hash) { - if(!wolfSSL_TI_CCMInit())return 1 ; - hash->used = 0 ; - hash->msg = 0 ; - hash->len = 0 ; - return 0 ; + if (!wolfSSL_TI_CCMInit())return 1; + hash->used = 0; + hash->msg = 0; + hash->len = 0; + return 0; } static int hashUpdate(wolfssl_TI_Hash *hash, const byte* data, word32 len) { - void *p ; + void *p; - if((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; + if ((hash== NULL) || (data == NULL))return BAD_FUNC_ARG; - if(hash->len < hash->used+len) { - if(hash->msg == NULL) { + if (hash->len < hash->used+len) { + if (hash->msg == NULL) { p = XMALLOC(hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { p = XREALLOC(hash->msg, hash->used+len, NULL, DYNAMIC_TYPE_TMP_BUFFER); } - if(p == 0)return 1 ; - hash->msg = p ; - hash->len = hash->used+len ; - } - XMEMCPY(hash->msg+hash->used, data, len) ; - hash->used += len ; - return 0 ; + if (p == 0)return 1; + hash->msg = p; + hash->len = hash->used+len; + } + XMEMCPY(hash->msg+hash->used, data, len); + hash->used += len; + return 0; } static int hashGetHash(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - uint32_t h[16] ; +{ + uint32_t h[16]; #ifndef TI_DUMMY_BUILD - wolfSSL_TI_lockCCM() ; + wolfSSL_TI_lockCCM(); ROM_SHAMD5Reset(SHAMD5_BASE); ROM_SHAMD5ConfigSet(SHAMD5_BASE, algo); - ROM_SHAMD5DataProcess(SHAMD5_BASE, + ROM_SHAMD5DataProcess(SHAMD5_BASE, (uint32_t *)hash->msg, hash->used, h); - wolfSSL_TI_unlockCCM() ; + wolfSSL_TI_unlockCCM(); #else - (void) hash ; - (void) algo ; + (void) hash; + (void) algo; #endif - XMEMCPY(result, h, hsize) ; + XMEMCPY(result, h, hsize); - return 0 ; + return 0; } -static void hashRestorePos(wolfssl_TI_Hash *h1, wolfssl_TI_Hash *h2) { - h1->used = h2->used ; +static int hashCopy(wolfssl_TI_Hash *src, wolfssl_TI_Hash *dst) { + XMEMCPY(dst, src, sizeof(wolfssl_TI_Hash)); + return 0; } static int hashFinal(wolfssl_TI_Hash *hash, byte* result, word32 algo, word32 hsize) -{ - hashGetHash(hash, result, algo, hsize) ; +{ + hashGetHash(hash, result, algo, hsize); XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word32 hsize) @@ -153,166 +154,183 @@ static int hashHash(const byte* data, word32 len, byte* hash, word32 algo, word3 } static int hashFree(wolfssl_TI_Hash *hash) -{ +{ XFREE(hash->msg, NULL, DYNAMIC_TYPE_TMP_BUFFER); - hashInit(hash) ; - return 0 ; + hashInit(hash); + return 0; } #if !defined(NO_MD5) -WOLFSSL_API void wc_InitMd5(Md5* md5) +WOLFSSL_API int wc_InitMd5_ex(Md5* md5, void* heap, int devId) { if (md5 == NULL) - return ; - hashInit((wolfssl_TI_Hash *)md5) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)md5); } - -WOLFSSL_API void wc_Md5Update(Md5* md5, const byte* data, word32 len) +WOLFSSL_API int wc_InitMd5(Md5* md5) { - hashUpdate((wolfssl_TI_Hash *)md5, data, len) ; + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); } -WOLFSSL_API void wc_Md5Final(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5Update(Md5* md5, const byte* data, word32 len) { - hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashUpdate((wolfssl_TI_Hash *)md5, data, len); } -WOLFSSL_API void wc_Md5GetHash(Md5* md5, byte* hash) +WOLFSSL_API int wc_Md5Final(Md5* md5, byte* hash) { - hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } -WOLFSSL_API void wc_Md5RestorePos(Md5* m1, Md5* m2) { - hashRestorePos((wolfssl_TI_Hash *)m1, (wolfssl_TI_Hash *)m2) ; +WOLFSSL_API int wc_Md5GetHash(Md5* md5, byte* hash) +{ + return hashGetHash((wolfssl_TI_Hash *)md5, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); +} + +WOLFSSL_API int wc_Md5Copy(Md5* src, Md5* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_Md5Hash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_MD5, MD5_DIGEST_SIZE); } WOLFSSL_API void wc_Md5Free(Md5* md5) { - hashFree((wolfssl_TI_Hash *)md5) ; + hashFree((wolfssl_TI_Hash *)md5); } -#endif /* NO_MD5 */ +#endif /* !NO_MD5 */ #if !defined(NO_SHA) -WOLFSSL_API int wc_InitSha(Sha* sha) +WOLFSSL_API int wc_InitSha_ex(Md5* sha, void* heap, int devId) { if (sha == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha); +} +WOLFSSL_API int wc_InitSha(Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); } WOLFSSL_API int wc_ShaUpdate(Sha* sha, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha, data, len); } WOLFSSL_API int wc_ShaFinal(Sha* sha, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API int wc_ShaGetHash(Sha* sha, byte* hash) { - return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; + return hashGetHash(sha, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } -WOLFSSL_API void wc_ShaRestorePos(Sha* s1, Sha* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; +WOLFSSL_API int wc_ShaCopy(Sha* src, Sha* dst) { + return hashCopy((wolfssl_TI_Hash *)src, (wolfssl_TI_Hash *)dst); } WOLFSSL_API int wc_ShaHash(const byte*data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA1, SHA_DIGEST_SIZE); } WOLFSSL_API void wc_ShaFree(Sha* sha) { - hashFree((wolfssl_TI_Hash *)sha) ; + hashFree((wolfssl_TI_Hash *)sha); } -#endif /* NO_SHA */ +#endif /* !NO_SHA */ -#if defined(HAVE_SHA224) -WOLFSSL_API int wc_InitSha224(Sha224* sha224) +#if defined(WOLFSSL_SHA224) +WOLFSSL_API int wc_InitSha224_ex(Sha224* sha224, void* heap, int devId) { if (sha224 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha224) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha224); +} +WOLFSSL_API int wc_InitSha224(Sha224* sha224) +{ + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha224Update(Sha224* sha224, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha224, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha224, data, len); } WOLFSSL_API int wc_Sha224Final(Sha224* sha224, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224GetHash(Sha224* sha224, byte* hash) { - return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha224RestorePos(Sha224* s1, Sha224* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha224, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API int wc_Sha224Hash(const byte* data, word32 len, byte*hash) -{ - return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE) ; +{ + return hashHash(data, len, hash, SHAMD5_ALGO_SHA224, SHA224_DIGEST_SIZE); } WOLFSSL_API void wc_Sha224Free(Sha224* sha224) { - hashFree((wolfssl_TI_Hash *)sha224) ; + hashFree((wolfssl_TI_Hash *)sha224); } -#endif /* HAVE_SHA224 */ +#endif /* WOLFSSL_SHA224 */ #if !defined(NO_SHA256) -WOLFSSL_API int wc_InitSha256(Sha256* sha256) +WOLFSSL_API int wc_InitSha256_ex(Sha256* sha256, void* heap, int devId) { if (sha256 == NULL) - return 1 ; - return hashInit((wolfssl_TI_Hash *)sha256) ; + return 1; + (void)heap; + (void)devId; + return hashInit((wolfssl_TI_Hash *)sha256); +} + +WOLFSSL_API int wc_InitSha256(Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); } WOLFSSL_API int wc_Sha256Update(Sha256* sha256, const byte* data, word32 len) { - return hashUpdate((wolfssl_TI_Hash *)sha256, data, len) ; + return hashUpdate((wolfssl_TI_Hash *)sha256, data, len); } WOLFSSL_API int wc_Sha256Final(Sha256* sha256, byte* hash) { - return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashFinal((wolfssl_TI_Hash *)sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256GetHash(Sha256* sha256, byte* hash) { - return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; -} - -WOLFSSL_API void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { - hashRestorePos((wolfssl_TI_Hash *)s1, (wolfssl_TI_Hash *)s2) ; + return hashGetHash(sha256, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API int wc_Sha256Hash(const byte* data, word32 len, byte*hash) { - return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE) ; + return hashHash(data, len, hash, SHAMD5_ALGO_SHA256, SHA256_DIGEST_SIZE); } WOLFSSL_API void wc_Sha256Free(Sha256* sha256) { - hashFree((wolfssl_TI_Hash *)sha256) ; + hashFree((wolfssl_TI_Hash *)sha256); } -#endif +#endif /* !NO_SHA256 */ #endif diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 7f545ee92..c51e7d1f5 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -59,16 +59,6 @@ #include #endif -#ifndef WOLFSSL_HAVE_MIN -#define WOLFSSL_HAVE_MIN - - static INLINE word32 min(word32 a, word32 b) - { - return a > b ? b : a; - } - -#endif /* WOLFSSL_HAVE_MIN */ - #ifndef NO_SHA /* PBKDF1 needs at least SHA available */ @@ -100,10 +90,22 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, switch (hashType) { #ifndef NO_MD5 case MD5: - wc_InitMd5(&md5); - wc_Md5Update(&md5, passwd, pLen); - wc_Md5Update(&md5, salt, sLen); - wc_Md5Final(&md5, buffer); + ret = wc_InitMd5(&md5); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, passwd, pLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Update(&md5, salt, sLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } break; #endif /* NO_MD5 */ case SHA: @@ -124,8 +126,14 @@ int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, } #ifndef NO_MD5 else { - wc_Md5Update(&md5, buffer, hLen); - wc_Md5Final(&md5, buffer); + ret = wc_Md5Update(&md5, buffer, hLen); + if (ret != 0) { + return ret; + } + ret = wc_Md5Final(&md5, buffer); + if (ret != 0) { + return ret; + } } #endif } @@ -192,10 +200,11 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, return MEMORY_E; #endif - ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); - + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); if (ret == 0) { - while (kLen) { + ret = wc_HmacSetKey(&hmac, hashType, passwd, pLen); + + while (ret == 0 && kLen) { int currentLen; ret = wc_HmacUpdate(&hmac, salt, sLen); @@ -240,6 +249,7 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, kLen -= currentLen; i++; } + wc_HmacFree(&hmac); } #ifdef WOLFSSL_SMALL_STACK @@ -310,13 +320,28 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, case MD5: { Md5 md5; - wc_InitMd5(&md5); - wc_Md5Update(&md5, buffer, totalLen); - wc_Md5Final(&md5, Ai); + ret = wc_InitMd5(&md5); + if (ret != 0) { + break; + } + ret = wc_Md5Update(&md5, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_Md5Update(&md5, Ai, u); - wc_Md5Final(&md5, Ai); + ret = wc_Md5Update(&md5, Ai, u); + if (ret != 0) { + break; + } + ret = wc_Md5Final(&md5, Ai); + if (ret != 0) { + break; + } } } break; @@ -328,12 +353,24 @@ int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, ret = wc_InitSha(&sha); if (ret != 0) break; - wc_ShaUpdate(&sha, buffer, totalLen); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, buffer, totalLen); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } for (i = 1; i < iterations; i++) { - wc_ShaUpdate(&sha, Ai, u); - wc_ShaFinal(&sha, Ai); + ret = wc_ShaUpdate(&sha, Ai, u); + if (ret != 0) { + break; + } + ret = wc_ShaFinal(&sha, Ai); + if (ret != 0) { + break; + } } } break; @@ -619,7 +656,7 @@ static void scryptSalsa(word32* out, word32* in) out[i] = in[i] + x[i]; #else for (i = 0; i < 16; i++) - out[i] = ByteReverseWord32(in[i] + x[i]); + out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); #endif } @@ -769,15 +806,15 @@ int wc_scrypt(byte* output, const byte* passwd, int passLen, bSz = 128 * blockSize; blocksSz = bSz * parallel; - blocks = XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (blocks == NULL) goto end; /* Temporary for scryptROMix. */ - v = XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (v == NULL) goto end; /* Temporary for scryptBlockMix. */ - y = XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (y == NULL) goto end; diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c old mode 100755 new mode 100644 index 550d96503..1940bff1c --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -33,13 +33,6 @@ #include -#if defined(CUSTOM_RAND_GENERATE) && !defined(CUSTOM_RAND_TYPE) -/* To maintain compatibility the default return value from CUSTOM_RAND_GENERATE is byte */ -#define CUSTOM_RAND_TYPE byte -#endif - -#define RNG_HEALTH_TEST_CHECK_SIZE (SHA256_DIGEST_SIZE * 4) - #ifdef HAVE_FIPS int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) @@ -47,31 +40,37 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) return GenerateSeed(os, seed, sz); } -int wc_InitRng(WC_RNG* rng) +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + (void)heap; + (void)devId; + return InitRng_fips(rng); +} + +int wc_InitRng(WC_RNG* rng) { return InitRng_fips(rng); } -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) { return RNG_GenerateBlock_fips(rng, b, sz); } -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) { return RNG_GenerateByte(rng, b); } -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) +#ifdef HAVE_HASHDRBG int wc_FreeRng(WC_RNG* rng) { return FreeRng_fips(rng); } - int wc_RNG_HealthTest(int reseed, const byte* entropyA, word32 entropyASz, const byte* entropyB, word32 entropyBSz, @@ -80,113 +79,77 @@ int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) return RNG_HealthTest_fips(reseed, entropyA, entropyASz, entropyB, entropyBSz, output, outputSz); } -#endif /* HAVE_HASHDRBG || NO_RC4 */ +#endif /* HAVE_HASHDRBG */ + #else /* else build without fips */ + #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ + #include +#include -/* Allow custom RNG system */ -#ifdef CUSTOM_RAND_GENERATE_BLOCK - -int wc_InitRng_ex(WC_RNG* rng, void* heap) -{ - (void)rng; - (void)heap; - return 0; -} - -int wc_InitRng(WC_RNG* rng) -{ - return wc_InitRng_ex(rng, NULL); -} - -int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) -{ - (void)rng; - XMEMSET(output, 0, sz); - return CUSTOM_RAND_GENERATE_BLOCK(output, sz); -} - - -int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) -{ - return wc_RNG_GenerateBlock(rng, b, 1); -} - - -int wc_FreeRng(WC_RNG* rng) -{ - (void)rng; - return 0; -} - +#ifdef NO_INLINE + #include #else - -/* Use HASHDRGB with SHA256 */ -#if defined(HAVE_HASHDRBG) || defined(NO_RC4) - - #include - - #ifdef NO_INLINE - #include - #else - #define WOLFSSL_MISC_INCLUDED - #include - #endif -#endif /* HAVE_HASHDRBG || NO_RC4 */ + #define WOLFSSL_MISC_INCLUDED + #include +#endif #if defined(WOLFSSL_SGX) -#include