summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--engines/e_ossltest.c35
-rw-r--r--ssl/build.info2
-rw-r--r--ssl/record/record.h1
-rw-r--r--ssl/record/ssl3_record_tls13.c104
-rw-r--r--ssl/ssl_locl.h2
-rw-r--r--ssl/t1_lib.c5
-rw-r--r--ssl/tls13_enc.c62
-rw-r--r--util/TLSProxy/Record.pm2
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