diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index 889ec4864..969a9d932 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -243,6 +243,64 @@ static const unsigned char dhg[] = #endif /* !NO_WOLFSSL_SERVER */ #endif /* !NO_DH */ +struct group_info { + word16 group; + const char *name; +}; + +static struct group_info groups[] = { + { WOLFSSL_ECC_SECP160K1, "ECC_SECP160K1" }, + { WOLFSSL_ECC_SECP160R1, "ECC_SECP160R1" }, + { WOLFSSL_ECC_SECP160R2, "ECC_SECP160R2" }, + { WOLFSSL_ECC_SECP192K1, "ECC_SECP192K1" }, + { WOLFSSL_ECC_SECP192R1, "ECC_SECP192R1" }, + { WOLFSSL_ECC_SECP224K1, "ECC_SECP224K1" }, + { WOLFSSL_ECC_SECP224R1, "ECC_SECP224R1" }, + { WOLFSSL_ECC_SECP256K1, "ECC_SECP256K1" }, + { WOLFSSL_ECC_SECP256R1, "ECC_SECP256R1" }, + { WOLFSSL_ECC_SECP384R1, "ECC_SECP384R1" }, + { WOLFSSL_ECC_SECP521R1, "ECC_SECP521R1" }, + { WOLFSSL_ECC_BRAINPOOLP256R1, "ECC_BRAINPOOLP256R1" }, + { WOLFSSL_ECC_BRAINPOOLP384R1, "ECC_BRAINPOOLP384R1" }, + { WOLFSSL_ECC_BRAINPOOLP512R1, "ECC_BRAINPOOLP512R1" }, + { WOLFSSL_ECC_X25519, "ECC_X25519" }, + { WOLFSSL_ECC_X448, "ECC_X448" }, + { WOLFSSL_FFDHE_2048, "FFDHE_2048" }, + { WOLFSSL_FFDHE_3072, "FFDHE_3072" }, + { WOLFSSL_FFDHE_4096, "FFDHE_4096" }, + { WOLFSSL_FFDHE_6144, "FFDHE_6144" }, + { WOLFSSL_FFDHE_8192, "FFDHE_8192" }, +#ifdef HAVE_LIBOQS + { WOLFSSL_NTRU_HPS_LEVEL1, "NTRU_HPS_LEVEL1" }, + { WOLFSSL_NTRU_HPS_LEVEL3, "NTRU_HPS_LEVEL3" }, + { WOLFSSL_NTRU_HPS_LEVEL5, "NTRU_HPS_LEVEL5" }, + { WOLFSSL_NTRU_HRSS_LEVEL3, "NTRU_HRSS_LEVEL3" }, + { WOLFSSL_SABER_LEVEL1, "SABER_LEVEL1" }, + { WOLFSSL_SABER_LEVEL3, "SABER_LEVEL3" }, + { WOLFSSL_SABER_LEVEL5, "SABER_LEVEL5" }, + { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" }, + { WOLFSSL_KYBER_LEVEL3, "KYBER_LEVEL3" }, + { WOLFSSL_KYBER_LEVEL5, "KYBER_LEVEL5" }, + { WOLFSSL_KYBER_90S_LEVEL1, "KYBER_90S_LEVEL1" }, + { WOLFSSL_KYBER_90S_LEVEL3, "KYBER_90S_LEVEL3" }, + { WOLFSSL_KYBER_90S_LEVEL5, "KYBER_90S_LEVEL5" }, + { WOLFSSL_P256_NTRU_HPS_LEVEL1, "P256_NTRU_HPS_LEVEL1" }, + { WOLFSSL_P384_NTRU_HPS_LEVEL3, "P384_NTRU_HPS_LEVEL3" }, + { WOLFSSL_P521_NTRU_HPS_LEVEL5, "P521_NTRU_HPS_LEVEL5" }, + { WOLFSSL_P384_NTRU_HRSS_LEVEL3, "P384_NTRU_HRSS_LEVEL3" }, + { WOLFSSL_P256_SABER_LEVEL1, "P256_SABER_LEVEL1" }, + { WOLFSSL_P384_SABER_LEVEL3, "P384_SABER_LEVEL3" }, + { WOLFSSL_P521_SABER_LEVEL5, "P521_SABER_LEVEL5" }, + { WOLFSSL_P256_KYBER_LEVEL1, "P256_KYBER_LEVEL1" }, + { WOLFSSL_P384_KYBER_LEVEL3, "P384_KYBER_LEVEL3" }, + { WOLFSSL_P521_KYBER_LEVEL5, "P521_KYBER_LEVEL5" }, + { WOLFSSL_P256_KYBER_90S_LEVEL1, "P256_KYBER_90S_LEVEL1" }, + { WOLFSSL_P384_KYBER_90S_LEVEL3, "P384_KYBER_90S_LEVEL3" }, + { WOLFSSL_P521_KYBER_90S_LEVEL5, "P521_KYBER_90S_LEVEL5" }, +#endif + { 0, NULL } +}; + #ifdef HAVE_PTHREAD typedef struct { unsigned char buf[MEM_BUFFER_SZ]; @@ -276,6 +334,7 @@ typedef struct { typedef struct { const char* cipher; + word16 group; const char* host; word32 port; int packetSize; /* The data payload size in the packet */ @@ -904,6 +963,14 @@ static int bench_tls_client(info_t* info) goto exit; } + if (info->group != 0) { + ret = wolfSSL_UseKeyShare(cli_ssl, info->group); + if (ret != WOLFSSL_SUCCESS) { + fprintf(stderr, "error setting client key share.\n"); + goto exit; + } + } + #ifdef WOLFSSL_DTLS if (info->doDTLS) { ret = wolfSSL_dtls_set_peer(cli_ssl, &info->serverAddr, @@ -1319,6 +1386,15 @@ static int bench_tls_server(info_t* info) fprintf(stderr, "error creating server object\n"); ret = MEMORY_E; goto exit; } + + if (info->group != 0) { + ret = wolfSSL_UseKeyShare(srv_ssl, info->group); + if (ret != WOLFSSL_SUCCESS) { + fprintf(stderr, "error setting server key share.\n"); + goto exit; + } + } + #ifdef WOLFSSL_DTLS if (info->doDTLS) { ret = wolfSSL_dtls_set_peer(srv_ssl, &info->clientAddr, @@ -1485,12 +1561,12 @@ static void* server_thread(void* args) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif -static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, int verbose) +static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, const char *group, int verbose) { const char* formatStr; if (verbose) { - formatStr = "wolfSSL %s Benchmark on %s:\n" + formatStr = "wolfSSL %s Benchmark on %s with group %s:\n" "\tTotal : %9d bytes\n" "\tNum Conns : %9d\n" "\tRx Total : %9.3f ms\n" @@ -1501,12 +1577,13 @@ static void print_stats(stats_t* wcStat, const char* desc, const char* cipher, i "\tConnect Avg : %9.3f ms\n"; } else { - formatStr = "%-6s %-33s %11d %9d %9.3f %9.3f %9.3f %9.3f %17.3f %15.3f\n"; + formatStr = "%-6s %-33s %-25s %11d %9d %9.3f %9.3f %9.3f %9.3f %17.3f %15.3f\n"; } fprintf(stderr, formatStr, desc, cipher, + group, wcStat->txTotal + wcStat->rxTotal, wcStat->connCount, wcStat->rxTime * 1000, @@ -1528,6 +1605,7 @@ static void Usage(void) fprintf(stderr, "-P Port (default %d)\n", BENCH_DEFAULT_PORT); fprintf(stderr, "-e List Every cipher suite available\n"); fprintf(stderr, "-i Show peer info\n"); + fprintf(stderr, "-g Run through each of the TLS 1.3 groups that are available\n"); fprintf(stderr, "-l Cipher suite list (: delimited)\n"); fprintf(stderr, "-t Time (seconds) to run each test (default %d)\n", BENCH_RUNTIME_SEC); fprintf(stderr, "-p The packet size in bytes [1-16kB] (default %d)\n", TEST_PACKET_SIZE); @@ -1558,6 +1636,54 @@ static void ShowCiphers(void) fprintf(stderr, "%s\n", ciphers); } +static int SetupSupportedGroups(int verbose) { + int i; + WOLFSSL_CTX* ctx = NULL; + WOLFSSL* ssl = NULL; + int ret = 0; + + if (ret == 0) { + ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()); + if (ctx == NULL) { + ret = -1; + } + } + + if (ret == 0) { + ssl = wolfSSL_new(ctx); + if (ssl == NULL) { + ret = -1; + } + } + + /* Determine which groups are actually supported. */ + for (i = 0; groups[i].name != NULL; i++) { + if (ret == 0) { + int uks_ret = wolfSSL_UseKeyShare(ssl, groups[i].group); + if (uks_ret == WOLFSSL_SUCCESS) { + if (verbose) { + printf("Will benchmark the following group; %s\n", + groups[i].name); + } + } else if (uks_ret == BAD_FUNC_ARG || uks_ret == NOT_COMPILED_IN) { + groups[i].group = 0; + if (verbose) { + printf("Will NOT benchmark the following group; %s\n", + groups[i].name); + } + } else { + ret = -1; + } + } + } + + if (ssl != NULL) + wolfSSL_free(ssl); + if (ctx != NULL) + wolfSSL_CTX_free(ctx); + return ret; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif @@ -1568,6 +1694,7 @@ int bench_tls(void* args) info_t *theadInfo = NULL, *info; stats_t cli_comb, srv_comb; int i; + int group_index; char *cipher, *next_cipher, *ciphers = NULL; int argc = 0; char** argv = NULL; @@ -1598,6 +1725,8 @@ int bench_tls(void* args) #ifdef WOLFSSL_DTLS int doDTLS = 0; #endif + int argDoGroups = 0; + if (args != NULL) { argc = ((func_args*)args)->argc; argv = ((func_args*)args)->argv; @@ -1608,7 +1737,7 @@ int bench_tls(void* args) wolfSSL_Init(); /* Parse command line arguments */ - while ((ch = mygetopt(argc, argv, "?" "udeil:p:t:vT:sch:P:mS:")) != -1) { + while ((ch = mygetopt(argc, argv, "?" "udeil:p:t:vT:sch:P:mS:g")) != -1) { switch (ch) { case '?' : Usage(); @@ -1640,6 +1769,10 @@ int bench_tls(void* args) ShowCiphers(); goto exit; + case 'g' : + argDoGroups = 1; + break; + case 'i' : argShowPeerInfo = 1; break; @@ -1717,6 +1850,12 @@ int bench_tls(void* args) cipher = ciphers; } + if (argDoGroups) { + if (SetupSupportedGroups(argShowVerbose) != 0) { + goto exit; + } + } + /* for server or client side only, only 1 thread is allowed */ if (argServerOnly || argClientOnly) { argThreadPairs = 1; @@ -1780,146 +1919,170 @@ int bench_tls(void* args) fprintf(stderr, "Cipher: %s\n", cipher); } - for (i=0; ihost = argHost; - info->port = argPort + i; /* threads must have separate ports */ - info->cipher = cipher; - info->packetSize = argTestPacketSize; + if (argDoGroups && groups[group_index].group == 0) { + /* Skip unsupported group. */ + continue; + } - info->runTimeSec = argRuntimeSec; - info->maxSize = argTestMaxSize; - info->showPeerInfo = argShowPeerInfo; - info->showVerbose = argShowVerbose; + for (i=0; ihost = argHost; + info->port = argPort + i; /* threads must have separate ports */ + info->cipher = cipher; + + if (argDoGroups && XSTRNCMP(theadInfo[0].cipher, "TLS13", 5) == 0) + info->group = groups[group_index].group; + else + info->group = 0; + + info->packetSize = argTestPacketSize; + + info->runTimeSec = argRuntimeSec; + info->maxSize = argTestMaxSize; + info->showPeerInfo = argShowPeerInfo; + info->showVerbose = argShowVerbose; #ifndef NO_WOLFSSL_SERVER - info->listenFd = listenFd; + info->listenFd = listenFd; #endif - info->client.sockFd = -1; - info->server.sockFd = -1; + info->client.sockFd = -1; + info->server.sockFd = -1; #ifdef WOLFSSL_DTLS - info->doDTLS = doDTLS; + info->doDTLS = doDTLS; #ifdef HAVE_PTHREAD - info->serverReady = 0; - if (argServerOnly || argClientOnly) { - info->clientOrserverOnly = 1; - } + info->serverReady = 0; + if (argServerOnly || argClientOnly) { + info->clientOrserverOnly = 1; + } #endif #endif - if (argClientOnly) { + if (argClientOnly) { #ifndef NO_WOLFSSL_CLIENT - ret = bench_tls_client(info); + ret = bench_tls_client(info); #endif - } - else if (argServerOnly) { + } + else if (argServerOnly) { #ifndef NO_WOLFSSL_SERVER - ret = bench_tls_server(info); + ret = bench_tls_server(info); #endif - } - else { + } + else { #ifdef HAVE_PTHREAD - info->useLocalMem = argLocalMem; - pthread_mutex_init(&info->to_server.mutex, NULL); - pthread_mutex_init(&info->to_client.mutex, NULL); + info->useLocalMem = argLocalMem; + pthread_mutex_init(&info->to_server.mutex, NULL); + pthread_mutex_init(&info->to_client.mutex, NULL); #ifdef WOLFSSL_DTLS - pthread_mutex_init(&info->dtls_mutex, NULL); - pthread_cond_init(&info->dtls_cond, NULL); + pthread_mutex_init(&info->dtls_mutex, NULL); + pthread_cond_init(&info->dtls_cond, NULL); #endif - pthread_cond_init(&info->to_server.cond, NULL); - pthread_cond_init(&info->to_client.cond, NULL); + pthread_cond_init(&info->to_server.cond, NULL); + pthread_cond_init(&info->to_client.cond, NULL); - pthread_create(&info->to_server.tid, NULL, server_thread, info); - pthread_create(&info->to_client.tid, NULL, client_thread, info); + pthread_create(&info->to_server.tid, NULL, server_thread, + info); + pthread_create(&info->to_client.tid, NULL, client_thread, + info); - /* State that we won't be joining this thread */ - pthread_detach(info->to_server.tid); - pthread_detach(info->to_client.tid); + /* State that we won't be joining this thread */ + pthread_detach(info->to_server.tid); + pthread_detach(info->to_client.tid); #endif + } } - } #ifdef HAVE_PTHREAD - /* For threading, wait for completion */ - if (!argClientOnly && !argServerOnly) { - /* Wait until threads are marked done */ - do { - doShutdown = 1; + /* For threading, wait for completion */ + if (!argClientOnly && !argServerOnly) { + /* Wait until threads are marked done */ + do { + doShutdown = 1; + + for (i = 0; i < argThreadPairs; ++i) { + info = &theadInfo[i]; + if (!info->to_client.done || !info->to_server.done) { + doShutdown = 0; + XSLEEP_MS(1000); /* Allow other threads to run */ + } - for (i = 0; i < argThreadPairs; ++i) { - info = &theadInfo[i]; - if (!info->to_client.done || !info->to_server.done) { - doShutdown = 0; - XSLEEP_MS(1000); /* Allow other threads to run */ } - + } while (!doShutdown); + if (argShowVerbose) { + fprintf(stderr, "Shutdown complete\n"); } - } while (!doShutdown); - if (argShowVerbose) { - fprintf(stderr, "Shutdown complete\n"); } - } #endif /* HAVE_PTHREAD */ - if (argShowVerbose) { - /* print results */ + const char *gname = theadInfo[0].group == 0 ? + "N/A" : groups[group_index].name; + if (argShowVerbose) { + /* print results */ + for (i = 0; i < argThreadPairs; ++i) { + info = &theadInfo[i]; + + fprintf(stderr, "\nThread %d\n", i); + #ifndef NO_WOLFSSL_SERVER + if (!argClientOnly) + print_stats(&info->server_stats, "Server", info->cipher, gname, 1); + #endif + #ifndef NO_WOLFSSL_CLIENT + if (!argServerOnly) + print_stats(&info->client_stats, "Client", info->cipher, gname, 1); + #endif + } + } + + /* print combined results for more than one thread */ + XMEMSET(&cli_comb, 0, sizeof(cli_comb)); + XMEMSET(&srv_comb, 0, sizeof(srv_comb)); + for (i = 0; i < argThreadPairs; ++i) { info = &theadInfo[i]; - fprintf(stderr, "\nThread %d\n", i); - #ifndef NO_WOLFSSL_SERVER - if (!argClientOnly) - print_stats(&info->server_stats, "Server", info->cipher, 1); - #endif - #ifndef NO_WOLFSSL_CLIENT - if (!argServerOnly) - print_stats(&info->client_stats, "Client", info->cipher, 1); - #endif + cli_comb.connCount += info->client_stats.connCount; + srv_comb.connCount += info->server_stats.connCount; + + cli_comb.connTime += info->client_stats.connTime; + srv_comb.connTime += info->server_stats.connTime; + + cli_comb.rxTotal += info->client_stats.rxTotal; + srv_comb.rxTotal += info->server_stats.rxTotal; + + cli_comb.rxTime += info->client_stats.rxTime; + srv_comb.rxTime += info->server_stats.rxTime; + + cli_comb.txTotal += info->client_stats.txTotal; + srv_comb.txTotal += info->server_stats.txTotal; + + cli_comb.txTime += info->client_stats.txTime; + srv_comb.txTime += info->server_stats.txTime; } - } - /* print combined results for more than one thread */ - XMEMSET(&cli_comb, 0, sizeof(cli_comb)); - XMEMSET(&srv_comb, 0, sizeof(srv_comb)); - - for (i = 0; i < argThreadPairs; ++i) { - info = &theadInfo[i]; - - cli_comb.connCount += info->client_stats.connCount; - srv_comb.connCount += info->server_stats.connCount; - - cli_comb.connTime += info->client_stats.connTime; - srv_comb.connTime += info->server_stats.connTime; - - cli_comb.rxTotal += info->client_stats.rxTotal; - srv_comb.rxTotal += info->server_stats.rxTotal; - - cli_comb.rxTime += info->client_stats.rxTime; - srv_comb.rxTime += info->server_stats.rxTime; - - cli_comb.txTotal += info->client_stats.txTotal; - srv_comb.txTotal += info->server_stats.txTotal; - - cli_comb.txTime += info->client_stats.txTime; - srv_comb.txTime += info->server_stats.txTime; - } - - if (argShowVerbose) { - fprintf(stderr, "Totals for %d Threads\n", argThreadPairs); - } - else { - fprintf(stderr, "%-6s %-33s %11s %9s %9s %9s %9s %9s %17s %15s\n", - "Side", "Cipher", "Total Bytes", "Num Conns", "Rx ms", "Tx ms", - "Rx MB/s", "Tx MB/s", "Connect Total ms", "Connect Avg ms"); + if (argShowVerbose) { + fprintf(stderr, "Totals for %d Threads\n", argThreadPairs); + } + else { + fprintf(stderr, "%-6s %-33s %-25s %11s %9s %9s %9s %9s %9s %17s %15s\n", + "Side", "Cipher", "Group", "Total Bytes", "Num Conns", "Rx ms", "Tx ms", + "Rx MB/s", "Tx MB/s", "Connect Total ms", "Connect Avg ms"); #ifndef NO_WOLFSSL_SERVER - if (!argClientOnly) - print_stats(&srv_comb, "Server", theadInfo[0].cipher, 0); + if (!argClientOnly) + print_stats(&srv_comb, "Server", theadInfo[0].cipher, gname, 0); #endif #ifndef NO_WOLFSSL_CLIENT - if (!argServerOnly) - print_stats(&cli_comb, "Client", theadInfo[0].cipher, 0); + if (!argServerOnly) + print_stats(&cli_comb, "Client", theadInfo[0].cipher, gname, 0); #endif + } + + if (!argDoGroups || theadInfo[0].group == 0) { + /* We only needed to do this once because they don't want to + * benchmarks groups or this isn't a TLS 1.3 cipher. */ + break; + } } /* target next cipher */