Commit bebc0c7d authored by Matt Caswell's avatar Matt Caswell
Browse files

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: default avatarRich Salz <rsalz@openssl.org>
parent 54d028aa
Loading
Loading
Loading
Loading
+24 −11
Original line number Diff line number Diff line
@@ -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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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);
+104 −0
Original line number Diff line number Diff line
/*
 * 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;
}
+2 −0
Original line number Diff line number Diff line
@@ -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? */
Loading