diff --git a/ssl/tls1.c b/ssl/tls1.c index eb38531f4..c23e36053 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -69,7 +69,7 @@ const uint8_t ssl_prot_prefs[NUM_PROTOCOLS] = #elif CONFIG_SSL_PROT_MEDIUM /* medium security, medium speed */ { 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_SHA256, SSL_AES_256_SHA, SSL_AES128_SHA }; +{ SSL_AES256_SHA256, SSL_AES128_SHA256, SSL_AES256_SHA, SSL_AES128_SHA }; #endif /** @@ -640,7 +640,7 @@ static void add_hmac_digest(SSL *ssl, int mode, uint8_t *hmac_header, const uint8_t *buf, int buf_len, uint8_t *hmac_buf) { int hmac_len = buf_len + 8 + SSL_RECORD_SIZE; - uint8_t *t_buf = (uint8_t *)alloca(buf_len); + 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); @@ -683,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[SHA256_SIZE]; + uint8_t hmac_buf[128]; int hmac_offset; if (ssl->cipher_info->padding_size) @@ -738,12 +738,22 @@ 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) { - if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2 + // TLS1.2 + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2 || ssl->version == 0) { SHA256_Update(&ssl->dc->sha256_ctx, pkt, len); +#if 0 +uint8_t buf[128]; +SHA256_CTX sha256_ctx = ssl->dc->sha256_ctx; // interim copy +SHA256_Final(buf, &sha256_ctx); +print_blob("handshake", buf, 8); +#endif + } - else // TLS1.0/1.0 + + if (ssl->version < SSL_PROTOCOL_VERSION_TLS1_2 || ssl->version == 0) { + uint8_t q[128]; MD5_Update(&ssl->dc->md5_ctx, pkt, len); SHA1_Update(&ssl->dc->sha1_ctx, pkt, len); } @@ -870,7 +880,7 @@ static void prf(SSL *ssl, const uint8_t *sec, int sec_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[128]; //print_blob("premaster secret", premaster_secret, 48); strcpy((char *)buf, "master secret"); memcpy(&buf[13], ssl->dc->client_random, SSL_RANDOM_SIZE); @@ -903,10 +913,11 @@ static void generate_key_block(SSL *ssl, * 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 *q = mac_buf; + int dgst_len; if (label) { @@ -919,17 +930,7 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) SHA256_CTX sha256_ctx = ssl->dc->sha256_ctx; // interim copy SHA256_Final(q, &sha256_ctx); q += SHA256_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); - } + dgst_len = (int)(q-mac_buf); } else // TLS1.0/1.1 { @@ -941,23 +942,26 @@ void finished_digest(SSL *ssl, const char *label, uint8_t *digest) SHA1_Final(q, &sha1_ctx); q += SHA1_SIZE; + dgst_len = (int)(q-mac_buf); + } - 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 (label) + { + 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, dgst_len); } #if 0 printf("label: %s\n", label); - 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; } /** @@ -1190,19 +1194,18 @@ static int set_key_block(SSL *ssl, int is_write) return -1; /* only do once in a handshake */ - if (ssl->dc->bm_proc_index ==0 ) + if (!ssl->dc->key_block_generated) { -#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, 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; @@ -1229,6 +1232,12 @@ static int set_key_block(SSL *ssl, int is_write) 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); @@ -2285,6 +2294,10 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code) printf("\n"); } +/** + * Debugging routine to display alerts. + */ + /** * Debugging routine to display alerts. */ diff --git a/ssl/tls1.h b/ssl/tls1.h index 516626cf8..03b56499d 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -81,7 +81,15 @@ extern "C" { #define BM_RECORD_OFFSET 5 #define NUM_PROTOCOLS 4 + #define SIG_ALG_EXTENSION 0x0d +#define SIG_ALG_MD5 1 +#define SIG_ALG_SHA1 2 +#define SIG_ALG_SHA224 3 +#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; } @@ -155,6 +163,7 @@ typedef struct 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 @@ -245,7 +254,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); diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index 62b457a9e..d5888a069 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -37,10 +37,16 @@ #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 }; +/* support sha512/384/256/1 rsa */ +static const uint8_t g_sig_alg[] = { 0x00, 0x08, + 0x00, SIG_ALG_EXTENSION, 0x00, 0x04, 0x00, 0x02, + SIG_ALG_SHA256, 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); @@ -232,14 +238,13 @@ static int send_client_hello(SSL *ssl) buf[offset++] = 1; /* no compression */ buf[offset++] = 0; - if (ssl->version > SSL_PROTOCOL_VERSION_TLS1_1) + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // 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); } @@ -303,43 +308,13 @@ static int process_server_hello(SSL *ssl) 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); - // 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; + PARANOIA_CHECK(pkt_size, offset); + // no extensions error: return ret; } @@ -404,6 +379,9 @@ static int process_cert_req(SSL *ssl) SET_SSL_FLAG(SSL_HAS_CERT_REQ); ssl->dc->bm_proc_index += offset; PARANOIA_CHECK(pkt_size, offset); + + // don't care about sig/hash algorithm, let server take care of that + // (only SHA256/RSA supported) error: return ret; } @@ -414,9 +392,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[128]; 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; @@ -426,13 +406,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) @@ -442,12 +435,18 @@ 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; + } + 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 - 2); error: return ret; diff --git a/ssl/tls1_svr.c b/ssl/tls1_svr.c index b67f88a74..dcec6b9b4 100644 --- a/ssl/tls1_svr.c +++ b/ssl/tls1_svr.c @@ -165,15 +165,17 @@ 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_extensions; } } } /* ouch! protocol is not supported */ - ret = SSL_ERROR_NO_CIPHER; + return SSL_ERROR_NO_CIPHER; + +do_extensions: + PARANOIA_CHECK(pkt_size, offset); -do_state: error: return ret; } @@ -338,10 +340,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 @@ -377,7 +375,7 @@ static int process_cert_verify(SSL *ssl) uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index]; int pkt_size = ssl->bm_index; uint8_t dgst_buf[MAX_KEY_BYTE_SIZE]; - uint8_t dgst[MD5_SIZE+SHA1_SIZE]; + uint8_t dgst[128]; X509_CTX *x509_ctx = ssl->x509_ctx; int ret = SSL_OK; int n; @@ -390,16 +388,33 @@ static int process_cert_verify(SSL *ssl) n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, sizeof(dgst_buf), 0); SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex); - if (n != SHA1_SIZE + MD5_SIZE) + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2 { - ret = SSL_ERROR_INVALID_KEY; - goto end_cert_vfy; - } + if (n != SHA256_SIZE) + { + ret = SSL_ERROR_INVALID_KEY; + goto end_cert_vfy; + } - finished_digest(ssl, NULL, dgst); /* calculate the digest */ - if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE)) + finished_digest(ssl, NULL, dgst); /* calculate the digest */ + if (memcmp(dgst_buf, dgst, SHA256_SIZE)) + { + ret = SSL_ERROR_INVALID_KEY; + } + } + else // TLS1.0/1.1 { - ret = SSL_ERROR_INVALID_KEY; + if (n != SHA1_SIZE + MD5_SIZE) + { + ret = SSL_ERROR_INVALID_KEY; + goto end_cert_vfy; + } + + finished_digest(ssl, NULL, dgst); /* calculate the digest */ + if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE)) + { + ret = SSL_ERROR_INVALID_KEY; + } } end_cert_vfy: diff --git a/tools/make_certs.sh b/tools/make_certs.sh index d521e9218..ace400f88 100644 --- a/tools/make_certs.sh +++ b/tools/make_certs.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2007, Cameron Rich +# Copyright (c) 2007-2016, Cameron Rich # # All rights reserved. # @@ -69,7 +69,7 @@ prompt = no EOF # private key generation -openssl genrsa -out axTLS.ca_key.pem 1024 +openssl genrsa -out axTLS.ca_key.pem 2048 openssl genrsa -out axTLS.key_512.pem 512 openssl genrsa -out axTLS.key_1024.pem 1024 openssl genrsa -out axTLS.key_1042.pem 1042 @@ -121,10 +121,10 @@ openssl x509 -req -in axTLS.x509_1042.req -out axTLS.x509_1042.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 \ + -sha1 -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 \ + -sha256 -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 \