/* * This function loads all the client/CA certificates and CRLs. Setup the TLS * layer and do all necessary magic. */ static CURLcode cyassl_connect_step1(struct connectdata *conn, int sockindex) { char error_buffer[CYASSL_MAX_ERROR_SZ]; char *ciphers; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; SSL_METHOD* req_method = NULL; curl_socket_t sockfd = conn->sock[sockindex]; #ifdef HAVE_SNI bool sni = FALSE; #define use_sni(x) sni = (x) #else #define use_sni(x) Curl_nop_stmt #endif if(connssl->state == ssl_connection_complete) return CURLE_OK; if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) { failf(data, "CyaSSL does not support to set maximum SSL/TLS version"); return CURLE_SSL_CONNECT_ERROR; } /* check to see if we've been told to use an explicit SSL/TLS version */ switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */ /* minimum protocol version is set later after the CTX object is created */ req_method = SSLv23_client_method(); #else infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, " "TLS 1.0 is used exclusively\n"); req_method = TLSv1_client_method(); #endif use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_0: #ifdef WOLFSSL_ALLOW_TLSV10 req_method = TLSv1_client_method(); use_sni(TRUE); #else failf(data, "CyaSSL does not support TLS 1.0"); return CURLE_NOT_BUILT_IN; #endif break; case CURL_SSLVERSION_TLSv1_1: req_method = TLSv1_1_client_method(); use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_2: req_method = TLSv1_2_client_method(); use_sni(TRUE); break; case CURL_SSLVERSION_TLSv1_3: #ifdef WOLFSSL_TLS13 req_method = wolfTLSv1_3_client_method(); use_sni(TRUE); break; #else failf(data, "CyaSSL: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; #endif case CURL_SSLVERSION_SSLv3: #ifdef WOLFSSL_ALLOW_SSLV3 req_method = SSLv3_client_method(); use_sni(FALSE); #else failf(data, "CyaSSL does not support SSLv3"); return CURLE_NOT_BUILT_IN; #endif break; case CURL_SSLVERSION_SSLv2: failf(data, "CyaSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } if(!req_method) { failf(data, "SSL: couldn't create a method!"); return CURLE_OUT_OF_MEMORY; } if(BACKEND->ctx) SSL_CTX_free(BACKEND->ctx); BACKEND->ctx = SSL_CTX_new(req_method); if(!BACKEND->ctx) { failf(data, "SSL: couldn't create a context!"); return CURLE_OUT_OF_MEMORY; } switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: #if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */ /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever minimum version of TLS was built in and at least TLS 1.0. For later library versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so we have this short circuit evaluation to find the minimum supported TLS version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion because only the former will work before the user's CTX callback is called. */ if((wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1) != 1) && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_1) != 1) && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_2) != 1) #ifdef WOLFSSL_TLS13 && (wolfSSL_CTX_SetMinVersion(BACKEND->ctx, WOLFSSL_TLSV1_3) != 1) #endif ) { failf(data, "SSL: couldn't set the minimum protocol version"); return CURLE_SSL_CONNECT_ERROR; } #endif break; } ciphers = SSL_CONN_CONFIG(cipher_list); if(ciphers) { if(!SSL_CTX_set_cipher_list(BACKEND->ctx, ciphers)) { failf(data, "failed setting cipher list: %s", ciphers); return CURLE_SSL_CIPHER; } infof(data, "Cipher selection: %s\n", ciphers); } #ifndef NO_FILESYSTEM /* load trusted cacert */ if(SSL_CONN_CONFIG(CAfile)) { if(1 != SSL_CTX_load_verify_locations(BACKEND->ctx, SSL_CONN_CONFIG(CAfile), SSL_CONN_CONFIG(CApath))) { if(SSL_CONN_CONFIG(verifypeer)) { /* Fail if we insist on successfully verifying the server. */ failf(data, "error setting certificate verify locations:\n" " CAfile: %s\n CApath: %s", SSL_CONN_CONFIG(CAfile)? SSL_CONN_CONFIG(CAfile): "none", SSL_CONN_CONFIG(CApath)? SSL_CONN_CONFIG(CApath) : "none"); return CURLE_SSL_CACERT_BADFILE; } else { /* Just continue with a warning if no strict certificate verification is required. */ infof(data, "error setting certificate verify locations," " continuing anyway:\n"); } } else { /* Everything is fine. */ infof(data, "successfully set certificate verify locations:\n"); } infof(data, " CAfile: %s\n" " CApath: %s\n", SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile): "none", SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath): "none"); } /* Load the client certificate, and private key */ if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) { int file_type = do_file_type(SSL_SET_OPTION(cert_type)); if(SSL_CTX_use_certificate_file(BACKEND->ctx, SSL_SET_OPTION(cert), file_type) != 1) { failf(data, "unable to use client certificate (no key or wrong pass" " phrase?)"); return CURLE_SSL_CONNECT_ERROR; } file_type = do_file_type(SSL_SET_OPTION(key_type)); if(SSL_CTX_use_PrivateKey_file(BACKEND->ctx, SSL_SET_OPTION(key), file_type) != 1) { failf(data, "unable to set private key"); return CURLE_SSL_CONNECT_ERROR; } } #endif /* !NO_FILESYSTEM */ /* SSL always tries to verify the peer, this only says whether it should * fail to connect if the verification fails, or if it should continue * anyway. In the latter case the result of the verification is checked with * SSL_get_verify_result() below. */ SSL_CTX_set_verify(BACKEND->ctx, SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER: SSL_VERIFY_NONE, NULL); #ifdef HAVE_SNI if(sni) { struct in_addr addr4; #ifdef ENABLE_IPV6 struct in6_addr addr6; #endif const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; size_t hostname_len = strlen(hostname); if((hostname_len < USHRT_MAX) && (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) && #ifdef ENABLE_IPV6 (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) && #endif (CyaSSL_CTX_UseSNI(BACKEND->ctx, CYASSL_SNI_HOST_NAME, hostname, (unsigned short)hostname_len) != 1)) { infof(data, "WARNING: failed to configure server name indication (SNI) " "TLS extension\n"); } } #endif #ifdef HAVE_SUPPORTED_CURVES /* CyaSSL/wolfSSL does not send the supported ECC curves ext automatically: https://github.com/wolfSSL/wolfssl/issues/366 The supported curves below are those also supported by OpenSSL 1.0.2 and in the same order. */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x17); /* secp256r1 */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x19); /* secp521r1 */ CyaSSL_CTX_UseSupportedCurve(BACKEND->ctx, 0x18); /* secp384r1 */ #endif /* give application a chance to interfere with SSL set up. */ if(data->set.ssl.fsslctx) { CURLcode result = CURLE_OK; result = (*data->set.ssl.fsslctx)(data, BACKEND->ctx, data->set.ssl.fsslctxp); if(result) { failf(data, "error signaled by ssl ctx callback"); return result; } } #ifdef NO_FILESYSTEM else if(SSL_CONN_CONFIG(verifypeer)) { failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built" " with \"no filesystem\". Either disable peer verification" " (insecure) or if you are building an application with libcurl you" " can load certificates via CURLOPT_SSL_CTX_FUNCTION."); return CURLE_SSL_CONNECT_ERROR; } #endif /* Let's make an SSL structure */ if(BACKEND->handle) SSL_free(BACKEND->handle); BACKEND->handle = SSL_new(BACKEND->ctx); if(!BACKEND->handle) { failf(data, "SSL: couldn't create a context (handle)!"); return CURLE_OUT_OF_MEMORY; } #ifdef HAVE_ALPN if(conn->bits.tls_enable_alpn) { char protocols[128]; *protocols = '\0'; /* wolfSSL's ALPN protocol name list format is a comma separated string of protocols in descending order of preference, eg: "h2,http/1.1" */ #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ","); infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1); infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); if(wolfSSL_UseALPN(BACKEND->handle, protocols, (unsigned)strlen(protocols), WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) { failf(data, "SSL: failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } } #endif /* HAVE_ALPN */ /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *ssl_sessionid = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) { /* we got a session id, use it! */ if(!SSL_set_session(BACKEND->handle, ssl_sessionid)) { Curl_ssl_sessionid_unlock(conn); failf(data, "SSL: SSL_set_session failed: %s", ERR_error_string(SSL_get_error(BACKEND->handle, 0), error_buffer)); return CURLE_SSL_CONNECT_ERROR; } /* Informational message */ infof(data, "SSL re-using session ID\n"); } Curl_ssl_sessionid_unlock(conn); } /* pass the raw socket into the SSL layer */ if(!SSL_set_fd(BACKEND->handle, (int)sockfd)) { failf(data, "SSL: SSL_set_fd failed"); return CURLE_SSL_CONNECT_ERROR; } connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
THREAD_RETURN CYASSL_THREAD server_test(void* args) { SOCKET_T sockfd = 0; SOCKET_T clientfd = 0; SSL_METHOD* method = 0; SSL_CTX* ctx = 0; SSL* ssl = 0; char msg[] = "I hear you fa shizzle!"; char input[80]; int idx; int ch; int version = SERVER_DEFAULT_VERSION; int doCliCertCheck = 1; int useAnyAddr = 0; word16 port = wolfSSLPort; int usePsk = 0; int useAnon = 0; int doDTLS = 0; int needDH = 0; int useNtruKey = 0; int nonBlocking = 0; int trackMemory = 0; int fewerPackets = 0; int pkCallbacks = 0; int serverReadyFile = 0; int wc_shutdown = 0; int resume = 0; /* do resume, and resume count */ int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; int ret; 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 argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; #ifndef NO_PSK int sendPskIdentityHint = 1; #endif #ifdef HAVE_SNI char* sniHostName = NULL; #endif #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA verifyCert = (char*)cliEccCert; ourCert = (char*)eccCert; ourKey = (char*)eccKey; #endif (void)trackMemory; (void)pkCallbacks; (void)needDH; (void)ourKey; (void)ourCert; (void)ourDhParam; (void)verifyCert; (void)useNtruKey; (void)doCliCertCheck; (void)minDhKeyBits; (void)alpnList; (void)alpn_opt; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); #endif while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPIp:v:l:A:c:k:Z:S:oO:D:L:")) != -1) { switch (ch) { case '?' : Usage(); exit(EXIT_SUCCESS); case 'd' : doCliCertCheck = 0; break; case 'b' : useAnyAddr = 1; break; case 's' : usePsk = 1; break; case 't' : #ifdef USE_WOLFSSL_MEMORY trackMemory = 1; #endif break; case 'n' : useNtruKey = 1; break; case 'u' : doDTLS = 1; break; case 'f' : fewerPackets = 1; break; case 'R' : serverReadyFile = 1; break; case 'r' : #ifndef NO_SESSION_CACHE resume = 1; #endif break; case 'P' : #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; case 'p' : port = (word16)atoi(myoptarg); #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) if (port == 0) err_sys("port number cannot be 0"); #endif break; case 'w' : wc_shutdown = 1; break; case 'v' : version = atoi(myoptarg); if (version < 0 || version > 3) { Usage(); exit(MY_EX_USAGE); } break; case 'l' : cipherList = myoptarg; break; case 'A' : verifyCert = myoptarg; break; case 'c' : ourCert = myoptarg; break; case 'k' : ourKey = myoptarg; break; case 'D' : #ifndef NO_DH ourDhParam = myoptarg; #endif break; case 'Z' : #ifndef NO_DH minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); exit(MY_EX_USAGE); } #endif break; case 'N': nonBlocking = 1; break; case 'S' : #ifdef HAVE_SNI sniHostName = myoptarg; #endif break; case 'o' : #ifdef HAVE_OCSP useOcsp = 1; #endif break; case 'O' : #ifdef HAVE_OCSP useOcsp = 1; ocspUrl = myoptarg; #endif break; case 'a' : #ifdef HAVE_ANON useAnon = 1; #endif break; case 'I': #ifndef NO_PSK sendPskIdentityHint = 0; #endif break; case 'L' : #ifdef HAVE_ALPN alpnList = myoptarg; if (alpnList[0] == 'C' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; else if (alpnList[0] == 'F' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; else { Usage(); exit(MY_EX_USAGE); } alpnList += 2; #endif break; default: Usage(); exit(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) version = CLIENT_DTLS_DEFAULT_VERSION; else version = CLIENT_DEFAULT_VERSION; } else { if (doDTLS) { if (version == 3) version = -2; else version = -1; } } #ifdef USE_CYASSL_MEMORY if (trackMemory) InitMemoryTracker(); #endif switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 case 0: method = SSLv3_server_method(); break; #endif #ifndef NO_TLS case 1: method = TLSv1_server_method(); break; case 2: method = TLSv1_1_server_method(); break; #endif #endif #ifndef NO_TLS case 3: method = TLSv1_2_server_method(); break; #endif #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS case -1: method = DTLSv1_server_method(); break; #endif case -2: method = DTLSv1_2_server_method(); break; #endif default: err_sys("Bad SSL version"); } if (method == NULL) err_sys("unable to get method"); ctx = SSL_CTX_new(method); if (ctx == NULL) err_sys("unable to get ctx"); #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) if (TicketInit() != 0) err_sys("unable to setup Session Ticket Key context"); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif if (cipherList) if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 1"); #ifdef CYASSL_LEANPSK usePsk = 1; #endif #if defined(NO_RSA) && !defined(HAVE_ECC) usePsk = 1; #endif if (fewerPackets) CyaSSL_CTX_set_group_messages(ctx); #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (!usePsk && !useAnon) { if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server cert file, check file and run from" " wolfSSL home dir"); } #endif #ifndef NO_DH wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); #endif #ifdef HAVE_NTRU if (useNtruKey) { if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) != SSL_SUCCESS) err_sys("can't load ntru key file, " "Please run from wolfSSL home dir"); } #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (!useNtruKey && !usePsk && !useAnon) { if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server private key file, check file and run " "from wolfSSL home dir"); } #endif if (usePsk) { #ifndef NO_PSK SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); if (sendPskIdentityHint == 1) SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); if (cipherList == NULL) { const char *defaultCipherList; #if defined(HAVE_AESGCM) && !defined(NO_DH) defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; needDH = 1; #elif defined(HAVE_NULL_CIPHER) defaultCipherList = "PSK-NULL-SHA256"; #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 2"); } #endif } if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 4"); } #endif } #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) /* if not using PSK, verify peer with certs */ if (doCliCertCheck && usePsk == 0 && useAnon == 0) { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0); if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); } #endif #if defined(CYASSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS) err_sys("server can't set cipher list 3"); } #endif #ifdef HAVE_SNI if (sniHostName) if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS) err_sys("UseSNI failed"); #endif while (1) { /* allow resume option */ if (resume > 1) { /* already did listen, just do accept */ if (doDTLS == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); } else { tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); clientfd = sockfd; } #ifdef USE_WINDOWS_API if (clientfd == INVALID_SOCKET) err_sys("tcp accept failed"); #else if (clientfd == -1) err_sys("tcp accept failed"); #endif } ssl = SSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL"); #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif #ifdef HAVE_CRL CyaSSL_EnableCRL(ssl, 0); CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON); CyaSSL_SetCRL_Cb(ssl, CRL_CallBack); #endif #ifdef HAVE_OCSP if (useOcsp) { if (ocspUrl != NULL) { CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE | CYASSL_OCSP_URL_OVERRIDE); } else CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE); } #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) SetupPkCallbacks(ctx, ssl); #endif if (resume < 2) { /* do listen and accept */ tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS, serverReadyFile); } SSL_set_fd(ssl, clientfd); #ifdef HAVE_ALPN if (alpnList != NULL) { printf("ALPN accepted protocols list : %s\n", alpnList); wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif #ifdef WOLFSSL_DTLS if (doDTLS) { SOCKADDR_IN_T cliaddr; byte b[1500]; int n; socklen_t len = sizeof(cliaddr); /* For DTLS, peek at the next datagram so we can get the client's * address and set it into the ssl object later to generate the * cookie. */ n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, (struct sockaddr*)&cliaddr, &len); if (n <= 0) err_sys("recvfrom failed"); wolfSSL_dtls_set_peer(ssl, &cliaddr, len); } #endif if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) { #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* repick suites with DHE, higher priority than PSK */ #endif } #ifndef CYASSL_CALLBACKS if (nonBlocking) { CyaSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&clientfd); NonBlockingSSL_Accept(ssl); } else if (SSL_accept(ssl) != SSL_SUCCESS) { int err = SSL_get_error(ssl, 0); char buffer[CYASSL_MAX_ERROR_SZ]; printf("error = %d, %s\n", err, ERR_error_string(err, buffer)); err_sys("SSL_accept failed"); } #else NonBlockingSSL_Accept(ssl); #endif showPeer(ssl); #ifdef HAVE_ALPN if (alpnList != NULL) { int err; char *protocol_name = NULL; word16 protocol_nameSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); if (err == SSL_SUCCESS) printf("Sent ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); else if (err == SSL_ALPN_NOT_FOUND) printf("No ALPN response sent (no match)\n"); else printf("Getting ALPN protocol name failed\n"); } #endif idx = SSL_read(ssl, input, sizeof(input)-1); if (idx > 0) { input[idx] = 0; printf("Client message: %s\n", input); } else if (idx < 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)) err_sys("SSL_write failed"); #if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX) os_dly_wait(500) ; #elif defined (CYASSL_TIRTOS) Task_yield(); #endif if (doDTLS == 0) { ret = SSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ } SSL_free(ssl); if (resume == 1) { CloseSocket(clientfd); resume++; /* only do one resume for testing */ continue; } break; /* out of while loop, done with normal and resume option */ } SSL_CTX_free(ctx); CloseSocket(clientfd); CloseSocket(sockfd); ((func_args*)args)->return_code = 0; #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) ecc_fp_free(); /* free per thread cache */ #endif #ifdef USE_WOLFSSL_MEMORY if (trackMemory) ShowMemoryTracker(); #endif #ifdef CYASSL_TIRTOS fdCloseSession(Task_self()); #endif #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) TicketCleanup(); #endif #ifndef CYASSL_TIRTOS return 0; #endif }
THREAD_RETURN WOLFSSL_THREAD client_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; WOLFSSL_METHOD* method = 0; WOLFSSL_CTX* ctx = 0; WOLFSSL* ssl = 0; WOLFSSL* sslResume = 0; WOLFSSL_SESSION* session = 0; char resumeMsg[32] = "resuming wolfssl!"; int resumeSz = (int)strlen(resumeMsg); char msg[32] = "hello wolfssl!"; /* GET may make bigger */ char reply[80]; int input; int msgSz = (int)strlen(msg); word16 port = wolfSSLPort; char* host = (char*)wolfSSLIP; const char* domain = "localhost"; /* can't default to www.wolfssl.com because can't tell if we're really going there to detect old chacha-poly */ int ch; int version = CLIENT_INVALID_VERSION; int usePsk = 0; int useAnon = 0; int sendGET = 0; int benchmark = 0; int throughput = 0; int doDTLS = 0; int matchName = 0; int doPeerCheck = 1; int nonBlocking = 0; int resumeSession = 0; int wc_shutdown = 0; int disableCRL = 0; int externalTest = 0; int ret; int scr = 0; /* allow secure renegotiation */ int forceScr = 0; /* force client initiaed scr */ int trackMemory = 0; int useClientCert = 1; int fewerPackets = 0; int atomicUser = 0; int pkCallbacks = 0; int overrideDateErrors = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; char* alpnList = NULL; unsigned char alpn_opt = 0; char* cipherList = NULL; const char* verifyCert = caCert; const char* ourCert = cliCert; const char* ourKey = cliKey; #ifdef HAVE_SNI char* sniHostName = NULL; #endif #ifdef HAVE_MAX_FRAGMENT byte maxFragment = 0; #endif #ifdef HAVE_TRUNCATED_HMAC byte truncatedHMAC = 0; #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) byte statusRequest = 0; #endif #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA verifyCert = (char*)eccCert; ourCert = (char*)cliEccCert; ourKey = (char*)cliEccKey; #endif (void)resumeSz; (void)session; (void)sslResume; (void)trackMemory; (void)atomicUser; (void)pkCallbacks; (void)scr; (void)forceScr; (void)ourKey; (void)ourCert; (void)verifyCert; (void)useClientCert; (void)overrideDateErrors; (void)disableCRL; (void)minDhKeyBits; (void)alpnList; (void)alpn_opt; StackTrap(); #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:")) != -1) { switch (ch) { case '?' : Usage(); exit(EXIT_SUCCESS); case 'g' : sendGET = 1; break; case 'd' : doPeerCheck = 0; break; case 'e' : ShowCiphers(); exit(EXIT_SUCCESS); case 'D' : overrideDateErrors = 1; break; case 'C' : #ifdef HAVE_CRL disableCRL = 1; #endif break; case 'u' : doDTLS = 1; break; case 's' : usePsk = 1; break; case 't' : #ifdef USE_WOLFSSL_MEMORY trackMemory = 1; #endif break; case 'm' : matchName = 1; break; case 'x' : useClientCert = 0; break; case 'X' : externalTest = 1; break; case 'f' : fewerPackets = 1; break; case 'U' : #ifdef ATOMIC_USER atomicUser = 1; #endif break; case 'P' : #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; case 'h' : host = myoptarg; domain = myoptarg; break; case 'p' : port = (word16)atoi(myoptarg); #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API) if (port == 0) err_sys("port number cannot be 0"); #endif break; case 'v' : version = atoi(myoptarg); if (version < 0 || version > 3) { Usage(); exit(MY_EX_USAGE); } break; case 'V' : ShowVersions(); exit(EXIT_SUCCESS); case 'l' : cipherList = myoptarg; break; case 'A' : verifyCert = myoptarg; break; case 'c' : ourCert = myoptarg; break; case 'k' : ourKey = myoptarg; break; case 'Z' : #ifndef NO_DH minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); exit(MY_EX_USAGE); } #endif break; case 'b' : benchmark = atoi(myoptarg); if (benchmark < 0 || benchmark > 1000000) { Usage(); exit(MY_EX_USAGE); } break; case 'B' : throughput = atoi(myoptarg); if (throughput <= 0) { Usage(); exit(MY_EX_USAGE); } break; case 'N' : nonBlocking = 1; break; case 'r' : resumeSession = 1; break; case 'w' : wc_shutdown = 1; break; case 'R' : #ifdef HAVE_SECURE_RENEGOTIATION scr = 1; #endif break; case 'i' : #ifdef HAVE_SECURE_RENEGOTIATION scr = 1; forceScr = 1; #endif break; case 'z' : #ifndef WOLFSSL_LEANPSK wolfSSL_GetObjectSize(); #endif break; case 'S' : #ifdef HAVE_SNI sniHostName = myoptarg; #endif break; case 'F' : #ifdef HAVE_MAX_FRAGMENT maxFragment = atoi(myoptarg); if (maxFragment < WOLFSSL_MFL_2_9 || maxFragment > WOLFSSL_MFL_2_13) { Usage(); exit(MY_EX_USAGE); } #endif break; case 'T' : #ifdef HAVE_TRUNCATED_HMAC truncatedHMAC = 1; #endif break; case 'W' : #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) statusRequest = atoi(myoptarg); #endif break; case 'o' : #ifdef HAVE_OCSP useOcsp = 1; #endif break; case 'O' : #ifdef HAVE_OCSP useOcsp = 1; ocspUrl = myoptarg; #endif break; case 'a' : #ifdef HAVE_ANON useAnon = 1; #endif break; case 'L' : #ifdef HAVE_ALPN alpnList = myoptarg; if (alpnList[0] == 'C' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; else if (alpnList[0] == 'F' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; else { Usage(); exit(MY_EX_USAGE); } alpnList += 2; #endif break; default: Usage(); exit(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ #endif /* !WOLFSSL_VXWORKS */ if (externalTest) { /* detect build cases that wouldn't allow test against wolfssl.com */ int done = 0; (void)done; #ifdef NO_RSA done = 1; #endif /* www.globalsign.com does not respond to ipv6 ocsp requests */ #if defined(TEST_IPV6) && defined(HAVE_OCSP) done = 1; #endif /* www.globalsign.com has limited supported cipher suites */ #if defined(NO_AES) && defined(HAVE_OCSP) done = 1; #endif /* www.globalsign.com only supports static RSA or ECDHE with AES */ /* We cannot expect users to have on static RSA so test for ECC only * as some users will most likely be on 32-bit systems where ECC * is not enabled by default */ #if defined(HAVE_OCSP) && !defined(HAVE_ECC) done = 1; #endif #ifndef NO_PSK done = 1; #endif #ifdef NO_SHA done = 1; /* external cert chain most likely has SHA */ #endif #if !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) if (!XSTRNCMP(domain, "www.google.com", 14) || !XSTRNCMP(domain, "www.wolfssl.com", 15)) { done = 1; /* google/wolfssl need ECDHE or static RSA */ } #endif #if !defined(WOLFSSL_SHA384) if (!XSTRNCMP(domain, "www.wolfssl.com", 15)) { done = 1; /* wolfssl need sha384 for cert chain verify */ } #endif #if !defined(HAVE_AESGCM) && defined(NO_AES) && \ !(defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) done = 1; /* need at least on of these for external tests */ #endif if (done) { printf("external test can't be run in this mode"); ((func_args*)args)->return_code = 0; exit(EXIT_SUCCESS); } } /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) version = CLIENT_DTLS_DEFAULT_VERSION; else version = CLIENT_DEFAULT_VERSION; } else { if (doDTLS) { if (version == 3) version = -2; else version = -1; } } #ifdef USE_WOLFSSL_MEMORY if (trackMemory) InitMemoryTracker(); #endif switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 case 0: method = wolfSSLv3_client_method(); break; #endif #ifndef NO_TLS case 1: method = wolfTLSv1_client_method(); break; case 2: method = wolfTLSv1_1_client_method(); break; #endif /* NO_TLS */ #endif /* NO_OLD_TLS */ #ifndef NO_TLS case 3: method = wolfTLSv1_2_client_method(); break; #endif #ifdef WOLFSSL_DTLS #ifndef NO_OLD_TLS case -1: method = wolfDTLSv1_client_method(); break; #endif case -2: method = wolfDTLSv1_2_client_method(); break; #endif default: err_sys("Bad SSL version"); break; } if (method == NULL) err_sys("unable to get method"); ctx = wolfSSL_CTX_new(method); if (ctx == NULL) err_sys("unable to get ctx"); if (cipherList) { if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("client can't set cipher list 1"); } #ifdef WOLFSSL_LEANPSK usePsk = 1; #endif #if defined(NO_RSA) && !defined(HAVE_ECC) usePsk = 1; #endif if (fewerPackets) wolfSSL_CTX_set_group_messages(ctx); #ifndef NO_DH wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); #endif if (usePsk) { #ifndef NO_PSK wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); if (cipherList == NULL) { const char *defaultCipherList; #if defined(HAVE_AESGCM) && !defined(NO_DH) defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; #elif defined(HAVE_NULL_CIPHER) defaultCipherList = "PSK-NULL-SHA256"; #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) !=SSL_SUCCESS) err_sys("client can't set cipher list 2"); } #endif useClientCert = 0; } if (useAnon) { #ifdef HAVE_ANON if (cipherList == NULL) { wolfSSL_CTX_allow_anon_cipher(ctx); if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS) err_sys("client can't set cipher list 4"); } #endif useClientCert = 0; } #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if defined(WOLFSSL_SNIFFER) if (cipherList == NULL) { /* don't use EDH, can't sniff tmp keys */ if (wolfSSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS) { err_sys("client can't set cipher list 3"); } } #endif #ifdef HAVE_OCSP if (useOcsp) { if (ocspUrl != NULL) { wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE | WOLFSSL_OCSP_URL_OVERRIDE); } else wolfSSL_CTX_EnableOCSP(ctx, 0); } #endif #ifdef USER_CA_CB wolfSSL_CTX_SetCACb(ctx, CaCb); #endif #ifdef VERIFY_CALLBACK wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (useClientCert){ if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS) err_sys("can't load client cert file, check file and run from" " wolfSSL home dir"); if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load client private key file, check file and run " "from wolfSSL home dir"); } if (!usePsk && !useAnon) { if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #ifdef HAVE_ECC /* load ecc verify too, echoserver uses it by default w/ ecc */ if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); #endif /* HAVE_ECC */ } #endif /* !NO_FILESYSTEM && !NO_CERTS */ #if !defined(NO_CERTS) if (!usePsk && !useAnon && doPeerCheck == 0) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); if (!usePsk && !useAnon && overrideDateErrors == 1) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb); #endif #ifdef HAVE_CAVIUM wolfSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID); #endif #ifdef HAVE_SNI if (sniHostName) if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS) err_sys("UseSNI failed"); #endif #ifdef HAVE_MAX_FRAGMENT if (maxFragment) if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS) err_sys("UseMaxFragment failed"); #endif #ifdef HAVE_TRUNCATED_HMAC if (truncatedHMAC) if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) err_sys("UseTruncatedHMAC failed"); #endif #ifdef HAVE_SESSION_TICKET if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) err_sys("UseSessionTicket failed"); #endif if (benchmark) { ((func_args*)args)->return_code = ClientBenchmarkConnections(ctx, host, port, doDTLS, benchmark, resumeSession); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } if(throughput) { ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, doDTLS, throughput); wolfSSL_CTX_free(ctx); exit(EXIT_SUCCESS); } #if defined(WOLFSSL_MDK_ARM) wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); #endif ssl = wolfSSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL object"); #ifdef HAVE_SUPPORTED_CURVES /* add curves to supported curves extension */ if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP256R1) != SSL_SUCCESS) { err_sys("unable to set curve secp256r1"); } if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP384R1) != SSL_SUCCESS) { err_sys("unable to set curve secp384r1"); } if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP521R1) != SSL_SUCCESS) { err_sys("unable to set curve secp521r1"); } if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP224R1) != SSL_SUCCESS) { err_sys("unable to set curve secp224r1"); } if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP192R1) != SSL_SUCCESS) { err_sys("unable to set curve secp192r1"); } if (wolfSSL_UseSupportedCurve(ssl, WOLFSSL_ECC_SECP160R1) != SSL_SUCCESS) { err_sys("unable to set curve secp160r1"); } #endif #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); #endif #ifdef HAVE_ALPN if (alpnList != NULL) { printf("ALPN accepted protocols list : %s\n", alpnList); wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (statusRequest) { switch (statusRequest) { case WOLFSSL_CSR_OCSP: if (wolfSSL_UseOCSPStapling(ssl, WOLFSSL_CSR_OCSP, WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) err_sys("UseCertificateStatusRequest failed"); break; } wolfSSL_CTX_EnableOCSP(ctx, 0); } #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 if (statusRequest) { switch (statusRequest) { case WOLFSSL_CSR2_OCSP: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP, WOLFSSL_CSR2_OCSP_USE_NONCE) != SSL_SUCCESS) err_sys("UseCertificateStatusRequest failed"); break; case WOLFSSL_CSR2_OCSP_MULTI: if (wolfSSL_UseOCSPStaplingV2(ssl, WOLFSSL_CSR2_OCSP_MULTI, 0) != SSL_SUCCESS) err_sys("UseCertificateStatusRequest failed"); break; } wolfSSL_CTX_EnableOCSP(ctx, 0); } #endif tcp_connect(&sockfd, host, port, doDTLS, ssl); wolfSSL_set_fd(ssl, sockfd); #ifdef HAVE_CRL if (disableCRL == 0) { if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) err_sys("can't enable crl check"); if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS) err_sys("can't load crl, check crlfile and date validity"); if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) err_sys("can't set crl callback"); } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) err_sys("can't enable secure renegotiation"); } #endif #ifdef ATOMIC_USER if (atomicUser) SetupAtomicUser(ctx, ssl); #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) SetupPkCallbacks(ctx, ssl); #endif if (matchName && doPeerCheck) wolfSSL_check_domain_name(ssl, domain); #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { wolfSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&sockfd); NonBlockingSSL_Connect(ssl); } else if (wolfSSL_connect(ssl) != SSL_SUCCESS) { /* see note at top of README */ int err = wolfSSL_get_error(ssl, 0); char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); err_sys("SSL_connect failed"); /* if you're getting an error here */ } #else timeout.tv_sec = 2; timeout.tv_usec = 0; NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif showPeer(ssl); #ifdef HAVE_ALPN if (alpnList != NULL) { int err; char *protocol_name = NULL; word16 protocol_nameSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); if (err == SSL_SUCCESS) printf("Received ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); else if (err == SSL_ALPN_NOT_FOUND) printf("No ALPN response received (no match with server)\n"); else printf("Getting ALPN protocol name failed\n"); } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr && forceScr) { if (nonBlocking) { printf("not doing secure renegotiation on example with" " nonblocking yet"); } else { if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) { int err = wolfSSL_get_error(ssl, 0); char buffer[WOLFSSL_MAX_ERROR_SZ]; printf("err = %d, %s\n", err, wolfSSL_ERR_error_string(err, buffer)); err_sys("wolfSSL_Rehandshake failed"); } } } #endif /* HAVE_SECURE_RENEGOTIATION */ if (sendGET) { printf("SSL connect ok, sending GET...\n"); msgSz = 28; strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz); msg[msgSz] = '\0'; resumeSz = msgSz; strncpy(resumeMsg, "GET /index.html HTTP/1.0\r\n\r\n", resumeSz); resumeMsg[resumeSz] = '\0'; } if (wolfSSL_write(ssl, msg, msgSz) != msgSz) err_sys("SSL_write failed"); input = wolfSSL_read(ssl, reply, sizeof(reply)-1); if (input > 0) { reply[input] = 0; printf("Server response: %s\n", reply); if (sendGET) { /* get html */ while (1) { input = wolfSSL_read(ssl, reply, sizeof(reply)-1); if (input > 0) { reply[input] = 0; printf("%s\n", reply); } else break; } } } else if (input < 0) { int readErr = wolfSSL_get_error(ssl, 0); if (readErr != SSL_ERROR_WANT_READ) err_sys("wolfSSL_read failed"); } #ifndef NO_SESSION_CACHE if (resumeSession) { session = wolfSSL_get_session(ssl); sslResume = wolfSSL_new(ctx); if (sslResume == NULL) err_sys("unable to get SSL object"); } #endif if (doDTLS == 0) { /* don't send alert after "break" command */ ret = wolfSSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(ssl); /* bidirectional shutdown */ } #ifdef ATOMIC_USER if (atomicUser) FreeAtomicUser(ssl); #endif wolfSSL_free(ssl); CloseSocket(sockfd); #ifndef NO_SESSION_CACHE if (resumeSession) { if (doDTLS) { #ifdef USE_WINDOWS_API Sleep(500); #elif defined(WOLFSSL_TIRTOS) Task_sleep(1); #else sleep(1); #endif } tcp_connect(&sockfd, host, port, doDTLS, sslResume); wolfSSL_set_fd(sslResume, sockfd); #ifdef HAVE_ALPN if (alpnList != NULL) { printf("ALPN accepted protocols list : %s\n", alpnList); wolfSSL_UseALPN(sslResume, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif #ifdef HAVE_SECURE_RENEGOTIATION if (scr) { if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS) err_sys("can't enable secure renegotiation"); } #endif wolfSSL_set_session(sslResume, session); #ifdef HAVE_SESSION_TICKET wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB, (void*)"resumed session"); #endif #ifndef WOLFSSL_CALLBACKS if (nonBlocking) { wolfSSL_set_using_nonblock(sslResume, 1); tcp_set_nonblocking(&sockfd); NonBlockingSSL_Connect(sslResume); } else if (wolfSSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed"); #else timeout.tv_sec = 2; timeout.tv_usec = 0; NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */ #endif showPeer(sslResume); if (wolfSSL_session_reused(sslResume)) printf("reused session id\n"); else printf("didn't reuse session id!!!\n"); #ifdef HAVE_ALPN if (alpnList != NULL) { int err; char *protocol_name = NULL; word16 protocol_nameSz = 0; printf("Sending ALPN accepted list : %s\n", alpnList); err = wolfSSL_ALPN_GetProtocol(sslResume, &protocol_name, &protocol_nameSz); if (err == SSL_SUCCESS) printf("Received ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); else if (err == SSL_ALPN_NOT_FOUND) printf("Not received ALPN response (no match with server)\n"); else printf("Getting ALPN protocol name failed\n"); } #endif if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz) err_sys("SSL_write failed"); if (nonBlocking) { /* give server a chance to bounce a message back to client */ #ifdef USE_WINDOWS_API Sleep(500); #elif defined(WOLFSSL_TIRTOS) Task_sleep(1); #else sleep(1); #endif } input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); if (input > 0) { reply[input] = 0; printf("Server resume response: %s\n", reply); if (sendGET) { /* get html */ while (1) { input = wolfSSL_read(sslResume, reply, sizeof(reply)-1); if (input > 0) { reply[input] = 0; printf("%s\n", reply); } else break; } } } else if (input < 0) { int readErr = wolfSSL_get_error(ssl, 0); if (readErr != SSL_ERROR_WANT_READ) err_sys("wolfSSL_read failed"); } /* try to send session break */ wolfSSL_write(sslResume, msg, msgSz); ret = wolfSSL_shutdown(sslResume); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) wolfSSL_shutdown(sslResume); /* bidirectional shutdown */ wolfSSL_free(sslResume); CloseSocket(sockfd); } #endif /* NO_SESSION_CACHE */ wolfSSL_CTX_free(ctx); ((func_args*)args)->return_code = 0; #ifdef USE_WOLFSSL_MEMORY if (trackMemory) ShowMemoryTracker(); #endif /* USE_WOLFSSL_MEMORY */ #if !defined(WOLFSSL_TIRTOS) return 0; #endif }
static void test_wolfSSL_UseALPN_params(void) { /* "http/1.1" */ char http1[] = {0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31}; /* "spdy/1" */ char spdy1[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x31}; /* "spdy/2" */ char spdy2[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x32}; /* "spdy/3" */ char spdy3[] = {0x73, 0x70, 0x64, 0x79, 0x2f, 0x33}; char buff[256]; word32 idx; WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); WOLFSSL *ssl = wolfSSL_new(ctx); AssertNotNull(ctx); AssertNotNull(ssl); /* error cases */ AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(NULL, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); AssertIntNE(SSL_SUCCESS, wolfSSL_UseALPN(ssl, NULL, 0, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* success case */ /* http1 only */ AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, http1, sizeof(http1), WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* http1, spdy1 */ memcpy(buff, http1, sizeof(http1)); idx = sizeof(http1); buff[idx++] = ','; memcpy(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* http1, spdy2, spdy1 */ memcpy(buff, http1, sizeof(http1)); idx = sizeof(http1); buff[idx++] = ','; memcpy(buff+idx, spdy2, sizeof(spdy2)); idx += sizeof(spdy2); buff[idx++] = ','; memcpy(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_FAILED_ON_MISMATCH)); /* spdy3, http1, spdy2, spdy1 */ memcpy(buff, spdy3, sizeof(spdy3)); idx = sizeof(spdy3); buff[idx++] = ','; memcpy(buff+idx, http1, sizeof(http1)); idx += sizeof(http1); buff[idx++] = ','; memcpy(buff+idx, spdy2, sizeof(spdy2)); idx += sizeof(spdy2); buff[idx++] = ','; memcpy(buff+idx, spdy1, sizeof(spdy1)); idx += sizeof(spdy1); AssertIntEQ(SSL_SUCCESS, wolfSSL_UseALPN(ssl, buff, idx, WOLFSSL_ALPN_CONTINUE_ON_MISMATCH)); wolfSSL_free(ssl); wolfSSL_CTX_free(ctx); }
THREAD_RETURN CYASSL_THREAD server_test(void* args) { SOCKET_T sockfd = WOLFSSL_SOCKET_INVALID; SOCKET_T clientfd = WOLFSSL_SOCKET_INVALID; wolfSSL_method_func method = NULL; SSL_CTX* ctx = 0; SSL* ssl = 0; #ifndef WOLFSSL_ALT_TEST_STRINGS const char msg[] = "I hear you fa shizzle!"; #else const char msg[] = "I hear you fa shizzle!\n"; #endif char input[80]; int ch; int version = SERVER_DEFAULT_VERSION; int doCliCertCheck = 1; int useAnyAddr = 0; word16 port = wolfSSLPort; int usePsk = 0; int usePskPlus = 0; int useAnon = 0; int doDTLS = 0; 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 echoData = 0; int throughput = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; short minRsaKeyBits = DEFAULT_MIN_RSAKEY_BITS; short minEccKeyBits = DEFAULT_MIN_ECCKEY_BITS; int doListen = 1; int crlFlags = 0; int ret; int err = 0; char* serverReadyFile = NULL; 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; tcp_ready* readySignal = NULL; int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; #ifdef WOLFSSL_TRUST_PEER_CERT const char* trustCert = NULL; #endif #ifndef NO_PSK int sendPskIdentityHint = 1; #endif #ifdef HAVE_SNI char* sniHostName = NULL; #endif #ifdef HAVE_OCSP int useOcsp = 0; char* ocspUrl = NULL; #endif #ifdef HAVE_WNR const char* wnrConfigFile = wnrConfig; #endif #ifdef WOLFSSL_STATIC_MEMORY #if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \ || defined(SESSION_CERTS) /* big enough to handle most cases including session certs */ byte memory[204000]; #else byte memory[80000]; #endif byte memoryIO[34500]; /* max of 17k for IO buffer (TLS packet can be 16k) */ WOLFSSL_MEM_CONN_STATS ssl_stats; #endif ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA verifyCert = (char*)cliEccCert; ourCert = (char*)eccCert; ourKey = (char*)eccKey; #endif (void)pkCallbacks; (void)needDH; (void)ourKey; (void)ourCert; (void)ourDhParam; (void)verifyCert; (void)useNtruKey; (void)doCliCertCheck; (void)minDhKeyBits; (void)minRsaKeyBits; (void)minEccKeyBits; (void)alpnList; (void)alpn_opt; (void)crlFlags; (void)readySignal; #ifdef CYASSL_TIRTOS fdOpenSession(Task_self()); #endif #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else while ((ch = mygetopt(argc, argv, "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { switch (ch) { case '?' : Usage(); exit(EXIT_SUCCESS); case 'd' : doCliCertCheck = 0; break; case 'b' : useAnyAddr = 1; break; case 's' : usePsk = 1; break; case 'j' : usePskPlus = 1; break; case 't' : #ifdef USE_WOLFSSL_MEMORY trackMemory = 1; #endif break; case 'n' : useNtruKey = 1; break; case 'u' : doDTLS = 1; break; case 'f' : fewerPackets = 1; break; case 'R' : serverReadyFile = myoptarg; break; case 'r' : #ifndef NO_SESSION_CACHE resume = 1; #endif break; case 'P' : #ifdef HAVE_PK_CALLBACKS pkCallbacks = 1; #endif break; case 'p' : port = (word16)atoi(myoptarg); break; case 'w' : wc_shutdown = 1; break; case 'v' : version = atoi(myoptarg); if (version < 0 || version > 3) { Usage(); exit(MY_EX_USAGE); } break; case 'l' : cipherList = myoptarg; break; case 'A' : verifyCert = myoptarg; break; case 'c' : ourCert = myoptarg; break; case 'k' : ourKey = myoptarg; break; case 'D' : #ifndef NO_DH ourDhParam = myoptarg; #endif break; case 'Z' : #ifndef NO_DH minDhKeyBits = atoi(myoptarg); if (minDhKeyBits <= 0 || minDhKeyBits > 16000) { Usage(); exit(MY_EX_USAGE); } #endif break; case 'N': nonBlocking = 1; break; case 'S' : #ifdef HAVE_SNI sniHostName = myoptarg; #endif break; case 'o' : #ifdef HAVE_OCSP useOcsp = 1; #endif break; case 'O' : #ifdef HAVE_OCSP useOcsp = 1; ocspUrl = myoptarg; #endif break; case 'a' : #ifdef HAVE_ANON useAnon = 1; #endif break; case 'I': #ifndef NO_PSK sendPskIdentityHint = 0; #endif break; case 'L' : #ifdef HAVE_ALPN alpnList = myoptarg; if (alpnList[0] == 'C' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_CONTINUE_ON_MISMATCH; else if (alpnList[0] == 'F' && alpnList[1] == ':') alpn_opt = WOLFSSL_ALPN_FAILED_ON_MISMATCH; else { Usage(); exit(MY_EX_USAGE); } alpnList += 2; #endif break; case 'i' : loopIndefinitely = 1; break; case 'e' : echoData = 1; break; case 'B': throughput = atoi(myoptarg); if (throughput <= 0) { Usage(); exit(MY_EX_USAGE); } break; #ifdef WOLFSSL_TRUST_PEER_CERT case 'E' : trustCert = myoptarg; break; #endif case 'q' : #ifdef HAVE_WNR wnrConfigFile = myoptarg; #endif break; default: Usage(); exit(MY_EX_USAGE); } } myoptind = 0; /* reset for test cases */ #endif /* !WOLFSSL_VXWORKS */ /* sort out DTLS versus TLS versions */ if (version == CLIENT_INVALID_VERSION) { if (doDTLS) version = CLIENT_DTLS_DEFAULT_VERSION; else version = CLIENT_DEFAULT_VERSION; } else { if (doDTLS) { if (version == 3) version = -2; else version = -1; } } #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"); #endif switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 case 0: method = wolfSSLv3_server_method_ex; break; #endif #ifndef NO_TLS case 1: method = wolfTLSv1_server_method_ex; break; case 2: method = wolfTLSv1_1_server_method_ex; break; #endif #endif #ifndef NO_TLS case 3: method = wolfTLSv1_2_server_method_ex; break; #endif #ifdef CYASSL_DTLS #ifndef NO_OLD_TLS case -1: method = wolfDTLSv1_server_method_ex; break; #endif case -2: method = wolfDTLSv1_2_server_method_ex; break; #endif default: err_sys("Bad SSL version"); } if (method == NULL) err_sys("unable to get method"); #ifdef WOLFSSL_STATIC_MEMORY #ifdef DEBUG_WOLFSSL /* print off helper buffer sizes for use with static memory * printing to stderr incase of debug mode turned on */ fprintf(stderr, "static memory management size = %d\n", wolfSSL_MemoryPaddingSz()); fprintf(stderr, "calculated optimum general buffer size = %d\n", wolfSSL_StaticBufferSz(memory, sizeof(memory), 0)); fprintf(stderr, "calculated optimum IO buffer size = %d\n", wolfSSL_StaticBufferSz(memoryIO, sizeof(memoryIO), WOLFMEM_IO_POOL_FIXED)); #endif /* DEBUG_WOLFSSL */ if (wolfSSL_CTX_load_static_memory(&ctx, method, memory, sizeof(memory),0,1) != SSL_SUCCESS) err_sys("unable to load static memory and create ctx"); /* load in a buffer for IO */ if (wolfSSL_CTX_load_static_memory(&ctx, NULL, memoryIO, sizeof(memoryIO), WOLFMEM_IO_POOL_FIXED | WOLFMEM_TRACK_STATS, 1) != SSL_SUCCESS) err_sys("unable to load static memory and create ctx"); #else ctx = SSL_CTX_new(method(NULL)); #endif if (ctx == NULL) err_sys("unable to get ctx"); #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) if (TicketInit() != 0) err_sys("unable to setup Session Ticket Key context"); wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb); #endif if (cipherList) if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 1"); #ifdef CYASSL_LEANPSK if (!usePsk) { usePsk = 1; } #endif #if defined(NO_RSA) && !defined(HAVE_ECC) if (!usePsk) { usePsk = 1; } #endif if (fewerPackets) CyaSSL_CTX_set_group_messages(ctx); #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if ((!usePsk || usePskPlus) && !useAnon) { if (SSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS) err_sys("can't load server cert file, check file and run from" " wolfSSL home dir"); } #endif #ifndef NO_DH if (wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits) != SSL_SUCCESS) { err_sys("Error setting minimum DH key size"); } #endif #ifndef NO_RSA if (wolfSSL_CTX_SetMinRsaKey_Sz(ctx, minRsaKeyBits) != SSL_SUCCESS){ err_sys("Error setting minimum RSA key size"); } #endif #ifdef HAVE_ECC if (wolfSSL_CTX_SetMinEccKey_Sz(ctx, minEccKeyBits) != SSL_SUCCESS){ err_sys("Error setting minimum ECC key size"); } #endif #ifdef HAVE_NTRU if (useNtruKey) { if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey) != SSL_SUCCESS) err_sys("can't load ntru key file, " "Please run from wolfSSL home dir"); } #endif #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) if (!useNtruKey && (!usePsk || usePskPlus) && !useAnon) { if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) err_sys("can't load server private key file, check file and run " "from wolfSSL home dir"); } #endif if (usePsk || usePskPlus) { #ifndef NO_PSK SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb); if (sendPskIdentityHint == 1) SSL_CTX_use_psk_identity_hint(ctx, "cyassl server"); if (cipherList == NULL && !usePskPlus) { const char *defaultCipherList; #if defined(HAVE_AESGCM) && !defined(NO_DH) defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; needDH = 1; #elif defined(HAVE_NULL_CIPHER) defaultCipherList = "PSK-NULL-SHA256"; #else defaultCipherList = "PSK-AES128-CBC-SHA256"; #endif if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS) err_sys("server can't set cipher list 2"); } #endif } if (useAnon) { #ifdef HAVE_ANON CyaSSL_CTX_allow_anon_cipher(ctx); if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 4"); } #endif } #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) /* if not using PSK, verify peer with certs if using PSK Plus then verify peer certs except PSK suites */ if (doCliCertCheck && (usePsk == 0 || usePskPlus) && useAnon == 0) { SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | ((usePskPlus)? SSL_VERIFY_FAIL_EXCEPT_PSK : SSL_VERIFY_FAIL_IF_NO_PEER_CERT),0); if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #ifdef WOLFSSL_TRUST_PEER_CERT if (trustCert) { if ((ret = wolfSSL_CTX_trust_peer_cert(ctx, trustCert, SSL_FILETYPE_PEM)) != SSL_SUCCESS) { err_sys("can't load trusted peer cert file"); } } #endif /* WOLFSSL_TRUST_PEER_CERT */ } #endif #if defined(CYASSL_SNIFFER) /* don't use EDH, can't sniff tmp keys */ if (cipherList == NULL) { if (SSL_CTX_set_cipher_list(ctx, "AES128-SHA") != SSL_SUCCESS) err_sys("server can't set cipher list 3"); } #endif #ifdef HAVE_SNI if (sniHostName) if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS) err_sys("UseSNI failed"); #endif #ifdef USE_WINDOWS_API if (port == 0) { /* Generate random port for testing */ port = GetRandomPort(); } #endif /* USE_WINDOWS_API */ while (1) { /* allow resume option */ if(resumeCount > 1) { if (doDTLS == 0) { SOCKADDR_IN_T client; socklen_t client_len = sizeof(client); clientfd = accept(sockfd, (struct sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); } else { tcp_listen(&sockfd, &port, useAnyAddr, doDTLS); clientfd = sockfd; } if(WOLFSSL_SOCKET_IS_INVALID(clientfd)) { err_sys("tcp accept failed"); } } #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) { WOLFSSL_MEM_STATS mem_stats; fprintf(stderr, "Before creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys("ctx not using static memory"); if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ err_sys("error printing out memory stats"); } #endif ssl = SSL_new(ctx); if (ssl == NULL) err_sys("unable to get SSL"); #if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL) { WOLFSSL_MEM_STATS mem_stats; fprintf(stderr, "After creating SSL\n"); if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1) err_sys("ctx not using static memory"); if (wolfSSL_PrintStats(&mem_stats) != 1) /* function in test.h */ err_sys("error printing out memory stats"); } #endif #ifndef NO_HANDSHAKE_DONE_CB wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL); #endif #ifdef HAVE_CRL #ifdef HAVE_CRL_MONITOR crlFlags = CYASSL_CRL_MONITOR | CYASSL_CRL_START_MON; #endif if (CyaSSL_EnableCRL(ssl, 0) != SSL_SUCCESS) err_sys("unable to enable CRL"); if (CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, crlFlags) != SSL_SUCCESS) err_sys("unable to load CRL"); if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) err_sys("unable to set CRL callback url"); #endif #ifdef HAVE_OCSP if (useOcsp) { if (ocspUrl != NULL) { CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE | CYASSL_OCSP_URL_OVERRIDE); } else CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE); } #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) if (wolfSSL_CTX_EnableOCSPStapling(ctx) != SSL_SUCCESS) err_sys("can't enable OCSP Stapling Certificate Manager"); if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate1-ca-cert.pem", 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate2-ca-cert.pem", 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); if (SSL_CTX_load_verify_locations(ctx, "certs/ocsp/intermediate3-ca-cert.pem", 0) != SSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #ifdef HAVE_PK_CALLBACKS if (pkCallbacks) SetupPkCallbacks(ctx, ssl); #endif /* do accept */ readySignal = ((func_args*)args)->signal; if (readySignal) { readySignal->srfName = serverReadyFile; } tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS, serverReadyFile ? 1 : 0, doListen); doListen = 0; /* Don't listen next time */ if (SSL_set_fd(ssl, clientfd) != SSL_SUCCESS) { err_sys("error in setting fd"); } #ifdef HAVE_ALPN if (alpnList != NULL) { printf("ALPN accepted protocols list : %s\n", alpnList); wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif #ifdef WOLFSSL_DTLS if (doDTLS) { SOCKADDR_IN_T cliaddr; byte b[1500]; int n; socklen_t len = sizeof(cliaddr); /* For DTLS, peek at the next datagram so we can get the client's * address and set it into the ssl object later to generate the * cookie. */ n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, (struct sockaddr*)&cliaddr, &len); if (n <= 0) err_sys("recvfrom failed"); wolfSSL_dtls_set_peer(ssl, &cliaddr, len); } #endif if ((usePsk == 0 || usePskPlus) || useAnon == 1 || cipherList != NULL || needDH == 1) { #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN) CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM); #elif !defined(NO_DH) SetDH(ssl); /* repick suites with DHE, higher priority than PSK */ #endif } #ifndef CYASSL_CALLBACKS if (nonBlocking) { CyaSSL_set_using_nonblock(ssl, 1); tcp_set_nonblocking(&clientfd); } #endif do { #ifdef WOLFSSL_ASYNC_CRYPT if (err == WC_PENDING_E) { ret = AsyncCryptPoll(ssl); 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 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)); err_sys("SSL_accept failed"); } showPeer(ssl); #ifdef HAVE_ALPN if (alpnList != NULL) { char *protocol_name = NULL, *list = NULL; word16 protocol_nameSz = 0, listSz = 0; err = wolfSSL_ALPN_GetProtocol(ssl, &protocol_name, &protocol_nameSz); if (err == SSL_SUCCESS) printf("Sent ALPN protocol : %s (%d)\n", protocol_name, protocol_nameSz); else if (err == SSL_ALPN_NOT_FOUND) printf("No ALPN response sent (no match)\n"); else printf("Getting ALPN protocol name failed\n"); err = wolfSSL_ALPN_GetPeerProtocol(ssl, &list, &listSz); if (err == SSL_SUCCESS) printf("List of protocol names sent by Client: %s (%d)\n", list, listSz); else printf("Get list of client's protocol name failed\n"); free(list); } #endif if(echoData == 0 && throughput == 0) { ret = SSL_read(ssl, input, sizeof(input)-1); if (ret > 0) { input[ret] = 0; 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)) err_sys("SSL_write failed"); } else { ServerEchoData(ssl, clientfd, echoData, throughput); } #if defined(WOLFSSL_MDK_SHELL) && defined(HAVE_MDK_RTX) os_dly_wait(500) ; #elif defined (CYASSL_TIRTOS) Task_yield(); #endif if (doDTLS == 0) { ret = SSL_shutdown(ssl); if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) SSL_shutdown(ssl); /* bidirectional shutdown */ } /* display collected statistics */ #ifdef WOLFSSL_STATIC_MEMORY if (wolfSSL_is_static_memory(ssl, &ssl_stats) != 1) err_sys("static memory was not used with ssl"); fprintf(stderr, "\nprint off SSL memory stats\n"); fprintf(stderr, "*** This is memory state before wolfSSL_free is called\n"); fprintf(stderr, "peak connection memory = %d\n", ssl_stats.peakMem); fprintf(stderr, "current memory in use = %d\n", ssl_stats.curMem); fprintf(stderr, "peak connection allocs = %d\n", ssl_stats.peakAlloc); fprintf(stderr, "current connection allocs = %d\n",ssl_stats.curAlloc); fprintf(stderr, "total connection allocs = %d\n",ssl_stats.totalAlloc); fprintf(stderr, "total connection frees = %d\n\n", ssl_stats.totalFr); #endif SSL_free(ssl); CloseSocket(clientfd); if (resume == 1 && resumeCount == 0) { resumeCount++; /* only do one resume for testing */ continue; } resumeCount = 0; if(!loopIndefinitely) { break; /* out of while loop, done with normal and resume option */ } } /* while(1) */ CloseSocket(sockfd); SSL_CTX_free(ctx); ((func_args*)args)->return_code = 0; #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \ && defined(HAVE_THREAD_LS) 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 #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ defined(HAVE_POLY1305) TicketCleanup(); #endif /* There are use cases when these assignments are not read. To avoid * potential confusion those warnings have been handled here. */ (void) ourKey; (void) verifyCert; (void) doCliCertCheck; (void) useNtruKey; (void) ourDhParam; (void) ourCert; (void) trackMemory; #ifndef CYASSL_TIRTOS return 0; #endif }