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
25 #include <cyassl/ssl.h> /* name change portability layer */
27 #include <cyassl/ctaocrypt/settings.h>
29 #include <cyassl/ctaocrypt/ecc.h> /* ecc_fp_free */
32 #if !defined(WOLFSSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
33 /* in case memory tracker wants stats */
34 #define WOLFSSL_TRACK_MEMORY
37 #if defined(CYASSL_MDK_ARM)
41 #if defined(CYASSL_MDK5)
49 #include "cyassl_MDK_ARM.h"
51 #include <cyassl/openssl/ssl.h>
52 #include <cyassl/test.h>
54 #include "examples/server/server.h"
57 #ifdef CYASSL_CALLBACKS
58 int srvHandShakeCB(HandShakeInfo*);
59 int srvTimeoutCB(TimeoutInfo*);
63 #ifndef NO_HANDSHAKE_DONE_CB
64 int myHsDoneCb(WOLFSSL* ssl, void* user_ctx);
69 static void NonBlockingSSL_Accept(SSL* ssl)
71 #ifndef CYASSL_CALLBACKS
72 int ret = SSL_accept(ssl);
74 int ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo);
76 int error = SSL_get_error(ssl, 0);
77 SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl);
80 while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
81 error == SSL_ERROR_WANT_WRITE)) {
84 if (error == SSL_ERROR_WANT_READ)
85 printf("... server would read block\n");
87 printf("... server would write block\n");
90 currTimeout = CyaSSL_dtls_get_current_timeout(ssl);
92 select_ret = tcp_select(sockfd, currTimeout);
94 if ((select_ret == TEST_RECV_READY) ||
95 (select_ret == TEST_ERROR_READY)) {
96 #ifndef CYASSL_CALLBACKS
97 ret = SSL_accept(ssl);
99 ret = CyaSSL_accept_ex(ssl,
100 srvHandShakeCB, srvTimeoutCB, srvTo);
102 error = SSL_get_error(ssl, 0);
104 else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) {
105 error = SSL_ERROR_WANT_READ;
108 else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) &&
109 CyaSSL_dtls_got_timeout(ssl) >= 0) {
110 error = SSL_ERROR_WANT_READ;
114 error = SSL_FATAL_ERROR;
117 if (ret != SSL_SUCCESS)
118 err_sys("SSL_accept failed");
122 static void Usage(void)
124 printf("server " LIBCYASSL_VERSION_STRING
125 " NOTE: All files relative to wolfSSL home dir\n");
126 printf("-? Help, print this usage\n");
127 printf("-p <num> Port to listen on, not 0, default %d\n", yasslPort);
128 printf("-v <num> SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n",
129 SERVER_DEFAULT_VERSION);
130 printf("-l <str> Cipher list\n");
131 printf("-c <file> Certificate file, default %s\n", svrCert);
132 printf("-k <file> Key file, default %s\n", svrKey);
133 printf("-A <file> Certificate Authority file, default %s\n", cliCert);
135 printf("-D <file> Diffie-Hellman Params file, default %s\n", dhParam);
136 printf("-Z <num> Minimum DH key bits, default %d\n",
137 DEFAULT_MIN_DHKEY_BITS);
139 printf("-d Disable client cert check\n");
140 printf("-b Bind to any interface instead of localhost only\n");
141 printf("-s Use pre Shared keys\n");
142 printf("-t Track wolfSSL memory use\n");
143 printf("-u Use UDP DTLS,"
144 " add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n");
145 printf("-f Fewer packets/group messages\n");
146 printf("-R Create server ready file, for external monitor\n");
147 printf("-r Allow one client Resumption\n");
148 printf("-N Use Non-blocking sockets\n");
149 printf("-S <str> Use Host Name Indication\n");
150 printf("-w Wait for bidirectional shutdown\n");
152 printf("-o Perform OCSP lookup on peer certificate\n");
153 printf("-O <url> Perform OCSP lookup using <url> as responder\n");
155 #ifdef HAVE_PK_CALLBACKS
156 printf("-P Public Key Callbacks\n");
159 printf("-a Anonymous server\n");
163 THREAD_RETURN CYASSL_THREAD server_test(void* args)
166 SOCKET_T clientfd = 0;
168 SSL_METHOD* method = 0;
172 char msg[] = "I hear you fa shizzle!";
176 int version = SERVER_DEFAULT_VERSION;
177 int doCliCertCheck = 1;
179 word16 port = yasslPort;
187 int fewerPackets = 0;
189 int serverReadyFile = 0;
191 int resume = 0; /* do resume, and resume count */
192 int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS;
194 char* cipherList = NULL;
195 const char* verifyCert = cliCert;
196 const char* ourCert = svrCert;
197 const char* ourKey = svrKey;
198 const char* ourDhParam = dhParam;
199 int argc = ((func_args*)args)->argc;
200 char** argv = ((func_args*)args)->argv;
203 char* sniHostName = NULL;
208 char* ocspUrl = NULL;
211 ((func_args*)args)->return_code = -1; /* error state */
214 verifyCert = (char*)cliEccCert;
215 ourCert = (char*)eccCert;
216 ourKey = (char*)eccKey;
226 (void)doCliCertCheck;
230 fdOpenSession(Task_self());
233 while ((ch = mygetopt(argc, argv, "?dbstnNufrRawPp:v:l:A:c:k:Z:S:oO:D:"))
253 #ifdef USE_WOLFSSL_MEMORY
275 #ifndef NO_SESSION_CACHE
281 #ifdef HAVE_PK_CALLBACKS
287 port = (word16)atoi(myoptarg);
288 #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
290 err_sys("port number cannot be 0");
299 version = atoi(myoptarg);
300 if (version < 0 || version > 3) {
307 cipherList = myoptarg;
311 verifyCert = myoptarg;
324 ourDhParam = myoptarg;
330 minDhKeyBits = atoi(myoptarg);
331 if (minDhKeyBits <= 0 || minDhKeyBits > 16000) {
344 sniHostName = myoptarg;
373 myoptind = 0; /* reset for test cases */
375 /* sort out DTLS versus TLS versions */
376 if (version == CLIENT_INVALID_VERSION) {
378 version = CLIENT_DTLS_DEFAULT_VERSION;
380 version = CLIENT_DEFAULT_VERSION;
391 #ifdef USE_CYASSL_MEMORY
399 method = SSLv3_server_method();
404 method = TLSv1_server_method();
409 method = TLSv1_1_server_method();
417 method = TLSv1_2_server_method();
424 method = DTLSv1_server_method();
429 method = DTLSv1_2_server_method();
434 err_sys("Bad SSL version");
438 err_sys("unable to get method");
440 ctx = SSL_CTX_new(method);
442 err_sys("unable to get ctx");
444 #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
445 defined(HAVE_POLY1305)
446 if (TicketInit() != 0)
447 err_sys("unable to setup Session Ticket Key context");
448 wolfSSL_CTX_set_TicketEncCb(ctx, myTicketEncCb);
452 if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
453 err_sys("server can't set cipher list 1");
455 #ifdef CYASSL_LEANPSK
459 #if defined(NO_RSA) && !defined(HAVE_ECC)
464 CyaSSL_CTX_set_group_messages(ctx);
466 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
467 SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
470 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
471 if (!usePsk && !useAnon) {
472 if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)
474 err_sys("can't load server cert file, check file and run from"
475 " wolfSSL home dir");
480 wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
485 if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
487 err_sys("can't load ntru key file, "
488 "Please run from wolfSSL home dir");
492 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
493 if (!useNtruKey && !usePsk && !useAnon) {
494 if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
496 err_sys("can't load server private key file, check file and run "
497 "from wolfSSL home dir");
503 SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
504 SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
505 if (cipherList == NULL) {
506 const char *defaultCipherList;
507 #if defined(HAVE_AESGCM) && !defined(NO_DH)
508 defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
510 #elif defined(HAVE_NULL_CIPHER)
511 defaultCipherList = "PSK-NULL-SHA256";
513 defaultCipherList = "PSK-AES128-CBC-SHA256";
515 if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS)
516 err_sys("server can't set cipher list 2");
523 CyaSSL_CTX_allow_anon_cipher(ctx);
524 if (cipherList == NULL) {
525 if (SSL_CTX_set_cipher_list(ctx, "ADH-AES128-SHA") != SSL_SUCCESS)
526 err_sys("server can't set cipher list 4");
531 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
532 /* if not using PSK, verify peer with certs */
533 if (doCliCertCheck && usePsk == 0 && useAnon == 0) {
534 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
535 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
536 if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
537 err_sys("can't load ca file, Please run from wolfSSL home dir");
541 #if defined(CYASSL_SNIFFER)
542 /* don't use EDH, can't sniff tmp keys */
543 if (cipherList == NULL) {
544 if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS)
545 err_sys("server can't set cipher list 3");
551 if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName,
552 XSTRLEN(sniHostName)) != SSL_SUCCESS)
553 err_sys("UseSNI failed");
556 while (1) { /* allow resume option */
557 if (resume > 1) { /* already did listen, just do accept */
559 SOCKADDR_IN_T client;
560 socklen_t client_len = sizeof(client);
561 clientfd = accept(sockfd, (struct sockaddr*)&client,
562 (ACCEPT_THIRD_T)&client_len);
564 tcp_listen(&sockfd, &port, useAnyAddr, doDTLS);
565 clientfd = udp_read_connect(sockfd);
567 #ifdef USE_WINDOWS_API
568 if (clientfd == INVALID_SOCKET) err_sys("tcp accept failed");
570 if (clientfd == -1) err_sys("tcp accept failed");
576 err_sys("unable to get SSL");
578 #ifndef NO_HANDSHAKE_DONE_CB
579 wolfSSL_SetHsDoneCb(ssl, myHsDoneCb, NULL);
582 CyaSSL_EnableCRL(ssl, 0);
583 CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR |
584 CYASSL_CRL_START_MON);
585 CyaSSL_SetCRL_Cb(ssl, CRL_CallBack);
589 if (ocspUrl != NULL) {
590 CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
591 CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE
592 | CYASSL_OCSP_URL_OVERRIDE);
595 CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE);
598 #ifdef HAVE_PK_CALLBACKS
600 SetupPkCallbacks(ctx, ssl);
603 if (resume < 2) { /* do listen and accept */
604 tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr,
605 doDTLS, serverReadyFile);
608 SSL_set_fd(ssl, clientfd);
609 if (usePsk == 0 || useAnon == 1 || cipherList != NULL || needDH == 1) {
610 #if !defined(NO_FILESYSTEM) && !defined(NO_DH) && !defined(NO_ASN)
611 CyaSSL_SetTmpDH_file(ssl, ourDhParam, SSL_FILETYPE_PEM);
612 #elif !defined(NO_DH)
613 SetDH(ssl); /* repick suites with DHE, higher priority than PSK */
617 #ifndef CYASSL_CALLBACKS
619 CyaSSL_set_using_nonblock(ssl, 1);
620 tcp_set_nonblocking(&clientfd);
621 NonBlockingSSL_Accept(ssl);
622 } else if (SSL_accept(ssl) != SSL_SUCCESS) {
623 int err = SSL_get_error(ssl, 0);
624 char buffer[CYASSL_MAX_ERROR_SZ];
625 printf("error = %d, %s\n", err, ERR_error_string(err, buffer));
626 err_sys("SSL_accept failed");
629 NonBlockingSSL_Accept(ssl);
633 idx = SSL_read(ssl, input, sizeof(input)-1);
636 printf("Client message: %s\n", input);
640 int readErr = SSL_get_error(ssl, 0);
641 if (readErr != SSL_ERROR_WANT_READ)
642 err_sys("SSL_read failed");
645 if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
646 err_sys("SSL_write failed");
648 #if defined(CYASSL_MDK_SHELL) && defined(HAVE_MDK_RTX)
650 #elif defined (CYASSL_TIRTOS)
655 ret = SSL_shutdown(ssl);
656 if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
657 SSL_shutdown(ssl); /* bidirectional shutdown */
661 CloseSocket(clientfd);
662 resume++; /* only do one resume for testing */
665 break; /* out of while loop, done with normal and resume option */
669 CloseSocket(clientfd);
671 ((func_args*)args)->return_code = 0;
674 #if defined(NO_MAIN_DRIVER) && defined(HAVE_ECC) && defined(FP_ECC) \
675 && defined(HAVE_THREAD_LS)
676 ecc_fp_free(); /* free per thread cache */
679 #ifdef USE_WOLFSSL_MEMORY
685 fdCloseSession(Task_self());
688 #if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \
689 defined(HAVE_POLY1305)
693 #ifndef CYASSL_TIRTOS
699 /* so overall tests can pull in test function */
700 #ifndef NO_MAIN_DRIVER
702 int main(int argc, char** argv)
707 int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID);
709 err_sys("Cavium OpenNitroxDevice failed");
710 #endif /* HAVE_CAVIUM */
718 #if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL)
719 CyaSSL_Debugging_ON();
721 if (CurrentDir("_build"))
723 else if (CurrentDir("server"))
725 else if (CurrentDir("Debug") || CurrentDir("Release"))
728 #ifdef HAVE_STACK_SIZE
729 StackSizeCheck(&args, server_test);
736 CspShutdown(CAVIUM_DEV_ID);
738 return args.return_code;
742 char* myoptarg = NULL;
744 #endif /* NO_MAIN_DRIVER */
747 #ifdef CYASSL_CALLBACKS
749 int srvHandShakeCB(HandShakeInfo* info)
756 int srvTimeoutCB(TimeoutInfo* info)
764 #ifndef NO_HANDSHAKE_DONE_CB
765 int myHsDoneCb(WOLFSSL* ssl, void* user_ctx)
770 /* printf("Notified HandShake done\n"); */
772 /* return negative number to end TLS connection now */