A library for setting up Secure Socket Layer (SSL) connections and verifying remote hosts using certificates. Contains only the source files for mbed platform implementation of the library.

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers test.h Source File

test.h

00001 /* test.h */
00002 
00003 #ifndef CyaSSL_TEST_H
00004 #define CyaSSL_TEST_H
00005 
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 #include <assert.h>
00009 #include <ctype.h>
00010 #include <cyassl/ssl.h>
00011 #include <cyassl/ctaocrypt/types.h>
00012 #include <cyassl/ctaocrypt/error-crypt.h>
00013 
00014 #ifdef ATOMIC_USER
00015     #include <cyassl/ctaocrypt/aes.h>
00016     #include <cyassl/ctaocrypt/arc4.h>
00017     #include <cyassl/ctaocrypt/hmac.h>
00018 #endif
00019 #ifdef HAVE_PK_CALLBACKS
00020     #include <cyassl/ctaocrypt/random.h>
00021     #include <cyassl/ctaocrypt/asn.h>
00022     #ifdef HAVE_ECC
00023         #include <cyassl/ctaocrypt/ecc.h>
00024     #endif /* HAVE_ECC */
00025 #endif /*HAVE_PK_CALLBACKS */
00026 
00027 #ifdef USE_WINDOWS_API 
00028     #include <winsock2.h>
00029     #include <process.h>
00030     #ifdef TEST_IPV6            /* don't require newer SDK for IPV4 */
00031         #include <ws2tcpip.h>
00032         #include <wspiapi.h>
00033     #endif
00034     #define SOCKET_T SOCKET
00035     #define SNPRINTF _snprintf
00036 #elif defined(CYASSL_MDK_ARM)
00037     #include <string.h>
00038 #elif defined(CYASSL_TIRTOS)
00039     #include <string.h>
00040     #include <netdb.h>
00041     #include <sys/types.h>
00042     #include <arpa/inet.h>
00043     #include <sys/socket.h>
00044     #include <ti/sysbios/knl/Task.h>
00045     #define SOCKET_T int
00046 #else
00047     #include <string.h>
00048     #include <sys/types.h>
00049 #ifndef CYASSL_LEANPSK
00050     #include <unistd.h>
00051     #include <netdb.h>
00052     #include <netinet/in.h>
00053     #include <netinet/tcp.h>
00054     #include <arpa/inet.h>
00055     #include <sys/ioctl.h>
00056     #include <sys/time.h>
00057     #include <sys/socket.h>
00058     #include <pthread.h>
00059     #include <fcntl.h>
00060     #ifdef TEST_IPV6
00061         #include <netdb.h>
00062     #endif
00063 #endif
00064     #define SOCKET_T int
00065     #ifndef SO_NOSIGPIPE
00066         #include <signal.h>  /* ignore SIGPIPE */
00067     #endif
00068     #define SNPRINTF snprintf
00069 #endif /* USE_WINDOWS_API */
00070 
00071 #ifdef HAVE_CAVIUM
00072     #include "cavium_sysdep.h"
00073     #include "cavium_common.h"
00074     #include "cavium_ioctl.h"
00075 #endif
00076 
00077 #ifdef _MSC_VER
00078     /* disable conversion warning */
00079     /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
00080     #pragma warning(disable:4244 4996)
00081 #endif
00082 
00083 
00084 #if defined(__MACH__) || defined(USE_WINDOWS_API)
00085     #ifndef _SOCKLEN_T
00086         typedef int socklen_t;
00087     #endif
00088 #endif
00089 
00090 
00091 /* HPUX doesn't use socklent_t for third parameter to accept, unless
00092    _XOPEN_SOURCE_EXTENDED is defined */
00093 #if !defined(__hpux__) && !defined(CYASSL_MDK_ARM) && !defined(CYASSL_IAR_ARM)
00094     typedef socklen_t* ACCEPT_THIRD_T;
00095 #else
00096     #if defined _XOPEN_SOURCE_EXTENDED
00097         typedef socklen_t* ACCEPT_THIRD_T;
00098     #else
00099         typedef int*       ACCEPT_THIRD_T;
00100     #endif
00101 #endif
00102 
00103 
00104 #ifdef USE_WINDOWS_API 
00105     #define CloseSocket(s) closesocket(s)
00106     #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); }
00107 #elif defined(CYASSL_MDK_ARM)
00108     #define CloseSocket(s) closesocket(s)
00109     #define StartTCP() 
00110 #else
00111     #define CloseSocket(s) close(s)
00112     #define StartTCP() 
00113 #endif
00114 
00115 
00116 #ifdef SINGLE_THREADED
00117     typedef unsigned int  THREAD_RETURN;
00118     typedef void*         THREAD_TYPE;
00119     #define CYASSL_THREAD
00120 #else
00121     #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
00122         typedef void*         THREAD_RETURN;
00123         typedef pthread_t     THREAD_TYPE;
00124         #define CYASSL_THREAD
00125         #define INFINITE -1
00126         #define WAIT_OBJECT_0 0L
00127     #elif defined(CYASSL_MDK_ARM)
00128         typedef unsigned int  THREAD_RETURN;
00129         typedef int           THREAD_TYPE;
00130         #define CYASSL_THREAD
00131     #elif defined(CYASSL_TIRTOS)
00132         typedef void          THREAD_RETURN;
00133         typedef Task_Handle   THREAD_TYPE;
00134         #define CYASSL_THREAD
00135     #else
00136         typedef unsigned int  THREAD_RETURN;
00137         typedef intptr_t      THREAD_TYPE;
00138         #define CYASSL_THREAD __stdcall
00139     #endif
00140 #endif
00141 
00142 
00143 #ifdef TEST_IPV6
00144     typedef struct sockaddr_in6 SOCKADDR_IN_T;
00145     #define AF_INET_V    AF_INET6
00146 #else
00147     typedef struct sockaddr_in  SOCKADDR_IN_T;
00148     #define AF_INET_V    AF_INET
00149 #endif
00150    
00151 
00152 #define SERVER_DEFAULT_VERSION 3
00153 #define SERVER_DTLS_DEFAULT_VERSION (-2)
00154 #define SERVER_INVALID_VERSION (-99)
00155 #define CLIENT_DEFAULT_VERSION 3
00156 #define CLIENT_DTLS_DEFAULT_VERSION (-2)
00157 #define CLIENT_INVALID_VERSION (-99)
00158 
00159 /* all certs relative to CyaSSL home directory now */
00160 #define caCert     "./certs/ca-cert.pem"
00161 #define eccCert    "./certs/server-ecc.pem"
00162 #define eccKey     "./certs/ecc-key.pem"
00163 #define svrCert    "./certs/server-cert.pem"
00164 #define svrKey     "./certs/server-key.pem"
00165 #define cliCert    "./certs/client-cert.pem"
00166 #define cliKey     "./certs/client-key.pem"
00167 #define ntruCert   "./certs/ntru-cert.pem"
00168 #define ntruKey    "./certs/ntru-key.raw"
00169 #define dhParam    "./certs/dh2048.pem"
00170 #define cliEccKey  "./certs/ecc-client-key.pem"
00171 #define cliEccCert "./certs/client-ecc-cert.pem"
00172 #define crlPemDir  "./certs/crl"
00173 
00174 typedef struct tcp_ready {
00175     word16 ready;              /* predicate */
00176     word16 port;
00177 #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
00178     pthread_mutex_t mutex;
00179     pthread_cond_t  cond;
00180 #endif
00181 } tcp_ready;    
00182 
00183 
00184 void InitTcpReady(tcp_ready*);
00185 void FreeTcpReady(tcp_ready*);
00186 
00187 typedef CYASSL_METHOD* (*method_provider)(void);
00188 typedef void (*ctx_callback)(CYASSL_CTX* ctx);
00189 typedef void (*ssl_callback)(CYASSL* ssl);
00190 
00191 typedef struct callback_functions {
00192     method_provider method;
00193     ctx_callback ctx_ready;
00194     ssl_callback ssl_ready;
00195     ssl_callback on_result;
00196 } callback_functions;
00197 
00198 typedef struct func_args {
00199     int    argc;
00200     char** argv;
00201     int    return_code;
00202     tcp_ready* signal;
00203     callback_functions *callbacks;
00204 } func_args;
00205 
00206 void wait_tcp_ready(func_args*);
00207 
00208 typedef THREAD_RETURN CYASSL_THREAD THREAD_FUNC(void*);
00209 
00210 void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*);
00211 void join_thread(THREAD_TYPE);
00212 
00213 /* yaSSL */
00214 #ifndef TEST_IPV6
00215     static const char* const yasslIP   = "127.0.0.1";
00216 #else
00217     static const char* const yasslIP   = "::1";
00218 #endif
00219 static const word16      yasslPort = 11111;
00220 
00221 static INLINE void err_sys(const char* msg)
00222 {
00223     printf("yassl error: %s\n", msg);
00224     if (msg)
00225         exit(EXIT_FAILURE);
00226 }
00227 
00228 
00229 #define MY_EX_USAGE 2
00230 
00231 extern int   myoptind;
00232 extern char* myoptarg;
00233 
00234 static INLINE int mygetopt(int argc, char** argv, const char* optstring)
00235 {
00236     static char* next = NULL;
00237 
00238     char  c;
00239     char* cp;
00240 
00241     if (myoptind == 0)
00242         next = NULL;   /* we're starting new/over */
00243 
00244     if (next == NULL || *next == '\0') {
00245         if (myoptind == 0)
00246             myoptind++;
00247 
00248         if (myoptind >= argc || argv[myoptind][0] != '-' ||
00249                                 argv[myoptind][1] == '\0') {
00250             myoptarg = NULL;
00251             if (myoptind < argc)
00252                 myoptarg = argv[myoptind];
00253 
00254             return -1;
00255         }
00256 
00257         if (strcmp(argv[myoptind], "--") == 0) {
00258             myoptind++;
00259             myoptarg = NULL;
00260 
00261             if (myoptind < argc)
00262                 myoptarg = argv[myoptind];
00263 
00264             return -1;
00265         }
00266 
00267         next = argv[myoptind];
00268         next++;                  /* skip - */
00269         myoptind++;
00270     }
00271 
00272     c  = *next++;
00273     /* The C++ strchr can return a different value */
00274     cp = (char*)strchr(optstring, c);
00275 
00276     if (cp == NULL || c == ':') 
00277         return '?';
00278 
00279     cp++;
00280 
00281     if (*cp == ':') {
00282         if (*next != '\0') {
00283             myoptarg = next;
00284             next     = NULL;
00285         }
00286         else if (myoptind < argc) {
00287             myoptarg = argv[myoptind];
00288             myoptind++;
00289         }
00290         else 
00291             return '?';
00292     }
00293 
00294     return c;
00295 }
00296 
00297 
00298 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
00299 
00300 static INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata)
00301 {
00302     (void)rw;
00303     (void)userdata;
00304     strncpy(passwd, "yassl123", sz);
00305     return 8;
00306 }
00307 
00308 #endif
00309 
00310 
00311 #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
00312 
00313 static INLINE void ShowX509(CYASSL_X509* x509, const char* hdr)
00314 {
00315     char* altName;
00316     char* issuer  = CyaSSL_X509_NAME_oneline(
00317                                        CyaSSL_X509_get_issuer_name(x509), 0, 0);
00318     char* subject = CyaSSL_X509_NAME_oneline(
00319                                       CyaSSL_X509_get_subject_name(x509), 0, 0);
00320     byte  serial[32];
00321     int   ret;
00322     int   sz = sizeof(serial);
00323         
00324     printf("%s\n issuer : %s\n subject: %s\n", hdr, issuer, subject);
00325 
00326     while ( (altName = CyaSSL_X509_get_next_altname(x509)) != NULL)
00327         printf(" altname = %s\n", altName);
00328 
00329     ret = CyaSSL_X509_get_serial_number(x509, serial, &sz);
00330     if (ret == SSL_SUCCESS) {
00331         int  i;
00332         int  strLen;
00333         char serialMsg[80];
00334 
00335         /* testsuite has multiple threads writing to stdout, get output
00336            message ready to write once */
00337         strLen = sprintf(serialMsg, " serial number");
00338         for (i = 0; i < sz; i++)
00339             sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]);
00340         printf("%s\n", serialMsg);
00341     }
00342 
00343     XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
00344     XFREE(issuer,  0, DYNAMIC_TYPE_OPENSSL);
00345 }
00346 
00347 #endif /* KEEP_PEER_CERT || SESSION_CERTS */
00348 
00349 
00350 static INLINE void showPeer(CYASSL* ssl)
00351 {
00352 
00353     CYASSL_CIPHER* cipher;
00354 #ifdef KEEP_PEER_CERT
00355     CYASSL_X509* peer = CyaSSL_get_peer_certificate(ssl);
00356     if (peer)
00357         ShowX509(peer, "peer's cert info:");
00358     else
00359         printf("peer has no cert!\n");
00360 #endif
00361     printf("SSL version is %s\n", CyaSSL_get_version(ssl));
00362 
00363     cipher = CyaSSL_get_current_cipher(ssl);
00364     printf("SSL cipher suite is %s\n", CyaSSL_CIPHER_get_name(cipher));
00365 
00366 #if defined(SESSION_CERTS) && defined(SHOW_CERTS)
00367     {
00368         CYASSL_X509_CHAIN* chain = CyaSSL_get_peer_chain(ssl);
00369         int                count = CyaSSL_get_chain_count(chain);
00370         int i;
00371 
00372         for (i = 0; i < count; i++) {
00373             int length;
00374             unsigned char buffer[3072];
00375             CYASSL_X509* chainX509;
00376 
00377             CyaSSL_get_chain_cert_pem(chain,i,buffer, sizeof(buffer), &length);
00378             buffer[length] = 0;
00379             printf("cert %d has length %d data = \n%s\n", i, length, buffer);
00380 
00381             chainX509 = CyaSSL_get_chain_X509(chain, i);
00382             if (chainX509)
00383                 ShowX509(chainX509, "session cert info:");
00384             else
00385                 printf("get_chain_X509 failed\n");
00386             CyaSSL_FreeX509(chainX509);
00387         }
00388     }
00389 #endif
00390   (void)ssl;
00391 }
00392 
00393 
00394 static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
00395                               word16 port, int udp)
00396 {
00397     int useLookup = 0;
00398     (void)useLookup;
00399     (void)udp;
00400 
00401     memset(addr, 0, sizeof(SOCKADDR_IN_T));
00402 
00403 #ifndef TEST_IPV6
00404     /* peer could be in human readable form */
00405     if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) {
00406         #ifdef CYASSL_MDK_ARM
00407             int err;
00408             struct hostent* entry = gethostbyname(peer, &err);
00409         #else
00410             struct hostent* entry = gethostbyname(peer);
00411         #endif
00412 
00413         if (entry) {
00414             memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0],
00415                    entry->h_length);
00416             useLookup = 1;
00417         }
00418         else
00419             err_sys("no entry for host");
00420     }
00421 #endif
00422 
00423 
00424 #ifndef TEST_IPV6
00425     #if defined(CYASSL_MDK_ARM)
00426         addr->sin_family = PF_INET;
00427     #else
00428         addr->sin_family = AF_INET_V;
00429     #endif
00430     addr->sin_port = htons(port);
00431     if (peer == INADDR_ANY)
00432         addr->sin_addr.s_addr = INADDR_ANY;
00433     else {
00434         if (!useLookup)
00435             addr->sin_addr.s_addr = inet_addr(peer);
00436     }
00437 #else
00438     addr->sin6_family = AF_INET_V;
00439     addr->sin6_port = htons(port);
00440     if (peer == INADDR_ANY)
00441         addr->sin6_addr = in6addr_any;
00442     else {
00443         #ifdef HAVE_GETADDRINFO
00444             struct addrinfo  hints;
00445             struct addrinfo* answer = NULL;
00446             int    ret;
00447             char   strPort[80];
00448 
00449             memset(&hints, 0, sizeof(hints));
00450 
00451             hints.ai_family   = AF_INET_V;
00452             hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
00453             hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
00454 
00455             SNPRINTF(strPort, sizeof(strPort), "%d", port);
00456             strPort[79] = '\0';
00457 
00458             ret = getaddrinfo(peer, strPort, &hints, &answer);
00459             if (ret < 0 || answer == NULL)
00460                 err_sys("getaddrinfo failed");
00461 
00462             memcpy(addr, answer->ai_addr, answer->ai_addrlen);
00463             freeaddrinfo(answer);
00464         #else
00465             printf("no ipv6 getaddrinfo, loopback only tests/examples\n");
00466             addr->sin6_addr = in6addr_loopback;
00467         #endif
00468     }
00469 #endif
00470 }
00471 
00472 
00473 static INLINE void tcp_socket(SOCKET_T* sockfd, int udp)
00474 {
00475     if (udp)
00476         *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0);
00477     else
00478         *sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
00479 
00480 #ifdef USE_WINDOWS_API
00481     if (*sockfd == INVALID_SOCKET)
00482         err_sys("socket failed\n");
00483 #elif defined(CYASSL_TIRTOS)
00484     if (*sockfd == -1)
00485         err_sys("socket failed\n");
00486 #else
00487     if (*sockfd < 0)
00488         err_sys("socket failed\n");
00489 #endif
00490 
00491 #ifndef USE_WINDOWS_API 
00492 #ifdef SO_NOSIGPIPE
00493     {
00494         int       on = 1;
00495         socklen_t len = sizeof(on);
00496         int       res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len);
00497         if (res < 0)
00498             err_sys("setsockopt SO_NOSIGPIPE failed\n");
00499     }
00500 #elif defined(CYASSL_MDK_ARM) || defined (CYASSL_TIRTOS)
00501     /* nothing to define */
00502 #else  /* no S_NOSIGPIPE */
00503     signal(SIGPIPE, SIG_IGN);
00504 #endif /* S_NOSIGPIPE */
00505 
00506 #if defined(TCP_NODELAY)
00507     if (!udp)
00508     {
00509         int       on = 1;
00510         socklen_t len = sizeof(on);
00511         int       res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len);
00512         if (res < 0)
00513             err_sys("setsockopt TCP_NODELAY failed\n");
00514     }
00515 #endif
00516 #endif  /* USE_WINDOWS_API */
00517 }
00518 
00519 static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port,
00520                                int udp)
00521 {
00522     SOCKADDR_IN_T addr;
00523     build_addr(&addr, ip, port, udp);
00524     tcp_socket(sockfd, udp);
00525 
00526     if (!udp) {
00527         if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
00528             err_sys("tcp connect failed");
00529     }
00530 }
00531 
00532 
00533 static INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz)
00534 {
00535     if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0)
00536         err_sys("tcp connect failed");
00537 }
00538 
00539 
00540 enum {
00541     TEST_SELECT_FAIL,
00542     TEST_TIMEOUT,
00543     TEST_RECV_READY,
00544     TEST_ERROR_READY
00545 };
00546 
00547 
00548 #if !defined(CYASSL_MDK_ARM) && !defined(CYASSL_TIRTOS)
00549 static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
00550 {
00551     fd_set recvfds, errfds;
00552     SOCKET_T nfds = socketfd + 1;
00553     struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0};
00554     int result;
00555 
00556     FD_ZERO(&recvfds);
00557     FD_SET(socketfd, &recvfds);
00558     FD_ZERO(&errfds);
00559     FD_SET(socketfd, &errfds);
00560 
00561     result = select(nfds, &recvfds, NULL, &errfds, &timeout);
00562 
00563     if (result == 0)
00564         return TEST_TIMEOUT;
00565     else if (result > 0) {
00566         if (FD_ISSET(socketfd, &recvfds))
00567             return TEST_RECV_READY;
00568         else if(FD_ISSET(socketfd, &errfds))
00569             return TEST_ERROR_READY;
00570     }
00571 
00572     return TEST_SELECT_FAIL;
00573 }
00574 #elif defined(CYASSL_TIRTOS)
00575 static INLINE int tcp_select(SOCKET_T socketfd, int to_sec)
00576 {
00577     return TEST_RECV_READY;
00578 }
00579 #endif /* !CYASSL_MDK_ARM */
00580 
00581 
00582 static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr,
00583                               int udp)
00584 {
00585     SOCKADDR_IN_T addr;
00586 
00587     /* don't use INADDR_ANY by default, firewall may block, make user switch
00588        on */
00589     build_addr(&addr, (useAnyAddr ? INADDR_ANY : yasslIP), *port, udp);
00590     tcp_socket(sockfd, udp);
00591 
00592 #if !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_ARM)
00593     {
00594         int       res, on  = 1;
00595         socklen_t len = sizeof(on);
00596         res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
00597         if (res < 0)
00598             err_sys("setsockopt SO_REUSEADDR failed\n");
00599     }
00600 #endif
00601 
00602     if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
00603         err_sys("tcp bind failed");
00604     if (!udp) {
00605         if (listen(*sockfd, 5) != 0)
00606             err_sys("tcp listen failed");
00607     }
00608     #if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)
00609         if (*port == 0) {
00610             socklen_t len = sizeof(addr);
00611             if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
00612                 #ifndef TEST_IPV6
00613                     *port = ntohs(addr.sin_port);
00614                 #else
00615                     *port = ntohs(addr.sin6_port);
00616                 #endif
00617             }
00618         }
00619     #endif
00620 }
00621 
00622 
00623 static INLINE int udp_read_connect(SOCKET_T sockfd)
00624 {
00625     SOCKADDR_IN_T cliaddr;
00626     byte          b[1500];
00627     int           n;
00628     socklen_t     len = sizeof(cliaddr);
00629 
00630     n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK,
00631                       (struct sockaddr*)&cliaddr, &len);
00632     if (n > 0) {
00633         if (connect(sockfd, (const struct sockaddr*)&cliaddr,
00634                     sizeof(cliaddr)) != 0)
00635             err_sys("udp connect failed");
00636     }
00637     else
00638         err_sys("recvfrom failed");
00639 
00640     return sockfd;
00641 }
00642 
00643 static INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
00644                               int useAnyAddr, word16 port, func_args* args)
00645 {
00646     SOCKADDR_IN_T addr;
00647 
00648     (void)args;
00649     build_addr(&addr, (useAnyAddr ? INADDR_ANY : yasslIP), port, 1);
00650     tcp_socket(sockfd, 1);
00651 
00652 
00653 #if !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_ARM)
00654     {
00655         int       res, on  = 1;
00656         socklen_t len = sizeof(on);
00657         res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
00658         if (res < 0)
00659             err_sys("setsockopt SO_REUSEADDR failed\n");
00660     }
00661 #endif
00662 
00663     if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
00664         err_sys("tcp bind failed");
00665 
00666     #if defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)
00667         if (port == 0) {
00668             socklen_t len = sizeof(addr);
00669             if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
00670                 #ifndef TEST_IPV6
00671                     port = ntohs(addr.sin_port);
00672                 #else
00673                     port = ntohs(addr.sin6_port);
00674                 #endif
00675             }
00676         }
00677     #endif
00678 
00679 #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
00680     /* signal ready to accept data */
00681     {
00682     tcp_ready* ready = args->signal;
00683     pthread_mutex_lock(&ready->mutex);
00684     ready->ready = 1;
00685     ready->port = port;
00686     pthread_cond_signal(&ready->cond);
00687     pthread_mutex_unlock(&ready->mutex);
00688     }
00689 #elif defined (CYASSL_TIRTOS)
00690     /* Need mutex? */
00691     tcp_ready* ready = args->signal;
00692     ready->ready = 1;
00693     ready->port = port;
00694 #endif
00695 
00696     *clientfd = udp_read_connect(*sockfd);
00697 }
00698 
00699 static INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd,
00700                               func_args* args, word16 port, int useAnyAddr,
00701                               int udp, int ready_file)
00702 {
00703     SOCKADDR_IN_T client;
00704     socklen_t client_len = sizeof(client);
00705 
00706     if (udp) {
00707         udp_accept(sockfd, clientfd, useAnyAddr, port, args);
00708         return;
00709     }
00710 
00711     tcp_listen(sockfd, &port, useAnyAddr, udp);
00712 
00713 #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__)
00714     /* signal ready to tcp_accept */
00715     {
00716     tcp_ready* ready = args->signal;
00717     pthread_mutex_lock(&ready->mutex);
00718     ready->ready = 1;
00719     ready->port = port;
00720     pthread_cond_signal(&ready->cond);
00721     pthread_mutex_unlock(&ready->mutex);
00722     }
00723 #elif defined (CYASSL_TIRTOS)
00724     /* Need mutex? */
00725     tcp_ready* ready = args->signal;
00726     ready->ready = 1;
00727     ready->port = port;
00728 #endif
00729 
00730     if (ready_file) {
00731 #ifndef NO_FILESYSTEM
00732         FILE* srf = fopen("./server_ready", "w+");
00733 
00734         if (srf) {
00735             fputs("ready", srf);
00736             fclose(srf);
00737         }
00738 #endif
00739     }
00740 
00741     *clientfd = accept(*sockfd, (struct sockaddr*)&client,
00742                       (ACCEPT_THIRD_T)&client_len);
00743 #ifdef USE_WINDOWS_API
00744     if (*clientfd == INVALID_SOCKET)
00745         err_sys("tcp accept failed");
00746 #else
00747     if (*clientfd == -1)
00748         err_sys("tcp accept failed");
00749 #endif
00750 }
00751 
00752 
00753 static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd)
00754 {
00755     #ifdef USE_WINDOWS_API 
00756         unsigned long blocking = 1;
00757         int ret = ioctlsocket(*sockfd, FIONBIO, &blocking);
00758         if (ret == SOCKET_ERROR)
00759             err_sys("ioctlsocket failed");
00760     #elif defined(CYASSL_MDK_ARM) || defined (CYASSL_TIRTOS)
00761          /* non blocking not suppported, for now */ 
00762     #else
00763         int flags = fcntl(*sockfd, F_GETFL, 0);
00764         if (flags < 0)
00765             err_sys("fcntl get failed");
00766         flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK);
00767         if (flags < 0)
00768             err_sys("fcntl set failed");
00769     #endif
00770 }
00771 
00772 
00773 #ifndef NO_PSK
00774 
00775 static INLINE unsigned int my_psk_client_cb(CYASSL* ssl, const char* hint,
00776         char* identity, unsigned int id_max_len, unsigned char* key,
00777         unsigned int key_max_len)
00778 {
00779     (void)ssl;
00780     (void)hint;
00781     (void)key_max_len;
00782 
00783     /* identity is OpenSSL testing default for openssl s_client, keep same */
00784     strncpy(identity, "Client_identity", id_max_len);
00785 
00786 
00787     /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
00788        unsigned binary */
00789     key[0] = 26;
00790     key[1] = 43;
00791     key[2] = 60;
00792     key[3] = 77;
00793 
00794     return 4;   /* length of key in octets or 0 for error */
00795 }
00796 
00797 
00798 static INLINE unsigned int my_psk_server_cb(CYASSL* ssl, const char* identity,
00799         unsigned char* key, unsigned int key_max_len)
00800 {
00801     (void)ssl;
00802     (void)key_max_len;
00803 
00804     /* identity is OpenSSL testing default for openssl s_client, keep same */
00805     if (strncmp(identity, "Client_identity", 15) != 0)
00806         return 0;
00807 
00808     /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using
00809        unsigned binary */
00810     key[0] = 26;
00811     key[1] = 43;
00812     key[2] = 60;
00813     key[3] = 77;
00814 
00815     return 4;   /* length of key in octets or 0 for error */
00816 }
00817 
00818 #endif /* NO_PSK */
00819 
00820 
00821 #ifdef USE_WINDOWS_API 
00822 
00823     #define WIN32_LEAN_AND_MEAN
00824     #include <windows.h>
00825 
00826     static INLINE double current_time()
00827     {
00828         static int init = 0;
00829         static LARGE_INTEGER freq;
00830     
00831         LARGE_INTEGER count;
00832 
00833         if (!init) {
00834             QueryPerformanceFrequency(&freq);
00835             init = 1;
00836         }
00837 
00838         QueryPerformanceCounter(&count);
00839 
00840         return (double)count.QuadPart / freq.QuadPart;
00841     }
00842 
00843 #elif defined(CYASSL_TIRTOS)
00844     extern double current_time();
00845 #else
00846 
00847 #if !defined(CYASSL_MDK_ARM)
00848     #include <sys/time.h>
00849 
00850     static INLINE double current_time(void)
00851     {
00852         struct timeval tv;
00853         gettimeofday(&tv, 0);
00854 
00855         return (double)tv.tv_sec + (double)tv.tv_usec / 1000000;
00856     }
00857         
00858 #endif
00859 #endif /* USE_WINDOWS_API */
00860 
00861 
00862 #if defined(NO_FILESYSTEM) && !defined(NO_CERTS)
00863 
00864     enum {
00865         CYASSL_CA   = 1,
00866         CYASSL_CERT = 2,
00867         CYASSL_KEY  = 3
00868     };
00869 
00870     static INLINE void load_buffer(CYASSL_CTX* ctx, const char* fname, int type)
00871     {
00872         /* test buffer load */
00873         long  sz = 0;
00874         byte  buff[10000];
00875         FILE* file = fopen(fname, "rb");
00876 
00877         if (!file)
00878             err_sys("can't open file for buffer load "
00879                     "Please run from CyaSSL home directory if not");
00880         fseek(file, 0, SEEK_END);
00881         sz = ftell(file);
00882         rewind(file);
00883         fread(buff, sizeof(buff), 1, file);
00884   
00885         if (type == CYASSL_CA) {
00886             if (CyaSSL_CTX_load_verify_buffer(ctx, buff, sz, SSL_FILETYPE_PEM)
00887                                               != SSL_SUCCESS)
00888                 err_sys("can't load buffer ca file");
00889         }
00890         else if (type == CYASSL_CERT) {
00891             if (CyaSSL_CTX_use_certificate_buffer(ctx, buff, sz,
00892                         SSL_FILETYPE_PEM) != SSL_SUCCESS)
00893                 err_sys("can't load buffer cert file");
00894         }
00895         else if (type == CYASSL_KEY) {
00896             if (CyaSSL_CTX_use_PrivateKey_buffer(ctx, buff, sz,
00897                         SSL_FILETYPE_PEM) != SSL_SUCCESS)
00898                 err_sys("can't load buffer key file");
00899         }
00900     }
00901 
00902 #endif /* NO_FILESYSTEM */
00903 
00904 #ifdef VERIFY_CALLBACK
00905 
00906 static INLINE int myVerify(int preverify, CYASSL_X509_STORE_CTX* store)
00907 {
00908     (void)preverify;
00909     char buffer[CYASSL_MAX_ERROR_SZ];
00910 
00911 #ifdef OPENSSL_EXTRA
00912     CYASSL_X509* peer;
00913 #endif
00914 
00915     printf("In verification callback, error = %d, %s\n", store->error,
00916                                  CyaSSL_ERR_error_string(store->error, buffer));
00917 #ifdef OPENSSL_EXTRA
00918     peer = store->current_cert;
00919     if (peer) {
00920         char* issuer  = CyaSSL_X509_NAME_oneline(
00921                                        CyaSSL_X509_get_issuer_name(peer), 0, 0);
00922         char* subject = CyaSSL_X509_NAME_oneline(
00923                                       CyaSSL_X509_get_subject_name(peer), 0, 0);
00924         printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer,
00925                                                                   subject);
00926         XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);
00927         XFREE(issuer,  0, DYNAMIC_TYPE_OPENSSL);
00928     }
00929     else
00930         printf("peer has no cert!\n");
00931 #endif
00932     printf("Subject's domain name is %s\n", store->domain);
00933 
00934     printf("Allowing to continue anyway (shouldn't do this, EVER!!!)\n");
00935     return 1;
00936 }
00937 
00938 #endif /* VERIFY_CALLBACK */
00939 
00940 
00941 static INLINE int myDateCb(int preverify, CYASSL_X509_STORE_CTX* store)
00942 {
00943     char buffer[CYASSL_MAX_ERROR_SZ];
00944     (void)preverify;
00945 
00946     printf("In verification callback, error = %d, %s\n", store->error,
00947                                  CyaSSL_ERR_error_string(store->error, buffer));
00948     printf("Subject's domain name is %s\n", store->domain);
00949 
00950     if (store->error == ASN_BEFORE_DATE_E || store->error == ASN_AFTER_DATE_E) {
00951         printf("Overriding cert date error as example for bad clock testing\n");
00952         return 1;
00953     }
00954     printf("Cert error is not date error, not overriding\n");
00955 
00956     return 0;
00957 }
00958 
00959 
00960 #ifdef HAVE_CRL
00961 
00962 static INLINE void CRL_CallBack(const char* url)
00963 {
00964     printf("CRL callback url = %s\n", url);
00965 }
00966 
00967 #endif
00968 
00969 #ifndef NO_CERTS
00970 
00971 static INLINE void CaCb(unsigned char* der, int sz, int type)
00972 {
00973     (void)der;
00974     printf("Got CA cache add callback, derSz = %d, type = %d\n", sz, type);
00975 }
00976 
00977 
00978 #ifndef NO_DH
00979 static INLINE void SetDH(CYASSL* ssl)
00980 {
00981     /* dh1024 p */
00982     static unsigned char p[] =
00983     {
00984         0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
00985         0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
00986         0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
00987         0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
00988         0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
00989         0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
00990         0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
00991         0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
00992         0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
00993         0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
00994         0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
00995     };
00996 
00997     /* dh1024 g */
00998     static unsigned char g[] =
00999     {
01000       0x02,
01001     };
01002 
01003     CyaSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g));
01004 }
01005 
01006 static INLINE void SetDHCtx(CYASSL_CTX* ctx)
01007 {
01008     /* dh1024 p */
01009     static unsigned char p[] =
01010     {
01011         0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
01012         0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
01013         0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
01014         0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
01015         0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
01016         0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
01017         0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
01018         0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
01019         0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
01020         0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
01021         0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
01022     };
01023 
01024     /* dh1024 g */
01025     static unsigned char g[] =
01026     {
01027       0x02,
01028     };
01029 
01030     CyaSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g));
01031 }
01032 #endif /* NO_DH */
01033 #endif /* !NO_CERTS */
01034 
01035 #ifdef HAVE_CAVIUM
01036 
01037 static INLINE int OpenNitroxDevice(int dma_mode,int dev_id)
01038 {
01039    Csp1CoreAssignment core_assign;
01040    Uint32             device;
01041 
01042    if (CspInitialize(CAVIUM_DIRECT,CAVIUM_DEV_ID))
01043       return -1;
01044    if (Csp1GetDevType(&device))
01045       return -1;
01046    if (device != NPX_DEVICE) {
01047       if (ioctl(gpkpdev_hdlr[CAVIUM_DEV_ID], IOCTL_CSP1_GET_CORE_ASSIGNMENT,
01048                 (Uint32 *)&core_assign)!= 0)
01049          return -1;
01050    }
01051    CspShutdown(CAVIUM_DEV_ID);
01052 
01053    return CspInitialize(dma_mode, dev_id);
01054 }
01055 
01056 #endif /* HAVE_CAVIUM */
01057 
01058 
01059 #ifdef USE_WINDOWS_API 
01060 
01061 /* do back x number of directories */
01062 static INLINE void ChangeDirBack(int x)
01063 {
01064     char path[MAX_PATH];
01065 
01066     if (x == 1)
01067         strncpy(path, "..\\", MAX_PATH);
01068     else if (x == 2)
01069         strncpy(path, "..\\..\\", MAX_PATH);
01070     else if (x == 3)
01071         strncpy(path, "..\\..\\..\\", MAX_PATH);
01072     else if (x == 4)
01073         strncpy(path, "..\\..\\..\\..\\", MAX_PATH);
01074     else
01075         strncpy(path, ".\\", MAX_PATH);
01076     
01077     SetCurrentDirectoryA(path);
01078 }
01079 
01080 /* does current dir contain str */
01081 static INLINE int CurrentDir(const char* str)
01082 {
01083     char  path[MAX_PATH];
01084     char* baseName;
01085 
01086     GetCurrentDirectoryA(sizeof(path), path);
01087 
01088     baseName = strrchr(path, '\\');
01089     if (baseName)
01090         baseName++;
01091     else
01092         baseName = path;
01093 
01094     if (strstr(baseName, str))
01095         return 1;
01096 
01097     return 0;
01098 }
01099 
01100 #elif defined(CYASSL_MDK_ARM)
01101     /* KEIL-RL File System does not support relative directry */
01102 #elif defined(CYASSL_TIRTOS)
01103 #else
01104 
01105 #ifndef MAX_PATH
01106     #define MAX_PATH 256
01107 #endif
01108 
01109 /* do back x number of directories */
01110 static INLINE void ChangeDirBack(int x)
01111 {
01112     char path[MAX_PATH];
01113 
01114     if (x == 1)
01115         strncpy(path, "../", MAX_PATH);
01116     else if (x == 2)
01117         strncpy(path, "../../", MAX_PATH);
01118     else if (x == 3)
01119         strncpy(path, "../../../", MAX_PATH);
01120     else if (x == 4)
01121         strncpy(path, "../../../../", MAX_PATH);
01122     else
01123         strncpy(path, "./", MAX_PATH);
01124     
01125     if (chdir(path) < 0)
01126         printf("chdir to %s failed\n", path);
01127 }
01128 
01129 /* does current dir contain str */
01130 static INLINE int CurrentDir(const char* str)
01131 {
01132     char  path[MAX_PATH];
01133     char* baseName;
01134 
01135     if (getcwd(path, sizeof(path)) == NULL) {
01136         printf("no current dir?\n");
01137         return 0;
01138     }
01139 
01140     baseName = strrchr(path, '/');
01141     if (baseName)
01142         baseName++;
01143     else
01144         baseName = path;
01145 
01146     if (strstr(baseName, str))
01147         return 1;
01148 
01149     return 0;
01150 }
01151 
01152 #endif /* USE_WINDOWS_API */
01153 
01154 
01155 #ifdef USE_CYASSL_MEMORY
01156 
01157     typedef struct memoryStats {
01158         size_t totalAllocs;     /* number of allocations */
01159         size_t totalBytes;      /* total number of bytes allocated */
01160         size_t peakBytes;       /* concurrent max bytes */
01161         size_t currentBytes;    /* total current bytes in use */
01162     } memoryStats;
01163 
01164     typedef struct memHint {
01165         size_t thisSize;      /* size of this memory */
01166         void*  thisMemory;    /* actual memory for user */
01167     } memHint;
01168 
01169     typedef struct memoryTrack {
01170         union {
01171             memHint hint;
01172             byte    alignit[16];   /* make sure we have strong alignment */
01173         } u;
01174     } memoryTrack;
01175 
01176     #if defined(CYASSL_TRACK_MEMORY)
01177         #define DO_MEM_STATS
01178         static memoryStats ourMemStats;
01179     #endif
01180 
01181     static INLINE void* TrackMalloc(size_t sz)
01182     {
01183         memoryTrack* mt;
01184 
01185         if (sz == 0)
01186             return NULL;
01187 
01188         mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz);
01189         if (mt == NULL)
01190             return NULL;
01191 
01192         mt->u.hint.thisSize   = sz;
01193         mt->u.hint.thisMemory = (byte*)mt + sizeof(memoryTrack);
01194 
01195 #ifdef DO_MEM_STATS
01196         ourMemStats.totalAllocs++;
01197         ourMemStats.totalBytes   += sz;
01198         ourMemStats.currentBytes += sz;
01199         if (ourMemStats.currentBytes > ourMemStats.peakBytes)
01200             ourMemStats.peakBytes = ourMemStats.currentBytes;
01201 #endif
01202 
01203         return mt->u.hint.thisMemory;
01204     }
01205 
01206 
01207     static INLINE void TrackFree(void* ptr)
01208     {
01209         memoryTrack* mt;
01210 
01211         if (ptr == NULL)
01212             return;
01213 
01214         mt = (memoryTrack*)ptr;
01215         --mt;   /* same as minus sizeof(memoryTrack), removes header */
01216 
01217 #ifdef DO_MEM_STATS 
01218         ourMemStats.currentBytes -= mt->u.hint.thisSize; 
01219 #endif
01220 
01221         free(mt);
01222     }
01223 
01224 
01225     static INLINE void* TrackRealloc(void* ptr, size_t sz)
01226     {
01227         void* ret = TrackMalloc(sz);
01228 
01229         if (ptr) {
01230             /* if realloc is bigger, don't overread old ptr */
01231             memoryTrack* mt = (memoryTrack*)ptr;
01232             --mt;  /* same as minus sizeof(memoryTrack), removes header */
01233 
01234             if (mt->u.hint.thisSize < sz)
01235                 sz = mt->u.hint.thisSize;
01236         }
01237 
01238         if (ret && ptr)
01239             memcpy(ret, ptr, sz);
01240 
01241         if (ret)
01242             TrackFree(ptr);
01243 
01244         return ret;
01245     }
01246 
01247     static INLINE void InitMemoryTracker(void) 
01248     {
01249         if (CyaSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc) != 0)
01250             err_sys("CyaSSL SetAllocators failed for track memory");
01251 
01252     #ifdef DO_MEM_STATS
01253         ourMemStats.totalAllocs  = 0;
01254         ourMemStats.totalBytes   = 0;
01255         ourMemStats.peakBytes    = 0;
01256         ourMemStats.currentBytes = 0;
01257     #endif
01258     }
01259 
01260     static INLINE void ShowMemoryTracker(void) 
01261     {
01262     #ifdef DO_MEM_STATS 
01263         printf("total   Allocs = %9lu\n",
01264                                        (unsigned long)ourMemStats.totalAllocs);
01265         printf("total   Bytes  = %9lu\n",
01266                                        (unsigned long)ourMemStats.totalBytes);
01267         printf("peak    Bytes  = %9lu\n",
01268                                        (unsigned long)ourMemStats.peakBytes);
01269         printf("current Bytes  = %9lu\n",
01270                                        (unsigned long)ourMemStats.currentBytes);
01271     #endif
01272     }
01273 
01274 #endif /* USE_CYASSL_MEMORY */
01275 
01276 
01277 #ifdef HAVE_STACK_SIZE
01278 
01279 typedef THREAD_RETURN CYASSL_THREAD (*thread_func)(void* args);
01280 
01281 
01282 static INLINE void StackSizeCheck(func_args* args, thread_func tf)
01283 {
01284     int            ret, i, used;
01285     unsigned char* myStack;
01286     int            stackSize = 1024*128;
01287     pthread_attr_t myAttr;
01288     pthread_t      threadId;
01289 
01290 #ifdef PTHREAD_STACK_MIN
01291     if (stackSize < PTHREAD_STACK_MIN)
01292         stackSize = PTHREAD_STACK_MIN;
01293 #endif
01294 
01295     ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize);
01296     if (ret != 0) 
01297         err_sys("posix_memalign failed\n");        
01298 
01299     memset(myStack, 0x01, stackSize);
01300 
01301     ret = pthread_attr_init(&myAttr);
01302     if (ret != 0)
01303         err_sys("attr_init failed");
01304 
01305     ret = pthread_attr_setstack(&myAttr, myStack, stackSize);
01306     if (ret != 0)
01307         err_sys("attr_setstackaddr failed");
01308 
01309     ret = pthread_create(&threadId, &myAttr, tf, args);
01310     if (ret != 0) {
01311         perror("pthread_create failed");
01312         exit(EXIT_FAILURE);
01313     }
01314 
01315     ret = pthread_join(threadId, NULL);
01316     if (ret != 0)
01317         err_sys("pthread_join failed");
01318 
01319     for (i = 0; i < stackSize; i++) {
01320         if (myStack[i] != 0x01) {
01321             break;
01322         }
01323     }
01324 
01325     used = stackSize - i;
01326     printf("stack used = %d\n", used);
01327 }
01328 
01329 
01330 #endif /* HAVE_STACK_SIZE */
01331 
01332 
01333 #ifdef STACK_TRAP
01334 
01335 /* good settings
01336    --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP"
01337 
01338 */
01339 
01340 #ifdef HAVE_STACK_SIZE
01341     /* client only for now, setrlimit will fail if pthread_create() called */
01342     /* STACK_SIZE does pthread_create() on client */
01343     #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail"
01344 #endif /* HAVE_STACK_SIZE */
01345 
01346 static INLINE void StackTrap(void)
01347 {
01348     struct rlimit  rl;
01349     if (getrlimit(RLIMIT_STACK, &rl) != 0)
01350         err_sys("getrlimit failed");
01351     printf("rlim_cur = %llu\n", rl.rlim_cur);
01352     rl.rlim_cur = 1024*21;  /* adjust trap size here */
01353     if (setrlimit(RLIMIT_STACK, &rl) != 0) {
01354         perror("setrlimit");
01355         err_sys("setrlimit failed");
01356     }
01357 }
01358 
01359 #else /* STACK_TRAP */
01360 
01361 static INLINE void StackTrap(void)
01362 {
01363 }
01364 
01365 #endif /* STACK_TRAP */
01366 
01367 
01368 #ifdef ATOMIC_USER
01369 
01370 /* Atomic Encrypt Context example */
01371 typedef struct AtomicEncCtx {
01372     int  keySetup;           /* have we done key setup yet */
01373     Aes  aes;                /* for aes example */
01374 } AtomicEncCtx;
01375 
01376 
01377 /* Atomic Decrypt Context example */
01378 typedef struct AtomicDecCtx {
01379     int  keySetup;           /* have we done key setup yet */
01380     Aes  aes;                /* for aes example */
01381 } AtomicDecCtx;
01382 
01383 
01384 static INLINE int myMacEncryptCb(CYASSL* ssl, unsigned char* macOut, 
01385        const unsigned char* macIn, unsigned int macInSz, int macContent, 
01386        int macVerify, unsigned char* encOut, const unsigned char* encIn,
01387        unsigned int encSz, void* ctx)
01388 {
01389     int  ret;
01390     Hmac hmac;
01391     byte myInner[CYASSL_TLS_HMAC_INNER_SZ];
01392     AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx;
01393     const char* tlsStr = "TLS";
01394 
01395     /* example supports (d)tls aes */
01396     if (CyaSSL_GetBulkCipher(ssl) != cyassl_aes) {
01397         printf("myMacEncryptCb not using AES\n");
01398         return -1;
01399     }
01400 
01401     if (strstr(CyaSSL_get_version(ssl), tlsStr) == NULL) {
01402         printf("myMacEncryptCb not using (D)TLS\n");
01403         return -1;
01404     }
01405 
01406     /* hmac, not needed if aead mode */
01407     CyaSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
01408 
01409     ret = HmacSetKey(&hmac, CyaSSL_GetHmacType(ssl),
01410                CyaSSL_GetMacSecret(ssl, macVerify), CyaSSL_GetHmacSize(ssl));
01411     if (ret != 0)
01412         return ret;
01413     ret = HmacUpdate(&hmac, myInner, sizeof(myInner));
01414     if (ret != 0)
01415         return ret;
01416     ret = HmacUpdate(&hmac, macIn, macInSz);
01417     if (ret != 0)
01418         return ret;
01419     ret = HmacFinal(&hmac, macOut);
01420     if (ret != 0)
01421         return ret;
01422 
01423 
01424     /* encrypt setup on first time */
01425     if (encCtx->keySetup == 0) {
01426         int   keyLen = CyaSSL_GetKeySize(ssl);
01427         const byte* key;
01428         const byte* iv;
01429 
01430         if (CyaSSL_GetSide(ssl) == CYASSL_CLIENT_END) {
01431             key = CyaSSL_GetClientWriteKey(ssl);
01432             iv  = CyaSSL_GetClientWriteIV(ssl);
01433         }
01434         else {
01435             key = CyaSSL_GetServerWriteKey(ssl);
01436             iv  = CyaSSL_GetServerWriteIV(ssl);
01437         }
01438 
01439         ret = AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION);
01440         if (ret != 0) {
01441             printf("AesSetKey failed in myMacEncryptCb\n");
01442             return ret;
01443         }
01444         encCtx->keySetup = 1;
01445     }
01446 
01447     /* encrypt */
01448     return AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz);
01449 }
01450 
01451 
01452 static INLINE int myDecryptVerifyCb(CYASSL* ssl, 
01453        unsigned char* decOut, const unsigned char* decIn,
01454        unsigned int decSz, int macContent, int macVerify,
01455        unsigned int* padSz, void* ctx)
01456 {
01457     AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx;
01458     int ret      = 0;
01459     int macInSz  = 0;
01460     int ivExtra  = 0;
01461     int digestSz = CyaSSL_GetHmacSize(ssl);
01462     unsigned int pad     = 0;
01463     unsigned int padByte = 0;
01464     Hmac hmac;
01465     byte myInner[CYASSL_TLS_HMAC_INNER_SZ];
01466     byte verify[MAX_DIGEST_SIZE];
01467     const char* tlsStr = "TLS";
01468 
01469     /* example supports (d)tls aes */
01470     if (CyaSSL_GetBulkCipher(ssl) != cyassl_aes) {
01471         printf("myMacEncryptCb not using AES\n");
01472         return -1;
01473     }
01474 
01475     if (strstr(CyaSSL_get_version(ssl), tlsStr) == NULL) {
01476         printf("myMacEncryptCb not using (D)TLS\n");
01477         return -1;
01478     }
01479 
01480     /*decrypt */
01481     if (decCtx->keySetup == 0) {
01482         int   keyLen = CyaSSL_GetKeySize(ssl);
01483         const byte* key;
01484         const byte* iv;
01485 
01486         /* decrypt is from other side (peer) */
01487         if (CyaSSL_GetSide(ssl) == CYASSL_SERVER_END) {
01488             key = CyaSSL_GetClientWriteKey(ssl);
01489             iv  = CyaSSL_GetClientWriteIV(ssl);
01490         }
01491         else {
01492             key = CyaSSL_GetServerWriteKey(ssl);
01493             iv  = CyaSSL_GetServerWriteIV(ssl);
01494         }
01495 
01496         ret = AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION);
01497         if (ret != 0) {
01498             printf("AesSetKey failed in myDecryptVerifyCb\n");
01499             return ret;
01500         }
01501         decCtx->keySetup = 1;
01502     }
01503 
01504     /* decrypt */
01505     ret = AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz);
01506 
01507     if (CyaSSL_GetCipherType(ssl) == CYASSL_AEAD_TYPE) {
01508         *padSz = CyaSSL_GetAeadMacSize(ssl);
01509         return 0; /* hmac, not needed if aead mode */
01510     }
01511 
01512     if (CyaSSL_GetCipherType(ssl) == CYASSL_BLOCK_TYPE) {
01513         pad     = *(decOut + decSz - 1);
01514         padByte = 1;
01515         if (CyaSSL_IsTLSv1_1(ssl))
01516             ivExtra = CyaSSL_GetCipherBlockSize(ssl);
01517     }
01518 
01519     *padSz  = CyaSSL_GetHmacSize(ssl) + pad + padByte;
01520     macInSz = decSz - ivExtra - digestSz - pad - padByte;
01521 
01522     CyaSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify);
01523 
01524     ret = HmacSetKey(&hmac, CyaSSL_GetHmacType(ssl),
01525                CyaSSL_GetMacSecret(ssl, macVerify), digestSz);
01526     if (ret != 0)
01527         return ret;
01528     ret = HmacUpdate(&hmac, myInner, sizeof(myInner));
01529     if (ret != 0)
01530         return ret;
01531     ret = HmacUpdate(&hmac, decOut + ivExtra, macInSz);
01532     if (ret != 0)
01533         return ret;
01534     ret = HmacFinal(&hmac, verify);
01535     if (ret != 0)
01536         return ret;
01537 
01538     if (memcmp(verify, decOut + decSz - digestSz - pad - padByte,
01539                digestSz) != 0) {
01540         printf("myDecryptVerify verify failed\n");
01541         return -1;
01542     }
01543 
01544     return ret;
01545 }
01546 
01547 
01548 static INLINE void SetupAtomicUser(CYASSL_CTX* ctx, CYASSL* ssl)
01549 {
01550     AtomicEncCtx* encCtx;
01551     AtomicDecCtx* decCtx;
01552 
01553     encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx));
01554     if (encCtx == NULL)
01555         err_sys("AtomicEncCtx malloc failed");
01556     memset(encCtx, 0, sizeof(AtomicEncCtx));
01557 
01558     decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx));
01559     if (decCtx == NULL) {
01560         free(encCtx);
01561         err_sys("AtomicDecCtx malloc failed");
01562     }
01563     memset(decCtx, 0, sizeof(AtomicDecCtx));
01564 
01565     CyaSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb);
01566     CyaSSL_SetMacEncryptCtx(ssl, encCtx);
01567 
01568     CyaSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb);
01569     CyaSSL_SetDecryptVerifyCtx(ssl, decCtx);
01570 }
01571 
01572 
01573 static INLINE void FreeAtomicUser(CYASSL* ssl)
01574 {
01575     AtomicEncCtx* encCtx = (AtomicEncCtx*)CyaSSL_GetMacEncryptCtx(ssl);
01576     AtomicDecCtx* decCtx = (AtomicDecCtx*)CyaSSL_GetDecryptVerifyCtx(ssl);
01577 
01578     free(decCtx);
01579     free(encCtx);
01580 }
01581 
01582 #endif /* ATOMIC_USER */
01583 
01584 
01585 #ifdef HAVE_PK_CALLBACKS
01586 
01587 #ifdef HAVE_ECC
01588 
01589 static INLINE int myEccSign(CYASSL* ssl, const byte* in, word32 inSz,
01590         byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
01591 {
01592     RNG     rng;
01593     int     ret;
01594     word32  idx = 0;
01595     ecc_key myKey;
01596 
01597     (void)ssl;
01598     (void)ctx;
01599 
01600     ret = InitRng(&rng);
01601     if (ret != 0)
01602         return ret;
01603 
01604     ecc_init(&myKey);
01605     
01606     ret = EccPrivateKeyDecode(key, &idx, &myKey, keySz);    
01607     if (ret == 0)
01608         ret = ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey);
01609     ecc_free(&myKey);
01610 
01611     return ret;
01612 }
01613 
01614 
01615 static INLINE int myEccVerify(CYASSL* ssl, const byte* sig, word32 sigSz,
01616         const byte* hash, word32 hashSz, const byte* key, word32 keySz,
01617         int* result, void* ctx)
01618 {
01619     int     ret;
01620     ecc_key myKey;
01621 
01622     (void)ssl;
01623     (void)ctx;
01624 
01625     ecc_init(&myKey);
01626     
01627     ret = ecc_import_x963(key, keySz, &myKey);
01628     if (ret == 0)
01629         ret = ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey);
01630     ecc_free(&myKey);
01631 
01632     return ret;
01633 }
01634 
01635 #endif /* HAVE_ECC */
01636 
01637 #ifndef NO_RSA
01638 
01639 static INLINE int myRsaSign(CYASSL* ssl, const byte* in, word32 inSz,
01640         byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
01641 {
01642     RNG     rng;
01643     int     ret;
01644     word32  idx = 0;
01645     RsaKey  myKey;
01646 
01647     (void)ssl;
01648     (void)ctx;
01649 
01650     ret = InitRng(&rng);
01651     if (ret != 0)
01652         return ret;
01653 
01654     InitRsaKey(&myKey, NULL);
01655     
01656     ret = RsaPrivateKeyDecode(key, &idx, &myKey, keySz);    
01657     if (ret == 0)
01658         ret = RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng);
01659     if (ret > 0) {  /* save and convert to 0 success */
01660         *outSz = ret;
01661         ret = 0;
01662     }
01663     FreeRsaKey(&myKey);
01664 
01665     return ret;
01666 }
01667 
01668 
01669 static INLINE int myRsaVerify(CYASSL* ssl, byte* sig, word32 sigSz,
01670         byte** out,
01671         const byte* key, word32 keySz,
01672         void* ctx)
01673 {
01674     int     ret;
01675     word32  idx = 0;
01676     RsaKey  myKey;
01677 
01678     (void)ssl;
01679     (void)ctx;
01680 
01681     InitRsaKey(&myKey, NULL);
01682     
01683     ret = RsaPublicKeyDecode(key, &idx, &myKey, keySz);
01684     if (ret == 0)
01685         ret = RsaSSL_VerifyInline(sig, sigSz, out, &myKey);
01686     FreeRsaKey(&myKey);
01687 
01688     return ret;
01689 }
01690 
01691 
01692 static INLINE int myRsaEnc(CYASSL* ssl, const byte* in, word32 inSz,
01693                            byte* out, word32* outSz, const byte* key,
01694                            word32 keySz, void* ctx)
01695 {
01696     int     ret;
01697     word32  idx = 0;
01698     RsaKey  myKey;
01699     RNG     rng;
01700 
01701     (void)ssl;
01702     (void)ctx;
01703 
01704     ret = InitRng(&rng);
01705     if (ret != 0)
01706         return ret;
01707 
01708     InitRsaKey(&myKey, NULL);
01709     
01710     ret = RsaPublicKeyDecode(key, &idx, &myKey, keySz);
01711     if (ret == 0) {
01712         ret = RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng);
01713         if (ret > 0) {
01714             *outSz = ret;
01715             ret = 0;  /* reset to success */
01716         }
01717     }
01718     FreeRsaKey(&myKey);
01719 
01720     return ret;
01721 }
01722 
01723 static INLINE int myRsaDec(CYASSL* ssl, byte* in, word32 inSz,
01724                            byte** out,
01725                            const byte* key, word32 keySz, void* ctx)
01726 {
01727     int     ret;
01728     word32  idx = 0;
01729     RsaKey  myKey;
01730 
01731     (void)ssl;
01732     (void)ctx;
01733 
01734     InitRsaKey(&myKey, NULL);
01735     
01736     ret = RsaPrivateKeyDecode(key, &idx, &myKey, keySz);
01737     if (ret == 0) {
01738         ret = RsaPrivateDecryptInline(in, inSz, out, &myKey);
01739     }
01740     FreeRsaKey(&myKey);
01741 
01742     return ret;
01743 }
01744 
01745 #endif /* NO_RSA */
01746 
01747 static INLINE void SetupPkCallbacks(CYASSL_CTX* ctx, CYASSL* ssl)
01748 {
01749     (void)ctx;
01750     (void)ssl;
01751 
01752     #ifdef HAVE_ECC
01753         CyaSSL_CTX_SetEccSignCb(ctx, myEccSign);
01754         CyaSSL_CTX_SetEccVerifyCb(ctx, myEccVerify);
01755     #endif /* HAVE_ECC */
01756     #ifndef NO_RSA 
01757         CyaSSL_CTX_SetRsaSignCb(ctx, myRsaSign);
01758         CyaSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify);
01759         CyaSSL_CTX_SetRsaEncCb(ctx, myRsaEnc);
01760         CyaSSL_CTX_SetRsaDecCb(ctx, myRsaDec);
01761     #endif /* NO_RSA */
01762 }
01763 
01764 #endif /* HAVE_PK_CALLBACKS */
01765 
01766 
01767 
01768 
01769 
01770 #if defined(__hpux__) || defined(__MINGW32__) || defined (CYASSL_TIRTOS)
01771 
01772 /* HP/UX doesn't have strsep, needed by test/suites.c */
01773 static INLINE char* strsep(char **stringp, const char *delim)
01774 {
01775     char* start;
01776     char* end;
01777 
01778     start = *stringp;
01779     if (start == NULL)
01780         return NULL;
01781 
01782     if ((end = strpbrk(start, delim))) {
01783         *end++ = '\0';
01784         *stringp = end;
01785     } else {
01786         *stringp = NULL;
01787     }
01788 
01789     return start;
01790 }
01791 
01792 #endif /* __hpux__ */
01793 
01794 #endif /* CyaSSL_TEST_H */
01795