/* Free the SSL/TLS connection data. * * ctx The connection data. */ static void SSLConn_Free(SSLConn_CTX* ctx) { int i; ThreadData* threadData; if (ctx == NULL) return; for (i = 0; i < ctx->numThreads; i++) { threadData = &ctx->threadData[i]; while (threadData->sslConn != NULL) SSLConn_Close(ctx, threadData, threadData->sslConn); SSLConn_FreeSSLConn(threadData); WolfSSLCtx_Final(threadData->ctx); } free(ctx->threadData); free(ctx); }
/* Main entry point for the program. * * argc The count of command line arguments. * argv The command line arguments. * returns 0 on success and 1 otherwise. */ int main(int argc, char* argv[]) { socklen_t socketfd = -1; int ch; WOLFSSL_CTX* ctx = NULL; SSLConn_CTX* sslConnCtx; word16 port = wolfSSLPort; int resumeSession = 0; char* cipherList = NULL; char* ourCert = CLI_CERT; char* ourKey = CLI_KEY; char* verifyCert = CA_CERT; int version = SERVER_DEFAULT_VERSION; int numConns = SSL_NUM_CONN; int numBytesRead = NUM_READ_BYTES; int numBytesWrite = NUM_WRITE_BYTES; int maxBytes = MAX_BYTES; int maxConns = MAX_CONNECTIONS; int i; /* Parse the command line arguments. */ while ((ch = mygetopt(argc, argv, OPTIONS)) != -1) { switch (ch) { /* Help with command line options. */ case '?': Usage(); exit(EXIT_SUCCESS); /* Port number to connect to. */ case 'p': port = (word16)atoi(myoptarg); break; /* Version of SSL/TLS to use. */ case 'v': version = atoi(myoptarg); if (version < 0 || version > 3) { Usage(); exit(MY_EX_USAGE); } break; /* List of cipher suites to use. */ case 'l': cipherList = myoptarg; break; /* File name of client certificate for client authentication. */ case 'c': ourCert = myoptarg; break; /* File name of client private key for client authentication. */ case 'k': ourKey = myoptarg; break; /* File name of server certificate/CA for peer verification. */ case 'A': verifyCert = myoptarg; break; /* Resume sessions. */ case 'r': resumeSession = 1; break; /* Number of connections to make. */ case 'n': maxConns = atoi(myoptarg); if (maxConns < 0 || maxConns > 1000000) { Usage(); exit(MY_EX_USAGE); } maxBytes = 0; break; /* Number of conncurrent connections to use. */ case 'N': numConns = atoi(myoptarg); if (numConns < 0 || numConns > 1000000) { Usage(); exit(MY_EX_USAGE); } break; /* Number of bytes to read each call. */ case 'R': numBytesRead = atoi(myoptarg); if (numBytesRead <= 0) { Usage(); exit(MY_EX_USAGE); } break; /* Number of bytes to write each call. */ case 'W': numBytesWrite = atoi(myoptarg); if (numBytesWrite <= 0) { Usage(); exit(MY_EX_USAGE); } break; /* Maximum number of read and write bytes (separate counts). */ case 'B': maxBytes = atoi(myoptarg); if (maxBytes <= 0) { Usage(); exit(MY_EX_USAGE); } maxConns = 0; break; /* Unrecognized command line argument. */ default: Usage(); exit(MY_EX_USAGE); } } #ifdef DEBUG_WOLFSSL wolfSSL_Debugging_ON(); #endif /* Initialize wolfSSL */ wolfSSL_Init(); /* Initialize wolfSSL and create a context object. */ if (WolfSSLCtx_Init(version, ourCert, ourKey, verifyCert, cipherList, &ctx) == EXIT_FAILURE) exit(EXIT_FAILURE); /* Create SSL/TLS connection data object. */ sslConnCtx = SSLConn_New(numConns, numBytesRead, numBytesWrite, maxConns, maxBytes, resumeSession); if (sslConnCtx == NULL) exit(EXIT_FAILURE); /* Keep handling connections until all done. */ for (i = 0; !SSLConn_Done(sslConnCtx); i = (i + 1) % numConns) { SSLConn* sslConn = &sslConnCtx->sslConn[i]; /* Perform close if in CLOSE state. */ if (sslConn->state == CLOSE) { if (sslConnCtx->numConnections == 0) { WOLFSSL_CIPHER* cipher; cipher = wolfSSL_get_current_cipher(sslConn->ssl); printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); } SSLConn_Close(sslConnCtx, sslConn); } /* Create TCP connection and connect if in INIT state. */ if ((sslConn->state == INIT) && ((sslConnCtx->maxConnections <= 0) || (sslConnCtx->numCreated < sslConnCtx->maxConnections))) { if (CreateSocketConnect(port, &socketfd) == EXIT_FAILURE) { printf("ERROR: failed to connect to server\n"); exit(EXIT_FAILURE); } SSLConn_Connect(sslConnCtx, ctx, socketfd, sslConn); } #ifdef WOLFSSL_ASYNC_CRYPT if (sslConn->err == 4) { int ret; double start; start = current_time(1); ret = wolfSSL_AsyncPoll(sslConn->ssl, WOLF_POLL_FLAG_CHECK_HW); sslConnCtx->asyncTime += current_time(0) - start; if (ret < 0) { printf("ERROR: failed in async polling\n"); break; } if (ret == 0) continue; } sslConn->err = 0; #endif /* Handle other SSL states. */ if (sslConnCtx->totalTime == 0) sslConnCtx->totalTime = current_time(1); if (SSLConn_ReadWrite(sslConnCtx, sslConn) == EXIT_FAILURE) { if (sslConnCtx->maxConnections > 0) sslConn->state = CLOSE; } } sslConnCtx->totalTime = current_time(0) - sslConnCtx->totalTime; SSLConn_PrintStats(sslConnCtx); SSLConn_Free(sslConnCtx); WolfSSLCtx_Final(ctx); wolfSSL_Cleanup(); exit(EXIT_SUCCESS); }
/* Initialize the wolfSSL library and create a wolfSSL context. * * version The protocol version. * cert The server's certificate. * key The server's private key matching the certificate. * verifyCert The certificate for client authentication. * cipherList The list of negotiable ciphers. * wolfsslCtx The new wolfSSL context object. * returns EXIT_SUCCESS when a wolfSSL context object is created and * EXIT_FAILURE otherwise. */ static int WolfSSLCtx_Init(ThreadData* threadData, int version, int allowDowngrade, char* cert, char* key, char* verifyCert, char* cipherList) { wolfSSL_method_func method = NULL; method = SSL_GetMethod(version, allowDowngrade); if (method == NULL) return(EXIT_FAILURE); /* Create and initialize WOLFSSL_CTX structure */ if ((threadData->ctx = wolfSSL_CTX_new(method(NULL))) == NULL) { fprintf(stderr, "wolfSSL_CTX_new error.\n"); return(EXIT_FAILURE); } #ifdef WOLFSSL_ASYNC_CRYPT #ifndef WC_NO_ASYNC_THREADING if (wolfAsync_DevOpenThread(&threadData->devId, &threadData->thread_id) < 0) #else if (wolfAsync_DevOpen(&threadData->devId) < 0) #endif { fprintf(stderr, "Async device open failed\nRunning without async\n"); } wolfSSL_CTX_UseAsync(threadData->ctx, threadData->devId); #endif /* Load server certificate into WOLFSSL_CTX */ if (wolfSSL_CTX_use_certificate_file(threadData->ctx, cert, SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading %s, please check the file.\n", cert); WolfSSLCtx_Final(threadData); return(EXIT_FAILURE); } /* Load server key into WOLFSSL_CTX */ if (wolfSSL_CTX_use_PrivateKey_file(threadData->ctx, key, SSL_FILETYPE_PEM) != SSL_SUCCESS) { fprintf(stderr, "Error loading %s, please check the file.\n", key); WolfSSLCtx_Final(threadData); return(EXIT_FAILURE); } /* Setup client authentication. */ wolfSSL_CTX_set_verify(threadData->ctx, SSL_VERIFY_PEER, 0); if (wolfSSL_CTX_load_verify_locations(threadData->ctx, verifyCert, 0) != SSL_SUCCESS) { fprintf(stderr, "Error loading %s, please check the file.\n", verifyCert); WolfSSLCtx_Final(threadData); return(EXIT_FAILURE); } if (cipherList != NULL) { if (wolfSSL_CTX_set_cipher_list(threadData->ctx, cipherList) != SSL_SUCCESS) { fprintf(stderr, "Server can't set cipher list.\n"); WolfSSLCtx_Final(threadData); return(EXIT_FAILURE); } } #ifndef NO_DH SetDHCtx(threadData->ctx); #endif return EXIT_SUCCESS; }