diff options
-rw-r--r-- | engines/e_ossltest.c | 35 | ||||
-rw-r--r-- | ssl/build.info | 2 | ||||
-rw-r--r-- | ssl/record/record.h | 1 | ||||
-rw-r--r-- | ssl/record/ssl3_record_tls13.c | 104 | ||||
-rw-r--r-- | ssl/ssl_locl.h | 2 | ||||
-rw-r--r-- | ssl/t1_lib.c | 5 | ||||
-rw-r--r-- | ssl/tls13_enc.c | 62 | ||||
-rw-r--r-- | util/TLSProxy/Record.pm | 2 |
8 files changed, 146 insertions, 67 deletions
diff --git a/engines/e_ossltest.c b/engines/e_ossltest.c index afa5edfeec..32d3118e70 100644 --- a/engines/e_ossltest.c +++ b/engines/e_ossltest.c @@ -617,33 +617,46 @@ int ossltest_aes128_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, int ossltest_aes128_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { - const size_t datalen = inl - EVP_GCM_TLS_EXPLICIT_IV_LEN - - EVP_GCM_TLS_TAG_LEN; - unsigned char *tmpbuf = OPENSSL_malloc(datalen); + unsigned char *tmpbuf = OPENSSL_malloc(inl); - if (tmpbuf == NULL) + if (tmpbuf == NULL && inl > 0) return -1; /* Remember what we were asked to encrypt */ - memcpy(tmpbuf, in + EVP_GCM_TLS_EXPLICIT_IV_LEN, datalen); + memcpy(tmpbuf, in, inl); /* Go through the motions of encrypting it */ EVP_CIPHER_meth_get_do_cipher(EVP_aes_128_gcm())(ctx, out, in, inl); /* - * Throw it all away and just use the plaintext as the output with empty - * IV and tag + * Throw it all away and just use the plaintext as the output */ - memset(out, 0, inl); - memcpy(out + EVP_GCM_TLS_EXPLICIT_IV_LEN, tmpbuf, datalen); + memcpy(out, tmpbuf, inl); OPENSSL_free(tmpbuf); - return 1; + return inl; } static int ossltest_aes128_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { + int ret; + /* Pass the ctrl down */ - return EVP_CIPHER_meth_get_ctrl(EVP_aes_128_gcm())(ctx, type, arg, ptr); + ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_gcm())(ctx, type, arg, ptr); + + if (ret <= 0) + return ret; + + switch(type) { + case EVP_CTRL_AEAD_GET_TAG: + /* Always give the same tag */ + memset(ptr, 0, EVP_GCM_TLS_TAG_LEN); + break; + + default: + break; + } + + return 1; } diff --git a/ssl/build.info b/ssl/build.info index 72b8dfc2be..23d33d3df8 100644 --- a/ssl/build.info +++ b/ssl/build.info @@ -11,4 +11,4 @@ SOURCE[../libssl]=\ ssl_asn1.c ssl_txt.c ssl_init.c ssl_conf.c ssl_mcnf.c \ bio_ssl.c ssl_err.c t1_reneg.c tls_srp.c t1_trce.c ssl_utst.c \ record/ssl3_buffer.c record/ssl3_record.c record/dtls1_bitmap.c \ - statem/statem.c + statem/statem.c record/ssl3_record_tls13.c diff --git a/ssl/record/record.h b/ssl/record/record.h index e30010d170..e9951966d1 100644 --- a/ssl/record/record.h +++ b/ssl/record/record.h @@ -230,6 +230,7 @@ __owur int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t size_t *written); __owur int tls1_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send); __owur int tls1_mac(SSL *ssl, SSL3_RECORD *rec, unsigned char *md, int send); +__owur int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send); int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl); void DTLS_RECORD_LAYER_free(RECORD_LAYER *rl); void DTLS_RECORD_LAYER_clear(RECORD_LAYER *rl); diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c new file mode 100644 index 0000000000..48d52700d4 --- /dev/null +++ b/ssl/record/ssl3_record_tls13.c @@ -0,0 +1,104 @@ +/* + * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "../ssl_locl.h" +#include "record_locl.h" + +/*- + * tls13_enc encrypts/decrypts |n_recs| in |recs|. + * + * Returns: + * 0: (in non-constant time) if the record is publically invalid (i.e. too + * short etc). + * 1: if the record encryption was successful. + * -1: if the record's AEAD-authenticator is invalid or, if sending, + * an internal error occurred. + */ +int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int send) +{ + EVP_CIPHER_CTX *ctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + size_t ivlen, offset, loop; + unsigned char *staticiv; + unsigned char *seq; + int lenu, lenf; + SSL3_RECORD *rec = &recs[0]; + + if (n_recs != 1) { + /* Should not happen */ + /* TODO(TLS1.3): Support pipelining */ + return -1; + } + + if (send) { + ctx = s->enc_write_ctx; + staticiv = s->write_iv; + seq = RECORD_LAYER_get_write_sequence(&s->rlayer); + } else { + ctx = s->enc_read_ctx; + staticiv = s->read_iv; + seq = RECORD_LAYER_get_read_sequence(&s->rlayer); + } + + if (ctx == NULL) { + memmove(rec->data, rec->input, rec->length); + rec->input = rec->data; + return 1; + } + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + + if (!send) { + /* + * Take off tag. There must be at least one byte of content type as + * well as the tag + */ + /* + * TODO(TLS1.3): We're going to need to figure out the tag len based on + * the cipher. For now we just support GCM tags. + * TODO(TLS1.3): When we've swapped over the record layer to TLSv1.3 + * then the length must be 1 + the tag len to account for the content + * byte that we know must have been encrypted. + */ + if (rec->length < EVP_GCM_TLS_TAG_LEN) + return 0; + rec->length -= EVP_GCM_TLS_TAG_LEN; + } + + /* Set up IV */ + if (ivlen < SEQ_NUM_SIZE) { + /* Should not happen */ + return -1; + } + offset = ivlen - SEQ_NUM_SIZE; + memcpy(iv, staticiv, offset); + for (loop = 0; loop < SEQ_NUM_SIZE; loop++) + iv[offset + loop] = staticiv[offset + loop] ^ seq[loop]; + + /* TODO(size_t): lenu/lenf should be a size_t but EVP can't support it */ + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, send) <= 0 + || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, + (unsigned int)rec->length) <= 0 + || (!send && EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, + EVP_GCM_TLS_TAG_LEN, + rec->data + rec->length) <= 0) + || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 + || (size_t)(lenu + lenf) != rec->length) { + return -1; + } + + if (send) { + /* Add the tag */ + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, EVP_GCM_TLS_TAG_LEN, + rec->data + rec->length) <= 0) + return -1; + rec->length += EVP_GCM_TLS_TAG_LEN; + } + + return 1; +} diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index e909cadf5a..cb29b996f3 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -960,10 +960,12 @@ struct ssl_st { unsigned char client_finished_secret[EVP_MAX_MD_SIZE]; unsigned char server_finished_secret[EVP_MAX_MD_SIZE]; EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */ + unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */ EVP_MD_CTX *read_hash; /* used for mac generation */ COMP_CTX *compress; /* compression */ COMP_CTX *expand; /* uncompress */ EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */ + unsigned char write_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static write IV */ EVP_MD_CTX *write_hash; /* used for mac generation */ /* session info */ /* client cert? */ diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index ce728b0a34..778f84ee72 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -79,7 +79,7 @@ SSL3_ENC_METHOD const TLSv1_2_enc_data = { }; SSL3_ENC_METHOD const TLSv1_3_enc_data = { - tls1_enc, + tls13_enc, tls1_mac, tls13_setup_key_block, tls13_generate_master_secret, @@ -89,8 +89,7 @@ SSL3_ENC_METHOD const TLSv1_3_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_TLS1_2_CIPHERS, + SSL_ENC_FLAG_SIGALGS | SSL_ENC_FLAG_SHA256_PRF, ssl3_set_handshake_header, tls_close_construct_packet, ssl3_handshake_write diff --git a/ssl/tls13_enc.c b/ssl/tls13_enc.c index 698b9be5ca..5af0c303bb 100644 --- a/ssl/tls13_enc.c +++ b/ssl/tls13_enc.c @@ -284,7 +284,7 @@ int tls13_change_cipher_state(SSL *s, int which) static const unsigned char server_application_traffic[] = "server application traffic secret"; unsigned char key[EVP_MAX_KEY_LENGTH]; - unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char *iv; unsigned char secret[EVP_MAX_MD_SIZE]; unsigned char *insecret; unsigned char *finsecret = NULL; @@ -306,6 +306,7 @@ int tls13_change_cipher_state(SSL *s, int which) } } ciph_ctx = s->enc_read_ctx; + iv = s->read_iv; RECORD_LAYER_reset_read_sequence(&s->rlayer); } else { @@ -319,6 +320,7 @@ int tls13_change_cipher_state(SSL *s, int which) } } ciph_ctx = s->enc_write_ctx; + iv = s->write_iv; RECORD_LAYER_reset_write_sequence(&s->rlayer); } @@ -357,13 +359,7 @@ int tls13_change_cipher_state(SSL *s, int which) /* TODO(size_t): convert me */ keylen = EVP_CIPHER_key_length(ciph); - - if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) - ivlen = EVP_GCM_TLS_FIXED_IV_LEN; - else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) - ivlen = EVP_CCM_TLS_FIXED_IV_LEN; - else - ivlen = EVP_CIPHER_iv_length(ciph); + ivlen = EVP_CIPHER_iv_length(ciph); if (!tls13_derive_key(s, secret, key, keylen) || !tls13_derive_iv(s, secret, iv, ivlen) @@ -374,40 +370,10 @@ int tls13_change_cipher_state(SSL *s, int which) goto err; } - if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) { - if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, NULL, - (which & SSL3_CC_WRITE)) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_GCM_SET_IV_FIXED, - (int)ivlen, iv)) { - SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); - goto err; - } - } else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) { - int taglen; - - if (s->s3->tmp.new_cipher->algorithm_enc - & (SSL_AES128CCM8 | SSL_AES256CCM8)) - taglen = 8; - else - taglen = 16; - if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, - (which & SSL3_CC_WRITE)) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, - NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, - NULL) - || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_CCM_SET_IV_FIXED, - (int)ivlen, iv) - || !EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1)) { - SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); - goto err; - } - } else { - if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, iv, - (which & SSL3_CC_WRITE))) { - SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); - goto err; - } + if (EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, NULL, + (which & SSL3_CC_WRITE)) <= 0) { + SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); + goto err; } #ifdef OPENSSL_SSL_TRACE_CRYPTO @@ -417,14 +383,10 @@ int tls13_change_cipher_state(SSL *s, int which) if (ciph->key_len) s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, key, ciph->key_len, s, s->msg_callback_arg); - if (ivlen) { - if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) - wh |= TLS1_RT_CRYPTO_FIXED_IV; - else - wh |= TLS1_RT_CRYPTO_IV; - s->msg_callback(2, s->version, wh, iv, ivlen, s, - s->msg_callback_arg); - } + + wh |= TLS1_RT_CRYPTO_IV; + s->msg_callback(2, s->version, wh, iv, ivlen, s, + s->msg_callback_arg); } #endif diff --git a/util/TLSProxy/Record.pm b/util/TLSProxy/Record.pm index 7189035fb4..5a35925aeb 100644 --- a/util/TLSProxy/Record.pm +++ b/util/TLSProxy/Record.pm @@ -242,8 +242,6 @@ sub decrypt() #an unecrypted alert, so don't try to decrypt return $data if (length($data) == 2); } - #8 bytes for a GCM IV - $data = substr($data, 8); $mactaglen = 16; } elsif ($self->version >= VERS_TLS_1_1()) { #16 bytes for a standard IV |