Use the TLSv1.3 nonce construction

This updates the record layer to use the TLSv1.3 style nonce construciton.
It also updates TLSProxy and ossltest to be able to recognise the new
layout.

Reviewed-by: Rich Salz <rsalz@openssl.org>
This commit is contained in:
Matt Caswell 2016-11-17 18:00:17 +00:00
parent 54d028aa0f
commit bebc0c7d85
8 changed files with 146 additions and 67 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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? */

View File

@ -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

View File

@ -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

View File

@ -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