diff options
Diffstat (limited to 'libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c')
-rw-r--r-- | libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c | 1983 |
1 files changed, 1983 insertions, 0 deletions
diff --git a/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c new file mode 100644 index 0000000000..d525e1a686 --- /dev/null +++ b/libs/luci-lib-nixio/axTLS/ssl/test/ssltest.c @@ -0,0 +1,1983 @@ +/* + * Copyright (c) 2007, Cameron Rich + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the axTLS project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The testing of the crypto and ssl stuff goes here. Keeps the individual code + * modules from being uncluttered with test code. + * + * This is test code - I make no apologies for the quality! + */ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef WIN32 +#include <pthread.h> +#endif + +#include "ssl.h" + +#define DEFAULT_CERT "../ssl/test/axTLS.x509_512.cer" +#define DEFAULT_KEY "../ssl/test/axTLS.key_512" +//#define DEFAULT_SVR_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES +#define DEFAULT_SVR_OPTION 0 +#define DEFAULT_CLNT_OPTION 0 +//#define DEFAULT_CLNT_OPTION SSL_DISPLAY_BYTES|SSL_DISPLAY_STATES + +static int g_port = 19001; + +/************************************************************************** + * AES tests + * + * Run through a couple of the RFC3602 tests to verify that AES is correct. + **************************************************************************/ +#define TEST1_SIZE 16 +#define TEST2_SIZE 32 + +static int AES_test(BI_CTX *bi_ctx) +{ + AES_CTX aes_key; + int res = 1; + uint8_t key[TEST1_SIZE]; + uint8_t iv[TEST1_SIZE]; + + { + /* + Case #1: Encrypting 16 bytes (1 block) using AES-CBC + Key : 0x06a9214036b8a15b512e03d534120006 + IV : 0x3dafba429d9eb430b422da802c9fac41 + Plaintext : "Single block msg" + Ciphertext: 0xe353779c1079aeb82708942dbe77181a + + */ + char *in_str = "Single block msg"; + uint8_t ct[TEST1_SIZE]; + uint8_t enc_data[TEST1_SIZE]; + uint8_t dec_data[TEST1_SIZE]; + + bigint *key_bi = bi_str_import( + bi_ctx, "06A9214036B8A15B512E03D534120006"); + bigint *iv_bi = bi_str_import( + bi_ctx, "3DAFBA429D9EB430B422DA802C9FAC41"); + bigint *ct_bi = bi_str_import( + bi_ctx, "E353779C1079AEB82708942DBE77181A"); + bi_export(bi_ctx, key_bi, key, TEST1_SIZE); + bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE); + bi_export(bi_ctx, ct_bi, ct, TEST1_SIZE); + + AES_set_key(&aes_key, key, iv, AES_MODE_128); + AES_cbc_encrypt(&aes_key, (const uint8_t *)in_str, + enc_data, sizeof(enc_data)); + if (memcmp(enc_data, ct, sizeof(ct))) + { + printf("Error: AES ENCRYPT #1 failed\n"); + goto end; + } + + AES_set_key(&aes_key, key, iv, AES_MODE_128); + AES_convert_key(&aes_key); + AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data)); + + if (memcmp(dec_data, in_str, sizeof(dec_data))) + { + printf("Error: AES DECRYPT #1 failed\n"); + goto end; + } + } + + { + /* + Case #2: Encrypting 32 bytes (2 blocks) using AES-CBC + Key : 0xc286696d887c9aa0611bbb3e2025a45a + IV : 0x562e17996d093d28ddb3ba695a2e6f58 + Plaintext : 0x000102030405060708090a0b0c0d0e0f + 101112131415161718191a1b1c1d1e1f + Ciphertext: 0xd296cd94c2cccf8a3a863028b5e1dc0a + 7586602d253cfff91b8266bea6d61ab1 + */ + uint8_t in_data[TEST2_SIZE]; + uint8_t ct[TEST2_SIZE]; + uint8_t enc_data[TEST2_SIZE]; + uint8_t dec_data[TEST2_SIZE]; + + bigint *in_bi = bi_str_import(bi_ctx, + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"); + bigint *key_bi = bi_str_import( + bi_ctx, "C286696D887C9AA0611BBB3E2025A45A"); + bigint *iv_bi = bi_str_import( + bi_ctx, "562E17996D093D28DDB3BA695A2E6F58"); + bigint *ct_bi = bi_str_import(bi_ctx, + "D296CD94C2CCCF8A3A863028B5E1DC0A7586602D253CFFF91B8266BEA6D61AB1"); + bi_export(bi_ctx, in_bi, in_data, TEST2_SIZE); + bi_export(bi_ctx, key_bi, key, TEST1_SIZE); + bi_export(bi_ctx, iv_bi, iv, TEST1_SIZE); + bi_export(bi_ctx, ct_bi, ct, TEST2_SIZE); + + AES_set_key(&aes_key, key, iv, AES_MODE_128); + AES_cbc_encrypt(&aes_key, (const uint8_t *)in_data, + enc_data, sizeof(enc_data)); + + if (memcmp(enc_data, ct, sizeof(ct))) + { + printf("Error: ENCRYPT #2 failed\n"); + goto end; + } + + AES_set_key(&aes_key, key, iv, AES_MODE_128); + AES_convert_key(&aes_key); + AES_cbc_decrypt(&aes_key, enc_data, dec_data, sizeof(enc_data)); + if (memcmp(dec_data, in_data, sizeof(dec_data))) + { + printf("Error: DECRYPT #2 failed\n"); + goto end; + } + } + + res = 0; + printf("All AES tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * RC4 tests + * + * ARC4 tests vectors from OpenSSL (crypto/rc4/rc4test.c) + **************************************************************************/ +static const uint8_t keys[7][30]= +{ + {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}, + {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}, + {8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {4,0xef,0x01,0x23,0x45}, + {8,0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}, + {4,0xef,0x01,0x23,0x45}, +}; + +static const uint8_t data_len[7]={8,8,8,20,28,10}; +static uint8_t data[7][30]= +{ + {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xff}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff}, + {0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0, + 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0, + 0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0, + 0x12,0x34,0x56,0x78,0xff}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, + {0}, +}; + +static const uint8_t output[7][30]= +{ + {0x75,0xb7,0x87,0x80,0x99,0xe0,0xc5,0x96,0x00}, + {0x74,0x94,0xc2,0xe7,0x10,0x4b,0x08,0x79,0x00}, + {0xde,0x18,0x89,0x41,0xa3,0x37,0x5d,0x3a,0x00}, + {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf, + 0xbd,0x61,0x5a,0x11,0x62,0xe1,0xc7,0xba, + 0x36,0xb6,0x78,0x58,0x00}, + {0x66,0xa0,0x94,0x9f,0x8a,0xf7,0xd6,0x89, + 0x1f,0x7f,0x83,0x2b,0xa8,0x33,0xc0,0x0c, + 0x89,0x2e,0xbe,0x30,0x14,0x3c,0xe2,0x87, + 0x40,0x01,0x1e,0xcf,0x00}, + {0xd6,0xa1,0x41,0xa7,0xec,0x3c,0x38,0xdf,0xbd,0x61,0x00}, + {0}, +}; + +static int RC4_test(BI_CTX *bi_ctx) +{ + int i, res = 1; + RC4_CTX s; + + for (i = 0; i < 6; i++) + { + RC4_setup(&s, &keys[i][1], keys[i][0]); + RC4_crypt(&s, data[i], data[i], data_len[i]); + + if (memcmp(data[i], output[i], data_len[i])) + { + printf("Error: RC4 CRYPT #%d failed\n", i); + goto end; + } + } + + res = 0; + printf("All RC4 tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * SHA1 tests + * + * Run through a couple of the RFC3174 tests to verify that SHA1 is correct. + **************************************************************************/ +static int SHA1_test(BI_CTX *bi_ctx) +{ + SHA1_CTX ctx; + uint8_t ct[SHA1_SIZE]; + uint8_t digest[SHA1_SIZE]; + int res = 1; + + { + const char *in_str = "abc"; + bigint *ct_bi = bi_str_import(bi_ctx, + "A9993E364706816ABA3E25717850C26C9CD0D89D"); + bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE); + + SHA1_Init(&ctx); + SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str)); + SHA1_Final(digest, &ctx); + + if (memcmp(digest, ct, sizeof(ct))) + { + printf("Error: SHA1 #1 failed\n"); + goto end; + } + } + + { + const char *in_str = + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"; + bigint *ct_bi = bi_str_import(bi_ctx, + "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); + bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE); + + SHA1_Init(&ctx); + SHA1_Update(&ctx, (const uint8_t *)in_str, strlen(in_str)); + SHA1_Final(digest, &ctx); + + if (memcmp(digest, ct, sizeof(ct))) + { + printf("Error: SHA1 #2 failed\n"); + goto end; + } + } + + res = 0; + printf("All SHA1 tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * MD5 tests + * + * Run through a couple of the RFC1321 tests to verify that MD5 is correct. + **************************************************************************/ +static int MD5_test(BI_CTX *bi_ctx) +{ + MD5_CTX ctx; + uint8_t ct[MD5_SIZE]; + uint8_t digest[MD5_SIZE]; + int res = 1; + + { + const char *in_str = "abc"; + bigint *ct_bi = bi_str_import(bi_ctx, + "900150983CD24FB0D6963F7D28E17F72"); + bi_export(bi_ctx, ct_bi, ct, MD5_SIZE); + + MD5_Init(&ctx); + MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str)); + MD5_Final(digest, &ctx); + + if (memcmp(digest, ct, sizeof(ct))) + { + printf("Error: MD5 #1 failed\n"); + goto end; + } + } + + { + const char *in_str = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + bigint *ct_bi = bi_str_import( + bi_ctx, "D174AB98D277D9F5A5611C2C9F419D9F"); + bi_export(bi_ctx, ct_bi, ct, MD5_SIZE); + + MD5_Init(&ctx); + MD5_Update(&ctx, (const uint8_t *)in_str, strlen(in_str)); + MD5_Final(digest, &ctx); + + if (memcmp(digest, ct, sizeof(ct))) + { + printf("Error: MD5 #2 failed\n"); + goto end; + } + } + res = 0; + printf("All MD5 tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * HMAC tests + * + * Run through a couple of the RFC2202 tests to verify that HMAC is correct. + **************************************************************************/ +static int HMAC_test(BI_CTX *bi_ctx) +{ + uint8_t key[SHA1_SIZE]; + uint8_t ct[SHA1_SIZE]; + uint8_t dgst[SHA1_SIZE]; + int res = 1; + const char *key_str; + + const char *data_str = "Hi There"; + bigint *key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); + bigint *ct_bi = bi_str_import(bi_ctx, "9294727A3638BB1C13F48EF8158BFC9D"); + bi_export(bi_ctx, key_bi, key, MD5_SIZE); + bi_export(bi_ctx, ct_bi, ct, MD5_SIZE); + hmac_md5((const uint8_t *)data_str, 8, key, MD5_SIZE, dgst); + if (memcmp(dgst, ct, MD5_SIZE)) + { + printf("HMAC MD5 #1 failed\n"); + goto end; + } + + data_str = "what do ya want for nothing?"; + key_str = "Jefe"; + ct_bi = bi_str_import(bi_ctx, "750C783E6AB0B503EAA86E310A5DB738"); + bi_export(bi_ctx, ct_bi, ct, MD5_SIZE); + hmac_md5((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 4, dgst); + if (memcmp(dgst, ct, MD5_SIZE)) + { + printf("HMAC MD5 #2 failed\n"); + goto end; + } + + data_str = "Hi There"; + key_bi = bi_str_import(bi_ctx, "0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B"); + bi_export(bi_ctx, key_bi, key, SHA1_SIZE); + ct_bi = bi_str_import(bi_ctx, "B617318655057264E28BC0B6FB378C8EF146BE00"); + bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE); + + hmac_sha1((const uint8_t *)data_str, 8, + (const uint8_t *)key, SHA1_SIZE, dgst); + if (memcmp(dgst, ct, SHA1_SIZE)) + { + printf("HMAC SHA1 #1 failed\n"); + goto end; + } + + data_str = "what do ya want for nothing?"; + key_str = "Jefe"; + ct_bi = bi_str_import(bi_ctx, "EFFCDF6AE5EB2FA2D27416D5F184DF9C259A7C79"); + bi_export(bi_ctx, ct_bi, ct, SHA1_SIZE); + + hmac_sha1((const uint8_t *)data_str, 28, (const uint8_t *)key_str, 5, dgst); + if (memcmp(dgst, ct, SHA1_SIZE)) + { + printf("HMAC SHA1 failed\n"); + exit(1); + } + + res = 0; + printf("All HMAC tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * BIGINT tests + * + **************************************************************************/ +static int BIGINT_test(BI_CTX *ctx) +{ + int res = 1; + bigint *bi_data, *bi_exp, *bi_res; + const char *expnt, *plaintext, *mod; + uint8_t compare[MAX_KEY_BYTE_SIZE]; + + /** + * 512 bit key + */ + plaintext = /* 64 byte number */ + "01aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee"; + + mod = "C30773C8ABE09FCC279EE0E5343370DE" + "8B2FFDB6059271E3005A7CEEF0D35E0A" + "1F9915D95E63560836CC2EB2C289270D" + "BCAE8CAF6F5E907FC2759EE220071E1B"; + + expnt = "A1E556CD1738E10DF539E35101334E97" + "BE8D391C57A5C89A7AD9A2EA2ACA1B3D" + "F3140F5091CC535CBAA47CEC4159EE1F" + "B6A3661AFF1AB758426EAB158452A9B9"; + + bi_data = bi_import(ctx, (uint8_t *)plaintext, strlen(plaintext)); + bi_exp = int_to_bi(ctx, 0x10001); + bi_set_mod(ctx, bi_str_import(ctx, mod), 0); + bi_res = bi_mod_power(ctx, bi_data, bi_exp); + + bi_data = bi_res; /* resuse again - see if we get the original */ + + bi_exp = bi_str_import(ctx, expnt); + bi_res = bi_mod_power(ctx, bi_data, bi_exp); + bi_free_mod(ctx, 0); + + bi_export(ctx, bi_res, compare, 64); + if (memcmp(plaintext, compare, 64) != 0) + goto end; + + printf("All BIGINT tests passed\n"); + res = 0; + +end: + return res; +} + +/************************************************************************** + * RSA tests + * + * Use the results from openssl to verify PKCS1 etc + **************************************************************************/ +static int RSA_test(void) +{ + int res = 1; + const char *plaintext = /* 128 byte hex number */ + "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeeee2" + "1aaaaaaaaaabbbbbbbbbbbbbbbccccccccccccccdddddddddddddeeeeeeeee2\012"; + uint8_t enc_data[128], dec_data[128]; + RSA_CTX *rsa_ctx = NULL; + BI_CTX *bi_ctx; + bigint *plaintext_bi; + bigint *enc_data_bi, *dec_data_bi; + uint8_t enc_data2[128], dec_data2[128]; + int size; + int len; + uint8_t *buf; + + /* extract the private key elements */ + len = get_file("../ssl/test/axTLS.key_1024", &buf); + if (asn1_get_private_key(buf, len, &rsa_ctx) < 0) + { + goto end; + } + + free(buf); + bi_ctx = rsa_ctx->bi_ctx; + plaintext_bi = bi_import(bi_ctx, + (const uint8_t *)plaintext, strlen(plaintext)); + + /* basic rsa encrypt */ + enc_data_bi = RSA_public(rsa_ctx, plaintext_bi); + bi_export(bi_ctx, bi_copy(enc_data_bi), enc_data, sizeof(enc_data)); + + /* basic rsa decrypt */ + dec_data_bi = RSA_private(rsa_ctx, enc_data_bi); + bi_export(bi_ctx, dec_data_bi, dec_data, sizeof(dec_data)); + + if (memcmp(dec_data, plaintext, strlen(plaintext))) + { + printf("Error: DECRYPT #1 failed\n"); + goto end; + } + + RSA_encrypt(rsa_ctx, (const uint8_t *)"abc", 3, enc_data2, 0); + size = RSA_decrypt(rsa_ctx, enc_data2, dec_data2, 1); + if (memcmp("abc", dec_data2, 3)) + { + printf("Error: ENCRYPT/DECRYPT #2 failed\n"); + goto end; + } + + RSA_free(rsa_ctx); + res = 0; + printf("All RSA tests passed\n"); + +end: + return res; +} + +/************************************************************************** + * Cert Testing + * + **************************************************************************/ +static int cert_tests(void) +{ + int res = -1, len; + X509_CTX *x509_ctx; + SSL_CTX *ssl_ctx; + uint8_t *buf; + + /* check a bunch of 3rd party certificates */ + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/microsoft.x509_ca", &buf); + if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0) + { + printf("Cert #1\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/thawte.x509_ca", &buf); + if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0) + { + printf("Cert #2\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/deutsche_telecom.x509_ca", &buf); + if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0) + { + printf("Cert #3\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/equifax.x509_ca", &buf); + if ((res = add_cert_auth(ssl_ctx, buf, len)) < 0) + { + printf("Cert #4\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/gnutls.cer", &buf); + if ((res = add_cert(ssl_ctx, buf, len)) < 0) + { + printf("Cert #5\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/socgen.cer", &buf); + if ((res = add_cert(ssl_ctx, buf, len)) < 0) + { + printf("Cert #6\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + len = get_file("../ssl/test/verisign.x509_ca", &buf); + if ((res = add_cert_auth(ssl_ctx, buf, len)) <0) + { + printf("Cert #7\n"); + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + free(buf); + + if (get_file("../ssl/test/verisign.x509_my_cert", &buf) < 0 || + x509_new(buf, &len, &x509_ctx)) + { + printf("Cert #8\n"); + ssl_display_error(res); + goto bad_cert; + } + + x509_free(x509_ctx); + free(buf); + + ssl_ctx = ssl_ctx_new(0, 0); + if ((res = ssl_obj_load(ssl_ctx, + SSL_OBJ_X509_CERT, "../ssl/test/ms_iis.cer", NULL)) != SSL_OK) + { + ssl_display_error(res); + goto bad_cert; + } + + ssl_ctx_free(ssl_ctx); + res = 0; /* all ok */ + printf("All Certificate tests passed\n"); + +bad_cert: + if (res) + printf("Error: A certificate test failed\n"); + return res; +} + +/** + * init a server socket. + */ +static int server_socket_init(int *port) +{ + struct sockaddr_in serv_addr; + int server_fd; + char yes = 1; + + /* Create socket for incoming connections */ + if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + return -1; + } + + setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + +go_again: + /* Construct local address structure */ + memset(&serv_addr, 0, sizeof(serv_addr)); /* Zero out structure */ + serv_addr.sin_family = AF_INET; /* Internet address family */ + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ + serv_addr.sin_port = htons(*port); /* Local port */ + + /* Bind to the local address */ + if (bind(server_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) + { + (*port)++; + goto go_again; + } + /* Mark the socket so it will listen for incoming connections */ + if (listen(server_fd, 3000) < 0) + { + return -1; + } + + return server_fd; +} + +/** + * init a client socket. + */ +static int client_socket_init(uint16_t port) +{ + struct sockaddr_in address; + int client_fd; + + address.sin_family = AF_INET; + address.sin_port = htons(port); + address.sin_addr.s_addr = inet_addr("127.0.0.1"); + client_fd = socket(AF_INET, SOCK_STREAM, 0); + if (connect(client_fd, (struct sockaddr *)&address, sizeof(address)) < 0) + { + perror("socket"); + SOCKET_CLOSE(client_fd); + client_fd = -1; + } + + return client_fd; +} + +/************************************************************************** + * SSL Server Testing + * + **************************************************************************/ +typedef struct +{ + /* not used as yet */ + int dummy; +} SVR_CTX; + +typedef struct +{ + const char *testname; + const char *openssl_option; +} client_t; + +static void do_client(client_t *clnt) +{ + char openssl_buf[2048]; + + /* make sure the main thread goes first */ + sleep(0); + + /* show the session ids in the reconnect test */ + if (strcmp(clnt->testname, "Session Reuse") == 0) + { + sprintf(openssl_buf, "echo \"hello client\" | openssl s_client " + "-connect localhost:%d %s 2>&1 | grep \"Session-ID:\"", + g_port, clnt->openssl_option); + } + else + { + sprintf(openssl_buf, "echo \"hello client\" | openssl s_client " +#ifdef WIN32 + "-connect localhost:%d -quiet %s", +#else + "-connect localhost:%d -quiet %s > /dev/null 2>&1", +#endif + g_port, clnt->openssl_option); + } + + system(openssl_buf); +} + +static int SSL_server_test( + const char *testname, + const char *openssl_option, + const char *device_cert, + const char *product_cert, + const char *private_key, + const char *ca_cert, + const char *password, + int axtls_option) +{ + int server_fd, ret = 0; + SSL_CTX *ssl_ctx = NULL; + struct sockaddr_in client_addr; + uint8_t *read_buf; + socklen_t clnt_len = sizeof(client_addr); + client_t client_data; +#ifndef WIN32 + pthread_t thread; +#endif + g_port++; + + client_data.testname = testname; + client_data.openssl_option = openssl_option; + + if ((server_fd = server_socket_init(&g_port)) < 0) + goto error; + + if (private_key) + { + axtls_option |= SSL_NO_DEFAULT_KEY; + } + + if ((ssl_ctx = ssl_ctx_new(axtls_option, SSL_DEFAULT_SVR_SESS)) == NULL) + { + ret = SSL_ERROR_INVALID_KEY; + goto error; + } + + if (private_key) + { + int obj_type = SSL_OBJ_RSA_KEY; + + if (strstr(private_key, ".p8")) + obj_type = SSL_OBJ_PKCS8; + else if (strstr(private_key, ".p12")) + obj_type = SSL_OBJ_PKCS12; + + if (ssl_obj_load(ssl_ctx, obj_type, private_key, password)) + { + ret = SSL_ERROR_INVALID_KEY; + goto error; + } + } + + if (device_cert) /* test chaining */ + { + if ((ret = ssl_obj_load(ssl_ctx, + SSL_OBJ_X509_CERT, device_cert, NULL)) != SSL_OK) + goto error; + } + + if (product_cert) /* test chaining */ + { + if ((ret = ssl_obj_load(ssl_ctx, + SSL_OBJ_X509_CERT, product_cert, NULL)) != SSL_OK) + goto error; + } + + if (ca_cert) /* test adding certificate authorities */ + { + if ((ret = ssl_obj_load(ssl_ctx, + SSL_OBJ_X509_CACERT, ca_cert, NULL)) != SSL_OK) + goto error; + } + +#ifndef WIN32 + pthread_create(&thread, NULL, + (void *(*)(void *))do_client, (void *)&client_data); + pthread_detach(thread); +#else + CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_client, + (LPVOID)&client_data, 0, NULL); +#endif + + for (;;) + { + int client_fd, size = 0; + SSL *ssl; + + /* Wait for a client to connect */ + if ((client_fd = accept(server_fd, + (struct sockaddr *)&client_addr, &clnt_len)) < 0) + { + ret = SSL_ERROR_SOCK_SETUP_FAILURE; + goto error; + } + + /* we are ready to go */ + ssl = ssl_server_new(ssl_ctx, client_fd); + while ((size = ssl_read(ssl, &read_buf)) == SSL_OK); + SOCKET_CLOSE(client_fd); + + if (size < SSL_OK) /* got some alert or something nasty */ + { + ret = size; + + if (ret == SSL_ERROR_CONN_LOST) + { + ret = SSL_OK; + continue; + } + + break; /* we've got a problem */ + } + else /* looks more promising */ + { + if (strstr("hello client", (char *)read_buf) == NULL) + { + printf("SSL server test \"%s\" passed\n", testname); + TTY_FLUSH(); + ret = 0; + break; + } + } + + ssl_free(ssl); + } + + SOCKET_CLOSE(server_fd); + +error: + ssl_ctx_free(ssl_ctx); + return ret; +} + +int SSL_server_tests(void) +{ + int ret = -1; + struct stat stat_buf; + SVR_CTX svr_test_ctx; + memset(&svr_test_ctx, 0, sizeof(SVR_CTX)); + + printf("### starting server tests\n"); TTY_FLUSH(); + + /* Go through the algorithms */ + + /* + * TLS1 client hello + */ + if ((ret = SSL_server_test("TLSv1", "-cipher RC4-SHA -tls1", + NULL, NULL, NULL, NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * AES128-SHA + */ + if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA", + DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL, + DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * AES256-SHA + */ + if ((ret = SSL_server_test("AES256-SHA", "-cipher AES128-SHA", + DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL, + DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * RC4-SHA + */ + if ((ret = SSL_server_test("RC4-SHA", "-cipher RC4-SHA", + DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL, + DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * RC4-MD5 + */ + if ((ret = SSL_server_test("RC4-MD5", "-cipher RC4-MD5", + DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL, + DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * Session Reuse + * all the session id's should match for session resumption. + */ + if ((ret = SSL_server_test("Session Reuse", + "-cipher RC4-SHA -reconnect", + DEFAULT_CERT, NULL, DEFAULT_KEY, NULL, NULL, + DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * 512 bit RSA key + */ + if ((ret = SSL_server_test("512 bit key", "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_512.cer", NULL, + "../ssl/test/axTLS.key_512", + NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * 1024 bit RSA key (check certificate chaining) + */ + if ((ret = SSL_server_test("1024 bit key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_device.cer", + "../ssl/test/axTLS.x509_512.cer", + "../ssl/test/axTLS.device_key", + NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * 2048 bit RSA key + */ + if ((ret = SSL_server_test("2048 bit key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_2048.cer", NULL, + "../ssl/test/axTLS.key_2048", + NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * 4096 bit RSA key + */ + if ((ret = SSL_server_test("4096 bit key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_4096.cer", NULL, + "../ssl/test/axTLS.key_4096", + NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * Client Verification + */ + if ((ret = SSL_server_test("Client Verification", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_2048.pem " + "-key ../ssl/test/axTLS.key_2048.pem ", + NULL, NULL, NULL, + "../ssl/test/axTLS.ca_x509.cer", NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION))) + goto cleanup; + + /* this test should fail */ + if (stat("../ssl/test/axTLS.x509_bad_before.pem", &stat_buf) >= 0) + { + if ((ret = SSL_server_test("Error: Bad Before Cert", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_bad_before.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + "../ssl/test/axTLS.ca_x509.cer", NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", "Bad Before Cert"); + TTY_FLUSH(); + ret = 0; /* is ok */ + } + + /* this test should fail */ + if ((ret = SSL_server_test("Error: Bad After Cert", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_bad_after.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + "../ssl/test/axTLS.ca_x509.cer", NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", "Bad After Cert"); + TTY_FLUSH(); + + /* + * No trusted cert + */ + if ((ret = SSL_server_test("Error: No trusted certificate", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + NULL, NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", "No trusted certificate"); + TTY_FLUSH(); + + /* + * Self-signed (from the server) + */ + if ((ret = SSL_server_test("Error: Self-signed certificate (from server)", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem " + "-CAfile ../ssl/test/axTLS.ca_x509.pem ", + NULL, NULL, NULL, + NULL, NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION)) != + SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED)) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", + "Self-signed certificate (from server)"); + TTY_FLUSH(); + + /* + * Self-signed (from the client) + */ + if ((ret = SSL_server_test("Self-signed certificate (from client)", + "-cipher RC4-SHA -tls1 " + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem ", + NULL, NULL, NULL, + "../ssl/test/axTLS.ca_x509.cer", + NULL, + DEFAULT_SVR_OPTION|SSL_CLIENT_AUTHENTICATION))) + goto cleanup; + + /* + * Key in PEM format + */ + if ((ret = SSL_server_test("Key in PEM format", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_512.cer", NULL, + "../ssl/test/axTLS.key_512.pem", NULL, + NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * Cert in PEM format + */ + if ((ret = SSL_server_test("Cert in PEM format", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_512.pem", NULL, + "../ssl/test/axTLS.key_512.pem", NULL, + NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * Cert chain in PEM format + */ + if ((ret = SSL_server_test("Cert chain in PEM format", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_device.pem", + NULL, "../ssl/test/axTLS.device_key.pem", + "../ssl/test/axTLS.ca_x509.pem", NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * AES128 Encrypted key + */ + if ((ret = SSL_server_test("AES128 encrypted key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_aes128.pem", NULL, + "../ssl/test/axTLS.key_aes128.pem", + NULL, "abcd", DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * AES256 Encrypted key + */ + if ((ret = SSL_server_test("AES256 encrypted key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_aes256.pem", NULL, + "../ssl/test/axTLS.key_aes256.pem", + NULL, "abcd", DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * AES128 Encrypted invalid key + */ + if ((ret = SSL_server_test("AES128 encrypted invalid key", + "-cipher RC4-SHA", + "../ssl/test/axTLS.x509_aes128.pem", NULL, + "../ssl/test/axTLS.key_aes128.pem", + NULL, "xyz", DEFAULT_SVR_OPTION)) != SSL_ERROR_INVALID_KEY) + goto cleanup; + + printf("SSL server test \"%s\" passed\n", "AES128 encrypted invalid key"); + TTY_FLUSH(); + + /* + * PKCS#8 key (encrypted) + */ + if ((ret = SSL_server_test("pkcs#8 encrypted", "-cipher RC4-SHA", + DEFAULT_CERT, NULL, "../ssl/test/axTLS.encrypted.p8", + NULL, "abcd", DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * PKCS#8 key (unencrypted) + */ + if ((ret = SSL_server_test("pkcs#8 unencrypted", "-cipher RC4-SHA", + DEFAULT_CERT, NULL, "../ssl/test/axTLS.unencrypted.p8", + NULL, NULL, DEFAULT_SVR_OPTION))) + goto cleanup; + + /* + * PKCS#12 key/certificate + */ + if ((ret = SSL_server_test("pkcs#12 with CA", "-cipher RC4-SHA", + NULL, NULL, "../ssl/test/axTLS.withCA.p12", + NULL, "abcd", DEFAULT_SVR_OPTION))) + goto cleanup; + + if ((ret = SSL_server_test("pkcs#12 no CA", "-cipher RC4-SHA", + DEFAULT_CERT, NULL, "../ssl/test/axTLS.withoutCA.p12", + NULL, "abcd", DEFAULT_SVR_OPTION))) + goto cleanup; + + ret = 0; + +cleanup: + if (ret) + { + printf("Error: A server test failed\n"); + ssl_display_error(ret); + exit(1); + } + else + { + printf("All server tests passed\n"); TTY_FLUSH(); + } + + return ret; +} + +/************************************************************************** + * SSL Client Testing + * + **************************************************************************/ +typedef struct +{ + uint8_t session_id[SSL_SESSION_ID_SIZE]; +#ifndef WIN32 + pthread_t server_thread; +#endif + int start_server; + int stop_server; + int do_reneg; +} CLNT_SESSION_RESUME_CTX; + +typedef struct +{ + const char *testname; + const char *openssl_option; +} server_t; + +static void do_server(server_t *svr) +{ + char openssl_buf[2048]; +#ifndef WIN32 + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); +#endif + sprintf(openssl_buf, "openssl s_server -tls1 " + "-accept %d -quiet %s ", g_port, svr->openssl_option); + system(openssl_buf); +} + +static int SSL_client_test( + const char *test, + SSL_CTX **ssl_ctx, + const char *openssl_option, + CLNT_SESSION_RESUME_CTX *sess_resume, + uint32_t client_options, + const char *private_key, + const char *password, + const char *cert) +{ + server_t server_data; + SSL *ssl = NULL; + int client_fd = -1; + uint8_t *session_id = NULL; + int ret = 1; +#ifndef WIN32 + pthread_t thread; +#endif + + if (sess_resume == NULL || sess_resume->start_server) + { + g_port++; + server_data.openssl_option = openssl_option; + +#ifndef WIN32 + pthread_create(&thread, NULL, + (void *(*)(void *))do_server, (void *)&server_data); + pthread_detach(thread); +#else + CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_server, + (LPVOID)&server_data, 0, NULL); +#endif + } + + usleep(200000); /* allow server to start */ + + if (*ssl_ctx == NULL) + { + if (private_key) + { + client_options |= SSL_NO_DEFAULT_KEY; + } + + if ((*ssl_ctx = ssl_ctx_new( + client_options, SSL_DEFAULT_CLNT_SESS)) == NULL) + { + ret = SSL_ERROR_INVALID_KEY; + goto client_test_exit; + } + + if (private_key) + { + int obj_type = SSL_OBJ_RSA_KEY; + + if (strstr(private_key, ".p8")) + obj_type = SSL_OBJ_PKCS8; + else if (strstr(private_key, ".p12")) + obj_type = SSL_OBJ_PKCS12; + + if (ssl_obj_load(*ssl_ctx, obj_type, private_key, password)) + { + ret = SSL_ERROR_INVALID_KEY; + goto client_test_exit; + } + } + + if (cert) + { + if ((ret = ssl_obj_load(*ssl_ctx, + SSL_OBJ_X509_CERT, cert, NULL)) != SSL_OK) + { + printf("could not add cert %s (%d)\n", cert, ret); + TTY_FLUSH(); + goto client_test_exit; + } + } + + if (ssl_obj_load(*ssl_ctx, SSL_OBJ_X509_CACERT, + "../ssl/test/axTLS.ca_x509.cer", NULL)) + { + printf("could not add cert auth\n"); TTY_FLUSH(); + goto client_test_exit; + } + } + + if (sess_resume && !sess_resume->start_server) + { + session_id = sess_resume->session_id; + } + + if ((client_fd = client_socket_init(g_port)) < 0) + { + printf("could not start socket on %d\n", g_port); TTY_FLUSH(); + goto client_test_exit; + } + + ssl = ssl_client_new(*ssl_ctx, client_fd, session_id, sizeof(session_id)); + + /* check the return status */ + if ((ret = ssl_handshake_status(ssl))) + goto client_test_exit; + + /* renegotiate client */ + if (sess_resume && sess_resume->do_reneg) + { + if (ssl_renegotiate(ssl) < 0) + goto client_test_exit; + } + + if (sess_resume) + { + memcpy(sess_resume->session_id, + ssl_get_session_id(ssl), SSL_SESSION_ID_SIZE); + } + + if (IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER) && + (ret = ssl_verify_cert(ssl))) + { + goto client_test_exit; + } + + ssl_write(ssl, (uint8_t *)"hello world\n", 13); + if (sess_resume) + { + const uint8_t *sess_id = ssl_get_session_id(ssl); + int i; + + printf(" Session-ID: "); + for (i = 0; i < SSL_SESSION_ID_SIZE; i++) + { + printf("%02X", sess_id[i]); + } + printf("\n"); + TTY_FLUSH(); + } + + ret = 0; + +client_test_exit: + ssl_free(ssl); + SOCKET_CLOSE(client_fd); + usleep(200000); /* allow openssl to say something */ + + if (sess_resume) + { + if (sess_resume->stop_server) + { + ssl_ctx_free(*ssl_ctx); + *ssl_ctx = NULL; +#ifndef WIN32 + pthread_cancel(sess_resume->server_thread); +#endif + } + else if (sess_resume->start_server) + { +#ifndef WIN32 + sess_resume->server_thread = thread; +#endif + } + } + else + { + ssl_ctx_free(*ssl_ctx); + *ssl_ctx = NULL; +#ifndef WIN32 + pthread_cancel(thread); +#endif + } + + if (ret == 0) + { + printf("SSL client test \"%s\" passed\n", test); + TTY_FLUSH(); + } + + return ret; +} + +int SSL_client_tests(void) +{ + int ret = -1; + SSL_CTX *ssl_ctx = NULL; + CLNT_SESSION_RESUME_CTX sess_resume; + memset(&sess_resume, 0, sizeof(CLNT_SESSION_RESUME_CTX)); + + sess_resume.start_server = 1; + printf("### starting client tests\n"); + + if ((ret = SSL_client_test("512 bit key", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_512.pem " + "-key ../ssl/test/axTLS.key_512.pem", &sess_resume, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + /* all the session id's should match for session resumption */ + sess_resume.start_server = 0; + if ((ret = SSL_client_test("Client session resumption #1", + &ssl_ctx, NULL, &sess_resume, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + sess_resume.do_reneg = 1; + if ((ret = SSL_client_test("Client renegotiation", + &ssl_ctx, NULL, &sess_resume, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + sess_resume.do_reneg = 0; + + sess_resume.stop_server = 1; + if ((ret = SSL_client_test("Client session resumption #2", + &ssl_ctx, NULL, &sess_resume, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + if ((ret = SSL_client_test("1024 bit key", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_1024.pem " + "-key ../ssl/test/axTLS.key_1024.pem", NULL, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + if ((ret = SSL_client_test("2048 bit key", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_2048.pem " + "-key ../ssl/test/axTLS.key_2048.pem", NULL, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + if ((ret = SSL_client_test("4096 bit key", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_4096.pem " + "-key ../ssl/test/axTLS.key_4096.pem", NULL, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + if ((ret = SSL_client_test("Server cert chaining", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_device.pem " + "-key ../ssl/test/axTLS.device_key.pem " + "-CAfile ../ssl/test/axTLS.x509_512.pem ", NULL, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL))) + goto cleanup; + + /* Check the server can verify the client */ + if ((ret = SSL_client_test("Client peer authentication", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_2048.pem " + "-key ../ssl/test/axTLS.key_2048.pem " + "-CAfile ../ssl/test/axTLS.ca_x509.pem " + "-verify 1 ", NULL, DEFAULT_CLNT_OPTION, + "../ssl/test/axTLS.key_1024", NULL, + "../ssl/test/axTLS.x509_1024.cer"))) + goto cleanup; + + /* Should get an "ERROR" from openssl (as the handshake fails as soon as + * the certificate verification fails) */ + if ((ret = SSL_client_test("Error: Expired cert (verify now)", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_bad_after.pem " + "-key ../ssl/test/axTLS.key_512.pem", NULL, + DEFAULT_CLNT_OPTION, NULL, NULL, NULL)) != + SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED)) + { + printf("*** Error: %d\n", ret); + goto cleanup; + } + + printf("SSL client test \"Expired cert (verify now)\" passed\n"); + + /* There is no "ERROR" from openssl */ + if ((ret = SSL_client_test("Error: Expired cert (verify later)", + &ssl_ctx, + "-cert ../ssl/test/axTLS.x509_bad_after.pem " + "-key ../ssl/test/axTLS.key_512.pem", NULL, + DEFAULT_CLNT_OPTION|SSL_SERVER_VERIFY_LATER, NULL, + NULL, NULL)) != SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED)) + { + printf("*** Error: %d\n", ret); + goto cleanup; + } + + printf("SSL client test \"Expired cert (verify later)\" passed\n"); + ret = 0; + +cleanup: + if (ret) + { + ssl_display_error(ret); + printf("Error: A client test failed\n"); + exit(1); + } + else + { + printf("All client tests passed\n"); TTY_FLUSH(); + } + + return ret; +} + +/************************************************************************** + * SSL Basic Testing (test a big packet handshake) + * + **************************************************************************/ +static uint8_t basic_buf[256*1024]; + +static void do_basic(void) +{ + int client_fd; + SSL *ssl_clnt; + SSL_CTX *ssl_clnt_ctx = ssl_ctx_new( + DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS); + usleep(200000); /* allow server to start */ + + if ((client_fd = client_socket_init(g_port)) < 0) + goto error; + + if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT, + "../ssl/test/axTLS.ca_x509.cer", NULL)) + goto error; + + ssl_clnt = ssl_client_new(ssl_clnt_ctx, client_fd, NULL, 0); + + /* check the return status */ + if (ssl_handshake_status(ssl_clnt) < 0) + { + printf("YA YA\n"); + ssl_display_error(ssl_handshake_status(ssl_clnt)); + goto error; + } + + ssl_write(ssl_clnt, basic_buf, sizeof(basic_buf)); + ssl_free(ssl_clnt); + +error: + ssl_ctx_free(ssl_clnt_ctx); + SOCKET_CLOSE(client_fd); + + /* exit this thread */ +} + +static int SSL_basic_test(void) +{ + int server_fd, client_fd, ret = 0, size = 0, offset = 0; + SSL_CTX *ssl_svr_ctx = NULL; + struct sockaddr_in client_addr; + uint8_t *read_buf; + socklen_t clnt_len = sizeof(client_addr); + SSL *ssl_svr; +#ifndef WIN32 + pthread_t thread; +#endif + memset(basic_buf, 0xA5, sizeof(basic_buf)/2); + memset(&basic_buf[sizeof(basic_buf)/2], 0x5A, sizeof(basic_buf)/2); + + if ((server_fd = server_socket_init(&g_port)) < 0) + goto error; + + ssl_svr_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS); + +#ifndef WIN32 + pthread_create(&thread, NULL, + (void *(*)(void *))do_basic, NULL); + pthread_detach(thread); +#else + CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_basic, NULL, 0, NULL); +#endif + + /* Wait for a client to connect */ + if ((client_fd = accept(server_fd, + (struct sockaddr *) &client_addr, &clnt_len)) < 0) + { + ret = SSL_ERROR_SOCK_SETUP_FAILURE; + goto error; + } + + /* we are ready to go */ + ssl_svr = ssl_server_new(ssl_svr_ctx, client_fd); + + do + { + while ((size = ssl_read(ssl_svr, &read_buf)) == SSL_OK); + + if (size < SSL_OK) /* got some alert or something nasty */ + { + printf("Server "); + ssl_display_error(size); + ret = size; + break; + } + else /* looks more promising */ + { + if (memcmp(read_buf, &basic_buf[offset], size) != 0) + { + ret = SSL_NOT_OK; + break; + } + } + + offset += size; + } while (offset < sizeof(basic_buf)); + + printf(ret == SSL_OK && offset == sizeof(basic_buf) ? + "SSL basic test passed\n" : + "SSL basic test failed\n"); + TTY_FLUSH(); + + ssl_free(ssl_svr); + SOCKET_CLOSE(server_fd); + SOCKET_CLOSE(client_fd); + +error: + ssl_ctx_free(ssl_svr_ctx); + return ret; +} + +#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING) +/************************************************************************** + * Multi-Threading Tests + * + **************************************************************************/ +#define NUM_THREADS 100 + +typedef struct +{ + SSL_CTX *ssl_clnt_ctx; + int port; + int thread_id; +} multi_t; + +void do_multi_clnt(multi_t *multi_data) +{ + int res = 1, client_fd, i; + SSL *ssl = NULL; + char tmp[5]; + + if ((client_fd = client_socket_init(multi_data->port)) < 0) + goto client_test_exit; + + sleep(1); + ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL, 0); + + if ((res = ssl_handshake_status(ssl))) + { + printf("Client "); + ssl_display_error(res); + goto client_test_exit; + } + + sprintf(tmp, "%d\n", multi_data->thread_id); + for (i = 0; i < 10; i++) + ssl_write(ssl, (uint8_t *)tmp, strlen(tmp)+1); + +client_test_exit: + ssl_free(ssl); + SOCKET_CLOSE(client_fd); + free(multi_data); +} + +void do_multi_svr(SSL *ssl) +{ + uint8_t *read_buf; + int *res_ptr = malloc(sizeof(int)); + int res; + + for (;;) + { + res = ssl_read(ssl, &read_buf); + + /* kill the client */ + if (res != SSL_OK) + { + if (res == SSL_ERROR_CONN_LOST) + { + SOCKET_CLOSE(ssl->client_fd); + ssl_free(ssl); + break; + } + else if (res > 0) + { + /* do nothing */ + } + else /* some problem */ + { + printf("Server "); + ssl_display_error(res); + goto error; + } + } + } + + res = SSL_OK; +error: + *res_ptr = res; + pthread_exit(res_ptr); +} + +int multi_thread_test(void) +{ + int server_fd = -1; + SSL_CTX *ssl_server_ctx; + SSL_CTX *ssl_clnt_ctx; + pthread_t clnt_threads[NUM_THREADS]; + pthread_t svr_threads[NUM_THREADS]; + int i, res = 0; + struct sockaddr_in client_addr; + socklen_t clnt_len = sizeof(client_addr); + + printf("Do multi-threading test (takes a minute)\n"); + + ssl_server_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION, SSL_DEFAULT_SVR_SESS); + ssl_clnt_ctx = ssl_ctx_new(DEFAULT_CLNT_OPTION, SSL_DEFAULT_CLNT_SESS); + + if (ssl_obj_load(ssl_clnt_ctx, SSL_OBJ_X509_CACERT, + "../ssl/test/axTLS.ca_x509.cer", NULL)) + goto error; + + if ((server_fd = server_socket_init(&g_port)) < 0) + goto error; + + for (i = 0; i < NUM_THREADS; i++) + { + multi_t *multi_data = (multi_t *)malloc(sizeof(multi_t)); + multi_data->ssl_clnt_ctx = ssl_clnt_ctx; + multi_data->port = g_port; + multi_data->thread_id = i+1; + pthread_create(&clnt_threads[i], NULL, + (void *(*)(void *))do_multi_clnt, (void *)multi_data); + pthread_detach(clnt_threads[i]); + } + + for (i = 0; i < NUM_THREADS; i++) + { + SSL *ssl_svr; + int client_fd = accept(server_fd, + (struct sockaddr *)&client_addr, &clnt_len); + + if (client_fd < 0) + goto error; + + ssl_svr = ssl_server_new(ssl_server_ctx, client_fd); + + pthread_create(&svr_threads[i], NULL, + (void *(*)(void *))do_multi_svr, (void *)ssl_svr); + } + + /* make sure we've run all of the threads */ + for (i = 0; i < NUM_THREADS; i++) + { + void *thread_res; + pthread_join(svr_threads[i], &thread_res); + + if (*((int *)thread_res) != 0) + res = 1; + + free(thread_res); + } + + if (res) + goto error; + + printf("Multi-thread test passed (%d)\n", NUM_THREADS); +error: + ssl_ctx_free(ssl_server_ctx); + ssl_ctx_free(ssl_clnt_ctx); + SOCKET_CLOSE(server_fd); + return res; +} +#endif /* !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING) */ + +/************************************************************************** + * Header issue + * + **************************************************************************/ +static void do_header_issue(void) +{ + char axtls_buf[2048]; +#ifndef WIN32 + pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); +#endif + sprintf(axtls_buf, "./axssl s_client -connect localhost:%d", g_port); + system(axtls_buf); +} + +static int header_issue(void) +{ + FILE *f = fopen("../ssl/test/header_issue.dat", "r"); + int server_fd = -1, client_fd = -1, ret = 1; + uint8_t buf[2048]; + int size = 0; + struct sockaddr_in client_addr; + socklen_t clnt_len = sizeof(client_addr); +#ifndef WIN32 + pthread_t thread; +#endif + + if (f == NULL || (server_fd = server_socket_init(&g_port)) < 0) + goto error; + +#ifndef WIN32 + pthread_create(&thread, NULL, + (void *(*)(void *))do_header_issue, NULL); + pthread_detach(thread); +#else + CreateThread(NULL, 1024, (LPTHREAD_START_ROUTINE)do_header_issue, + NULL, 0, NULL); +#endif + if ((client_fd = accept(server_fd, + (struct sockaddr *) &client_addr, &clnt_len)) < 0) + { + ret = SSL_ERROR_SOCK_SETUP_FAILURE; + goto error; + } + + size = fread(buf, 1, sizeof(buf), f); + SOCKET_WRITE(client_fd, buf, size); + usleep(200000); + + ret = 0; +error: + fclose(f); + SOCKET_CLOSE(client_fd); + SOCKET_CLOSE(server_fd); + TTY_FLUSH(); + system("killall axssl"); + return ret; +} + +/************************************************************************** + * main() + * + **************************************************************************/ +int main(int argc, char *argv[]) +{ + int ret = 1; + BI_CTX *bi_ctx; + int fd; + +#ifdef WIN32 + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 2); + WSAStartup(wVersionRequested, &wsaData); + fd = _open("test_result.txt", O_WRONLY|O_TEMPORARY|O_CREAT, _S_IWRITE); + dup2(fd, 2); /* write stderr to this file */ +#else + fd = open("/dev/null", O_WRONLY); /* write stderr to /dev/null */ + signal(SIGPIPE, SIG_IGN); /* ignore pipe errors */ + dup2(fd, 2); +#endif + + /* can't do testing in this mode */ +#if defined CONFIG_SSL_GENERATE_X509_CERT + printf("Error: Must compile with default key/certificates\n"); + exit(1); +#endif + + bi_ctx = bi_initialize(); + + if (AES_test(bi_ctx)) + { + printf("AES tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (RC4_test(bi_ctx)) + { + printf("RC4 tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (MD5_test(bi_ctx)) + { + printf("MD5 tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (SHA1_test(bi_ctx)) + { + printf("SHA1 tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (HMAC_test(bi_ctx)) + { + printf("HMAC tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (BIGINT_test(bi_ctx)) + { + printf("BigInt tests failed!\n"); + goto cleanup; + } + TTY_FLUSH(); + + bi_terminate(bi_ctx); + + if (RSA_test()) + { + printf("RSA tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + + if (cert_tests()) + { + printf("CERT tests failed\n"); + goto cleanup; + } + TTY_FLUSH(); + +#if !defined(WIN32) && defined(CONFIG_SSL_CTX_MUTEXING) + if (multi_thread_test()) + goto cleanup; +#endif + + if (SSL_basic_test()) + goto cleanup; + + system("sh ../ssl/test/killopenssl.sh"); + + if (SSL_client_tests()) + goto cleanup; + + system("sh ../ssl/test/killopenssl.sh"); + + if (SSL_server_tests()) + goto cleanup; + + system("sh ../ssl/test/killopenssl.sh"); + + if (header_issue()) + { + printf("Header tests failed\n"); TTY_FLUSH(); + goto cleanup; + } + + ret = 0; /* all ok */ + printf("**** ALL TESTS PASSED ****\n"); TTY_FLUSH(); +cleanup: + + if (ret) + printf("Error: Some tests failed!\n"); + + close(fd); + return ret; +} |