Commit 2faa1b48 authored by Cory Benfield's avatar Cory Benfield Committed by Richard Levitte
Browse files

Add support for key logging callbacks.

parent ea24bb0a
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -775,6 +775,25 @@ __owur int SSL_extension_supported(unsigned int ext_type);
# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2

/*
 * A callback for logging out TLS key material. This callback should log out
 * |line| followed by a newline.
 */
typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);

/*
 * SSL_CTX_set_keylog_callback configures a callback to log key material. This
 * is intended for debugging use with tools like Wireshark. The cb function
 * should log line followed by a newline.
 */
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);

/*
 * SSL_CTX_get_keylog_callback returns the callback configured by
 * SSL_CTX_set_keylog_callback.
 */
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);

#ifdef __cplusplus
}
#endif
@@ -2079,6 +2098,7 @@ int ERR_load_SSL_strings(void);
# define SSL_F_FINAL_EMS                                  486
# define SSL_F_FINAL_RENEGOTIATE                          483
# define SSL_F_FINAL_SIG_ALGS                             497
# define SSL_F_NSS_KEYLOG_INT                             500
# define SSL_F_OPENSSL_INIT_SSL                           342
# define SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION       436
# define SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE       430
@@ -2170,6 +2190,8 @@ int ERR_load_SSL_strings(void);
# define SSL_F_SSL_GET_SIGN_PKEY                          183
# define SSL_F_SSL_INIT_WBIO_BUFFER                       184
# define SSL_F_SSL_LOAD_CLIENT_CA_FILE                    185
# define SSL_F_SSL_LOG_MASTER_SECRET                      498
# define SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE            499
# define SSL_F_SSL_MODULE_INIT                            392
# define SSL_F_SSL_NEW                                    186
# define SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT      300
+5 −1
Original line number Diff line number Diff line
/*
 * Generated by util/mkerr.pl DO NOT EDIT
 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright 1995-2017 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
@@ -53,6 +53,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
    {ERR_FUNC(SSL_F_FINAL_EMS), "final_ems"},
    {ERR_FUNC(SSL_F_FINAL_RENEGOTIATE), "final_renegotiate"},
    {ERR_FUNC(SSL_F_FINAL_SIG_ALGS), "final_sig_algs"},
    {ERR_FUNC(SSL_F_NSS_KEYLOG_INT), "nss_keylog_int"},
    {ERR_FUNC(SSL_F_OPENSSL_INIT_SSL), "OPENSSL_init_ssl"},
    {ERR_FUNC(SSL_F_OSSL_STATEM_CLIENT13_READ_TRANSITION),
     "ossl_statem_client13_read_transition"},
@@ -177,6 +178,9 @@ static ERR_STRING_DATA SSL_str_functs[] = {
    {ERR_FUNC(SSL_F_SSL_GET_SIGN_PKEY), "ssl_get_sign_pkey"},
    {ERR_FUNC(SSL_F_SSL_INIT_WBIO_BUFFER), "ssl_init_wbio_buffer"},
    {ERR_FUNC(SSL_F_SSL_LOAD_CLIENT_CA_FILE), "SSL_load_client_CA_file"},
    {ERR_FUNC(SSL_F_SSL_LOG_MASTER_SECRET), "ssl_log_master_secret"},
    {ERR_FUNC(SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE),
     "ssl_log_rsa_client_key_exchange"},
    {ERR_FUNC(SSL_F_SSL_MODULE_INIT), "ssl_module_init"},
    {ERR_FUNC(SSL_F_SSL_NEW), "SSL_new"},
    {ERR_FUNC(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT),
+111 −0
Original line number Diff line number Diff line
@@ -4344,3 +4344,114 @@ const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx)
}

#endif

void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb)
{
    ctx->keylog_callback = cb;
}

SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx)
{
    return ctx->keylog_callback;
}

static int nss_keylog_int(const char *prefix,
                          SSL *ssl,
                          const uint8_t *parameter_1,
                          size_t parameter_1_len,
                          const uint8_t *parameter_2,
                          size_t parameter_2_len)
{
    char *out = NULL;
    char *cursor = NULL;
    size_t out_len = 0;
    size_t i;
    size_t prefix_len;

    if (ssl->ctx->keylog_callback == NULL) return 1;

    /*
     * Our output buffer will contain the following strings, rendered with
     * space characters in between, terminated by a NULL character: first the
     * prefix, then the first parameter, then the second parameter. The
     * meaning of each parameter depends on the specific key material being
     * logged. Note that the first and second parameters are encoded in
     * hexadecimal, so we need a buffer that is twice their lengths.
     */
    prefix_len = strlen(prefix);
    out_len = prefix_len + (2*parameter_1_len) + (2*parameter_2_len) + 3;
    if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) {
        SSLerr(SSL_F_NSS_KEYLOG_INT, ERR_R_MALLOC_FAILURE);
        return 0;
    }

    strcpy(cursor, prefix);
    cursor += prefix_len;
    *cursor++ = ' ';

    for (i = 0; i < parameter_1_len; i++) {
        sprintf(cursor, "%02x", parameter_1[i]);
        cursor += 2;
    }
    *cursor++ = ' ';

    for (i = 0; i < parameter_2_len; i++) {
        sprintf(cursor, "%02x", parameter_2[i]);
        cursor += 2;
    }
    *cursor = '\0';

    ssl->ctx->keylog_callback(ssl, (const char *)out);
    OPENSSL_free(out);
    return 1;

}

int ssl_log_rsa_client_key_exchange(SSL *ssl,
                                    const uint8_t *encrypted_premaster,
                                    size_t encrypted_premaster_len,
                                    const uint8_t *premaster,
                                    size_t premaster_len)
{
    if (encrypted_premaster_len < 8) {
        SSLerr(SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return nss_keylog_int("RSA",
                          ssl,
                          encrypted_premaster,
                          encrypted_premaster_len,
                          premaster,
                          premaster_len);
}

int ssl_log_master_secret(SSL *ssl,
                          const uint8_t *client_random,
                          size_t client_random_len,
                          const uint8_t *master,
                          size_t master_len)
{
    /*
     * TLSv1.3 changes the derivation of the master secret compared to earlier
     * TLS versions, meaning that logging it out is less useful. Instead we
     * want to log out other secrets: specifically, the handshake and
     * application traffic secrets. For this reason, if this function is called
     * for TLSv1.3 we don't bother logging, and just return success
     * immediately.
     */
    if (SSL_IS_TLS13(ssl)) return 1;

    if (client_random_len != 32) {
        SSLerr(SSL_F_SSL_LOG_MASTER_SECRET, ERR_R_INTERNAL_ERROR);
        return 0;
    }

    return nss_keylog_int("CLIENT_RANDOM",
                          ssl,
                          client_random,
                          client_random_len,
                          master,
                          master_len);
}
+26 −0
Original line number Diff line number Diff line
@@ -875,6 +875,12 @@ struct ssl_ctx_st {
    int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);

    CRYPTO_RWLOCK *lock;

    /*
     * Callback for logging key material for use with debugging tools like
     * Wireshark. The callback should log `line` followed by a newline.
     */
    SSL_CTX_keylog_cb_func keylog_callback;
};

struct ssl_st {
@@ -2194,6 +2200,26 @@ __owur const EVP_MD *ssl_md(int idx);
__owur const EVP_MD *ssl_handshake_md(SSL *s);
__owur const EVP_MD *ssl_prf_md(SSL *s);

/*
 * ssl_log_rsa_client_key_exchange logs |premaster| to the SSL_CTX associated
 * with |ssl|, if logging is enabled. It returns one on success and zero on
 * failure. The entry is identified by the first 8 bytes of
 * |encrypted_premaster|.
 */
__owur int ssl_log_rsa_client_key_exchange(SSL *ssl,
                                           const uint8_t *encrypted_premaster,
                                           size_t encrypted_premaster_len,
                                           const uint8_t *premaster,
                                           size_t premaster_len);

/* ssl_log_master_secret logs |master| to the SSL_CTX associated with |ssl|, if
 * logging is enabled. It returns one on success and zero on failure. The entry
 * is identified by |client_random|.
 */
__owur int ssl_log_master_secret(SSL *ssl, const uint8_t *client_random,
                                 size_t client_random_len,
                                 const uint8_t *master, size_t master_len);

/* s3_cbc.c */
__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
__owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
+5 −1
Original line number Diff line number Diff line
@@ -2522,6 +2522,10 @@ static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt, int *al)
    s->s3->tmp.pms = pms;
    s->s3->tmp.pmslen = pmslen;

    /* Log the premaster secret, if logging is enabled. */
    if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen))
        goto err;

    return 1;
 err:
    OPENSSL_clear_free(pms, pmslen);
Loading