1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-06-16 11:21:18 +03:00

Merge pull request #19 from ikeyasu/merge-200

Merging axtls 2.0.0
This commit is contained in:
Ivan Grokhotkov
2016-08-25 10:50:14 +08:00
committed by GitHub
21 changed files with 855 additions and 452 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -38,9 +38,6 @@
#include "os_port.h"
#include "crypto.h"
/* all commented out in skeleton mode */
#ifndef CONFIG_SSL_SKELETON_MODE
#define rot1(x) (((x) << 24) | ((x) >> 8))
#define rot2(x) (((x) << 16) | ((x) >> 16))
#define rot3(x) (((x) << 8) | ((x) >> 24))
@ -453,5 +450,3 @@ static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
data[row-1] = tmp[row-1] ^ *(--k);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2015, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -200,6 +200,8 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest);
/**************************************************************************
* RSA declarations

View File

@ -53,7 +53,7 @@ static int rng_fd = -1;
static HCRYPTPROV gCryptProv;
#endif
#if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
#if (!defined(ESP8266) && !defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
/* change to processor registers as appropriate */
#define ENTROPY_POOL_SIZE 32
#define ENTROPY_COUNTER1 ((((uint64_t)tv.tv_sec)<<32) | tv.tv_usec)
@ -109,7 +109,7 @@ int get_file(const char *filename, uint8_t **buf)
EXP_FUNC void STDCALL RNG_initialize()
{
#if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
rng_fd = ax_open("/dev/urandom", O_RDONLY);
rng_fd = open("/dev/urandom", O_RDONLY);
#elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
if (!CryptAcquireContext(&gCryptProv,
NULL, NULL, PROV_RSA_FULL, 0))
@ -130,7 +130,7 @@ EXP_FUNC void STDCALL RNG_initialize()
/* start of with a stack to copy across */
int i;
memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE);
srand((unsigned int)&i);
rand_r((unsigned int *)entropy_pool);
#endif
}
@ -181,7 +181,7 @@ EXP_FUNC int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
#else /* nothing else to use, so use a custom RNG */
/* The method we use when we've got nothing better. Use RC4, time
and a couple of random seeds to generate a random sequence */
RC4_CTX rng_ctx;
AES_CTX rng_ctx;
struct timeval tv;
MD5_CTX rng_digest_ctx;
uint8_t digest[MD5_SIZE];
@ -200,10 +200,10 @@ EXP_FUNC int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
MD5_Final(digest, &rng_digest_ctx);
/* come up with the random sequence */
RC4_setup(&rng_ctx, digest, MD5_SIZE); /* use as a key */
AES_set_key(&rng_ctx, digest, (const uint8_t *)ep, AES_MODE_128); /* use as a key */
memcpy(rand_data, entropy_pool, num_rand_bytes < ENTROPY_POOL_SIZE ?
num_rand_bytes : ENTROPY_POOL_SIZE);
RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
AES_cbc_encrypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
/* move things along */
for (i = ENTROPY_POOL_SIZE-1; i >= MD5_SIZE ; i--)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -103,3 +103,37 @@ void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
SHA1_Update(&context, digest, SHA1_SIZE);
SHA1_Final(digest, &context);
}
/**
* Perform HMAC-SHA256
* NOTE: does not handle keys larger than the block size.
*/
void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key,
int key_len, uint8_t *digest)
{
SHA256_CTX context;
uint8_t k_ipad[64];
uint8_t k_opad[64];
int i;
memset(k_ipad, 0, sizeof k_ipad);
memset(k_opad, 0, sizeof k_opad);
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
for (i = 0; i < 64; i++)
{
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
SHA256_Init(&context);
SHA256_Update(&context, k_ipad, 64);
SHA256_Update(&context, msg, length);
SHA256_Final(digest, &context);
SHA256_Init(&context);
SHA256_Update(&context, k_opad, 64);
SHA256_Update(&context, digest, SHA256_SIZE);
SHA256_Final(digest, &context);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Cameron Rich
* Copyright (c) 2012-2016, Cameron Rich
*
* All rights reserved.
*
@ -56,7 +56,6 @@ typedef INT64 int64_t;
#include <inttypes.h>
#else
#include <stdint.h>
#include <endian.h>
#endif /* Not Solaris */
#endif /* Not Win32 */

View File

@ -125,7 +125,6 @@ const char * x509_display_error(int error);
#define ASN1_EXPLICIT_TAG 0xa0
#define ASN1_V3_DATA 0xa3
#define SIG_TYPE_MD2 0x02
#define SIG_TYPE_MD5 0x04
#define SIG_TYPE_SHA1 0x05
#define SIG_TYPE_SHA256 0x0b

View File

@ -82,7 +82,9 @@ EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type,
#ifdef CONFIG_SSL_HAS_PEM
ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
#else
#ifdef CONFIG_SSL_FULL_MODE
printf("%s", unsupported_str);
#endif
ret = SSL_ERROR_NOT_SUPPORTED;
#endif
}
@ -93,7 +95,9 @@ error:
ssl_obj_free(ssl_obj);
return ret;
#else
#ifdef CONFIG_SSL_FULL_MODE
printf("%s", unsupported_str);
#endif
return SSL_ERROR_NOT_SUPPORTED;
#endif /* CONFIG_SSL_SKELETON_MODE */
}
@ -150,7 +154,9 @@ static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
break;
#endif
default:
#ifdef CONFIG_SSL_FULL_MODE
printf("%s", unsupported_str);
#endif
ret = SSL_ERROR_NOT_SUPPORTED;
break;
}
@ -223,7 +229,7 @@ static int pem_decrypt(const char *where, const char *end,
if (password == NULL || strlen(password) == 0)
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Need a password for this PEM file\n"); TTY_FLUSH();
printf("Error: Need a password for this PEM file\n");
#endif
goto error;
}
@ -240,7 +246,7 @@ static int pem_decrypt(const char *where, const char *end,
else
{
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: Unsupported password cipher\n"); TTY_FLUSH();
printf("Error: Unsupported password cipher\n");
#endif
goto error;
}
@ -475,7 +481,7 @@ error:
#ifdef CONFIG_SSL_FULL_MODE
if (ret)
{
printf("Error: Certificate or key not loaded\n"); TTY_FLUSH();
printf("Error: Certificate or key not loaded\n");
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -49,10 +49,8 @@
static char *key_password = NULL;
void *SSLv23_server_method(void) { return NULL; }
void *SSLv3_server_method(void) { return NULL; }
void *TLSv1_server_method(void) { return NULL; }
void *SSLv23_client_method(void) { return NULL; }
void *SSLv3_client_method(void) { return NULL; }
void *TLSv1_client_method(void) { return NULL; }
@ -81,14 +79,13 @@ void SSL_CTX_free(SSL_CTX * ssl_ctx)
SSL * SSL_new(SSL_CTX *ssl_ctx)
{
SSL *ssl;
ssl_func_type_t ssl_func_type;
#ifdef CONFIG_SSL_ENABLE_CLIENT
ssl_func_type_t ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
#endif
ssl = ssl_new(ssl_ctx, -1); /* fd is set later */
ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
#ifdef CONFIG_SSL_ENABLE_CLIENT
if (ssl_func_type == SSLv23_client_method ||
ssl_func_type == SSLv3_client_method ||
if (ssl_func_type == SSLv3_client_method ||
ssl_func_type == TLSv1_client_method)
{
SET_SSL_FLAG(SSL_IS_CLIENT);
@ -231,8 +228,6 @@ void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file)
ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL);
}
void SSLv23_method(void) { }
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { }
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -91,9 +91,3 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size)
}
#endif
#undef malloc
#undef realloc
#undef calloc
static const char * out_of_mem_str = "out of memory";
static const char * file_open_str = "Could not open file \"%s\"";

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2015, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -62,7 +62,7 @@ extern "C" {
#include "util/time.h"
#include <errno.h>
// #define alloca(size) __builtin_alloca(size)
#define alloca(size) __builtin_alloca(size)
#define TTY_FLUSH()
#ifdef putc
#undef putc
@ -80,6 +80,7 @@ extern "C" {
#define EWOULDBLOCK EAGAIN
#define hmac_sha1 ax_hmac_sha1
#define hmac_sha256 ax_hmac_sha256
#define hmac_md5 ax_hmac_md5
#ifndef be64toh
@ -189,19 +190,6 @@ EXP_FUNC int STDCALL getdomainname(char *buf, int buf_size);
#endif /* Not Win32 */
/* some functions to mutate the way these work */
#define malloc(A) ax_port_malloc(A, __FILE__, __LINE__)
#ifndef realloc
#define realloc(A,B) ax_port_realloc(A,B, __FILE__, __LINE__)
#endif
#define calloc(A,B) ax_port_calloc(A,B, __FILE__, __LINE__)
#define free(x) ax_port_free(x)
EXP_FUNC void * STDCALL ax_port_malloc(size_t s, const char*, int);
EXP_FUNC void * STDCALL ax_port_realloc(void *y, size_t s, const char*, int);
EXP_FUNC void * STDCALL ax_port_calloc(size_t n, size_t s, const char*, int);
EXP_FUNC void * STDCALL ax_port_free(void*);
EXP_FUNC int STDCALL ax_open(const char *pathname, int flags);
inline uint32_t htonl(uint32_t n){
return ((n & 0xff) << 24) |
((n & 0xff00) << 8) |
@ -211,6 +199,8 @@ inline uint32_t htonl(uint32_t n){
#define ntohl htonl
EXP_FUNC int STDCALL ax_open(const char *pathname, int flags);
#ifdef CONFIG_PLATFORM_LINUX
void exit_now(const char *format, ...) __attribute((noreturn));
#else

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -91,13 +91,16 @@ extern "C" {
#define SSL_ERROR_DEAD -2
#define SSL_CLOSE_NOTIFY -3
#define SSL_ERROR_CONN_LOST -256
#define SSL_ERROR_RECORD_OVERFLOW -257
#define SSL_ERROR_SOCK_SETUP_FAILURE -258
#define SSL_ERROR_INVALID_HANDSHAKE -260
#define SSL_ERROR_INVALID_PROT_MSG -261
#define SSL_ERROR_INVALID_HMAC -262
#define SSL_ERROR_INVALID_VERSION -263
#define SSL_ERROR_UNSUPPORTED_EXTENSION -264
#define SSL_ERROR_INVALID_SESSION -265
#define SSL_ERROR_NO_CIPHER -266
#define SSL_ERROR_INVALID_CERT_HASH_ALG -267
#define SSL_ERROR_BAD_CERTIFICATE -268
#define SSL_ERROR_INVALID_KEY -269
#define SSL_ERROR_FINISHED_INVALID -271
@ -115,19 +118,25 @@ extern "C" {
#define SSL_ALERT_CLOSE_NOTIFY 0
#define SSL_ALERT_UNEXPECTED_MESSAGE 10
#define SSL_ALERT_BAD_RECORD_MAC 20
#define SSL_ALERT_RECORD_OVERFLOW 22
#define SSL_ALERT_HANDSHAKE_FAILURE 40
#define SSL_ALERT_BAD_CERTIFICATE 42
#define SSL_ALERT_UNSUPPORTED_CERTIFICATE 43
#define SSL_ALERT_CERTIFICATE_EXPIRED 45
#define SSL_ALERT_CERTIFICATE_UNKNOWN 46
#define SSL_ALERT_ILLEGAL_PARAMETER 47
#define SSL_ALERT_UNKNOWN_CA 48
#define SSL_ALERT_DECODE_ERROR 50
#define SSL_ALERT_DECRYPT_ERROR 51
#define SSL_ALERT_INVALID_VERSION 70
#define SSL_ALERT_NO_RENEGOTIATION 100
#define SSL_ALERT_UNSUPPORTED_EXTENSION 110
/* The ciphers that are supported */
#define SSL_AES128_SHA 0x2f
#define SSL_AES256_SHA 0x35
#define SSL_RC4_128_SHA 0x05
#define SSL_RC4_128_MD5 0x04
#define SSL_AES128_SHA256 0x3c
#define SSL_AES256_SHA256 0x3d
/* build mode ids' */
#define SSL_BUILD_SKELETON_MODE 0x01

View File

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC5DCCAcwCCQDGL4Ul/VVK0TANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA4
MTUxMDIwNTZaFw0zMDA0MjQxMDIwNTZaMDQxMjAwBgNVBAoTKWF4VExTIFByb2pl
Y3QgRG9kZ3kgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEA6d9BDlOJo6fdmSkUdAkMYFnlAK4Q5qwE/vYX8umY0Gz1
CEIwEyKJq+rCpl2vmlwEETGcphlRsiybOMwVfdRDQv51ZfTJnz1WQZBKdsYb55xy
JWOZFHSpuZa+THW1TOImpvxXoK3OMh/dcuaQG5G7QoWMWRK5aZvpl27rRx033dik
U8lO12oaUtCD3AgNttU7zTLiIQjeIZ9JbES74mx1s4lT22nmXoL5/AdJa3yGjDjG
J1RX8hQ7/pbcC2s4+0XIjGthB2ClJWyvv8bY96POZ+Kc5XLFFjxYoGHtRzQbw2gx
rx7r5/a+d7XgWedMnwf1M1/v9vNA14kgjg2pwuFD4QIDAQABMA0GCSqGSIb3DQEB
CwUAA4IBAQBW9MtGYroXnu8id8rDvjki8Vk8lDBD0AkOq5QYbXB322Wbg2C+cmHP
zQAJ9YZU/NjnRZiEX1QVoZAXdSXXScbUbSlBQweEvGZmailTGPhJ/wtmNtK6P7ZP
YIJ6XaQdALvteULFMhEQKM9UUkrsbqh41wtoTjOsMlWcRvq9FHLujXxyzjvFPdEI
kz26d7F2yqtgzxW4YLAlclZu6vex/MzNmbjhHenMWp6LNWVWofdIv9jRS1tOSyK+
hg2sV7CL75nzQ/A22ql8X3SZLAZNR/V7DF+MSBrIcHBzgFZ8QEGlNam29WseuC2C
51+ZXtv0DZ1bPmX+Pz1E06wMGlBTpC4z
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAUACCQCMs+C6AhuzaTANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA4
MTUxMDIwNTZaFw0zMDA0MjQxMDIwNTZaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAq9P2gjL8e0OgMrA81JoZeqaZMRmSaTH8xIHf7MkbGYW1ZyBWW+n+017itYgH
pu61CiYcyAfuUACTL2VBhrakCb+j53OF0V+9uEH/BkftUUcu+6ppBB4XI5KbYmTH
JjhBW8N1OHadHLCG4dkQLjnaFgekpM8xZzvd4kkbM4mZqtECAwEAATANBgkqhkiG
9w0BAQsFAAOCAQEAG/SBHWYNVf5drxN1aLx9UqTpryjmzDP9/gckKpuNEiDCmp38
MIKBJYamL9hTwmtf1k4vHB2sxXfv9AVULwMa7+RcgUc3fhTWWoqf1LvYvzMrx9W9
yU6bfXQh5zb6TOrq/j4fliA2NeDvAzq8tzhBVhiyvy0GhhU1C9eBRVFr4D9l/B2z
odWvCZ4ljLjtmoOhrSSf0OHFuk/eqFJ/SS1jo3ugl7wEmMzphOjmwgK7CLyACBSn
6Bzlh/A16AgqznniMHZ9p99zopMSqPUkCCHPEUiqs8hoy6Pc7O6FrTKfkeiAnY1u
SfKiOf4ODmDcLb5gVtDx+zp59Q/khBX+6IT+BA==
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAUACCQCMs+C6AhuzajANBgkqhkiG9w0BAQwFADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA4
MTUxMDIwNTZaFw0zMDA0MjQxMDIwNTZaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAq9P2gjL8e0OgMrA81JoZeqaZMRmSaTH8xIHf7MkbGYW1ZyBWW+n+017itYgH
pu61CiYcyAfuUACTL2VBhrakCb+j53OF0V+9uEH/BkftUUcu+6ppBB4XI5KbYmTH
JjhBW8N1OHadHLCG4dkQLjnaFgekpM8xZzvd4kkbM4mZqtECAwEAATANBgkqhkiG
9w0BAQwFAAOCAQEA151mqDTC1YPiFq4t7J2UK84jYlGriW0z6KhfmtecLm18Uu07
vDh+cvWoFRf/fgSlO7c6td0Jb4NGjPBwpV4UmoYND65d1+EkrP+Bl+2DndUi/xka
h4bwfmPrKAjDbUZaNnRi1zQdyPU9tta9b0MamHQVHFOIAyLQXDf1/Tz+wRaFPCIH
PfJEqjD4Nr15O41aMJOaM170rOtbQ9uH4Vlotpt+xJsHufmHFMf1fJtgBXayCzmS
1927ajoKNyDA/QQ+e+60uba6UN6CQnoMzmkMypMxD4JBUt6TEgB46uQ7nkkf3raS
tMAyMnytSc+O7EbhZSWWBSTUkeI+YWjLAtI42Q==
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICWDCCAUACCQCMs+C6AhuzazANBgkqhkiG9w0BAQ0FADA0MTIwMAYDVQQKEylh
eFRMUyBQcm9qZWN0IERvZGd5IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNjA4
MTUxMDIwNTZaFw0zMDA0MjQxMDIwNTZaMCwxFjAUBgNVBAoTDWF4VExTIFByb2pl
Y3QxEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
gYEAq9P2gjL8e0OgMrA81JoZeqaZMRmSaTH8xIHf7MkbGYW1ZyBWW+n+017itYgH
pu61CiYcyAfuUACTL2VBhrakCb+j53OF0V+9uEH/BkftUUcu+6ppBB4XI5KbYmTH
JjhBW8N1OHadHLCG4dkQLjnaFgekpM8xZzvd4kkbM4mZqtECAwEAATANBgkqhkiG
9w0BAQ0FAAOCAQEA51hsTX6DlE9WnI0XaNfx0hfWG74maMZK+GG1LQKi6JlaA6U4
7aLpoluw4G7oZz39ROuNbOvTMrhN4kOXG16Zk2HGufzAQgqoegIsgI2BiaOtmBnn
vOchhiZ16JLmKB6ZMlESFubV1Ynyr6QacTLOipLGICGn3N65BrbwfaXD/nbJQd+a
YOwkJ9OHxbK9zqLMBG3kK/QKXqID3dI21+MDCGSSBAh/tVPhwTMcTzViF5vT4Mpq
81+Z9eg3vI++rOiBppdjRKH4CFcO74rEA6j9fNFHI0PiS142TtT4vXLf+D4PQLkI
tBuSq99ensRy5IvjYXpcx7/jixVd3MmwWrolbg==
-----END CERTIFICATE-----

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -54,55 +54,37 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void
static int send_raw_packet(SSL *ssl, uint8_t protocol);
static void certificate_free(SSL* ssl);
static int increase_bm_data_size(SSL *ssl, size_t size);
static int check_certificate_chain(SSL *ssl);
/**
* The server will pick the cipher based on the order that the order that the
* ciphers are listed. This order is defined at compile time.
*/
#ifdef CONFIG_SSL_SKELETON_MODE
const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
{ SSL_RC4_128_SHA };
#else
#ifndef CONFIG_SSL_SKELETON_MODE
static void session_free(SSL_SESSION *ssl_sessions[], int sess_index);
#endif
const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] =
#ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */
{ SSL_AES128_SHA, SSL_AES256_SHA};
{ SSL_AES128_SHA, SSL_AES128_SHA256, SSL_AES256_SHA, SSL_AES256_SHA256 };
#elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */
{ SSL_AES128_SHA, SSL_AES256_SHA};
{ SSL_AES128_SHA256, SSL_AES256_SHA256, SSL_AES256_SHA, SSL_AES128_SHA };
#else /* CONFIG_SSL_PROT_HIGH */ /* high security, low speed */
{ SSL_AES256_SHA, SSL_AES128_SHA};
{ SSL_AES256_SHA256, SSL_AES128_SHA256, SSL_AES256_SHA, SSL_AES128_SHA };
#endif
#endif /* CONFIG_SSL_SKELETON_MODE */
/**
* The cipher map containing all the essentials for each cipher.
*/
#ifdef CONFIG_SSL_SKELETON_MODE
static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
{
{ /* RC4-SHA */
SSL_RC4_128_SHA, /* RC4-SHA */
16, /* key size */
0, /* iv size */
2*(SHA1_SIZE+16), /* key block size */
0, /* no padding */
SHA1_SIZE, /* digest size */
hmac_sha1, /* hmac algorithm */
(crypt_func)RC4_crypt, /* encrypt */
(crypt_func)RC4_crypt /* decrypt */
},
};
#else
static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
{
{ /* AES128-SHA */
SSL_AES128_SHA, /* AES128-SHA */
16, /* key size */
16, /* iv size */
2*(SHA1_SIZE+16+16), /* key block size */
16, /* block padding size */
SHA1_SIZE, /* digest size */
2*(SHA1_SIZE+16+16), /* key block size */
hmac_sha1, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
@ -111,17 +93,39 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] =
SSL_AES256_SHA, /* AES256-SHA */
32, /* key size */
16, /* iv size */
2*(SHA1_SIZE+32+16), /* key block size */
16, /* block padding size */
SHA1_SIZE, /* digest size */
2*(SHA1_SIZE+32+16), /* key block size */
hmac_sha1, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
},
{ /* AES128-SHA256 */
SSL_AES128_SHA256, /* AES128-SHA256 */
16, /* key size */
16, /* iv size */
16, /* block padding size */
SHA256_SIZE, /* digest size */
2*(SHA256_SIZE+32+16), /* key block size */
hmac_sha256, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
},
{ /* AES256-SHA256 */
SSL_AES256_SHA256, /* AES256-SHA256 */
32, /* key size */
16, /* iv size */
16, /* block padding size */
SHA256_SIZE, /* digest size */
2*(SHA256_SIZE+32+16), /* key block size */
hmac_sha256, /* hmac algorithm */
(crypt_func)AES_cbc_encrypt, /* encrypt */
(crypt_func)AES_cbc_decrypt /* decrypt */
}
};
#endif
static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
static void prf(SSL *ssl, const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len,
uint8_t *out, int olen);
static const cipher_info_t *get_cipher_info(uint8_t cipher);
static void increment_read_sequence(SSL *ssl);
@ -247,7 +251,9 @@ EXP_FUNC void STDCALL ssl_free(SSL *ssl)
/* may already be free - but be sure */
free(ssl->encrypt_ctx);
ssl->encrypt_ctx = NULL;
free(ssl->decrypt_ctx);
ssl->decrypt_ctx = NULL;
disposable_free(ssl);
certificate_free(ssl);
free(ssl->bm_all_data);
@ -343,6 +349,26 @@ int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len)
ssl_cert = &ssl_ctx->certs[i];
ssl_cert->size = len;
ssl_cert->buf = (uint8_t *)malloc(len);
switch (cert->sig_type)
{
case SIG_TYPE_SHA1:
ssl_cert->hash_alg = SIG_ALG_SHA1;
break;
case SIG_TYPE_SHA256:
ssl_cert->hash_alg = SIG_ALG_SHA256;
break;
case SIG_TYPE_SHA384:
ssl_cert->hash_alg = SIG_ALG_SHA384;
break;
case SIG_TYPE_SHA512:
ssl_cert->hash_alg = SIG_ALG_SHA512;
break;
}
memcpy(ssl_cert->buf, buf, len);
ssl_ctx->chain_length++;
len -= offset;
@ -634,36 +660,19 @@ static void increment_write_sequence(SSL *ssl)
static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
const uint8_t *buf, int buf_len, uint8_t *hmac_buf)
{
const size_t prefix_size = 8 + SSL_RECORD_SIZE;
bool hmac_inplace = (uint32_t)buf - (uint32_t)ssl->bm_data >= prefix_size;
uint8_t tmp[prefix_size];
int hmac_len = buf_len + prefix_size;
uint8_t *t_buf;
if (hmac_inplace) {
t_buf = ((uint8_t*)buf) - prefix_size;
memcpy(tmp, t_buf, prefix_size);
} else {
t_buf = (uint8_t *)malloc(hmac_len+10);
}
int hmac_len = buf_len + 8 + SSL_RECORD_SIZE;
uint8_t *t_buf = (uint8_t *)alloca(buf_len+100);
memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ?
ssl->write_sequence : ssl->read_sequence, 8);
memcpy(&t_buf[8], hmac_header, SSL_RECORD_SIZE);
if (!hmac_inplace) {
memcpy(&t_buf[8+SSL_RECORD_SIZE], buf, buf_len);
}
ssl->cipher_info->hmac(t_buf, hmac_len,
(mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_READ) ?
ssl->server_mac : ssl->client_mac,
ssl->cipher_info->digest_size, hmac_buf);
if (hmac_inplace) {
memcpy(t_buf, tmp, prefix_size);
}
else {
free(t_buf);
}
#if 0
print_blob("record", hmac_header, SSL_RECORD_SIZE);
print_blob("buf", buf, buf_len);
@ -686,7 +695,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
print_blob("client mac",
ssl->client_mac, ssl->cipher_info->digest_size);
}
print_blob("hmac", hmac_buf, SHA1_SIZE);
print_blob("hmac", hmac_buf, ssl->cipher_info->digest_size);
#endif
}
@ -695,11 +704,9 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header,
*/
static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
{
uint8_t hmac_buf[SHA1_SIZE];
uint8_t hmac_buf[SHA256_SIZE]; // size of largest digest
int hmac_offset;
if (ssl->cipher_info->padding_size)
{
int last_blk_size = buf[read_len-1], i;
hmac_offset = read_len-last_blk_size-ssl->cipher_info->digest_size-1;
@ -720,16 +727,6 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
}
}
}
}
else /* stream cipher */
{
hmac_offset = read_len - ssl->cipher_info->digest_size;
if (hmac_offset < 0)
{
hmac_offset = 0;
}
}
/* sanity check the offset */
ssl->hmac_header[3] = hmac_offset >> 8; /* insert size */
@ -749,10 +746,21 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len)
* it to calculate the hash at the end.
*/
void add_packet(SSL *ssl, const uint8_t *pkt, int len)
{
// TLS1.2+
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2 || ssl->version == 0)
{
SHA256_Update(&ssl->dc->sha256_ctx, pkt, len);
}
if (ssl->version < SSL_PROTOCOL_VERSION_TLS1_2 ||
ssl->next_state == HS_SERVER_HELLO ||
ssl->next_state == 0)
{
MD5_Update(&ssl->dc->md5_ctx, pkt, len);
SHA1_Update(&ssl->dc->sha1_ctx, pkt, len);
}
}
/**
* Work out the MD5 PRF.
@ -760,7 +768,7 @@ void add_packet(SSL *ssl, const uint8_t *pkt, int len)
static void p_hash_md5(const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len, uint8_t *out, int olen)
{
uint8_t a1[128];
uint8_t a1[MD5_SIZE+77];
/* A(1) */
hmac_md5(seed, seed_len, sec, sec_len, a1);
@ -788,7 +796,7 @@ static void p_hash_md5(const uint8_t *sec, int sec_len,
static void p_hash_sha1(const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len, uint8_t *out, int olen)
{
uint8_t a1[128];
uint8_t a1[SHA1_SIZE+77];
/* A(1) */
hmac_sha1(seed, seed_len, sec, sec_len, a1);
@ -810,11 +818,46 @@ static void p_hash_sha1(const uint8_t *sec, int sec_len,
}
}
/**
* Work out the SHA256 PRF.
*/
static void p_hash_sha256(const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len, uint8_t *out, int olen)
{
uint8_t a1[SHA256_SIZE+77];
/* A(1) */
hmac_sha256(seed, seed_len, sec, sec_len, a1);
memcpy(&a1[SHA256_SIZE], seed, seed_len);
hmac_sha256(a1, SHA256_SIZE+seed_len, sec, sec_len, out);
while (olen > SHA256_SIZE)
{
uint8_t a2[SHA256_SIZE];
out += SHA256_SIZE;
olen -= SHA256_SIZE;
// A(N)
hmac_sha256(a1, SHA256_SIZE, sec, sec_len, a2);
memcpy(a1, a2, SHA256_SIZE);
// work out the actual hash
hmac_sha256(a1, SHA256_SIZE+seed_len, sec, sec_len, out);
}
}
/**
* Work out the PRF.
*/
static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
static void prf(SSL *ssl, const uint8_t *sec, int sec_len,
uint8_t *seed, int seed_len,
uint8_t *out, int olen)
{
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
p_hash_sha256(sec, sec_len, seed, seed_len, out, olen);
}
else // TLS1.0/1.1
{
int len, i;
const uint8_t *S1, *S2;
@ -832,6 +875,7 @@ static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
for (i = 0; i < olen; i++)
out[i] = xbuf[i] ^ ybuf[i];
}
}
/**
* Generate a master secret based on the client/server random data and the
@ -839,37 +883,44 @@ static void prf(const uint8_t *sec, int sec_len, uint8_t *seed, int seed_len,
*/
void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret)
{
uint8_t buf[128]; /* needs to be > 13+32+32 in size */
uint8_t buf[77];
//print_blob("premaster secret", premaster_secret, 48);
strcpy((char *)buf, "master secret");
memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE);
memcpy(&buf[45], ssl->dc->server_random, SSL_RANDOM_SIZE);
prf(premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
prf(ssl, premaster_secret, SSL_SECRET_SIZE, buf, 77, ssl->dc->master_secret,
SSL_SECRET_SIZE);
#if 0
print_blob("client random", ssl->dc->client_random, 32);
print_blob("server random", ssl->dc->server_random, 32);
print_blob("master secret", ssl->dc->master_secret, 48);
#endif
}
/**
* Generate a 'random' blob of data used for the generation of keys.
*/
static void generate_key_block(uint8_t *client_random, uint8_t *server_random,
static void generate_key_block(SSL *ssl,
uint8_t *client_random, uint8_t *server_random,
uint8_t *master_secret, uint8_t *key_block, int key_block_size)
{
uint8_t buf[128];
uint8_t buf[77];
strcpy((char *)buf, "key expansion");
memcpy(&buf[13], server_random, SSL_RANDOM_SIZE);
memcpy(&buf[45], client_random, SSL_RANDOM_SIZE);
prf(master_secret, SSL_SECRET_SIZE, buf, 77, key_block, key_block_size);
prf(ssl, master_secret, SSL_SECRET_SIZE, buf, 77,
key_block, key_block_size);
}
/**
* Calculate the digest used in the finished message. This function also
* doubles up as a certificate verify function.
*/
void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
int finished_digest(SSL *ssl, const char *label, uint8_t *digest)
{
uint8_t mac_buf[128];
uint8_t mac_buf[SHA1_SIZE+MD5_SIZE+15];
uint8_t *q = mac_buf;
MD5_CTX md5_ctx = ssl->dc->md5_ctx;
SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
int dgst_len;
if (label)
{
@ -877,28 +928,43 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest)
q += strlen(label);
}
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
SHA256_CTX sha256_ctx = ssl->dc->sha256_ctx; // interim copy
SHA256_Final(q, &sha256_ctx);
q += SHA256_SIZE;
dgst_len = (int)(q-mac_buf);
}
else // TLS1.0/1.1
{
MD5_CTX md5_ctx = ssl->dc->md5_ctx; // interim copy
SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx;
MD5_Final(q, &md5_ctx);
q += MD5_SIZE;
SHA1_Final(q, &sha1_ctx);
q += SHA1_SIZE;
dgst_len = (int)(q-mac_buf);
}
if (label)
{
prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf),
digest, SSL_FINISHED_HASH_SIZE);
prf(ssl, ssl->dc->master_secret, SSL_SECRET_SIZE,
mac_buf, dgst_len, digest, SSL_FINISHED_HASH_SIZE);
}
else /* for use in a certificate verify */
{
memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE);
memcpy(digest, mac_buf, dgst_len);
}
#if 0
printf("label: %s\n", label);
print_blob("master secret", ssl->dc->master_secret, 48);
print_blob("mac_buf", mac_buf, q-mac_buf);
print_blob("mac_buf", mac_buf, dgst_len);
print_blob("finished digest", digest, SSL_FINISHED_HASH_SIZE);
#endif
return dgst_len;
}
/**
@ -908,8 +974,8 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void
{
switch (ssl->cipher)
{
#ifndef CONFIG_SSL_SKELETON_MODE
case SSL_AES128_SHA:
case SSL_AES128_SHA256:
{
AES_CTX *aes_ctx;
if (cached)
@ -927,6 +993,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void
}
case SSL_AES256_SHA:
case SSL_AES256_SHA256:
{
AES_CTX *aes_ctx;
if (cached)
@ -944,19 +1011,6 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void
return (void *)aes_ctx;
}
case SSL_RC4_128_MD5:
#endif
case SSL_RC4_128_SHA:
{
RC4_CTX* rc4_ctx;
if (cached)
rc4_ctx = (RC4_CTX*) cached;
else
rc4_ctx = (RC4_CTX*) malloc(sizeof(RC4_CTX));
RC4_setup(rc4_ctx, key, 16);
return (void *)rc4_ctx;
}
}
return NULL; /* its all gone wrong */
@ -1036,6 +1090,9 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
if (ssl->hs_status == SSL_ERROR_DEAD)
return SSL_ERROR_CONN_LOST;
if (IS_SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY))
return SSL_CLOSE_NOTIFY;
if (in) /* has the buffer already been initialised? */
{
memcpy(ssl->bm_data, in, length);
@ -1071,8 +1128,7 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
&ssl->bm_data[msg_length]);
msg_length += ssl->cipher_info->digest_size;
/* add padding? */
if (ssl->cipher_info->padding_size)
/* add padding */
{
int last_blk_size = msg_length%ssl->cipher_info->padding_size;
int pad_bytes = ssl->cipher_info->padding_size - last_blk_size;
@ -1089,8 +1145,7 @@ int send_packet(SSL *ssl, uint8_t protocol, const uint8_t *in, int length)
increment_write_sequence(ssl);
/* add the explicit IV for TLS1.1 */
if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
ssl->cipher_info->iv_size)
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1)
{
uint8_t iv_size = ssl->cipher_info->iv_size;
uint8_t *t_buf = malloc(msg_length + iv_size);
@ -1140,21 +1195,18 @@ static int set_key_block(SSL *ssl, int is_write)
return -1;
/* only do once in a handshake */
if (ssl->dc->key_block == NULL)
if (!ssl->dc->key_block_generated)
{
ssl->dc->key_block = (uint8_t *)malloc(ciph_info->key_block_size);
#if 0
print_blob("client", ssl->dc->client_random, 32);
print_blob("server", ssl->dc->server_random, 32);
print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
#endif
generate_key_block(ssl->dc->client_random, ssl->dc->server_random,
generate_key_block(ssl, ssl->dc->client_random, ssl->dc->server_random,
ssl->dc->master_secret, ssl->dc->key_block,
ciph_info->key_block_size);
#if 0
print_blob("master", ssl->dc->master_secret, SSL_SECRET_SIZE);
print_blob("keyblock", ssl->dc->key_block, ciph_info->key_block_size);
print_blob("client random", ssl->dc->client_random, 32);
print_blob("server random", ssl->dc->server_random, 32);
#endif
ssl->dc->key_block_generated = 1;
}
q = ssl->dc->key_block;
@ -1177,14 +1229,15 @@ static int set_key_block(SSL *ssl, int is_write)
memcpy(server_key, q, ciph_info->key_size);
q += ciph_info->key_size;
#ifndef CONFIG_SSL_SKELETON_MODE
if (ciph_info->iv_size) /* RC4 has no IV, AES does */
{
memcpy(client_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
memcpy(server_iv, q, ciph_info->iv_size);
q += ciph_info->iv_size;
}
#if 0
print_blob("client key", client_key, ciph_info->key_size);
print_blob("server key", server_key, ciph_info->key_size);
print_blob("client iv", client_iv, ciph_info->iv_size);
print_blob("server iv", server_iv, ciph_info->iv_size);
#endif
// free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx);
@ -1222,6 +1275,9 @@ int basic_read(SSL *ssl, uint8_t **in_data)
int read_len, is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
uint8_t *buf = ssl->bm_data;
if (IS_SET_SSL_FLAG(SSL_SENT_CLOSE_NOTIFY))
return SSL_CLOSE_NOTIFY;
read_len = SOCKET_READ(ssl->client_fd, &buf[ssl->bm_read_index],
ssl->need_bytes-ssl->got_bytes);
@ -1261,31 +1317,10 @@ int basic_read(SSL *ssl, uint8_t **in_data)
/* check for sslv2 "client hello" */
if (buf[0] & 0x80 && buf[2] == 1)
{
#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
uint8_t version = (buf[3] << 4) + buf[4];
DISPLAY_BYTES(ssl, "ssl2 record", buf, 5);
/* should be v3.1 (TLSv1) or better */
ssl->version = ssl->client_version = version;
if (version > SSL_PROTOCOL_VERSION_MAX)
{
/* use client's version */
ssl->version = SSL_PROTOCOL_VERSION_MAX;
}
else if (version < SSL_PROTOCOL_MIN_VERSION)
{
ret = SSL_ERROR_INVALID_VERSION;
ssl_display_error(ret);
return ret;
}
add_packet(ssl, &buf[2], 3);
ret = process_sslv23_client_hello(ssl);
#else
printf("Error: no SSLv23 handshaking allowed\n"); TTY_FLUSH();
ret = SSL_ERROR_NOT_SUPPORTED;
#ifdef CONFIG_SSL_FULL_MODE
printf("Error: no SSLv23 handshaking allowed\n");
#endif
ret = SSL_ERROR_NOT_SUPPORTED;
goto error; /* not an error - just get out of here */
}
@ -1294,8 +1329,7 @@ int basic_read(SSL *ssl, uint8_t **in_data)
/* do we violate the spec with the message size? */
if (ssl->need_bytes > RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET)
{
printf("ssl->need_bytes=%d violates spec\r\n", ssl->need_bytes, RT_MAX_PLAIN_LENGTH+RT_EXTRA-BM_RECORD_OFFSET);
ret = SSL_ERROR_INVALID_PROT_MSG;
ret = SSL_ERROR_RECORD_OVERFLOW;
goto error;
}
@ -1326,8 +1360,7 @@ int basic_read(SSL *ssl, uint8_t **in_data)
{
ssl->cipher_info->decrypt(ssl->decrypt_ctx, buf, buf, read_len);
if (ssl->version >= SSL_PROTOCOL_VERSION1_1 &&
ssl->cipher_info->iv_size)
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1)
{
buf += ssl->cipher_info->iv_size;
read_len -= ssl->cipher_info->iv_size;
@ -1516,7 +1549,7 @@ int send_change_cipher_spec(SSL *ssl)
*/
int send_finished(SSL *ssl)
{
uint8_t buf[SSL_FINISHED_HASH_SIZE+4] = {
uint8_t buf[SHA1_SIZE+MD5_SIZE+15+4] = {
HS_FINISHED, 0, 0, SSL_FINISHED_HASH_SIZE };
/* now add the finished digest mac (12 bytes) */
@ -1547,7 +1580,7 @@ int send_alert(SSL *ssl, int error_code)
int is_warning = 0;
uint8_t buf[2];
/* Don't bother we're already dead */
/* Don't bother, we're already dead */
if (ssl->hs_status == SSL_ERROR_DEAD)
{
return SSL_ERROR_CONN_LOST;
@ -1569,38 +1602,60 @@ int send_alert(SSL *ssl, int error_code)
is_warning = 1;
break;
case SSL_ERROR_INVALID_HANDSHAKE:
case SSL_ERROR_INVALID_PROT_MSG:
case SSL_ERROR_NO_CIPHER:
alert_num = SSL_ALERT_HANDSHAKE_FAILURE;
break;
case SSL_ERROR_INVALID_HMAC:
case SSL_ERROR_FINISHED_INVALID:
alert_num = SSL_ALERT_BAD_RECORD_MAC;
break;
case SSL_ERROR_FINISHED_INVALID:
case SSL_ERROR_INVALID_KEY:
alert_num = SSL_ALERT_DECRYPT_ERROR;
break;
case SSL_ERROR_INVALID_VERSION:
alert_num = SSL_ALERT_INVALID_VERSION;
break;
case SSL_ERROR_INVALID_SESSION:
case SSL_ERROR_NO_CIPHER:
case SSL_ERROR_INVALID_KEY:
alert_num = SSL_ALERT_ILLEGAL_PARAMETER;
break;
case SSL_ERROR_BAD_CERTIFICATE:
alert_num = SSL_ALERT_BAD_CERTIFICATE;
break;
case SSL_ERROR_NO_CLIENT_RENOG:
alert_num = SSL_ALERT_NO_RENEGOTIATION;
break;
case SSL_ERROR_RECORD_OVERFLOW:
alert_num = SSL_ALERT_RECORD_OVERFLOW;
break;
case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
alert_num = SSL_ALERT_CERTIFICATE_EXPIRED;
break;
case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
alert_num = SSL_ALERT_UNKNOWN_CA;
break;
case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
case SSL_ERROR_INVALID_CERT_HASH_ALG:
alert_num = SSL_ALERT_UNSUPPORTED_CERTIFICATE;
break;
case SSL_ERROR_BAD_CERTIFICATE:
case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
alert_num = SSL_ALERT_BAD_CERTIFICATE;
break;
case SSL_ERROR_INVALID_HANDSHAKE:
case SSL_ERROR_INVALID_PROT_MSG:
default:
/* a catch-all for any badly verified certificates */
/* a catch-all for anything bad */
alert_num = (error_code <= SSL_X509_OFFSET) ?
SSL_ALERT_BAD_CERTIFICATE : SSL_ALERT_UNEXPECTED_MESSAGE;
SSL_ALERT_CERTIFICATE_UNKNOWN: SSL_ALERT_UNEXPECTED_MESSAGE;
break;
}
@ -1645,6 +1700,7 @@ error:
*/
int send_certificate(SSL *ssl)
{
int ret = SSL_OK;
int i = 0;
uint8_t *buf = ssl->bm_data;
int offset = 7;
@ -1654,6 +1710,14 @@ int send_certificate(SSL *ssl)
buf[1] = 0;
buf[4] = 0;
/* spec says we must check if the hash/sig algorithm is OK */
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2 &&
((ret = check_certificate_chain(ssl)) != SSL_OK))
{
ret = SSL_ERROR_INVALID_CERT_HASH_ALG;
goto error;
}
while (i < ssl->ssl_ctx->chain_length)
{
SSL_CERT *cert = &ssl->ssl_ctx->certs[i];
@ -1672,7 +1736,10 @@ int send_certificate(SSL *ssl)
buf[2] = chain_length >> 8; /* handshake length */
buf[3] = chain_length & 0xff;
ssl->bm_index = offset;
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
error:
return ret;
}
/**
@ -1684,6 +1751,7 @@ void disposable_new(SSL *ssl)
if (ssl->dc == NULL)
{
ssl->dc = (DISPOSABLE_CTX *)calloc(1, sizeof(DISPOSABLE_CTX));
SHA256_Init(&ssl->dc->sha256_ctx);
MD5_Init(&ssl->dc->md5_ctx);
SHA1_Init(&ssl->dc->sha1_ctx);
}
@ -1696,7 +1764,6 @@ void disposable_free(SSL *ssl)
{
if (ssl->dc)
{
free(ssl->dc->key_block);
memset(ssl->dc, 0, sizeof(DISPOSABLE_CTX));
free(ssl->dc);
ssl->dc = NULL;
@ -1891,6 +1958,43 @@ EXP_FUNC int STDCALL ssl_get_config(int offset)
}
}
/**
* Check the certificate chain to see if the certs are supported
*/
static int check_certificate_chain(SSL *ssl)
{
int i = 0;
int ret = SSL_OK;
while (i < ssl->ssl_ctx->chain_length)
{
int j = 0;
uint8_t found = 0;
SSL_CERT *cert = &ssl->ssl_ctx->certs[i];
while (j < ssl->num_sig_algs)
{
if (ssl->sig_algs[j++] == cert->hash_alg)
{
found = 1;
break;
}
}
if (!found)
{
ret = SSL_ERROR_INVALID_CERT_HASH_ALG;
goto error;
}
i++;
}
error:
return ret;
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
/**
* Authenticate a received certificate.
@ -1918,32 +2022,97 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
int ret = SSL_OK;
uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
int pkt_size = ssl->bm_index;
int cert_size, offset = 5;
int total_cert_size = (buf[offset]<<8) + buf[offset+1];
int cert_size, offset = 5, offset_start;
int total_cert_len = (buf[offset]<<8) + buf[offset+1];
int is_client = IS_SET_SSL_FLAG(SSL_IS_CLIENT);
X509_CTX **chain = x509_ctx;
X509_CTX *chain = 0;
X509_CTX **certs = 0;
int *cert_used = 0;
int num_certs = 0;
int i = 0;
offset += 2;
PARANOIA_CHECK(total_cert_size, offset);
PARANOIA_CHECK(pkt_size, total_cert_len + offset);
while (offset < total_cert_size)
// record the start point for the second pass
offset_start = offset;
// first pass - count the certificates
while (offset < total_cert_len)
{
offset++; /* skip empty char */
cert_size = (buf[offset]<<8) + buf[offset+1];
offset += 2;
offset += cert_size;
num_certs++;
}
PARANOIA_CHECK(pkt_size, offset);
certs = (X509_CTX**) calloc(num_certs, sizeof(void*));
cert_used = (int*) calloc(num_certs, sizeof(int));
num_certs = 0;
// restore the offset from the saved value
offset = offset_start;
// second pass - load the certificates
while (offset < total_cert_len)
{
offset++; /* skip empty char */
cert_size = (buf[offset]<<8) + buf[offset+1];
offset += 2;
if (x509_new(&buf[offset], NULL, chain))
if (x509_new(&buf[offset], NULL, certs+num_certs))
{
ret = SSL_ERROR_BAD_CERTIFICATE;
goto error;
}
chain = &((*chain)->next);
num_certs++;
offset += cert_size;
}
PARANOIA_CHECK(pkt_size, offset);
// third pass - link certs together, assume server cert is the first
*x509_ctx = certs[0];
chain = certs[0];
cert_used[0] = 1;
// repeat until the end of the chain is found
while (1)
{
// look for CA cert
for( i = 1; i < num_certs; i++ )
{
if (certs[i] == chain)
continue;
if (cert_used[i])
continue; // don't allow loops
if (asn1_compare_dn(chain->ca_cert_dn, certs[i]->cert_dn) == 0)
{
// CA cert found, add it to the chain
cert_used[i] = 1;
chain->next = certs[i];
chain = certs[i];
break;
}
}
// no CA cert found, reached the end of the chain
if (i >= num_certs)
break;
}
// clean up any certs that aren't part of the chain
for (i = 1; i < num_certs; i++)
{
if (cert_used[i] == 0)
x509_free(certs[i]);
}
/* if we are client we can do the verify now or later */
if (is_client && !IS_SET_SSL_FLAG(SSL_SERVER_VERIFY_LATER))
{
@ -1953,6 +2122,13 @@ int process_certificate(SSL *ssl, X509_CTX **x509_ctx)
ssl->next_state = is_client ? HS_SERVER_HELLO_DONE : HS_CLIENT_KEY_XCHG;
ssl->dc->bm_proc_index += offset;
error:
// clean up arrays
if (certs)
free(certs);
if (cert_used)
free(cert_used);
return ret;
}
@ -2043,7 +2219,6 @@ void DISPLAY_STATE(SSL *ssl, int is_send, uint8_t state, int not_ok)
}
printf("%s\n", str);
TTY_FLUSH();
}
/**
@ -2105,6 +2280,10 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code)
printf("connection dead");
break;
case SSL_ERROR_RECORD_OVERFLOW:
printf("record overflow");
break;
case SSL_ERROR_INVALID_HANDSHAKE:
printf("invalid handshake");
break;
@ -2129,6 +2308,10 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code)
printf("no cipher");
break;
case SSL_ERROR_INVALID_CERT_HASH_ALG:
printf("invalid cert hash algorithm");
break;
case SSL_ERROR_CONN_LOST:
printf("connection lost");
break;
@ -2163,9 +2346,12 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code)
}
printf("\n");
TTY_FLUSH();
}
/**
* Debugging routine to display alerts.
*/
/**
* Debugging routine to display alerts.
*/
@ -2182,14 +2368,6 @@ void DISPLAY_ALERT(SSL *ssl, int alert)
printf("close notify");
break;
case SSL_ALERT_INVALID_VERSION:
printf("invalid version");
break;
case SSL_ALERT_BAD_CERTIFICATE:
printf("bad certificate");
break;
case SSL_ALERT_UNEXPECTED_MESSAGE:
printf("unexpected message");
break;
@ -2198,14 +2376,38 @@ void DISPLAY_ALERT(SSL *ssl, int alert)
printf("bad record mac");
break;
case SSL_ERROR_RECORD_OVERFLOW:
printf("record overlow");
break;
case SSL_ALERT_HANDSHAKE_FAILURE:
printf("handshake failure");
break;
case SSL_ALERT_BAD_CERTIFICATE:
printf("bad certificate");
break;
case SSL_ALERT_UNSUPPORTED_CERTIFICATE:
printf("unsupported certificate");
break;
case SSL_ALERT_CERTIFICATE_EXPIRED:
printf("certificate expired");
break;
case SSL_ALERT_CERTIFICATE_UNKNOWN:
printf("certificate unknown");
break;
case SSL_ALERT_ILLEGAL_PARAMETER:
printf("illegal parameter");
break;
case SSL_ALERT_UNKNOWN_CA:
printf("unknown ca");
break;
case SSL_ALERT_DECODE_ERROR:
printf("decode error");
break;
@ -2214,6 +2416,10 @@ void DISPLAY_ALERT(SSL *ssl, int alert)
printf("decrypt error");
break;
case SSL_ALERT_INVALID_VERSION:
printf("invalid version");
break;
case SSL_ALERT_NO_RENEGOTIATION:
printf("no renegotiation");
break;
@ -2224,7 +2430,6 @@ void DISPLAY_ALERT(SSL *ssl, int alert)
}
printf("\n");
TTY_FLUSH();
}
#endif /* CONFIG_SSL_FULL_MODE */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007-2014, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -43,13 +43,14 @@ extern "C" {
#include "version.h"
#include "config.h"
#include "os_int.h"
#include "os_port.h"
#include "crypto.h"
#include "crypto_misc.h"
#define SSL_PROTOCOL_MIN_VERSION 0x31 /* TLS v1.0 */
#define SSL_PROTOCOL_MINOR_VERSION 0x02 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_MAX 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION1_1 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_MAX 0x33 /* TLS v1.3 */
#define SSL_PROTOCOL_VERSION_TLS1_1 0x32 /* TLS v1.1 */
#define SSL_PROTOCOL_VERSION_TLS1_2 0x33 /* TLS v1.2 */
#define SSL_RANDOM_SIZE 32
#define SSL_SECRET_SIZE 48
#define SSL_FINISHED_HASH_SIZE 12
@ -79,11 +80,15 @@ extern "C" {
#define RT_EXTRA 1024
#define BM_RECORD_OFFSET 5
#ifdef CONFIG_SSL_SKELETON_MODE
#define NUM_PROTOCOLS 1
#else
#define NUM_PROTOCOLS 2
#endif
#define NUM_PROTOCOLS 4
#define MAX_SIG_ALGORITHMS 4
#define SIG_ALG_EXTENSION 0x0d
#define SIG_ALG_SHA1 2
#define SIG_ALG_SHA256 4
#define SIG_ALG_SHA384 5
#define SIG_ALG_SHA512 6
#define SIG_ALG_RSA 1
#define PARANOIA_CHECK(A, B) if (A < B) { \
ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
@ -117,9 +122,9 @@ typedef struct
uint8_t cipher;
uint8_t key_size;
uint8_t iv_size;
uint8_t key_block_size;
uint8_t padding_size;
uint8_t digest_size;
uint8_t key_block_size;
hmac_func hmac;
crypt_func encrypt;
crypt_func decrypt;
@ -144,18 +149,21 @@ typedef struct
{
uint8_t *buf;
int size;
uint8_t hash_alg;
} SSL_CERT;
typedef struct
{
MD5_CTX md5_ctx;
SHA1_CTX sha1_ctx;
uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
uint8_t *key_block;
uint8_t master_secret[SSL_SECRET_SIZE];
SHA256_CTX sha256_ctx;
uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
uint8_t final_finish_mac[128];
uint8_t master_secret[SSL_SECRET_SIZE];
uint8_t key_block[256];
uint16_t bm_proc_index;
uint8_t key_block_generated;
} DISPOSABLE_CTX;
struct _SSL
@ -180,6 +188,8 @@ struct _SSL
uint16_t bm_index;
uint16_t bm_read_index;
size_t max_plain_length;
uint8_t sig_algs[MAX_SIG_ALGORITHMS];
uint8_t num_sig_algs;
struct _SSL *next; /* doubly linked list */
struct _SSL *prev;
struct _SSL_CTX *ssl_ctx; /* back reference to a clnt/svr ctx */
@ -192,8 +202,8 @@ struct _SSL
bool can_free_certificates;
#endif
uint8_t session_id[SSL_SESSION_ID_SIZE];
uint8_t client_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA1_SIZE]; /* for HMAC verification */
uint8_t client_mac[SHA256_SIZE]; /* for HMAC verification */
uint8_t server_mac[SHA256_SIZE]; /* for HMAC verification */
uint8_t read_sequence[8]; /* 64 bit sequence number */
uint8_t write_sequence[8]; /* 64 bit sequence number */
uint8_t hmac_header[SSL_RECORD_SIZE]; /* rx hmac */
@ -246,7 +256,7 @@ int send_finished(SSL *ssl);
int send_certificate(SSL *ssl);
int basic_read(SSL *ssl, uint8_t **in_data);
int send_change_cipher_spec(SSL *ssl);
void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
int finished_digest(SSL *ssl, const char *label, uint8_t *digest);
void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
void add_packet(SSL *ssl, const uint8_t *pkt, int len);
int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -37,6 +37,23 @@
#ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */
/* support sha512/384/256/1 RSA */
static const uint8_t g_sig_alg[] = {
0x00, 0x0e,
0x00, SIG_ALG_EXTENSION,
0x00, 0x0a, 0x00, 0x08,
SIG_ALG_SHA512, SIG_ALG_RSA,
SIG_ALG_SHA384, SIG_ALG_RSA,
SIG_ALG_SHA256, SIG_ALG_RSA,
SIG_ALG_SHA1, SIG_ALG_RSA
};
static const uint8_t g_asn1_sha256[] =
{
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
};
static int send_client_hello(SSL *ssl);
static int process_server_hello(SSL *ssl);
static int process_server_hello_done(SSL *ssl);
@ -227,27 +244,14 @@ static int send_client_hello(SSL *ssl)
buf[offset++] = 1; /* no compression */
buf[offset++] = 0;
if (ssl->host_name != NULL) {
unsigned int host_len = strlen(ssl->host_name);
buf[offset++] = 0;
buf[offset++] = host_len+9; /* extensions length */
buf[offset++] = 0;
buf[offset++] = 0; /* server_name(0) (65535) */
buf[offset++] = 0;
buf[offset++] = host_len+5; /* server_name length */
buf[offset++] = 0;
buf[offset++] = host_len+3; /* server_list length */
buf[offset++] = 0; /* host_name(0) (255) */
buf[offset++] = 0;
buf[offset++] = host_len; /* host_name length */
strncpy((char*) &buf[offset], ssl->host_name, host_len);
offset += host_len;
/* send the signature algorithm extension for TLS 1.2+ */
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2)
{
memcpy(&buf[offset], g_sig_alg, sizeof(g_sig_alg));
offset += sizeof(g_sig_alg);
}
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
@ -306,15 +310,18 @@ static int process_server_hello(SSL *ssl)
ssl->sess_id_size = sess_id_size;
offset += sess_id_size;
/* get the real cipher we are using */
/* get the real cipher we are using - ignore MSB */
ssl->cipher = buf[++offset];
ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
HS_FINISHED : HS_CERTIFICATE;
offset++; // skip the compr
offset += 2; // ignore compression
PARANOIA_CHECK(pkt_size, offset);
ssl->dc->bm_proc_index = offset+1;
ssl->dc->bm_proc_index = offset+1;
PARANOIA_CHECK(pkt_size, offset);
// no extensions
error:
return ret;
}
@ -340,8 +347,10 @@ static int send_client_key_xchg(SSL *ssl)
buf[0] = HS_CLIENT_KEY_XCHG;
buf[1] = 0;
premaster_secret[0] = 0x03; /* encode the version number */
premaster_secret[1] = SSL_PROTOCOL_MINOR_VERSION; /* must be TLS 1.1 */
// spec says client must use the what is initially negotiated -
// and this is our current version
premaster_secret[0] = 0x03;
premaster_secret[1] = SSL_PROTOCOL_VERSION_MAX & 0x0f;
if (get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]) < 0)
return SSL_NOT_OK;
@ -369,14 +378,47 @@ static int process_cert_req(SSL *ssl)
{
uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
int ret = SSL_OK;
int offset = (buf[2] << 4) + buf[3];
int cert_req_size = (buf[2]<<8) + buf[3];
int offset = 4;
int pkt_size = ssl->bm_index;
uint8_t cert_type_len, sig_alg_len;
PARANOIA_CHECK(pkt_size, offset + cert_req_size);
ssl->dc->bm_proc_index = cert_req_size;
/* don't do any processing - we will send back an RSA certificate anyway */
ssl->next_state = HS_SERVER_HELLO_DONE;
SET_SSL_FLAG(SSL_HAS_CERT_REQ);
ssl->dc->bm_proc_index += offset;
PARANOIA_CHECK(pkt_size, offset);
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
// supported certificate types
cert_type_len = buf[offset++];
PARANOIA_CHECK(pkt_size, offset + cert_type_len);
offset += cert_type_len;
// supported signature algorithms
sig_alg_len = buf[offset++] << 8;
sig_alg_len += buf[offset++];
PARANOIA_CHECK(pkt_size, offset + sig_alg_len);
while (sig_alg_len > 0)
{
uint8_t hash_alg = buf[offset++];
uint8_t sig_alg = buf[offset++];
sig_alg_len -= 2;
if (sig_alg == SIG_ALG_RSA &&
(hash_alg == SIG_ALG_SHA1 ||
hash_alg == SIG_ALG_SHA256 ||
hash_alg == SIG_ALG_SHA384 ||
hash_alg == SIG_ALG_SHA512))
{
ssl->sig_algs[ssl->num_sig_algs++] = hash_alg;
}
}
}
error:
return ret;
}
@ -387,9 +429,11 @@ error:
static int send_cert_verify(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
uint8_t dgst[MD5_SIZE+SHA1_SIZE];
uint8_t dgst[SHA1_SIZE+MD5_SIZE+15];
RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
int n = 0, ret;
int offset = 0;
int dgst_len;
if (rsa_ctx == NULL)
return SSL_OK;
@ -399,13 +443,26 @@ static int send_cert_verify(SSL *ssl)
buf[0] = HS_CERT_VERIFY;
buf[1] = 0;
finished_digest(ssl, NULL, dgst); /* calculate the digest */
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
buf[4] = SIG_ALG_SHA256;
buf[5] = SIG_ALG_RSA;
offset = 6;
memcpy(dgst, g_asn1_sha256, sizeof(g_asn1_sha256));
dgst_len = finished_digest(ssl, NULL, &dgst[sizeof(g_asn1_sha256)]) +
sizeof(g_asn1_sha256);
}
else
{
offset = 4;
dgst_len = finished_digest(ssl, NULL, dgst);
}
/* rsa_ctx->bi_ctx is not thread-safe */
if (rsa_ctx)
{
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
n = RSA_encrypt(rsa_ctx, dgst, dgst_len, &buf[offset + 2], 1);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (n == 0)
@ -415,12 +472,19 @@ static int send_cert_verify(SSL *ssl)
}
}
buf[4] = n >> 8; /* add the RSA size (not officially documented) */
buf[5] = n & 0xff;
buf[offset] = n >> 8; /* add the RSA size */
buf[offset+1] = n & 0xff;
n += 2;
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
n += 2; // sig/alg
offset -= 2;
}
buf[2] = n >> 8;
buf[3] = n & 0xff;
ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);
ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n + offset);
error:
return ret;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, Cameron Rich
* Copyright (c) 2007-2016, Cameron Rich
*
* All rights reserved.
*
@ -35,6 +35,11 @@
#include "ssl.h"
static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
static const uint8_t g_asn1_sha256[] =
{
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
};
static int process_client_hello(SSL *ssl);
static int send_server_hello_sequence(SSL *ssl);
@ -154,7 +159,7 @@ static int process_client_hello(SSL *ssl)
cs_len = (buf[offset]<<8) + buf[offset+1];
offset += 3; /* add 1 due to all cipher suites being 8 bit */
PARANOIA_CHECK(pkt_size, offset);
PARANOIA_CHECK(pkt_size, offset + cs_len);
/* work out what cipher suite we are going to use - client defines
the preference */
@ -165,89 +170,75 @@ static int process_client_hello(SSL *ssl)
if (ssl_prot_prefs[j] == buf[offset+i]) /* got a match? */
{
ssl->cipher = ssl_prot_prefs[j];
goto do_state;
goto do_compression;
}
}
}
/* ouch! protocol is not supported */
ret = SSL_ERROR_NO_CIPHER;
return SSL_ERROR_NO_CIPHER;
do_state:
error:
return ret;
}
#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
/*
* Some browsers use a hybrid SSLv2 "client hello"
*/
int process_sslv23_client_hello(SSL *ssl)
{
uint8_t *buf = ssl->bm_data;
int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
int ret = SSL_OK;
/* we have already read 3 extra bytes so far */
int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
int cs_len = buf[1];
int id_len = buf[3];
int ch_len = buf[5];
int i, j, offset = 8; /* start at first cipher */
int random_offset = 0;
DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
/* connection has gone, so die */
if (read_len < 0)
{
return SSL_ERROR_CONN_LOST;
}
add_packet(ssl, buf, read_len);
/* now work out what cipher suite we are going to use */
for (j = 0; j < NUM_PROTOCOLS; j++)
{
for (i = 0; i < cs_len; i += 3)
{
if (ssl_prot_prefs[j] == buf[offset+i])
{
ssl->cipher = ssl_prot_prefs[j];
goto server_hello;
}
}
}
/* ouch! protocol is not supported */
ret = SSL_ERROR_NO_CIPHER;
goto error;
server_hello:
/* get the session id */
offset += cs_len - 2; /* we've gone 2 bytes past the end */
#ifndef CONFIG_SSL_SKELETON_MODE
ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
#endif
/* get the client random data */
/* completely ignore compression */
do_compression:
offset += cs_len;
id_len = buf[offset++];
offset += id_len;
PARANOIA_CHECK(pkt_size, offset + id_len);
/* random can be anywhere between 16 and 32 bytes long - so it is padded
* with 0's to the left */
if (ch_len == 0x10)
if (offset == pkt_size)
{
random_offset += 0x10;
/* no extensions */
goto error;
}
memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
ret = send_server_hello_sequence(ssl);
/* extension size */
id_len = buf[offset++] << 8;
id_len += buf[offset++];
PARANOIA_CHECK(pkt_size, offset + id_len);
// Check for extensions from the client - only the signature algorithm
// is supported
while (offset < pkt_size)
{
int ext = buf[offset++] << 8;
ext += buf[offset++];
int ext_len = buf[offset++] << 8;
ext_len += buf[offset++];
PARANOIA_CHECK(pkt_size, offset + ext_len);
if (ext == SIG_ALG_EXTENSION)
{
while (ext_len > 0)
{
uint8_t hash_alg = buf[offset++];
uint8_t sig_alg = buf[offset++];
ext_len -= 2;
if (sig_alg == SIG_ALG_RSA &&
(hash_alg == SIG_ALG_SHA1 ||
hash_alg == SIG_ALG_SHA256 ||
hash_alg == SIG_ALG_SHA384 ||
hash_alg == SIG_ALG_SHA512))
{
ssl->sig_algs[ssl->num_sig_algs++] = hash_alg;
}
}
}
else
{
offset += ext_len;
}
}
/* default is RSA/SHA1 */
if (ssl->num_sig_algs == 0)
{
ssl->sig_algs[ssl->num_sig_algs++] = SIG_ALG_SHA1;
}
error:
return ret;
}
#endif
/*
* Send the entire server hello sequence
@ -350,7 +341,7 @@ static int send_server_hello(SSL *ssl)
buf[offset++] = 0; /* cipher we are using */
buf[offset++] = ssl->cipher;
buf[offset++] = 0; /* no compression */
buf[offset++] = 0; /* no compression and no extensions supported */
buf[3] = offset - 4; /* handshake size */
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
}
@ -409,10 +400,6 @@ static int process_client_key_xchg(SSL *ssl)
/* and continue - will die eventually when checking the mac */
}
#if 0
print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
#endif
generate_master_secret(ssl, premaster_secret);
#ifdef CONFIG_SSL_CERT_VERIFICATION
@ -428,16 +415,35 @@ error:
}
#ifdef CONFIG_SSL_CERT_VERIFICATION
static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0,
0, 0x0e,
1, 1, // rsa sign
0x00, 0x08,
SIG_ALG_SHA256, SIG_ALG_RSA,
SIG_ALG_SHA512, SIG_ALG_RSA,
SIG_ALG_SHA384, SIG_ALG_RSA,
SIG_ALG_SHA1, SIG_ALG_RSA,
0, 0
};
static const uint8_t g_cert_request_v1[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
/*
* Send the certificate request message.
*/
static int send_certificate_request(SSL *ssl)
{
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
g_cert_request, sizeof(g_cert_request));
}
else
{
return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
g_cert_request_v1, sizeof(g_cert_request_v1));
}
}
/*
* Ensure the client has the private key by first decrypting the packet and
@ -451,16 +457,51 @@ static int process_cert_verify(SSL *ssl)
uint8_t dgst[MD5_SIZE + SHA1_SIZE];
X509_CTX *x509_ctx = ssl->x509_ctx;
int ret = SSL_OK;
int offset = 6;
int rsa_len;
int n;
PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
// TODO: should really need to be able to handle other algorihms. An
// assumption is made on RSA/SHA256 and appears to be OK.
//uint8_t hash_alg = buf[4];
//uint8_t sig_alg = buf[5];
offset = 8;
rsa_len = (buf[6] << 8) + buf[7];
}
else
{
rsa_len = (buf[4] << 8) + buf[5];
}
PARANOIA_CHECK(pkt_size, offset + rsa_len);
/* rsa_ctx->bi_ctx is not thread-safe */
SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, sizeof(dgst_buf), 0);
n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[offset], dgst_buf,
sizeof(dgst_buf), 0);
SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
{
if (memcmp(dgst_buf, g_asn1_sha256, sizeof(g_asn1_sha256)))
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
finished_digest(ssl, NULL, dgst); /* calculate the digest */
if (memcmp(&dgst_buf[sizeof(g_asn1_sha256)], dgst, SHA256_SIZE))
{
ret = SSL_ERROR_INVALID_KEY;
goto error;
}
}
else // TLS1.0/1.1
{
if (n != SHA1_SIZE + MD5_SIZE)
{
ret = SSL_ERROR_INVALID_KEY;
@ -472,6 +513,7 @@ static int process_cert_verify(SSL *ssl)
{
ret = SSL_ERROR_INVALID_KEY;
}
}
end_cert_vfy:
ssl->next_state = HS_FINISHED;

View File

@ -74,7 +74,9 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
int begin_tbs, end_tbs;
int ret = X509_NOT_OK, offset = 0, cert_size = 0;
X509_CTX *x509_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
BI_CTX *bi_ctx;
#endif
*ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
x509_ctx = *ctx;
@ -117,7 +119,6 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
goto end_cert;
}
bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
x509_ctx->fingerprint = malloc(SHA1_SIZE);
SHA1_CTX sha_fp_ctx;
@ -126,6 +127,8 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx);
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
/* use the appropriate signature algorithm */
switch (x509_ctx->sig_type)
{
@ -524,9 +527,6 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
printf("Sig Type:\t\t\t");
switch (cert->sig_type)
{
case SIG_TYPE_MD2:
printf("MD2\n");
break;
case SIG_TYPE_MD5:
printf("MD5\n");
break;

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# Copyright (c) 2007, Cameron Rich
# Copyright (c) 2007-2016, Cameron Rich
#
# All rights reserved.
#
@ -56,7 +56,7 @@ prompt = no
[ req_distinguished_name ]
O = $PROJECT_NAME
CN = 127.0.0.1
CN = localhost
EOF
cat > device_cert.conf << EOF
@ -69,21 +69,16 @@ prompt = no
EOF
# private key generation
openssl genrsa -out axTLS.ca_key.pem 1024
openssl genrsa -out axTLS.key_512.pem 512
openssl genrsa -out axTLS.ca_key.pem 2048
openssl genrsa -out axTLS.key_1024.pem 1024
openssl genrsa -out axTLS.key_1042.pem 1042
openssl genrsa -out axTLS.key_2048.pem 2048
openssl genrsa -out axTLS.key_4096.pem 4096
openssl genrsa -out axTLS.device_key.pem 1024
openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 512
openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 512
openssl genrsa -aes128 -passout pass:abcd -out axTLS.key_aes128.pem 1024
openssl genrsa -aes256 -passout pass:abcd -out axTLS.key_aes256.pem 1024
# convert private keys into DER format
openssl rsa -in axTLS.key_512.pem -out axTLS.key_512 -outform DER
openssl rsa -in axTLS.key_1024.pem -out axTLS.key_1024 -outform DER
openssl rsa -in axTLS.key_1042.pem -out axTLS.key_1042 -outform DER
openssl rsa -in axTLS.key_2048.pem -out axTLS.key_2048 -outform DER
openssl rsa -in axTLS.key_4096.pem -out axTLS.key_4096 -outform DER
openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER
@ -91,12 +86,8 @@ openssl rsa -in axTLS.device_key.pem -out axTLS.device_key -outform DER
# cert requests
openssl req -out axTLS.ca_x509.req -key axTLS.ca_key.pem -new \
-config ./ca_cert.conf
openssl req -out axTLS.x509_512.req -key axTLS.key_512.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_1024.req -key axTLS.key_1024.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_1042.req -key axTLS.key_1042.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_2048.req -key axTLS.key_2048.pem -new \
-config ./certs.conf
openssl req -out axTLS.x509_4096.req -key axTLS.key_4096.pem -new \
@ -110,25 +101,32 @@ openssl req -out axTLS.x509_aes256.req -key axTLS.key_aes256.pem \
# generate the actual certs.
openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509.pem \
-sha1 -days 5000 -signkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_512.pem \
-sha1 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
-sha1 -days 5000 -signkey axTLS.ca_key.pem \
-CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.ca_x509.req -out axTLS.ca_x509_sha256.pem \
-sha256 -days 5000 -signkey axTLS.ca_key.pem \
-CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024.pem \
-sha1 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_1042.req -out axTLS.x509_1042.pem \
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024_sha256.pem \
-sha256 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509_sha256.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024_sha384.pem \
-sha384 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509_sha256.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_1024_sha512.pem \
-sha512 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509_sha256.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \
-sha1 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_2048.req -out axTLS.x509_2048.pem \
-md5 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_4096.req -out axTLS.x509_4096.pem \
-md5 -CAcreateserial -days 5000 \
-sha1 -CAcreateserial -days 5000 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
openssl x509 -req -in axTLS.x509_device.req -out axTLS.x509_device.pem \
-sha1 -CAcreateserial -days 5000 \
-CA axTLS.x509_512.pem -CAkey axTLS.key_512.pem
-CA axTLS.x509_1024.pem -CAkey axTLS.key_1024.pem
openssl x509 -req -in axTLS.x509_aes128.req \
-out axTLS.x509_aes128.pem \
-sha1 -CAcreateserial -days 5000 \
@ -141,35 +139,33 @@ openssl x509 -req -in axTLS.x509_aes256.req \
# note: must be root to do this
DATE_NOW=`date`
if date -s "Jan 1 2025"; then
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_before.pem \
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_bad_before.pem \
-sha1 -CAcreateserial -days 365 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
date -s "$DATE_NOW"
touch axTLS.x509_bad_before.pem
fi
openssl x509 -req -in axTLS.x509_512.req -out axTLS.x509_bad_after.pem \
openssl x509 -req -in axTLS.x509_1024.req -out axTLS.x509_bad_after.pem \
-sha1 -CAcreateserial -days -365 \
-CA axTLS.ca_x509.pem -CAkey axTLS.ca_key.pem
# some cleanup
rm axTLS*.req
rm axTLS.srl
rm *.srl
rm *.conf
# need this for the client tests
openssl x509 -in axTLS.ca_x509.pem -outform DER -out axTLS.ca_x509.cer
openssl x509 -in axTLS.x509_512.pem -outform DER -out axTLS.x509_512.cer
openssl x509 -in axTLS.x509_1024.pem -outform DER -out axTLS.x509_1024.cer
openssl x509 -in axTLS.x509_1042.pem -outform DER -out axTLS.x509_1042.cer
openssl x509 -in axTLS.x509_2048.pem -outform DER -out axTLS.x509_2048.cer
openssl x509 -in axTLS.x509_4096.pem -outform DER -out axTLS.x509_4096.cer
openssl x509 -in axTLS.x509_device.pem -outform DER -out axTLS.x509_device.cer
# generate pkcs8 files (use RC4-128 for encryption)
openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
openssl pkcs8 -in axTLS.key_512.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8
openssl pkcs8 -in axTLS.key_512.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8
openssl pkcs8 -in axTLS.key_1024.pem -passout pass:abcd -topk8 -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted_pem.p8
openssl pkcs8 -in axTLS.key_1024.pem -passout pass:abcd -topk8 -outform DER -v1 PBE-SHA1-RC4-128 -out axTLS.encrypted.p8
openssl pkcs8 -in axTLS.key_1024.pem -nocrypt -topk8 -out axTLS.unencrypted_pem.p8
openssl pkcs8 -in axTLS.key_1024.pem -nocrypt -topk8 -outform DER -out axTLS.unencrypted.p8
# generate pkcs12 files (use RC4-128 for encryption)
openssl pkcs12 -export -in axTLS.x509_1024.pem -inkey axTLS.key_1024.pem -certfile axTLS.ca_x509.pem -keypbe PBE-SHA1-RC4-128 -certpbe PBE-SHA1-RC4-128 -name "p12_with_CA" -out axTLS.withCA.p12 -password pass:abcd