[openssl-commits] [openssl] master update
Richard Levitte
levitte at openssl.org
Mon Jan 23 16:09:10 UTC 2017
The branch master has been updated
via 2f5f49d146a0baef81c7562be29a6a71f894f336 (commit)
via 6acdd3e531e52173a0c76490c0aae3ecebe04a89 (commit)
via 2faa1b48fd6864f6bb8f992fd638378202fdd416 (commit)
from ea24bb0ac5afee1cb7807752a674cb8a858545db (commit)
- Log -----------------------------------------------------------------
commit 2f5f49d146a0baef81c7562be29a6a71f894f336
Author: Cory Benfield <lukasaoz at gmail.com>
Date: Fri Jan 20 16:22:49 2017 +0000
Add documentation for the key logging callbacks
Reviewed-by: Rich Salz <rsalz at openssl.org>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1646)
commit 6acdd3e531e52173a0c76490c0aae3ecebe04a89
Author: Cory Benfield <lukasaoz at gmail.com>
Date: Fri Jan 20 16:22:39 2017 +0000
Add tests for the key logging callbacks.
Reviewed-by: Rich Salz <rsalz at openssl.org>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1646)
commit 2faa1b48fd6864f6bb8f992fd638378202fdd416
Author: Cory Benfield <lukasaoz at gmail.com>
Date: Fri Jan 20 16:22:30 2017 +0000
Add support for key logging callbacks.
Reviewed-by: Rich Salz <rsalz at openssl.org>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/1646)
-----------------------------------------------------------------------
Summary of changes:
doc/man3/SSL_CTX_set_keylog_callback.pod | 48 +++++
include/openssl/ssl.h | 22 ++
ssl/ssl_err.c | 6 +-
ssl/ssl_lib.c | 111 ++++++++++
ssl/ssl_locl.h | 26 +++
ssl/statem/statem_clnt.c | 6 +-
ssl/statem/statem_lib.c | 6 +
test/sslapitest.c | 342 +++++++++++++++++++++++++++++++
util/libssl.num | 2 +
9 files changed, 567 insertions(+), 2 deletions(-)
create mode 100644 doc/man3/SSL_CTX_set_keylog_callback.pod
diff --git a/doc/man3/SSL_CTX_set_keylog_callback.pod b/doc/man3/SSL_CTX_set_keylog_callback.pod
new file mode 100644
index 0000000..abe45ae
--- /dev/null
+++ b/doc/man3/SSL_CTX_set_keylog_callback.pod
@@ -0,0 +1,48 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_keylog_callback, SSL_CTX_get_keylog_callback,
+SSL_CTX_keylog_cb_func - logging TLS key material
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);
+
+ void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);
+ SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set_keylog_callback() sets the TLS key logging callback. This callback
+is called whenever TLS key material is generated or received, in order to allow
+applications to store this keying material for debugging purposes.
+
+SSL_CTX_get_keylog_callback() retrieves the previously set TLS key logging
+callback. If no callback has been set, this will return NULL. When there is no
+key logging callback, or if SSL_CTX_set_keylog_callback is called with NULL as
+the value of cb, no logging of key material will be done.
+
+The key logging callback is called with two items: the B<ssl> object associated
+with the connection, and B<line>, a string containing the key material in the
+format used by NSS for its B<SSLKEYLOGFILE> debugging output. To recreate that
+file, the key logging callback should log B<line>, followed by a newline.
+B<line> will always be a NULL-terminated string.
+
+
+=head1 SEE ALSO
+
+L<ssl(3)>
+
+=head1 COPYRIGHT
+
+Copyright 2016-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
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 2f6d59a..86ffcb9 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -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
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 79cbf2e..d380c86 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/*
* 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),
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 21ea284..fe17f3d 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -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);
+}
+
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 10ae54c..27bfd9e 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -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,
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 5eec0d1..80ae480 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -2258,7 +2258,7 @@ int tls_process_cert_status_body(SSL *s, PACKET *pkt, int *al)
return 1;
}
-
+
MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
{
@@ -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);
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 03efdec..905a2cc 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -427,6 +427,12 @@ int tls_construct_finished(SSL *s, WPACKET *pkt)
goto err;
}
+ /* Log the master secret, if logging is enabled. */
+ if (!ssl_log_master_secret(s, s->s3->client_random, SSL3_RANDOM_SIZE,
+ s->session->master_key,
+ s->session->master_key_length))
+ return 0;
+
/*
* Copy the finished so we can use it for renegotiation checks
*/
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 4a84f4d..ac065b2 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -23,6 +23,13 @@
static char *cert = NULL;
static char *privkey = NULL;
+#define LOG_BUFFER_SIZE 1024
+static char server_log_buffer[LOG_BUFFER_SIZE + 1] = {0};
+static int server_log_buffer_index = 0;
+static char client_log_buffer[LOG_BUFFER_SIZE + 1] = {0};
+static int client_log_buffer_index = 0;
+static int error_writing_log = 0;
+
#ifndef OPENSSL_NO_OCSP
static const unsigned char orespder[] = "Dummy OCSP Response";
static int ocsp_server_called = 0;
@@ -34,6 +41,337 @@ static X509 *ocspcert = NULL;
#define NUM_EXTRA_CERTS 40
+static void client_keylog_callback(const SSL *ssl, const char *line) {
+ int line_length = strlen(line);
+
+ /* If the log doesn't fit, error out. */
+ if ((client_log_buffer_index + line_length) > LOG_BUFFER_SIZE) {
+ printf("No room in client log\n");
+ error_writing_log = 1;
+ return;
+ }
+
+ strcat(client_log_buffer, line);
+ client_log_buffer_index += line_length;
+ client_log_buffer[client_log_buffer_index] = '\n';
+ client_log_buffer_index += 1;
+
+ return;
+}
+
+static void server_keylog_callback(const SSL *ssl, const char *line) {
+ int line_length = strlen(line);
+
+ /* If the log doesn't fit, error out. */
+ if ((server_log_buffer_index + line_length) > LOG_BUFFER_SIZE) {
+ printf("No room in server log\n");
+ error_writing_log = 1;
+ return;
+ }
+
+ strcat(server_log_buffer, line);
+ server_log_buffer_index += line_length;
+ server_log_buffer[server_log_buffer_index] = '\n';
+ server_log_buffer_index += 1;
+
+ return;
+}
+
+static int compare_hex_encoded_buffer(const char *hex_encoded,
+ size_t hex_length,
+ const uint8_t *raw,
+ size_t raw_length) {
+ size_t i;
+ size_t j;
+
+ /* One byte too big, just to be safe. */
+ char hexed[3] = {0};
+
+ if ((raw_length * 2) != hex_length) {
+ printf("Inconsistent hex encoded lengths.\n");
+ return 1;
+ }
+
+ for (i = j = 0; (i < raw_length) && ((j + 1) < hex_length); i++) {
+ sprintf(hexed, "%02x", raw[i]);
+ if ((hexed[0] != hex_encoded[j]) || (hexed[1] != hex_encoded[j + 1])) {
+ printf("Hex output does not match.\n");
+ return 1;
+ }
+ j += 2;
+ }
+
+ return 0;
+}
+
+static int test_keylog_output(char *buffer, const SSL *ssl,
+ const SSL_SESSION *session) {
+ int saw_client_random = 0;
+ char *token = NULL;
+ unsigned char actual_client_random[SSL3_RANDOM_SIZE] = {0};
+ size_t client_random_size = SSL3_RANDOM_SIZE;
+ unsigned char actual_master_key[SSL_MAX_MASTER_KEY_LENGTH] = {0};
+ size_t master_key_size = SSL_MAX_MASTER_KEY_LENGTH;
+
+ token = strtok(buffer, " \n");
+ while (token) {
+ if (strcmp(token, "RSA") == 0) {
+ /* Premaster secret. Tokens should be: 16 ASCII bytes of
+ * hex-encoded encrypted secret, then the hex-encoded pre-master
+ * secret.
+ */
+ token = strtok(NULL, " \n");
+ if (!token) {
+ printf("Unexpectedly short premaster secret log.\n");
+ return -1;
+ }
+ if (strlen(token) != 16) {
+ printf("Bad value for encrypted secret: %s\n", token);
+ return -1;
+ }
+ token = strtok(NULL, " \n");
+ if (!token) {
+ printf("Unexpectedly short premaster secret log.\n");
+ return -1;
+ }
+ /* TODO: Can I check this sensibly? */
+ } else if (strcmp(token, "CLIENT_RANDOM") == 0) {
+ /* Master secret. Tokens should be: 64 ASCII bytes of hex-encoded
+ * client random, then the hex-encoded master secret.
+ */
+ client_random_size = SSL_get_client_random(ssl,
+ actual_client_random,
+ SSL3_RANDOM_SIZE);
+ if (client_random_size != SSL3_RANDOM_SIZE) {
+ printf("Unexpected short client random.\n");
+ return -1;
+ }
+
+ token = strtok(NULL, " \n");
+ if (!token) {
+ printf("Unexpected short master secret log.\n");
+ return -1;
+ }
+ if (strlen(token) != 64) {
+ printf("Bad value for client random: %s\n", token);
+ return -1;
+ }
+ if (compare_hex_encoded_buffer(token, 64, actual_client_random,
+ client_random_size)) {
+ printf("Bad value for client random: %s\n", token);
+ return -1;
+ }
+
+ token = strtok(NULL, " \n");
+ if (!token) {
+ printf("Unexpectedly short master secret log.\n");
+ return -1;
+ }
+
+ master_key_size = SSL_SESSION_get_master_key(session,
+ actual_master_key,
+ master_key_size);
+ if (!master_key_size) {
+ printf("Error getting master key to compare.\n");
+ return -1;
+ }
+ if (compare_hex_encoded_buffer(token, strlen(token),
+ actual_master_key,
+ master_key_size)) {
+ printf("Bad value for master key: %s\n", token);
+ return -1;
+ }
+
+ saw_client_random = 1;
+ } else {
+ printf("Unexpected token in buffer: %s\n", token);
+ return -1;
+ }
+
+ token = strtok(NULL, " \n");
+ }
+
+ return saw_client_random;
+}
+
+static int test_keylog(void) {
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+
+ /* Clean up logging space */
+ memset(client_log_buffer, 0, LOG_BUFFER_SIZE + 1);
+ memset(server_log_buffer, 0, LOG_BUFFER_SIZE + 1);
+ client_log_buffer_index = 0;
+ server_log_buffer_index = 0;
+ error_writing_log = 0;
+
+ if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx,
+ &cctx, cert, privkey)) {
+ printf("Unable to create SSL_CTX pair\n");
+ return 0;
+ }
+
+ /* We cannot log the master secret for TLSv1.3, so we should forbid it. */
+ SSL_CTX_set_options(cctx, SSL_OP_NO_TLSv1_3);
+ SSL_CTX_set_options(sctx, SSL_OP_NO_TLSv1_3);
+
+ if (SSL_CTX_get_keylog_callback(cctx)) {
+ printf("Unexpected initial value for client "
+ "SSL_CTX_get_keylog_callback()\n");
+ goto end;
+ }
+ if (SSL_CTX_get_keylog_callback(sctx)) {
+ printf("Unexpected initial value for server "
+ "SSL_CTX_get_keylog_callback()\n");
+ goto end;
+ }
+
+ SSL_CTX_set_keylog_callback(cctx, client_keylog_callback);
+ SSL_CTX_set_keylog_callback(sctx, server_keylog_callback);
+
+ if (SSL_CTX_get_keylog_callback(cctx) != client_keylog_callback) {
+ printf("Unexpected set value for client "
+ "SSL_CTX_get_keylog_callback()\n");
+ }
+
+ if (SSL_CTX_get_keylog_callback(sctx) != server_keylog_callback) {
+ printf("Unexpected set value for server "
+ "SSL_CTX_get_keylog_callback()\n");
+ }
+
+ /* Now do a handshake and check that the logs have been written to. */
+ if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
+ printf("Unable to create SSL objects\n");
+ goto end;
+ }
+
+ if (!create_ssl_connection(serverssl, clientssl)) {
+ printf("Unable to create SSL connection\n");
+ goto end;
+ }
+
+ if (error_writing_log) {
+ printf("Error encountered while logging\n");
+ goto end;
+ }
+
+ if ((client_log_buffer_index == 0) || (server_log_buffer_index == 0)) {
+ printf("No logs written\n");
+ goto end;
+ }
+
+ /* Now we want to test that our output data was vaguely sensible. We
+ * do that by using strtok and confirming that we have more or less the
+ * data we expect.
+ */
+ if (test_keylog_output(client_log_buffer, clientssl,
+ SSL_get_session(clientssl)) != 1) {
+ printf("Error encountered in client log buffer\n");
+ goto end;
+ }
+ if (test_keylog_output(server_log_buffer, serverssl,
+ SSL_get_session(serverssl)) != 1) {
+ printf("Error encountered in server log buffer\n");
+ goto end;
+ }
+
+ testresult = 1;
+
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+
+#ifndef OPENSSL_NO_TLS1_3
+static int test_keylog_no_master_key(void) {
+ SSL_CTX *cctx = NULL, *sctx = NULL;
+ SSL *clientssl = NULL, *serverssl = NULL;
+ int testresult = 0;
+
+ /* Clean up logging space */
+ memset(client_log_buffer, 0, LOG_BUFFER_SIZE + 1);
+ memset(server_log_buffer, 0, LOG_BUFFER_SIZE + 1);
+ client_log_buffer_index = 0;
+ server_log_buffer_index = 0;
+ error_writing_log = 0;
+
+ if (!create_ssl_ctx_pair(TLS_server_method(), TLS_client_method(), &sctx,
+ &cctx, cert, privkey)) {
+ printf("Unable to create SSL_CTX pair\n");
+ return 0;
+ }
+
+ if (SSL_CTX_get_keylog_callback(cctx)) {
+ printf("Unexpected initial value for client "
+ "SSL_CTX_get_keylog_callback()\n");
+ goto end;
+ }
+ if (SSL_CTX_get_keylog_callback(sctx)) {
+ printf("Unexpected initial value for server "
+ "SSL_CTX_get_keylog_callback()\n");
+ goto end;
+ }
+
+ SSL_CTX_set_keylog_callback(cctx, client_keylog_callback);
+ SSL_CTX_set_keylog_callback(sctx, server_keylog_callback);
+
+ if (SSL_CTX_get_keylog_callback(cctx) != client_keylog_callback) {
+ printf("Unexpected set value for client "
+ "SSL_CTX_get_keylog_callback()\n");
+ }
+
+ if (SSL_CTX_get_keylog_callback(sctx) != server_keylog_callback) {
+ printf("Unexpected set value for server "
+ "SSL_CTX_get_keylog_callback()\n");
+ }
+
+ /* Now do a handshake and check that the logs have been written to. */
+ if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
+ printf("Unable to create SSL objects\n");
+ goto end;
+ }
+
+ if (!create_ssl_connection(serverssl, clientssl)) {
+ printf("Unable to create SSL connection\n");
+ goto end;
+ }
+
+ if (error_writing_log) {
+ printf("Error encountered while logging\n");
+ goto end;
+ }
+
+ /* Now we want to test that our output data was vaguely sensible. For this
+ * test, we expect no CLIENT_RANDOM entry.
+ */
+ if (test_keylog_output(client_log_buffer, clientssl,
+ SSL_get_session(clientssl)) != 0) {
+ printf("Error encountered in client log buffer\n");
+ goto end;
+ }
+ if (test_keylog_output(server_log_buffer, serverssl,
+ SSL_get_session(serverssl)) != 0) {
+ printf("Error encountered in server log buffer\n");
+ goto end;
+ }
+
+ testresult = 1;
+
+end:
+ SSL_free(serverssl);
+ SSL_free(clientssl);
+ SSL_CTX_free(sctx);
+ SSL_CTX_free(cctx);
+
+ return testresult;
+}
+#endif
+
static int execute_test_large_message(const SSL_METHOD *smeth,
const SSL_METHOD *cmeth, int read_ahead)
{
@@ -1044,6 +1382,10 @@ int test_main(int argc, char *argv[])
ADD_TEST(test_ssl_bio_change_rbio);
ADD_TEST(test_ssl_bio_change_wbio);
ADD_ALL_TESTS(test_set_sigalgs, OSSL_NELEM(testsigalgs) * 2);
+ ADD_TEST(test_keylog);
+#ifndef OPENSSL_NO_TLS1_3
+ ADD_TEST(test_keylog_no_master_key);
+#endif
testresult = run_tests(argv[0]);
diff --git a/util/libssl.num b/util/libssl.num
index 730cff1..94def68 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -410,3 +410,5 @@ SSL_peek_ex 410 1_1_1 EXIST::FUNCTION:
SSL_write_ex 411 1_1_1 EXIST::FUNCTION:
SSL_COMP_get_id 412 1_1_0d EXIST::FUNCTION:
SSL_COMP_get0_name 413 1_1_0d EXIST::FUNCTION:
+SSL_CTX_set_keylog_callback 414 1_1_1 EXIST::FUNCTION:
+SSL_CTX_get_keylog_callback 415 1_1_1 EXIST::FUNCTION:
More information about the openssl-commits
mailing list