From b60b9e7afe649a564db13dbf10ca571e973844c1 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Wed, 27 Mar 2013 19:54:48 +0000 Subject: [PATCH] Enable TLS 1.2 ciphers in DTLS 1.2. Port TLS 1.2 GCM code to DTLS. Enable use of TLS 1.2 only ciphers when in DTLS 1.2 mode too. (cherry picked from commit 4221c0dd3004117c63b182af5e8ab345b7265902) --- ssl/d1_both.c | 9 +++++++-- ssl/d1_lib.c | 7 ++++--- ssl/d1_pkt.c | 46 ++++++++++++++++++++++++---------------------- ssl/s3_lib.c | 8 ++++---- ssl/ssl_locl.h | 15 +++++++++++++++ ssl/t1_enc.c | 2 +- ssl/t1_lib.c | 7 ++++--- 7 files changed, 59 insertions(+), 35 deletions(-) diff --git a/ssl/d1_both.c b/ssl/d1_both.c index 262299b154..f7947bd988 100644 --- a/ssl/d1_both.c +++ b/ssl/d1_both.c @@ -272,12 +272,17 @@ int dtls1_do_write(SSL *s, int type) (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); if (s->write_hash) - mac_size = EVP_MD_CTX_size(s->write_hash); + { + if (s->enc_write_ctx && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_GCM_MODE) + mac_size = 0; + else + mac_size = EVP_MD_CTX_size(s->write_hash); + } else mac_size = 0; if (s->enc_write_ctx && - (EVP_CIPHER_mode( s->enc_write_ctx->cipher) & EVP_CIPH_CBC_MODE)) + (EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE)) blocksize = 2 * EVP_CIPHER_block_size(s->enc_write_ctx->cipher); else blocksize = 0; diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index 2b82d527df..b07ee3551a 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -73,7 +73,7 @@ const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT; int dtls1_listen(SSL *s, struct sockaddr *client); SSL3_ENC_METHOD DTLSv1_enc_data={ - dtls1_enc, + tls1_enc, tls1_mac, tls1_setup_key_block, tls1_generate_master_secret, @@ -92,7 +92,7 @@ SSL3_ENC_METHOD DTLSv1_enc_data={ }; SSL3_ENC_METHOD DTLSv1_2_enc_data={ - dtls1_enc, + tls1_enc, tls1_mac, tls1_setup_key_block, tls1_generate_master_secret, @@ -104,7 +104,8 @@ SSL3_ENC_METHOD DTLSv1_2_enc_data={ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, - SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF, + SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS + |SSL_ENC_FLAG_SHA256_PRF|SSL_ENC_FLAG_TLS1_2_CIPHERS, DTLS1_HM_HEADER_LENGTH, dtls1_set_handshake_header, dtls1_handshake_write diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c index 8186462d4a..8ace79a8ac 100644 --- a/ssl/d1_pkt.c +++ b/ssl/d1_pkt.c @@ -1472,10 +1472,10 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, unsigned char *p,*pseq; int i,mac_size,clear=0; int prefix_len = 0; + int eivlen; SSL3_RECORD *wr; SSL3_BUFFER *wb; SSL_SESSION *sess; - int bs; /* first check if there is a SSL3_BUFFER still being written * out. This will happen with non blocking IO */ @@ -1560,18 +1560,27 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, pseq=p; p+=10; - /* lets setup the record stuff. */ - - /* Make space for the explicit IV in case of CBC. - * (this is a bit of a boundary violation, but what the heck). - */ - if ( s->enc_write_ctx && - (EVP_CIPHER_mode( s->enc_write_ctx->cipher ) & EVP_CIPH_CBC_MODE)) - bs = EVP_CIPHER_block_size(s->enc_write_ctx->cipher); - else - bs = 0; + /* Explicit IV length, block ciphers appropriate version flag */ + if (s->enc_write_ctx) + { + int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx); + if (mode == EVP_CIPH_CBC_MODE) + { + eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx); + if (eivlen <= 1) + eivlen = 0; + } + /* Need explicit part of IV for GCM mode */ + else if (mode == EVP_CIPH_GCM_MODE) + eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN; + else + eivlen = 0; + } + else + eivlen = 0; - wr->data=p + bs; /* make room for IV in case of CBC */ + /* lets setup the record stuff. */ + wr->data=p + eivlen; /* make room for IV in case of CBC */ wr->length=(int)len; wr->input=(unsigned char *)buf; @@ -1599,7 +1608,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, if (mac_size != 0) { - if(s->method->ssl3_enc->mac(s,&(p[wr->length + bs]),1) < 0) + if(s->method->ssl3_enc->mac(s,&(p[wr->length + eivlen]),1) < 0) goto err; wr->length+=mac_size; } @@ -1608,15 +1617,8 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len, wr->input=p; wr->data=p; - - /* ssl3_enc can only have an error on read */ - if (bs) /* bs != 0 in case of CBC */ - { - RAND_pseudo_bytes(p,bs); - /* master IV and last CBC residue stand for - * the rest of randomness */ - wr->length += bs; - } + if (eivlen) + wr->length += eivlen; s->method->ssl3_enc->enc(s,1); diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 59d2fbbfac..e418c6428d 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3383,7 +3383,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) #ifndef OPENSSL_NO_HEARTBEATS case SSL_CTRL_TLS_EXT_SEND_HEARTBEAT: - if (SSL_version(s) == DTLS1_VERSION || SSL_version(s) == DTLS1_BAD_VER) + if (SSL_IS_DTLS(s)) ret = dtls1_heartbeat(s); else ret = tls1_heartbeat(s); @@ -3505,7 +3505,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) return ssl_cert_set_cert_store(s->cert, parg, 1, larg); case SSL_CTRL_GET_PEER_SIGNATURE_NID: - if (TLS1_get_version(s) >= TLS1_2_VERSION) + if (SSL_USE_SIGALGS(s)) { if (s->session && s->session->sess_cert) { @@ -4085,9 +4085,9 @@ SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, { c=sk_SSL_CIPHER_value(prio,i); - /* Skip TLS v1.2 only ciphersuites if lower than v1.2 */ + /* Skip TLS v1.2 only ciphersuites if not supported */ if ((c->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_version(s) < TLS1_2_VERSION)) + !SSL_USE_TLS1_2_CIPHERS(s)) continue; ssl_set_cert_masks(cert,c); diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index f5597ee64b..a19f98569e 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -450,6 +450,17 @@ */ #define SSL_USE_SIGALGS(s) \ (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS) +/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: + * may apply to others in future. + */ +#define SSL_USE_TLS1_2_CIPHERS(s) \ + (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS) +/* Determine if a client can use TLS 1.2 ciphersuites: can't rely on method + * flags because it may not be set to correct version yet. + */ +#define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \ + ((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \ + (!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION)) /* Mostly for SSLv3 */ #define SSL_PKEY_RSA_ENC 0 @@ -723,6 +734,10 @@ typedef struct ssl3_enc_method #define SSL_ENC_FLAG_SHA256_PRF 0x4 /* Is DTLS */ #define SSL_ENC_FLAG_DTLS 0x8 +/* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: + * may apply to others in future. + */ +#define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10 #ifndef OPENSSL_NO_COMP /* Used for holding the relevant compression methods loaded into SSL_CTX */ diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c index 63761e5c72..c35270706b 100644 --- a/ssl/t1_enc.c +++ b/ssl/t1_enc.c @@ -724,7 +724,7 @@ int tls1_enc(SSL *s, int send) int ivlen; enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx); /* For TLSv1.1 and later explicit IV */ - if (s->version >= TLS1_1_VERSION + if (SSL_USE_EXPLICIT_IV(s) && EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE) ivlen = EVP_CIPHER_iv_length(enc); else diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 35a58a956c..b3c7cb5df1 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -178,7 +178,8 @@ SSL3_ENC_METHOD TLSv1_2_enc_data={ TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE, tls1_alert_code, tls1_export_keying_material, - SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF, + SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF + |SSL_ENC_FLAG_TLS1_2_CIPHERS, SSL3_HM_HEADER_LENGTH, ssl3_set_handshake_header, ssl3_handshake_write @@ -1018,8 +1019,8 @@ void ssl_set_client_disabled(SSL *s) int have_rsa = 0, have_dsa = 0, have_ecdsa = 0; c->mask_a = 0; c->mask_k = 0; - /* If less than TLS 1.2 don't allow TLS 1.2 only ciphers */ - if (TLS1_get_client_version(s) < TLS1_2_VERSION) + /* Don't allow TLS 1.2 only ciphers if we don't suppport them */ + if (!SSL_CLIENT_USE_TLS1_2_CIPHERS(s)) c->mask_ssl = SSL_TLSV1_2; else c->mask_ssl = 0; -- 2.34.1