3 * Copyright (C) 2006-2015 wolfSSL Inc.
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <wolfssl/ssl.h>
28 #if defined(WOLFSSL_MDK_ARM)
32 #if defined(WOLFSSL_MDK5)
40 #include "wolfssl_MDK_ARM.h"
43 #include <wolfssl/wolfcrypt/settings.h>
45 #if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
46 /* in case memory tracker wants stats */
47 #define WOLFSSL_TRACK_MEMORY
50 #include <wolfssl/ssl.h>
52 #include <wolfssl/test.h>
54 #include "examples/client/client.h"
57 #ifdef WOLFSSL_CALLBACKS
58 int handShakeCB(HandShakeInfo*);
59 int timeoutCB(TimeoutInfo*);
63 #ifdef HAVE_SESSION_TICKET
64 int sessionTicketCB(WOLFSSL*, const unsigned char*, int, void*);
68 static void NonBlockingSSL_Connect(WOLFSSL* ssl)
70 #ifndef WOLFSSL_CALLBACKS
71 int ret = wolfSSL_connect(ssl);
73 int ret = wolfSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
75 int error = wolfSSL_get_error(ssl, 0);
76 SOCKET_T sockfd = (SOCKET_T)wolfSSL_get_fd(ssl);
79 while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
80 error == SSL_ERROR_WANT_WRITE)) {
83 if (error == SSL_ERROR_WANT_READ)
84 printf("... client would read block\n");
86 printf("... client would write block\n");
89 currTimeout = wolfSSL_dtls_get_current_timeout(ssl);
91 select_ret = tcp_select(sockfd, currTimeout);
93 if ((select_ret == TEST_RECV_READY) ||
94 (select_ret == TEST_ERROR_READY)) {
95 #ifndef WOLFSSL_CALLBACKS
96 ret = wolfSSL_connect(ssl);
98 ret = wolfSSL_connect_ex(ssl,handShakeCB,timeoutCB,timeout);
100 error = wolfSSL_get_error(ssl, 0);
102 else if (select_ret == TEST_TIMEOUT && !wolfSSL_dtls(ssl)) {
103 error = SSL_ERROR_WANT_READ;
106 else if (select_ret == TEST_TIMEOUT && wolfSSL_dtls(ssl) &&
107 wolfSSL_dtls_got_timeout(ssl) >= 0) {
108 error = SSL_ERROR_WANT_READ;
112 error = SSL_FATAL_ERROR;
115 if (ret != SSL_SUCCESS)
116 err_sys("SSL_connect failed");
120 static void Usage(void)
122 printf("client " LIBWOLFSSL_VERSION_STRING
123 " NOTE: All files relative to wolfSSL home dir\n");
124 printf("-? Help, print this usage\n");
125 printf("-h <host> Host to connect to, default %s\n", wolfSSLIP);
126 printf("-p <num> Port to connect on, not 0, default %d\n", wolfSSLPort);
127 printf("-v <num> SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n",
128 CLIENT_DEFAULT_VERSION);
129 printf("-l <str> Cipher list\n");
130 printf("-c <file> Certificate file, default %s\n", cliCert);
131 printf("-k <file> Key file, default %s\n", cliKey);
132 printf("-A <file> Certificate Authority file, default %s\n", caCert);
134 printf("-Z <num> Minimum DH key bits, default %d\n",
135 DEFAULT_MIN_DHKEY_BITS);
137 printf("-b <num> Benchmark <num> connections and print stats\n");
138 printf("-s Use pre Shared keys\n");
139 printf("-t Track wolfSSL memory use\n");
140 printf("-d Disable peer checks\n");
141 printf("-D Override Date Errors example\n");
142 printf("-g Send server HTTP GET\n");
143 printf("-u Use UDP DTLS,"
144 " add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n");
145 printf("-m Match domain name in cert\n");
146 printf("-N Use Non-blocking sockets\n");
147 printf("-r Resume session\n");
148 printf("-w Wait for bidirectional shutdown\n");
149 #ifdef HAVE_SECURE_RENEGOTIATION
150 printf("-R Allow Secure Renegotiation\n");
151 printf("-i Force client Initiated Secure Renegotiation\n");
153 printf("-f Fewer packets/group messages\n");
154 printf("-x Disable client cert/key loading\n");
155 printf("-X Driven by eXternal test case\n");
157 printf("-z Print structure sizes\n");
160 printf("-S <str> Use Host Name Indication\n");
162 #ifdef HAVE_MAX_FRAGMENT
163 printf("-L <num> Use Maximum Fragment Length [1-5]\n");
165 #ifdef HAVE_TRUNCATED_HMAC
166 printf("-T Use Truncated HMAC\n");
169 printf("-o Perform OCSP lookup on peer certificate\n");
170 printf("-O <url> Perform OCSP lookup using <url> as responder\n");
173 printf("-U Atomic User Record Layer Callbacks\n");
175 #ifdef HAVE_PK_CALLBACKS
176 printf("-P Public Key Callbacks\n");
179 printf("-a Anonymous client\n");
182 printf("-C Disable CRL\n");
186 THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
190 WOLFSSL_METHOD* method = 0;
191 WOLFSSL_CTX* ctx = 0;
194 WOLFSSL* sslResume = 0;
195 WOLFSSL_SESSION* session = 0;
196 char resumeMsg[] = "resuming wolfssl!";
197 int resumeSz = sizeof(resumeMsg);
199 char msg[32] = "hello wolfssl!"; /* GET may make bigger */
202 int msgSz = (int)strlen(msg);
204 word16 port = wolfSSLPort;
205 char* host = (char*)wolfSSLIP;
206 const char* domain = "www.wolfssl.com";
209 int version = CLIENT_INVALID_VERSION;
218 int resumeSession = 0;
221 int externalTest = 0;
223 int scr = 0; /* allow secure renegotiation */
224 int forceScr = 0; /* force client initiaed scr */
226 int useClientCert = 1;
227 int fewerPackets = 0;
230 int overrideDateErrors = 0;
231 int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
232 char* cipherList = NULL;
233 const char* verifyCert = caCert;
234 const char* ourCert = cliCert;
235 const char* ourKey = cliKey;
238 char* sniHostName = NULL;
240 #ifdef HAVE_MAX_FRAGMENT
241 byte maxFragment = 0;
243 #ifdef HAVE_TRUNCATED_HMAC
244 byte truncatedHMAC = 0;
250 char* ocspUrl = NULL;
253 int argc = ((func_args*)args)->argc;
254 char** argv = ((func_args*)args)->argv;
256 ((func_args*)args)->return_code = -1; /* error state */
259 verifyCert = (char*)eccCert;
260 ourCert = (char*)cliEccCert;
261 ourKey = (char*)cliEccKey;
275 (void)overrideDateErrors;
281 while ((ch = mygetopt(argc, argv,
282 "?gdDusmNrwRitfxXUPCh:p:v:l:A:c:k:Z:b:zS:L:ToO:a"))
298 overrideDateErrors = 1;
316 #ifdef USE_WOLFSSL_MEMORY
344 #ifdef HAVE_PK_CALLBACKS
355 port = (word16)atoi(myoptarg);
356 #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
358 err_sys("port number cannot be 0");
363 version = atoi(myoptarg);
364 if (version < 0 || version > 3) {
371 cipherList = myoptarg;
375 verifyCert = myoptarg;
388 minDhKeyBits = atoi(myoptarg);
389 if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
397 benchmark = atoi(myoptarg);
398 if (benchmark < 0 || benchmark > 1000000) {
417 #ifdef HAVE_SECURE_RENEGOTIATION
423 #ifdef HAVE_SECURE_RENEGOTIATION
430 #ifndef WOLFSSL_LEANPSK
431 wolfSSL_GetObjectSize();
437 sniHostName = myoptarg;
442 #ifdef HAVE_MAX_FRAGMENT
443 maxFragment = atoi(myoptarg);
444 if (maxFragment < WOLFSSL_MFL_2_9 ||
445 maxFragment > WOLFSSL_MFL_2_13) {
453 #ifdef HAVE_TRUNCATED_HMAC
483 myoptind = 0; /* reset for test cases */
486 /* detect build cases that wouldn't allow test against wolfssl.com */
499 done = 1; /* external cert chain most likely has SHA */
503 printf("external test can't be run in this mode");
505 ((func_args*)args)->return_code = 0;
510 /* sort out DTLS versus TLS versions */
511 if (version == CLIENT_INVALID_VERSION) {
513 version = CLIENT_DTLS_DEFAULT_VERSION;
515 version = CLIENT_DEFAULT_VERSION;
526 #ifdef USE_WOLFSSL_MEMORY
534 method = wolfSSLv3_client_method();
540 method = wolfTLSv1_client_method();
544 method = wolfTLSv1_1_client_method();
548 #endif /* NO_OLD_TLS */
552 method = wolfTLSv1_2_client_method();
559 method = wolfDTLSv1_client_method();
564 method = wolfDTLSv1_2_client_method();
569 err_sys("Bad SSL version");
574 err_sys("unable to get method");
576 ctx = wolfSSL_CTX_new(method);
578 err_sys("unable to get ctx");
581 if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
582 err_sys("client can't set cipher list 1");
584 #ifdef WOLFSSL_LEANPSK
588 #if defined(NO_RSA) && !defined(HAVE_ECC)
593 wolfSSL_CTX_set_group_messages(ctx);
596 wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
601 wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
602 if (cipherList == NULL) {
603 const char *defaultCipherList;
604 #if defined(HAVE_AESGCM) && !defined(NO_DH)
605 defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
606 #elif defined(HAVE_NULL_CIPHER)
607 defaultCipherList = "PSK-NULL-SHA256";
609 defaultCipherList = "PSK-AES128-CBC-SHA256";
611 if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList)
613 err_sys("client can't set cipher list 2");
621 if (cipherList == NULL) {
622 wolfSSL_CTX_allow_anon_cipher(ctx);
623 if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS)
624 err_sys("client can't set cipher list 4");
630 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
631 wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
634 #if defined(WOLFSSL_SNIFFER)
635 if (cipherList == NULL) {
636 /* don't use EDH, can't sniff tmp keys */
637 if (wolfSSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS) {
638 err_sys("client can't set cipher list 3");
645 if (ocspUrl != NULL) {
646 wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
647 wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
648 | WOLFSSL_OCSP_URL_OVERRIDE);
651 wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
656 wolfSSL_CTX_SetCACb(ctx, CaCb);
659 #ifdef VERIFY_CALLBACK
660 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
662 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
664 if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS)
665 err_sys("can't load client cert file, check file and run from"
666 " wolfSSL home dir");
668 if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
670 err_sys("can't load client private key file, check file and run "
671 "from wolfSSL home dir");
674 if (!usePsk && !useAnon) {
675 if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS)
676 err_sys("can't load ca file, Please run from wolfSSL home dir");
678 /* load ecc verify too, echoserver uses it by default w/ ecc */
679 if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
680 err_sys("can't load ecc ca file, Please run from wolfSSL home dir");
681 #endif /* HAVE_ECC */
683 #endif /* !NO_FILESYSTEM && !NO_CERTS */
684 #if !defined(NO_CERTS)
685 if (!usePsk && !useAnon && doPeerCheck == 0)
686 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
687 if (!usePsk && !useAnon && overrideDateErrors == 1)
688 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb);
692 wolfSSL_CTX_UseCavium(ctx, CAVIUM_DEV_ID);
697 if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName))
699 err_sys("UseSNI failed");
701 #ifdef HAVE_MAX_FRAGMENT
703 if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS)
704 err_sys("UseMaxFragment failed");
706 #ifdef HAVE_TRUNCATED_HMAC
708 if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
709 err_sys("UseTruncatedHMAC failed");
711 #ifdef HAVE_SESSION_TICKET
712 if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
713 err_sys("UseSessionTicket failed");
717 /* time passed in number of connects give average */
718 int times = benchmark;
719 int loops = resumeSession ? 2 : 1;
721 WOLFSSL_SESSION* benchSession = NULL;
724 int benchResume = resumeSession && loops == 0;
725 double start = current_time(), avg;
727 for (i = 0; i < times; i++) {
728 tcp_connect(&sockfd, host, port, doDTLS);
730 ssl = wolfSSL_new(ctx);
732 wolfSSL_set_session(ssl, benchSession);
733 wolfSSL_set_fd(ssl, sockfd);
734 if (wolfSSL_connect(ssl) != SSL_SUCCESS)
735 err_sys("SSL_connect failed");
737 wolfSSL_shutdown(ssl);
738 if (i == (times-1) && resumeSession) {
739 benchSession = wolfSSL_get_session(ssl);
744 avg = current_time() - start;
746 avg *= 1000; /* milliseconds */
748 printf("wolfSSL_resume avg took: %8.3f milliseconds\n", avg);
750 printf("wolfSSL_connect avg took: %8.3f milliseconds\n", avg);
753 wolfSSL_CTX_free(ctx);
754 ((func_args*)args)->return_code = 0;
759 #if defined(WOLFSSL_MDK_ARM)
760 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
763 ssl = wolfSSL_new(ctx);
765 err_sys("unable to get SSL object");
766 #ifdef HAVE_SESSION_TICKET
767 wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
771 build_addr(&addr, host, port, 1);
772 wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
773 tcp_socket(&sockfd, 1);
776 tcp_connect(&sockfd, host, port, 0);
780 /* use old poly to connect with google server */
781 if (!XSTRNCMP(domain, "www.google.com", 14)) {
782 if (wolfSSL_use_old_poly(ssl, 1) != 0)
783 err_sys("unable to set to old poly");
787 wolfSSL_set_fd(ssl, sockfd);
789 if (disableCRL == 0) {
790 if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS)
791 err_sys("can't enable crl check");
792 if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
793 err_sys("can't load crl, check crlfile and date validity");
794 if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
795 err_sys("can't set crl callback");
798 #ifdef HAVE_SECURE_RENEGOTIATION
800 if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
801 err_sys("can't enable secure renegotiation");
806 SetupAtomicUser(ctx, ssl);
808 #ifdef HAVE_PK_CALLBACKS
810 SetupPkCallbacks(ctx, ssl);
812 if (matchName && doPeerCheck)
813 wolfSSL_check_domain_name(ssl, domain);
814 #ifndef WOLFSSL_CALLBACKS
816 wolfSSL_set_using_nonblock(ssl, 1);
817 tcp_set_nonblocking(&sockfd);
818 NonBlockingSSL_Connect(ssl);
820 else if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
821 /* see note at top of README */
822 int err = wolfSSL_get_error(ssl, 0);
823 char buffer[WOLFSSL_MAX_ERROR_SZ];
824 printf("err = %d, %s\n", err,
825 wolfSSL_ERR_error_string(err, buffer));
826 err_sys("SSL_connect failed");
827 /* if you're getting an error here */
832 NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */
836 #ifdef HAVE_SECURE_RENEGOTIATION
837 if (scr && forceScr) {
839 printf("not doing secure renegotiation on example with"
842 if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) {
843 int err = wolfSSL_get_error(ssl, 0);
844 char buffer[WOLFSSL_MAX_ERROR_SZ];
845 printf("err = %d, %s\n", err,
846 wolfSSL_ERR_error_string(err, buffer));
847 err_sys("wolfSSL_Rehandshake failed");
851 #endif /* HAVE_SECURE_RENEGOTIATION */
854 printf("SSL connect ok, sending GET...\n");
856 strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz);
859 if (wolfSSL_write(ssl, msg, msgSz) != msgSz)
860 err_sys("SSL_write failed");
862 input = wolfSSL_read(ssl, reply, sizeof(reply)-1);
865 printf("Server response: %s\n", reply);
867 if (sendGET) { /* get html */
869 input = wolfSSL_read(ssl, reply, sizeof(reply)-1);
872 printf("%s\n", reply);
879 else if (input < 0) {
880 int readErr = wolfSSL_get_error(ssl, 0);
881 if (readErr != SSL_ERROR_WANT_READ)
882 err_sys("wolfSSL_read failed");
885 #ifndef NO_SESSION_CACHE
887 session = wolfSSL_get_session(ssl);
888 sslResume = wolfSSL_new(ctx);
892 if (doDTLS == 0) { /* don't send alert after "break" command */
893 ret = wolfSSL_shutdown(ssl);
894 if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
895 wolfSSL_shutdown(ssl); /* bidirectional shutdown */
904 #ifndef NO_SESSION_CACHE
908 #ifdef USE_WINDOWS_API
910 #elif defined(WOLFSSL_TIRTOS)
915 build_addr(&addr, host, port, 1);
916 wolfSSL_dtls_set_peer(sslResume, &addr, sizeof(addr));
917 tcp_socket(&sockfd, 1);
920 tcp_connect(&sockfd, host, port, 0);
922 wolfSSL_set_fd(sslResume, sockfd);
923 #ifdef HAVE_SECURE_RENEGOTIATION
925 if (wolfSSL_UseSecureRenegotiation(sslResume) != SSL_SUCCESS)
926 err_sys("can't enable secure renegotiation");
929 wolfSSL_set_session(sslResume, session);
930 #ifdef HAVE_SESSION_TICKET
931 wolfSSL_set_SessionTicket_cb(sslResume, sessionTicketCB,
932 (void*)"resumed session");
936 #ifndef WOLFSSL_CALLBACKS
938 wolfSSL_set_using_nonblock(sslResume, 1);
939 tcp_set_nonblocking(&sockfd);
940 NonBlockingSSL_Connect(sslResume);
942 else if (wolfSSL_connect(sslResume) != SSL_SUCCESS)
943 err_sys("SSL resume failed");
947 NonBlockingSSL_Connect(ssl); /* will keep retrying on timeout */
950 if (wolfSSL_session_reused(sslResume))
951 printf("reused session id\n");
953 printf("didn't reuse session id!!!\n");
955 if (wolfSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
956 err_sys("SSL_write failed");
959 /* give server a chance to bounce a message back to client */
960 #ifdef USE_WINDOWS_API
962 #elif defined(WOLFSSL_TIRTOS)
969 input = wolfSSL_read(sslResume, reply, sizeof(reply)-1);
972 printf("Server resume response: %s\n", reply);
975 /* try to send session break */
976 wolfSSL_write(sslResume, msg, msgSz);
978 ret = wolfSSL_shutdown(sslResume);
979 if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
980 wolfSSL_shutdown(sslResume); /* bidirectional shutdown */
982 wolfSSL_free(sslResume);
985 #endif /* NO_SESSION_CACHE */
987 wolfSSL_CTX_free(ctx);
989 ((func_args*)args)->return_code = 0;
991 #ifdef USE_WOLFSSL_MEMORY
994 #endif /* USE_WOLFSSL_MEMORY */
996 #if !defined(WOLFSSL_TIRTOS)
1002 /* so overall tests can pull in test function */
1003 #ifndef NO_MAIN_DRIVER
1005 int main(int argc, char** argv)
1010 int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID);
1012 err_sys("Cavium OpenNitroxDevice failed");
1013 #endif /* HAVE_CAVIUM */
1021 #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_MDK_SHELL) && !defined(STACK_TRAP)
1022 wolfSSL_Debugging_ON();
1024 if (CurrentDir("_build"))
1026 else if (CurrentDir("client"))
1028 else if (CurrentDir("Debug") || CurrentDir("Release"))
1031 #ifdef HAVE_STACK_SIZE
1032 StackSizeCheck(&args, client_test);
1039 CspShutdown(CAVIUM_DEV_ID);
1041 return args.return_code;
1045 char* myoptarg = NULL;
1047 #endif /* NO_MAIN_DRIVER */
1051 #ifdef WOLFSSL_CALLBACKS
1053 int handShakeCB(HandShakeInfo* info)
1060 int timeoutCB(TimeoutInfo* info)
1069 #ifdef HAVE_SESSION_TICKET
1071 int sessionTicketCB(WOLFSSL* ssl,
1072 const unsigned char* ticket, int ticketSz,
1077 printf("Session Ticket CB: ticketSz = %d, ctx = %s\n",
1078 ticketSz, (char*)ctx);