1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-30 16:24:09 +03:00

added versioning/fragmentation

git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@56 9a5d90b5-6617-0410-8a86-bb477d3ed2e3
This commit is contained in:
cameronrich
2007-02-01 08:31:32 +00:00
parent bb61a8921c
commit f616c74150
40 changed files with 611 additions and 545 deletions

View File

@ -210,6 +210,19 @@ config CONFIG_SSL_MAX_CERTS
The default is to allow one certificate + 1 certificate in the chain
(which may be the certificate authority certificate).
config CONFIG_SSLCTX_MUTEXING
bool "Enable SSLCTX mutexing"
default n
help
Normally mutexing is not required - each SSLCTX object can deal with
many SSL objects (as long as each SSLCTX object is using a single
thread).
If the SSLCTX object is not thread safe e.g. the case where a
new thread is created for each SSL object, then mutexing is required.
Select y when a mutex on the SSLCTX object is required.
config CONFIG_USE_DEV_URANDOM
bool "Use /dev/urandom"
default y

View File

@ -39,7 +39,7 @@ endif
# shared library major/minor numbers
LIBMAJOR=$(BASETARGET).1
LIBMINOR=$(BASETARGET).1.0
LIBMINOR=$(BASETARGET).1.1
else
TARGET1=axtls.lib
TARGET2=../$(STAGE)/axtls.dll
@ -49,7 +49,7 @@ endif
libs: $(TARGET1) $(TARGET2)
OBJ=\
aes.o \
aes.o \
asn1.o \
bigint.o \
crypto_misc.o \

View File

@ -400,7 +400,6 @@ static void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
}
tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);

View File

@ -781,7 +781,9 @@ void bi_free_mod(BI_CTX *ctx, int mod_offset)
*/
static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
{
int i, j, i_plus_j, n = bia->size, t = bib->size;
int i, j, i_plus_j;
int n = bia->size;
int t = bib->size;
bigint *biR = alloc(ctx, n + t);
comp *sr = biR->comps;
comp *sa = bia->comps;
@ -1397,9 +1399,7 @@ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
#ifdef CONFIG_BIGINT_SLIDING_WINDOW
for (j = i; j > 32; j /= 5) /* work out an optimum size */
{
window_size++;
}
/* work out the slide constants */
precompute_slide_window(ctx, window_size, bi);
@ -1420,15 +1420,11 @@ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
int part_exp = 0;
if (l < 0) /* LSB of exponent will always be 1 */
{
l = 0;
}
else
{
while (exp_bit_is_one(biexp, l) == 0)
{
l++; /* go back up */
}
}
/* build up the section of the exponent */

View File

@ -74,14 +74,14 @@ bigint *bi_str_import(BI_CTX *ctx, const char *data);
* appropriate reduction technique (which is bi_mod() when doing classical
* reduction).
*/
#if defined(CONFIG_BIGINT_CLASSICAL)
#define bi_residue(A, B) bi_mod(A, B)
#if defined(CONFIG_BIGINT_MONTGOMERY)
#define bi_residue(A, B) bi_mont(A, B)
bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
#elif defined(CONFIG_BIGINT_BARRETT)
#define bi_residue(A, B) bi_barrett(A, B)
bigint *bi_barrett(BI_CTX *ctx, bigint *bi);
#else /* CONFIG_BIGINT_MONTGOMERY */
#define bi_residue(A, B) bi_mont(A, B)
bigint *bi_mont(BI_CTX *ctx, bigint *bixy);
#else /* if defined(CONFIG_BIGINT_CLASSICAL) */
#define bi_residue(A, B) bi_mod(A, B)
#endif
#ifdef CONFIG_BIGINT_SQUARE

View File

@ -143,7 +143,6 @@ typedef struct
bigint *qInv; /* q^-1 mod p */
#endif
int num_octets;
bigint *sig_m; /* signature modulus */
BI_CTX *bi_ctx;
} RSA_CTX;
@ -163,15 +162,14 @@ void RSA_pub_key_new(RSA_CTX **rsa_ctx,
const uint8_t *modulus, int mod_len,
const uint8_t *pub_exp, int pub_len);
void RSA_free(RSA_CTX *ctx);
int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
int is_decryption);
bigint *RSA_private(RSA_CTX *c, bigint *bi_msg);
bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);
#ifdef CONFIG_SSL_CERT_VERIFICATION
bigint *RSA_raw_sign_verify(RSA_CTX *c, bigint *bi_msg);
bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
bigint *modulus, bigint *pub_exp);
bigint *RSA_public(RSA_CTX *c, bigint *bi_msg);
int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);
int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
uint8_t *out_data, int is_signing);
void RSA_print(const RSA_CTX *ctx);
#endif
@ -267,17 +265,6 @@ typedef void (*crypt_func)(void *, const uint8_t *, uint8_t *, int);
typedef void (*hmac_func)(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
typedef struct
{
uint8_t *pre_data; /* include the ssl record bytes */
uint8_t *data; /* the regular ssl data */
int max_len;
int index;
} BUF_MEM;
BUF_MEM buf_new(void);
void buf_grow(BUF_MEM *bm, int len);
void buf_free(BUF_MEM *bm);
int get_file(const char *filename, uint8_t **buf);
#if defined(CONFIG_SSL_FULL_MODE) || defined(WIN32) || defined(CONFIG_DEBUG)

View File

@ -29,8 +29,6 @@
#include "wincrypt.h"
#endif
#define BM_RECORD_OFFSET 5 /* same as SSL_RECORD_SIZE */
#ifndef WIN32
static int rng_fd = -1;
#elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
@ -44,45 +42,6 @@ static uint64_t rng_num;
static int rng_ref_count;
const char * const unsupported_str = "Error: feature not supported\n";
/**
* Allocate a new memory buffer
*/
BUF_MEM buf_new()
{
BUF_MEM bm;
bm.pre_data = (uint8_t *)calloc(1, 2048); /* start with this */
bm.data = bm.pre_data+BM_RECORD_OFFSET; /* some space at the start */
bm.max_len = 2048-BM_RECORD_OFFSET;
bm.index = 0;
return bm;
}
/**
* Grow a buffer if necessary
*/
void buf_grow(BUF_MEM *bm, int len)
{
if (len <= bm->max_len)
{
return;
}
/* add 1kB just to be sure */
bm->pre_data = (uint8_t *)realloc(bm->pre_data, len+1024+BM_RECORD_OFFSET);
bm->data = bm->pre_data+BM_RECORD_OFFSET;
bm->max_len = len + 1024;
}
/**
* Free a buffer
*/
void buf_free(BUF_MEM *bm)
{
free(bm->pre_data);
bm->pre_data = NULL;
bm->data = NULL;
}
#ifndef CONFIG_SSL_SKELETON_MODE
/**
* Retrieve a file and put it into memory

View File

@ -76,9 +76,7 @@ EXP_FUNC int STDCALL ssl_obj_load(SSLCTX *ssl_ctx, int obj_type,
#endif
}
else
{
ret = do_obj(ssl_ctx, obj_type, ssl_obj, password);
}
error:
ssl_obj_free(ssl_obj);
@ -149,15 +147,18 @@ static int do_obj(SSLCTX *ssl_ctx, int obj_type,
}
/*
* Release things.
* Clean up our mess.
*/
void ssl_obj_free(SSLObjLoader *ssl_obj)
{
free(ssl_obj->buf);
free(ssl_obj);
if (ssl_obj)
{
free(ssl_obj->buf);
free(ssl_obj);
}
}
/**
/*
* Support for PEM encoded keys/certificates.
*/
#ifdef CONFIG_SSL_HAS_PEM
@ -214,7 +215,7 @@ static int base64_decode(const uint8_t *in, int len,
g = 3;
for (x = y = z = t = 0; x < len; x++)
{
if ((c = map[in[x]&0x7F]) == 0xff)
if ((c = map[in[x] & 0x7F]) == 0xff)
continue;
if (c == 254) /* this is the end... */
@ -234,14 +235,10 @@ static int base64_decode(const uint8_t *in, int len,
out[z++] = (uint8_t)((t>>16)&255);
if (g > 1)
{
out[z++] = (uint8_t)((t>>8)&255);
}
if (g > 2)
{
out[z++] = (uint8_t)(t&255);
}
y = t = 0;
}
@ -256,9 +253,7 @@ static int base64_decode(const uint8_t *in, int len,
error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret < 0)
{
printf("Error: Invalid base64 file\n");
}
#endif
return ret;
}
@ -312,7 +307,7 @@ static int pem_decrypt(const uint8_t *where, const uint8_t *end,
uint8_t c = *start++ - '0';
iv[i] = (c > 9 ? c + '0' - 'A' + 10 : c) << 4;
c = *start++ - '0';
iv[i] +=(c > 9 ? c + '0' - 'A' + 10 : c);
iv[i] += (c > 9 ? c + '0' - 'A' + 10 : c);
}
while (*start == '\r' || *start == '\n')
@ -402,10 +397,7 @@ static int new_pem_obj(SSLCTX *ssl_ctx, int is_cacert, uint8_t *where,
/* In a format we can now understand - so process it */
if ((ret = do_obj(ssl_ctx, obj_type, ssl_obj, password)))
{
ssl_obj_free(ssl_obj);
goto error;
}
end += strlen(ends[i]);
remain -= strlen(ends[i]);
@ -415,7 +407,6 @@ static int new_pem_obj(SSLCTX *ssl_ctx, int is_cacert, uint8_t *where,
remain--;
}
ssl_obj_free(ssl_obj);
break;
}
}
@ -428,6 +419,7 @@ static int new_pem_obj(SSLCTX *ssl_ctx, int is_cacert, uint8_t *where,
ret = new_pem_obj(ssl_ctx, is_cacert, end, remain, password);
error:
ssl_obj_free(ssl_obj);
return ret;
}

View File

@ -47,7 +47,7 @@ static void MD5Transform(uint32_t state[4], const uint8_t block[64]);
static void Encode(uint8_t *output, uint32_t *input, uint32_t len);
static void Decode(uint32_t *output, const uint8_t *input, uint32_t len);
static uint8_t PADDING[64] =
static const uint8_t PADDING[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -114,8 +114,7 @@ void MD5Update(MD5_CTX *ctx, const uint8_t * msg, int len)
x = (uint32_t)((ctx->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((ctx->count[0] += ((uint32_t)len << 3))
< ((uint32_t)len << 3))
if ((ctx->count[0] += ((uint32_t)len << 3)) < ((uint32_t)len << 3))
ctx->count[1]++;
ctx->count[1] += ((uint32_t)len >> 29);

View File

@ -389,6 +389,7 @@ int pkcs12_decode(SSLCTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
/* get the salt */
if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
goto error;
salt = &buf[offset];
/* work out what the mac should be */

View File

@ -36,9 +36,7 @@ void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length)
m = ctx->m;
for (i = 0; i < 256; i++)
{
m[i] = i;
}
for (i = 0; i < 256; i++)
{
@ -48,9 +46,7 @@ void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length)
m[j] = a;
if (++k >= length)
{
k = 0;
}
}
}

View File

@ -28,7 +28,7 @@
#include "crypto.h"
#ifdef CONFIG_BIGINT_CRT
static bigint *bi_crt(RSA_CTX *rsa, bigint *bi);
static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi);
#endif
void RSA_priv_key_new(RSA_CTX **ctx,
@ -126,8 +126,8 @@ void RSA_free(RSA_CTX *rsa_ctx)
* @return The number of bytes that were originally encrypted. -1 on error.
* @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
int is_decryption)
int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data,
uint8_t *out_data, int is_decryption)
{
int byte_size = ctx->num_octets;
uint8_t *block;
@ -155,10 +155,9 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */
{
while (block[i++] == 0xff && i < byte_size);
if (block[i-2] != 0xff)
{
i = byte_size; /*ensure size is 0 */
}
}
else /* PKCS1.5 encryption padding is random */
#endif
@ -169,9 +168,7 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
/* get only the bit we want */
if (size > 0)
{
memcpy(out_data, &block[i], size);
}
free(block);
return size ? size : -1;
@ -180,7 +177,7 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,
/**
* Performs m = c^d mod n
*/
bigint *RSA_private(RSA_CTX *c, bigint *bi_msg)
bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)
{
#ifdef CONFIG_BIGINT_CRT
return bi_crt(c, bi_msg);
@ -197,7 +194,7 @@ bigint *RSA_private(RSA_CTX *c, bigint *bi_msg)
* This should really be in bigint.c (and was at one stage), but needs
* access to the RSA_CTX context...
*/
static bigint *bi_crt(RSA_CTX *rsa, bigint *bi)
static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi)
{
BI_CTX *ctx = rsa->bi_ctx;
bigint *m1, *m2, *h;
@ -245,7 +242,7 @@ void RSA_print(const RSA_CTX *rsa_ctx)
/**
* Performs c = m^e mod n
*/
bigint *RSA_public(RSA_CTX *c, bigint *bi_msg)
bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)
{
c->bi_ctx->mod_offset = BIGINT_M_OFFSET;
return bi_mod_power(c->bi_ctx, bi_msg, c->e);
@ -255,7 +252,7 @@ bigint *RSA_public(RSA_CTX *c, bigint *bi_msg)
* Use PKCS1.5 for encryption/signing.
* see http://www.rsasecurity.com/rsalabs/node.asp?id=2125
*/
int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len,
uint8_t *out_data, int is_signing)
{
int byte_size = ctx->num_octets;

View File

@ -57,17 +57,13 @@ void SHA1Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
while (len--)
{
ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
ctx->Length_Low += 8;
if (ctx->Length_Low == 0)
{
ctx->Length_High++;
}
if (ctx->Message_Block_Index == 64)
{
SHA1ProcessMessageBlock(ctx);
}
msg++;
}

View File

@ -150,14 +150,17 @@ extern "C" {
* @brief Establish a new client/server context.
*
* This function is called before any client/server SSL connections are made.
* If multiple threads are used, then each thread will have its own SSLCTX
* context. Any number of connections may be made with a single
* context.
*
* Each new connection will use the this context's private key and
* certificate chain. If a different certificate chain is required, then a
* different context needs to be be used.
*
* There are two threading models supported - a single thread with one
* SSLCTX can support any number of SSL connections - and multiple threads can
* support one SSLCTX object each (the default). But if a single SSLCTX
* object uses many SSL objects in individual threads, then the
* CONFIG_SSLCTX_MUTEXING option needs to be configured.
*
* @param options [in] Any particular options. At present the options
* supported are:
* - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
@ -233,6 +236,7 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl);
/**
* @brief Read the SSL data stream.
* The socket must be in blocking mode.
* @param ssl [in] An SSL object reference.
* @param in_data [out] If the read was successful, a pointer to the read
* buffer will be here. Do NOT ever free this memory as this buffer is used in
@ -248,7 +252,8 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl);
EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
/**
* @brief Write to the SSL data stream.
* @brief Write to the SSL data stream.
* The socket must be in blocking mode.
* @param ssl [in] An SSL obect reference.
* @param out_data [in] The data to be written
* @param out_len [in] The number of bytes to be written.
@ -407,6 +412,12 @@ EXP_FUNC int STDCALL ssl_obj_load(SSLCTX *ssl_ctx, int obj_type, const char *fil
*/
EXP_FUNC int STDCALL ssl_obj_memory_load(SSLCTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
/**
* @brief Return the axTLS library version as a string.
* @note New API function for v1.1
*/
EXP_FUNC const char * STDCALL ssl_version(void);
/** @} */
#ifdef __cplusplus

View File

@ -1445,179 +1445,269 @@ cleanup:
return ret;
}
#if 0
/**************************************************************************
* 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;
SSLCTX *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);
/* check the return status */
if (ssl_handshake_status(ssl_clnt))
{
printf("Client ");
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);
close(client_fd);
/* exit this thread */
}
static int SSL_basic_test(void)
{
int server_fd, client_fd, ret = 0, size = 0, offset = 0;
SSLCTX *ssl_svr_ctx = NULL;
struct sockaddr_in client_addr;
uint8_t *read_buf;
int 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);
close(server_fd);
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 1
#define NUM_THREADS_STR "1"
static SSL *my_ssls[NUM_THREADS*3]; /* enough for all client fds */
#define NUM_THREADS 200
typedef struct
{
SSLCTX *ssl_ctx;
SSLCTX *ssl_clnt_ctx;
int port;
int thread_id;
} multi_t;
int do_connect(multi_t *multi_data)
void do_multi_clnt(multi_t *multi_data)
{
int res = 1, client_fd, i;
SSL *ssl = NULL;
char tmp[5];
/* make sure other threads work before this one */
if (multi_data->thread_id == NUM_THREADS)
{
sleep(2); /* sets the maximum time this test will run */
}
if ((client_fd = client_socket_init(multi_data->port)) < 0)
goto client_test_exit;
sleep(0);
ssl = ssl_client_new(multi_data->ssl_ctx, client_fd, NULL);
sleep(1);
ssl = ssl_client_new(multi_data->ssl_clnt_ctx, client_fd, NULL);
if ((res = ssl_handshake_status(ssl)))
goto client_test_exit;
sprintf(tmp, "%d\n", multi_data->thread_id);
for (i = 0; i < 100; i++)
{
ssl_write(ssl, (uint8_t *)tmp, strlen(tmp)+1);
printf("Client ");
ssl_display_error(res);
goto client_test_exit;
}
res = 0;
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);
close(client_fd);
free(multi_data);
return 0;
}
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)
{
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;
SSLCTX *ssl_server_ctx = NULL;
uint8_t buf[1024];
pthread_t threads[NUM_THREADS];
int i, res = 1;
SSLCTX *ssl_server_ctx;
SSLCTX *ssl_clnt_ctx;
pthread_t clnt_threads[NUM_THREADS];
pthread_t svr_threads[NUM_THREADS];
int i, res = 0;
struct sockaddr_in client_addr;
int clnt_len = sizeof(client_addr);
fd_set read_set;
int max_fd;
int death_total = 0;
SSLCTX *ssl_client_ctx = ssl_ctx_new(DEFAULT_CLNT_OPTION,
SSL_DEFAULT_CLNT_SESS, NULL);
printf("Do multi-threading test (takes a minute)\n");
FD_ZERO(&read_set);
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;
FD_SET(server_fd, &read_set);
max_fd = server_fd;
ssl_server_ctx = ssl_ctx_new(DEFAULT_SVR_OPTION|SSL_SERVER_VERIFY_LATER,
SSL_DEFAULT_SVR_SESS, NULL);
for (i = 0; i < NUM_THREADS; i++)
{
multi_t *multi_data = (multi_t *)malloc(sizeof(multi_t));
multi_data->ssl_ctx = ssl_server_ctx;
multi_data->ssl_clnt_ctx = ssl_clnt_ctx;
multi_data->port = g_port;
multi_data->thread_id = i+1;
if (pthread_create(&threads[i], NULL,
(void *(*)(void *))do_connect, (void *)multi_data) < 0)
goto error;
pthread_create(&clnt_threads[i], NULL,
(void *(*)(void *))do_multi_clnt, (void *)multi_data);
pthread_detach(clnt_threads[i]);
}
sleep(1);
for (;;)
for (i = 0; i < NUM_THREADS; i++)
{
fd_set rdfs = read_set;
int n;
SSL *ssl_svr;
int client_fd = accept(server_fd,
(struct sockaddr *)&client_addr, &clnt_len);
if ((n = select(max_fd+1, &rdfs, NULL, NULL, 0)) > 0)
{
while (n)
{
/* check for server */
if (FD_ISSET(server_fd, &rdfs))
{
int client_fd = accept(server_fd,
(struct sockaddr *)&client_addr, &clnt_len);
if (client_fd < 0)
goto error;
if (client_fd < 0)
goto error;
ssl_svr = ssl_server_new(ssl_server_ctx, client_fd);
if (client_fd > max_fd) /* set max fd */
{
max_fd = client_fd;
}
my_ssls[client_fd] = ssl_server_new(
ssl_server_ctx, client_fd);
FD_SET(client_fd, &read_set);
if (--n == 0)
continue;
}
i = server_fd;
while (++i <= max_fd && n)
{
if (FD_ISSET(i, &rdfs))
{
SSL *ssl;
ssl = my_ssls[i];
res = ssl_read(ssl, &read_buf);
n--;
/* kill the client */
if (res != SSL_OK)
{
if (res == SSL_ERROR_CONN_LOST)
{
ssl_free(ssl);
my_ssls[i] = NULL;
close(i);
FD_CLR(i, &read_set);
death_total++;
}
else if (res > 0)
{
if (strcmp(NUM_THREADS_STR "\n",
(const char *)buf) == 0)
{
sleep(1); /* allow rest of data */
goto all_ok;
}
}
else /* some problem */
{
printf("Got some problem %d\n", res);
goto error;
}
} /* if */
} /* if */
} /* for */
}
}
pthread_create(&svr_threads[i], NULL,
(void *(*)(void *))do_multi_svr, (void *)ssl_svr);
}
all_ok:
printf("Multi-thread test passed (%d)\n", death_total);
res = 0;
/* 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_client_ctx);
ssl_ctx_free(ssl_clnt_ctx);
close(server_fd);
return res;
}
@ -1705,6 +1795,14 @@ int main(int argc, char *argv[])
}
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())

View File

@ -165,6 +165,8 @@ EXP_FUNC SSLCTX *STDCALL ssl_ctx_new(uint32_t options, int num_sessions)
ssl_ctx->num_sessions = num_sessions;
#endif
SSL_CTX_MUTEX_INIT(ssl_ctx->mutex);
#if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
if (~options & SSL_NO_DEFAULT_KEY)
{
@ -201,7 +203,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSLCTX *ssl_ctx)
if (ssl_ctx == NULL)
return;
ssl = ssl_ctx->sess_head;
ssl = ssl_ctx->head;
/* clear out all the ssl entries */
while (ssl)
@ -214,9 +216,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSLCTX *ssl_ctx)
#ifndef CONFIG_SSL_SKELETON_MODE
/* clear out all the sessions */
for (i = 0; i < ssl_ctx->num_sessions; i++)
{
session_free(ssl_ctx->ssl_sessions, i);
}
free(ssl_ctx->ssl_sessions);
#endif
@ -232,6 +232,7 @@ EXP_FUNC void STDCALL ssl_ctx_free(SSLCTX *ssl_ctx)
remove_ca_certs(ssl_ctx->ca_cert_ctx);
#endif
ssl_ctx->chain_length = 0;
SSL_CTX_MUTEX_DESTROY(ssl_ctx->mutex);
RSA_free(ssl_ctx->rsa_ctx);
RNG_terminate();
free(ssl_ctx);
@ -252,24 +253,20 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl)
ssl_ctx = ssl->ssl_ctx;
SSL_CTX_LOCK(ssl_ctx->mutex);
/* adjust the server SSL list */
if (ssl->prev)
{
ssl->prev->next = ssl->next;
}
else
{
ssl_ctx->sess_head = ssl->next;
}
ssl_ctx->head = ssl->next;
if (ssl->next)
{
ssl->next->prev = ssl->prev;
}
else
{
ssl_ctx->sess_tail = ssl->prev;
}
ssl_ctx->tail = ssl->prev;
SSL_CTX_UNLOCK(ssl_ctx->mutex);
/* may already be free - but be sure */
free(ssl->all_pkts);
@ -278,7 +275,6 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl)
free(ssl->encrypt_ctx);
free(ssl->decrypt_ctx);
free(ssl->master_secret);
buf_free(&ssl->bm_buf);
#ifdef CONFIG_SSL_CERT_VERIFICATION
x509_free(ssl->x509_ctx);
#endif
@ -315,15 +311,28 @@ EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data)
EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len)
{
int ret = send_packet(ssl, PT_APP_PROTOCOL_DATA, out_data, out_len);
int n = out_len, nw, i, tot = 0;
/* make sure there is no problem with overflow due to padding etc */
if (ret > out_len)
/* maximum size of a TLS packet is around 16kB, so fragment */
do
{
ret = out_len;
}
nw = n;
return ret;
if (nw > RT_MAX_PLAIN_LENGTH) /* fragment if necessary */
nw = RT_MAX_PLAIN_LENGTH;
if ((i = send_packet(ssl, PT_APP_PROTOCOL_DATA,
&out_data[tot], nw)) <= 0)
{
out_len = i; /* an error */
break;
}
tot += i;
n -= i;
} while (n > 0);
return out_len;
}
/**
@ -411,9 +420,7 @@ int add_cert_auth(SSLCTX *ssl_ctx, const uint8_t *buf, int len)
/* recurse? */
if (len > 0)
{
ret = add_cert_auth(ssl_ctx, &buf[offset], len);
}
error:
return ret;
@ -459,17 +466,24 @@ EXP_FUNC const char * STDCALL ssl_get_cert_dn(SSL *ssl, int component)
*/
EXP_FUNC SSL * STDCALL ssl_find(SSLCTX *ssl_ctx, int client_fd)
{
SSL *ssl = ssl_ctx->sess_head;
SSL *ssl;
SSL_CTX_LOCK(ssl_ctx->mutex);
ssl = ssl_ctx->head;
/* search through all the ssl entries */
while (ssl)
{
if (ssl->client_fd == client_fd)
{
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return ssl;
}
ssl = ssl->next;
}
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return NULL;
}
@ -526,31 +540,33 @@ SSL *ssl_new(SSLCTX *ssl_ctx, int client_fd)
SSL *ssl = (SSL *)calloc(1, sizeof(SSL));
ssl->ssl_ctx = ssl_ctx;
ssl->need_bytes = SSL_RECORD_SIZE; /* need a record */
ssl->bm_buf = buf_new();
ssl->client_fd = client_fd;
ssl->flag = SSL_NEED_RECORD;
ssl->certs = ssl_ctx->certs;
ssl->chain_length = ssl_ctx->chain_length;
ssl->bm_data = ssl->bm_all_data+BM_RECORD_OFFSET; /* space at the start */
#ifdef CONFIG_ENABLE_VERIFICATION
ssl->ca_cert_ctx = ssl_ctx->ca_cert_ctx;
#endif
/* a bit hacky but saves a few bytes of memory */
ssl->flag |= ssl_ctx->options;
SSL_CTX_LOCK(ssl_ctx->mutex);
/* build up a linked list, so we can remove it all later */
if (ssl_ctx->sess_head == NULL)
if (ssl_ctx->head == NULL)
{
ssl_ctx->sess_head = ssl;
ssl_ctx->sess_tail = ssl;
ssl_ctx->head = ssl;
ssl_ctx->tail = ssl;
}
else
{
ssl->prev = ssl_ctx->sess_tail;
ssl_ctx->sess_tail->next = ssl;
ssl_ctx->sess_tail = ssl;
ssl->prev = ssl_ctx->tail;
ssl_ctx->tail->next = ssl;
ssl_ctx->tail = ssl;
}
SSL_CTX_UNLOCK(ssl_ctx->mutex);
return ssl;
}
@ -905,32 +921,30 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt)
*/
static int send_raw_packet(SSL *ssl, uint8_t protocol)
{
uint8_t *rec_buf = ssl->bm_buf.pre_data;
int pkt_size = SSL_RECORD_SIZE+ssl->bm_buf.index;
uint8_t *rec_buf = ssl->bm_all_data;
int pkt_size = SSL_RECORD_SIZE+ssl->bm_index;
int ret;
rec_buf[0] = protocol;
rec_buf[1] = 0x03; /* version = 3.1 (TLS) */
rec_buf[2] = 0x01;
rec_buf[3] = ssl->bm_buf.index >> 8;
rec_buf[4] = ssl->bm_buf.index & 0xff;
rec_buf[3] = ssl->bm_index >> 8;
rec_buf[4] = ssl->bm_index & 0xff;
DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_buf.pre_data,
DISPLAY_BYTES(ssl, "sending %d bytes", ssl->bm_all_data,
pkt_size, pkt_size);
ret = SOCKET_WRITE(ssl->client_fd, ssl->bm_buf.pre_data, pkt_size);
if ((ret = SOCKET_WRITE(ssl->client_fd,
ssl->bm_all_data, pkt_size)) < 0)
ret = SSL_ERROR_CONN_LOST;
SET_SSL_FLAG(SSL_NEED_RECORD); /* reset for next time */
ssl->bm_buf.index = 0;
ssl->bm_index = 0;
if (ret < 0)
{
ret = SSL_ERROR_CONN_LOST;
}
else if (protocol != PT_APP_PROTOCOL_DATA)
if (protocol != PT_APP_PROTOCOL_DATA)
{
/* always return SSL_OK during handshake */
return ret = SSL_OK;
ret = SSL_OK;
}
return ret;
@ -942,18 +956,16 @@ static int send_raw_packet(SSL *ssl, uint8_t protocol)
int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
{
int msg_length = length;
ssl->bm_buf.index = msg_length;
buf_grow(&ssl->bm_buf, msg_length+32);
int ret, pad_bytes = 0;
ssl->bm_index = msg_length;
/* if our state is bad, don't bother */
if (ssl->hs_status == SSL_ERROR_DEAD)
{
return SSL_ERROR_CONN_LOST;
}
if (in) /* has the buffer already been initialised? */
{
memcpy(ssl->bm_buf.data, in, length);
memcpy(ssl->bm_data, in, length);
}
if (IS_SET_SSL_FLAG(SSL_TX_ENCRYPTED))
@ -966,55 +978,56 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
if (protocol == PT_HANDSHAKE_PROTOCOL)
{
DISPLAY_STATE(ssl, 1, ssl->bm_buf.data[0], 0);
DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
if (ssl->bm_buf.data[0] != HS_HELLO_REQUEST)
if (ssl->bm_data[0] != HS_HELLO_REQUEST)
{
add_packet(ssl, ssl->bm_buf.data, ssl->bm_buf.index);
add_packet(ssl, ssl->bm_data, ssl->bm_index);
}
}
/* add the packet digest */
msg_length += ssl->cipher_info->digest_size;
ssl->bm_buf.index = msg_length;
add_hmac_digest(ssl, mode, ssl->bm_buf.data, length,
&ssl->bm_buf.data[length]);
ssl->bm_index = msg_length;
add_hmac_digest(ssl, mode, ssl->bm_data, length,
&ssl->bm_data[length]);
/* add padding? */
if (ssl->cipher_info->padding_size)
{
int last_blk_size = msg_length%ssl->cipher_info->padding_size;
int pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
/* ensure we always have at least 1 padding byte */
if (pad_bytes == 0)
{
pad_bytes += ssl->cipher_info->padding_size;
}
memset(&ssl->bm_buf.data[msg_length], pad_bytes-1, pad_bytes);
memset(&ssl->bm_data[msg_length], pad_bytes-1, pad_bytes);
msg_length += pad_bytes;
ssl->bm_buf.index = msg_length;
ssl->bm_index = msg_length;
}
DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_buf.data, msg_length);
DISPLAY_BYTES(ssl, "unencrypted write", ssl->bm_data, msg_length);
increment_write_sequence(ssl);
/* now encrypt the packet */
ssl->cipher_info->encrypt(ssl->encrypt_ctx, ssl->bm_buf.data,
ssl->bm_buf.data, msg_length);
ssl->cipher_info->encrypt(ssl->encrypt_ctx, ssl->bm_data,
ssl->bm_data, msg_length);
}
else if (protocol == PT_HANDSHAKE_PROTOCOL)
{
DISPLAY_STATE(ssl, 1, ssl->bm_buf.data[0], 0);
DISPLAY_STATE(ssl, 1, ssl->bm_data[0], 0);
if (ssl->bm_buf.data[0] != HS_HELLO_REQUEST)
if (ssl->bm_data[0] != HS_HELLO_REQUEST)
{
add_packet(ssl, ssl->bm_buf.data, ssl->bm_buf.index);
add_packet(ssl, ssl->bm_data, ssl->bm_index);
}
}
return send_raw_packet(ssl, protocol);
if ((ret = send_raw_packet(ssl, protocol)) <= 0)
return ret;
return length; /* just return what we wanted to send */
}
/**
@ -1125,9 +1138,8 @@ int basic_read(SSL *ssl, uint8_t **in_data)
int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
uint8_t *buf;
buf_grow(&ssl->bm_buf, ssl->need_bytes);
buf = ssl->bm_buf.data;
read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_buf.index],
buf = ssl->bm_data;
read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_index],
ssl->need_bytes-ssl->got_bytes);
/* connection has gone, so die */
@ -1139,17 +1151,16 @@ int basic_read(SSL *ssl, uint8_t **in_data)
}
DISPLAY_BYTES(ssl, "received %d bytes",
&ssl->bm_buf.data[ssl->bm_buf.index], read_len, read_len);
&ssl->bm_data[ssl->bm_index], read_len, read_len);
ssl->got_bytes += read_len;
ssl->bm_buf.index += read_len;
ssl->bm_index += read_len;
/* haven't quite got what we want, so try again later */
if (ssl->got_bytes < ssl->need_bytes)
{
return SSL_OK;
}
read_len = ssl->got_bytes;
ssl->got_bytes = 0;
if (IS_SET_SSL_FLAG(SSL_NEED_RECORD))
@ -1162,14 +1173,21 @@ int basic_read(SSL *ssl, uint8_t **in_data)
add_packet(ssl, &buf[2], 3);
ret = process_sslv23_client_hello(ssl);
#else
printf("Error: no SSLv23 handshaking allowed\n");
TTY_FLUSH();
printf("Error: no SSLv23 handshaking allowed\n"); TTY_FLUSH();
ret = SSL_ERROR_NOT_SUPPORTED;
#endif
goto error; /* not an error - just get out of here */
}
ssl->need_bytes = (buf[3] << 8) + buf[4];
/* do we violate the spec with the message size? */
if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET)
{
ret = SSL_ERROR_INVALID_PROT_MSG;
goto error;
}
CLR_SSL_FLAG(SSL_NEED_RECORD);
memcpy(ssl->record_buf, buf, 3); /* store for hmac */
is_record = 1;
@ -1182,9 +1200,7 @@ int basic_read(SSL *ssl, uint8_t **in_data)
}
if (is_record)
{
ssl->record_type = buf[0];
}
else if (IS_SET_SSL_FLAG(SSL_RX_ENCRYPTED))
{
ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, read_len);
@ -1224,8 +1240,8 @@ int basic_read(SSL *ssl, uint8_t **in_data)
break;
case PT_APP_PROTOCOL_DATA:
*in_data = ssl->bm_buf.data; /* point to the work buffer */
(*in_data)[read_len] = 0; /* null terminate just in case */
*in_data = ssl->bm_data; /* point to the work buffer */
(*in_data)[read_len] = 0; /* null terminate just in case */
ret = read_len;
break;
@ -1242,12 +1258,10 @@ int basic_read(SSL *ssl, uint8_t **in_data)
}
error:
ssl->bm_buf.index = 0; /* reset to go again */
ssl->bm_index = 0; /* reset to go again */
if (ret < SSL_OK && in_data) /* if all wrong, then clear this buffer ptr */
{
*in_data = NULL;
}
return ret;
}
@ -1277,13 +1291,11 @@ static int do_handshake(SSL *ssl, uint8_t *buf, int read_len)
}
hs_len += SSL_HS_HDR_SIZE; /* adjust for when adding packets */
ssl->bm_buf.index = hs_len; /* store the size and check later */
ssl->bm_index = hs_len; /* store the size and check later */
DISPLAY_STATE(ssl, 0, handshake_type, 0);
if (handshake_type != HS_CERT_VERIFY && handshake_type != HS_HELLO_REQUEST)
{
add_packet(ssl, buf, hs_len);
}
#if defined(CONFIG_SSL_ENABLE_CLIENT)
ret = is_client ?
@ -1295,9 +1307,7 @@ static int do_handshake(SSL *ssl, uint8_t *buf, int read_len)
/* just use recursion to get the rest */
if (hs_len < read_len && ret == SSL_OK)
{
ret = do_handshake(ssl, &buf[hs_len], read_len-hs_len);
}
error:
return ret;
@ -1322,7 +1332,7 @@ int send_change_cipher_spec(SSL *ssl)
*/
int send_finished(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
buf[0] = HS_FINISHED;
buf[1] = 0;
@ -1365,9 +1375,7 @@ int send_alert(SSL *ssl, int error_code)
#ifdef CONFIG_SSL_FULL_MODE
if (IS_SET_SSL_FLAG(SSL_DISPLAY_STATES))
{
ssl_display_error(error_code);
}
#endif
switch (error_code)
@ -1424,25 +1432,21 @@ int send_alert(SSL *ssl, int error_code)
*/
int process_finished(SSL *ssl, int hs_len)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
int ret = SSL_OK;
int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
int resume = IS_SET_SSL_FLAG(SSL_SESSION_RESUME);
PARANOIA_CHECK(ssl->bm_buf.index, SSL_FINISHED_HASH_SIZE+4);
PARANOIA_CHECK(ssl->bm_index, SSL_FINISHED_HASH_SIZE+4);
/* check that we all work before we continue */
if (memcmp(ssl->final_finish_mac, &buf[4], SSL_FINISHED_HASH_SIZE))
{
return SSL_ERROR_FINISHED_INVALID;
}
if ((!is_client && !resume) || (is_client && resume))
{
if ((ret = send_change_cipher_spec(ssl)) == SSL_OK)
{
ret = send_finished(ssl);
}
}
/* Don't need this stuff anymore */
@ -1470,7 +1474,7 @@ error:
int send_certificate(SSL *ssl)
{
int i = 0;
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
int offset = 7;
int chain_length;
@ -1485,7 +1489,6 @@ int send_certificate(SSL *ssl)
buf[offset++] = 0;
buf[offset++] = cert->size >> 8; /* cert 1 length */
buf[offset++] = cert->size & 0xff;
buf_grow(&ssl->bm_buf, offset + cert->size);
memcpy(&buf[offset], cert->buf, cert->size);
offset += cert->size;
i++;
@ -1497,7 +1500,7 @@ int send_certificate(SSL *ssl)
chain_length += 3;
buf[2] = chain_length >> 8; /* handshake length */
buf[3] = chain_length & 0xff;
ssl->bm_buf.index = offset;
ssl->bm_index = offset;
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
@ -1516,10 +1519,9 @@ SSL_SESS *ssl_session_update(int max_sessions,
/* no sessions? Then bail */
if (max_sessions == 0)
{
return NULL;
}
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
if (session_id)
{
for (i = 0; i < max_sessions; i++)
@ -1543,6 +1545,7 @@ SSL_SESS *ssl_session_update(int max_sessions,
memcpy(ssl->master_secret,
ssl_sessions[i]->master_secret, SSL_SECRET_SIZE);
SET_SSL_FLAG(SSL_SESSION_RESUME);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
return ssl_sessions[i]; /* a session was found */
}
}
@ -1558,6 +1561,7 @@ SSL_SESS *ssl_session_update(int max_sessions,
ssl_sessions[i] = (SSL_SESS *)calloc(1, sizeof(SSL_SESS));
ssl_sessions[i]->conn_time = tm;
ssl->session_index = i;
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
return ssl_sessions[i]; /* return the session object */
}
else if (ssl_sessions[i]->conn_time <= oldest_sess_time)
@ -1573,6 +1577,7 @@ SSL_SESS *ssl_session_update(int max_sessions,
oldest_sess->conn_time = tm;
memset(oldest_sess->session_id, 0, sizeof(SSL_SESSION_ID_SIZE));
memset(oldest_sess->master_secret, 0, sizeof(SSL_SECRET_SIZE));
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
return oldest_sess;
}
@ -1593,11 +1598,15 @@ static void session_free(SSL_SESS *ssl_sessions[], int sess_index)
*/
void kill_ssl_session(SSL_SESS **ssl_sessions, SSL *ssl)
{
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
if (ssl->ssl_ctx->num_sessions)
{
session_free(ssl_sessions, ssl->session_index);
ssl->session = NULL;
}
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
}
#endif /* CONFIG_SSL_SKELETON_MODE */
@ -1684,10 +1693,10 @@ EXP_FUNC int STDCALL ssl_verify_cert(SSL *ssl)
int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
{
int ret = SSL_OK;
int pkt_size = ssl->bm_buf.index;
int pkt_size = ssl->bm_index;
int cert_size, offset = 5;
int total_cert_size = (ssl->bm_buf.data[offset]<<8) +
ssl->bm_buf.data[offset+1];
int total_cert_size = (ssl->bm_data[offset]<<8) +
ssl->bm_data[offset+1];
int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
X509_CTX **chain = x509_ctx;
offset += 2;
@ -1697,10 +1706,10 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
while (offset < total_cert_size)
{
offset++; /* skip empty char */
cert_size = (ssl->bm_buf.data[offset]<<8) + ssl->bm_buf.data[offset+1];
cert_size = (ssl->bm_data[offset]<<8) + ssl->bm_data[offset+1];
offset += 2;
if (x509_new(&ssl->bm_buf.data[offset], NULL, chain))
if (x509_new(&ssl->bm_data[offset], NULL, chain))
{
ret = SSL_ERROR_BAD_CERTIFICATE;
goto error;
@ -1983,6 +1992,15 @@ void DISPLAY_ALERT(SSL *ssl, int alert)
#endif /* CONFIG_SSL_FULL_MODE */
/**
* Return the version of this library.
*/
EXP_FUNC const char * STDCALL ssl_version()
{
static const char * axtls_version = AXTLS_VERSION " " __DATE__;
return axtls_version;
}
/**
* Enable the various language bindings to work regardless of the
* configuration - they just return an error statement and a bad return code.

View File

@ -28,6 +28,31 @@
extern "C" {
#endif
#include "version.h"
/* Mutexing definitions */
#if defined(CONFIG_SSLCTX_MUTEXING)
#if defined(WIN32)
#define SSL_CTX_MUTEX_TYPE HANDLE
#define SSL_CTX_MUTEX_INIT(A) A=CreateMutex(0, FALSE, 0)
#define SSL_CTX_MUTEX_DESTROY(A) CloseHandle(A)
#define SSL_CTX_LOCK(A) WaitForSingleObject(A, INFINITE)
#define SSL_CTX_UNLOCK(A) ReleaseMutex(A)
#else
#include <pthread.h>
#define SSL_CTX_MUTEX_TYPE pthread_mutex_t
#define SSL_CTX_MUTEX_INIT(A) pthread_mutex_init(&A, NULL)
#define SSL_CTX_MUTEX_DESTROY(A) pthread_mutex_destroy(&A)
#define SSL_CTX_LOCK(A) pthread_mutex_lock(&A)
#define SSL_CTX_UNLOCK(A) pthread_mutex_unlock(&A)
#endif
#else /* no mutexing */
#define SSL_CTX_MUTEX_INIT(A)
#define SSL_CTX_MUTEX_DESTROY(A)
#define SSL_CTX_LOCK(A)
#define SSL_CTX_UNLOCK(A)
#endif
#define SSL_RANDOM_SIZE 32
#define SSL_SECRET_SIZE 48
#define SSL_FINISHED_HASH_SIZE 12
@ -52,6 +77,9 @@ extern "C" {
#define IS_SET_SSL_FLAG(A) (ssl->flag & A)
#define MAX_KEY_BYTE_SIZE 512 /* for a 4096 bit key */
#define RT_MAX_PLAIN_LENGTH 16384
#define RT_EXTRA 1024
#define BM_RECORD_OFFSET 5
#ifdef CONFIG_SSL_SKELETON_MODE
#define NUM_PROTOCOLS 1
@ -138,11 +166,13 @@ struct _SSL
uint8_t *key_block;
void *encrypt_ctx;
void *decrypt_ctx;
BUF_MEM bm_buf;
uint8_t bm_all_data[RT_MAX_PLAIN_LENGTH+RT_EXTRA];
uint8_t *bm_data;
int bm_index;
struct _SSL *next; /* doubly linked list */
struct _SSL *prev;
SSL_CERT *certs;
struct _SSLCTX *ssl_ctx; /* back reference to a clnt/svr ctx */
struct _SSLCTX *ssl_ctx; /* back reference to a clnt/svr ctx */
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t session_index;
SSL_SESS *session;
@ -172,13 +202,16 @@ struct _SSLCTX
#ifdef CONFIG_SSL_CERT_VERIFICATION
CA_CERT_CTX *ca_cert_ctx;
#endif
SSL *sess_head;
SSL *sess_tail;
SSL *head;
SSL *tail;
SSL_CERT certs[CONFIG_SSL_MAX_CERTS];
#ifndef CONFIG_SSL_SKELETON_MODE
uint16_t num_sessions;
SSL_SESS **ssl_sessions;
#endif
#ifdef CONFIG_SSLCTX_MUTEXING
SSL_CTX_MUTEX_TYPE mutex;
#endif
};
typedef struct _SSLCTX SSLCTX;

View File

@ -117,7 +117,7 @@ int do_client_connect(SSL *ssl)
int ret = SSL_OK;
send_client_hello(ssl); /* send the client hello */
ssl->bm_buf.index = 0;
ssl->bm_index = 0;
ssl->next_state = HS_SERVER_HELLO;
ssl->hs_status = SSL_NOT_OK; /* not connected */
@ -151,7 +151,7 @@ int do_client_connect(SSL *ssl)
*/
static int send_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
time_t tm = time(NULL);
uint8_t *tm_ptr = &buf[6]; /* time will go here */
int i, offset;
@ -186,19 +186,19 @@ static int send_client_hello(SSL *ssl)
buf[offset++] = 0;
}
buf[offset++] = 0; /* number of ciphers */
buf[offset++] = NUM_PROTOCOLS*2; /* number of ciphers */
buf[offset++] = 0; /* number of ciphers */
buf[offset++] = NUM_PROTOCOLS*2;/* number of ciphers */
/* put all our supported protocols in our request */
for (i = 0; i < NUM_PROTOCOLS; i++)
{
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = ssl_prot_prefs[i];
}
buf[offset++] = 1; /* no compression */
buf[offset++] = 1; /* no compression */
buf[offset++] = 0;
buf[3] = offset - 4; /* handshake size */
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
@ -208,8 +208,8 @@ static int send_client_hello(SSL *ssl)
*/
static int process_server_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
int pkt_size = ssl->bm_buf.index;
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
int offset;
int version = (buf[4] << 4) + buf[5];
int num_sessions = ssl->ssl_ctx->num_sessions;
@ -217,9 +217,7 @@ static int process_server_hello(SSL *ssl)
/* check that we are talking to a TLSv1 server */
if (version != 0x31)
{
return SSL_ERROR_INVALID_VERSION;
}
/* get the server random value */
memcpy(ssl->server_random, &buf[6], SSL_RANDOM_SIZE);
@ -260,7 +258,7 @@ static int process_server_hello_done(SSL *ssl)
*/
static int send_client_key_xchg(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
uint8_t premaster_secret[SSL_SECRET_SIZE];
int enc_secret_size = -1;
@ -271,8 +269,13 @@ static int send_client_key_xchg(SSL *ssl)
premaster_secret[1] = 0x01;
get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]);
DISPLAY_RSA(ssl, "send_client_key_xchg", ssl->x509_ctx->rsa_ctx);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
enc_secret_size = RSA_encrypt(ssl->x509_ctx->rsa_ctx, premaster_secret,
SSL_SECRET_SIZE, &buf[6], 0);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
buf[2] = (enc_secret_size + 2) >> 8;
buf[3] = (enc_secret_size + 2) & 0xff;
buf[4] = enc_secret_size >> 8;
@ -298,7 +301,7 @@ static int process_cert_req(SSL *ssl)
*/
static int send_cert_verify(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
uint8_t dgst[MD5_SIZE+SHA1_SIZE];
RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
int n, ret;
@ -309,7 +312,11 @@ static int send_cert_verify(SSL *ssl)
buf[1] = 0;
finished_digest(ssl, NULL, dgst); /* calculate the digest */
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (n == 0)
{

View File

@ -45,10 +45,7 @@ EXP_FUNC SSL * STDCALL ssl_server_new(SSLCTX *ssl_ctx, int client_fd)
#ifdef CONFIG_SSL_FULL_MODE
if (ssl_ctx->chain_length == 0)
{
printf("Warning - no server certificate defined\n");
TTY_FLUSH();
}
printf("Warning - no server certificate defined\n"); TTY_FLUSH();
#endif
return ssl;
@ -67,9 +64,7 @@ int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
{
case HS_CLIENT_HELLO:
if ((ret = process_client_hello(ssl)) == SSL_OK)
{
ret = send_server_hello_sequence(ssl);
}
break;
#ifdef CONFIG_SSL_CERT_VERIFICATION
@ -107,9 +102,9 @@ int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
*/
static int process_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
uint8_t *record_buf = ssl->record_buf;
int pkt_size = ssl->bm_buf.index;
int pkt_size = ssl->bm_index;
int i, j, cs_len, id_len, offset = 6 + SSL_RANDOM_SIZE;
int version = (record_buf[1] << 4) + record_buf[2];
int ret = SSL_OK;
@ -169,7 +164,7 @@ error:
*/
int process_sslv23_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
int version = (buf[3] << 4) + buf[4];
int ret = SSL_OK;
@ -291,7 +286,7 @@ static int send_server_hello_sequence(SSL *ssl)
*/
static int send_server_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
uint8_t *buf = ssl->bm_data;
int offset = 0;
buf[0] = HS_SERVER_HELLO;
@ -358,8 +353,8 @@ static int send_server_hello_done(SSL *ssl)
*/
static int process_client_key_xchg(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
int pkt_size = ssl->bm_buf.index;
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
int premaster_size, secret_length = (buf[2] << 8) + buf[3];
uint8_t premaster_secret[MAX_KEY_BYTE_SIZE];
RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
@ -370,12 +365,14 @@ static int process_client_key_xchg(SSL *ssl)
/* is there an extra size field? */
if ((secret_length - 2) == rsa_ctx->num_octets)
{
offset += 2;
}
PARANOIA_CHECK(pkt_size, rsa_ctx->num_octets+offset);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
premaster_size = RSA_decrypt(rsa_ctx, &buf[offset], premaster_secret, 1);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (premaster_size != SSL_SECRET_SIZE ||
premaster_secret[0] != 0x03 || /* check version is 3.1 (TLS) */
@ -420,8 +417,8 @@ static int send_certificate_request(SSL *ssl)
*/
static int process_cert_verify(SSL *ssl)
{
uint8_t *buf = ssl->bm_buf.data;
int pkt_size = ssl->bm_buf.index;
uint8_t *buf = ssl->bm_data;
int pkt_size = ssl->bm_index;
uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
uint8_t dgst[MD5_SIZE+SHA1_SIZE];
X509_CTX *x509_ctx = ssl->x509_ctx;