Skip to content

Commit 66c53b0

Browse files
committed
Decoupled keylogfile registration and sniffer server creation APIs
fixed (very old) use-after-free found by ASAN Updated documentation review comments (spelling and housekeeping)
1 parent 2ee6a01 commit 66c53b0

6 files changed

Lines changed: 136 additions & 68 deletions

File tree

scripts/sniffer-testsuite.test

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ RESULT=0
7272
# TLS v1.2 Static RSA Test
7373
if test $RESULT -eq 0 && test $has_rsa == yes && test $has_tlsv12 == yes && test $has_static_rsa == yes
7474
then
75-
echo -e "\nStaring snifftest on testsuite.pcap...\n"
75+
echo -e "\nStaring snifftest on sniffer-static-rsa.pcap...\n"
7676
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-static-rsa.pcap -key ./certs/server-key.pem -server 127.0.0.1 -port 11111
7777

7878
RESULT=$?
@@ -91,9 +91,11 @@ fi
9191

9292
# TLS v1.2 sniffer keylog file test: runs sniffer on pcap and associated keylog file and compares decrypted traffic with known good output.
9393
# To regenerate the known good output, run `scripts/sniffer-gen.sh` to regenerate the pcap and keylog file, then run the sniffer on it
94-
# with the same arguments as in the test belowl, but redirect output to `./scripts/sniffer-tls12-keylog.out`.
94+
# with the same arguments as in the test below, but redirect output to `./scripts/sniffer-tls12-keylog.out`.
9595
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_keylog == yes
9696
then
97+
echo -e "\nStaring snifftest on sniffer-tls12-keylog.pcap...\n"
98+
9799
TMPFILE=$(mktemp)
98100
RESULT=$?
99101
[ $RESULT -ne 0 ] && echo -e "\nsnifftest keylog test failed: unable to create tmpfile\n" && rm $TMPFILE && exit 1
@@ -118,6 +120,7 @@ fi
118120
# TLS v1.3 sniffer test ECC
119121
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes
120122
then
123+
echo -e "\nStaring snifftest on sniffer-tls13-ecc.pcap...\n"
121124
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-ecc.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
122125

123126
RESULT=$?
@@ -127,6 +130,7 @@ fi
127130
# TLS v1.3 sniffer test DH
128131
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_dh == yes
129132
then
133+
echo -e "\nStaring snifftest on sniffer-tls13-dh.pcap...\n"
130134
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-dh.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
131135

132136
RESULT=$?
@@ -136,6 +140,7 @@ fi
136140
# TLS v1.3 sniffer test X25519
137141
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_x25519 == yes
138142
then
143+
echo -e "\nStaring snifftest on sniffer-tls13-x25519.pcap...\n"
139144
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-x25519.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
140145

141146
RESULT=$?
@@ -145,6 +150,7 @@ fi
145150
# TLS v1.3 sniffer test ECC resumption
146151
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes && test $session_ticket == yes
147152
then
153+
echo -e "\nStaring snifftest on sniffer-tls13-ecc-resume.pcap...\n"
148154
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-ecc-resume.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
149155

150156
RESULT=$?
@@ -154,6 +160,7 @@ fi
154160
# TLS v1.3 sniffer test DH
155161
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_dh == yes && test $session_ticket == yes
156162
then
163+
echo -e "\nStaring snifftest on sniffer-tls13-dh-resume.pcap...\n"
157164
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-dh-resume.pcap -key ./certs/statickeys/dh-ffdhe2048.pem -server 127.0.0.1 -port 11111
158165

159166
RESULT=$?
@@ -163,6 +170,7 @@ fi
163170
# TLS v1.3 sniffer test X25519
164171
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_x25519 == yes && test $session_ticket == yes
165172
then
173+
echo -e "\nStaring snifftest on sniffer-tls13-x25519-resume.pcap...\n"
166174
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-x25519-resume.pcap -key ./certs/statickeys/x25519.pem -server 127.0.0.1 -port 11111
167175

168176
RESULT=$?
@@ -172,6 +180,7 @@ fi
172180
# TLS v1.3 sniffer test hello_retry_request (HRR) with ECDHE
173181
if test $RESULT -eq 0 && test $has_tlsv13 == yes && test $has_ecc == yes
174182
then
183+
echo -e "\nStaring snifftest on sniffer-tls13-hrr.pcap...\n"
175184
./sslSniffer/sslSnifferTest/snifftest -pcap ./scripts/sniffer-tls13-hrr.pcap -key ./certs/statickeys/ecc-secp256r1.pem -server 127.0.0.1 -port 11111
176185

177186
RESULT=$?

src/sniffer.c

Lines changed: 86 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -661,13 +661,19 @@ static void UpdateMissedDataSessions(void)
661661
#endif
662662

663663
#if defined(WOLFSSL_SNIFFER_KEYLOGFILE)
664-
static int addSecretNode(unsigned char* clientRandom, unsigned char* masterSecret, char* error);
664+
static int addSecretNode(unsigned char* clientRandom,
665+
unsigned char* masterSecret,
666+
char* error);
665667
static void hexToBin(const char* hex, unsigned char* bin, int binLength);
666668
static int parseKeyLogFile(const char* fileName, char* error);
667669
static unsigned char* findMasterSecret(unsigned char* clientRandom);
668670
static void freeSecretList(void);
669-
static int snifferSecretCb(unsigned char* client_random, unsigned char* output_secret);
671+
static int snifferSecretCb(unsigned char* client_random,
672+
unsigned char* output_secret);
670673
static void setSnifferSecretCb(SnifferSession* session);
674+
static int addKeyLogSnifferServerHelper(const char* address,
675+
int port,
676+
char* error);
671677
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
672678

673679

@@ -1188,8 +1194,14 @@ static void TraceSetServer(const char* srv, int port, const char* keyFile)
11881194
{
11891195
if (TraceOn) {
11901196
XFPRINTF(TraceFile, "\tTrying to install a new Sniffer Server with\n");
1191-
XFPRINTF(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
1192-
keyFile);
1197+
if (keyFile != NULL) {
1198+
XFPRINTF(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n",
1199+
srv, port, keyFile);
1200+
}
1201+
else {
1202+
XFPRINTF(TraceFile, "\tserver: %s, port: %d\n",
1203+
srv, port);
1204+
}
11931205
}
11941206
}
11951207

@@ -1758,6 +1770,7 @@ static int CreateWatchSnifferServer(char* error)
17581770

17591771
#endif
17601772

1773+
17611774
/* Caller locks ServerListMutex */
17621775
static int SetNamedPrivateKey(const char* name, const char* address, int port,
17631776
const char* keyFile, int keySz, int typeKey, const char* password,
@@ -1806,10 +1819,11 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
18061819
if (serverIp.ip4 == XINADDR_NONE) {
18071820
#ifdef FUSION_RTOS
18081821
if (XINET_PTON(AF_INET6, address, serverIp.ip6,
1809-
sizeof(serverIp.ip4)) == 1) {
1822+
sizeof(serverIp.ip4)) == 1)
18101823
#else
1811-
if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1) {
1824+
if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1)
18121825
#endif
1826+
{
18131827
serverIp.version = IPV6;
18141828
}
18151829
}
@@ -3745,7 +3759,6 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
37453759
switch (extType) {
37463760
#ifdef WOLFSSL_TLS13
37473761
case EXT_KEY_SHARE:
3748-
// 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)
37493762
ret = ProcessServerKeyShare(session, input, extLen, error);
37503763
if (ret != 0) {
37513764
SetError(SERVER_HELLO_INPUT_STR, error, session,
@@ -3905,7 +3918,6 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
39053918
#ifdef WOLFSSL_TLS13
39063919
/* Setup handshake keys */
39073920
if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len > 0) {
3908-
// BRN-sniffer-TODO (TLS13): This is where handshake keys are set up and likely where we need to inject them
39093921
ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
39103922
session, error, &session->cliKs);
39113923
if (ret != 0) {
@@ -4154,7 +4166,6 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
41544166
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
41554167
break;
41564168
}
4157-
// BRN-sniffer-TODO (TLS13): This is where the client public key is stored by the sniffer
41584169
XMEMCPY(session->cliKeyShare, &input[2], ksLen);
41594170
}
41604171
break;
@@ -6553,10 +6564,10 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
65536564
SnifferSession* session, char* error)
65546565
{
65556566
if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
6556-
RemoveSession(session, ipInfo, tcpInfo, 0);
65576567
if (!session->verboseErr) {
65586568
SetError(FATAL_ERROR_STR, error, NULL, 0);
65596569
}
6570+
RemoveSession(session, ipInfo, tcpInfo, 0);
65606571
return 1;
65616572
}
65626573
return 0;
@@ -7233,6 +7244,7 @@ static unsigned int secretHashFunction(unsigned char* clientRandom);
72337244
#define UNLOCK_SECRET_LIST() wc_UnLockMutex(&secretListMutex)
72347245
#endif
72357246

7247+
72367248
/*
72377249
* Basic polynomial hash function that maps a 32-byte client random value to an
72387250
* array index
@@ -7250,6 +7262,7 @@ static unsigned int secretHashFunction(unsigned char* clientRandom)
72507262
return hash;
72517263
}
72527264

7265+
72537266
static int addSecretNode(unsigned char* clientRandom,
72547267
unsigned char* masterSecret,
72557268
char* error)
@@ -7282,11 +7295,9 @@ static int addSecretNode(unsigned char* clientRandom,
72827295
if (memcmp(current->clientRandom,
72837296
clientRandom,
72847297
CLIENT_RANDOM_LENGTH) == 0) {
7285-
// BRN-sniffer-TODO: what if the same client random has a
7286-
// different master secret? Should we just update it? or
7287-
// return error?
7298+
/* No need for a new node, since it already exists */
72887299
fprintf(stderr, "Found duplicate client random value in "
7289-
"keylog file. Rejecting\n");
7300+
"keylog file. Rejecting.\n");
72907301
XFREE(newSecretNode, NULL, DYNAMIC_TYPE_SNIFFER_KEYLOG_NODE);
72917302
break;
72927303
}
@@ -7341,6 +7352,7 @@ static void hexToBin(const char* hex, unsigned char* bin, int binLength)
73417352
}
73427353
}
73437354

7355+
73447356
static int parseKeyLogFile(const char* fileName, char* error)
73457357
{
73467358
const char CLIENT_RANDOM_LABEL_STR[] = "CLIENT_RANDOM";
@@ -7425,6 +7437,7 @@ static int snifferSecretCb(unsigned char* client_random,
74257437
return WOLFSSL_SNIFFER_ERROR;
74267438
}
74277439

7440+
74287441
static void setSnifferSecretCb(SnifferSession* session)
74297442
{
74307443
session->context->useKeyLogFile = 1;
@@ -7433,34 +7446,32 @@ static void setSnifferSecretCb(SnifferSession* session)
74337446
}
74347447

74357448

7436-
WOLFSSL_API
7437-
SSL_SNIFFER_API int ssl_LoadSecretsFromKeyLogFile(const char* address,
7438-
int port,
7439-
const char* keylogfile,
7440-
char* error)
7449+
/*
7450+
* Helper function that creates a sniffer server object that can decrypt using
7451+
* a keylog file, and adds it to the server list
7452+
*
7453+
* NOTE: the caller is responsible for locking and unlocking the server list
7454+
*/
7455+
static int addKeyLogSnifferServerHelper(const char* address,
7456+
int port,
7457+
char* error)
74417458
{
7442-
int ret = WOLFSSL_SNIFFER_ERROR;
74437459
IpAddrInfo serverIp = {0};
7444-
7445-
TraceHeader();
7446-
TraceSetServer(address, port, keylogfile);
7447-
74487460
SnifferServer *sniffer = NULL;
74497461

7450-
if (keylogfile == NULL) {
7451-
SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7452-
return WOLFSSL_SNIFFER_ERROR;
7453-
}
7462+
TraceHeader();
7463+
TraceSetServer(address, port, NULL);
74547464

74557465
serverIp.version = IPV4;
74567466
serverIp.ip4 = XINET_ADDR(address);
74577467
if (serverIp.ip4 == XINADDR_NONE) {
74587468
#ifdef FUSION_RTOS
74597469
if (XINET_PTON(AF_INET6, address, serverIp.ip6,
7460-
sizeof(serverIp.ip4)) == 1) {
7470+
sizeof(serverIp.ip4)) == 1)
74617471
#else
7462-
if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1) {
7472+
if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1)
74637473
#endif
7474+
{
74647475
serverIp.version = IPV6;
74657476
}
74667477
}
@@ -7476,7 +7487,7 @@ SSL_SNIFFER_API int ssl_LoadSecretsFromKeyLogFile(const char* address,
74767487
NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
74777488
if (sniffer == NULL) {
74787489
SetError(MEMORY_STR, error, NULL, 0);
7479-
return -1;
7490+
return WOLFSSL_SNIFFER_ERROR;
74807491
}
74817492
InitSnifferServer(sniffer);
74827493

@@ -7489,39 +7500,69 @@ SSL_SNIFFER_API int ssl_LoadSecretsFromKeyLogFile(const char* address,
74897500
if (!sniffer->ctx) {
74907501
SetError(MEMORY_STR, error, NULL, 0);
74917502
FreeSnifferServer(sniffer);
7492-
return -1;
7503+
return WOLFSSL_SNIFFER_ERROR;
74937504
}
74947505
#if defined(WOLF_CRYPTO_CB) || defined(WOLFSSL_ASYNC_CRYPT)
74957506
if (CryptoDeviceId != INVALID_DEVID)
74967507
wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
74977508
#endif
74987509

7499-
/* We've initialized the sniffer server and added it to the ServerList
7500-
* without initializing its keys, so we must now tag it as a key log
7501-
* file sniffer, as it won't be useable otherwise */
7502-
sniffer->useKeyLogFile = 1;
7503-
75047510
sniffer->next = ServerList;
75057511
ServerList = sniffer;
75067512
}
75077513
else {
75087514
printf("SESSION ALREADY EXISTS\n");
75097515
}
75107516

7511-
ret = parseKeyLogFile(keylogfile, error);
7512-
if (ret != 0) {
7513-
FreeSnifferServer(sniffer);
7514-
return ret;
7515-
}
7516-
else {
7517-
Trace(NEW_SERVER_STR);
7517+
/* Tag the new or existing server as requiring keylog support to
7518+
* decrypt, otherwise it won't be useable */
7519+
sniffer->useKeyLogFile = 1;
7520+
7521+
return 0;
7522+
}
7523+
7524+
/*
7525+
* Creates a sniffer server that is able to decrypt using secrets from a
7526+
* keylog file, and adds it to the server list
7527+
*
7528+
* If a server at the address and port already exists, it will be marked
7529+
* for keylog file decryption
7530+
*/
7531+
int ssl_CreateKeyLogSnifferServer(const char* address, int port, char* error)
7532+
{
7533+
int ret = 0;
7534+
7535+
if (address == NULL) {
7536+
SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7537+
return WOLFSSL_SNIFFER_ERROR;
75187538
}
75197539

7540+
LOCK_SERVER_LIST();
7541+
7542+
ret = addKeyLogSnifferServerHelper(address, port, error);
7543+
7544+
UNLOCK_SERVER_LIST();
7545+
75207546
return ret;
75217547
}
75227548

7523-
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
75247549

7550+
/*
7551+
* Loads secrets to decrypt TLS traffic from a keylog file. Only sniffer
7552+
* servers registered with ssl_createKeyLogSnifferServer() will be able to
7553+
* decrypt using these secrets
7554+
*/
7555+
int ssl_LoadSecretsFromKeyLogFile(const char* keylogfile, char* error)
7556+
{
7557+
if (keylogfile == NULL) {
7558+
SetError(KEYLOG_FILE_INVALID, error, NULL, 0);
7559+
return WOLFSSL_SNIFFER_ERROR;
7560+
}
7561+
7562+
return parseKeyLogFile(keylogfile, error);
7563+
}
7564+
7565+
#endif /* WOLFSSL_SNIFFER_KEYLOGFILE */
75257566

75267567

75277568
#undef ERROR_OUT

src/tls13.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,7 +1386,6 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv";
13861386
* store ready for provisioning.
13871387
* returns 0 on success, otherwise failure.
13881388
*/
1389-
// 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)
13901389
int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
13911390
{
13921391
int ret = BAD_FUNC_ARG; /* Assume failure */
@@ -1425,15 +1424,7 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store)
14251424
switch (secret) {
14261425
#ifdef WOLFSSL_EARLY_DATA
14271426
case early_data_key:
1428-
/*
1429-
* BRN-sniffer-TODO(TLS13): Maybe something like:
1430-
* #if SNIFFER
1431-
* ssl->clientSecret = getSecretFromSniffer(CLIENT_EARLY_TRAFFIC_SECRET)
1432-
* #else
1433-
* the following code
1434-
*/
14351427
ret = DeriveEarlyTrafficSecret(ssl, ssl->clientSecret,
1436-
14371428
WOLFSSL_CLIENT_END);
14381429
if (ret != 0)
14391430
goto end;

0 commit comments

Comments
 (0)