diff --git a/crypto/crypto.h b/crypto/crypto.h index fcf32c703..9914afeec 100644 --- a/crypto/crypto.h +++ b/crypto/crypto.h @@ -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 diff --git a/crypto/hmac.c b/crypto/hmac.c index 24a04d77a..e618ee2eb 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -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); +} + diff --git a/ssl/ssl.h b/ssl/ssl.h index 36d56fd19..064a00896 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -97,6 +97,7 @@ extern "C" { #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_BAD_CERTIFICATE -268 @@ -128,12 +129,13 @@ extern "C" { #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 diff --git a/ssl/tls1.c b/ssl/tls1.c index a3b06381b..eb38531f4 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -64,13 +64,14 @@ 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 /* same as medium for now */ -{ SSL_AES128_SHA, SSL_AES256_SHA }; +#ifdef CONFIG_SSL_PROT_LOW /* low security, fast speed */ +{ 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_SHA, SSL_AES128_SHA256, SSL_AES_256_SHA, SSL_AES128_SHA }; #endif + /** * The cipher map containing all the essentials for each cipher. */ @@ -80,9 +81,9 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] = 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 */ @@ -90,17 +91,40 @@ static const cipher_info_t cipher_info[NUM_PROTOCOLS] = { /* AES256-SHA */ SSL_AES256_SHA, /* AES256-SHA */ 32, /* key size */ - 16, /* iv size */ - 2*(SHA1_SIZE+32+16), /* key block size */ + 16, /* iv 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 */ + } }; -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); @@ -615,36 +639,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); - memcpy(t_buf, (mode == SSL_SERVER_WRITE || mode == SSL_CLIENT_WRITE) ? + 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); - } + 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->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); @@ -667,7 +674,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 } @@ -676,7 +683,7 @@ 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]; int hmac_offset; if (ssl->cipher_info->padding_size) @@ -731,8 +738,15 @@ static int verify_digest(SSL *ssl, int mode, const uint8_t *buf, int read_len) */ void add_packet(SSL *ssl, const uint8_t *pkt, int len) { - MD5_Update(&ssl->dc->md5_ctx, pkt, len); - SHA1_Update(&ssl->dc->sha1_ctx, pkt, len); + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2 + { + SHA256_Update(&ssl->dc->sha256_ctx, pkt, len); + } + else // TLS1.0/1.0 + { + MD5_Update(&ssl->dc->md5_ctx, pkt, len); + SHA1_Update(&ssl->dc->sha1_ctx, pkt, len); + } } /** @@ -791,27 +805,63 @@ 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[128]; + + /* 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) { - int len, i; - const uint8_t *S1, *S2; - uint8_t xbuf[256]; /* needs to be > the amount of key data */ - uint8_t ybuf[256]; /* needs to be > the amount of key data */ + 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; + uint8_t xbuf[256]; /* needs to be > the amount of key data */ + uint8_t ybuf[256]; /* needs to be > the amount of key data */ - len = sec_len/2; - S1 = sec; - S2 = &sec[len]; - len += (sec_len & 1); /* add for odd, make longer */ + len = sec_len/2; + S1 = sec; + S2 = &sec[len]; + len += (sec_len & 1); /* add for odd, make longer */ - p_hash_md5(S1, len, seed, seed_len, xbuf, olen); - p_hash_sha1(S2, len, seed, seed_len, ybuf, olen); + p_hash_md5(S1, len, seed, seed_len, xbuf, olen); + p_hash_sha1(S2, len, seed, seed_len, ybuf, olen); - for (i = 0; i < olen; i++) - out[i] = xbuf[i] ^ ybuf[i]; + for (i = 0; i < olen; i++) + out[i] = xbuf[i] ^ ybuf[i]; + } } /** @@ -821,24 +871,32 @@ 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 */ + //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]; 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); } /** @@ -849,8 +907,6 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) { uint8_t mac_buf[128]; uint8_t *q = mac_buf; - MD5_CTX md5_ctx = ssl->dc->md5_ctx; - SHA1_CTX sha1_ctx = ssl->dc->sha1_ctx; if (label) { @@ -858,25 +914,47 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) q += strlen(label); } - MD5_Final(q, &md5_ctx); - q += MD5_SIZE; - - SHA1_Final(q, &sha1_ctx); - q += SHA1_SIZE; + 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; - if (label) - { - prf(ssl->dc->master_secret, SSL_SECRET_SIZE, mac_buf, (int)(q-mac_buf), - digest, SSL_FINISHED_HASH_SIZE); + if (label) + { + prf(ssl, ssl->dc->master_secret, SSL_SECRET_SIZE, + mac_buf, (int)(q-mac_buf), digest, + SSL_FINISHED_HASH_SIZE); + } + else // for use in a certificate verify + { + memcpy(digest, mac_buf, SHA256_SIZE); + } } - else /* for use in a certificate verify */ + else // TLS1.0/1.1 { - memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE); + 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; + + if (label) + { + prf(ssl, ssl->dc->master_secret, SSL_SECRET_SIZE, + mac_buf, (int)(q-mac_buf), digest, SSL_FINISHED_HASH_SIZE); + } + else /* for use in a certificate verify */ + { + memcpy(digest, mac_buf, MD5_SIZE + SHA1_SIZE); + } } #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("finished digest", digest, SSL_FINISHED_HASH_SIZE); #endif @@ -890,6 +968,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void switch (ssl->cipher) { case SSL_AES128_SHA: + case SSL_AES128_SHA256: { AES_CTX *aes_ctx; if (cached) @@ -907,6 +986,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) @@ -923,6 +1003,7 @@ static void *crypt_new(SSL *ssl, uint8_t *key, uint8_t *iv, int is_decrypt, void return (void *)aes_ctx; } + } return NULL; /* its all gone wrong */ @@ -1058,7 +1139,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 && + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1 && ssl->cipher_info->iv_size) { uint8_t iv_size = ssl->cipher_info->iv_size; @@ -1109,16 +1190,14 @@ 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->bm_proc_index ==0 ) { - 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 @@ -1146,13 +1225,10 @@ static int set_key_block(SSL *ssl, int is_write) memcpy(server_key, q, ciph_info->key_size); q += ciph_info->key_size; - 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; - } + 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; // free(is_write ? ssl->encrypt_ctx : ssl->decrypt_ctx); @@ -1274,7 +1350,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 && + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_1 && ssl->cipher_info->iv_size) { buf += ssl->cipher_info->iv_size; @@ -1464,7 +1540,7 @@ int send_change_cipher_spec(SSL *ssl) */ int send_finished(SSL *ssl) { - uint8_t buf[SSL_FINISHED_HASH_SIZE+4] = { + uint8_t buf[128] = { HS_FINISHED, 0, 0, SSL_FINISHED_HASH_SIZE }; /* now add the finished digest mac (12 bytes) */ @@ -1653,6 +1729,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); } @@ -1665,7 +1742,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; diff --git a/ssl/tls1.h b/ssl/tls1.h index 624fe9dfd..516626cf8 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -48,9 +48,9 @@ extern "C" { #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.2 */ +#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 @@ -80,7 +80,8 @@ extern "C" { #define RT_EXTRA 1024 #define BM_RECORD_OFFSET 5 -#define NUM_PROTOCOLS 2 +#define NUM_PROTOCOLS 4 +#define SIG_ALG_EXTENSION 0x0d #define PARANOIA_CHECK(A, B) if (A < B) { \ ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; } @@ -114,9 +115,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; @@ -147,11 +148,12 @@ 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; } DISPOSABLE_CTX; @@ -189,10 +191,10 @@ 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 read_sequence[8]; /* 64 bit sequence number */ - uint8_t write_sequence[8]; /* 64 bit sequence number */ + 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 */ char *host_name; /* Needed for the SNI support */ }; diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 77f11780d..62b457a9e 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Cameron Rich + * Copyright (c) 2007-2016, Cameron Rich * * All rights reserved. * @@ -37,6 +37,11 @@ #ifdef CONFIG_SSL_ENABLE_CLIENT /* all commented out if no client */ +/* support sha512/384/256/224/1 rsa */ +static const uint8_t g_sig_alg[] = { 0x00, 0x10, + 0x00, SIG_ALG_EXTENSION, 0x00, 0x0c, 0x00, 0x0a, + 0x06, 0x01, 0x05, 0x01, 0x04, 0x01, 0x03, 0x01, 0x02, 0x01 }; + static int send_client_hello(SSL *ssl); static int process_server_hello(SSL *ssl); static int process_server_hello_done(SSL *ssl); @@ -227,23 +232,10 @@ 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; + if (ssl->version > SSL_PROTOCOL_VERSION_TLS1_1) + { + memcpy(&buf[offset], g_sig_alg, sizeof(g_sig_alg)); + offset += sizeof(g_sig_alg); } buf[3] = offset - 4; /* handshake size */ @@ -306,13 +298,46 @@ 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 PARANOIA_CHECK(pkt_size, offset); + + // Check for extensions from the server - only the signature algorithm + // is supported + if (pkt_size > offset) + { + if (buf[offset++] > 0) // MSB of extension len must be 0 + { + ret = SSL_ALERT_UNSUPPORTED_EXTENSION; + goto error; + } + + offset++; // ignore the extension size as we only look at one + + if (buf[offset++] == 0 && buf[offset++] == SIG_ALG_EXTENSION) + { + if (buf[offset++] != 0) // MSB of alg_sig_len must be 0 + { + ret = SSL_ALERT_UNSUPPORTED_EXTENSION; + goto error; + } + + int alg_sig_len = buf[offset++]; + offset += alg_sig_len; + PARANOIA_CHECK(pkt_size, offset); + // we don't use what comes back (for now) + } + else + { + ret = SSL_ALERT_UNSUPPORTED_EXTENSION; + goto error; + } + } + ssl->dc->bm_proc_index = offset+1; error: @@ -340,8 +365,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; diff --git a/ssl/tls1_svr.c b/ssl/tls1_svr.c index 9c0cec444..b67f88a74 100644 --- a/ssl/tls1_svr.c +++ b/ssl/tls1_svr.c @@ -279,7 +279,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); }