From 5ac03256db0fe4ca7e3ad1117d096c3a76368b76 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Fri, 9 Jan 2015 09:46:07 +0100 Subject: backported CyaSSL/OpenSSL support for internal webserver instead of MatrixSSL --- .../router/cyassl/include/openssl/cyassl_test.h | 563 +++++++++++++++++++++ 1 file changed, 563 insertions(+) create mode 100644 release/src/router/cyassl/include/openssl/cyassl_test.h (limited to 'release/src/router/cyassl/include/openssl/cyassl_test.h') diff --git a/release/src/router/cyassl/include/openssl/cyassl_test.h b/release/src/router/cyassl/include/openssl/cyassl_test.h new file mode 100644 index 00000000..555f3e19 --- /dev/null +++ b/release/src/router/cyassl/include/openssl/cyassl_test.h @@ -0,0 +1,563 @@ +/* cyassl_test.h */ + +#ifndef CyaSSL_TEST_H +#define CyaSSL_TEST_H + +#include +#include +#include +#include +#include "types.h" + +#ifdef USE_WINDOWS_API + #include + #include + #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ + #include + #include + #endif + #define SOCKET_T int +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifdef NON_BLOCKING + #include + #endif + #ifdef TEST_IPV6 + #include + #endif + #define SOCKET_T unsigned int +#endif /* USE_WINDOWS_API */ + +#ifdef _MSC_VER + /* disable conversion warning */ + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable:4244 4996) +#endif + +#if defined(__MACH__) || defined(USE_WINDOWS_API) + #ifndef _SOCKLEN_T + typedef int socklen_t; + #endif +#endif + + +/* HPUX doesn't use socklent_t for third parameter to accept */ +#if !defined(__hpux__) + typedef socklen_t* ACCEPT_THIRD_T; +#else + typedef int* ACCEPT_THIRD_T; +#endif + + +#ifdef USE_WINDOWS_API + #define CloseSocket(s) closesocket(s) + #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } +#else + #define CloseSocket(s) close(s) + #define StartTCP() +#endif + + +#ifdef SINGLE_THREADED + typedef unsigned int THREAD_RETURN; + typedef void* THREAD_TYPE; + #define CYASSL_API +#else + #ifndef _POSIX_THREADS + typedef unsigned int THREAD_RETURN; + typedef HANDLE THREAD_TYPE; + #define CYASSL_API __stdcall + #else + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define CYASSL_API + #endif +#endif + + +#ifdef TEST_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + +#ifndef NO_MAIN_DRIVER + const char* caCert = "../../certs/ca-cert.pem"; + const char* eccCert = "../../certs/server-ecc.pem"; + const char* eccKey = "../../certs/ecc-key.pem"; + const char* svrCert = "../../certs/server-cert.pem"; + const char* svrKey = "../../certs/server-key.pem"; + const char* cliCert = "../../certs/client-cert.pem"; + const char* cliKey = "../../certs/client-key.pem"; + const char* ntruCert = "../../certs/ntru-cert.pem"; + const char* ntruKey = "../../certs/ntru-key.raw"; +#else + static const char* caCert = "../certs/ca-cert.pem"; + static const char* eccCert = "../certs/server-ecc.pem"; + static const char* eccKey = "../certs/ecc-key.pem"; + static const char* svrCert = "../certs/server-cert.pem"; + static const char* svrKey = "../certs/server-key.pem"; + static const char* cliCert = "../certs/client-cert.pem"; + static const char* cliKey = "../certs/client-key.pem"; + static const char* ntruCert = "../certs/ntru-cert.pem"; + static const char* ntruKey = "../certs/ntru-key.raw"; +#endif + +typedef struct tcp_ready { + int ready; /* predicate */ +#ifdef _POSIX_THREADS + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif +} tcp_ready; + + +void InitTcpReady(); +void FreeTcpReady(); + + +typedef struct func_args { + int argc; + char** argv; + int return_code; + tcp_ready* signal; +} func_args; + + +typedef THREAD_RETURN CYASSL_API THREAD_FUNC(void*); + +void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); +void join_thread(THREAD_TYPE); + +/* yaSSL */ +static const char* const yasslIP = "127.0.0.1"; +static const word16 yasslPort = 11111; + + +static INLINE void err_sys(const char* msg) +{ + printf("yassl error: %s\n", msg); + exit(EXIT_FAILURE); +} + + +#ifdef OPENSSL_EXTRA + +static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + strncpy(passwd, "yassl123", sz); + return 8; +} + +#endif + + +static INLINE void showPeer(SSL* ssl) +{ +#ifdef OPENSSL_EXTRA + + SSL_CIPHER* cipher; + X509* peer = SSL_get_peer_certificate(ssl); + if (peer) { + char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0); + char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0); + + printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, + subject); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + } + else + printf("peer has no cert!\n"); + printf("SSL version is %s\n", SSL_get_version(ssl)); + + cipher = SSL_get_current_cipher(ssl); + printf("SSL cipher suite is %s\n", SSL_CIPHER_get_name(cipher)); +#endif + +#ifdef SESSION_CERTS + { + X509_CHAIN* chain = CyaSSL_get_peer_chain(ssl); + int count = CyaSSL_get_chain_count(chain); + int i; + + for (i = 0; i < count; i++) { + int length; + unsigned char buffer[3072]; + + CyaSSL_get_chain_cert_pem(chain,i,buffer, sizeof(buffer), &length); + buffer[length] = 0; + printf("cert %d has length %d data = \n%s\n", i, length, buffer); + } + } +#endif + +} + + +static INLINE void tcp_socket(SOCKET_T* sockfd, SOCKADDR_IN_T* addr, + const char* peer, word16 port) +{ +#ifndef TEST_IPV6 + const char* host = peer; + + /* peer could be in human readable form */ + if (peer != INADDR_ANY && isalpha(peer[0])) { + struct hostent* entry = gethostbyname(peer); + + if (entry) { + struct sockaddr_in tmp; + memset(&tmp, 0, sizeof(struct sockaddr_in)); + memcpy(&tmp.sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + host = inet_ntoa(tmp.sin_addr); + } + else + err_sys("no entry for host"); + } +#endif + +#ifdef CYASSL_DTLS + *sockfd = socket(AF_INET_V, SOCK_DGRAM, 0); +#else + *sockfd = socket(AF_INET_V, SOCK_STREAM, 0); +#endif + memset(addr, 0, sizeof(SOCKADDR_IN_T)); + +#ifndef TEST_IPV6 + addr->sin_family = AF_INET_V; + addr->sin_port = htons(port); + if (host == INADDR_ANY) + addr->sin_addr.s_addr = INADDR_ANY; + else + addr->sin_addr.s_addr = inet_addr(host); +#else + addr->sin6_family = AF_INET_V; + addr->sin6_port = htons(port); + addr->sin6_addr = in6addr_loopback; +#endif + +#ifndef USE_WINDOWS_API +#ifdef SO_NOSIGPIPE + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); + if (res < 0) + err_sys("setsockopt SO_NOSIGPIPE failed\n"); + } +#endif + +#if defined(TCP_NODELAY) && !defined(CYASSL_DTLS) + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len); + if (res < 0) + err_sys("setsockopt TCP_NODELAY failed\n"); + } +#endif +#endif /* USE_WINDOWS_API */ +} + + +static INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port) +{ + SOCKADDR_IN_T addr; + tcp_socket(sockfd, &addr, ip, port); + + if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp connect failed"); +} + + +static INLINE void tcp_listen(SOCKET_T* sockfd) +{ + SOCKADDR_IN_T addr; + + /* don't use INADDR_ANY by default, firewall may block, make user switch + on */ +#ifdef USE_ANY_ADDR + tcp_socket(sockfd, &addr, INADDR_ANY, yasslPort); +#else + tcp_socket(sockfd, &addr, yasslIP, yasslPort); +#endif + +#ifndef USE_WINDOWS_API + { + int on = 1; + socklen_t len = sizeof(on); + setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); +#ifndef CYASSL_DTLS + if (listen(*sockfd, 5) != 0) + err_sys("tcp listen failed"); +#endif +} + + +static INLINE int udp_read_connect(SOCKET_T sockfd) +{ + SOCKADDR_IN_T cliaddr; + byte b[1500]; + int n; + socklen_t len = sizeof(cliaddr); + + n = recvfrom(sockfd, b, sizeof(b), MSG_PEEK, (struct sockaddr*)&cliaddr, + &len); + if (n > 0) { + if (connect(sockfd, (const struct sockaddr*)&cliaddr, + sizeof(cliaddr)) != 0) + err_sys("udp connect failed"); + } + else + err_sys("recvfrom failed"); + + return sockfd; +} + +static INLINE void udp_accept(SOCKET_T* sockfd, int* clientfd, func_args* args) +{ + SOCKADDR_IN_T addr; + + tcp_socket(sockfd, &addr, yasslIP, yasslPort); + + +#ifndef USE_WINDOWS_API + { + int on = 1; + socklen_t len = sizeof(on); + setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + +#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) + /* signal ready to accept data */ + { + tcp_ready* ready = args->signal; + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } +#endif + + *clientfd = udp_read_connect(*sockfd); +} + +static INLINE void tcp_accept(SOCKET_T* sockfd, int* clientfd, func_args* args) +{ + SOCKADDR_IN_T client; + socklen_t client_len = sizeof(client); + + #ifdef CYASSL_DTLS + udp_accept(sockfd, clientfd, args); + return; + #endif + + tcp_listen(sockfd); + +#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) + /* signal ready to tcp_accept */ + { + tcp_ready* ready = args->signal; + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } +#endif + + *clientfd = accept(*sockfd, (struct sockaddr*)&client, + (ACCEPT_THIRD_T)&client_len); + if (*clientfd == -1) + err_sys("tcp accept failed"); +} + + +static INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) +{ +#ifdef NON_BLOCKING + #ifdef USE_WINDOWS_API + unsigned long blocking = 1; + int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); + #else + int flags = fcntl(*sockfd, F_GETFL, 0); + int ret = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK); + #endif +#endif +} + + +#ifndef NO_PSK + +static INLINE unsigned int my_psk_client_cb(SSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + /* identity is OpenSSL testing default for openssl s_client, keep same */ + strncpy(identity, "Client_identity", id_max_len); + + + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return 4; /* length of key in octets or 0 for error */ +} + + +static INLINE unsigned int my_psk_server_cb(SSL* ssl, const char* identity, + unsigned char* key, unsigned int key_max_len) +{ + /* identity is OpenSSL testing default for openssl s_client, keep same */ + if (strncmp(identity, "Client_identity", 15) != 0) + return 0; + + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 26; + key[1] = 43; + key[2] = 60; + key[3] = 77; + + return 4; /* length of key in octets or 0 for error */ +} + +#endif /* NO_PSK */ + + +#ifdef USE_WINDOWS_API + + #define WIN32_LEAN_AND_MEAN + #include + + static INLINE double current_time() + { + static int init = 0; + static LARGE_INTEGER freq; + + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (double)count.QuadPart / freq.QuadPart; + } + +#else + + #include + + static INLINE double current_time() + { + struct timeval tv; + gettimeofday(&tv, 0); + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; + } + +#endif /* USE_WINDOWS_API */ + + +#ifdef NO_FILESYSTEM + + enum { + CYASSL_CA = 1, + CYASSL_CERT = 2, + CYASSL_KEY = 3 + }; + + static INLINE void load_buffer(SSL_CTX* ctx, const char* fname, int type) + { + /* test buffer load */ + long sz = 0; + byte buff[4096]; + FILE* file = fopen(fname, "rb"); + + if (!file) + err_sys("can't open file for buffer load"); + fseek(file, 0, SEEK_END); + sz = ftell(file); + rewind(file); + fread(buff, sizeof(buff), 1, file); + + if (type == CYASSL_CA) { + if (CyaSSL_CTX_load_verify_buffer(ctx, buff, sz, SSL_FILETYPE_PEM) + != SSL_SUCCESS) + err_sys("can't load buffer ca file"); + } + else if (type == CYASSL_CERT) { + if (CyaSSL_CTX_use_certificate_buffer(ctx, buff, sz, + SSL_FILETYPE_PEM) != SSL_SUCCESS) + err_sys("can't load buffer cert file"); + } + else if (type == CYASSL_KEY) { + if (CyaSSL_CTX_use_PrivateKey_buffer(ctx, buff, sz, + SSL_FILETYPE_PEM) != SSL_SUCCESS) + err_sys("can't load buffer key file"); + } + } + +#endif /* NO_FILESYSTEM */ + +#ifdef VERIFY_CALLBACK + +static int myVerify(int preverify, X509_STORE_CTX* store) +{ + char buffer[80]; + + printf("In verification callback, error = %d, %s\n", store->error, + ERR_error_string(store->error, buffer)); +#ifdef OPENSSL_EXTRA + X509* peer = store->current_cert; + if (peer) { + char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0); + char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0); + + printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer, + subject); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + } + else + printf("peer has no cert!\n"); +#endif + printf("Subject's domain name is %s\n", store->domain); + + printf("Allowing to continue anyway (shouldn't do this, EVER!!!)\n"); + return 1; +} + +#endif /* VERIFY_CALLBACK */ + + +#endif /* CyaSSL_TEST_H */ + -- cgit v1.2.3-54-g00ecf