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

Implement the early data changes required in tls13_change_cipher_state()

parent 923ac827
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -299,12 +299,13 @@ extern "C" {
# define SSL3_MT_CCS                             1
# define SSL3_MT_CCS                             1


/* These are used when changing over to a new cipher */
/* These are used when changing over to a new cipher */
# define SSL3_CC_READ            0x01
# define SSL3_CC_READ            0x001
# define SSL3_CC_WRITE           0x02
# define SSL3_CC_WRITE           0x002
# define SSL3_CC_CLIENT          0x10
# define SSL3_CC_CLIENT          0x010
# define SSL3_CC_SERVER          0x20
# define SSL3_CC_SERVER          0x020
# define SSL3_CC_HANDSHAKE       0x40
# define SSL3_CC_EARLY           0x040
# define SSL3_CC_APPLICATION     0x80
# define SSL3_CC_HANDSHAKE       0x080
# define SSL3_CC_APPLICATION     0x100
# define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE)
# define SSL3_CHANGE_CIPHER_CLIENT_WRITE (SSL3_CC_CLIENT|SSL3_CC_WRITE)
# define SSL3_CHANGE_CIPHER_SERVER_READ  (SSL3_CC_SERVER|SSL3_CC_READ)
# define SSL3_CHANGE_CIPHER_SERVER_READ  (SSL3_CC_SERVER|SSL3_CC_READ)
# define SSL3_CHANGE_CIPHER_CLIENT_READ  (SSL3_CC_CLIENT|SSL3_CC_READ)
# define SSL3_CHANGE_CIPHER_CLIENT_READ  (SSL3_CC_CLIENT|SSL3_CC_READ)
+7 −4
Original line number Original line Diff line number Diff line
@@ -2196,10 +2196,12 @@ __owur int tls13_hkdf_expand(SSL *s, const EVP_MD *md,
                             const unsigned char *label, size_t labellen,
                             const unsigned char *label, size_t labellen,
                             const unsigned char *hash,
                             const unsigned char *hash,
                             unsigned char *out, size_t outlen);
                             unsigned char *out, size_t outlen);
__owur int tls13_derive_key(SSL *s, const unsigned char *secret,
__owur int tls13_derive_key(SSL *s, const EVP_MD *md,
                            unsigned char *key, size_t keylen);
                            const unsigned char *secret, unsigned char *key,
__owur int tls13_derive_iv(SSL *s, const unsigned char *secret,
                            size_t keylen);
                           unsigned char *iv, size_t ivlen);
__owur int tls13_derive_iv(SSL *s, const EVP_MD *md,
                           const unsigned char *secret, unsigned char *iv,
                           size_t ivlen);
__owur int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
__owur int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
                                    const unsigned char *secret,
                                    const unsigned char *secret,
                                    unsigned char *fin, size_t finlen);
                                    unsigned char *fin, size_t finlen);
@@ -2352,6 +2354,7 @@ __owur int ssl_log_secret(SSL *ssl, const char *label,
                          const uint8_t *secret, size_t secret_len);
                          const uint8_t *secret, size_t secret_len);


#define MASTER_SECRET_LABEL "CLIENT_RANDOM"
#define MASTER_SECRET_LABEL "CLIENT_RANDOM"
#define CLIENT_EARLY_LABEL "CLIENT_EARLY_TRAFFIC_SECRET"
#define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
#define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
#define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET"
#define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET"
#define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0"
#define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0"
+77 −21
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
            || !WPACKET_sub_memcpy_u8(&pkt, hash, (hash == NULL) ? 0 : hashlen)
            || !WPACKET_sub_memcpy_u8(&pkt, hash, (hash == NULL) ? 0 : hashlen)
            || !WPACKET_get_total_written(&pkt, &hkdflabellen)
            || !WPACKET_get_total_written(&pkt, &hkdflabellen)
            || !WPACKET_finish(&pkt)) {
            || !WPACKET_finish(&pkt)) {
        EVP_PKEY_CTX_free(pctx);
        WPACKET_cleanup(&pkt);
        WPACKET_cleanup(&pkt);
        return 0;
        return 0;
    }
    }
@@ -77,26 +78,26 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
 * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
 * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on
 * success  0 on failure.
 * success  0 on failure.
 */
 */
int tls13_derive_key(SSL *s, const unsigned char *secret, unsigned char *key,
int tls13_derive_key(SSL *s, const EVP_MD *md, const unsigned char *secret,
                     size_t keylen)
                     unsigned char *key, size_t keylen)
{
{
    static const unsigned char keylabel[] = "key";
    static const unsigned char keylabel[] = "key";


    return tls13_hkdf_expand(s, ssl_handshake_md(s), secret, keylabel,
    return tls13_hkdf_expand(s, md, secret, keylabel, sizeof(keylabel) - 1,
                             sizeof(keylabel) - 1, NULL, key, keylen);
                             NULL, key, keylen);
}
}


/*
/*
 * Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on
 * Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on
 * success  0 on failure.
 * success  0 on failure.
 */
 */
int tls13_derive_iv(SSL *s, const unsigned char *secret, unsigned char *iv,
int tls13_derive_iv(SSL *s, const EVP_MD *md, const unsigned char *secret,
                    size_t ivlen)
                    unsigned char *iv, size_t ivlen)
{
{
    static const unsigned char ivlabel[] = "iv";
    static const unsigned char ivlabel[] = "iv";


    return tls13_hkdf_expand(s, ssl_handshake_md(s), secret, ivlabel,
    return tls13_hkdf_expand(s, md, secret, ivlabel, sizeof(ivlabel) - 1,
                             sizeof(ivlabel) - 1, NULL, iv, ivlen);
                             NULL, iv, ivlen);
}
}


int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
@@ -242,7 +243,8 @@ int tls13_setup_key_block(SSL *s)
    return 1;
    return 1;
}
}


static int derive_secret_key_and_iv(SSL *s, int send,
static int derive_secret_key_and_iv(SSL *s, int send, const EVP_MD *md,
                                    const EVP_CIPHER *ciph,
                                    const unsigned char *insecret,
                                    const unsigned char *insecret,
                                    const unsigned char *hash,
                                    const unsigned char *hash,
                                    const unsigned char *label,
                                    const unsigned char *label,
@@ -251,9 +253,7 @@ static int derive_secret_key_and_iv(SSL *s, int send,
{
{
    unsigned char key[EVP_MAX_KEY_LENGTH];
    unsigned char key[EVP_MAX_KEY_LENGTH];
    size_t ivlen, keylen, taglen;
    size_t ivlen, keylen, taglen;
    const EVP_MD *md = ssl_handshake_md(s);
    size_t hashlen = EVP_MD_size(md);
    size_t hashlen = EVP_MD_size(md);
    const EVP_CIPHER *ciph = s->s3->tmp.new_sym_enc;


    if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, secret,
    if (!tls13_hkdf_expand(s, md, insecret, label, labellen, hash, secret,
                           hashlen)) {
                           hashlen)) {
@@ -275,8 +275,8 @@ static int derive_secret_key_and_iv(SSL *s, int send,
        taglen = 0;
        taglen = 0;
    }
    }


    if (!tls13_derive_key(s, secret, key, keylen)
    if (!tls13_derive_key(s, md, secret, key, keylen)
            || !tls13_derive_iv(s, secret, iv, ivlen)) {
            || !tls13_derive_iv(s, md, secret, iv, ivlen)) {
        SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_INTERNAL_ERROR);
        SSLerr(SSL_F_DERIVE_SECRET_KEY_AND_IV, ERR_R_INTERNAL_ERROR);
        goto err;
        goto err;
    }
    }
@@ -312,6 +312,8 @@ static int derive_secret_key_and_iv(SSL *s, int send,


int tls13_change_cipher_state(SSL *s, int which)
int tls13_change_cipher_state(SSL *s, int which)
{
{
    static const unsigned char client_early_traffic[] =
        "client early traffic secret";
    static const unsigned char client_handshake_traffic[] =
    static const unsigned char client_handshake_traffic[] =
        "client handshake traffic secret";
        "client handshake traffic secret";
    static const unsigned char client_application_traffic[] =
    static const unsigned char client_application_traffic[] =
@@ -334,6 +336,8 @@ int tls13_change_cipher_state(SSL *s, int which)
    const unsigned char *label;
    const unsigned char *label;
    size_t labellen, hashlen = 0;
    size_t labellen, hashlen = 0;
    int ret = 0;
    int ret = 0;
    const EVP_MD *md;
    const EVP_CIPHER *cipher;


    if (which & SSL3_CC_READ) {
    if (which & SSL3_CC_READ) {
        if (s->enc_read_ctx != NULL) {
        if (s->enc_read_ctx != NULL) {
@@ -367,7 +371,51 @@ int tls13_change_cipher_state(SSL *s, int which)


    if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
    if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
            || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
            || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
        if (which & SSL3_CC_HANDSHAKE) {
        if (which & SSL3_CC_EARLY) {
            EVP_MD_CTX *mdctx = NULL;
            long handlen;
            void *hdata;
            unsigned int hashlenui;
            const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);

            insecret = s->early_secret;
            label = client_early_traffic;
            labellen = sizeof(client_early_traffic) - 1;
            log_label = CLIENT_EARLY_LABEL;

            handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
            if (handlen <= 0) {
                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE,
                       SSL_R_BAD_HANDSHAKE_LENGTH);
                goto err;
            }
            if (sslcipher == NULL) {
                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                goto err;
            }

            /*
             * We need to calculate the handshake digest using the digest from
             * the session. We haven't yet selected our ciphersuite so we can't
             * use ssl_handshake_md().
             */
            mdctx = EVP_MD_CTX_new();
            if (mdctx == NULL) {
                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
            md = ssl_md(sslcipher->algorithm2);
            if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
                    || !EVP_DigestUpdate(mdctx, hdata, handlen)
                    || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
                SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                EVP_MD_CTX_free(mdctx);
                goto err;
            }
            hashlen = hashlenui;
            EVP_MD_CTX_free(mdctx);
        } else if (which & SSL3_CC_HANDSHAKE) {
            insecret = s->handshake_secret;
            insecret = s->handshake_secret;
            finsecret = s->client_finished_secret;
            finsecret = s->client_finished_secret;
            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
@@ -388,6 +436,7 @@ int tls13_change_cipher_state(SSL *s, int which)
            hash = s->server_finished_hash;
            hash = s->server_finished_hash;
        }
        }
    } else {
    } else {
        /* Early data never applies to client-read/server-write */
        if (which & SSL3_CC_HANDSHAKE) {
        if (which & SSL3_CC_HANDSHAKE) {
            insecret = s->handshake_secret;
            insecret = s->handshake_secret;
            finsecret = s->server_finished_secret;
            finsecret = s->server_finished_secret;
@@ -403,11 +452,15 @@ int tls13_change_cipher_state(SSL *s, int which)
        }
        }
    }
    }


    if (!(which & SSL3_CC_EARLY)) {
        md = ssl_handshake_md(s);
        cipher = s->s3->tmp.new_sym_enc;
        if (!ssl3_digest_cached_records(s, 1)
        if (!ssl3_digest_cached_records(s, 1)
                || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
                || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
            SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
            goto err;
            goto err;
        }
        }
    }


    /*
    /*
     * Save the hash of handshakes up to now for use when we calculate the
     * Save the hash of handshakes up to now for use when we calculate the
@@ -431,8 +484,9 @@ int tls13_change_cipher_state(SSL *s, int which)
        s->session->master_key_length = hashlen;
        s->session->master_key_length = hashlen;
    }
    }


    if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, insecret, hash,
    if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
                                  label, labellen, secret, iv, ciph_ctx)) {
                                  insecret, hash, label, labellen, secret, iv,
                                  ciph_ctx)) {
        goto err;
        goto err;
    }
    }


@@ -485,7 +539,9 @@ int tls13_update_key(SSL *s, int send)
        RECORD_LAYER_reset_read_sequence(&s->rlayer);
        RECORD_LAYER_reset_read_sequence(&s->rlayer);
    }
    }


    if (!derive_secret_key_and_iv(s, send, insecret, NULL, application_traffic,
    if (!derive_secret_key_and_iv(s, send, ssl_handshake_md(s),
                                  s->s3->tmp.new_sym_enc, insecret, NULL,
                                  application_traffic,
                                  sizeof(application_traffic) - 1, secret, iv,
                                  sizeof(application_traffic) - 1, secret, iv,
                                  ciph_ctx))
                                  ciph_ctx))
        goto err;
        goto err;
+7 −2
Original line number Original line Diff line number Diff line
@@ -192,6 +192,11 @@ int ssl_log_secret(SSL *ssl,
    return 1;
    return 1;
}
}


const EVP_MD *ssl_md(int idx)
{
    return EVP_sha256();
}

/* End of mocked out code */
/* End of mocked out code */


static int test_secret(SSL *s, unsigned char *prk,
static int test_secret(SSL *s, unsigned char *prk,
@@ -222,7 +227,7 @@ static int test_secret(SSL *s, unsigned char *prk,
        return 0;
        return 0;
    }
    }


    if (!tls13_derive_key(s, gensecret, key, KEYLEN)) {
    if (!tls13_derive_key(s, md, gensecret, key, KEYLEN)) {
        fprintf(stderr, "Key generation failed\n");
        fprintf(stderr, "Key generation failed\n");
        return 0;
        return 0;
    }
    }
@@ -232,7 +237,7 @@ static int test_secret(SSL *s, unsigned char *prk,
        return 0;
        return 0;
    }
    }


    if (!tls13_derive_iv(s, gensecret, iv, IVLEN)) {
    if (!tls13_derive_iv(s, md, gensecret, iv, IVLEN)) {
        fprintf(stderr, "IV generation failed\n");
        fprintf(stderr, "IV generation failed\n");
        return 0;
        return 0;
    }
    }