From fc6b6b346feaa950fa1ae690af9f690f56380746 Mon Sep 17 00:00:00 2001 From: cameronrich Date: Thu, 11 Aug 2016 10:04:13 +0000 Subject: [PATCH] Server side v1.2 is basically working git-svn-id: svn://svn.code.sf.net/p/axtls/code/trunk@265 9a5d90b5-6617-0410-8a86-bb477d3ed2e3 --- ssl/crypto_misc.h | 1 - ssl/ssl.h | 1 + ssl/tls1.c | 84 +++++++++++++++++++++++++++++++++----- ssl/tls1.h | 6 ++- ssl/tls1_clnt.c | 55 +++++++++++++++++++++---- ssl/tls1_svr.c | 102 +++++++++++++++++++++++++++++++++++++++++----- ssl/x509.c | 3 -- 7 files changed, 217 insertions(+), 35 deletions(-) diff --git a/ssl/crypto_misc.h b/ssl/crypto_misc.h index 2129422f6..92494b605 100644 --- a/ssl/crypto_misc.h +++ b/ssl/crypto_misc.h @@ -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 diff --git a/ssl/ssl.h b/ssl/ssl.h index 064a00896..fb91602f9 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -100,6 +100,7 @@ extern "C" { #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 diff --git a/ssl/tls1.c b/ssl/tls1.c index c23e36053..ba84d043d 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -54,6 +54,7 @@ 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 @@ -348,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; @@ -742,18 +763,10 @@ void add_packet(SSL *ssl, const uint8_t *pkt, int len) 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 - } - if (ssl->version < SSL_PROTOCOL_VERSION_TLS1_2 || ssl->version == 0) + if (ssl->version < SSL_PROTOCOL_VERSION_TLS1_2) { - uint8_t q[128]; MD5_Update(&ssl->dc->md5_ctx, pkt, len); SHA1_Update(&ssl->dc->sha1_ctx, pkt, len); } @@ -1641,6 +1654,7 @@ int send_alert(SSL *ssl, int error_code) break; case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST): + case SSL_ERROR_INVALID_CERT_HASH_ALG: alert_num = SSL_ALERT_UNSUPPORTED_CERTIFICATE; break; @@ -1699,6 +1713,7 @@ error: */ int send_certificate(SSL *ssl) { + int ret = SSL_OK; int i = 0; uint8_t *buf = ssl->bm_data; int offset = 7; @@ -1708,6 +1723,12 @@ int send_certificate(SSL *ssl) buf[1] = 0; buf[4] = 0; + if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2 && + ((ret = check_certificate_chain(ssl)) != SSL_OK)) + { + goto error; + } + while (i < ssl->ssl_ctx->chain_length) { SSL_CERT *cert = &ssl->ssl_ctx->certs[i]; @@ -1726,7 +1747,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; } /** @@ -1945,6 +1969,42 @@ 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. @@ -2258,6 +2318,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; diff --git a/ssl/tls1.h b/ssl/tls1.h index 03b56499d..e2768d419 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -82,10 +82,9 @@ extern "C" { #define NUM_PROTOCOLS 4 +#define MAX_SIG_ALGORITHMS 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 @@ -150,6 +149,7 @@ typedef struct { uint8_t *buf; int size; + uint8_t hash_alg; } SSL_CERT; typedef struct @@ -188,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 */ diff --git a/ssl/tls1_clnt.c b/ssl/tls1_clnt.c index d5888a069..d0a85384a 100644 --- a/ssl/tls1_clnt.c +++ b/ssl/tls1_clnt.c @@ -38,9 +38,15 @@ #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, 0x08, - 0x00, SIG_ALG_EXTENSION, 0x00, 0x04, 0x00, 0x02, - SIG_ALG_SHA256, SIG_ALG_RSA }; +static const uint8_t g_sig_alg[] = { + 0x00, 0x0e, + 0x00, SIG_ALG_EXTENSION, + 0x00, 0x0a, 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 +}; static const uint8_t g_asn1_sha256[] = { @@ -238,7 +244,8 @@ static int send_client_hello(SSL *ssl) buf[offset++] = 1; /* no compression */ buf[offset++] = 0; - if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2 + /* 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); @@ -371,17 +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); - // don't care about sig/hash algorithm, let server take care of that - // (only SHA256/RSA supported) + 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; } diff --git a/ssl/tls1_svr.c b/ssl/tls1_svr.c index dcec6b9b4..e9d0269b9 100644 --- a/ssl/tls1_svr.c +++ b/ssl/tls1_svr.c @@ -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,7 +170,7 @@ 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_extensions; + goto do_compression; } } } @@ -173,8 +178,57 @@ static int process_client_hello(SSL *ssl) /* ouch! protocol is not supported */ return SSL_ERROR_NO_CIPHER; -do_extensions: - PARANOIA_CHECK(pkt_size, offset); + /* completely ignore compression */ +do_compression: + offset += cs_len; + id_len = buf[offset++]; + offset += id_len; + PARANOIA_CHECK(pkt_size, offset + id_len); + + /* 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; @@ -355,7 +409,16 @@ 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 +}; /* * Send the certificate request message. @@ -378,28 +441,47 @@ static int process_cert_verify(SSL *ssl) uint8_t dgst[128]; X509_CTX *x509_ctx = ssl->x509_ctx; int ret = SSL_OK; + int offset = 6; + uint8_t hash_alg; + uint8_t sig_alg; + 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 + { + hash_alg = buf[4]; + 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 (n != SHA256_SIZE) + if (memcmp(dgst_buf, g_asn1_sha256, sizeof(g_asn1_sha256))) { ret = SSL_ERROR_INVALID_KEY; - goto end_cert_vfy; + goto error; } finished_digest(ssl, NULL, dgst); /* calculate the digest */ - if (memcmp(dgst_buf, dgst, SHA256_SIZE)) + if (memcmp(&dgst_buf[sizeof(g_asn1_sha256)], dgst, SHA256_SIZE)) { ret = SSL_ERROR_INVALID_KEY; + goto error; } } else // TLS1.0/1.1 diff --git a/ssl/x509.c b/ssl/x509.c index da0706288..2a3fd565e 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -524,9 +524,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;