source: azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/src/sniffer.c@ 457

Last change on this file since 457 was 457, checked in by coas-nagasima, 4 years ago

ファイルを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 134.4 KB
Line 
1/* sniffer.c
2 *
3 * Copyright (C) 2006-2020 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23#ifdef HAVE_CONFIG_H
24 #include <config.h>
25#endif
26
27#include <wolfssl/wolfcrypt/settings.h>
28
29#ifndef WOLFCRYPT_ONLY
30#ifdef WOLFSSL_SNIFFER
31
32#include <assert.h>
33#include <time.h>
34
35#ifndef _WIN32
36 #include <arpa/inet.h>
37#else
38 #include <WS2tcpip.h>
39#endif
40
41#ifdef _WIN32
42 #define SNPRINTF _snprintf
43#else
44 #define SNPRINTF snprintf
45#endif
46
47#include <wolfssl/openssl/ssl.h>
48#include <wolfssl/internal.h>
49#include <wolfssl/error-ssl.h>
50#include <wolfssl/sniffer.h>
51#include <wolfssl/sniffer_error.h>
52#ifdef NO_INLINE
53 #include <wolfssl/wolfcrypt/misc.h>
54#else
55 #define WOLFSSL_MISC_INCLUDED
56 #include <wolfcrypt/src/misc.c>
57#endif
58
59#ifdef WOLF_CRYPTO_CB
60 #include <wolfssl/wolfcrypt/cryptocb.h>
61 #ifdef HAVE_INTEL_QA_SYNC
62 #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
63 #endif
64 #ifdef HAVE_CAVIUM_OCTEON_SYNC
65 #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
66 #endif
67#endif
68
69
70#ifndef WOLFSSL_SNIFFER_TIMEOUT
71 #define WOLFSSL_SNIFFER_TIMEOUT 900
72 /* Cache unclosed Sessions for 15 minutes since last used */
73#endif
74
75/* Misc constants */
76enum {
77 MAX_SERVER_ADDRESS = 128, /* maximum server address length */
78 MAX_SERVER_NAME = 128, /* maximum server name length */
79 MAX_ERROR_LEN = 80, /* maximum error length */
80 ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
81 LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
82 TCP_PROTO = 6, /* TCP_PROTOCOL */
83 IP_HDR_SZ = 20, /* IPv4 header length, min */
84 IP6_HDR_SZ = 40, /* IPv6 header length, min */
85 TCP_HDR_SZ = 20, /* TCP header length, min */
86 IPV4 = 4, /* IP version 4 */
87 IPV6 = 6, /* IP version 6 */
88 TCP_PROTOCOL = 6, /* TCP Protocol id */
89 NO_NEXT_HEADER = 59, /* IPv6 no headers follow */
90 TRACE_MSG_SZ = 80, /* Trace Message buffer size */
91 HASH_SIZE = 499, /* Session Hash Table Rows */
92 PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
93 FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
94 TICKET_HINT_LEN = 4, /* Session Ticket Hint length */
95 EXT_TYPE_SZ = 2, /* Extension length */
96 MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
97 MTU_EXTRA, /* Max input sz of reassembly */
98 EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */
99 TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
100};
101
102
103#ifdef _WIN32
104
105static HMODULE dllModule; /* for error string resources */
106
107BOOL APIENTRY DllMain( HMODULE hModule,
108 DWORD ul_reason_for_call,
109 LPVOID lpReserved
110 )
111{
112 static int didInit = 0;
113
114 switch (ul_reason_for_call)
115 {
116 case DLL_PROCESS_ATTACH:
117 if (didInit == 0) {
118 dllModule = hModule;
119 ssl_InitSniffer();
120 didInit = 1;
121 }
122 break;
123 case DLL_THREAD_ATTACH:
124 break;
125 case DLL_THREAD_DETACH:
126 break;
127 case DLL_PROCESS_DETACH:
128 if (didInit) {
129 ssl_FreeSniffer();
130 didInit = 0;
131 }
132 break;
133 }
134 return TRUE;
135}
136
137#endif /* _WIN32 */
138
139
140static WOLFSSL_GLOBAL int TraceOn = 0; /* Trace is off by default */
141static WOLFSSL_GLOBAL FILE* TraceFile = 0;
142
143
144/* windows uses .rc table for this */
145#ifndef _WIN32
146
147static const char* const msgTable[] =
148{
149 /* 1 */
150 "Out of Memory",
151 "New SSL Sniffer Server Registered",
152 "Checking IP Header",
153 "SSL Sniffer Server Not Registered",
154 "Checking TCP Header",
155
156 /* 6 */
157 "SSL Sniffer Server Port Not Registered",
158 "RSA Private Decrypt Error",
159 "RSA Private Decode Error",
160 "Set Cipher Spec Error",
161 "Server Hello Input Malformed",
162
163 /* 11 */
164 "Couldn't Resume Session Error",
165 "Server Did Resumption",
166 "Client Hello Input Malformed",
167 "Client Trying to Resume",
168 "Handshake Input Malformed",
169
170 /* 16 */
171 "Got Hello Verify msg",
172 "Got Server Hello msg",
173 "Got Cert Request msg",
174 "Got Server Key Exchange msg",
175 "Got Cert msg",
176
177 /* 21 */
178 "Got Server Hello Done msg",
179 "Got Finished msg",
180 "Got Client Hello msg",
181 "Got Client Key Exchange msg",
182 "Got Cert Verify msg",
183
184 /* 26 */
185 "Got Unknown Handshake msg",
186 "New SSL Sniffer Session created",
187 "Couldn't create new SSL",
188 "Got a Packet to decode",
189 "No data present",
190
191 /* 31 */
192 "Session Not Found",
193 "Got an Old Client Hello msg",
194 "Old Client Hello Input Malformed",
195 "Old Client Hello OK",
196 "Bad Old Client Hello",
197
198 /* 36 */
199 "Bad Record Header",
200 "Record Header Input Malformed",
201 "Got a HandShake msg",
202 "Bad HandShake msg",
203 "Got a Change Cipher Spec msg",
204
205 /* 41 */
206 "Got Application Data msg",
207 "Bad Application Data",
208 "Got an Alert msg",
209 "Another msg to Process",
210 "Removing Session From Table",
211
212 /* 46 */
213 "Bad Key File",
214 "Wrong IP Version",
215 "Wrong Protocol type",
216 "Packet Short for header processing",
217 "Got Unknown Record Type",
218
219 /* 51 */
220 "Can't Open Trace File",
221 "Session in Fatal Error State",
222 "Partial SSL record received",
223 "Buffer Error, malformed input",
224 "Added to Partial Input",
225
226 /* 56 */
227 "Received a Duplicate Packet",
228 "Received an Out of Order Packet",
229 "Received an Overlap Duplicate Packet",
230 "Received an Overlap Reassembly Begin Duplicate Packet",
231 "Received an Overlap Reassembly End Duplicate Packet",
232
233 /* 61 */
234 "Missed the Client Hello Entirely",
235 "Got Hello Request msg",
236 "Got Session Ticket msg",
237 "Bad Input",
238 "Bad Decrypt Type",
239
240 /* 66 */
241 "Bad Finished Message Processing",
242 "Bad Compression Type",
243 "Bad DeriveKeys Error",
244 "Saw ACK for Missing Packet Error",
245 "Bad Decrypt Operation",
246
247 /* 71 */
248 "Decrypt Keys Not Set Up",
249 "Late Key Load Error",
250 "Got Certificate Status msg",
251 "RSA Key Missing Error",
252 "Secure Renegotiation Not Supported",
253
254 /* 76 */
255 "Get Session Stats Failure",
256 "Reassembly Buffer Size Exceeded",
257 "Dropping Lost Fragment",
258 "Dropping Partial Record",
259 "Clear ACK Fault",
260
261 /* 81 */
262 "Bad Decrypt Size",
263 "Extended Master Secret Hash Error",
264 "Handshake Message Split Across TLS Records",
265 "ECC Private Decode Error",
266 "ECC Public Decode Error",
267
268 /* 86 */
269 "Watch callback not set",
270 "Watch hash failed",
271 "Watch callback failed",
272 "Bad Certificate Message",
273 "Store data callback not set",
274
275 /* 91 */
276 "No data destination Error",
277 "Store data callback failed",
278 "Loading chain input"
279};
280
281
282/* *nix version uses table above */
283static void GetError(int idx, char* str)
284{
285 XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1);
286 str[MAX_ERROR_LEN-1] = '\0';
287}
288
289
290#else /* _WIN32 */
291
292
293/* Windows version uses .rc table */
294static void GetError(int idx, char* buffer)
295{
296 if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
297 buffer[0] = 0;
298}
299
300
301#endif /* _WIN32 */
302
303
304/* Packet Buffer for reassembly list and ready list */
305typedef struct PacketBuffer {
306 word32 begin; /* relative sequence begin */
307 word32 end; /* relative sequence end */
308 byte* data; /* actual data */
309 struct PacketBuffer* next; /* next on reassembly list or ready list */
310} PacketBuffer;
311
312
313#ifdef HAVE_SNI
314
315/* NamedKey maps a SNI name to a specific private key */
316typedef struct NamedKey {
317 char name[MAX_SERVER_NAME]; /* server DNS name */
318 word32 nameSz; /* size of server DNS name */
319 byte* key; /* DER private key */
320 word32 keySz; /* size of DER private key */
321 struct NamedKey* next; /* for list */
322} NamedKey;
323
324#endif
325
326
327typedef struct IpAddrInfo {
328 int version;
329 union {
330 word32 ip4;
331 byte ip6[16];
332 };
333} IpAddrInfo;
334
335
336/* Sniffer Server holds info for each server/port monitored */
337typedef struct SnifferServer {
338 SSL_CTX* ctx; /* SSL context */
339 char address[MAX_SERVER_ADDRESS]; /* passed in server address */
340 IpAddrInfo server; /* network order address */
341 int port; /* server port */
342#ifdef HAVE_SNI
343 NamedKey* namedKeys; /* mapping of names and keys */
344 wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */
345#endif
346 struct SnifferServer* next; /* for list */
347} SnifferServer;
348
349
350/* Session Flags */
351typedef struct Flags {
352 byte side; /* which end is current packet headed */
353 byte serverCipherOn; /* indicates whether cipher is active */
354 byte clientCipherOn; /* indicates whether cipher is active */
355 byte resuming; /* did this session come from resumption */
356 byte cached; /* have we cached this session yet */
357 byte clientHello; /* processed client hello yet, for SSLv2 */
358 byte finCount; /* get both FINs before removing */
359 byte fatalError; /* fatal error state */
360 byte cliAckFault; /* client acked unseen data from server */
361 byte srvAckFault; /* server acked unseen data from client */
362 byte cliSkipPartial; /* client skips partial data to catch up */
363 byte srvSkipPartial; /* server skips partial data to catch up */
364#ifdef HAVE_EXTENDED_MASTER
365 byte expectEms; /* expect extended master secret */
366#endif
367} Flags;
368
369
370/* Out of Order FIN capture */
371typedef struct FinCaputre {
372 word32 cliFinSeq; /* client relative sequence FIN 0 is no */
373 word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
374 byte cliCounted; /* did we count yet, detects duplicates */
375 byte srvCounted; /* did we count yet, detects duplicates */
376} FinCaputre;
377
378
379typedef struct HsHashes {
380#ifndef NO_OLD_TLS
381#ifndef NO_SHA
382 wc_Sha hashSha;
383#endif
384#ifndef NO_MD5
385 wc_Md5 hashMd5;
386#endif
387#endif
388#ifndef NO_SHA256
389 wc_Sha256 hashSha256;
390#endif
391#ifdef WOLFSSL_SHA384
392 wc_Sha384 hashSha384;
393#endif
394} HsHashes;
395
396
397/* Sniffer Session holds info for each client/server SSL/TLS session */
398typedef struct SnifferSession {
399 SnifferServer* context; /* server context */
400 SSL* sslServer; /* SSL server side decode */
401 SSL* sslClient; /* SSL client side decode */
402 IpAddrInfo server; /* server address in network byte order */
403 IpAddrInfo client; /* client address in network byte order */
404 word16 srvPort; /* server port */
405 word16 cliPort; /* client port */
406 word32 cliSeqStart; /* client start sequence */
407 word32 srvSeqStart; /* server start sequence */
408 word32 cliExpected; /* client expected sequence (relative) */
409 word32 srvExpected; /* server expected sequence (relative) */
410 FinCaputre finCaputre; /* retain out of order FIN s */
411 Flags flags; /* session flags */
412 time_t lastUsed; /* last used ticks */
413 word32 keySz; /* size of the private key */
414 PacketBuffer* cliReassemblyList; /* client out of order packets */
415 PacketBuffer* srvReassemblyList; /* server out of order packets */
416 word32 cliReassemblyMemory; /* client packet memory used */
417 word32 srvReassemblyMemory; /* server packet memory used */
418 struct SnifferSession* next; /* for hash table list */
419 byte* ticketID; /* mac ID of session ticket */
420#ifdef HAVE_SNI
421 const char* sni; /* server name indication */
422#endif
423#ifdef HAVE_EXTENDED_MASTER
424 HsHashes* hash;
425#endif
426} SnifferSession;
427
428
429/* Sniffer Server List and mutex */
430static WOLFSSL_GLOBAL SnifferServer* ServerList = 0;
431static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex;
432
433
434/* Session Hash Table, mutex, and count */
435static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE];
436static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex;
437static WOLFSSL_GLOBAL int SessionCount = 0;
438
439/* Recovery of missed data switches and stats */
440static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex; /* for stats */
441static WOLFSSL_GLOBAL int RecoveryEnabled = 0; /* global switch */
442static WOLFSSL_GLOBAL int MaxRecoveryMemory = -1;
443 /* per session max recovery memory */
444static WOLFSSL_GLOBAL word32 MissedDataSessions = 0;
445 /* # of sessions with missed data */
446
447/* Connection Info Callback */
448static WOLFSSL_GLOBAL SSLConnCb ConnectionCb;
449static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL;
450
451#ifdef WOLFSSL_SNIFFER_STATS
452/* Sessions Statistics */
453static WOLFSSL_GLOBAL SSLStats SnifferStats;
454static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex;
455#endif
456
457#ifdef WOLFSSL_SNIFFER_WATCH
458/* Watch Key Callback */
459static WOLFSSL_GLOBAL SSLWatchCb WatchCb;
460static WOLFSSL_GLOBAL void* WatchCbCtx = NULL;
461#endif
462
463#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
464/* Store Data Callback */
465static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb;
466#endif
467
468
469static void UpdateMissedDataSessions(void)
470{
471 wc_LockMutex(&RecoveryMutex);
472 MissedDataSessions += 1;
473 wc_UnLockMutex(&RecoveryMutex);
474}
475
476
477#ifdef WOLFSSL_SNIFFER_STATS
478#define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0)
479#define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0)
480#define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0)
481#define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1)
482#define ADD_TO_STAT(x,y) do { LOCK_STAT(); \
483 NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0)
484#define INC_STAT(x) do { LOCK_STAT(); \
485 NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0)
486#endif
487
488
489#ifdef WOLF_CRYPTO_CB
490 static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID;
491#endif
492
493
494/* Initialize overall Sniffer */
495void ssl_InitSniffer(void)
496{
497 wolfSSL_Init();
498 wc_InitMutex(&ServerListMutex);
499 wc_InitMutex(&SessionMutex);
500 wc_InitMutex(&RecoveryMutex);
501#ifdef WOLFSSL_SNIFFER_STATS
502 XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
503 wc_InitMutex(&StatsMutex);
504#endif
505#ifdef WOLF_CRYPTO_CB
506 #ifdef HAVE_INTEL_QA_SYNC
507 CryptoDeviceId = wc_CryptoCb_InitIntelQa();
508 if (INVALID_DEVID == CryptoDeviceId) {
509 printf("Couldn't init the Intel QA\n");
510 }
511 #endif
512 #ifdef HAVE_CAVIUM_OCTEON_SYNC
513 CryptoDeviceId = wc_CryptoCb_InitOcteon();
514 if (INVALID_DEVID == CryptoDeviceId) {
515 printf("Couldn't init the Intel QA\n");
516 }
517 #endif
518#endif
519}
520
521
522#ifdef HAVE_SNI
523
524/* Free Named Key and the zero out the private key it holds */
525static void FreeNamedKey(NamedKey* in)
526{
527 if (in) {
528 if (in->key) {
529 ForceZero(in->key, in->keySz);
530 XFREE(in->key, NULL, DYNAMIC_TYPE_X509);
531 }
532 XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
533 }
534}
535
536
537static void FreeNamedKeyList(NamedKey* in)
538{
539 NamedKey* next;
540
541 while (in) {
542 next = in->next;
543 FreeNamedKey(in);
544 in = next;
545 }
546}
547
548#endif
549
550
551/* Free Sniffer Server's resources/self */
552static void FreeSnifferServer(SnifferServer* srv)
553{
554 if (srv) {
555#ifdef HAVE_SNI
556 wc_LockMutex(&srv->namedKeysMutex);
557 FreeNamedKeyList(srv->namedKeys);
558 wc_UnLockMutex(&srv->namedKeysMutex);
559 wc_FreeMutex(&srv->namedKeysMutex);
560#endif
561 SSL_CTX_free(srv->ctx);
562 }
563 XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
564}
565
566
567/* free PacketBuffer's resources/self */
568static void FreePacketBuffer(PacketBuffer* del)
569{
570 if (del) {
571 XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
572 XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB);
573 }
574}
575
576
577/* remove PacketBuffer List */
578static void FreePacketList(PacketBuffer* in)
579{
580 if (in) {
581 PacketBuffer* del;
582 PacketBuffer* packet = in;
583
584 while (packet) {
585 del = packet;
586 packet = packet->next;
587 FreePacketBuffer(del);
588 }
589 }
590}
591
592
593/* Free Sniffer Session's resources/self */
594static void FreeSnifferSession(SnifferSession* session)
595{
596 if (session) {
597 SSL_free(session->sslClient);
598 SSL_free(session->sslServer);
599
600 FreePacketList(session->cliReassemblyList);
601 FreePacketList(session->srvReassemblyList);
602
603 XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
604#ifdef HAVE_EXTENDED_MASTER
605 XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
606#endif
607 }
608 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
609}
610
611
612/* Free overall Sniffer */
613void ssl_FreeSniffer(void)
614{
615 SnifferServer* srv;
616 SnifferServer* removeServer;
617 SnifferSession* session;
618 SnifferSession* removeSession;
619 int i;
620
621 wc_LockMutex(&ServerListMutex);
622 wc_LockMutex(&SessionMutex);
623
624 srv = ServerList;
625 while (srv) {
626 removeServer = srv;
627 srv = srv->next;
628 FreeSnifferServer(removeServer);
629 }
630
631 for (i = 0; i < HASH_SIZE; i++) {
632 session = SessionTable[i];
633 while (session) {
634 removeSession = session;
635 session = session->next;
636 FreeSnifferSession(removeSession);
637 }
638 }
639
640 wc_UnLockMutex(&SessionMutex);
641 wc_UnLockMutex(&ServerListMutex);
642
643 wc_FreeMutex(&RecoveryMutex);
644 wc_FreeMutex(&SessionMutex);
645 wc_FreeMutex(&ServerListMutex);
646
647#ifdef WOLF_CRYPTO_CB
648#ifdef HAVE_INTEL_QA_SYNC
649 wc_CryptoCb_CleanupIntelQa(&CryptoDeviceId);
650#endif
651#ifdef HAVE_CAVIUM_OCTEON_SYNC
652 wc_CryptoCb_CleanupOcteon(&CryptoDeviceId);
653#endif
654#endif
655
656 if (TraceFile) {
657 TraceOn = 0;
658 fclose(TraceFile);
659 TraceFile = NULL;
660 }
661
662 wolfSSL_Cleanup();
663}
664
665
666#ifdef HAVE_EXTENDED_MASTER
667
668static int HashInit(HsHashes* hash)
669{
670 int ret = 0;
671
672 XMEMSET(hash, 0, sizeof(HsHashes));
673
674#ifndef NO_OLD_TLS
675#ifndef NO_SHA
676 if (ret == 0)
677 ret = wc_InitSha(&hash->hashSha);
678#endif
679#ifndef NO_MD5
680 if (ret == 0) {
681 ret = wc_InitMd5(&hash->hashMd5);
682 }
683#endif
684#endif
685#ifndef NO_SHA256
686 if (ret == 0)
687 ret = wc_InitSha256(&hash->hashSha256);
688#endif
689#ifdef WOLFSSL_SHA384
690 if (ret == 0)
691 ret = wc_InitSha384(&hash->hashSha384);
692#endif
693
694 return ret;
695}
696
697
698static int HashUpdate(HsHashes* hash, const byte* input, int sz)
699{
700 int ret = 0;
701
702 input -= HANDSHAKE_HEADER_SZ;
703 sz += HANDSHAKE_HEADER_SZ;
704
705#ifndef NO_OLD_TLS
706#ifndef NO_SHA
707 if (ret == 0)
708 ret = wc_ShaUpdate(&hash->hashSha, input, sz);
709#endif
710#ifndef NO_MD5
711 if (ret == 0) {
712 ret = wc_Md5Update(&hash->hashMd5, input, sz);
713 }
714#endif
715#endif
716#ifndef NO_SHA256
717 if (ret == 0)
718 ret = wc_Sha256Update(&hash->hashSha256, input, sz);
719#endif
720#ifdef WOLFSSL_SHA384
721 if (ret == 0)
722 ret = wc_Sha384Update(&hash->hashSha384, input, sz);
723#endif
724
725 return ret;
726}
727
728
729static int HashCopy(HS_Hashes* d, HsHashes* s)
730{
731#ifndef NO_OLD_TLS
732#ifndef NO_SHA
733 XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
734#endif
735#ifndef NO_MD5
736 XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
737#endif
738#endif
739
740#ifndef NO_SHA256
741 XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
742#endif
743#ifdef WOLFSSL_SHA384
744 XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
745#endif
746
747 return 0;
748}
749
750#endif
751
752
753/* Initialize a SnifferServer */
754static void InitSnifferServer(SnifferServer* sniffer)
755{
756 XMEMSET(sniffer, 0, sizeof(SnifferServer));
757}
758
759
760/* Initialize session flags */
761static void InitFlags(Flags* flags)
762{
763 XMEMSET(flags, 0, sizeof(Flags));
764}
765
766
767/* Initialize FIN Capture */
768static void InitFinCapture(FinCaputre* cap)
769{
770 XMEMSET(cap, 0, sizeof(FinCaputre));
771}
772
773
774/* Initialize a Sniffer Session */
775static void InitSession(SnifferSession* session)
776{
777 XMEMSET(session, 0, sizeof(SnifferSession));
778 InitFlags(&session->flags);
779 InitFinCapture(&session->finCaputre);
780}
781
782
783/* IP Info from IP Header */
784typedef struct IpInfo {
785 int length; /* length of this header */
786 int total; /* total length of fragment */
787 IpAddrInfo src; /* network order source address */
788 IpAddrInfo dst; /* network order destination address */
789} IpInfo;
790
791
792/* TCP Info from TCP Header */
793typedef struct TcpInfo {
794 int srcPort; /* source port */
795 int dstPort; /* source port */
796 int length; /* length of this header */
797 word32 sequence; /* sequence number */
798 word32 ackNumber; /* ack number */
799 byte fin; /* FIN set */
800 byte rst; /* RST set */
801 byte syn; /* SYN set */
802 byte ack; /* ACK set */
803} TcpInfo;
804
805
806/* Tcp Pseudo Header for Checksum calculation */
807typedef struct TcpPseudoHdr {
808 word32 src; /* source address */
809 word32 dst; /* destination address */
810 byte rsv; /* reserved, always 0 */
811 byte protocol; /* IP protocol */
812 word16 length; /* tcp header length + data length (doesn't include */
813 /* pseudo header length) network order */
814} TcpPseudoHdr;
815
816
817/* Password Setting Callback */
818static int SetPassword(char* passwd, int sz, int rw, void* userdata)
819{
820 (void)rw;
821 XSTRNCPY(passwd, (const char*)userdata, sz);
822 return (int)XSTRLEN((const char*)userdata);
823}
824
825
826/* Ethernet Header */
827typedef struct EthernetHdr {
828 byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */
829 byte src[ETHER_IF_ADDR_LEN]; /* source host address */
830 word16 type; /* IP, ARP, etc */
831} EthernetHdr;
832
833
834/* IPv4 Header */
835typedef struct IpHdr {
836 byte ver_hl; /* version/header length */
837 byte tos; /* type of service */
838 word16 length; /* total length */
839 word16 id; /* identification */
840 word16 offset; /* fragment offset field */
841 byte ttl; /* time to live */
842 byte protocol; /* protocol */
843 word16 sum; /* checksum */
844 word32 src; /* source address */
845 word32 dst; /* destination address */
846} IpHdr;
847
848
849/* IPv6 Header */
850typedef struct Ip6Hdr {
851 byte ver_hl; /* version/traffic class high */
852 byte tc_fl; /* traffic class low/flow label high */
853 word16 fl; /* flow label low */
854 word16 length; /* payload length */
855 byte next_header; /* next header (6 for TCP, any other skip) */
856 byte hl; /* hop limit */
857 byte src[16]; /* source address */
858 byte dst[16]; /* destination address */
859} Ip6Hdr;
860
861
862/* IPv6 extension header */
863typedef struct Ip6ExtHdr {
864 byte next_header; /* next header (6 for TCP, any other skip) */
865 byte length; /* length in 8-octet units - 1 */
866 byte reserved[6];
867} Ip6ExtHdr;
868
869
870#define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4)
871#define IP_V(ip) ( ((ip)->ver_hl) >> 4)
872
873/* TCP Header */
874typedef struct TcpHdr {
875 word16 srcPort; /* source port */
876 word16 dstPort; /* destination port */
877 word32 sequence; /* sequence number */
878 word32 ack; /* acknowledgment number */
879 byte offset; /* data offset, reserved */
880 byte flags; /* option flags */
881 word16 window; /* window */
882 word16 sum; /* checksum */
883 word16 urgent; /* urgent pointer */
884} TcpHdr;
885
886#define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4)
887#define TCP_FIN 0x01
888#define TCP_SYN 0x02
889#define TCP_RST 0x04
890#define TCP_ACK 0x10
891
892
893
894
895
896/* Use platform specific GetError to write to trace file if tracing */
897static void Trace(int idx)
898{
899 if (TraceOn) {
900 char myBuffer[MAX_ERROR_LEN];
901 GetError(idx, myBuffer);
902 fprintf(TraceFile, "\t%s\n", myBuffer);
903#ifdef DEBUG_SNIFFER
904 fprintf(stderr, "\t%s\n", myBuffer);
905#endif
906 }
907}
908
909
910/* Show TimeStamp for beginning of packet Trace */
911static void TraceHeader(void)
912{
913 if (TraceOn) {
914 time_t ticks = time(NULL);
915 fprintf(TraceFile, "\n%s", ctime(&ticks));
916 }
917}
918
919
920/* Show Set Server info for Trace */
921static void TraceSetServer(const char* srv, int port, const char* keyFile)
922{
923 if (TraceOn) {
924 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
925 fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
926 keyFile);
927 }
928}
929
930
931#ifdef HAVE_SNI
932
933/* Show Set Named Server info for Trace */
934static void TraceSetNamedServer(const char* name,
935 const char* srv, int port, const char* keyFile)
936{
937 if (TraceOn) {
938 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
939 fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
940 name, srv, port, keyFile);
941 }
942}
943
944#endif
945
946
947/* Trace got packet number */
948static void TracePacket(void)
949{
950 if (TraceOn) {
951 static word32 packetNumber = 0;
952 fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
953 ++packetNumber);
954 }
955}
956
957
958/* Convert network byte order address into human readable */
959static const char* IpToS(int version, void* src, char* dst)
960{
961 return inet_ntop(version, src, dst, TRACE_MSG_SZ);
962}
963
964
965/* Show destination and source address from Ip Hdr for packet Trace */
966static void TraceIP(IpHdr* iphdr)
967{
968 if (TraceOn) {
969 char src[TRACE_MSG_SZ];
970 char dst[TRACE_MSG_SZ];
971 fprintf(TraceFile, "\tdst:%s src:%s\n",
972 IpToS(AF_INET, &iphdr->dst, dst),
973 IpToS(AF_INET, &iphdr->src, src));
974 }
975}
976
977
978/* Show destination and source address from Ip6Hdr for packet Trace */
979static void TraceIP6(Ip6Hdr* iphdr)
980{
981 if (TraceOn) {
982 char src[TRACE_MSG_SZ];
983 char dst[TRACE_MSG_SZ];
984 fprintf(TraceFile, "\tdst: %s src: %s\n",
985 IpToS(AF_INET6, iphdr->dst, dst),
986 IpToS(AF_INET6, iphdr->src, src));
987 }
988}
989
990
991/* Show destination and source port from Tcp Hdr for packet Trace */
992static void TraceTcp(TcpHdr* tcphdr)
993{
994 if (TraceOn) {
995 fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
996 ntohs(tcphdr->srcPort));
997 }
998}
999
1000
1001/* Show sequence and payload length for Trace */
1002static void TraceSequence(word32 seq, int len)
1003{
1004 if (TraceOn) {
1005 fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
1006 }
1007}
1008
1009
1010/* Show sequence and payload length for Trace */
1011static void TraceAck(word32 ack, word32 expected)
1012{
1013 if (TraceOn) {
1014 fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
1015 }
1016}
1017
1018
1019/* Show relative expected and relative received sequences */
1020static void TraceRelativeSequence(word32 expected, word32 got)
1021{
1022 if (TraceOn) {
1023 fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
1024 expected, got);
1025 }
1026}
1027
1028
1029/* Show server sequence startup from SYN */
1030static void TraceServerSyn(word32 seq)
1031{
1032 if (TraceOn) {
1033 fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
1034 }
1035}
1036
1037
1038/* Show client sequence startup from SYN */
1039static void TraceClientSyn(word32 seq)
1040{
1041 if (TraceOn) {
1042 fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
1043 }
1044}
1045
1046
1047/* Show client FIN capture */
1048static void TraceClientFin(word32 finSeq, word32 relSeq)
1049{
1050 if (TraceOn) {
1051 fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
1052 finSeq, relSeq);
1053 }
1054}
1055
1056
1057/* Show server FIN capture */
1058static void TraceServerFin(word32 finSeq, word32 relSeq)
1059{
1060 if (TraceOn) {
1061 fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
1062 finSeq, relSeq);
1063 }
1064}
1065
1066
1067/* Show number of SSL data bytes decoded, could be 0 (ok) */
1068static void TraceGotData(int bytes)
1069{
1070 if (TraceOn) {
1071 fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
1072 }
1073}
1074
1075
1076/* Show bytes added to old SSL App data */
1077static void TraceAddedData(int newBytes, int existingBytes)
1078{
1079 if (TraceOn) {
1080 fprintf(TraceFile,
1081 "\t%d bytes added to %d existing bytes in User Buffer\n",
1082 newBytes, existingBytes);
1083 }
1084}
1085
1086
1087/* Show Stale Session */
1088static void TraceStaleSession(void)
1089{
1090 if (TraceOn) {
1091 fprintf(TraceFile, "\tFound a stale session\n");
1092 }
1093}
1094
1095
1096/* Show Finding Stale Sessions */
1097static void TraceFindingStale(void)
1098{
1099 if (TraceOn) {
1100 fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
1101 }
1102}
1103
1104
1105/* Show Removed Session */
1106static void TraceRemovedSession(void)
1107{
1108 if (TraceOn) {
1109 fprintf(TraceFile, "\tRemoved it\n");
1110 }
1111}
1112
1113
1114/* Show SSLInfo if provided and is valid. */
1115static void TraceSessionInfo(SSLInfo* sslInfo)
1116{
1117 if (TraceOn) {
1118 if (sslInfo != NULL && sslInfo->isValid) {
1119 fprintf(TraceFile,
1120 "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) "
1121 #ifdef HAVE_SNI
1122 "sni:(%s) "
1123 #endif
1124 "keySize:(%u)\n",
1125 sslInfo->protocolVersionMajor,
1126 sslInfo->protocolVersionMinor,
1127 sslInfo->serverCipherSuite0,
1128 sslInfo->serverCipherSuite,
1129 sslInfo->serverCipherSuiteName,
1130 #ifdef HAVE_SNI
1131 sslInfo->serverNameIndication,
1132 #endif
1133 sslInfo->keySize);
1134 }
1135 }
1136}
1137
1138
1139#ifdef WOLFSSL_SNIFFER_STATS
1140
1141/* Show value added to a named statistic. */
1142static void TraceStat(const char* name, int add)
1143{
1144 if (TraceOn) {
1145 fprintf(TraceFile, "\tAdding %d to %s\n", add, name);
1146 }
1147}
1148
1149#endif
1150
1151
1152/* Set user error string */
1153static void SetError(int idx, char* error, SnifferSession* session, int fatal)
1154{
1155 GetError(idx, error);
1156 Trace(idx);
1157 if (session && fatal == FATAL_ERROR_STATE)
1158 session->flags.fatalError = 1;
1159}
1160
1161
1162/* Compare IpAddrInfo structs */
1163static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r)
1164{
1165 if (l.version == r.version) {
1166 if (l.version == IPV4)
1167 return (l.ip4 == r.ip4);
1168 else if (l.version == IPV6)
1169 return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
1170 }
1171 return 0;
1172}
1173
1174
1175#ifndef WOLFSSL_SNIFFER_WATCH
1176
1177/* See if this IPV4 network order address has been registered */
1178/* return 1 is true, 0 is false */
1179static int IsServerRegistered(word32 addr)
1180{
1181 int ret = 0; /* false */
1182 SnifferServer* sniffer;
1183
1184 wc_LockMutex(&ServerListMutex);
1185
1186 sniffer = ServerList;
1187 while (sniffer) {
1188 if (sniffer->server.ip4 == addr) {
1189 ret = 1;
1190 break;
1191 }
1192 sniffer = sniffer->next;
1193 }
1194
1195 wc_UnLockMutex(&ServerListMutex);
1196
1197 return ret;
1198}
1199
1200
1201/* See if this port has been registered to watch */
1202/* See if this IPV4 network order address has been registered */
1203/* return 1 is true, 0 is false */
1204static int IsServerRegistered6(byte* addr)
1205{
1206 int ret = 0; /* false */
1207 SnifferServer* sniffer;
1208
1209 wc_LockMutex(&ServerListMutex);
1210
1211 sniffer = ServerList;
1212 while (sniffer) {
1213 if (sniffer->server.version == IPV6 &&
1214 0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
1215 ret = 1;
1216 break;
1217 }
1218 sniffer = sniffer->next;
1219 }
1220
1221 wc_UnLockMutex(&ServerListMutex);
1222
1223 return ret;
1224}
1225
1226
1227/* See if this port has been registered to watch */
1228/* return 1 is true, 0 is false */
1229static int IsPortRegistered(word32 port)
1230{
1231 int ret = 0; /* false */
1232 SnifferServer* sniffer;
1233
1234 wc_LockMutex(&ServerListMutex);
1235
1236 sniffer = ServerList;
1237 while (sniffer) {
1238 if (sniffer->port == (int)port) {
1239 ret = 1;
1240 break;
1241 }
1242 sniffer = sniffer->next;
1243 }
1244
1245 wc_UnLockMutex(&ServerListMutex);
1246
1247 return ret;
1248}
1249
1250#endif
1251
1252
1253/* Get SnifferServer from IP and Port */
1254static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
1255{
1256 SnifferServer* sniffer;
1257
1258 wc_LockMutex(&ServerListMutex);
1259
1260 sniffer = ServerList;
1261
1262#ifndef WOLFSSL_SNIFFER_WATCH
1263 while (sniffer) {
1264 if (sniffer->port == tcpInfo->srcPort &&
1265 MatchAddr(sniffer->server, ipInfo->src))
1266 break;
1267 if (sniffer->port == tcpInfo->dstPort &&
1268 MatchAddr(sniffer->server, ipInfo->dst))
1269 break;
1270
1271 sniffer = sniffer->next;
1272 }
1273#else
1274 (void)ipInfo;
1275 (void)tcpInfo;
1276#endif
1277
1278 wc_UnLockMutex(&ServerListMutex);
1279
1280 return sniffer;
1281}
1282
1283
1284/* Hash the Session Info, return hash row */
1285static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
1286{
1287 word32 hash = 1;
1288
1289 if (ipInfo->src.version == IPV4) {
1290 hash *= ipInfo->src.ip4 * ipInfo->dst.ip4;
1291 }
1292 else if (ipInfo->src.version == IPV6) {
1293 word32* x;
1294 word32 y;
1295 x = (word32*)ipInfo->src.ip6;
1296 y = x[0] ^ x[1] ^ x[2] ^ x[3];
1297 hash *= y;
1298 x = (word32*)ipInfo->dst.ip6;
1299 y = x[0] ^ x[1] ^ x[2] ^ x[3];
1300 hash *= y;
1301 }
1302 hash *= tcpInfo->srcPort * tcpInfo->dstPort;
1303
1304 return hash % HASH_SIZE;
1305}
1306
1307
1308/* Get Existing SnifferSession from IP and Port */
1309static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
1310{
1311 SnifferSession* session;
1312 time_t currTime = time(NULL);
1313 word32 row = SessionHash(ipInfo, tcpInfo);
1314
1315 assert(row <= HASH_SIZE);
1316
1317 wc_LockMutex(&SessionMutex);
1318
1319 session = SessionTable[row];
1320 while (session) {
1321 if (MatchAddr(session->server, ipInfo->src) &&
1322 MatchAddr(session->client, ipInfo->dst) &&
1323 session->srvPort == tcpInfo->srcPort &&
1324 session->cliPort == tcpInfo->dstPort)
1325 break;
1326
1327 if (MatchAddr(session->client, ipInfo->src) &&
1328 MatchAddr(session->server, ipInfo->dst) &&
1329 session->cliPort == tcpInfo->srcPort &&
1330 session->srvPort == tcpInfo->dstPort)
1331 break;
1332
1333 session = session->next;
1334 }
1335
1336 if (session)
1337 session->lastUsed= currTime; /* keep session alive, remove stale will */
1338 /* leave alone */
1339 wc_UnLockMutex(&SessionMutex);
1340
1341 /* determine side */
1342 if (session) {
1343 if (MatchAddr(ipInfo->dst, session->server) &&
1344 tcpInfo->dstPort == session->srvPort) {
1345
1346 session->flags.side = WOLFSSL_SERVER_END;
1347 }
1348 else {
1349 session->flags.side = WOLFSSL_CLIENT_END;
1350 }
1351 }
1352
1353 return session;
1354}
1355
1356
1357#if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH)
1358
1359static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1360 const char* keyFile, int typeKey,
1361 const char* password)
1362{
1363 byte* loadBuf;
1364 long fileSz = 0;
1365 XFILE file;
1366 int ret;
1367
1368 if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1369 return -1;
1370 }
1371
1372 file = XFOPEN(keyFile, "rb");
1373 if (file == XBADFILE) return -1;
1374 if(XFSEEK(file, 0, XSEEK_END) != 0) {
1375 XFCLOSE(file);
1376 return -1;
1377 }
1378 fileSz = XFTELL(file);
1379 if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) {
1380 XFCLOSE(file);
1381 return -1;
1382 }
1383 XREWIND(file);
1384
1385 loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE);
1386 if (loadBuf == NULL) {
1387 XFCLOSE(file);
1388 return -1;
1389 }
1390
1391 ret = (int)XFREAD(loadBuf, 1, fileSz, file);
1392 XFCLOSE(file);
1393
1394 if (ret != fileSz) {
1395 XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1396 return -1;
1397 }
1398
1399 if (typeKey == WOLFSSL_FILETYPE_PEM) {
1400 byte* saveBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509);
1401 int saveBufSz = 0;
1402
1403 ret = -1;
1404 if (saveBuf != NULL) {
1405 saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
1406 saveBuf, (int)fileSz, password);
1407 if (saveBufSz < 0) {
1408 saveBufSz = 0;
1409 XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509);
1410 saveBuf = NULL;
1411 }
1412 else
1413 ret = 0;
1414 }
1415
1416 ForceZero(loadBuf, (word32)fileSz);
1417 XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1418
1419 if (saveBuf) {
1420 *keyBuf = saveBuf;
1421 *keyBufSz = (word32)saveBufSz;
1422 }
1423 }
1424 else {
1425 *keyBuf = loadBuf;
1426 *keyBufSz = (word32)fileSz;
1427 }
1428
1429 if (ret < 0) {
1430 return -1;
1431 }
1432
1433 return ret;
1434}
1435
1436#endif
1437
1438
1439#ifdef WOLFSSL_SNIFFER_WATCH
1440
1441static int CreateWatchSnifferServer(char* error)
1442{
1443 SnifferServer* sniffer;
1444
1445 sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL,
1446 DYNAMIC_TYPE_SNIFFER_SERVER);
1447 if (sniffer == NULL) {
1448 SetError(MEMORY_STR, error, NULL, 0);
1449 return -1;
1450 }
1451 InitSnifferServer(sniffer);
1452 sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
1453 if (!sniffer->ctx) {
1454 SetError(MEMORY_STR, error, NULL, 0);
1455 FreeSnifferServer(sniffer);
1456 return -1;
1457 }
1458#ifdef WOLF_CRYPTO_CB
1459 if (CryptoDeviceId != INVALID_DEVID)
1460 wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1461#endif
1462 ServerList = sniffer;
1463
1464 return 0;
1465}
1466
1467#endif
1468
1469
1470static int SetNamedPrivateKey(const char* name, const char* address, int port,
1471 const char* keyFile, int typeKey, const char* password, char* error)
1472{
1473 SnifferServer* sniffer;
1474 int ret;
1475 int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
1476 WOLFSSL_FILETYPE_ASN1;
1477 int isNew = 0;
1478 IpAddrInfo serverIp;
1479
1480#ifdef HAVE_SNI
1481 NamedKey* namedKey = NULL;
1482#endif
1483
1484 (void)name;
1485#ifdef HAVE_SNI
1486 if (name != NULL) {
1487 namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey),
1488 NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
1489 if (namedKey == NULL) {
1490 SetError(MEMORY_STR, error, NULL, 0);
1491 return -1;
1492 }
1493 XMEMSET(namedKey, 0, sizeof(NamedKey));
1494
1495 namedKey->nameSz = (word32)XSTRLEN(name);
1496 if (namedKey->nameSz > sizeof(namedKey->name)-1)
1497 namedKey->nameSz = sizeof(namedKey->name)-1;
1498 XSTRNCPY(namedKey->name, name, namedKey->nameSz);
1499 namedKey->name[MAX_SERVER_NAME-1] = '\0';
1500
1501 ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1502 keyFile, type, password);
1503 if (ret < 0) {
1504 SetError(KEY_FILE_STR, error, NULL, 0);
1505 FreeNamedKey(namedKey);
1506 return -1;
1507 }
1508 }
1509#endif
1510
1511 serverIp.version = IPV4;
1512 serverIp.ip4 = inet_addr(address);
1513 if (serverIp.ip4 == INADDR_NONE) {
1514 if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) {
1515 serverIp.version = IPV6;
1516 }
1517 }
1518 sniffer = ServerList;
1519 while (sniffer != NULL &&
1520 (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
1521 sniffer = sniffer->next;
1522 }
1523
1524 if (sniffer == NULL) {
1525 isNew = 1;
1526 sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
1527 NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
1528 if (sniffer == NULL) {
1529 SetError(MEMORY_STR, error, NULL, 0);
1530#ifdef HAVE_SNI
1531 FreeNamedKey(namedKey);
1532#endif
1533 return -1;
1534 }
1535 InitSnifferServer(sniffer);
1536
1537 XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1538 sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1539 sniffer->server = serverIp;
1540 sniffer->port = port;
1541
1542 sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method());
1543 if (!sniffer->ctx) {
1544 SetError(MEMORY_STR, error, NULL, 0);
1545#ifdef HAVE_SNI
1546 FreeNamedKey(namedKey);
1547#endif
1548 FreeSnifferServer(sniffer);
1549 return -1;
1550 }
1551 }
1552
1553 if (name == NULL) {
1554 if (password) {
1555 #ifdef WOLFSSL_ENCRYPTED_KEYS
1556 SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1557 SSL_CTX_set_default_passwd_cb_userdata(
1558 sniffer->ctx, (void*)password);
1559 #endif
1560 }
1561 ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1562 if (ret != WOLFSSL_SUCCESS) {
1563 SetError(KEY_FILE_STR, error, NULL, 0);
1564 if (isNew)
1565 FreeSnifferServer(sniffer);
1566 return -1;
1567 }
1568 #ifdef WOLF_CRYPTO_CB
1569 wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1570 #endif
1571 }
1572#ifdef HAVE_SNI
1573 else {
1574 wc_LockMutex(&sniffer->namedKeysMutex);
1575 namedKey->next = sniffer->namedKeys;
1576 sniffer->namedKeys = namedKey;
1577 wc_UnLockMutex(&sniffer->namedKeysMutex);
1578 }
1579#endif
1580
1581 if (isNew) {
1582 sniffer->next = ServerList;
1583 ServerList = sniffer;
1584 }
1585
1586 return 0;
1587}
1588
1589
1590#ifdef HAVE_SNI
1591
1592/* Sets the private key for a specific name, server and port */
1593/* returns 0 on success, -1 on error */
1594int ssl_SetNamedPrivateKey(const char* name,
1595 const char* address, int port,
1596 const char* keyFile, int typeKey,
1597 const char* password, char* error)
1598{
1599 int ret;
1600
1601 TraceHeader();
1602 TraceSetNamedServer(name, address, port, keyFile);
1603
1604 wc_LockMutex(&ServerListMutex);
1605 ret = SetNamedPrivateKey(name, address, port, keyFile,
1606 typeKey, password, error);
1607 wc_UnLockMutex(&ServerListMutex);
1608
1609 if (ret == 0)
1610 Trace(NEW_SERVER_STR);
1611
1612 return ret;
1613}
1614
1615#endif
1616
1617
1618/* Sets the private key for a specific server and port */
1619/* returns 0 on success, -1 on error */
1620int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
1621 int typeKey, const char* password, char* error)
1622{
1623 int ret;
1624
1625 TraceHeader();
1626 TraceSetServer(address, port, keyFile);
1627
1628 wc_LockMutex(&ServerListMutex);
1629 ret = SetNamedPrivateKey(NULL, address, port, keyFile,
1630 typeKey, password, error);
1631 wc_UnLockMutex(&ServerListMutex);
1632
1633 if (ret == 0)
1634 Trace(NEW_SERVER_STR);
1635
1636 return ret;
1637}
1638
1639
1640/* Check IP Header for IPV6, TCP, and a registered server address */
1641/* returns 0 on success, -1 on error */
1642static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
1643{
1644 int version = IP_V(iphdr);
1645 int exthdrsz = IP6_HDR_SZ;
1646
1647 TraceIP6(iphdr);
1648 Trace(IP_CHECK_STR);
1649
1650 if (version != IPV6) {
1651 SetError(BAD_IPVER_STR, error, NULL, 0);
1652 return -1;
1653 }
1654
1655 /* Here, we need to move onto next header if not TCP. */
1656 if (iphdr->next_header != TCP_PROTOCOL) {
1657 Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ);
1658 do {
1659 int hdrsz = (exthdr->length + 1) * 8;
1660 if (hdrsz > length - exthdrsz) {
1661 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
1662 return -1;
1663 }
1664 exthdrsz += hdrsz;
1665 exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
1666 }
1667 while (exthdr->next_header != TCP_PROTOCOL &&
1668 exthdr->next_header != NO_NEXT_HEADER);
1669 }
1670
1671#ifndef WOLFSSL_SNIFFER_WATCH
1672 if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) {
1673 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1674 return -1;
1675 }
1676#endif
1677
1678 info->length = exthdrsz;
1679 info->total = ntohs(iphdr->length) + info->length;
1680 /* IPv6 doesn't include its own header size in the length like v4. */
1681 info->src.version = IPV6;
1682 XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6));
1683 info->dst.version = IPV6;
1684 XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6));
1685
1686 return 0;
1687}
1688
1689
1690/* Check IP Header for IPV4, TCP, and a registered server address */
1691/* If header IPv6, pass to CheckIp6Hdr(). */
1692/* returns 0 on success, -1 on error */
1693static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
1694{
1695 int version = IP_V(iphdr);
1696
1697 if (version == IPV6)
1698 return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error);
1699
1700 TraceIP(iphdr);
1701 Trace(IP_CHECK_STR);
1702
1703 if (version != IPV4) {
1704 SetError(BAD_IPVER_STR, error, NULL, 0);
1705 return -1;
1706 }
1707
1708 if (iphdr->protocol != TCP_PROTOCOL) {
1709 SetError(BAD_PROTO_STR, error, NULL, 0);
1710 return -1;
1711 }
1712
1713#ifndef WOLFSSL_SNIFFER_WATCH
1714 if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
1715 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1716 return -1;
1717 }
1718#endif
1719
1720 info->length = IP_HL(iphdr);
1721 info->total = ntohs(iphdr->length);
1722 info->src.version = IPV4;
1723 info->src.ip4 = iphdr->src;
1724 info->dst.version = IPV4;
1725 info->dst.ip4 = iphdr->dst;
1726
1727 if (info->total == 0)
1728 info->total = length; /* reassembled may be off */
1729
1730 return 0;
1731}
1732
1733
1734/* Check TCP Header for a registered port */
1735/* returns 0 on success, -1 on error */
1736static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
1737{
1738 TraceTcp(tcphdr);
1739 Trace(TCP_CHECK_STR);
1740 info->srcPort = ntohs(tcphdr->srcPort);
1741 info->dstPort = ntohs(tcphdr->dstPort);
1742 info->length = TCP_LEN(tcphdr);
1743 info->sequence = ntohl(tcphdr->sequence);
1744 info->fin = tcphdr->flags & TCP_FIN;
1745 info->rst = tcphdr->flags & TCP_RST;
1746 info->syn = tcphdr->flags & TCP_SYN;
1747 info->ack = tcphdr->flags & TCP_ACK;
1748 if (info->ack)
1749 info->ackNumber = ntohl(tcphdr->ack);
1750
1751#ifndef WOLFSSL_SNIFFER_WATCH
1752 if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
1753 SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
1754 return -1;
1755 }
1756#else
1757 (void)error;
1758#endif
1759
1760 return 0;
1761}
1762
1763
1764/* Decode Record Layer Header */
1765static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
1766{
1767 XMEMCPY(rh, input, RECORD_HEADER_SZ);
1768 *size = (rh->length[0] << 8) | rh->length[1];
1769
1770 if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
1771 return LENGTH_ERROR;
1772
1773 return 0;
1774}
1775
1776
1777/* Copies the session's information to the provided sslInfo. Skip copy if
1778 * SSLInfo is not provided. */
1779static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo)
1780{
1781 if (NULL != sslInfo) {
1782 XMEMSET(sslInfo, 0, sizeof(SSLInfo));
1783
1784 /* Pass back Session Info after we have processed the Server Hello. */
1785 if (0 != session->sslServer->options.cipherSuite) {
1786 const char* pCipher;
1787
1788 sslInfo->isValid = 1;
1789 sslInfo->protocolVersionMajor = session->sslServer->version.major;
1790 sslInfo->protocolVersionMinor = session->sslServer->version.minor;
1791 sslInfo->serverCipherSuite0 =
1792 session->sslServer->options.cipherSuite0;
1793 sslInfo->serverCipherSuite =
1794 session->sslServer->options.cipherSuite;
1795
1796 pCipher = wolfSSL_get_cipher(session->sslServer);
1797 if (NULL != pCipher) {
1798 XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher,
1799 sizeof(sslInfo->serverCipherSuiteName));
1800 sslInfo->serverCipherSuiteName
1801 [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0';
1802 }
1803 sslInfo->keySize = session->keySz;
1804 #ifdef HAVE_SNI
1805 if (NULL != session->sni) {
1806 XSTRNCPY((char*)sslInfo->serverNameIndication,
1807 session->sni, sizeof(sslInfo->serverNameIndication));
1808 sslInfo->serverNameIndication
1809 [sizeof(sslInfo->serverNameIndication) - 1] = '\0';
1810 }
1811 #endif
1812 TraceSessionInfo(sslInfo);
1813 }
1814 }
1815}
1816
1817
1818/* Call the session connection start callback. */
1819static void CallConnectionCb(SnifferSession* session)
1820{
1821 if (ConnectionCb != NULL) {
1822 SSLInfo info;
1823 CopySessionInfo(session, &info);
1824 ConnectionCb((const void*)session, &info, ConnectionCbCtx);
1825 }
1826}
1827
1828
1829/* Process Client Key Exchange, RSA or static ECDH */
1830static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
1831 SnifferSession* session, char* error)
1832{
1833 word32 idx = 0;
1834 int tryEcc = 0;
1835 int ret;
1836
1837 if (session->sslServer->buffers.key == NULL ||
1838 session->sslServer->buffers.key->buffer == NULL ||
1839 session->sslServer->buffers.key->length == 0) {
1840
1841 SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
1842 return -1;
1843 }
1844
1845 {
1846 RsaKey key;
1847 int length;
1848
1849 ret = wc_InitRsaKey(&key, 0);
1850 if (ret == 0) {
1851 ret = wc_RsaPrivateKeyDecode(
1852 session->sslServer->buffers.key->buffer,
1853 &idx, &key, session->sslServer->buffers.key->length);
1854 if (ret != 0) {
1855 tryEcc = 1;
1856 #ifndef HAVE_ECC
1857 SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
1858 #else
1859 /* If we can do ECC, this isn't fatal. Not loading an ECC
1860 * key will be fatal, though. */
1861 SetError(RSA_DECODE_STR, error, session, 0);
1862 #endif
1863 }
1864 }
1865
1866 if (ret == 0) {
1867 length = wc_RsaEncryptSize(&key);
1868 if (IsTLS(session->sslServer)) {
1869 input += 2; /* tls pre length */
1870 }
1871
1872 if (length > *sslBytes) {
1873 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
1874 ret = -1;
1875 }
1876 }
1877
1878 #ifdef WC_RSA_BLINDING
1879 if (ret == 0) {
1880 ret = wc_RsaSetRNG(&key, session->sslServer->rng);
1881 if (ret != 0) {
1882 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1883 }
1884 }
1885 #endif
1886
1887 if (ret == 0) {
1888 session->keySz = length * WOLFSSL_BIT_SIZE;
1889 /* length is the key size in bytes */
1890 session->sslServer->arrays->preMasterSz = SECRET_LEN;
1891
1892 do {
1893 #ifdef WOLFSSL_ASYNC_CRYPT
1894 ret = wc_AsyncWait(ret, &key.asyncDev,
1895 WC_ASYNC_FLAG_CALL_AGAIN);
1896 #endif
1897 if (ret >= 0) {
1898 ret = wc_RsaPrivateDecrypt(input, length,
1899 session->sslServer->arrays->preMasterSecret,
1900 session->sslServer->arrays->preMasterSz, &key);
1901 }
1902 } while (ret == WC_PENDING_E);
1903
1904 if (ret != SECRET_LEN) {
1905 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1906 }
1907 }
1908
1909 wc_FreeRsaKey(&key);
1910 }
1911
1912 if (tryEcc) {
1913#ifdef HAVE_ECC
1914 ecc_key key;
1915 ecc_key pubKey;
1916 int length, keyInit = 0, pubKeyInit = 0;
1917
1918 idx = 0;
1919 ret = wc_ecc_init(&key);
1920 if (ret == 0) {
1921 keyInit = 1;
1922 ret = wc_ecc_init(&pubKey);
1923 }
1924 if (ret == 0) {
1925 pubKeyInit = 1;
1926 ret = wc_EccPrivateKeyDecode(
1927 session->sslServer->buffers.key->buffer,
1928 &idx, &key, session->sslServer->buffers.key->length);
1929 if (ret != 0) {
1930 SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
1931 }
1932 }
1933
1934 if (ret == 0) {
1935 length = wc_ecc_size(&key) * 2 + 1;
1936 /* The length should be 2 times the key size (x and y), plus 1
1937 * for the type byte. */
1938 if (IsTLS(session->sslServer)) {
1939 input += 1; /* Don't include the TLS length for the key. */
1940 }
1941
1942 if (length + 1 > *sslBytes) {
1943 SetError(PARTIAL_INPUT_STR,
1944 error, session, FATAL_ERROR_STATE);
1945 ret = -1;
1946 }
1947 }
1948
1949 if (ret == 0) {
1950 ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF);
1951 if (ret != 0) {
1952 SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
1953 }
1954 }
1955
1956 if (ret == 0) {
1957 session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE;
1958 /* Length is in bytes. Subtract 1 for the ECC key type. Divide
1959 * by two as the key is in (x,y) coordinates, where x and y are
1960 * the same size, the key size. Convert from bytes to bits. */
1961 session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
1962
1963 do {
1964 #ifdef WOLFSSL_ASYNC_CRYPT
1965 ret = wc_AsyncWait(ret, &key.asyncDev,
1966 WC_ASYNC_FLAG_CALL_AGAIN);
1967 #endif
1968 if (ret >= 0) {
1969 ret = wc_ecc_shared_secret(&key, &pubKey,
1970 session->sslServer->arrays->preMasterSecret,
1971 &session->sslServer->arrays->preMasterSz);
1972 }
1973 } while (ret == WC_PENDING_E);
1974 }
1975
1976#ifdef WOLFSSL_SNIFFER_STATS
1977 if (ret != 0)
1978 INC_STAT(SnifferStats.sslKeyFails);
1979#endif
1980
1981 if (keyInit)
1982 wc_ecc_free(&key);
1983 if (pubKeyInit)
1984 wc_ecc_free(&pubKey);
1985#endif
1986 }
1987
1988 /* store for client side as well */
1989 XMEMCPY(session->sslClient->arrays->preMasterSecret,
1990 session->sslServer->arrays->preMasterSecret,
1991 session->sslServer->arrays->preMasterSz);
1992 session->sslClient->arrays->preMasterSz =
1993 session->sslServer->arrays->preMasterSz;
1994
1995 #ifdef SHOW_SECRETS
1996 {
1997 word32 i;
1998 printf("pre master secret: ");
1999 for (i = 0; i < session->sslServer->arrays->preMasterSz; i++)
2000 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
2001 printf("\n");
2002 }
2003 #endif
2004
2005 if (SetCipherSpecs(session->sslServer) != 0) {
2006 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2007 return -1;
2008 }
2009
2010 if (SetCipherSpecs(session->sslClient) != 0) {
2011 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2012 return -1;
2013 }
2014
2015 ret = MakeMasterSecret(session->sslServer);
2016 ret += MakeMasterSecret(session->sslClient);
2017 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
2018 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
2019
2020 if (ret != 0) {
2021 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
2022 return -1;
2023 }
2024
2025#ifdef SHOW_SECRETS
2026 {
2027 int i;
2028 printf("server master secret: ");
2029 for (i = 0; i < SECRET_LEN; i++)
2030 printf("%02x", session->sslServer->arrays->masterSecret[i]);
2031 printf("\n");
2032
2033 printf("client master secret: ");
2034 for (i = 0; i < SECRET_LEN; i++)
2035 printf("%02x", session->sslClient->arrays->masterSecret[i]);
2036 printf("\n");
2037
2038 printf("server suite = %d\n", session->sslServer->options.cipherSuite);
2039 printf("client suite = %d\n", session->sslClient->options.cipherSuite);
2040 }
2041#endif
2042
2043 CallConnectionCb(session);
2044
2045 return ret;
2046}
2047
2048
2049/* Process Session Ticket */
2050static int ProcessSessionTicket(const byte* input, int* sslBytes,
2051 SnifferSession* session, char* error)
2052{
2053 word16 len;
2054
2055 /* make sure can read through hint and len */
2056 if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
2057 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
2058 return -1;
2059 }
2060
2061 input += TICKET_HINT_LEN; /* skip over hint */
2062 *sslBytes -= TICKET_HINT_LEN;
2063
2064 len = (word16)((input[0] << 8) | input[1]);
2065 input += LENGTH_SZ;
2066 *sslBytes -= LENGTH_SZ;
2067
2068 /* make sure can read through ticket */
2069 if (len > *sslBytes || len < ID_LEN) {
2070 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
2071 return -1;
2072 }
2073
2074 /* store session with macID as sessionID */
2075 session->sslServer->options.haveSessionId = 1;
2076 XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
2077
2078 return 0;
2079}
2080
2081
2082/* Process Server Hello */
2083static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
2084 SnifferSession* session, char* error)
2085{
2086 ProtocolVersion pv;
2087 byte b, b0;
2088 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
2089 int doResume = 0;
2090 int initialBytes = *sslBytes;
2091
2092 (void)msgSz;
2093 (void)initialBytes;
2094
2095 /* make sure we didn't miss ClientHello */
2096 if (session->flags.clientHello == 0) {
2097 SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
2098 return -1;
2099 }
2100
2101 /* make sure can read through session len */
2102 if (toRead > *sslBytes) {
2103 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2104 return -1;
2105 }
2106
2107 XMEMCPY(&pv, input, VERSION_SZ);
2108 input += VERSION_SZ;
2109 *sslBytes -= VERSION_SZ;
2110
2111 session->sslServer->version = pv;
2112 session->sslClient->version = pv;
2113
2114 XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
2115 XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
2116 input += RAN_LEN;
2117 *sslBytes -= RAN_LEN;
2118
2119 b = *input++;
2120 *sslBytes -= 1;
2121
2122 /* make sure can read through compression */
2123 if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
2124 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2125 return -1;
2126 }
2127 if (b) {
2128 XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
2129 session->sslServer->options.haveSessionId = 1;
2130 }
2131 input += b;
2132 *sslBytes -= b;
2133
2134 /* cipher suite */
2135 b0 = *input++; /* first byte, ECC or not */
2136 session->sslServer->options.cipherSuite0 = b0;
2137 session->sslClient->options.cipherSuite0 = b0;
2138 b = *input++;
2139 session->sslServer->options.cipherSuite = b;
2140 session->sslClient->options.cipherSuite = b;
2141 *sslBytes -= SUITE_LEN;
2142
2143#ifdef WOLFSSL_SNIFFER_STATS
2144 {
2145 const CipherSuiteInfo* suites = GetCipherNames();
2146 int suitesSz = GetCipherNamesSize();
2147 int match = 0;
2148
2149 while (suitesSz) {
2150 if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) {
2151 match = 1;
2152 break;
2153 }
2154 suites++;
2155 suitesSz--;
2156 }
2157 if (!match)
2158 INC_STAT(SnifferStats.sslCiphersUnsupported);
2159 }
2160#endif /* WOLFSSL_SNIFFER_STATS */
2161
2162 /* compression */
2163 b = *input++;
2164 *sslBytes -= ENUM_LEN;
2165
2166 if (b) {
2167 SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
2168 return -1;
2169 }
2170
2171#ifdef HAVE_EXTENDED_MASTER
2172 /* extensions */
2173 if ((initialBytes - *sslBytes) < msgSz) {
2174 word16 len;
2175
2176 /* skip extensions until extended master secret */
2177 /* make sure can read len */
2178 if (SUITE_LEN > *sslBytes) {
2179 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2180 return -1;
2181 }
2182 len = (word16)((input[0] << 8) | input[1]);
2183 input += SUITE_LEN;
2184 *sslBytes -= SUITE_LEN;
2185 /* make sure can read through all extensions */
2186 if (len > *sslBytes) {
2187 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2188 return -1;
2189 }
2190
2191 while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
2192 byte extType[EXT_TYPE_SZ];
2193 word16 extLen;
2194
2195 extType[0] = input[0];
2196 extType[1] = input[1];
2197 input += EXT_TYPE_SZ;
2198 *sslBytes -= EXT_TYPE_SZ;
2199
2200 extLen = (word16)((input[0] << 8) | input[1]);
2201 input += LENGTH_SZ;
2202 *sslBytes -= LENGTH_SZ;
2203
2204 /* make sure can read through individual extension */
2205 if (extLen > *sslBytes) {
2206 SetError(SERVER_HELLO_INPUT_STR, error, session,
2207 FATAL_ERROR_STATE);
2208 return -1;
2209 }
2210
2211 if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
2212 session->flags.expectEms = 1;
2213 }
2214
2215 input += extLen;
2216 *sslBytes -= extLen;
2217 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
2218 }
2219 }
2220
2221 if (!session->flags.expectEms) {
2222 XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
2223 session->hash = NULL;
2224 }
2225#endif
2226
2227 if (session->sslServer->options.haveSessionId) {
2228 if (XMEMCMP(session->sslServer->arrays->sessionID,
2229 session->sslClient->arrays->sessionID, ID_LEN) == 0)
2230 doResume = 1;
2231 }
2232 else if (session->sslClient->options.haveSessionId == 0 &&
2233 session->sslServer->options.haveSessionId == 0 &&
2234 session->ticketID)
2235 doResume = 1;
2236
2237 if (session->ticketID && doResume) {
2238 /* use ticketID to retrieve from session, prefer over sessionID */
2239 XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
2240 session->sslServer->options.haveSessionId = 1; /* may not have
2241 actual sessionID */
2242 }
2243
2244 if (doResume ) {
2245 int ret = 0;
2246 SSL_SESSION* resume = GetSession(session->sslServer,
2247 session->sslServer->arrays->masterSecret, 0);
2248 if (resume == NULL) {
2249#ifdef WOLFSSL_SNIFFER_STATS
2250 INC_STAT(SnifferStats.sslResumeMisses);
2251#endif
2252 SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
2253 return -1;
2254 }
2255 /* make sure client has master secret too */
2256 XMEMCPY(session->sslClient->arrays->masterSecret,
2257 session->sslServer->arrays->masterSecret, SECRET_LEN);
2258 session->flags.resuming = 1;
2259
2260 Trace(SERVER_DID_RESUMPTION_STR);
2261#ifdef WOLFSSL_SNIFFER_STATS
2262 INC_STAT(SnifferStats.sslResumedConns);
2263 INC_STAT(SnifferStats.sslResumptionValid);
2264#endif
2265 if (SetCipherSpecs(session->sslServer) != 0) {
2266 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2267 return -1;
2268 }
2269
2270 if (SetCipherSpecs(session->sslClient) != 0) {
2271 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2272 return -1;
2273 }
2274
2275 if (session->sslServer->options.tls) {
2276 ret = DeriveTlsKeys(session->sslServer);
2277 ret += DeriveTlsKeys(session->sslClient);
2278 }
2279 else {
2280 ret = DeriveKeys(session->sslServer);
2281 ret += DeriveKeys(session->sslClient);
2282 }
2283 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
2284 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
2285
2286 if (ret != 0) {
2287 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
2288 return -1;
2289 }
2290 }
2291 else {
2292#ifdef WOLFSSL_SNIFFER_STATS
2293 INC_STAT(SnifferStats.sslStandardConns);
2294#endif
2295 }
2296#ifdef SHOW_SECRETS
2297 {
2298 int i;
2299 printf("cipher suite = 0x%02x\n",
2300 session->sslServer->options.cipherSuite);
2301 printf("server random: ");
2302 for (i = 0; i < RAN_LEN; i++)
2303 printf("%02x", session->sslServer->arrays->serverRandom[i]);
2304 printf("\n");
2305 }
2306#endif
2307 return 0;
2308}
2309
2310
2311/* Process normal Client Hello */
2312static int ProcessClientHello(const byte* input, int* sslBytes,
2313 SnifferSession* session, char* error)
2314{
2315 byte bLen;
2316 word16 len;
2317 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
2318
2319#ifdef HAVE_SNI
2320 {
2321 byte name[MAX_SERVER_NAME];
2322 word32 nameSz = sizeof(name);
2323 int ret;
2324
2325 ret = wolfSSL_SNI_GetFromBuffer(
2326 input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
2327 *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
2328 WOLFSSL_SNI_HOST_NAME, name, &nameSz);
2329
2330 if (ret == WOLFSSL_SUCCESS) {
2331 NamedKey* namedKey;
2332
2333 if (nameSz > sizeof(name) - 1)
2334 nameSz = sizeof(name) - 1;
2335 name[nameSz] = 0;
2336 wc_LockMutex(&session->context->namedKeysMutex);
2337 namedKey = session->context->namedKeys;
2338 while (namedKey != NULL) {
2339 if (nameSz == namedKey->nameSz &&
2340 XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
2341 if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
2342 namedKey->key, namedKey->keySz,
2343 WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
2344 wc_UnLockMutex(&session->context->namedKeysMutex);
2345 SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
2346 FATAL_ERROR_STATE);
2347 return -1;
2348 }
2349 session->sni = namedKey->name;
2350 break;
2351 }
2352 else
2353 namedKey = namedKey->next;
2354 }
2355 wc_UnLockMutex(&session->context->namedKeysMutex);
2356 }
2357 }
2358#endif
2359
2360 session->flags.clientHello = 1; /* don't process again */
2361
2362 /* make sure can read up to session len */
2363 if (toRead > *sslBytes) {
2364 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2365 return -1;
2366 }
2367
2368 /* skip, get negotiated one from server hello */
2369 input += VERSION_SZ;
2370 *sslBytes -= VERSION_SZ;
2371
2372 XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
2373 XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
2374
2375 input += RAN_LEN;
2376 *sslBytes -= RAN_LEN;
2377
2378 /* store session in case trying to resume */
2379 bLen = *input++;
2380 *sslBytes -= ENUM_LEN;
2381 if (bLen) {
2382 if (ID_LEN > *sslBytes) {
2383 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2384 return -1;
2385 }
2386 Trace(CLIENT_RESUME_TRY_STR);
2387 XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
2388 session->sslClient->options.haveSessionId = 1;
2389 }
2390#ifdef SHOW_SECRETS
2391 {
2392 int i;
2393 printf("client random: ");
2394 for (i = 0; i < RAN_LEN; i++)
2395 printf("%02x", session->sslServer->arrays->clientRandom[i]);
2396 printf("\n");
2397 }
2398#endif
2399
2400 input += bLen;
2401 *sslBytes -= bLen;
2402
2403 /* skip cipher suites */
2404 /* make sure can read len */
2405 if (SUITE_LEN > *sslBytes) {
2406 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2407 return -1;
2408 }
2409 len = (word16)((input[0] << 8) | input[1]);
2410 input += SUITE_LEN;
2411 *sslBytes -= SUITE_LEN;
2412 /* make sure can read suites + comp len */
2413 if (len + ENUM_LEN > *sslBytes) {
2414 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2415 return -1;
2416 }
2417 input += len;
2418 *sslBytes -= len;
2419
2420 /* skip compression */
2421 bLen = *input++;
2422 *sslBytes -= ENUM_LEN;
2423 /* make sure can read len */
2424 if (bLen > *sslBytes) {
2425 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2426 return -1;
2427 }
2428 input += bLen;
2429 *sslBytes -= bLen;
2430
2431 if (*sslBytes == 0) {
2432 /* no extensions */
2433 return 0;
2434 }
2435
2436 /* skip extensions until session ticket */
2437 /* make sure can read len */
2438 if (SUITE_LEN > *sslBytes) {
2439 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2440 return -1;
2441 }
2442 len = (word16)((input[0] << 8) | input[1]);
2443 input += SUITE_LEN;
2444 *sslBytes -= SUITE_LEN;
2445 /* make sure can read through all extensions */
2446 if (len > *sslBytes) {
2447 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2448 return -1;
2449 }
2450
2451 while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
2452 byte extType[EXT_TYPE_SZ];
2453 word16 extLen;
2454
2455 extType[0] = input[0];
2456 extType[1] = input[1];
2457 input += EXT_TYPE_SZ;
2458 *sslBytes -= EXT_TYPE_SZ;
2459
2460 extLen = (word16)((input[0] << 8) | input[1]);
2461 input += LENGTH_SZ;
2462 *sslBytes -= LENGTH_SZ;
2463
2464 /* make sure can read through individual extension */
2465 if (extLen > *sslBytes) {
2466 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2467 return -1;
2468 }
2469
2470 if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
2471
2472 /* make sure can read through ticket if there is a non blank one */
2473 if (extLen && extLen < ID_LEN) {
2474 SetError(CLIENT_HELLO_INPUT_STR, error, session,
2475 FATAL_ERROR_STATE);
2476 return -1;
2477 }
2478
2479 if (extLen) {
2480 if (session->ticketID == 0) {
2481 session->ticketID = (byte*)XMALLOC(ID_LEN,
2482 NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
2483 if (session->ticketID == 0) {
2484 SetError(MEMORY_STR, error, session,
2485 FATAL_ERROR_STATE);
2486 return -1;
2487 }
2488 }
2489 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
2490 }
2491 }
2492
2493 input += extLen;
2494 *sslBytes -= extLen;
2495 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
2496 }
2497
2498 return 0;
2499}
2500
2501
2502#ifdef WOLFSSL_SNIFFER_WATCH
2503
2504/* Process Certificate */
2505static int ProcessCertificate(const byte* input, int* sslBytes,
2506 SnifferSession* session, char* error)
2507{
2508 Sha256 sha;
2509 const byte* certChain;
2510 word32 certChainSz;
2511 word32 certSz;
2512 int ret;
2513 byte digest[SHA256_DIGEST_SIZE];
2514
2515 /* If the receiver is the server, this is the client certificate message,
2516 * and it should be ignored at this point. */
2517 if (session->flags.side == WOLFSSL_SERVER_END)
2518 return 0;
2519
2520 if (WatchCb == NULL) {
2521 SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
2522 return -1;
2523 }
2524
2525 if (*sslBytes < CERT_HEADER_SZ) {
2526 SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
2527 return -1;
2528 }
2529 ato24(input, &certChainSz);
2530 *sslBytes -= CERT_HEADER_SZ;
2531 input += CERT_HEADER_SZ;
2532
2533 if (*sslBytes < (int)certChainSz) {
2534 SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
2535 return -1;
2536 }
2537 certChain = input;
2538
2539 ato24(input, &certSz);
2540 input += OPAQUE24_LEN;
2541 if (*sslBytes < (int)certSz) {
2542 SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
2543 return -1;
2544 }
2545
2546 *sslBytes -= certChainSz;
2547
2548 ret = wc_InitSha256(&sha);
2549 if (ret == 0)
2550 ret = wc_Sha256Update(&sha, input, certSz);
2551 if (ret == 0)
2552 ret = wc_Sha256Final(&sha, digest);
2553 if (ret != 0) {
2554 SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE);
2555 return -1;
2556 }
2557
2558 ret = WatchCb((void*)session, digest, sizeof(digest),
2559 certChain, certChainSz, WatchCbCtx, error);
2560 if (ret != 0) {
2561#ifdef WOLFSSL_SNIFFER_STATS
2562 INC_STAT(SnifferStats.sslKeysUnmatched);
2563#endif
2564 SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE);
2565 return -1;
2566 }
2567 else {
2568#ifdef WOLFSSL_SNIFFER_STATS
2569 INC_STAT(SnifferStats.sslKeyMatches);
2570#endif
2571 }
2572
2573 return 0;
2574}
2575
2576#endif
2577
2578
2579/* Process Finished */
2580static int ProcessFinished(const byte* input, int size, int* sslBytes,
2581 SnifferSession* session, char* error)
2582{
2583 SSL* ssl;
2584 word32 inOutIdx = 0;
2585 int ret;
2586
2587 if (session->flags.side == WOLFSSL_SERVER_END)
2588 ssl = session->sslServer;
2589 else
2590 ssl = session->sslClient;
2591
2592 ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
2593 SNIFF);
2594 *sslBytes -= (int)inOutIdx;
2595
2596 if (ret < 0) {
2597 SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
2598 return ret;
2599 }
2600
2601 if (ret == 0 && session->flags.cached == 0) {
2602 if (session->sslServer->options.haveSessionId) {
2603 WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
2604 if (sess == NULL) {
2605 AddSession(session->sslServer); /* don't re add */
2606#ifdef WOLFSSL_SNIFFER_STATS
2607 INC_STAT(SnifferStats.sslResumptionInserts);
2608#endif
2609 }
2610 session->flags.cached = 1;
2611 }
2612 }
2613
2614 /* If receiving a finished message from one side, free the resources
2615 * from the other side's tracker. */
2616 if (session->flags.side == WOLFSSL_SERVER_END)
2617 FreeHandshakeResources(session->sslClient);
2618 else
2619 FreeHandshakeResources(session->sslServer);
2620
2621 return ret;
2622}
2623
2624
2625/* Process HandShake input */
2626static int DoHandShake(const byte* input, int* sslBytes,
2627 SnifferSession* session, char* error)
2628{
2629 byte type;
2630 int size;
2631 int ret = 0;
2632 int startBytes;
2633
2634 if (*sslBytes < HANDSHAKE_HEADER_SZ) {
2635 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
2636 return -1;
2637 }
2638 type = input[0];
2639 size = (input[1] << 16) | (input[2] << 8) | input[3];
2640
2641 input += HANDSHAKE_HEADER_SZ;
2642 *sslBytes -= HANDSHAKE_HEADER_SZ;
2643 startBytes = *sslBytes;
2644
2645 if (*sslBytes < size) {
2646 Trace(SPLIT_HANDSHAKE_MSG_STR);
2647 *sslBytes = 0;
2648 return ret;
2649 }
2650
2651 /* A session's arrays are released when the handshake is completed. */
2652 if (session->sslServer->arrays == NULL &&
2653 session->sslClient->arrays == NULL) {
2654
2655 SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
2656 return -1;
2657 }
2658
2659#ifdef HAVE_EXTENDED_MASTER
2660 if (session->hash) {
2661 if (HashUpdate(session->hash, input, size) != 0) {
2662 SetError(EXTENDED_MASTER_HASH_STR, error,
2663 session, FATAL_ERROR_STATE);
2664 return -1;
2665 }
2666 }
2667#endif
2668
2669 switch (type) {
2670 case hello_verify_request:
2671 Trace(GOT_HELLO_VERIFY_STR);
2672 break;
2673 case hello_request:
2674 Trace(GOT_HELLO_REQUEST_STR);
2675 break;
2676 case session_ticket:
2677 Trace(GOT_SESSION_TICKET_STR);
2678 ret = ProcessSessionTicket(input, sslBytes, session, error);
2679 break;
2680 case server_hello:
2681 Trace(GOT_SERVER_HELLO_STR);
2682 ret = ProcessServerHello(size, input, sslBytes, session, error);
2683 break;
2684 case certificate_request:
2685 Trace(GOT_CERT_REQ_STR);
2686 break;
2687 case server_key_exchange:
2688#ifdef WOLFSSL_SNIFFER_STATS
2689 INC_STAT(SnifferStats.sslEphemeralMisses);
2690#endif
2691 Trace(GOT_SERVER_KEY_EX_STR);
2692 /* can't know temp key passively */
2693 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2694 ret = -1;
2695 break;
2696 case certificate:
2697 Trace(GOT_CERT_STR);
2698 if (session->flags.side == WOLFSSL_SERVER_END) {
2699#ifdef WOLFSSL_SNIFFER_STATS
2700 INC_STAT(SnifferStats.sslClientAuthConns);
2701#endif
2702 }
2703#ifdef WOLFSSL_SNIFFER_WATCH
2704 ret = ProcessCertificate(input, sslBytes, session, error);
2705#endif
2706 break;
2707 case server_hello_done:
2708 Trace(GOT_SERVER_HELLO_DONE_STR);
2709 break;
2710 case finished:
2711 Trace(GOT_FINISHED_STR);
2712 ret = ProcessFinished(input, size, sslBytes, session, error);
2713 break;
2714 case client_hello:
2715 Trace(GOT_CLIENT_HELLO_STR);
2716 ret = ProcessClientHello(input, sslBytes, session, error);
2717 break;
2718 case client_key_exchange:
2719 Trace(GOT_CLIENT_KEY_EX_STR);
2720#ifdef HAVE_EXTENDED_MASTER
2721 if (session->flags.expectEms && session->hash != NULL) {
2722 if (HashCopy(session->sslServer->hsHashes,
2723 session->hash) == 0 &&
2724 HashCopy(session->sslClient->hsHashes,
2725 session->hash) == 0) {
2726
2727 session->sslServer->options.haveEMS = 1;
2728 session->sslClient->options.haveEMS = 1;
2729 }
2730 else {
2731 SetError(EXTENDED_MASTER_HASH_STR, error,
2732 session, FATAL_ERROR_STATE);
2733 ret = -1;
2734 }
2735 XMEMSET(session->hash, 0, sizeof(HsHashes));
2736 XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
2737 session->hash = NULL;
2738 }
2739 else {
2740 session->sslServer->options.haveEMS = 0;
2741 session->sslClient->options.haveEMS = 0;
2742 }
2743#endif
2744 if (ret == 0)
2745 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
2746 break;
2747 case certificate_verify:
2748 Trace(GOT_CERT_VER_STR);
2749 break;
2750 case certificate_status:
2751 Trace(GOT_CERT_STATUS_STR);
2752 break;
2753 default:
2754 SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
2755 return -1;
2756 }
2757
2758 *sslBytes = startBytes - size; /* actual bytes of full process */
2759
2760 return ret;
2761}
2762
2763
2764/* Decrypt input into plain output, 0 on success */
2765static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
2766{
2767 int ret = 0;
2768
2769 (void)output;
2770 (void)input;
2771 (void)sz;
2772
2773 switch (ssl->specs.bulk_cipher_algorithm) {
2774 #ifdef BUILD_ARC4
2775 case wolfssl_rc4:
2776 wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
2777 break;
2778 #endif
2779
2780 #ifdef BUILD_DES3
2781 case wolfssl_triple_des:
2782 ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
2783 break;
2784 #endif
2785
2786 #ifdef BUILD_AES
2787 case wolfssl_aes:
2788 ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
2789 break;
2790 #endif
2791
2792 #ifdef HAVE_HC128
2793 case wolfssl_hc128:
2794 wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
2795 break;
2796 #endif
2797
2798 #ifdef BUILD_RABBIT
2799 case wolfssl_rabbit:
2800 wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
2801 break;
2802 #endif
2803
2804 #ifdef HAVE_CAMELLIA
2805 case wolfssl_camellia:
2806 wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
2807 break;
2808 #endif
2809
2810 #ifdef HAVE_IDEA
2811 case wolfssl_idea:
2812 wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
2813 break;
2814 #endif
2815
2816 #ifdef HAVE_AESGCM
2817 case wolfssl_aes_gcm:
2818 if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
2819 {
2820 /* scratch buffer, sniffer ignores auth tag*/
2821 byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
2822
2823 byte nonce[AESGCM_NONCE_SZ];
2824 XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
2825 XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
2826
2827 if (wc_AesGcmEncrypt(ssl->decrypt.aes,
2828 output,
2829 input + AESGCM_EXP_IV_SZ,
2830 sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
2831 nonce, AESGCM_NONCE_SZ,
2832 authTag, sizeof(authTag),
2833 NULL, 0) < 0) {
2834 Trace(BAD_DECRYPT);
2835 ret = -1;
2836 }
2837 ForceZero(nonce, AESGCM_NONCE_SZ);
2838 }
2839 else {
2840 Trace(BAD_DECRYPT_SIZE);
2841 ret = -1;
2842 }
2843 break;
2844 #endif
2845
2846 #ifdef HAVE_NULL_CIPHER
2847 case wolfssl_cipher_null:
2848 XMEMCPY(output, input, sz);
2849 break;
2850 #endif
2851
2852 default:
2853 Trace(BAD_DECRYPT_TYPE);
2854 ret = -1;
2855 break;
2856 }
2857
2858 return ret;
2859}
2860
2861
2862/* Decrypt input message into output, adjust output steam if needed */
2863static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
2864 byte* output, int* error, int* advance)
2865{
2866 int ivExtra = 0;
2867
2868 int ret = Decrypt(ssl, output, input, sz);
2869 if (ret != 0) {
2870 *error = ret;
2871 return NULL;
2872 }
2873 ssl->keys.encryptSz = sz;
2874 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
2875 output += ssl->specs.block_size; /* go past TLSv1.1 IV */
2876 ivExtra = ssl->specs.block_size;
2877 *advance = ssl->specs.block_size;
2878 }
2879
2880 if (ssl->specs.cipher_type == aead) {
2881 *advance = ssl->specs.aead_mac_size;
2882 ssl->keys.padSz = ssl->specs.aead_mac_size;
2883 }
2884 else
2885 ssl->keys.padSz = ssl->specs.hash_size;
2886
2887 if (ssl->specs.cipher_type == block)
2888 ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
2889
2890 return output;
2891}
2892
2893
2894/* remove session from table, use rowHint if no info (means we have a lock) */
2895static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
2896 TcpInfo* tcpInfo, word32 rowHint)
2897{
2898 SnifferSession* previous = 0;
2899 SnifferSession* current;
2900 word32 row = rowHint;
2901 int haveLock = 0;
2902
2903 if (ipInfo && tcpInfo)
2904 row = SessionHash(ipInfo, tcpInfo);
2905 else
2906 haveLock = 1;
2907
2908 assert(row <= HASH_SIZE);
2909 Trace(REMOVE_SESSION_STR);
2910
2911 if (!haveLock)
2912 wc_LockMutex(&SessionMutex);
2913
2914 current = SessionTable[row];
2915
2916 while (current) {
2917 if (current == session) {
2918 if (previous)
2919 previous->next = current->next;
2920 else
2921 SessionTable[row] = current->next;
2922 FreeSnifferSession(session);
2923 TraceRemovedSession();
2924 break;
2925 }
2926 previous = current;
2927 current = current->next;
2928 }
2929
2930 if (!haveLock)
2931 wc_UnLockMutex(&SessionMutex);
2932}
2933
2934
2935/* Remove stale sessions from the Session Table, have a lock */
2936static void RemoveStaleSessions(void)
2937{
2938 word32 i;
2939 SnifferSession* session;
2940
2941 for (i = 0; i < HASH_SIZE; i++) {
2942 session = SessionTable[i];
2943 while (session) {
2944 SnifferSession* next = session->next;
2945 if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
2946 TraceStaleSession();
2947 RemoveSession(session, NULL, NULL, i);
2948 }
2949 session = next;
2950 }
2951 }
2952}
2953
2954
2955/* Create a new Sniffer Session */
2956static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2957 char* error)
2958{
2959 SnifferSession* session = 0;
2960 int row;
2961
2962 Trace(NEW_SESSION_STR);
2963 /* create a new one */
2964 session = (SnifferSession*)XMALLOC(sizeof(SnifferSession),
2965 NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
2966 if (session == NULL) {
2967 SetError(MEMORY_STR, error, NULL, 0);
2968 return 0;
2969 }
2970 InitSession(session);
2971#ifdef HAVE_EXTENDED_MASTER
2972 {
2973 HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes),
2974 NULL, DYNAMIC_TYPE_HASHES);
2975 if (newHash == NULL) {
2976 SetError(MEMORY_STR, error, NULL, 0);
2977 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
2978 return 0;
2979 }
2980 if (HashInit(newHash) != 0) {
2981 SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
2982 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
2983 return 0;
2984 }
2985 session->hash = newHash;
2986 }
2987#endif
2988 session->server = ipInfo->dst;
2989 session->client = ipInfo->src;
2990 session->srvPort = (word16)tcpInfo->dstPort;
2991 session->cliPort = (word16)tcpInfo->srcPort;
2992 session->cliSeqStart = tcpInfo->sequence;
2993 session->cliExpected = 1; /* relative */
2994 session->lastUsed= time(NULL);
2995 session->keySz = 0;
2996#ifdef HAVE_SNI
2997 session->sni = NULL;
2998#endif
2999
3000 session->context = GetSnifferServer(ipInfo, tcpInfo);
3001 if (session->context == NULL) {
3002 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
3003 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
3004 return 0;
3005 }
3006
3007 session->sslServer = SSL_new(session->context->ctx);
3008 if (session->sslServer == NULL) {
3009 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
3010 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
3011 return 0;
3012 }
3013 session->sslClient = SSL_new(session->context->ctx);
3014 if (session->sslClient == NULL) {
3015 SSL_free(session->sslServer);
3016 session->sslServer = 0;
3017
3018 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
3019 XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
3020 return 0;
3021 }
3022 /* put server back into server mode */
3023 session->sslServer->options.side = WOLFSSL_SERVER_END;
3024
3025 row = SessionHash(ipInfo, tcpInfo);
3026
3027 /* add it to the session table */
3028 wc_LockMutex(&SessionMutex);
3029
3030 session->next = SessionTable[row];
3031 SessionTable[row] = session;
3032
3033 SessionCount++;
3034
3035 if ( (SessionCount % HASH_SIZE) == 0) {
3036 TraceFindingStale();
3037 RemoveStaleSessions();
3038 }
3039
3040 wc_UnLockMutex(&SessionMutex);
3041
3042 /* CreateSession is called in response to a SYN packet, we know this
3043 * is headed to the server. Also we know the server is one we care
3044 * about as we've passed the GetSnifferServer() successfully. */
3045 session->flags.side = WOLFSSL_SERVER_END;
3046
3047 return session;
3048}
3049
3050
3051#ifdef OLD_HELLO_ALLOWED
3052
3053/* Process Old Client Hello Input */
3054static int DoOldHello(SnifferSession* session, const byte* sslFrame,
3055 int* rhSize, int* sslBytes, char* error)
3056{
3057 const byte* input = sslFrame;
3058 byte b0, b1;
3059 word32 idx = 0;
3060 int ret;
3061
3062 Trace(GOT_OLD_CLIENT_HELLO_STR);
3063 session->flags.clientHello = 1; /* don't process again */
3064 b0 = *input++;
3065 b1 = *input++;
3066 *sslBytes -= 2;
3067 *rhSize = ((b0 & 0x7f) << 8) | b1;
3068
3069 if (*rhSize > *sslBytes) {
3070 SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
3071 return -1;
3072 }
3073
3074 ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
3075 (word16)*rhSize);
3076 if (ret < 0 && ret != MATCH_SUITE_ERROR) {
3077 SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
3078 return -1;
3079 }
3080
3081 Trace(OLD_CLIENT_OK_STR);
3082 XMEMCPY(session->sslClient->arrays->clientRandom,
3083 session->sslServer->arrays->clientRandom, RAN_LEN);
3084
3085 *sslBytes -= *rhSize;
3086 return 0;
3087}
3088
3089#endif /* OLD_HELLO_ALLOWED */
3090
3091
3092#if 0
3093/* Calculate the TCP checksum, see RFC 1071 */
3094/* return 0 for success, -1 on error */
3095/* can be called from decode() with
3096 TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
3097 could also add a 64bit version if type available and using this
3098*/
3099int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
3100 const byte* packet)
3101{
3102 TcpPseudoHdr pseudo;
3103 int count = PSEUDO_HDR_SZ;
3104 const word16* data = (word16*)&pseudo;
3105 word32 sum = 0;
3106 word16 checksum;
3107
3108 pseudo.src = ipInfo->src;
3109 pseudo.dst = ipInfo->dst;
3110 pseudo.rsv = 0;
3111 pseudo.protocol = TCP_PROTO;
3112 pseudo.length = htons(tcpInfo->length + dataLen);
3113
3114 /* pseudo header sum */
3115 while (count >= 2) {
3116 sum += *data++;
3117 count -= 2;
3118 }
3119
3120 count = tcpInfo->length + dataLen;
3121 data = (word16*)packet;
3122
3123 /* main sum */
3124 while (count > 1) {
3125 sum += *data++;
3126 count -=2;
3127 }
3128
3129 /* get left-over, if any */
3130 packet = (byte*)data;
3131 if (count > 0) {
3132 sum += *packet;
3133 }
3134
3135 /* fold 32bit sum into 16 bits */
3136 while (sum >> 16)
3137 sum = (sum & 0xffff) + (sum >> 16);
3138
3139 checksum = (word16)~sum;
3140 /* checksum should now equal 0, since included already calcd checksum */
3141 /* field, but tcp checksum offloading could negate calculation */
3142 if (checksum == 0)
3143 return 0;
3144 return -1;
3145}
3146#endif
3147
3148
3149/* Check IP and TCP headers, set payload */
3150/* returns 0 on success, -1 on error */
3151static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
3152 int length, const byte** sslFrame, int* sslBytes, char* error)
3153{
3154 TraceHeader();
3155 TracePacket();
3156
3157 /* ip header */
3158 if (length < IP_HDR_SZ) {
3159 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
3160 return -1;
3161 }
3162 if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
3163 return -1;
3164
3165 /* tcp header */
3166 if (length < (ipInfo->length + TCP_HDR_SZ)) {
3167 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
3168 return -1;
3169 }
3170 if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
3171 return -1;
3172
3173 /* setup */
3174 *sslFrame = packet + ipInfo->length + tcpInfo->length;
3175 if (*sslFrame > packet + length) {
3176 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
3177 return -1;
3178 }
3179 /* We only care about the data in the TCP/IP record. There may be extra
3180 * data after the IP record for the FCS for Ethernet. */
3181 *sslBytes = (int)(packet + ipInfo->total - *sslFrame);
3182
3183 return 0;
3184}
3185
3186
3187/* Create or Find existing session */
3188/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3189static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
3190 SnifferSession** session, char* error)
3191{
3192 /* create a new SnifferSession on client SYN */
3193 if (tcpInfo->syn && !tcpInfo->ack) {
3194 TraceClientSyn(tcpInfo->sequence);
3195#ifdef WOLFSSL_SNIFFER_STATS
3196 INC_STAT(SnifferStats.sslEncryptedConns);
3197#endif
3198 *session = CreateSession(ipInfo, tcpInfo, error);
3199 if (*session == NULL) {
3200 *session = GetSnifferSession(ipInfo, tcpInfo);
3201 /* already had existing, so OK */
3202 if (*session)
3203 return 1;
3204
3205 SetError(MEMORY_STR, error, NULL, 0);
3206 return -1;
3207 }
3208 return 1;
3209 }
3210 /* get existing sniffer session */
3211 else {
3212 *session = GetSnifferSession(ipInfo, tcpInfo);
3213 if (*session == NULL) {
3214 /* don't worry about extraneous RST or duplicate FINs */
3215 if (tcpInfo->fin || tcpInfo->rst)
3216 return 1;
3217 /* don't worry about duplicate ACKs either */
3218 if (sslBytes == 0 && tcpInfo->ack)
3219 return 1;
3220
3221#ifdef WOLFSSL_SNIFFER_STATS
3222 LOCK_STAT();
3223 NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
3224 NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
3225 UNLOCK_STAT();
3226#endif
3227
3228 SetError(BAD_SESSION_STR, error, NULL, 0);
3229 return -1;
3230 }
3231 }
3232 return 0;
3233}
3234
3235
3236/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
3237static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
3238 int* bytesLeft)
3239{
3240 PacketBuffer* pb;
3241
3242 int added = end - *begin + 1;
3243 assert(*begin <= end);
3244
3245 pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer),
3246 NULL, DYNAMIC_TYPE_SNIFFER_PB);
3247 if (pb == NULL) return NULL;
3248
3249 pb->next = 0;
3250 pb->begin = *begin;
3251 pb->end = end;
3252 pb->data = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
3253
3254 if (pb->data == NULL) {
3255 XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB);
3256 return NULL;
3257 }
3258 XMEMCPY(pb->data, data, added);
3259
3260 *bytesLeft -= added;
3261 *begin = pb->end + 1;
3262
3263 return pb;
3264}
3265
3266
3267/* Add sslFrame to Reassembly List */
3268/* returns 1 (end) on success, -1, on error */
3269static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
3270 int sslBytes, SnifferSession* session, char* error)
3271{
3272 PacketBuffer* add;
3273 PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
3274 &session->cliReassemblyList: &session->srvReassemblyList;
3275 PacketBuffer* curr = *front;
3276 PacketBuffer* prev = curr;
3277
3278 word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
3279 &session->cliReassemblyMemory : &session->srvReassemblyMemory;
3280 word32 startSeq = seq;
3281 word32 added;
3282 int bytesLeft = sslBytes; /* could be overlapping fragment */
3283
3284 /* if list is empty add full frame to front */
3285 if (!curr) {
3286 if (MaxRecoveryMemory != -1 &&
3287 (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
3288 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
3289 return -1;
3290 }
3291 add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
3292 if (add == NULL) {
3293 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3294 return -1;
3295 }
3296 *front = add;
3297 *reassemblyMemory += sslBytes;
3298 return 1;
3299 }
3300
3301 /* add to front if before current front, up to next->begin */
3302 if (seq < curr->begin) {
3303 word32 end = seq + sslBytes - 1;
3304
3305 if (end >= curr->begin)
3306 end = curr->begin - 1;
3307
3308 if (MaxRecoveryMemory -1 &&
3309 (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
3310 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
3311 return -1;
3312 }
3313 add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
3314 if (add == NULL) {
3315 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3316 return -1;
3317 }
3318 add->next = curr;
3319 *front = add;
3320 *reassemblyMemory += sslBytes;
3321 }
3322
3323 /* while we have bytes left, try to find a gap to fill */
3324 while (bytesLeft > 0) {
3325 /* get previous packet in list */
3326 while (curr && (seq >= curr->begin)) {
3327 prev = curr;
3328 curr = curr->next;
3329 }
3330
3331 /* don't add duplicate data */
3332 if (prev->end >= seq) {
3333 if ( (seq + bytesLeft - 1) <= prev->end)
3334 return 1;
3335 seq = prev->end + 1;
3336 bytesLeft = startSeq + sslBytes - seq;
3337 }
3338
3339 if (!curr)
3340 /* we're at the end */
3341 added = bytesLeft;
3342 else
3343 /* we're in between two frames */
3344 added = min((word32)bytesLeft, curr->begin - seq);
3345
3346 /* data already there */
3347 if (added == 0)
3348 continue;
3349
3350 if (MaxRecoveryMemory != -1 &&
3351 (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
3352 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
3353 return -1;
3354 }
3355 add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
3356 &bytesLeft);
3357 if (add == NULL) {
3358 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3359 return -1;
3360 }
3361 add->next = prev->next;
3362 prev->next = add;
3363 *reassemblyMemory += added;
3364 }
3365 return 1;
3366}
3367
3368
3369/* Add out of order FIN capture */
3370/* returns 1 for success (end) */
3371static int AddFinCapture(SnifferSession* session, word32 sequence)
3372{
3373 if (session->flags.side == WOLFSSL_SERVER_END) {
3374 if (session->finCaputre.cliCounted == 0)
3375 session->finCaputre.cliFinSeq = sequence;
3376 }
3377 else {
3378 if (session->finCaputre.srvCounted == 0)
3379 session->finCaputre.srvFinSeq = sequence;
3380 }
3381 return 1;
3382}
3383
3384
3385/* Adjust incoming sequence based on side */
3386/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3387static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
3388 int* sslBytes, const byte** sslFrame, char* error)
3389{
3390 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
3391 session->cliSeqStart :session->srvSeqStart;
3392 word32 real = tcpInfo->sequence - seqStart;
3393 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3394 &session->cliExpected : &session->srvExpected;
3395 PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
3396 session->cliReassemblyList : session->srvReassemblyList;
3397 byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
3398 session->flags.srvSkipPartial :
3399 session->flags.cliSkipPartial;
3400
3401 /* handle rollover of sequence */
3402 if (tcpInfo->sequence < seqStart)
3403 real = 0xffffffffU - seqStart + tcpInfo->sequence;
3404
3405 TraceRelativeSequence(*expected, real);
3406
3407 if (real < *expected) {
3408 Trace(DUPLICATE_STR);
3409 if (real + *sslBytes > *expected) {
3410 int overlap = *expected - real;
3411 Trace(OVERLAP_DUPLICATE_STR);
3412
3413 /* adjust to expected, remove duplicate */
3414 *sslFrame += overlap;
3415 *sslBytes -= overlap;
3416
3417 /* The following conditional block is duplicated below. It is the
3418 * same action but for a different setup case. If changing this
3419 * block be sure to also update the block below. */
3420 if (reassemblyList) {
3421 word32 newEnd = *expected + *sslBytes;
3422
3423 if (newEnd > reassemblyList->begin) {
3424 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
3425
3426 /* remove bytes already on reassembly list */
3427 *sslBytes -= newEnd - reassemblyList->begin;
3428 }
3429 if (newEnd > reassemblyList->end) {
3430 Trace(OVERLAP_REASSEMBLY_END_STR);
3431
3432 /* may be past reassembly list end (could have more on list)
3433 so try to add what's past the front->end */
3434 AddToReassembly(session->flags.side, reassemblyList->end +1,
3435 *sslFrame + reassemblyList->end - *expected + 1,
3436 newEnd - reassemblyList->end, session, error);
3437 }
3438 }
3439 }
3440 else
3441 return 1;
3442 }
3443 else if (real > *expected) {
3444 Trace(OUT_OF_ORDER_STR);
3445 if (*sslBytes > 0) {
3446 int addResult = AddToReassembly(session->flags.side, real,
3447 *sslFrame, *sslBytes, session, error);
3448 if (skipPartial) {
3449 *sslBytes = 0;
3450 return 0;
3451 }
3452 else
3453 return addResult;
3454 }
3455 else if (tcpInfo->fin)
3456 return AddFinCapture(session, real);
3457 }
3458 else if (*sslBytes > 0) {
3459 if (skipPartial) {
3460 AddToReassembly(session->flags.side, real,
3461 *sslFrame, *sslBytes, session, error);
3462 *expected += *sslBytes;
3463 *sslBytes = 0;
3464 if (tcpInfo->fin)
3465 *expected += 1;
3466 return 0;
3467 }
3468 /* The following conditional block is duplicated above. It is the
3469 * same action but for a different setup case. If changing this
3470 * block be sure to also update the block above. */
3471 else if (reassemblyList) {
3472 word32 newEnd = *expected + *sslBytes;
3473
3474 if (newEnd > reassemblyList->begin) {
3475 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
3476
3477 /* remove bytes already on reassembly list */
3478 *sslBytes -= newEnd - reassemblyList->begin;
3479 }
3480 if (newEnd > reassemblyList->end) {
3481 Trace(OVERLAP_REASSEMBLY_END_STR);
3482
3483 /* may be past reassembly list end (could have more on list)
3484 so try to add what's past the front->end */
3485 AddToReassembly(session->flags.side, reassemblyList->end +1,
3486 *sslFrame + reassemblyList->end - *expected + 1,
3487 newEnd - reassemblyList->end, session, error);
3488 }
3489 }
3490 }
3491 /* got expected sequence */
3492 *expected += *sslBytes;
3493 if (tcpInfo->fin)
3494 *expected += 1;
3495
3496 return 0;
3497}
3498
3499
3500static int FindNextRecordInAssembly(SnifferSession* session,
3501 const byte** sslFrame, int* sslBytes,
3502 const byte** end, char* error)
3503{
3504 PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
3505 &session->cliReassemblyList :
3506 &session->srvReassemblyList;
3507 PacketBuffer* curr = *front;
3508 PacketBuffer* prev = NULL;
3509 byte* skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
3510 &session->flags.srvSkipPartial :
3511 &session->flags.cliSkipPartial;
3512 word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
3513 &session->cliReassemblyMemory :
3514 &session->srvReassemblyMemory;
3515 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
3516 session->sslServer :
3517 session->sslClient;
3518 ProtocolVersion pv = ssl->version;
3519 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3520 &session->cliExpected :
3521 &session->srvExpected;
3522
3523 while (curr != NULL) {
3524 *expected = curr->end + 1;
3525
3526 if (curr->data[0] == application_data &&
3527 curr->data[1] == pv.major &&
3528 curr->data[2] == pv.minor) {
3529
3530 if (ssl->buffers.inputBuffer.length > 0)
3531 Trace(DROPPING_PARTIAL_RECORD);
3532
3533 *sslBytes = curr->end - curr->begin + 1;
3534 if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
3535 if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
3536 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3537 return -1;
3538 }
3539 }
3540
3541 XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
3542
3543 *front = curr->next;
3544 *reassemblyMemory -= *sslBytes;
3545 FreePacketBuffer(curr);
3546
3547 ssl->buffers.inputBuffer.length = *sslBytes;
3548 *sslFrame = ssl->buffers.inputBuffer.buffer;
3549 *end = *sslFrame + *sslBytes;
3550 *skipPartial = 0;
3551
3552 return 0;
3553 }
3554 else if (ssl->specs.cipher_type == block) {
3555 if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
3556#ifdef BUILD_AES
3557 wc_AesSetIV(ssl->decrypt.aes,
3558 curr->data + curr->end - curr->begin
3559 - ssl->specs.block_size + 1);
3560#endif
3561 }
3562 else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
3563#ifdef BUILD_DES3
3564 wc_Des3_SetIV(ssl->decrypt.des3,
3565 curr->data + curr->end - curr->begin
3566 - ssl->specs.block_size + 1);
3567#endif
3568 }
3569 }
3570
3571 Trace(DROPPING_LOST_FRAG_STR);
3572#ifdef WOLFSSL_SNIFFER_STATS
3573 INC_STAT(SnifferStats.sslDecodeFails);
3574#endif
3575 prev = curr;
3576 curr = curr->next;
3577 *reassemblyMemory -= (prev->end - prev->begin + 1);
3578 FreePacketBuffer(prev);
3579 }
3580
3581 *front = curr;
3582
3583 return 0;
3584}
3585
3586
3587static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
3588{
3589 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3590 &session->srvExpected : &session->cliExpected;
3591 PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
3592 session->srvReassemblyList :
3593 session->cliReassemblyList;
3594 byte* skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
3595 &session->flags.srvSkipPartial :
3596 &session->flags.cliSkipPartial;
3597
3598 *skipPartial = 1;
3599 if (list != NULL)
3600 *expected = list->begin;
3601 else {
3602 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
3603 session->srvSeqStart : session->cliSeqStart;
3604 word32 real = tcpInfo->ackNumber - seqStart;
3605
3606 *expected = real;
3607 }
3608
3609 return 1;
3610}
3611
3612
3613/* Check latest ack number for missing packets
3614 return 0 ok, <0 on error */
3615static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
3616{
3617 if (tcpInfo->ack) {
3618 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
3619 session->srvSeqStart :session->cliSeqStart;
3620 word32 real = tcpInfo->ackNumber - seqStart;
3621 word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3622 session->srvExpected : session->cliExpected;
3623
3624 /* handle rollover of sequence */
3625 if (tcpInfo->ackNumber < seqStart)
3626 real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
3627
3628 TraceAck(real, expected);
3629
3630 if (real > expected)
3631 return -1; /* we missed a packet, ACKing data we never saw */
3632 }
3633 return 0;
3634}
3635
3636
3637/* Check TCP Sequence status */
3638/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3639static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
3640 SnifferSession* session, int* sslBytes,
3641 const byte** sslFrame, char* error)
3642{
3643 int actualLen;
3644 byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
3645 &session->flags.cliAckFault :
3646 &session->flags.srvAckFault;
3647
3648 /* init SEQ from server to client */
3649 if (tcpInfo->syn && tcpInfo->ack) {
3650 session->srvSeqStart = tcpInfo->sequence;
3651 session->srvExpected = 1;
3652 TraceServerSyn(tcpInfo->sequence);
3653 return 1;
3654 }
3655
3656 /* adjust potential ethernet trailer */
3657 actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
3658 if (*sslBytes > actualLen) {
3659 *sslBytes = actualLen;
3660 }
3661
3662 TraceSequence(tcpInfo->sequence, *sslBytes);
3663 if (CheckAck(tcpInfo, session) < 0) {
3664 if (!RecoveryEnabled) {
3665 UpdateMissedDataSessions();
3666 SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
3667 return -1;
3668 }
3669 else {
3670 SetError(ACK_MISSED_STR, error, session, 0);
3671 if (*ackFault == 0) {
3672 *ackFault = 1;
3673 UpdateMissedDataSessions();
3674 }
3675 return FixSequence(tcpInfo, session);
3676 }
3677 }
3678
3679 if (*ackFault) {
3680 Trace(CLEAR_ACK_FAULT);
3681 *ackFault = 0;
3682 }
3683
3684 return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
3685}
3686
3687
3688/* Check Status before record processing */
3689/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3690static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
3691 const byte** sslFrame, SnifferSession** session,
3692 int* sslBytes, const byte** end,
3693 void* vChain, word32 chainSz, char* error)
3694{
3695 word32 length;
3696 SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
3697 (*session)->sslServer : (*session)->sslClient;
3698 byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
3699 (*session)->flags.srvSkipPartial :
3700 (*session)->flags.cliSkipPartial;
3701 /* remove SnifferSession on 2nd FIN or RST */
3702 if (tcpInfo->fin || tcpInfo->rst) {
3703 /* flag FIN and RST */
3704 if (tcpInfo->fin)
3705 (*session)->flags.finCount += 1;
3706 else if (tcpInfo->rst)
3707 (*session)->flags.finCount += 2;
3708
3709 if ((*session)->flags.finCount >= 2) {
3710 RemoveSession(*session, ipInfo, tcpInfo, 0);
3711 *session = NULL;
3712 return 1;
3713 }
3714 }
3715
3716 if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
3717 SetError(FATAL_ERROR_STR, error, NULL, 0);
3718 return -1;
3719 }
3720
3721 if (skipPartial) {
3722 if (FindNextRecordInAssembly(*session,
3723 sslFrame, sslBytes, end, error) < 0) {
3724 return -1;
3725 }
3726 }
3727
3728 if (*sslBytes == 0) {
3729 Trace(NO_DATA_STR);
3730 return 1;
3731 }
3732
3733 /* if current partial data, add to end of partial */
3734 /* if skipping, the data is already at the end of partial */
3735 if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) {
3736 Trace(PARTIAL_ADD_STR);
3737
3738 if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
3739 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
3740 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
3741 return -1;
3742 }
3743 }
3744 if (vChain == NULL) {
3745 XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
3746 *sslFrame, *sslBytes);
3747 *sslBytes += length;
3748 ssl->buffers.inputBuffer.length = *sslBytes;
3749 *sslFrame = ssl->buffers.inputBuffer.buffer;
3750 *end = *sslFrame + *sslBytes;
3751 }
3752 }
3753
3754 if (vChain != NULL) {
3755#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
3756 struct iovec* chain = (struct iovec*)vChain;
3757 word32 i, offset, headerSz, qty, remainder;
3758
3759 Trace(CHAIN_INPUT_STR);
3760 headerSz = (word32)*sslFrame - (word32)chain[0].iov_base;
3761 remainder = *sslBytes;
3762
3763 if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
3764 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
3765 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
3766 return -1;
3767 }
3768 }
3769
3770 qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz);
3771 XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
3772 (byte*)chain[0].iov_base + headerSz, qty);
3773 offset = length;
3774 for (i = 1; i < chainSz; i++) {
3775 offset += qty;
3776 remainder -= qty;
3777
3778 if (chain[i].iov_len > remainder)
3779 qty = remainder;
3780 else
3781 qty = (word32)chain[i].iov_len;
3782 XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
3783 chain[i].iov_base, qty);
3784 }
3785
3786 *sslBytes += length;
3787 ssl->buffers.inputBuffer.length = *sslBytes;
3788 *sslFrame = ssl->buffers.inputBuffer.buffer;
3789 *end = *sslFrame + *sslBytes;
3790#endif
3791 (void)chainSz;
3792 }
3793
3794 if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
3795 /* Sanity check the packet for an old style client hello. */
3796 int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
3797
3798 if ((rhSize <= (*sslBytes - 2)) &&
3799 (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
3800#ifdef OLD_HELLO_ALLOWED
3801 int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
3802 if (ret < 0)
3803 return -1; /* error already set */
3804 if (*sslBytes <= 0)
3805 return 1;
3806#endif
3807 }
3808 else {
3809#ifdef STARTTLS_ALLOWED
3810 if (ssl->buffers.inputBuffer.dynamicFlag) {
3811 ssl->buffers.inputBuffer.length = 0;
3812 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
3813 }
3814 return 1;
3815#endif
3816 }
3817 }
3818
3819 return 0;
3820}
3821
3822
3823/* See if input on the reassembly list is ready for consuming */
3824/* returns 1 for TRUE, 0 for FALSE */
3825static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
3826 int* sslBytes, const byte** end, char* error)
3827{
3828 /* sequence and reassembly based on from, not to */
3829 int moreInput = 0;
3830 PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
3831 &session->cliReassemblyList : &session->srvReassemblyList;
3832 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3833 &session->cliExpected : &session->srvExpected;
3834 /* buffer is on receiving end */
3835 word32* length = (session->flags.side == WOLFSSL_SERVER_END) ?
3836 &session->sslServer->buffers.inputBuffer.length :
3837 &session->sslClient->buffers.inputBuffer.length;
3838 byte** myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
3839 &session->sslServer->buffers.inputBuffer.buffer :
3840 &session->sslClient->buffers.inputBuffer.buffer;
3841 word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
3842 &session->sslServer->buffers.inputBuffer.bufferSize :
3843 &session->sslClient->buffers.inputBuffer.bufferSize;
3844 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
3845 session->sslServer : session->sslClient;
3846 word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
3847 &session->cliReassemblyMemory : &session->srvReassemblyMemory;
3848
3849 while (*front && ((*front)->begin == *expected) ) {
3850 word32 room = *bufferSize - *length;
3851 word32 packetLen = (*front)->end - (*front)->begin + 1;
3852
3853 if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
3854 if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
3855 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3856 return 0;
3857 }
3858 room = *bufferSize - *length; /* bufferSize is now bigger */
3859 }
3860
3861 if (packetLen <= room) {
3862 PacketBuffer* del = *front;
3863 byte* buf = *myBuffer;
3864
3865 XMEMCPY(&buf[*length], (*front)->data, packetLen);
3866 *length += packetLen;
3867 *expected += packetLen;
3868
3869 /* remove used packet */
3870 *front = (*front)->next;
3871
3872 *reassemblyMemory -= packetLen;
3873 FreePacketBuffer(del);
3874
3875 moreInput = 1;
3876 }
3877 else
3878 break;
3879 }
3880 if (moreInput) {
3881 *sslFrame = *myBuffer;
3882 *sslBytes = *length;
3883 *end = *myBuffer + *length;
3884 }
3885 return moreInput;
3886}
3887
3888
3889
3890/* Process Message(s) from sslFrame */
3891/* return Number of bytes on success, 0 for no data yet, and -1 on error */
3892static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
3893 int sslBytes, byte** data, const byte* end,
3894 void* ctx, char* error)
3895{
3896 const byte* sslBegin = sslFrame;
3897 const byte* recordEnd; /* end of record indicator */
3898 const byte* inRecordEnd; /* indicator from input stream not decrypt */
3899 RecordLayerHeader rh;
3900 int rhSize = 0;
3901 int ret;
3902 int errCode = 0;
3903 int decoded = 0; /* bytes stored for user in data */
3904 int notEnough; /* notEnough bytes yet flag */
3905 int decrypted = 0; /* was current msg decrypted */
3906 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
3907 session->sslServer : session->sslClient;
3908doMessage:
3909 notEnough = 0;
3910 if (sslBytes < 0) {
3911 SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
3912 return -1;
3913 }
3914 if (sslBytes >= RECORD_HEADER_SZ) {
3915 if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
3916 SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
3917 return -1;
3918 }
3919 }
3920 else
3921 notEnough = 1;
3922
3923 if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
3924 /* don't have enough input yet to process full SSL record */
3925 Trace(PARTIAL_INPUT_STR);
3926
3927 /* store partial if not there already or we advanced */
3928 if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
3929 if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
3930 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
3931 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3932 return -1;
3933 }
3934 }
3935 XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
3936 ssl->buffers.inputBuffer.length = sslBytes;
3937 }
3938 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
3939 goto doMessage;
3940 return decoded;
3941 }
3942 sslFrame += RECORD_HEADER_SZ;
3943 sslBytes -= RECORD_HEADER_SZ;
3944 recordEnd = sslFrame + rhSize; /* may have more than one record */
3945 inRecordEnd = recordEnd;
3946
3947 /* decrypt if needed */
3948 if ((session->flags.side == WOLFSSL_SERVER_END &&
3949 session->flags.serverCipherOn)
3950 || (session->flags.side == WOLFSSL_CLIENT_END &&
3951 session->flags.clientCipherOn)) {
3952 int ivAdvance = 0; /* TLSv1.1 advance amount */
3953 if (ssl->decrypt.setup != 1) {
3954 SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
3955 return -1;
3956 }
3957 if (CheckAvailableSize(ssl, rhSize) < 0) {
3958 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3959 return -1;
3960 }
3961 sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
3962 ssl->buffers.outputBuffer.buffer, &errCode,
3963 &ivAdvance);
3964 recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so
3965 should recordEnd */
3966 decrypted = 1;
3967
3968#ifdef WOLFSSL_SNIFFER_STATS
3969 if (errCode != 0) {
3970 INC_STAT(SnifferStats.sslKeyFails);
3971 }
3972 else {
3973 LOCK_STAT();
3974 NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
3975 NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
3976 UNLOCK_STAT();
3977 }
3978#endif
3979 if (errCode != 0) {
3980 SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
3981 return -1;
3982 }
3983 }
3984
3985doPart:
3986
3987 switch ((enum ContentType)rh.type) {
3988 case handshake:
3989 {
3990 int startIdx = sslBytes;
3991 int used;
3992
3993 Trace(GOT_HANDSHAKE_STR);
3994 ret = DoHandShake(sslFrame, &sslBytes, session, error);
3995 if (ret != 0) {
3996 if (session->flags.fatalError == 0)
3997 SetError(BAD_HANDSHAKE_STR, error, session,
3998 FATAL_ERROR_STATE);
3999 return -1;
4000 }
4001
4002 /* DoHandShake now fully decrements sslBytes to remaining */
4003 used = startIdx - sslBytes;
4004 sslFrame += used;
4005 if (decrypted)
4006 sslFrame += ssl->keys.padSz;
4007 }
4008 break;
4009 case change_cipher_spec:
4010 if (session->flags.side == WOLFSSL_SERVER_END)
4011 session->flags.serverCipherOn = 1;
4012 else
4013 session->flags.clientCipherOn = 1;
4014 Trace(GOT_CHANGE_CIPHER_STR);
4015 ssl->options.handShakeState = HANDSHAKE_DONE;
4016 ssl->options.handShakeDone = 1;
4017
4018 sslFrame += 1;
4019 sslBytes -= 1;
4020
4021 break;
4022 case application_data:
4023 Trace(GOT_APP_DATA_STR);
4024 {
4025 word32 inOutIdx = 0;
4026
4027 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
4028 if (ret == 0) {
4029 ret = ssl->buffers.clearOutputBuffer.length;
4030 TraceGotData(ret);
4031 if (ret) { /* may be blank message */
4032 if (data != NULL) {
4033 byte* tmpData; /* don't leak on realloc free */
4034 /* add an extra byte at end of allocation in case
4035 * user wants to null terminate plaintext */
4036 tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
4037 NULL, DYNAMIC_TYPE_TMP_BUFFER);
4038 if (tmpData == NULL) {
4039 ForceZero(*data, decoded);
4040 XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4041 *data = NULL;
4042 SetError(MEMORY_STR, error, session,
4043 FATAL_ERROR_STATE);
4044 return -1;
4045 }
4046 *data = tmpData;
4047 XMEMCPY(*data + decoded,
4048 ssl->buffers.clearOutputBuffer.buffer, ret);
4049 }
4050 else {
4051#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
4052 if (StoreDataCb) {
4053 const byte* buf;
4054 word32 offset = 0;
4055 word32 bufSz;
4056 int stored;
4057
4058 buf = ssl->buffers.clearOutputBuffer.buffer;
4059 bufSz = ssl->buffers.clearOutputBuffer.length;
4060 do {
4061 stored = StoreDataCb(buf, bufSz, offset,
4062 ctx);
4063 if (stored <= 0) {
4064 return -1;
4065 }
4066 offset += stored;
4067 } while (offset < bufSz);
4068 }
4069 else {
4070 SetError(STORE_DATA_CB_MISSING_STR, error,
4071 session, FATAL_ERROR_STATE);
4072 return -1;
4073 }
4074#else
4075 (void)ctx;
4076 SetError(NO_DATA_DEST_STR, error, session,
4077 FATAL_ERROR_STATE);
4078 return -1;
4079#endif
4080 }
4081 TraceAddedData(ret, decoded);
4082 decoded += ret;
4083 ssl->buffers.clearOutputBuffer.length = 0;
4084 }
4085 }
4086 else {
4087 SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
4088 return -1;
4089 }
4090 if (ssl->buffers.outputBuffer.dynamicFlag)
4091 ShrinkOutputBuffer(ssl);
4092
4093 sslFrame += inOutIdx;
4094 sslBytes -= inOutIdx;
4095 }
4096 break;
4097 case alert:
4098 Trace(GOT_ALERT_STR);
4099#ifdef WOLFSSL_SNIFFER_STATS
4100 INC_STAT(SnifferStats.sslAlerts);
4101#endif
4102 sslFrame += rhSize;
4103 sslBytes -= rhSize;
4104 break;
4105 case no_type:
4106 default:
4107 SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
4108 return -1;
4109 }
4110
4111 /* do we have another msg in record ? */
4112 if (sslFrame < recordEnd) {
4113 Trace(ANOTHER_MSG_STR);
4114 goto doPart;
4115 }
4116
4117 /* back to input stream instead of potential decrypt buffer */
4118 recordEnd = inRecordEnd;
4119
4120 /* do we have more records ? */
4121 if (recordEnd < end) {
4122 Trace(ANOTHER_MSG_STR);
4123 sslFrame = recordEnd;
4124 sslBytes = (int)(end - recordEnd);
4125 goto doMessage;
4126 }
4127
4128 /* clear used input */
4129 ssl->buffers.inputBuffer.length = 0;
4130
4131 /* could have more input ready now */
4132 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
4133 goto doMessage;
4134
4135 if (ssl->buffers.inputBuffer.dynamicFlag)
4136 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
4137
4138 return decoded;
4139}
4140
4141
4142/* See if we need to process any pending FIN captures */
4143/* Return 0=normal, else = session removed */
4144static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
4145 SnifferSession* session)
4146{
4147 int ret = 0;
4148 if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
4149 session->cliExpected) {
4150 if (session->finCaputre.cliCounted == 0) {
4151 session->flags.finCount += 1;
4152 session->finCaputre.cliCounted = 1;
4153 TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
4154 }
4155 }
4156
4157 if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
4158 session->srvExpected) {
4159 if (session->finCaputre.srvCounted == 0) {
4160 session->flags.finCount += 1;
4161 session->finCaputre.srvCounted = 1;
4162 TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
4163 }
4164 }
4165
4166 if (session->flags.finCount >= 2) {
4167 RemoveSession(session, ipInfo, tcpInfo, 0);
4168 ret = 1;
4169 }
4170 return ret;
4171}
4172
4173
4174/* If session is in fatal error state free resources now
4175 return true if removed, 0 otherwise */
4176static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
4177 SnifferSession* session, char* error)
4178{
4179 if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
4180 RemoveSession(session, ipInfo, tcpInfo, 0);
4181 SetError(FATAL_ERROR_STR, error, NULL, 0);
4182 return 1;
4183 }
4184 return 0;
4185}
4186
4187
4188/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
4189/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
4190static int ssl_DecodePacketInternal(const byte* packet, int length,
4191 void* vChain, word32 chainSz,
4192 byte** data, SSLInfo* sslInfo,
4193 void* ctx, char* error)
4194{
4195 TcpInfo tcpInfo;
4196 IpInfo ipInfo;
4197 const byte* sslFrame;
4198 const byte* end;
4199 int sslBytes; /* ssl bytes unconsumed */
4200 int ret;
4201 SnifferSession* session = 0;
4202
4203#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
4204 if (packet == NULL && vChain != NULL) {
4205 struct iovec* chain = (struct iovec*)vChain;
4206 word32 i;
4207
4208 length = 0;
4209 for (i = 0; i < chainSz; i++)
4210 length += chain[i].iov_len;
4211 packet = (const byte*)chain[0].iov_base;
4212 }
4213#endif
4214
4215 if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
4216 error) != 0)
4217 return -1;
4218
4219 end = sslFrame + sslBytes;
4220
4221 ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
4222 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
4223 else if (ret == -1) return -1;
4224 else if (ret == 1) {
4225#ifdef WOLFSSL_SNIFFER_STATS
4226 if (sslBytes > 0) {
4227 LOCK_STAT();
4228 NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
4229 NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
4230 UNLOCK_STAT();
4231 }
4232 else
4233 INC_STAT(SnifferStats.sslDecryptedPackets);
4234#endif
4235 return 0; /* done for now */
4236 }
4237
4238 ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
4239 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
4240 else if (ret == -1) return -1;
4241 else if (ret == 1) {
4242#ifdef WOLFSSL_SNIFFER_STATS
4243 INC_STAT(SnifferStats.sslDecryptedPackets);
4244#endif
4245 return 0; /* done for now */
4246 }
4247
4248 ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
4249 &end, vChain, chainSz, error);
4250 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
4251 else if (ret == -1) return -1;
4252 else if (ret == 1) {
4253#ifdef WOLFSSL_SNIFFER_STATS
4254 INC_STAT(SnifferStats.sslDecryptedPackets);
4255#endif
4256 return 0; /* done for now */
4257 }
4258
4259#ifdef WOLFSSL_SNIFFER_STATS
4260 if (sslBytes > 0) {
4261 LOCK_STAT();
4262 NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
4263 NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
4264 UNLOCK_STAT();
4265 }
4266 else
4267 INC_STAT(SnifferStats.sslDecryptedPackets);
4268#endif
4269
4270 ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error);
4271 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
4272 if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
4273 CopySessionInfo(session, sslInfo);
4274 }
4275
4276 return ret;
4277}
4278
4279
4280/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
4281/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
4282/* Also returns Session Info if available */
4283int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
4284 unsigned char** data, SSLInfo* sslInfo, char* error)
4285{
4286 return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo,
4287 NULL, error);
4288}
4289
4290
4291/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
4292/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
4293int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
4294{
4295 return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL,
4296 error);
4297}
4298
4299
4300#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
4301
4302int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
4303 int length, void* ctx, SSLInfo* sslInfo, char* error)
4304{
4305 return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo,
4306 ctx, error);
4307}
4308
4309#endif
4310
4311
4312#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
4313
4314int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data,
4315 char* error)
4316{
4317 return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL,
4318 error);
4319}
4320
4321#endif
4322
4323
4324#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
4325 defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
4326
4327int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz,
4328 void* ctx, SSLInfo* sslInfo, char* error)
4329{
4330 return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo,
4331 ctx, error);
4332}
4333
4334#endif
4335
4336
4337/* Deallocator for the decoded data buffer. */
4338/* returns 0 on success, -1 on error */
4339int ssl_FreeDecodeBuffer(byte** data, char* error)
4340{
4341 return ssl_FreeZeroDecodeBuffer(data, 0, error);
4342}
4343
4344
4345/* Deallocator for the decoded data buffer, zeros out buffer. */
4346/* returns 0 on success, -1 on error */
4347int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
4348{
4349 (void)error;
4350
4351 if (sz < 0) {
4352 return -1;
4353 }
4354
4355 if (data != NULL) {
4356 ForceZero(*data, (word32)sz);
4357 XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4358 *data = NULL;
4359 }
4360
4361 return 0;
4362}
4363
4364
4365/* Enables (if traceFile)/ Disables debug tracing */
4366/* returns 0 on success, -1 on error */
4367int ssl_Trace(const char* traceFile, char* error)
4368{
4369 if (traceFile) {
4370 /* Don't try to reopen the file */
4371 if (TraceFile == NULL) {
4372 TraceFile = fopen(traceFile, "a");
4373 if (!TraceFile) {
4374 SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
4375 return -1;
4376 }
4377 TraceOn = 1;
4378 }
4379 }
4380 else
4381 TraceOn = 0;
4382
4383 return 0;
4384}
4385
4386
4387/* Enables/Disables Recovery of missed data if later packets allow
4388 * maxMemory is number of bytes to use for reassembly buffering per session,
4389 * -1 means unlimited
4390 * returns 0 on success, -1 on error */
4391int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
4392{
4393 (void)error;
4394
4395 RecoveryEnabled = onOff;
4396 if (onOff)
4397 MaxRecoveryMemory = maxMemory;
4398
4399 return 0;
4400}
4401
4402
4403
4404#ifdef WOLFSSL_SESSION_STATS
4405
4406int ssl_GetSessionStats(unsigned int* active, unsigned int* total,
4407 unsigned int* peak, unsigned int* maxSessions,
4408 unsigned int* missedData, unsigned int* reassemblyMem,
4409 char* error)
4410{
4411 int ret;
4412
4413 if (missedData) {
4414 wc_LockMutex(&RecoveryMutex);
4415 *missedData = MissedDataSessions;
4416 wc_UnLockMutex(&RecoveryMutex);
4417 }
4418
4419 if (reassemblyMem) {
4420 SnifferSession* session;
4421 int i;
4422
4423 *reassemblyMem = 0;
4424 wc_LockMutex(&SessionMutex);
4425 for (i = 0; i < HASH_SIZE; i++) {
4426 session = SessionTable[i];
4427 while (session) {
4428 *reassemblyMem += session->cliReassemblyMemory;
4429 *reassemblyMem += session->srvReassemblyMemory;
4430 session = session->next;
4431 }
4432 }
4433 wc_UnLockMutex(&SessionMutex);
4434 }
4435
4436 ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
4437
4438 if (ret == WOLFSSL_SUCCESS)
4439 return 0;
4440 else {
4441 SetError(BAD_SESSION_STATS, error, NULL, 0);
4442 return -1;
4443 }
4444}
4445
4446#endif
4447
4448
4449
4450int ssl_SetConnectionCb(SSLConnCb cb)
4451{
4452 ConnectionCb = cb;
4453 return 0;
4454}
4455
4456
4457
4458int ssl_SetConnectionCtx(void* ctx)
4459{
4460 ConnectionCbCtx = ctx;
4461 return 0;
4462}
4463
4464
4465#ifdef WOLFSSL_SNIFFER_STATS
4466
4467/* Resets the statistics tracking global structure.
4468 * returns 0 on success, -1 on error */
4469int ssl_ResetStatistics(void)
4470{
4471 wc_LockMutex(&StatsMutex);
4472 XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
4473 wc_UnLockMutex(&StatsMutex);
4474 return 0;
4475}
4476
4477
4478/* Copies the SSL statistics into the provided stats record.
4479 * returns 0 on success, -1 on error */
4480int ssl_ReadStatistics(SSLStats* stats)
4481{
4482 if (stats == NULL)
4483 return -1;
4484
4485 LOCK_STAT();
4486 XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
4487 UNLOCK_STAT();
4488 return 0;
4489}
4490
4491/* Copies the SSL statistics into the provided stats record then
4492 * resets the statistics tracking global structure.
4493 * returns 0 on success, -1 on error */
4494int ssl_ReadResetStatistics(SSLStats* stats)
4495{
4496 if (stats == NULL)
4497 return -1;
4498
4499 LOCK_STAT();
4500 XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
4501 XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
4502 UNLOCK_STAT();
4503 return 0;
4504}
4505
4506#endif /* WOLFSSL_SNIFFER_STATS */
4507
4508
4509#ifdef WOLFSSL_SNIFFER_WATCH
4510
4511int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error)
4512{
4513 (void)devId;
4514 WatchCb = cb;
4515 return CreateWatchSnifferServer(error);
4516}
4517
4518
4519int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error)
4520{
4521 WatchCb = cb;
4522 return CreateWatchSnifferServer(error);
4523}
4524
4525
4526int ssl_SetWatchKeyCtx(void* ctx, char* error)
4527{
4528 (void)error;
4529 WatchCbCtx = ctx;
4530 return 0;
4531}
4532
4533
4534int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
4535 int keyType, char* error)
4536{
4537 SnifferSession* sniffer;
4538 int ret;
4539
4540 if (vSniffer == NULL) {
4541 return -1;
4542 }
4543 if (key == NULL || keySz == 0) {
4544 return -1;
4545 }
4546
4547 sniffer = (SnifferSession*)vSniffer;
4548 /* Remap the keyType from what the user can use to
4549 * what wolfSSL_use_PrivateKey_buffer expects. */
4550 keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
4551 WOLFSSL_FILETYPE_ASN1;
4552
4553 ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer,
4554 key, keySz, keyType);
4555 if (ret != WOLFSSL_SUCCESS) {
4556 SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE);
4557 return -1;
4558 }
4559
4560 return 0;
4561}
4562
4563
4564int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
4565 const char* password, char* error)
4566{
4567 byte* keyBuf = NULL;
4568 word32 keyBufSz = 0;
4569 int ret;
4570
4571 if (vSniffer == NULL) {
4572 return -1;
4573 }
4574 if (keyFile == NULL) {
4575 return -1;
4576 }
4577
4578 /* Remap the keyType from what the user can use to
4579 * what LoadKeyFile expects. */
4580 keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
4581 WOLFSSL_FILETYPE_ASN1;
4582
4583 ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, keyType, password);
4584 if (ret < 0) {
4585 SetError(KEY_FILE_STR, error, NULL, 0);
4586 XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
4587 return -1;
4588 }
4589
4590 ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER,
4591 error);
4592 XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
4593
4594 return ret;
4595}
4596
4597#endif /* WOLFSSL_SNIFFER_WATCH */
4598
4599
4600#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
4601
4602int ssl_SetStoreDataCallback(SSLStoreDataCb cb)
4603{
4604 StoreDataCb = cb;
4605 return 0;
4606}
4607
4608#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
4609
4610#endif /* WOLFSSL_SNIFFER */
4611#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.