mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-29 12:12:12 +01:00
Initial sniffer keylog file support for TLS 1.2
This commit is contained in:
@@ -7492,7 +7492,7 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SECRET_CALLBACK) && defined(SHOW_SECRETS) && \
|
||||
defined(WOLFSSL_SSLKEYLOGFILE)
|
||||
defined(WOLFSSL_SSLKEYLOGFILE) && defined(WOLFSSL_TLS13)
|
||||
(void)wolfSSL_set_tls13_secret_cb(ssl, tls13ShowSecrets, NULL);
|
||||
#endif
|
||||
|
||||
@@ -17585,7 +17585,7 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input,
|
||||
*
|
||||
* Return 0 on success negative values in error case
|
||||
*/
|
||||
static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
|
||||
int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input,
|
||||
word16 sz)
|
||||
{
|
||||
byte add[AEAD_AUTH_DATA_SZ];
|
||||
|
||||
422
src/sniffer.c
422
src/sniffer.c
@@ -373,6 +373,9 @@ static const char* const msgTable[] =
|
||||
"Setting up keys",
|
||||
"Unsupported TLS Version",
|
||||
"Server Client Key Mismatch",
|
||||
|
||||
/* 99 */
|
||||
"Invalid or missing keylog file",
|
||||
};
|
||||
|
||||
|
||||
@@ -436,6 +439,11 @@ typedef struct SnifferServer {
|
||||
NamedKey* namedKeys; /* mapping of names and keys */
|
||||
wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */
|
||||
#endif
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
byte useKeyLogFile; /* True if session secrets are coming from a
|
||||
keylog file */
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
struct SnifferServer* next; /* for list */
|
||||
} SnifferServer;
|
||||
|
||||
@@ -652,6 +660,16 @@ static void UpdateMissedDataSessions(void)
|
||||
static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID;
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
static int addSecretNode(unsigned char* clientRandom, unsigned char* masterSecret, char* error);
|
||||
static void hexToBin(const char* hex, unsigned char* bin, int binLength);
|
||||
static int parseKeyLogFile(const char* fileName, char* error);
|
||||
static unsigned char* findMasterSecret(unsigned char* clientRandom);
|
||||
static void freeSecretList(void);
|
||||
static int snifferSecretCb(unsigned char* client_random, unsigned char* output_secret);
|
||||
static void setSnifferSecretCb(SnifferSession* session);
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
|
||||
/* Initialize overall Sniffer */
|
||||
void ssl_InitSniffer_ex(int devId)
|
||||
@@ -867,8 +885,16 @@ void ssl_FreeSniffer(void)
|
||||
}
|
||||
ServerList = NULL;
|
||||
|
||||
|
||||
|
||||
UNLOCK_SESSION();
|
||||
UNLOCK_SERVER_LIST();
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
freeSecretList();
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
|
||||
#ifndef WOLFSSL_SNIFFER_NO_RECOVERY
|
||||
wc_FreeMutex(&RecoveryMutex);
|
||||
#endif
|
||||
@@ -2463,6 +2489,17 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
if (session->context->useKeyLogFile) {
|
||||
ret = 0;
|
||||
XMEMSET(args, 0, sizeof(SetupKeysArgs));
|
||||
|
||||
/* We want to skip all the key setup and go right to master secret generation, which is
|
||||
* where we inject the master secret obtained from the keylog file */
|
||||
ssl->options.asyncState = TLS_ASYNC_FINALIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (ssl->options.asyncState) {
|
||||
case TLS_ASYNC_BEGIN:
|
||||
{
|
||||
@@ -3084,12 +3121,17 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
|
||||
|
||||
case TLS_ASYNC_FINALIZE:
|
||||
{
|
||||
/* store for client side as well */
|
||||
XMEMCPY(session->sslClient->arrays->preMasterSecret,
|
||||
session->sslServer->arrays->preMasterSecret,
|
||||
session->sslServer->arrays->preMasterSz);
|
||||
session->sslClient->arrays->preMasterSz =
|
||||
session->sslServer->arrays->preMasterSz;
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
if (!session->context->useKeyLogFile)
|
||||
#endif /* !WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
{
|
||||
/* store for client side as well */
|
||||
XMEMCPY(session->sslClient->arrays->preMasterSecret,
|
||||
session->sslServer->arrays->preMasterSecret,
|
||||
session->sslServer->arrays->preMasterSz);
|
||||
session->sslClient->arrays->preMasterSz =
|
||||
session->sslServer->arrays->preMasterSz;
|
||||
}
|
||||
|
||||
#ifdef SHOW_SECRETS
|
||||
PrintSecret("pre master secret",
|
||||
@@ -3703,6 +3745,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
switch (extType) {
|
||||
#ifdef WOLFSSL_TLS13
|
||||
case EXT_KEY_SHARE:
|
||||
// BRN-sniffer-TODO: TLS 1-3: This is where both client and server keys are actually obtained (client key was cached until now, but we grab them both and store them here)
|
||||
ret = ProcessServerKeyShare(session, input, extLen, error);
|
||||
if (ret != 0) {
|
||||
SetError(SERVER_HELLO_INPUT_STR, error, session,
|
||||
@@ -3862,6 +3905,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
#ifdef WOLFSSL_TLS13
|
||||
/* Setup handshake keys */
|
||||
if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len > 0) {
|
||||
// BRN-sniffer-TODO (TLS13): This is where handshake keys are set up and likely where we need to inject them
|
||||
ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
|
||||
session, error, &session->cliKs);
|
||||
if (ret != 0) {
|
||||
@@ -4110,6 +4154,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
||||
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
|
||||
break;
|
||||
}
|
||||
// BRN-sniffer-TODO (TLS13): This is where the client public key is stored by the sniffer
|
||||
XMEMCPY(session->cliKeyShare, &input[2], ksLen);
|
||||
}
|
||||
break;
|
||||
@@ -4556,14 +4601,21 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
||||
Trace(GOT_CERT_REQ_STR);
|
||||
break;
|
||||
case server_key_exchange:
|
||||
#ifdef WOLFSSL_SNIFFER_STATS
|
||||
INC_STAT(SnifferStats.sslEphemeralMisses);
|
||||
#endif
|
||||
Trace(GOT_SERVER_KEY_EX_STR);
|
||||
/* can't know temp key passively */
|
||||
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
|
||||
session->verboseErr = 1;
|
||||
ret = -1;
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
if (!session->context->useKeyLogFile)
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
{
|
||||
/* can't know temp key passively */
|
||||
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
|
||||
session->verboseErr = 1;
|
||||
ret = -1;
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_STATS)
|
||||
INC_STAT(SnifferStats.sslEphemeralMisses);
|
||||
#endif /* WOLFSSL_SNIFFER_STATS */
|
||||
}
|
||||
break;
|
||||
case encrypted_extensions:
|
||||
Trace(GOT_ENC_EXT_STR);
|
||||
@@ -4720,6 +4772,8 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
|
||||
case wolfssl_aes_gcm:
|
||||
case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
|
||||
{
|
||||
/* For ciphers that use AEAD use the encrypt routine to
|
||||
* bypass the auth tag checking */
|
||||
wc_AesAuthEncryptFunc aes_auth_fn;
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
@@ -4749,7 +4803,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
|
||||
input + AESGCM_EXP_IV_SZ,
|
||||
sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
|
||||
ssl->decrypt.nonce, AESGCM_NONCE_SZ,
|
||||
ssl->decrypt.additional, ssl->specs.aead_mac_size,
|
||||
ssl->decrypt.additional, AEAD_AUTH_DATA_SZ,
|
||||
NULL, 0)) < 0) {
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
if (ret == WC_PENDING_E) {
|
||||
@@ -4782,7 +4836,7 @@ static int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input,
|
||||
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && \
|
||||
!defined(NO_CHAPOL_AEAD)
|
||||
case wolfssl_chacha:
|
||||
ret = ChachaAEADEncrypt(ssl, plain, input, sz);
|
||||
ret = ChachaAEADDecrypt(ssl, plain, input, sz);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -5122,6 +5176,13 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
||||
/* put server back into server mode */
|
||||
session->sslServer->options.side = WOLFSSL_SERVER_END;
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
if (session->context->useKeyLogFile) {
|
||||
setSnifferSecretCb(session);
|
||||
}
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
|
||||
row = SessionHash(ipInfo, tcpInfo);
|
||||
|
||||
/* add it to the session table */
|
||||
@@ -7132,6 +7193,337 @@ int ssl_PollSniffer(WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags,
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
|
||||
#define CLIENT_RANDOM_LABEL_LENGTH 13
|
||||
#define CLIENT_RANDOM_LENGTH 32
|
||||
#define MASTER_SECRET_LENGTH 48
|
||||
#define CLIENT_RANDOM_BITS ((CLIENT_RANDOM_LENGTH) * 8)
|
||||
|
||||
|
||||
typedef struct SecretNode {
|
||||
unsigned char clientRandom[CLIENT_RANDOM_LENGTH];
|
||||
unsigned char masterSecret[MASTER_SECRET_LENGTH];
|
||||
struct SecretNode* next;
|
||||
} SecretNode;
|
||||
|
||||
|
||||
/* Default to the same size hash table as the session table,
|
||||
* but allow user to override */
|
||||
#ifndef WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE
|
||||
#define WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE HASH_SIZE
|
||||
#endif
|
||||
|
||||
static THREAD_LS_T WOLFSSL_GLOBAL
|
||||
SecretNode*
|
||||
secretHashTable[WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE] = {NULL};
|
||||
#ifndef HAVE_C___ATOMIC
|
||||
static WOLFSSL_GLOBAL wolfSSL_Mutex secretListMutex;
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned int secretHashFunction(unsigned char* clientRandom);
|
||||
|
||||
#ifdef HAVE_C___ATOMIC
|
||||
#define LOCK_SECRET_LIST() WC_DO_NOTHING
|
||||
#define UNLOCK_SECRET_LIST() WC_DO_NOTHING
|
||||
#else
|
||||
#define LOCK_SECRET_LIST() wc_LockMutex(&secretListMutex)
|
||||
#define UNLOCK_SECRET_LIST() wc_UnLockMutex(&secretListMutex)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Basic polynomial hash function that maps a 32-byte client random value to an
|
||||
* array index
|
||||
*/
|
||||
static unsigned int secretHashFunction(unsigned char* clientRandom)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int hash = 0;
|
||||
|
||||
for (i = 0; i < CLIENT_RANDOM_LENGTH; i++) {
|
||||
hash = (hash * CLIENT_RANDOM_BITS + clientRandom[i])
|
||||
% WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static int addSecretNode(unsigned char* clientRandom,
|
||||
unsigned char* masterSecret,
|
||||
char* error)
|
||||
{
|
||||
unsigned int index = 0;
|
||||
SecretNode* newSecretNode = NULL;
|
||||
|
||||
newSecretNode = (SecretNode*)XMALLOC(sizeof(SecretNode),
|
||||
NULL,
|
||||
DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
|
||||
if (newSecretNode == NULL) {
|
||||
SetError(MEMORY_STR, error, NULL, 0);
|
||||
return WOLFSSL_SNIFFER_ERROR;
|
||||
}
|
||||
|
||||
XMEMCPY(newSecretNode->clientRandom, clientRandom, CLIENT_RANDOM_LENGTH);
|
||||
XMEMCPY(newSecretNode->masterSecret, masterSecret, MASTER_SECRET_LENGTH);
|
||||
|
||||
LOCK_SECRET_LIST();
|
||||
|
||||
index = secretHashFunction(clientRandom);
|
||||
newSecretNode->next = NULL;
|
||||
|
||||
if (secretHashTable[index] == NULL) {
|
||||
secretHashTable[index] = newSecretNode;
|
||||
}
|
||||
else {
|
||||
SecretNode* current = secretHashTable[index];
|
||||
while (current != NULL) {
|
||||
if (memcmp(current->clientRandom,
|
||||
clientRandom,
|
||||
CLIENT_RANDOM_LENGTH) == 0) {
|
||||
// BRN-sniffer-TODO: what if the same client random has a
|
||||
// different master secret? Should we just update it? or
|
||||
// return error?
|
||||
fprintf(stderr, "Found duplicate client random value in "
|
||||
"keylog file. Rejecting\n");
|
||||
XFREE(newSecretNode, NULL, DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
|
||||
break;
|
||||
}
|
||||
if (current->next == NULL) {
|
||||
current->next = newSecretNode;
|
||||
break;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_SECRET_LIST();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Looks up a master secret for a given client random from the keylog file
|
||||
*/
|
||||
static unsigned char* findMasterSecret(unsigned char* clientRandom)
|
||||
{
|
||||
unsigned char* secret = NULL;
|
||||
SecretNode* node = NULL;
|
||||
unsigned int index = 0;
|
||||
|
||||
LOCK_SECRET_LIST();
|
||||
|
||||
index = secretHashFunction(clientRandom);
|
||||
node = secretHashTable[index];
|
||||
|
||||
while (node != NULL) {
|
||||
if (XMEMCMP(node->clientRandom,
|
||||
clientRandom, CLIENT_RANDOM_LENGTH) == 0) {
|
||||
secret = node->masterSecret;
|
||||
break;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
UNLOCK_SECRET_LIST();
|
||||
|
||||
return secret;
|
||||
}
|
||||
|
||||
|
||||
static void hexToBin(const char* hex, unsigned char* bin, int binLength)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < binLength; i++) {
|
||||
sscanf(hex + 2 * i, "%02hhx", &bin[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int parseKeyLogFile(const char* fileName, char* error)
|
||||
{
|
||||
const char CLIENT_RANDOM_LABEL_STR[] = "CLIENT_RANDOM";
|
||||
unsigned char clientRandom[CLIENT_RANDOM_LENGTH];
|
||||
unsigned char masterSecret[MASTER_SECRET_LENGTH];
|
||||
FILE* file = NULL;
|
||||
int ret = 0;
|
||||
/* +1 for null terminator */
|
||||
char clientRandomLabel[CLIENT_RANDOM_LABEL_LENGTH + 1] = {0};
|
||||
/* 2 chars for Hexadecimal representation, plus null terminator */
|
||||
char clientRandomHex[2 * CLIENT_RANDOM_LENGTH + 1] = {0};
|
||||
char masterSecretHex[2 * MASTER_SECRET_LENGTH + 1] = {0};
|
||||
|
||||
|
||||
file = fopen(fileName, "r");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Could not open keylog file: %s\n", fileName);
|
||||
SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
|
||||
return WOLFSSL_SNIFFER_ERROR;
|
||||
}
|
||||
|
||||
while (fscanf(file, "%13s %64s %96s",
|
||||
clientRandomLabel, clientRandomHex, masterSecretHex) == 3) {
|
||||
if (XSTRCMP(clientRandomLabel, CLIENT_RANDOM_LABEL_STR) == 0) {
|
||||
hexToBin(clientRandomHex, clientRandom, CLIENT_RANDOM_LENGTH);
|
||||
hexToBin(masterSecretHex, masterSecret, MASTER_SECRET_LENGTH);
|
||||
ret = addSecretNode(clientRandom, masterSecret, error);
|
||||
if (ret != 0) {
|
||||
fclose(file);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void freeSecretList(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
LOCK_SECRET_LIST();
|
||||
|
||||
for (i=0; i<WOLFSSL_SNIFFER_KEYLOGFILE_HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
SecretNode* current = secretHashTable[i];
|
||||
SecretNode * next = NULL;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
XFREE(current, NULL, DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_SECRET_LIST();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Looks up secret based on client random and copies it to output_secret
|
||||
*/
|
||||
static int snifferSecretCb(unsigned char* client_random,
|
||||
unsigned char* output_secret)
|
||||
{
|
||||
unsigned char* secret = NULL;
|
||||
|
||||
if (client_random == NULL || output_secret == NULL) {
|
||||
return WOLFSSL_SNIFFER_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* get secret from secret table based on client random */
|
||||
secret = findMasterSecret(client_random);
|
||||
if (secret != NULL) {
|
||||
XMEMCPY(output_secret, secret, MASTER_SECRET_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* didn't find the secret */
|
||||
return WOLFSSL_SNIFFER_ERROR;
|
||||
}
|
||||
|
||||
static void setSnifferSecretCb(SnifferSession* session)
|
||||
{
|
||||
session->context->useKeyLogFile = 1;
|
||||
session->sslServer->snifferSecretCb = snifferSecretCb;
|
||||
session->sslClient->snifferSecretCb = snifferSecretCb;
|
||||
}
|
||||
|
||||
|
||||
WOLFSSL_API
|
||||
SSL_SNIFFER_API int ssl_LoadSecretsFromKeyLogFile(const char* address,
|
||||
int port,
|
||||
const char* keylogfile,
|
||||
char* error)
|
||||
{
|
||||
int ret = WOLFSSL_SNIFFER_ERROR;
|
||||
IpAddrInfo serverIp = {0};
|
||||
|
||||
TraceHeader();
|
||||
TraceSetServer(address, port, keylogfile);
|
||||
|
||||
SnifferServer *sniffer = NULL;
|
||||
|
||||
if (keylogfile == NULL) {
|
||||
SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
|
||||
return WOLFSSL_SNIFFER_ERROR;
|
||||
}
|
||||
|
||||
serverIp.version = IPV4;
|
||||
serverIp.ip4 = XINET_ADDR(address);
|
||||
if (serverIp.ip4 == XINADDR_NONE) {
|
||||
#ifdef FUSION_RTOS
|
||||
if (XINET_PTON(AF_INET6, address, serverIp.ip6,
|
||||
sizeof(serverIp.ip4)) == 1) {
|
||||
#else
|
||||
if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1) {
|
||||
#endif
|
||||
serverIp.version = IPV6;
|
||||
}
|
||||
}
|
||||
|
||||
sniffer = ServerList;
|
||||
while (sniffer != NULL &&
|
||||
(!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
|
||||
sniffer = sniffer->next;
|
||||
}
|
||||
|
||||
if (sniffer == NULL) {
|
||||
sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
|
||||
NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
|
||||
if (sniffer == NULL) {
|
||||
SetError(MEMORY_STR, error, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
InitSnifferServer(sniffer);
|
||||
|
||||
XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
|
||||
sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
|
||||
sniffer->server = serverIp;
|
||||
sniffer->port = port;
|
||||
|
||||
sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
if (!sniffer->ctx) {
|
||||
SetError(MEMORY_STR, error, NULL, 0);
|
||||
FreeSnifferServer(sniffer);
|
||||
return -1;
|
||||
}
|
||||
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
|
||||
if (CryptoDeviceId != INVALID_DEVID)
|
||||
wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
|
||||
#endif
|
||||
|
||||
/* We've initialized the sniffer server and added it to the ServerList
|
||||
* without initializing its keys, so we must now tag it as a key log
|
||||
* file sniffer, as it won't be useable otherwise */
|
||||
sniffer->useKeyLogFile = 1;
|
||||
|
||||
sniffer->next = ServerList;
|
||||
ServerList = sniffer;
|
||||
}
|
||||
else {
|
||||
printf("SESSION ALREADY EXISTS\n");
|
||||
}
|
||||
|
||||
ret = parseKeyLogFile(keylogfile, error);
|
||||
if (ret != 0) {
|
||||
FreeSnifferServer(sniffer);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
Trace(NEW_SERVER_STR);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
|
||||
|
||||
#undef ERROR_OUT
|
||||
|
||||
#endif /* WOLFSSL_SNIFFER */
|
||||
|
||||
13
src/tls.c
13
src/tls.c
@@ -516,6 +516,19 @@ int MakeTlsMasterSecret(WOLFSSL* ssl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(WOLFSSL_SNIFFER) && defined(WOLFSSL_SNIFFER_KEYLOGFILE)
|
||||
/* If this is called from a sniffer session with keylog file support, obtain
|
||||
* the master secret from the callback */
|
||||
if (ssl->snifferSecretCb != NULL) {
|
||||
ret = ssl->snifferSecretCb(ssl->arrays->clientRandom, ssl->arrays->masterSecret);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = DeriveTlsKeys(ssl);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WOLFSSL_SNIFFER && WOLFSSL_SNIFFER_KEYLOGFILE */
|
||||
|
||||
#ifdef HAVE_EXTENDED_MASTER
|
||||
if (ssl->options.haveEMS) {
|
||||
word32 hashSz = HSHASH_SZ;
|
||||
|
||||
15
src/tls13.c
15
src/tls13.c
@@ -1386,6 +1386,7 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv";
|
||||
* store ready for provisioning.
|
||||
* returns 0 on success, otherwise failure.
|
||||
*/
|
||||
// BRN-sniffer-TODO(TLS13): this function is where I think we should be grabbing secrets from sniffer and storing them (or deriving keys based on them...tbd which is exported)
|
||||
int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
|
||||
{
|
||||
int ret = BAD_FUNC_ARG; /* Assume failure */
|
||||
@@ -1424,7 +1425,15 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
|
||||
switch (secret) {
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
case early_data_key:
|
||||
/*
|
||||
* BRN-sniffer-TODO(TLS13): Maybe something like:
|
||||
* #if SNIFFER
|
||||
* ssl->clientSecret = getSecretFromSniffer(CLIENT_EARLY_TRAFFIC_SECRET)
|
||||
* #else
|
||||
* the following code
|
||||
*/
|
||||
ret = DeriveEarlyTrafficSecret(ssl, ssl->clientSecret,
|
||||
|
||||
WOLFSSL_CLIENT_END);
|
||||
if (ret != 0)
|
||||
goto end;
|
||||
@@ -13729,6 +13738,12 @@ int tls13ShowSecrets(WOLFSSL* ssl, int id, const unsigned char* secret,
|
||||
str = "SERVER_TRAFFIC_SECRET_0"; break;
|
||||
case EXPORTER_SECRET:
|
||||
str = "EXPORTER_SECRET"; break;
|
||||
default:
|
||||
#ifdef WOLFSSL_SSLKEYLOGFILE_OUTPUT
|
||||
XFCLOSE(fp);
|
||||
#endif
|
||||
return BAD_FUNC_ARG;
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(fp, "%s ", str);
|
||||
|
||||
Reference in New Issue
Block a user