From 5df0f7820a9cb9651f7d38cef6e19648e166fcc6 Mon Sep 17 00:00:00 2001 From: TakayukiMatsuo Date: Mon, 22 Feb 2021 16:33:18 +0900 Subject: [PATCH] Add wolfSSL_CTX_set_keylog_callback --- Makefile.am | 3 +- src/internal.c | 239 +++++++++++ src/ssl.c | 33 +- src/tls13.c | 66 ++- tests/api.c | 904 +++++++++++++++++++++++++++++------------- wolfssl/internal.h | 9 + wolfssl/openssl/evp.h | 8 +- wolfssl/openssl/ssl.h | 4 + wolfssl/ssl.h | 9 + 9 files changed, 996 insertions(+), 279 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2ed2fb6a3..617e45c46 100644 --- a/Makefile.am +++ b/Makefile.am @@ -125,7 +125,8 @@ CLEANFILES+= ecc-key.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der \ pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der \ - tests/test-log-dump-to-file.txt + tests/test-log-dump-to-file.txt \ + MyKeyLog.txt exampledir = $(docdir)/example dist_example_DATA= diff --git a/src/internal.c b/src/internal.c index af6d4cab3..add5b0463 100644 --- a/src/internal.c +++ b/src/internal.c @@ -84,6 +84,9 @@ #include #endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + #include +#endif #ifdef HAVE_LIBZ #include "zlib.h" #endif @@ -224,6 +227,225 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int tsip_generatePremasterSecret(); int tsip_generateEncryptPreMasterSecret(WOLFSSL *ssl, byte *out, word32 *outSz); #endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + + static int SessionSecret_callback(WOLFSSL* ssl, void* secret, + int* secretSz, void* ctx); + static int SessionSecret_callback_Tls13(WOLFSSL* ssl, int id, + const unsigned char* secret, int secretSz, void* ctx); + + /* + * This function builds up string for key-logging then call user's + * key-log-callback to pass the string for TLS1.2 and older. + * The user's key-logging callback has been set via + * wolfSSL_CTX_set_keylog_callback function. The logging string format is: + * "CLIENT_RANDOM " + * parameter + * - ssl: WOLFSSL object + * - secret: pointer to the buffer holding master-secret + * - secretSz: size of secret + * - ctx: not used + * returns 0 on success, negative value on failure. + */ + static int SessionSecret_callback(WOLFSSL* ssl, void* secret, + int* secretSz, void* ctx) + { + wolfSSL_CTX_keylog_cb_func logCb = NULL; + int msSz; + int hasVal; + int i; + const char* label = "CLIENT_RANDOM"; + int labelSz = sizeof("CLIENT_RANDOM"); + int buffSz; + byte* log = NULL; + word32 outSz; + int idx; + int ret; + (void)ctx; + + if (ssl == NULL || secret == NULL || *secretSz == 0) + return BAD_FUNC_ARG; + if (ssl->arrays == NULL) + return BAD_FUNC_ARG; + + /* get the user-callback func from CTX*/ + logCb = ssl->ctx->keyLogCb; + if (logCb == NULL) + return 0; + + /* need to make sure the given master-secret has a meaningful value */ + msSz = *secretSz; + hasVal = 0; + for (i = 0; i < msSz; i++) { + if (*((byte*)secret) != 0) { + hasVal = 1; + break; + } + } + if (hasVal == 0) + return 0; /* master-secret looks invalid */ + + /* build up a hex-decoded keylog string + "CLIENT_RANDOM " + note that each keylog string does not have LF. + */ + buffSz = labelSz + (RAN_LEN * 2) + 1 + ((*secretSz) * 2) + 1; + log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET); + + if (log == NULL) + return MEMORY_E; + + XMEMSET(log, 0, buffSz); + XMEMCPY(log, label, labelSz -1); /* put label w/o terminator */ + XMEMSET(log + labelSz - 1, ' ', 1); /* '\0' -> ' ' */ + idx = labelSz; + outSz = buffSz - idx; + if ((ret = Base16_Encode(ssl->arrays->clientRandom, RAN_LEN, + log + idx, &outSz)) == 0) { + idx += (outSz - 1); /* reduce terminator byte */ + outSz = buffSz - idx; + + if (outSz > 1) { + XMEMSET(log + idx, ' ', 1); /* add space*/ + idx++; + outSz = buffSz - idx; + + if ((ret = Base16_Encode((byte*)secret, *secretSz, + log + idx, &outSz)) == 0) { + /* pass the log to the client callback*/ + logCb(ssl, (char*)log); + ret = 0; + } + } + else + ret = MEMORY_E; + } + XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET); + return ret; + } +#if defined(WOLFSSL_TLS13) + /* + * This function builds up string for key-logging then call user's + * key-log-callback to pass the string for TLS1.3. + * The user's key-logging callback has been set via + * wolfSSL_CTX_set_keylog_callback function. The logging string format is: + * " " + * + * parameter + * - ssl: WOLFSSL object + * - id: type of secret for logging + * - secret: pointer to the buffer holding secret + * - secretSz: size of secret + * - ctx: not used + * returns 0 on success, negative value on failure. + */ + static int SessionSecret_callback_Tls13(WOLFSSL* ssl, int id, + const unsigned char* secret, int secretSz, void* ctx) + { + wolfSSL_CTX_keylog_cb_func logCb = NULL; + char label[50]; + int labelSz = 0; + int buffSz = 0; + byte* log = NULL; + word32 outSz; + int idx; + int ret; + + (void)ctx; + + if (ssl == NULL || secret == NULL || secretSz == 0) + return BAD_FUNC_ARG; + if (ssl->arrays == NULL) + return BAD_FUNC_ARG; + + /* get the user-callback func from CTX*/ + logCb = ssl->ctx->keyLogCb; + if (logCb == NULL) + return 0; + + switch (id) { + case CLIENT_EARLY_TRAFFIC_SECRET: + + labelSz = sizeof("CLIENT_EARLY_TRAFFIC_SECRET"); + XSTRNCPY(label,"CLIENT_EARLY_TRAFFIC_SECRET", labelSz); + break; + + case CLIENT_HANDSHAKE_TRAFFIC_SECRET: + + labelSz = sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET"); + XSTRNCPY(label, "CLIENT_HANDSHAKE_TRAFFIC_SECRET", labelSz); + break; + + case SERVER_HANDSHAKE_TRAFFIC_SECRET: + + labelSz = sizeof("SERVER_HANDSHAKE_TRAFFIC_SECRET"); + XSTRNCPY(label, "SERVER_HANDSHAKE_TRAFFIC_SECRET", labelSz); + break; + + case CLIENT_TRAFFIC_SECRET: + + labelSz = sizeof("CLIENT_TRAFFIC_SECRET_0"); + XSTRNCPY(label, "CLIENT_TRAFFIC_SECRET_0", labelSz); + break; + + case SERVER_TRAFFIC_SECRET: + + labelSz = sizeof("SERVER_TRAFFIC_SECRET_0"); + XSTRNCPY(label, "SERVER_TRAFFIC_SECRET_0", labelSz); + break; + + case EARLY_EXPORTER_SECRET: + + labelSz = sizeof("EARLY_EXPORTER_SECRET"); + XSTRNCPY(label, "EARLY_EXPORTER_SECRET", labelSz); + break; + + case EXPORTER_SECRET: + + labelSz = sizeof("EXPORTER_SECRET"); + XSTRNCPY(label, "EXPORTER_SECRET", labelSz); + break; + + default: + return BAD_FUNC_ARG; + } + /* prepare a log string for passing user callback */ + buffSz = labelSz + (RAN_LEN * 2) + 1 + secretSz * 2 + 1; + log = XMALLOC(buffSz, ssl->heap, DYNAMIC_TYPE_SECRET); + if (log == NULL) + return MEMORY_E; + + XMEMSET(log, 0, buffSz); + XMEMCPY(log, label, labelSz - 1); /* put label w/o terminator */ + XMEMSET(log + labelSz - 1, ' ', 1); /* '\0' -> ' ' */ + + idx = labelSz; + outSz = buffSz - idx; + if ((ret = Base16_Encode(ssl->arrays->clientRandom, RAN_LEN, + log + idx, &outSz)) == 0) { + idx += (outSz -1); /* reduce terminator byte */ + outSz = buffSz - idx; + + if (outSz >1) { + XMEMSET(log + idx, ' ', 1); /* add space*/ + idx++; + outSz = buffSz - idx; + + if ((ret = Base16_Encode((byte*)secret, secretSz, + log + idx, &outSz)) == 0) { + logCb(ssl, (char*)log); + ret = 0; + } + } + else + ret = MEMORY_E; + } + XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET); + return ret; + } +#endif /* WOLFSSL_TLS13*/ +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK*/ + int IsTLS(const WOLFSSL* ssl) { if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR) @@ -6135,6 +6357,14 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->tls13SecretCtx = NULL; #endif #endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + if (ctx->keyLogCb != NULL) { + ssl->keyLogCb = SessionSecret_callback; +#if defined(WOLFSSL_TLS13) + ssl->tls13KeyLogCb = SessionSecret_callback_Tls13; +#endif /*WOLFSSL_TLS13*/ + } +#endif /*OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ #ifdef HAVE_SESSION_TICKET ssl->options.noTicketTls12 = ctx->noTicketTls12; @@ -25389,6 +25619,15 @@ int SendClientKeyExchange(WOLFSSL* ssl) } ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; } + #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + if (ssl->keyLogCb != NULL) { + int secretSz = SECRET_LEN; + ret = ssl->keyLogCb(ssl, ssl->arrays->masterSecret, &secretSz, + NULL); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } + #endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ break; } default: diff --git a/src/ssl.c b/src/ssl.c index 6d31307fe..ee693d0f0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -43754,7 +43754,11 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) #endif /* OPENSSL_EXTRA */ -#if defined(HAVE_EX_DATA) || defined(FORTRESS) || defined(WOLFSSL_WPAS_SMALL) +#if defined(HAVE_EX_DATA) && \ + (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(HAVE_LIGHTY)) || defined(HAVE_EX_DATA) || defined(FORTRESS) || \ + defined(WOLFSSL_WPAS_SMALL) /** * get_ex_new_index is a helper function for the following * xx_get_ex_new_index functions: @@ -49559,7 +49563,6 @@ int oid2nid(word32 oid, int grp) return -1; } - /* when calling SetIndividualInternal, mpi should be cleared by caller if no * longer used. ie mp_free(mpi). This is to free data when fastmath is * disabled since a copy of mpi is made by this function and placed into bn. @@ -51993,6 +51996,7 @@ void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); /* bn = NULL, don't try to access or double free it */ } + } void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) @@ -53958,6 +53962,31 @@ int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value) return ret; } +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) +/* + * This API accepts a user callback which puts key-log records into + * a KEY LOGFILE. The callback is stored into a CTX and propagated to + * each SSL object on its creation timing. + */ +void wolfSSL_CTX_set_keylog_callback(WOLFSSL_CTX* ctx, wolfSSL_CTX_keylog_cb_func cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_keylog_callback"); + /* stores the callback into WOLFSSL_CTX */ + if (ctx != NULL) { + ctx->keyLogCb = cb; + } +} +wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback( + const WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_keylog_callback"); + if (ctx != NULL) + return ctx->keyLogCb; + else + return NULL; +} +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ + /** * Return DH p, q and g parameters * @param dh a pointer to WOLFSSL_DH diff --git a/src/tls13.c b/src/tls13.c index 6d547b9a0..696ba9eb1 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -531,6 +531,15 @@ static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, CLIENT_EARLY_TRAFFIC_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -560,12 +569,21 @@ static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) ssl->specs.mac_algorithm, 1); #ifdef HAVE_SECRET_CALLBACK if (ret == 0 && ssl->tls13SecretCb != NULL) { - ret = ssl->tls13SecretCb(ssl, EARLY_EXPORTER_SECRET, key + ret = ssl->tls13SecretCb(ssl, EARLY_EXPORTER_SECRET, key, ssl->specs.hash_size, ssl->tls13SecretCtx); if (ret != 0) { return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, EARLY_EXPORTER_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -602,6 +620,15 @@ static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, CLIENT_HANDSHAKE_TRAFFIC_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -636,6 +663,15 @@ static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, SERVER_HANDSHAKE_TRAFFIC_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -670,6 +706,15 @@ static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, CLIENT_TRAFFIC_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -704,6 +749,15 @@ static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, SERVER_TRAFFIC_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -739,6 +793,15 @@ static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) return TLS13_SECRET_CB_E; } } +#ifdef OPENSSL_EXTRA + if (ret == 0 && ssl->tls13KeyLogCb != NULL) { + ret = ssl->tls13KeyLogCb(ssl, EXPORTER_SECRET, key, + ssl->specs.hash_size, NULL); + if (ret != 0) { + return TLS13_SECRET_CB_E; + } + } +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_SECRET_CALLBACK */ return ret; } @@ -3852,6 +3915,7 @@ static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) #endif } + #ifndef NO_PSK /* Attempt to find the PSK (not session ticket) that matches. * diff --git a/tests/api.c b/tests/api.c index 659114aa2..d144798fc 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2638,6 +2638,276 @@ static void test_ED448(void) | EVP *----------------------------------------------------------------------------*/ +static void test_wolfSSL_EVP_PKEY_print_public(void) +{ +#if defined(OPENSSL_EXTRA) + + WOLFSSL_BIO* rbio = NULL; + WOLFSSL_BIO* wbio = NULL; + WOLFSSL_EVP_PKEY* pkey = NULL; + char line[256] = { 0 }; + char line1[256] = { 0 }; + int i; + + printf(testingFmt, "EVP_PKEY_print_public()"); + /* test error cases */ + AssertIntEQ( EVP_PKEY_print_public(NULL,NULL,0,NULL),0L); + + /* + * test RSA public key print + * in this test, pass '3' for indent + */ +#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_1024) + + rbio = BIO_new_mem_buf( client_keypub_der_1024, + sizeof_client_keypub_der_1024); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,3,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " RSA Public-Key: (1024 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " Modulus:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " 00:BC:73:0E:A8:49:F3:74:A2:A9:EF:18:A5:DA:55:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* skip to the end of modulus element*/ + for( i = 0; i < 8 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, " Exponent: 65537 (0x010001)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* !NO_RSA && USE_CERT_BUFFERS_1024*/ + + /* + * test DSA public key print + */ +#if !defined(NO_DSA) && defined(USE_CERT_BUFFERS_2048) + rbio = BIO_new_mem_buf( dsa_pub_key_der_2048, + sizeof_dsa_pub_key_der_2048); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "DSA Public-Key: (2048 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "pub:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 00:C2:35:2D:EC:83:83:6C:73:13:9E:52:7C:74:C8:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of pub element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "P:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of P element*/ + for( i = 0; i < 18 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "Q:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of Q element*/ + for( i = 0; i < 3 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "G:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of G element*/ + for( i = 0; i < 18 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* !NO_DSA && USE_CERT_BUFFERS_2048 */ + + /* + * test ECC public key print + */ +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + + rbio = BIO_new_mem_buf( ecc_clikeypub_der_256, + sizeof_ecc_clikeypub_der_256); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "Public-Key: (256 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "pub:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 04:55:BF:F4:0F:44:50:9A:3D:CE:9B:B7:F0:C5:4D:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of pub element*/ + for( i = 0; i < 4 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "ASN1 OID: prime256v1\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "NIST CURVE: P-256\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ + + /* + * test DH public key print + */ +#if defined(WOLFSSL_DH_EXTRA) && defined(USE_CERT_BUFFERS_2048) + + rbio = BIO_new_mem_buf( dh_pub_key_der_2048, + sizeof_dh_pub_key_der_2048); + AssertNotNull(rbio); + + wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); + AssertNotNull(pkey); + + wbio = BIO_new(BIO_s_mem()); + AssertNotNull(wbio); + + AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "DH Public-Key: (2048 bit)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "public-key:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 34:41:BF:E9:F2:11:BF:05:DB:B2:72:A8:29:CC:BD:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of public-key element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "prime:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, + " 00:D3:B2:99:84:5C:0A:4C:E7:37:CC:FC:18:37:01:\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* skip to the end of prime element*/ + for( i = 0; i < 17 ;i++) { + BIO_gets(wbio, line, sizeof(line)); + } + + BIO_gets(wbio, line, sizeof(line)); + strcpy(line1, "generator: 2 (0x02)\n"); + AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); + + /* should reach EOF */ + AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); + + EVP_PKEY_free(pkey); + pkey = NULL; + BIO_free(rbio); + BIO_free(wbio); + rbio = NULL; + wbio = NULL; + +#endif /* WOLFSSL_DH_EXTRA && USE_CERT_BUFFERS_2048 */ + + /* to prevent "unused variable" warning */ + (void)pkey; + (void)wbio; + (void)rbio; + (void)line; + (void)line1; + (void)i; + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} /* Test functions for base64 encode/decode */ static void test_wolfSSL_EVP_ENCODE_CTX_new(void) { @@ -3140,276 +3410,6 @@ static void test_wolfSSL_EVP_DecodeFinal(void) printf(resultFmt, passed); #endif /* OPENSSL && WOLFSSL_BASE_DECODE */ } -static void test_wolfSSL_EVP_PKEY_print_public(void) -{ -#if defined(OPENSSL_EXTRA) - - WOLFSSL_BIO* rbio = NULL; - WOLFSSL_BIO* wbio = NULL; - WOLFSSL_EVP_PKEY* pkey = NULL; - char line[256] = { 0 }; - char line1[256] = { 0 }; - int i; - - printf(testingFmt, "EVP_PKEY_print_public()"); - /* test error cases */ - AssertIntEQ( EVP_PKEY_print_public(NULL,NULL,0,NULL),0L); - - /* - * test RSA public key print - * in this test, pass '3' for indent - */ -#if !defined(NO_RSA) && defined(USE_CERT_BUFFERS_1024) - - rbio = BIO_new_mem_buf( client_keypub_der_1024, - sizeof_client_keypub_der_1024); - AssertNotNull(rbio); - - wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); - AssertNotNull(pkey); - - wbio = BIO_new(BIO_s_mem()); - AssertNotNull(wbio); - - AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,3,NULL),1); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, " RSA Public-Key: (1024 bit)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, " Modulus:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, " 00:BC:73:0E:A8:49:F3:74:A2:A9:EF:18:A5:DA:55:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - - /* skip to the end of modulus element*/ - for( i = 0; i < 8 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, " Exponent: 65537 (0x010001)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - - /* should reach EOF */ - AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); - - EVP_PKEY_free(pkey); - pkey = NULL; - BIO_free(rbio); - BIO_free(wbio); - rbio = NULL; - wbio = NULL; - -#endif /* !NO_RSA && USE_CERT_BUFFERS_1024*/ - - /* - * test DSA public key print - */ -#if !defined(NO_DSA) && defined(USE_CERT_BUFFERS_2048) - rbio = BIO_new_mem_buf( dsa_pub_key_der_2048, - sizeof_dsa_pub_key_der_2048); - AssertNotNull(rbio); - - wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); - AssertNotNull(pkey); - - wbio = BIO_new(BIO_s_mem()); - AssertNotNull(wbio); - - AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "DSA Public-Key: (2048 bit)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "pub:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, - " 00:C2:35:2D:EC:83:83:6C:73:13:9E:52:7C:74:C8:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of pub element*/ - for( i = 0; i < 17 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "P:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of P element*/ - for( i = 0; i < 18 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "Q:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of Q element*/ - for( i = 0; i < 3 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "G:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of G element*/ - for( i = 0; i < 18 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - /* should reach EOF */ - AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); - - EVP_PKEY_free(pkey); - pkey = NULL; - BIO_free(rbio); - BIO_free(wbio); - rbio = NULL; - wbio = NULL; - -#endif /* !NO_DSA && USE_CERT_BUFFERS_2048 */ - - /* - * test ECC public key print - */ -#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) - - rbio = BIO_new_mem_buf( ecc_clikeypub_der_256, - sizeof_ecc_clikeypub_der_256); - AssertNotNull(rbio); - - wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); - AssertNotNull(pkey); - - wbio = BIO_new(BIO_s_mem()); - AssertNotNull(wbio); - - AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "Public-Key: (256 bit)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "pub:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, - " 04:55:BF:F4:0F:44:50:9A:3D:CE:9B:B7:F0:C5:4D:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of pub element*/ - for( i = 0; i < 4 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "ASN1 OID: prime256v1\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "NIST CURVE: P-256\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - - /* should reach EOF */ - AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); - - EVP_PKEY_free(pkey); - pkey = NULL; - BIO_free(rbio); - BIO_free(wbio); - rbio = NULL; - wbio = NULL; - -#endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ - - /* - * test DH public key print - */ -#if defined(WOLFSSL_DH_EXTRA) && defined(USE_CERT_BUFFERS_2048) - - rbio = BIO_new_mem_buf( dh_pub_key_der_2048, - sizeof_dh_pub_key_der_2048); - AssertNotNull(rbio); - - wolfSSL_d2i_PUBKEY_bio(rbio, &pkey); - AssertNotNull(pkey); - - wbio = BIO_new(BIO_s_mem()); - AssertNotNull(wbio); - - AssertIntEQ(EVP_PKEY_print_public(wbio, pkey,0,NULL),1); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "DH Public-Key: (2048 bit)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "public-key:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, - " 34:41:BF:E9:F2:11:BF:05:DB:B2:72:A8:29:CC:BD:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of public-key element*/ - for( i = 0; i < 17 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "prime:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, - " 00:D3:B2:99:84:5C:0A:4C:E7:37:CC:FC:18:37:01:\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* skip to the end of prime element*/ - for( i = 0; i < 17 ;i++) { - BIO_gets(wbio, line, sizeof(line)); - } - - BIO_gets(wbio, line, sizeof(line)); - strcpy(line1, "generator: 2 (0x02)\n"); - AssertIntEQ(XSTRNCMP( line, line1, XSTRLEN(line1)), 0); - - /* should reach EOF */ - AssertIntLE(BIO_gets(wbio, line, sizeof(line)) ,0); - - EVP_PKEY_free(pkey); - pkey = NULL; - BIO_free(rbio); - BIO_free(wbio); - rbio = NULL; - wbio = NULL; - -#endif /* WOLFSSL_DH_EXTRA && USE_CERT_BUFFERS_2048 */ - - /* to prevent "unused variable" warning */ - (void)pkey; - (void)wbio; - (void)rbio; - (void)line; - (void)line1; - (void)i; - printf(resultFmt, passed); -#endif /* OPENSSL_EXTRA */ -} /* Test function for wolfSSL_EVP_get_cipherbynid. */ @@ -30361,6 +30361,364 @@ static void test_wolfSSL_CTX_add_client_CA(void) printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_WOLFSSL_CLIENT */ } +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) +static THREAD_RETURN WOLFSSL_THREAD server_task(void* args) +{ + callback_functions* callbacks = ((func_args*)args)->callbacks; + WOLFSSL_CTX* ctx = wolfSSL_CTX_new(callbacks->method()); + WOLFSSL* ssl = NULL; + SOCKET_T sfd = 0; + SOCKET_T cfd = 0; + word16 port; + char msg[] = "I hear you fa shizzle!"; + int len = (int) XSTRLEN(msg); + char input[1024]; + int idx; + int ret, err = 0; + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + ((func_args*)args)->return_code = TEST_FAIL; + port = ((func_args*)args)->signal->port; + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, svrCertFile, + WOLFSSL_FILETYPE_PEM)); + + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile, + WOLFSSL_FILETYPE_PEM)); + + if (callbacks->ctx_ready) + callbacks->ctx_ready(ctx); + + ssl = wolfSSL_new(ctx); + tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, NULL, NULL); + CloseSocket(sfd); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd)); + + if (callbacks->ssl_ready) + callbacks->ssl_ready(ssl); + + do { + err = 0; /* Reset error */ + ret = wolfSSL_accept(ssl); + if (ret != WOLFSSL_SUCCESS) { + err = wolfSSL_get_error(ssl, 0); + } + } while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E); + + if (ret != WOLFSSL_SUCCESS) { + char buff[WOLFSSL_MAX_ERROR_SZ]; + printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff)); + } + else { + if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) { + input[idx] = 0; + printf("Client message: %s\n", input); + } + + AssertIntEQ(len, wolfSSL_write(ssl, msg, len)); +#ifdef WOLFSSL_TIRTOS + Task_yield(); +#endif + ((func_args*)args)->return_code = TEST_SUCCESS; + } + + if (callbacks->on_result) + callbacks->on_result(ssl); + + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(cfd); + +#ifdef WOLFSSL_TIRTOS + fdCloseSession(Task_self()); +#endif +#ifndef WOLFSSL_TIRTOS + return 0; +#endif +} + +static void keyLog_callback(const WOLFSSL* ssl, const char* line ) +{ + + AssertNotNull(ssl); + AssertNotNull(line); + + XFILE fp; + const byte lf = '\n'; + fp = XFOPEN("./MyKeyLog.txt", "a"); + XFWRITE( line, 1, strlen(line),fp); + XFWRITE( (void*)&lf,1,1,fp); + XFCLOSE(fp); + +} +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ +static void test_wolfSSL_CTX_set_keylog_callback(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + SSL_CTX* ctx; + + printf( testingFmt, "wolfSSL_CTX_set_keylog_callback()"); + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + SSL_CTX_set_keylog_callback(ctx, keyLog_callback ); + SSL_CTX_free(ctx); + SSL_CTX_set_keylog_callback(NULL, NULL); + printf(resultFmt, passed); + +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ +} +static void test_wolfSSL_CTX_get_keylog_callback(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + SSL_CTX* ctx; + + printf( testingFmt, "wolfSSL_CTX_get_keylog_callback()"); + AssertNotNull(ctx = SSL_CTX_new(wolfSSLv23_client_method())); + AssertPtrEq(SSL_CTX_get_keylog_callback(ctx),NULL); + SSL_CTX_set_keylog_callback(ctx, keyLog_callback ); + AssertPtrEq(SSL_CTX_get_keylog_callback(ctx),keyLog_callback); + SSL_CTX_set_keylog_callback(ctx, NULL ); + AssertPtrEq(SSL_CTX_get_keylog_callback(ctx),NULL); + SSL_CTX_free(ctx); + printf(resultFmt, passed); + +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ +} +static void test_wolfSSL_Tls12_Key_Logging_test(void) +{ + #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + /* This test is intended for checking whether keylog callback is called + * in client during TLS handshake between the client and a server. + */ + + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions server_cbf; + callback_functions client_cbf; + SOCKET_T sockfd = 0; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + XFILE fp; + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int msgSz = (int)XSTRLEN(msg); + + printf(testingFmt, "wolfSSL_Tls12_Key_Logging_test()"); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + InitTcpReady(&ready); + ready.port = 22222; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + XMEMSET(&client_cbf, 0, sizeof(callback_functions)); + server_cbf.method = wolfTLSv1_2_server_method; + + server_args.callbacks = &server_cbf; + server_args.signal = &ready; + + /* clean up keylog file */ + fp = XFOPEN("./MyKeyLog.txt", "w"); + XFCLOSE(fp); + + /* start server task */ + start_thread(server_task, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + + /* run as a TLS1.2 client */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + + tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); + + /* set keylog callback */ + wolfSSL_CTX_set_keylog_callback(ctx,keyLog_callback); + + /* get connected the server task */ + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); + + + AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); + + AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); + AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)), 0); + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + CloseSocket(sockfd); + join_thread(serverThread); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + /* check if the keylog file exists */ + + char buff[300] = {0}; + int found = 0; + + fp = XFOPEN("./MyKeyLog.txt", "r"); + + AssertNotNull(fp); + + while(XFGETS( buff, (int)sizeof(buff),fp) != NULL ) { + if(0 == strncmp(buff,"CLIENT_RANDOM ", + sizeof("CLIENT_RANDOM ")-1)) { + found = 1; + break; + } + } + XFCLOSE(fp); + /* a log starting with "CLIENT_RANDOM " should exit in the file */ + AssertNotNull( found ); + printf(resultFmt, passed); + +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ +} +static void test_wolfSSL_Tls13_Key_Logging_test(void) +{ + #if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + /* This test is intended for checking whether keylog callback is called + * in client during TLS handshake between the client and a server. + */ + + tcp_ready ready; + func_args client_args; + func_args server_args; + THREAD_TYPE serverThread; + callback_functions server_cbf; + callback_functions client_cbf; + SOCKET_T sockfd = 0; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + XFILE fp; + char msg[64] = "hello wolfssl!"; + char reply[1024]; + int msgSz = (int)XSTRLEN(msg); + + printf(testingFmt, "wolfSSL_Tls13_Key_Logging_test()"); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + InitTcpReady(&ready); + ready.port = 22222; + + XMEMSET(&client_args, 0, sizeof(func_args)); + XMEMSET(&server_args, 0, sizeof(func_args)); + XMEMSET(&server_cbf, 0, sizeof(callback_functions)); + XMEMSET(&client_cbf, 0, sizeof(callback_functions)); + server_cbf.method = wolfTLSv1_3_server_method; /* TLS1.3 */ + + server_args.callbacks = &server_cbf; + server_args.signal = &ready; + + /* clean up keylog file */ + fp = XFOPEN("./MyKeyLog.txt", "w"); + XFCLOSE(fp); + + /* start server task */ + start_thread(server_task, &server_args, &serverThread); + wait_tcp_ready(&server_args); + + + /* run as a TLS1.2 client */ + AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM)); + AssertIntEQ(WOLFSSL_SUCCESS, + wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM)); + + tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL); + + /* set keylog callback */ + wolfSSL_CTX_set_keylog_callback(ctx,keyLog_callback); + + /* get connected the server task */ + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_write(ssl, msg, msgSz), msgSz); + AssertIntGT(wolfSSL_read(ssl, reply, sizeof(reply)), 0); + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); + + join_thread(serverThread); + + FreeTcpReady(&ready); + +#ifdef WOLFSSL_TIRTOS + fdOpenSession(Task_self()); +#endif + + /* check if the keylog file exists */ + + char buff[300] = {0}; + int found[4] = {0}; + + fp = XFOPEN("./MyKeyLog.txt", "r"); + + AssertNotNull(fp); + + while(XFGETS( buff, (int)sizeof(buff),fp) != NULL ) { + if(0 == strncmp(buff,"CLIENT_HANDSHAKE_TRAFFIC_SECRET ", + sizeof("CLIENT_HANDSHAKE_TRAFFIC_SECRET ")-1)) { + found[0] = 1; + continue; + } + else if(0 == strncmp(buff,"SERVER_HANDSHAKE_TRAFFIC_SECRET ", + sizeof("SERVER_HANDSHAKE_TRAFFIC_SECRET ")-1)) { + found[1] = 1; + continue; + } + else if(0 == strncmp(buff,"CLIENT_TRAFFIC_SECRET_0 ", + sizeof("CLIENT_TRAFFIC_SECRET_0 ")-1)) { + found[2] = 1; + continue; + } + else if(0 == strncmp(buff,"SERVER_TRAFFIC_SECRET_0 ", + sizeof("SERVER_TRAFFIC_SECRET_0 ")-1)) { + found[3] = 1; + continue; + } + } + XFCLOSE(fp); + int numfnd = 0; + for( uint i = 0; i < 4; i++) { + if( found[i] != 0) + numfnd++; + } + AssertIntEQ( numfnd,4 ); + + printf(resultFmt, passed); + +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ +} static void test_wolfSSL_X509_NID(void) { @@ -45173,6 +45531,7 @@ void ApiTest(void) test_wolfSSL_EVP_MD_hmac_signing(); test_wolfSSL_EVP_MD_rsa_signing(); test_wolfSSL_EVP_MD_ecc_signing(); + test_wolfSSL_EVP_PKEY_print_public(); test_wolfSSL_EVP_ENCODE_CTX_new(); test_wolfSSL_EVP_ENCODE_CTX_free(); test_wolfSSL_EVP_EncodeInit(); @@ -45181,7 +45540,6 @@ void ApiTest(void) test_wolfSSL_EVP_DecodeInit(); test_wolfSSL_EVP_DecodeUpdate(); test_wolfSSL_EVP_DecodeFinal(); - test_wolfSSL_EVP_PKEY_print_public(); test_wolfSSL_CTX_add_extra_chain_cert(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) test_wolfSSL_ERR_peek_last_error_line(); @@ -45244,6 +45602,10 @@ void ApiTest(void) test_wolfSSL_CTX_add_client_CA(); test_wolfSSL_CTX_set_srp_username(); test_wolfSSL_CTX_set_srp_password(); + test_wolfSSL_CTX_set_keylog_callback(); + test_wolfSSL_CTX_get_keylog_callback(); + test_wolfSSL_Tls12_Key_Logging_test(); + test_wolfSSL_Tls13_Key_Logging_test(); test_wolfSSL_CTX_set_ecdh_auto(); test_wolfSSL_THREADID_hash(); test_wolfSSL_RAND_set_rand_method(); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 4f07d53a9..85c13300c 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3066,6 +3066,9 @@ struct WOLFSSL_CTX { Srp* srp; /* TLS Secure Remote Password Protocol*/ byte* srp_password; #endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK) + wolfSSL_CTX_keylog_cb_func keyLogCb; +#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */ #ifdef WOLFSSL_STATIC_EPHEMERAL StaticKeyExchangeInfo_t staticKE; #endif @@ -4438,6 +4441,12 @@ struct WOLFSSL { Tls13SecretCb tls13SecretCb; void* tls13SecretCtx; #endif + #ifdef OPENSSL_EXTRA + SessionSecretCb keyLogCb; + #ifdef WOLFSSL_TLS13 + Tls13SecretCb tls13KeyLogCb; + #endif + #endif #endif /* HAVE_SECRET_CALLBACK */ #ifdef WOLFSSL_JNI void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index fc92977b7..44e4c3362 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -377,6 +377,10 @@ struct WOLFSSL_EVP_PKEY_CTX { int nbits; }; +typedef +struct WOLFSSL_ASN1_PCTX { + int dummy; +} WOLFSSL_ASN1_PCTX; #if defined(WOLFSSL_BASE64_ENCODE) || defined(WOLFSSL_BASE64_DECODE) #define BASE64_ENCODE_BLOCK_SIZE 48 @@ -409,10 +413,6 @@ WOLFSSL_API int wolfSSL_EVP_DecodeUpdate(WOLFSSL_EVP_ENCODE_CTX* ctx, WOLFSSL_API int wolfSSL_EVP_DecodeFinal(WOLFSSL_EVP_ENCODE_CTX* ctx, unsigned char*out, int *outl); #endif /* WOLFSSL_BASE64_DECODE */ -typedef -struct WOLFSSL_ASN1_PCTX { - int dummy; -} WOLFSSL_ASN1_PCTX; typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index e8f317a42..7b16d1757 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -815,6 +815,10 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_info_callback wolfSSL_CTX_set_info_callback #define SSL_CTX_set_alpn_protos wolfSSL_CTX_set_alpn_protos +#define SSL_CTX_keylog_cb_func wolfSSL_CTX_keylog_cb_func +#define SSL_CTX_set_keylog_callback wolfSSL_CTX_set_keylog_callback +#define SSL_CTX_get_keylog_callback wolfSSL_CTX_get_keylog_callback + #define SSL_alert_type_string wolfSSL_alert_type_string #define SSL_alert_desc_string wolfSSL_alert_desc_string #define SSL_state_string wolfSSL_state_string diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 105bb3163..2d7faf590 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -4165,6 +4165,15 @@ WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, const void *buf, size_t len, WOLFSSL *ssl, void *arg); +#if defined(HAVE_SECRET_CALLBACK) +typedef void (*wolfSSL_CTX_keylog_cb_func) + (const WOLFSSL* ssl, const char* line); +WOLFSSL_API void wolfSSL_CTX_set_keylog_callback(WOLFSSL_CTX* ctx, + wolfSSL_CTX_keylog_cb_func cb); +WOLFSSL_API wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback( + const WOLFSSL_CTX* ctx); +#endif /* HAVE_SECRET_CALLBACK */ + WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb); WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb); WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg);