1 /* sniffer.c
2  *
3  * Copyright (C) 2006-2021 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 #include <wolfssl/wolfcrypt/types.h>
29 #include <wolfssl/wolfcrypt/wc_port.h>
30 
31 /* xctime */
32 #ifndef XCTIME
33    #define XCTIME ctime
34 #endif
35 
36 /* only in this file, to avoid confusing future ports leave
37  * these defines here. Do not move to wc_port.h */
38 #ifdef USER_CUSTOM_SNIFFX
39     /* To be implemented in user_settings.h */
40 #elif defined(FUSION_RTOS)
41     #include <fcl_network.h>
42     #define XINET_NTOA FNS_INET_NTOA
43     #define XINET_ATON FNS_INET_ATON
44     #define XINET_PTON(a,b,c,d) FNS_INET_PTON((a),(b),(c),(d),NULL)
45     #define XINET_NTOP(a,b,c,d) FNS_INET_NTOP((a),(b),(c),(d),NULL)
46     #define XINET_ADDR FNS_INET_ADDR
47     #define XHTONS FNS_HTONS
48     #define XNTOHS FNS_NTOHS
49     #define XHTONL FNS_HTONL
50     #define XNTOHL FNS_NTOHL
51     #define XINADDR_NONE FNS_INADDR_NONE
52 #else
53     /* default */
54     #define XINET_NTOA inet_ntoa
55     #define XINET_ATON inet_aton
56     #define XINET_PTON(a,b,c) inet_pton((a),(b),(c))
57     #define XINET_NTOP inet_ntop
58     #define XINET_ADDR inet_addr
59     #define XHTONS htons
60     #define XNTOHS ntohs
61     #define XHTONL htonl
62     #define XNTOHL ntohl
63     #define XINADDR_NONE INADDR_NONE
64 #endif
65 
66 #if !defined(WOLFCRYPT_ONLY) && !defined(NO_FILESYSTEM)
67 #ifdef WOLFSSL_SNIFFER
68 
69 #include <time.h>
70 
71 #ifdef FUSION_RTOS
72     #include <fns_inet.h>
73     #ifdef TCP_PROTOCOL
74         #undef TCP_PROTOCOL
75     #endif
76 #else
77     #ifndef _WIN32
78         #include <arpa/inet.h>
79     #else
80         #include <ws2tcpip.h>
81     #endif
82 #endif
83 
84 #ifdef _WIN32
85     #define SNPRINTF _snprintf
86 #else
87     #define SNPRINTF snprintf
88 #endif
89 
90 #include <wolfssl/internal.h>
91 #include <wolfssl/error-ssl.h>
92 #include <wolfssl/sniffer.h>
93 #include <wolfssl/sniffer_error.h>
94 
95 #ifndef NO_RSA
96     #include <wolfssl/wolfcrypt/rsa.h>
97 #endif
98 #ifndef NO_DH
99     #include <wolfssl/wolfcrypt/dh.h>
100 #endif
101 #ifdef HAVE_ECC
102     #include <wolfssl/wolfcrypt/ecc.h>
103 #endif
104 #ifdef HAVE_CURVE25519
105     #include <wolfssl/wolfcrypt/curve25519.h>
106 #endif
107 
108 #ifdef NO_INLINE
109     #include <wolfssl/wolfcrypt/misc.h>
110 #else
111     #define WOLFSSL_MISC_INCLUDED
112     #include <wolfcrypt/src/misc.c>
113 #endif
114 
115 #ifdef WOLF_CRYPTO_CB
116     #include <wolfssl/wolfcrypt/cryptocb.h>
117     #ifdef HAVE_INTEL_QA_SYNC
118         #include <wolfssl/wolfcrypt/port/intel/quickassist_sync.h>
119     #endif
120     #ifdef HAVE_CAVIUM_OCTEON_SYNC
121         #include <wolfssl/wolfcrypt/port/cavium/cavium_octeon_sync.h>
122     #endif
123 #endif
124 
125 
126 #ifndef WOLFSSL_SNIFFER_TIMEOUT
127     #define WOLFSSL_SNIFFER_TIMEOUT 900
128     /* Cache unclosed Sessions for 15 minutes since last used */
129 #endif
130 
131 /* Misc constants */
132 enum {
133     MAX_SERVER_ADDRESS = 128, /* maximum server address length */
134     MAX_SERVER_NAME    = 128, /* maximum server name length */
135     MAX_ERROR_LEN      = 80,  /* maximum error length */
136     ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
137     LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
138     TCP_PROTO          = 6,   /* TCP_PROTOCOL */
139     IP_HDR_SZ          = 20,  /* IPv4 header length, min */
140     IP6_HDR_SZ         = 40,  /* IPv6 header length, min */
141     TCP_HDR_SZ         = 20,  /* TCP header length, min */
142     IPV4               = 4,   /* IP version 4 */
143     IPV6               = 6,   /* IP version 6 */
144     TCP_PROTOCOL       = 6,   /* TCP Protocol id */
145     NO_NEXT_HEADER     = 59,  /* IPv6 no headers follow */
146     TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
147     HASH_SIZE          = 499, /* Session Hash Table Rows */
148     PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
149     FATAL_ERROR_STATE  = 1,   /* SnifferSession fatal error state */
150     TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
151     TICKET_HINT_AGE_LEN= 4,   /* Session Ticket Age add length */
152     EXT_TYPE_SZ        = 2,   /* Extension type length */
153     MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
154                          MTU_EXTRA,  /* Max input sz of reassembly */
155 
156     /* TLS Extensions */
157     EXT_SERVER_NAME                = 0x0000, /* a.k.a. SNI  */
158     EXT_MAX_FRAGMENT_LENGTH        = 0x0001,
159     EXT_TRUSTED_CA_KEYS            = 0x0003,
160     EXT_TRUNCATED_HMAC             = 0x0004,
161     EXT_STATUS_REQUEST             = 0x0005, /* a.k.a. OCSP stapling   */
162     EXT_SUPPORTED_GROUPS           = 0x000a, /* a.k.a. Supported Curves */
163     EXT_EC_POINT_FORMATS           = 0x000b,
164     EXT_SIGNATURE_ALGORITHMS       = 0x000d,
165     EXT_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */
166     EXT_STATUS_REQUEST_V2          = 0x0011, /* a.k.a. OCSP stapling v2 */
167     EXT_ENCRYPT_THEN_MAC           = 0x0016, /* RFC 7366 */
168     EXT_MASTER_SECRET              = 0x0017, /* Extended Master Secret Extension ID */
169     EXT_TICKET_ID                  = 0x0023, /* Session Ticket Extension ID */
170     EXT_PRE_SHARED_KEY             = 0x0029,
171     EXT_EARLY_DATA                 = 0x002a,
172     EXT_SUPPORTED_VERSIONS         = 0x002b,
173     EXT_COOKIE                     = 0x002c,
174     EXT_PSK_KEY_EXCHANGE_MODES     = 0x002d,
175     EXT_POST_HANDSHAKE_AUTH        = 0x0031,
176     EXT_SIGNATURE_ALGORITHMS_CERT  = 0x0032,
177     EXT_KEY_SHARE                  = 0x0033,
178     EXT_RENEGOTIATION_INFO         = 0xff01
179 };
180 
181 
182 #ifdef _WIN32
183 
184 static HMODULE dllModule;  /* for error string resources */
185 
DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)186 BOOL APIENTRY DllMain( HMODULE hModule,
187                        DWORD  ul_reason_for_call,
188                        LPVOID lpReserved
189                      )
190 {
191     static int didInit = 0;
192 
193     switch (ul_reason_for_call)
194     {
195     case DLL_PROCESS_ATTACH:
196         if (didInit == 0) {
197             dllModule = hModule;
198             ssl_InitSniffer();
199             didInit = 1;
200         }
201         break;
202     case DLL_THREAD_ATTACH:
203         break;
204     case DLL_THREAD_DETACH:
205         break;
206     case DLL_PROCESS_DETACH:
207         if (didInit) {
208             ssl_FreeSniffer();
209             didInit = 0;
210         }
211         break;
212     }
213     return TRUE;
214 }
215 
216 #endif /* _WIN32 */
217 
218 
219 static WOLFSSL_GLOBAL int TraceOn = 0;         /* Trace is off by default */
220 static WOLFSSL_GLOBAL XFILE TraceFile = 0;
221 
222 
223 /* windows uses .rc table for this */
224 #ifndef _WIN32
225 
226 static const char* const msgTable[] =
227 {
228     /* 1 */
229     "Out of Memory",
230     "New SSL Sniffer Server Registered",
231     "Checking IP Header",
232     "SSL Sniffer Server Not Registered",
233     "Checking TCP Header",
234 
235     /* 6 */
236     "SSL Sniffer Server Port Not Registered",
237     "RSA Private Decrypt Error",
238     "RSA Private Decode Error",
239     "Set Cipher Spec Error",
240     "Server Hello Input Malformed",
241 
242     /* 11 */
243     "Couldn't Resume Session Error",
244     "Server Did Resumption",
245     "Client Hello Input Malformed",
246     "Client Trying to Resume",
247     "Handshake Input Malformed",
248 
249     /* 16 */
250     "Got Hello Verify msg",
251     "Got Server Hello msg",
252     "Got Cert Request msg",
253     "Got Server Key Exchange msg",
254     "Got Cert msg",
255 
256     /* 21 */
257     "Got Server Hello Done msg",
258     "Got Finished msg",
259     "Got Client Hello msg",
260     "Got Client Key Exchange msg",
261     "Got Cert Verify msg",
262 
263     /* 26 */
264     "Got Unknown Handshake msg",
265     "New SSL Sniffer Session created",
266     "Couldn't create new SSL",
267     "Got a Packet to decode",
268     "No data present",
269 
270     /* 31 */
271     "Session Not Found",
272     "Got an Old Client Hello msg",
273     "Old Client Hello Input Malformed",
274     "Old Client Hello OK",
275     "Bad Old Client Hello",
276 
277     /* 36 */
278     "Bad Record Header",
279     "Record Header Input Malformed",
280     "Got a HandShake msg",
281     "Bad HandShake msg",
282     "Got a Change Cipher Spec msg",
283 
284     /* 41 */
285     "Got Application Data msg",
286     "Bad Application Data",
287     "Got an Alert msg",
288     "Another msg to Process",
289     "Removing Session From Table",
290 
291     /* 46 */
292     "Bad Key File",
293     "Wrong IP Version",
294     "Wrong Protocol type",
295     "Packet Short for header processing",
296     "Got Unknown Record Type",
297 
298     /* 51 */
299     "Can't Open Trace File",
300     "Session in Fatal Error State",
301     "Partial SSL record received",
302     "Buffer Error, malformed input",
303     "Added to Partial Input",
304 
305     /* 56 */
306     "Received a Duplicate Packet",
307     "Received an Out of Order Packet",
308     "Received an Overlap Duplicate Packet",
309     "Received an Overlap Reassembly Begin Duplicate Packet",
310     "Received an Overlap Reassembly End Duplicate Packet",
311 
312     /* 61 */
313     "Missed the Client Hello Entirely",
314     "Got Hello Request msg",
315     "Got Session Ticket msg",
316     "Bad Input",
317     "Bad Decrypt Type",
318 
319     /* 66 */
320     "Bad Finished Message Processing",
321     "Bad Compression Type",
322     "Bad DeriveKeys Error",
323     "Saw ACK for Missing Packet Error",
324     "Bad Decrypt Operation",
325 
326     /* 71 */
327     "Decrypt Keys Not Set Up",
328     "Late Key Load Error",
329     "Got Certificate Status msg",
330     "RSA Key Missing Error",
331     "Secure Renegotiation Not Supported",
332 
333     /* 76 */
334     "Get Session Stats Failure",
335     "Reassembly Buffer Size Exceeded",
336     "Dropping Lost Fragment",
337     "Dropping Partial Record",
338     "Clear ACK Fault",
339 
340     /* 81 */
341     "Bad Decrypt Size",
342     "Extended Master Secret Hash Error",
343     "Handshake Message Split Across TLS Records",
344     "ECC Private Decode Error",
345     "ECC Public Decode Error",
346 
347     /* 86 */
348     "Watch callback not set",
349     "Watch hash failed",
350     "Watch callback failed",
351     "Bad Certificate Message",
352     "Store data callback not set",
353 
354     /* 91 */
355     "No data destination Error",
356     "Store data callback failed",
357     "Loading chain input",
358     "Got encrypted extension",
359     "Got Hello Retry Request",
360 };
361 
362 
363 /* *nix version uses table above */
GetError(int idx,char * str)364 static void GetError(int idx, char* str)
365 {
366     if (str == NULL ||
367             idx < 0 || idx > (int)(sizeof(msgTable)/sizeof(const char* const)))
368         return;
369     XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1);
370     str[MAX_ERROR_LEN-1] = '\0';
371 }
372 
373 
374 #else /* _WIN32 */
375 
376 
377 /* Windows version uses .rc table */
GetError(int idx,char * buffer)378 static void GetError(int idx, char* buffer)
379 {
380     if (buffer == NULL)
381         return;
382     if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
383         buffer[0] = 0;
384 }
385 
386 
387 #endif /* _WIN32 */
388 
389 
390 /* Packet Buffer for reassembly list and ready list */
391 typedef struct PacketBuffer {
392     word32  begin;      /* relative sequence begin */
393     word32  end;        /* relative sequence end   */
394     byte*   data;       /* actual data             */
395     struct PacketBuffer* next; /* next on reassembly list or ready list */
396 } PacketBuffer;
397 
398 
399 #ifdef HAVE_SNI
400 
401 /* NamedKey maps a SNI name to a specific private key */
402 typedef struct NamedKey {
403     char             name[MAX_SERVER_NAME];      /* server DNS name */
404     word32           nameSz;                     /* size of server DNS name */
405     byte*            key;                        /* DER private key */
406     word32           keySz;                      /* size of DER private key */
407     int              isEphemeralKey;
408     struct NamedKey* next;                       /* for list */
409 } NamedKey;
410 
411 #endif
412 
413 
414 typedef struct IpAddrInfo {
415     int version;
416     union {
417         word32 ip4;
418         byte   ip6[16];
419     };
420 } IpAddrInfo;
421 
422 
423 /* Sniffer Server holds info for each server/port monitored */
424 typedef struct SnifferServer {
425     WOLFSSL_CTX*   ctx;                          /* SSL context */
426     char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
427     IpAddrInfo     server;                       /* network order address */
428     int            port;                         /* server port */
429 #ifdef HAVE_SNI
430     NamedKey*      namedKeys;                    /* mapping of names and keys */
431     wolfSSL_Mutex  namedKeysMutex;               /* mutex for namedKey list */
432 #endif
433     struct SnifferServer* next;                  /* for list */
434 } SnifferServer;
435 
436 
437 /* Session Flags */
438 typedef struct Flags {
439     byte           side;            /* which end is current packet headed */
440     byte           serverCipherOn;  /* indicates whether cipher is active */
441     byte           clientCipherOn;  /* indicates whether cipher is active */
442     byte           resuming;        /* did this session come from resumption */
443     byte           cached;          /* have we cached this session yet */
444     byte           clientHello;     /* processed client hello yet, for SSLv2 */
445     byte           finCount;        /* get both FINs before removing */
446     byte           fatalError;      /* fatal error state */
447     byte           cliAckFault;     /* client acked unseen data from server */
448     byte           srvAckFault;     /* server acked unseen data from client */
449     byte           cliSkipPartial;  /* client skips partial data to catch up */
450     byte           srvSkipPartial;  /* server skips partial data to catch up */
451 #ifdef HAVE_EXTENDED_MASTER
452     byte           expectEms;       /* expect extended master secret */
453 #endif
454     byte           gotFinished;     /* processed finished */
455     byte           secRenegEn;      /* secure renegotiation enabled */
456 } Flags;
457 
458 
459 /* Out of Order FIN capture */
460 typedef struct FinCapture {
461     word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
462     word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
463     byte   cliCounted;              /* did we count yet, detects duplicates */
464     byte   srvCounted;              /* did we count yet, detects duplicates */
465 } FinCapture;
466 
467 
468 typedef struct HsHashes {
469 #ifndef NO_OLD_TLS
470 #ifndef NO_SHA
471     wc_Sha hashSha;
472 #endif
473 #ifndef NO_MD5
474     wc_Md5 hashMd5;
475 #endif
476 #endif /* !NO_OLD_TLS */
477 #ifndef NO_SHA256
478     wc_Sha256 hashSha256;
479 #endif
480 #ifdef WOLFSSL_SHA384
481     wc_Sha384 hashSha384;
482 #endif
483 } HsHashes;
484 
485 typedef struct KeyShareInfo {
486     word16      named_group;
487     int         key_len;
488     const byte* key;
489 
490     /* additional info */
491     int         dh_key_bits;
492     int         curve_id;
493 } KeyShareInfo;
494 
495 /* maximum previous acks to capture */
496 #ifndef WC_SNIFFER_HS_ACK_HIST_MAX
497 #define WC_SNIFFER_HS_ACK_HIST_MAX 10
498 #endif
499 
500 /* Sniffer Session holds info for each client/server SSL/TLS session */
501 typedef struct SnifferSession {
502     SnifferServer* context;         /* server context */
503     WOLFSSL*       sslServer;       /* SSL server side decode */
504     WOLFSSL*       sslClient;       /* SSL client side decode */
505     IpAddrInfo     server;          /* server address in network byte order */
506     IpAddrInfo     client;          /* client address in network byte order */
507     word16         srvPort;         /* server port */
508     word16         cliPort;         /* client port */
509     word32         cliSeqStart;     /* client start sequence */
510     word32         srvSeqStart;     /* server start sequence */
511     word32         cliExpected;     /* client expected sequence (relative) */
512     word32         srvExpected;     /* server expected sequence (relative) */
513     word32         cliAcks[WC_SNIFFER_HS_ACK_HIST_MAX]; /* history of acks during handshake */
514     word32         srvAcks[WC_SNIFFER_HS_ACK_HIST_MAX]; /* history of acks during handshake */
515     FinCapture     finCapture;      /* retain out of order FIN s */
516     Flags          flags;           /* session flags */
517     time_t         lastUsed;        /* last used ticks */
518     word32         keySz;           /* size of the private key */
519     PacketBuffer*  cliReassemblyList; /* client out of order packets */
520     PacketBuffer*  srvReassemblyList; /* server out of order packets */
521     word32         cliReassemblyMemory; /* client packet memory used */
522     word32         srvReassemblyMemory; /* server packet memory used */
523     struct SnifferSession* next;    /* for hash table list */
524     byte*          ticketID;        /* mac ID of session ticket */
525 #ifdef HAVE_MAX_FRAGMENT
526     byte*          tlsFragBuf;
527     word32         tlsFragOffset;
528     word32         tlsFragSize;
529 #endif
530 #ifdef HAVE_SNI
531     const char*    sni;             /* server name indication */
532 #endif
533 #ifdef HAVE_EXTENDED_MASTER
534     HsHashes*      hash;
535 #endif
536 #ifdef WOLFSSL_TLS13
537     byte*          cliKeyShare;
538     word32         cliKeyShareSz;
539     KeyShareInfo   srvKs;
540     KeyShareInfo   cliKs;
541 #endif
542 } SnifferSession;
543 
544 
545 /* Sniffer Server List and mutex */
546 static WOLFSSL_GLOBAL SnifferServer* ServerList = NULL;
547 static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex;
548 
549 /* Session Hash Table, mutex, and count */
550 static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE];
551 static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex;
552 static WOLFSSL_GLOBAL int SessionCount = 0;
553 
554 /* Recovery of missed data switches and stats */
555 static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex; /* for stats */
556 static WOLFSSL_GLOBAL int RecoveryEnabled    = 0;  /* global switch */
557 static WOLFSSL_GLOBAL int MaxRecoveryMemory  = -1;
558                                            /* per session max recovery memory */
559 static WOLFSSL_GLOBAL word32 MissedDataSessions = 0;
560                                             /* # of sessions with missed data */
561 
562 /* Connection Info Callback */
563 static WOLFSSL_GLOBAL SSLConnCb ConnectionCb;
564 static WOLFSSL_GLOBAL void*     ConnectionCbCtx = NULL;
565 
566 #ifdef WOLFSSL_SNIFFER_STATS
567 /* Sessions Statistics */
568 static WOLFSSL_GLOBAL SSLStats SnifferStats;
569 static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex;
570 #endif
571 
572 #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
573 static WOLFSSL_GLOBAL SSLKeyCb KeyCb;
574 static WOLFSSL_GLOBAL void*    KeyCbCtx = NULL;
575 #endif
576 
577 #ifdef WOLFSSL_SNIFFER_WATCH
578 /* Watch Key Callback */
579 static WOLFSSL_GLOBAL SSLWatchCb WatchCb;
580 static WOLFSSL_GLOBAL void*      WatchCbCtx = NULL;
581 #endif
582 
583 #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
584 /* Store Data Callback */
585 static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb;
586 #endif
587 
588 
UpdateMissedDataSessions(void)589 static void UpdateMissedDataSessions(void)
590 {
591     wc_LockMutex(&RecoveryMutex);
592     MissedDataSessions += 1;
593     wc_UnLockMutex(&RecoveryMutex);
594 }
595 
596 
597 #ifdef WOLFSSL_SNIFFER_STATS
598 #define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0)
599 #define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0)
600 #define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0)
601 #define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1)
602 #define ADD_TO_STAT(x,y) do { LOCK_STAT(); \
603     NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0)
604 #define INC_STAT(x) do { LOCK_STAT(); \
605     NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0)
606 #endif
607 
608 
609 #ifdef WOLF_CRYPTO_CB
610     static WOLFSSL_GLOBAL int CryptoDeviceId = INVALID_DEVID;
611 #endif
612 
613 
614 /* Initialize overall Sniffer */
ssl_InitSniffer(void)615 void ssl_InitSniffer(void)
616 {
617     wolfSSL_Init();
618     wc_InitMutex(&ServerListMutex);
619     wc_InitMutex(&SessionMutex);
620     wc_InitMutex(&RecoveryMutex);
621 #ifdef WOLFSSL_SNIFFER_STATS
622     XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
623     wc_InitMutex(&StatsMutex);
624 #endif
625 #ifdef WOLF_CRYPTO_CB
626     #ifdef HAVE_INTEL_QA_SYNC
627     CryptoDeviceId = wc_CryptoCb_InitIntelQa();
628     if (INVALID_DEVID == CryptoDeviceId) {
629         printf("Couldn't init the Intel QA\n");
630     }
631     #endif
632     #ifdef HAVE_CAVIUM_OCTEON_SYNC
633     CryptoDeviceId = wc_CryptoCb_InitOcteon();
634     if (INVALID_DEVID == CryptoDeviceId) {
635         printf("Couldn't init the Intel QA\n");
636     }
637     #endif
638 #endif
639 }
640 
641 
642 #ifdef HAVE_SNI
643 
644 /* Free Named Key and the zero out the private key it holds */
FreeNamedKey(NamedKey * in)645 static void FreeNamedKey(NamedKey* in)
646 {
647     if (in) {
648         if (in->key) {
649             ForceZero(in->key, in->keySz);
650             XFREE(in->key, NULL, DYNAMIC_TYPE_X509);
651         }
652         XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
653     }
654 }
655 
656 
FreeNamedKeyList(NamedKey * in)657 static void FreeNamedKeyList(NamedKey* in)
658 {
659     NamedKey* next;
660 
661     while (in) {
662         next = in->next;
663         FreeNamedKey(in);
664         in = next;
665     }
666 }
667 
668 #endif
669 
670 
671 /* Free Sniffer Server's resources/self */
FreeSnifferServer(SnifferServer * srv)672 static void FreeSnifferServer(SnifferServer* srv)
673 {
674     if (srv) {
675 #ifdef HAVE_SNI
676         wc_LockMutex(&srv->namedKeysMutex);
677         FreeNamedKeyList(srv->namedKeys);
678         wc_UnLockMutex(&srv->namedKeysMutex);
679         wc_FreeMutex(&srv->namedKeysMutex);
680 #endif
681         wolfSSL_CTX_free(srv->ctx);
682     }
683     XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
684 }
685 
686 
687 /* free PacketBuffer's resources/self */
FreePacketBuffer(PacketBuffer * del)688 static void FreePacketBuffer(PacketBuffer* del)
689 {
690     if (del) {
691         XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
692         XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB);
693     }
694 }
695 
696 
697 /* remove PacketBuffer List */
FreePacketList(PacketBuffer * in)698 static void FreePacketList(PacketBuffer* in)
699 {
700     if (in) {
701         PacketBuffer* del;
702         PacketBuffer* packet = in;
703 
704         while (packet) {
705             del = packet;
706             packet = packet->next;
707             FreePacketBuffer(del);
708         }
709     }
710 }
711 
712 
713 /* Free Sniffer Session's resources/self */
FreeSnifferSession(SnifferSession * session)714 static void FreeSnifferSession(SnifferSession* session)
715 {
716     if (session) {
717         wolfSSL_free(session->sslClient);
718         wolfSSL_free(session->sslServer);
719 
720         FreePacketList(session->cliReassemblyList);
721         FreePacketList(session->srvReassemblyList);
722 
723         XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
724 #ifdef HAVE_EXTENDED_MASTER
725         XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
726 #endif
727 #ifdef WOLFSSL_TLS13
728         if (session->cliKeyShare)
729             XFREE(session->cliKeyShare, NULL, DYNAMIC_TYPE_TMP_BUFFER);
730 #endif
731 #ifdef HAVE_MAX_FRAGMENT
732         if (session->tlsFragBuf) {
733             XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
734             session->tlsFragBuf = NULL;
735         }
736 #endif
737     }
738     XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
739 }
740 
741 
742 /* Free overall Sniffer */
ssl_FreeSniffer(void)743 void ssl_FreeSniffer(void)
744 {
745     SnifferServer*  srv;
746     SnifferServer*  removeServer;
747     SnifferSession* session;
748     SnifferSession* removeSession;
749     int i;
750 
751     wc_LockMutex(&ServerListMutex);
752     wc_LockMutex(&SessionMutex);
753 
754     /* Free sessions (wolfSSL objects) first */
755     for (i = 0; i < HASH_SIZE; i++) {
756         session = SessionTable[i];
757         while (session) {
758             removeSession = session;
759             session = session->next;
760             FreeSnifferSession(removeSession);
761         }
762     }
763     SessionCount = 0;
764 
765     /* Then server (wolfSSL_CTX) */
766     srv = ServerList;
767     while (srv) {
768         removeServer = srv;
769         srv = srv->next;
770         FreeSnifferServer(removeServer);
771     }
772     ServerList = NULL;
773 
774     wc_UnLockMutex(&SessionMutex);
775     wc_UnLockMutex(&ServerListMutex);
776 
777     wc_FreeMutex(&RecoveryMutex);
778     wc_FreeMutex(&SessionMutex);
779     wc_FreeMutex(&ServerListMutex);
780 
781 #ifdef WOLF_CRYPTO_CB
782 #ifdef HAVE_INTEL_QA_SYNC
783     wc_CryptoCb_CleanupIntelQa(&CryptoDeviceId);
784 #endif
785 #ifdef HAVE_CAVIUM_OCTEON_SYNC
786     wc_CryptoCb_CleanupOcteon(&CryptoDeviceId);
787 #endif
788 #endif
789 
790     if (TraceFile) {
791         TraceOn = 0;
792         XFCLOSE(TraceFile);
793         TraceFile = NULL;
794     }
795 
796     wolfSSL_Cleanup();
797 }
798 
799 
800 #ifdef HAVE_EXTENDED_MASTER
801 
HashInit(HsHashes * hash)802 static int HashInit(HsHashes* hash)
803 {
804     int ret = 0;
805 
806     XMEMSET(hash, 0, sizeof(HsHashes));
807 
808 #ifndef NO_OLD_TLS
809 #ifndef NO_SHA
810     if (ret == 0)
811         ret = wc_InitSha(&hash->hashSha);
812 #endif
813 #ifndef NO_MD5
814     if (ret == 0)
815         ret = wc_InitMd5(&hash->hashMd5);
816 #endif
817 #endif /* !NO_OLD_TLS */
818 #ifndef NO_SHA256
819     if (ret == 0)
820         ret = wc_InitSha256(&hash->hashSha256);
821 #endif
822 #ifdef WOLFSSL_SHA384
823     if (ret == 0)
824         ret = wc_InitSha384(&hash->hashSha384);
825 #endif
826 
827     return ret;
828 }
829 
HashUpdate(HsHashes * hash,const byte * input,int sz)830 static int HashUpdate(HsHashes* hash, const byte* input, int sz)
831 {
832     int ret = 0;
833 
834     input -= HANDSHAKE_HEADER_SZ;
835     sz += HANDSHAKE_HEADER_SZ;
836 
837 #ifndef NO_OLD_TLS
838 #ifndef NO_SHA
839     if (ret == 0)
840         ret = wc_ShaUpdate(&hash->hashSha, input, sz);
841 #endif
842 #ifndef NO_MD5
843     if (ret == 0)
844         ret = wc_Md5Update(&hash->hashMd5, input, sz);
845 #endif
846 #endif /* !NO_OLD_TLS */
847 #ifndef NO_SHA256
848     if (ret == 0)
849         ret = wc_Sha256Update(&hash->hashSha256, input, sz);
850 #endif
851 #ifdef WOLFSSL_SHA384
852     if (ret == 0)
853         ret = wc_Sha384Update(&hash->hashSha384, input, sz);
854 #endif
855 
856     return ret;
857 }
858 
HashCopy(HS_Hashes * d,HsHashes * s)859 static int HashCopy(HS_Hashes* d, HsHashes* s)
860 {
861 #ifndef NO_OLD_TLS
862 #ifndef NO_SHA
863     XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
864 #endif
865 #ifndef NO_MD5
866     XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
867 #endif
868 #endif /* !NO_OLD_TLS */
869 #ifndef NO_SHA256
870     XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
871 #endif
872 #ifdef WOLFSSL_SHA384
873     XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
874 #endif
875 
876     return 0;
877 }
878 
879 #endif
880 
881 
882 /* Initialize a SnifferServer */
InitSnifferServer(SnifferServer * sniffer)883 static void InitSnifferServer(SnifferServer* sniffer)
884 {
885     XMEMSET(sniffer, 0, sizeof(SnifferServer));
886 }
887 
888 
889 /* Initialize session flags */
InitFlags(Flags * flags)890 static void InitFlags(Flags* flags)
891 {
892     XMEMSET(flags, 0, sizeof(Flags));
893 }
894 
895 
896 /* Initialize FIN Capture */
InitFinCapture(FinCapture * cap)897 static void InitFinCapture(FinCapture* cap)
898 {
899     XMEMSET(cap, 0, sizeof(FinCapture));
900 }
901 
902 
903 /* Initialize a Sniffer Session */
InitSession(SnifferSession * session)904 static void InitSession(SnifferSession* session)
905 {
906     XMEMSET(session, 0, sizeof(SnifferSession));
907     InitFlags(&session->flags);
908     InitFinCapture(&session->finCapture);
909 }
910 
911 
912 /* IP Info from IP Header */
913 typedef struct IpInfo {
914     int    length;        /* length of this header */
915     int    total;         /* total length of fragment */
916     IpAddrInfo src;       /* network order source address */
917     IpAddrInfo dst;       /* network order destination address */
918 } IpInfo;
919 
920 
921 /* TCP Info from TCP Header */
922 typedef struct TcpInfo {
923     int    srcPort;       /* source port */
924     int    dstPort;       /* source port */
925     int    length;        /* length of this header */
926     word32 sequence;      /* sequence number */
927     word32 ackNumber;     /* ack number */
928     byte   fin;           /* FIN set */
929     byte   rst;           /* RST set */
930     byte   syn;           /* SYN set */
931     byte   ack;           /* ACK set */
932 } TcpInfo;
933 
934 
935 /* Tcp Pseudo Header for Checksum calculation */
936 typedef struct TcpPseudoHdr {
937     word32  src;        /* source address */
938     word32  dst;        /* destination address */
939     byte    rsv;        /* reserved, always 0 */
940     byte    protocol;   /* IP protocol */
941     word16  length;     /* tcp header length + data length (doesn't include */
942                         /* pseudo header length) network order */
943 } TcpPseudoHdr;
944 
945 
946 /* Password Setting Callback */
SetPassword(char * passwd,int sz,int rw,void * userdata)947 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
948 {
949     (void)rw;
950     XSTRNCPY(passwd, (const char*)userdata, sz);
951     return (int)XSTRLEN((const char*)userdata);
952 }
953 
954 
955 /* Ethernet Header */
956 typedef struct EthernetHdr {
957     byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */
958     byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */
959     word16 type;                      /* IP, ARP, etc */
960 } EthernetHdr;
961 
962 
963 /* IPv4 Header */
964 typedef struct IpHdr {
965     byte    ver_hl;              /* version/header length */
966     byte    tos;                 /* type of service */
967     word16  length;              /* total length */
968     word16  id;                  /* identification */
969     word16  offset;              /* fragment offset field */
970     byte    ttl;                 /* time to live */
971     byte    protocol;            /* protocol */
972     word16  sum;                 /* checksum */
973     word32  src;                 /* source address */
974     word32  dst;                 /* destination address */
975 } IpHdr;
976 
977 
978 /* IPv6 Header */
979 typedef struct Ip6Hdr {
980     byte    ver_hl;              /* version/traffic class high */
981     byte    tc_fl;               /* traffic class low/flow label high */
982     word16  fl;                  /* flow label low */
983     word16  length;              /* payload length */
984     byte    next_header;         /* next header (6 for TCP, any other skip) */
985     byte    hl;                  /* hop limit */
986     byte    src[16];             /* source address */
987     byte    dst[16];             /* destination address */
988 } Ip6Hdr;
989 
990 
991 /* IPv6 extension header */
992 typedef struct Ip6ExtHdr {
993     byte next_header;            /* next header (6 for TCP, any other skip) */
994     byte length;                 /* length in 8-octet units - 1 */
995     byte reserved[6];
996 } Ip6ExtHdr;
997 
998 
999 #define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
1000 #define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
1001 
1002 /* TCP Header */
1003 typedef struct TcpHdr {
1004     word16  srcPort;            /* source port */
1005     word16  dstPort;            /* destination port */
1006     word32  sequence;           /* sequence number */
1007     word32  ack;                /* acknowledgment number */
1008     byte    offset;             /* data offset, reserved */
1009     byte    flags;              /* option flags */
1010     word16  window;             /* window */
1011     word16  sum;                /* checksum */
1012     word16  urgent;             /* urgent pointer */
1013 } TcpHdr;
1014 
1015 #define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
1016 #define TCP_FIN 0x01
1017 #define TCP_SYN 0x02
1018 #define TCP_RST 0x04
1019 #define TCP_ACK 0x10
1020 
1021 
1022 
1023 
1024 
1025 /* Use platform specific GetError to write to trace file if tracing */
TraceError(int idx,char * error)1026 static void TraceError(int idx, char* error)
1027 {
1028     if (TraceOn) {
1029         char myBuffer[MAX_ERROR_LEN];
1030         if (error == NULL) {
1031             error = myBuffer;
1032             GetError(idx, myBuffer);
1033         }
1034         XFPRINTF(TraceFile, "\t%s\n", error);
1035 #ifdef DEBUG_SNIFFER
1036         XFPRINTF(stderr,    "\t%s\n", error);
1037 #endif
1038     }
1039 }
1040 
Trace(int idx)1041 static void Trace(int idx)
1042 {
1043     TraceError(idx, NULL);
1044 }
1045 
1046 
1047 /* Show TimeStamp for beginning of packet Trace */
TraceHeader(void)1048 static void TraceHeader(void)
1049 {
1050     if (TraceOn) {
1051         time_t ticks = XTIME(NULL);
1052         XFPRINTF(TraceFile, "\n%s", XCTIME(&ticks));
1053     }
1054 }
1055 
1056 
1057 /* Show Set Server info for Trace */
TraceSetServer(const char * srv,int port,const char * keyFile)1058 static void TraceSetServer(const char* srv, int port, const char* keyFile)
1059 {
1060     if (TraceOn) {
1061         XFPRINTF(TraceFile, "\tTrying to install a new Sniffer Server with\n");
1062         XFPRINTF(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
1063                                                                     keyFile);
1064     }
1065 }
1066 
1067 
1068 #ifdef HAVE_SNI
1069 
1070 /* Show Set Named Server info for Trace */
TraceSetNamedServer(const char * name,const char * srv,int port,const char * keyFile)1071 static void TraceSetNamedServer(const char* name,
1072                                  const char* srv, int port, const char* keyFile)
1073 {
1074     if (TraceOn) {
1075         XFPRINTF(TraceFile, "\tTrying to install a new Sniffer Server with\n");
1076         XFPRINTF(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
1077         name ? name : "",
1078         srv ? srv : "",
1079         port,
1080         keyFile ? keyFile : "");
1081     }
1082 }
1083 
1084 #endif
1085 
1086 
1087 /* Trace got packet number */
TracePacket(void)1088 static void TracePacket(void)
1089 {
1090     if (TraceOn) {
1091         static word32 packetNumber = 0;
1092         XFPRINTF(TraceFile, "\tGot a Packet to decode, packet %u\n",
1093                 ++packetNumber);
1094     }
1095 }
1096 
1097 
1098 /* Convert network byte order address into human readable */
IpToS(int version,void * src,char * dst)1099 static const char* IpToS(int version, void* src, char* dst)
1100 {
1101     return XINET_NTOP(version, src, dst, TRACE_MSG_SZ);
1102 }
1103 
1104 
1105 /* Show destination and source address from Ip Hdr for packet Trace */
TraceIP(IpHdr * iphdr)1106 static void TraceIP(IpHdr* iphdr)
1107 {
1108     if (TraceOn) {
1109         char src[TRACE_MSG_SZ];
1110         char dst[TRACE_MSG_SZ];
1111         XFPRINTF(TraceFile, "\tdst:%s src:%s\n",
1112                 IpToS(AF_INET, &iphdr->dst, dst),
1113                 IpToS(AF_INET, &iphdr->src, src));
1114     }
1115 }
1116 
1117 
1118 /* Show destination and source address from Ip6Hdr for packet Trace */
TraceIP6(Ip6Hdr * iphdr)1119 static void TraceIP6(Ip6Hdr* iphdr)
1120 {
1121     if (TraceOn) {
1122         char src[TRACE_MSG_SZ];
1123         char dst[TRACE_MSG_SZ];
1124         XFPRINTF(TraceFile, "\tdst: %s src: %s\n",
1125                 IpToS(AF_INET6, iphdr->dst, dst),
1126                 IpToS(AF_INET6, iphdr->src, src));
1127     }
1128 }
1129 
1130 
1131 /* Show destination and source port from Tcp Hdr for packet Trace */
TraceTcp(TcpHdr * tcphdr)1132 static void TraceTcp(TcpHdr* tcphdr)
1133 {
1134     if (TraceOn) {
1135         XFPRINTF(TraceFile, "\tdstPort:%u srcPort:%u\n", XNTOHS(tcphdr->dstPort),
1136                 XNTOHS(tcphdr->srcPort));
1137     }
1138 }
1139 
1140 
1141 /* Show sequence and payload length for Trace */
TraceSequence(word32 seq,int len)1142 static void TraceSequence(word32 seq, int len)
1143 {
1144     if (TraceOn) {
1145         XFPRINTF(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
1146     }
1147 }
1148 
1149 
1150 /* Show sequence and payload length for Trace */
TraceAck(word32 ack,word32 expected)1151 static void TraceAck(word32 ack, word32 expected)
1152 {
1153     if (TraceOn) {
1154         XFPRINTF(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
1155     }
1156 }
1157 
1158 
1159 /* Show relative expected and relative received sequences */
TraceRelativeSequence(word32 expected,word32 got)1160 static void TraceRelativeSequence(word32 expected, word32 got)
1161 {
1162     if (TraceOn) {
1163         XFPRINTF(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
1164                 expected, got);
1165     }
1166 }
1167 
1168 
1169 /* Show server sequence startup from SYN */
TraceServerSyn(word32 seq)1170 static void TraceServerSyn(word32 seq)
1171 {
1172     if (TraceOn) {
1173         XFPRINTF(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
1174     }
1175 }
1176 
1177 
1178 /* Show client sequence startup from SYN */
TraceClientSyn(word32 seq)1179 static void TraceClientSyn(word32 seq)
1180 {
1181     if (TraceOn) {
1182         XFPRINTF(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
1183     }
1184 }
1185 
1186 
1187 /* Show client FIN capture */
TraceClientFin(word32 finSeq,word32 relSeq)1188 static void TraceClientFin(word32 finSeq, word32 relSeq)
1189 {
1190     if (TraceOn) {
1191         XFPRINTF(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
1192                 finSeq, relSeq);
1193     }
1194 }
1195 
1196 
1197 /* Show server FIN capture */
TraceServerFin(word32 finSeq,word32 relSeq)1198 static void TraceServerFin(word32 finSeq, word32 relSeq)
1199 {
1200     if (TraceOn) {
1201         XFPRINTF(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
1202                 finSeq, relSeq);
1203     }
1204 }
1205 
1206 
1207 /* Show number of SSL data bytes decoded, could be 0 (ok) */
TraceGotData(int bytes)1208 static void TraceGotData(int bytes)
1209 {
1210     if (TraceOn) {
1211         XFPRINTF(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
1212     }
1213 }
1214 
1215 
1216 /* Show bytes added to old SSL App data */
TraceAddedData(int newBytes,int existingBytes)1217 static void TraceAddedData(int newBytes, int existingBytes)
1218 {
1219     if (TraceOn) {
1220         XFPRINTF(TraceFile,
1221                 "\t%d bytes added to %d existing bytes in User Buffer\n",
1222                 newBytes, existingBytes);
1223     }
1224 }
1225 
1226 
1227 /* Show Stale Session */
TraceStaleSession(void)1228 static void TraceStaleSession(void)
1229 {
1230     if (TraceOn) {
1231         XFPRINTF(TraceFile, "\tFound a stale session\n");
1232     }
1233 }
1234 
1235 
1236 /* Show Finding Stale Sessions */
TraceFindingStale(void)1237 static void TraceFindingStale(void)
1238 {
1239     if (TraceOn) {
1240         XFPRINTF(TraceFile, "\tTrying to find Stale Sessions\n");
1241     }
1242 }
1243 
1244 
1245 /* Show Removed Session */
TraceRemovedSession(void)1246 static void TraceRemovedSession(void)
1247 {
1248     if (TraceOn) {
1249         XFPRINTF(TraceFile, "\tRemoved it\n");
1250     }
1251 }
1252 
1253 
1254 /* Show SSLInfo if provided and is valid. */
TraceSessionInfo(SSLInfo * sslInfo)1255 static void TraceSessionInfo(SSLInfo* sslInfo)
1256 {
1257     if (TraceOn) {
1258         if (sslInfo != NULL && sslInfo->isValid) {
1259             XFPRINTF(TraceFile,
1260                     "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) "
1261                     #ifdef HAVE_SNI
1262                     "sni:(%s) "
1263                     #endif
1264                     "keySize:(%u)\n",
1265                     sslInfo->protocolVersionMajor,
1266                     sslInfo->protocolVersionMinor,
1267                     sslInfo->serverCipherSuite0,
1268                     sslInfo->serverCipherSuite,
1269                     sslInfo->serverCipherSuiteName,
1270                     #ifdef HAVE_SNI
1271                     sslInfo->serverNameIndication,
1272                     #endif
1273                     sslInfo->keySize);
1274         }
1275     }
1276 }
1277 
1278 
1279 #ifdef WOLFSSL_SNIFFER_STATS
1280 
1281 /* Show value added to a named statistic. */
TraceStat(const char * name,int add)1282 static void TraceStat(const char* name, int add)
1283 {
1284     if (TraceOn) {
1285         XFPRINTF(TraceFile, "\tAdding %d to %s\n", add, name);
1286     }
1287 }
1288 
1289 #endif
1290 
1291 
1292 /* Set user error string */
SetError(int idx,char * error,SnifferSession * session,int fatal)1293 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
1294 {
1295     GetError(idx, error);
1296     TraceError(idx, error);
1297     if (session && fatal == FATAL_ERROR_STATE)
1298         session->flags.fatalError = 1;
1299 }
1300 
1301 
1302 /* Compare IpAddrInfo structs */
MatchAddr(IpAddrInfo l,IpAddrInfo r)1303 static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r)
1304 {
1305     if (l.version == r.version) {
1306         if (l.version == IPV4)
1307             return (l.ip4 == r.ip4);
1308         else if (l.version == IPV6)
1309             return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6)));
1310     }
1311     return 0;
1312 }
1313 
1314 
1315 #ifndef WOLFSSL_SNIFFER_WATCH
1316 
1317 /* See if this IPV4 network order address has been registered */
1318 /* return 1 is true, 0 is false */
IsServerRegistered(word32 addr)1319 static int IsServerRegistered(word32 addr)
1320 {
1321     int ret = 0;     /* false */
1322     SnifferServer* sniffer;
1323 
1324     wc_LockMutex(&ServerListMutex);
1325 
1326     sniffer = ServerList;
1327     while (sniffer) {
1328         if (sniffer->server.ip4 == addr) {
1329             ret = 1;
1330             break;
1331         }
1332         sniffer = sniffer->next;
1333     }
1334 
1335     wc_UnLockMutex(&ServerListMutex);
1336 
1337     return ret;
1338 }
1339 
1340 
1341 /* See if this port has been registered to watch */
1342 /* See if this IPV4 network order address has been registered */
1343 /* return 1 is true, 0 is false */
IsServerRegistered6(byte * addr)1344 static int IsServerRegistered6(byte* addr)
1345 {
1346     int ret = 0;     /* false */
1347     SnifferServer* sniffer;
1348 
1349     wc_LockMutex(&ServerListMutex);
1350 
1351     sniffer = ServerList;
1352     while (sniffer) {
1353         if (sniffer->server.version == IPV6 &&
1354                 0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) {
1355             ret = 1;
1356             break;
1357         }
1358         sniffer = sniffer->next;
1359     }
1360 
1361     wc_UnLockMutex(&ServerListMutex);
1362 
1363     return ret;
1364 }
1365 
1366 
1367 /* See if this port has been registered to watch */
1368 /* return 1 is true, 0 is false */
IsPortRegistered(word32 port)1369 static int IsPortRegistered(word32 port)
1370 {
1371     int ret = 0;    /* false */
1372     SnifferServer* sniffer;
1373 
1374     wc_LockMutex(&ServerListMutex);
1375 
1376     sniffer = ServerList;
1377     while (sniffer) {
1378         if (sniffer->port == (int)port) {
1379             ret = 1;
1380             break;
1381         }
1382         sniffer = sniffer->next;
1383     }
1384 
1385     wc_UnLockMutex(&ServerListMutex);
1386 
1387     return ret;
1388 }
1389 
1390 #endif
1391 
1392 
1393 /* Get SnifferServer from IP and Port */
GetSnifferServer(IpInfo * ipInfo,TcpInfo * tcpInfo)1394 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
1395 {
1396     SnifferServer* sniffer;
1397 
1398     wc_LockMutex(&ServerListMutex);
1399 
1400     sniffer = ServerList;
1401 
1402 #ifndef WOLFSSL_SNIFFER_WATCH
1403     while (sniffer) {
1404         if (sniffer->port == tcpInfo->srcPort &&
1405                 MatchAddr(sniffer->server, ipInfo->src))
1406             break;
1407         if (sniffer->port == tcpInfo->dstPort &&
1408                 MatchAddr(sniffer->server, ipInfo->dst))
1409             break;
1410 
1411         sniffer = sniffer->next;
1412     }
1413 #else
1414     (void)ipInfo;
1415     (void)tcpInfo;
1416 #endif
1417 
1418     wc_UnLockMutex(&ServerListMutex);
1419 
1420     return sniffer;
1421 }
1422 
1423 
1424 /* Hash the Session Info, return hash row */
SessionHash(IpInfo * ipInfo,TcpInfo * tcpInfo)1425 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
1426 {
1427     word32 hash = 1;
1428 
1429     if (ipInfo->src.version == IPV4) {
1430         hash *= ipInfo->src.ip4 * ipInfo->dst.ip4;
1431     }
1432     else if (ipInfo->src.version == IPV6) {
1433         word32* x;
1434         word32  y;
1435         x = (word32*)ipInfo->src.ip6;
1436         y = x[0] ^ x[1] ^ x[2] ^ x[3];
1437         hash *= y;
1438         x = (word32*)ipInfo->dst.ip6;
1439         y = x[0] ^ x[1] ^ x[2] ^ x[3];
1440         hash *= y;
1441     }
1442     hash *= tcpInfo->srcPort * tcpInfo->dstPort;
1443 
1444     return hash % HASH_SIZE;
1445 }
1446 
1447 
1448 /* Get Existing SnifferSession from IP and Port */
GetSnifferSession(IpInfo * ipInfo,TcpInfo * tcpInfo)1449 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
1450 {
1451     SnifferSession* session;
1452     time_t          currTime = XTIME(NULL);
1453     word32          row = SessionHash(ipInfo, tcpInfo);
1454 
1455     wc_LockMutex(&SessionMutex);
1456 
1457     session = SessionTable[row];
1458     while (session) {
1459         if (MatchAddr(session->server, ipInfo->src) &&
1460             MatchAddr(session->client, ipInfo->dst) &&
1461                     session->srvPort == tcpInfo->srcPort &&
1462                     session->cliPort == tcpInfo->dstPort)
1463             break;
1464 
1465         if (MatchAddr(session->client, ipInfo->src) &&
1466             MatchAddr(session->server, ipInfo->dst) &&
1467                     session->cliPort == tcpInfo->srcPort &&
1468                     session->srvPort == tcpInfo->dstPort)
1469             break;
1470 
1471         session = session->next;
1472     }
1473 
1474     if (session)
1475         session->lastUsed= currTime; /* keep session alive, remove stale will */
1476                                      /* leave alone */
1477     wc_UnLockMutex(&SessionMutex);
1478 
1479     /* determine side */
1480     if (session) {
1481         if (MatchAddr(ipInfo->dst, session->server) &&
1482             tcpInfo->dstPort == session->srvPort) {
1483 
1484             session->flags.side = WOLFSSL_SERVER_END;
1485         }
1486         else {
1487             session->flags.side = WOLFSSL_CLIENT_END;
1488         }
1489     }
1490 
1491     return session;
1492 }
1493 
1494 
1495 #if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH)
1496 
LoadKeyFile(byte ** keyBuf,word32 * keyBufSz,const char * keyFile,int keySz,int typeKey,const char * password)1497 static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1498                 const char* keyFile, int keySz, int typeKey,
1499                 const char* password)
1500 {
1501     byte* loadBuf;
1502     long fileSz = 0;
1503     XFILE file;
1504     int ret = -1;
1505 
1506     if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1507         return -1;
1508     }
1509 
1510     if (keySz == 0) {
1511         /* load from file */
1512         file = XFOPEN(keyFile, "rb");
1513         if (file == XBADFILE) return -1;
1514         if(XFSEEK(file, 0, XSEEK_END) != 0) {
1515             XFCLOSE(file);
1516             return -1;
1517         }
1518         fileSz = XFTELL(file);
1519         if (fileSz > MAX_WOLFSSL_FILE_SIZE || fileSz < 0) {
1520             XFCLOSE(file);
1521             return -1;
1522         }
1523         XREWIND(file);
1524 
1525         loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE);
1526         if (loadBuf == NULL) {
1527             XFCLOSE(file);
1528             return -1;
1529         }
1530 
1531         ret = (int)XFREAD(loadBuf, 1, fileSz, file);
1532         XFCLOSE(file);
1533 
1534         if (ret != fileSz) {
1535             XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1536             return -1;
1537         }
1538     }
1539     else {
1540         /* use buffer directly */
1541         loadBuf = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_FILE);
1542         if (loadBuf == NULL) {
1543             return -1;
1544         }
1545         fileSz = keySz;
1546         XMEMCPY(loadBuf, keyFile, fileSz);
1547     }
1548 
1549     if (typeKey == WOLFSSL_FILETYPE_PEM) {
1550         byte* saveBuf   = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509);
1551         int   saveBufSz = 0;
1552 
1553         ret = -1;
1554         if (saveBuf != NULL) {
1555             saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz,
1556                                                 saveBuf, (int)fileSz, password);
1557             if (saveBufSz < 0) {
1558                 saveBufSz = 0;
1559                 XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509);
1560                 saveBuf = NULL;
1561             }
1562             else
1563                 ret = 0;
1564         }
1565 
1566         ForceZero(loadBuf, (word32)fileSz);
1567         XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE);
1568 
1569         if (saveBuf) {
1570             *keyBuf = saveBuf;
1571             *keyBufSz = (word32)saveBufSz;
1572         }
1573     }
1574     else {
1575         *keyBuf = loadBuf;
1576         *keyBufSz = (word32)fileSz;
1577     }
1578 
1579     if (ret < 0) {
1580         return -1;
1581     }
1582 
1583     return ret;
1584 }
1585 
1586 #endif
1587 
1588 
1589 #ifdef WOLFSSL_SNIFFER_WATCH
1590 
CreateWatchSnifferServer(char * error)1591 static int CreateWatchSnifferServer(char* error)
1592 {
1593     SnifferServer* sniffer;
1594 
1595     sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL,
1596             DYNAMIC_TYPE_SNIFFER_SERVER);
1597     if (sniffer == NULL) {
1598         SetError(MEMORY_STR, error, NULL, 0);
1599         return -1;
1600     }
1601     InitSnifferServer(sniffer);
1602     sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
1603     if (!sniffer->ctx) {
1604         SetError(MEMORY_STR, error, NULL, 0);
1605         FreeSnifferServer(sniffer);
1606         return -1;
1607     }
1608 #ifdef WOLF_CRYPTO_CB
1609     if (CryptoDeviceId != INVALID_DEVID)
1610         wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1611 #endif
1612 
1613     /* add to server list */
1614     wc_LockMutex(&ServerListMutex);
1615     sniffer->next = ServerList;
1616     ServerList = sniffer;
1617     wc_UnLockMutex(&ServerListMutex);
1618 
1619     return 0;
1620 }
1621 
1622 #endif
1623 
1624 /* Caller locks ServerListMutex */
SetNamedPrivateKey(const char * name,const char * address,int port,const char * keyFile,int keySz,int typeKey,const char * password,char * error,int isEphemeralKey)1625 static int SetNamedPrivateKey(const char* name, const char* address, int port,
1626     const char* keyFile, int keySz, int typeKey, const char* password,
1627     char* error, int isEphemeralKey)
1628 {
1629     SnifferServer* sniffer;
1630     int            ret;
1631     int            type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
1632                                                       WOLFSSL_FILETYPE_ASN1;
1633     int            isNew = 0;
1634     IpAddrInfo     serverIp;
1635 
1636 #ifdef HAVE_SNI
1637     NamedKey* namedKey = NULL;
1638 #endif
1639 
1640     (void)name;
1641 #ifdef HAVE_SNI
1642     if (name != NULL) {
1643         namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey),
1644                 NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY);
1645         if (namedKey == NULL) {
1646             SetError(MEMORY_STR, error, NULL, 0);
1647             return -1;
1648         }
1649         XMEMSET(namedKey, 0, sizeof(NamedKey));
1650 
1651         namedKey->nameSz = (word32)XSTRLEN(name);
1652         if (namedKey->nameSz > sizeof(namedKey->name)-1)
1653             namedKey->nameSz = sizeof(namedKey->name)-1;
1654         XSTRNCPY(namedKey->name, name, namedKey->nameSz);
1655         namedKey->name[MAX_SERVER_NAME-1] = '\0';
1656         namedKey->isEphemeralKey = isEphemeralKey;
1657         ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1658                           keyFile, keySz, type, password);
1659         if (ret < 0) {
1660             SetError(KEY_FILE_STR, error, NULL, 0);
1661             FreeNamedKey(namedKey);
1662             return -1;
1663         }
1664     }
1665 #endif
1666 
1667     serverIp.version = IPV4;
1668     serverIp.ip4 = XINET_ADDR(address);
1669     if (serverIp.ip4 == XINADDR_NONE) {
1670     #ifdef FUSION_RTOS
1671         if (XINET_PTON(AF_INET6, address, serverIp.ip6,
1672                        sizeof(serverIp.ip4)) == 1) {
1673     #else
1674         if (XINET_PTON(AF_INET6, address, serverIp.ip6) == 1) {
1675     #endif
1676             serverIp.version = IPV6;
1677         }
1678     }
1679 
1680     sniffer = ServerList;
1681     while (sniffer != NULL &&
1682             (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
1683         sniffer = sniffer->next;
1684     }
1685 
1686     if (sniffer == NULL) {
1687         isNew = 1;
1688         sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer),
1689                 NULL, DYNAMIC_TYPE_SNIFFER_SERVER);
1690         if (sniffer == NULL) {
1691             SetError(MEMORY_STR, error, NULL, 0);
1692 #ifdef HAVE_SNI
1693             FreeNamedKey(namedKey);
1694 #endif
1695             return -1;
1696         }
1697         InitSnifferServer(sniffer);
1698 
1699         XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1700         sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1701         sniffer->server = serverIp;
1702         sniffer->port = port;
1703 
1704         sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
1705         if (!sniffer->ctx) {
1706             SetError(MEMORY_STR, error, NULL, 0);
1707 #ifdef HAVE_SNI
1708             FreeNamedKey(namedKey);
1709 #endif
1710             FreeSnifferServer(sniffer);
1711             return -1;
1712         }
1713     }
1714 
1715     if (name == NULL) {
1716         if (password) {
1717     #ifdef WOLFSSL_ENCRYPTED_KEYS
1718             wolfSSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1719             wolfSSL_CTX_set_default_passwd_cb_userdata(
1720                                                  sniffer->ctx, (void*)password);
1721     #endif
1722         }
1723 
1724     #ifdef WOLFSSL_STATIC_EPHEMERAL
1725         if (isEphemeralKey) {
1726             /* auto detect key type with WC_PK_TYPE_NONE */
1727             /* keySz == 0 mean load file */
1728             ret = wolfSSL_CTX_set_ephemeral_key(sniffer->ctx, WC_PK_TYPE_NONE,
1729                 keyFile, keySz, type);
1730             if (ret == 0)
1731                 ret = WOLFSSL_SUCCESS;
1732         }
1733         else
1734     #endif
1735         {
1736             if (keySz == 0) {
1737                 ret = wolfSSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1738             }
1739             else {
1740                 ret = wolfSSL_CTX_use_PrivateKey_buffer(sniffer->ctx,
1741                                             (const byte*)keyFile, keySz, type);
1742             }
1743         }
1744         if (ret != WOLFSSL_SUCCESS) {
1745             SetError(KEY_FILE_STR, error, NULL, 0);
1746             if (isNew)
1747                 FreeSnifferServer(sniffer);
1748             return -1;
1749         }
1750     #ifdef WOLF_CRYPTO_CB
1751         wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId);
1752     #endif
1753     }
1754 #ifdef HAVE_SNI
1755     else {
1756         wc_LockMutex(&sniffer->namedKeysMutex);
1757         namedKey->next = sniffer->namedKeys;
1758         sniffer->namedKeys = namedKey;
1759         wc_UnLockMutex(&sniffer->namedKeysMutex);
1760     }
1761 #endif
1762 
1763     if (isNew) {
1764         sniffer->next = ServerList;
1765         ServerList = sniffer;
1766     }
1767 
1768     return 0;
1769 }
1770 
1771 
1772 #ifdef HAVE_SNI
1773 /* Sets the private key for a specific name, server and port  */
1774 /* returns 0 on success, -1 on error */
1775 int ssl_SetNamedPrivateKey(const char* name,
1776                            const char* address, int port,
1777                            const char* keyFile, int typeKey,
1778                            const char* password, char* error)
1779 {
1780     int ret;
1781 
1782     TraceHeader();
1783     TraceSetNamedServer(name, address, port, keyFile);
1784 
1785     wc_LockMutex(&ServerListMutex);
1786     ret = SetNamedPrivateKey(name, address, port, keyFile, 0,
1787                              typeKey, password, error, 0);
1788     wc_UnLockMutex(&ServerListMutex);
1789 
1790     if (ret == 0)
1791         Trace(NEW_SERVER_STR);
1792 
1793     return ret;
1794 }
1795 
1796 int ssl_SetNamedPrivateKeyBuffer(const char* name,
1797                                  const char* address, int port,
1798                                  const char* keyBuf, int keySz, int typeKey,
1799                                  const char* password, char* error)
1800 {
1801     int ret;
1802 
1803     TraceHeader();
1804     TraceSetNamedServer(name, address, port, NULL);
1805 
1806     wc_LockMutex(&ServerListMutex);
1807     ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz,
1808                              typeKey, password, error, 0);
1809     wc_UnLockMutex(&ServerListMutex);
1810 
1811     if (ret == 0)
1812         Trace(NEW_SERVER_STR);
1813 
1814     return ret;
1815 }
1816 #endif /* HAVE_SNI */
1817 
1818 /* Sets the private key for a specific server and port  */
1819 /* returns 0 on success, -1 on error */
1820 int ssl_SetPrivateKey(const char* address, int port,
1821                       const char* keyFile, int typeKey,
1822                       const char* password, char* error)
1823 {
1824     int ret;
1825 
1826     TraceHeader();
1827     TraceSetServer(address, port, keyFile);
1828 
1829     wc_LockMutex(&ServerListMutex);
1830     ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0,
1831                              typeKey, password, error, 0);
1832     wc_UnLockMutex(&ServerListMutex);
1833 
1834     if (ret == 0)
1835         Trace(NEW_SERVER_STR);
1836 
1837     return ret;
1838 }
1839 
1840 int ssl_SetPrivateKeyBuffer(const char* address, int port,
1841                             const char* keyBuf, int keySz, int typeKey,
1842                             const char* password, char* error)
1843 {
1844     int ret;
1845 
1846     TraceHeader();
1847     TraceSetServer(address, port, "from buffer");
1848 
1849     wc_LockMutex(&ServerListMutex);
1850     ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz,
1851                              typeKey, password, error, 0);
1852     wc_UnLockMutex(&ServerListMutex);
1853 
1854     if (ret == 0)
1855         Trace(NEW_SERVER_STR);
1856 
1857     return ret;
1858 }
1859 
1860 #ifdef WOLFSSL_STATIC_EPHEMERAL
1861 #ifdef HAVE_SNI
1862 /* Sets the ephemeral key for a specific name, server and port  */
1863 /* returns 0 on success, -1 on error */
1864 int ssl_SetNamedEphemeralKey(const char* name,
1865                              const char* address, int port,
1866                              const char* keyFile, int typeKey,
1867                              const char* password, char* error)
1868 {
1869     int ret;
1870 
1871     TraceHeader();
1872     TraceSetNamedServer(name, address, port, keyFile);
1873 
1874     wc_LockMutex(&ServerListMutex);
1875     ret = SetNamedPrivateKey(name, address, port, keyFile, 0,
1876                              typeKey, password, error, 1);
1877     wc_UnLockMutex(&ServerListMutex);
1878 
1879     if (ret == 0)
1880         Trace(NEW_SERVER_STR);
1881 
1882     return ret;
1883 }
1884 
1885 int ssl_SetNamedEphemeralKeyBuffer(const char* name,
1886                                    const char* address, int port,
1887                                    const char* keyBuf, int keySz, int typeKey,
1888                                    const char* password, char* error)
1889 {
1890     int ret;
1891 
1892     TraceHeader();
1893     TraceSetNamedServer(name, address, port, NULL);
1894 
1895     wc_LockMutex(&ServerListMutex);
1896     ret = SetNamedPrivateKey(name, address, port, keyBuf, keySz,
1897                              typeKey, password, error, 1);
1898     wc_UnLockMutex(&ServerListMutex);
1899 
1900     if (ret == 0)
1901         Trace(NEW_SERVER_STR);
1902 
1903     return ret;
1904 }
1905 #endif /* HAVE_SNI */
1906 
1907 /* Sets the ephemeral key for a specific server and port  */
1908 /* returns 0 on success, -1 on error */
1909 int ssl_SetEphemeralKey(const char* address, int port,
1910                         const char* keyFile, int typeKey,
1911                         const char* password, char* error)
1912 {
1913     int ret;
1914 
1915     TraceHeader();
1916     TraceSetServer(address, port, keyFile);
1917 
1918     wc_LockMutex(&ServerListMutex);
1919     ret = SetNamedPrivateKey(NULL, address, port, keyFile, 0,
1920                              typeKey, password, error, 1);
1921     wc_UnLockMutex(&ServerListMutex);
1922 
1923     if (ret == 0)
1924         Trace(NEW_SERVER_STR);
1925 
1926     return ret;
1927 }
1928 
1929 int ssl_SetEphemeralKeyBuffer(const char* address, int port,
1930                               const char* keyBuf, int keySz, int typeKey,
1931                               const char* password, char* error)
1932 {
1933     int ret;
1934 
1935     TraceHeader();
1936     TraceSetServer(address, port, "from buffer");
1937 
1938     wc_LockMutex(&ServerListMutex);
1939     ret = SetNamedPrivateKey(NULL, address, port, keyBuf, keySz,
1940                              typeKey, password, error, 1);
1941     wc_UnLockMutex(&ServerListMutex);
1942 
1943     if (ret == 0)
1944         Trace(NEW_SERVER_STR);
1945 
1946     return ret;
1947 }
1948 #endif /* WOLFSSL_STATIC_EPHEMERAL */
1949 
1950 /* Check IP Header for IPV6, TCP, and a registered server address */
1951 /* returns 0 on success, -1 on error */
1952 static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error)
1953 {
1954     int        version = IP_V(iphdr);
1955     int        exthdrsz = IP6_HDR_SZ;
1956 
1957     TraceIP6(iphdr);
1958     Trace(IP_CHECK_STR);
1959 
1960     if (version != IPV6) {
1961         SetError(BAD_IPVER_STR, error, NULL, 0);
1962         return -1;
1963     }
1964 
1965     /* Here, we need to move onto next header if not TCP. */
1966     if (iphdr->next_header != TCP_PROTOCOL) {
1967         Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ);
1968         do {
1969             int hdrsz = (exthdr->length + 1) * 8;
1970             if (hdrsz > length - exthdrsz) {
1971                 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
1972                 return -1;
1973             }
1974             exthdrsz += hdrsz;
1975             exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz);
1976         }
1977         while (exthdr->next_header != TCP_PROTOCOL &&
1978                 exthdr->next_header != NO_NEXT_HEADER);
1979     }
1980 
1981 #ifndef WOLFSSL_SNIFFER_WATCH
1982     if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) {
1983         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1984         return -1;
1985     }
1986 #endif
1987 
1988     info->length = exthdrsz;
1989     info->total = XNTOHS(iphdr->length) + info->length;
1990     /* IPv6 doesn't include its own header size in the length like v4. */
1991     info->src.version = IPV6;
1992     XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6));
1993     info->dst.version = IPV6;
1994     XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6));
1995 
1996     return 0;
1997 }
1998 
1999 
2000 /* Check IP Header for IPV4, TCP, and a registered server address */
2001 /* If header IPv6, pass to CheckIp6Hdr(). */
2002 /* returns 0 on success, -1 on error */
2003 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
2004 {
2005     int version = IP_V(iphdr);
2006 
2007     if (version == IPV6)
2008         return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error);
2009 
2010     TraceIP(iphdr);
2011     Trace(IP_CHECK_STR);
2012 
2013     if (version != IPV4) {
2014         SetError(BAD_IPVER_STR, error, NULL, 0);
2015         return -1;
2016     }
2017 
2018     if (iphdr->protocol != TCP_PROTOCOL) {
2019         SetError(BAD_PROTO_STR, error, NULL, 0);
2020         return -1;
2021     }
2022 
2023 #ifndef WOLFSSL_SNIFFER_WATCH
2024     if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
2025         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
2026         return -1;
2027     }
2028 #endif
2029 
2030     info->length  = IP_HL(iphdr);
2031     info->total   = XNTOHS(iphdr->length);
2032     info->src.version = IPV4;
2033     info->src.ip4 = iphdr->src;
2034     info->dst.version = IPV4;
2035     info->dst.ip4 = iphdr->dst;
2036 
2037     if (info->total == 0)
2038         info->total = length;  /* reassembled may be off */
2039 
2040     return 0;
2041 }
2042 
2043 
2044 /* Check TCP Header for a registered port */
2045 /* returns 0 on success, -1 on error */
2046 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
2047 {
2048     TraceTcp(tcphdr);
2049     Trace(TCP_CHECK_STR);
2050     info->srcPort   = XNTOHS(tcphdr->srcPort);
2051     info->dstPort   = XNTOHS(tcphdr->dstPort);
2052     info->length    = TCP_LEN(tcphdr);
2053     info->sequence  = XNTOHL(tcphdr->sequence);
2054     info->fin       = tcphdr->flags & TCP_FIN;
2055     info->rst       = tcphdr->flags & TCP_RST;
2056     info->syn       = tcphdr->flags & TCP_SYN;
2057     info->ack       = tcphdr->flags & TCP_ACK;
2058     if (info->ack)
2059         info->ackNumber = XNTOHL(tcphdr->ack);
2060 
2061 #ifndef WOLFSSL_SNIFFER_WATCH
2062     if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
2063         SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
2064         return -1;
2065     }
2066 #else
2067     (void)error;
2068 #endif
2069 
2070     return 0;
2071 }
2072 
2073 
2074 /* Decode Record Layer Header */
2075 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
2076 {
2077     XMEMCPY(rh, input, RECORD_HEADER_SZ);
2078     *size = (rh->length[0] << 8) | rh->length[1];
2079 
2080     if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
2081         return LENGTH_ERROR;
2082 
2083     return 0;
2084 }
2085 
2086 
2087 /* Copies the session's information to the provided sslInfo. Skip copy if
2088  * SSLInfo is not provided. */
2089 static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo)
2090 {
2091     if (NULL != sslInfo) {
2092         XMEMSET(sslInfo, 0, sizeof(SSLInfo));
2093 
2094         /* Pass back Session Info after we have processed the Server Hello. */
2095         if (0 != session->sslServer->options.cipherSuite) {
2096             const char* pCipher;
2097 
2098             sslInfo->isValid = 1;
2099             sslInfo->protocolVersionMajor = session->sslServer->version.major;
2100             sslInfo->protocolVersionMinor = session->sslServer->version.minor;
2101             sslInfo->serverCipherSuite0 =
2102                         session->sslServer->options.cipherSuite0;
2103             sslInfo->serverCipherSuite =
2104                         session->sslServer->options.cipherSuite;
2105 
2106             pCipher = wolfSSL_get_cipher(session->sslServer);
2107             if (NULL != pCipher) {
2108                 XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher,
2109                          sizeof(sslInfo->serverCipherSuiteName));
2110                 sslInfo->serverCipherSuiteName
2111                          [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0';
2112             }
2113             sslInfo->keySize = session->keySz;
2114         #ifdef HAVE_SNI
2115             if (NULL != session->sni) {
2116                 XSTRNCPY((char*)sslInfo->serverNameIndication,
2117                          session->sni, sizeof(sslInfo->serverNameIndication));
2118                 sslInfo->serverNameIndication
2119                          [sizeof(sslInfo->serverNameIndication) - 1] = '\0';
2120             }
2121         #endif
2122             TraceSessionInfo(sslInfo);
2123         }
2124     }
2125 }
2126 
2127 
2128 /* Call the session connection start callback. */
2129 static void CallConnectionCb(SnifferSession* session)
2130 {
2131     if (ConnectionCb != NULL) {
2132         SSLInfo info;
2133         CopySessionInfo(session, &info);
2134         ConnectionCb((const void*)session, &info, ConnectionCbCtx);
2135     }
2136 }
2137 
2138 #ifdef SHOW_SECRETS
2139 static void PrintSecret(const char* desc, const byte* buf, int sz)
2140 {
2141     int i;
2142     printf("%s: ", desc);
2143     for (i = 0; i < sz; i++) {
2144         printf("%02x", buf[i]);
2145     }
2146     printf("\n");
2147 }
2148 
2149 static void ShowTlsSecrets(SnifferSession* session)
2150 {
2151     PrintSecret("server master secret", session->sslServer->arrays->masterSecret, SECRET_LEN);
2152     PrintSecret("client master secret", session->sslClient->arrays->masterSecret, SECRET_LEN);
2153     printf("server suite = %d\n", session->sslServer->options.cipherSuite);
2154     printf("client suite = %d\n", session->sslClient->options.cipherSuite);
2155 }
2156 #endif /* SHOW_SECRETS */
2157 
2158 
2159 /* Process Keys */
2160 
2161 static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
2162     char* error, KeyShareInfo* ksInfo)
2163 {
2164     word32 idx = 0;
2165     int ret;
2166     DerBuffer* keyBuf = NULL;
2167     int keyBufFree = 0;
2168 #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
2169     int useCurveId = 0;
2170 #endif
2171     int devId = INVALID_DEVID;
2172     WOLFSSL_CTX* ctx = session->context->ctx;
2173     WOLFSSL* ssl = session->sslServer;
2174 
2175 #if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
2176     if (ksInfo && ksInfo->curve_id != 0)
2177         useCurveId = ksInfo->curve_id;
2178 #endif
2179 #ifdef WOLF_CRYPTO_CB
2180     devId = CryptoDeviceId;
2181 #endif
2182 
2183     if (session->sslServer->arrays == NULL || session->sslClient->arrays == NULL) {
2184         /* secret's have already been established and released */
2185         /* this can happen with secure renegotiation */
2186         return 0;
2187     }
2188 
2189 #ifndef NO_RSA
2190     /* Static RSA */
2191     if (ksInfo == NULL && ssl->buffers.key) {
2192         RsaKey key;
2193         int length;
2194         int keyInit = 0;
2195 
2196         ret = wc_InitRsaKey_ex(&key, NULL, devId);
2197         if (ret == 0) {
2198             keyInit = 1;
2199             keyBuf = ssl->buffers.key;
2200 
2201             ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key,
2202                 keyBuf->length);
2203             if (ret != 0) {
2204             #ifndef HAVE_ECC
2205                 #ifdef WOLFSSL_SNIFFER_STATS
2206                 INC_STAT(SnifferStats.sslKeyFails);
2207                 #endif
2208                 SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
2209             #else
2210                 /* If we can do ECC, this isn't fatal. Not loading a key later
2211                  * will be fatal, though. */
2212                 SetError(RSA_DECODE_STR, error, session, 0);
2213                 keyBuf = NULL;
2214             #endif
2215             }
2216         }
2217 
2218         if (ret == 0) {
2219             length = wc_RsaEncryptSize(&key);
2220             if (IsTLS(session->sslServer)) {
2221                 input += 2;     /* tls pre length */
2222             }
2223 
2224             if (length > *sslBytes) {
2225                 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
2226                 ret = -1;
2227             }
2228         }
2229 
2230     #ifdef WC_RSA_BLINDING
2231         if (ret == 0) {
2232             ret = wc_RsaSetRNG(&key, session->sslServer->rng);
2233             if (ret != 0) {
2234                 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
2235             }
2236         }
2237     #endif
2238 
2239         if (ret == 0) {
2240             session->keySz = length * WOLFSSL_BIT_SIZE;
2241             /* length is the key size in bytes */
2242             session->sslServer->arrays->preMasterSz = SECRET_LEN;
2243 
2244             do {
2245             #ifdef WOLFSSL_ASYNC_CRYPT
2246                 ret = wc_AsyncWait(ret, &key.asyncDev,
2247                         WC_ASYNC_FLAG_CALL_AGAIN);
2248             #endif
2249                 if (ret >= 0) {
2250                     ret = wc_RsaPrivateDecrypt(input, length,
2251                         session->sslServer->arrays->preMasterSecret,
2252                         session->sslServer->arrays->preMasterSz, &key);
2253                 }
2254             } while (ret == WC_PENDING_E);
2255 
2256             if (ret != SECRET_LEN) {
2257                 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
2258             }
2259         }
2260 
2261         if (keyInit) {
2262             wc_FreeRsaKey(&key);
2263         }
2264     }
2265 #endif /* !NO_RSA */
2266 
2267 #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
2268     /* Static DH Key */
2269     if (ksInfo && ksInfo->dh_key_bits != 0 && keyBuf == NULL) {
2270         DhKey dhKey;
2271     #ifdef HAVE_PUBLIC_FFDHE
2272         const DhParams* params;
2273     #endif
2274         word32 privKeySz = 0, p_len = 0;
2275         byte privKey[52]; /* max for TLS */
2276         int keyInit = 0;
2277 
2278         /* try and load static ephemeral */
2279     #ifdef WOLFSSL_STATIC_EPHEMERAL
2280         #ifndef SINGLE_THREADED
2281         int keyLocked = 0;
2282         if (ctx->staticKELockInit &&
2283             wc_LockMutex(&ctx->staticKELock) == 0)
2284         #endif
2285         {
2286         #ifndef SINGLE_THREADED
2287             keyLocked = 1;
2288         #endif
2289             keyBuf = ssl->staticKE.dhKey;
2290             if (keyBuf == NULL)
2291                 keyBuf = ctx->staticKE.dhKey;
2292         }
2293     #endif
2294 
2295         ret = 0;
2296     #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2297         if (KeyCb != NULL) {
2298             if (keyBuf == NULL) {
2299                 ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
2300                 if (ret == 0)
2301                     keyBufFree = 1;
2302             }
2303             ret = KeyCb(session, ksInfo->named_group,
2304                 session->srvKs.key, session->srvKs.key_len,
2305                 session->cliKs.key, session->cliKs.key_len,
2306                 keyBuf, KeyCbCtx, error);
2307             if (ret != 0) {
2308                 SetError(-1, error, session, FATAL_ERROR_STATE);
2309             }
2310         }
2311     #endif
2312         if (ret == 0 && keyBuf == NULL) {
2313             ret = BUFFER_E;
2314         }
2315 
2316     #ifdef HAVE_PUBLIC_FFDHE
2317         if (ret == 0) {
2318             /* get DH params */
2319             switch (ksInfo->named_group) {
2320             #ifdef HAVE_FFDHE_2048
2321                 case WOLFSSL_FFDHE_2048:
2322                     params = wc_Dh_ffdhe2048_Get();
2323                     privKeySz = 29;
2324                     break;
2325             #endif
2326             #ifdef HAVE_FFDHE_3072
2327                 case WOLFSSL_FFDHE_3072:
2328                     params = wc_Dh_ffdhe3072_Get();
2329                     privKeySz = 34;
2330                     break;
2331             #endif
2332             #ifdef HAVE_FFDHE_4096
2333                 case WOLFSSL_FFDHE_4096:
2334                     params = wc_Dh_ffdhe4096_Get();
2335                     privKeySz = 39;
2336                     break;
2337             #endif
2338             #ifdef HAVE_FFDHE_6144
2339                 case WOLFSSL_FFDHE_6144:
2340                     params = wc_Dh_ffdhe6144_Get();
2341                     privKeySz = 46;
2342                     break;
2343             #endif
2344             #ifdef HAVE_FFDHE_8192
2345                 case WOLFSSL_FFDHE_8192:
2346                     params = wc_Dh_ffdhe8192_Get();
2347                     privKeySz = 52;
2348                     break;
2349             #endif
2350                 default:
2351                     ret = BAD_FUNC_ARG;
2352             }
2353         }
2354     #endif
2355 
2356         if (ret == 0) {
2357             ret = wc_InitDhKey_ex(&dhKey, NULL, devId);
2358             if (ret == 0)
2359                 keyInit = 1;
2360         }
2361         if (ret == 0) {
2362     #ifdef HAVE_PUBLIC_FFDHE
2363             ret = wc_DhSetKey(&dhKey,
2364                 (byte*)params->p, params->p_len,
2365                 (byte*)params->g, params->g_len);
2366             p_len = params->p_len;
2367     #else
2368             ret = wc_DhSetNamedKey(&dhKey, ksInfo->named_group);
2369             if (ret == 0) {
2370                 privKeySz = wc_DhGetNamedKeyMinSize(ksInfo->named_group);
2371                 ret = wc_DhGetNamedKeyParamSize(ksInfo->named_group,
2372                         &p_len, NULL, NULL);
2373             }
2374     #endif
2375         }
2376         if (ret == 0) {
2377             ret = wc_DhKeyDecode(keyBuf->buffer, &idx, &dhKey,
2378                 keyBuf->length);
2379         }
2380         if (ret == 0) {
2381             ret = wc_DhExportKeyPair(&dhKey, privKey, &privKeySz, NULL,
2382                 NULL);
2383         }
2384 
2385     #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
2386         if (keyLocked) {
2387             wc_UnLockMutex(&ctx->staticKELock);
2388         }
2389     #endif
2390 
2391         if (ret == 0) {
2392             /* Derive secret from private key and peer's public key */
2393             do {
2394             #ifdef WOLFSSL_ASYNC_CRYPT
2395                 ret = wc_AsyncWait(ret, &dhKey.asyncDev,
2396                         WC_ASYNC_FLAG_CALL_AGAIN);
2397             #endif
2398                 if (ret >= 0) {
2399                     PRIVATE_KEY_UNLOCK();
2400                     ret = wc_DhAgree(&dhKey,
2401                         session->sslServer->arrays->preMasterSecret,
2402                         &session->sslServer->arrays->preMasterSz,
2403                         privKey, privKeySz,
2404                         input, *sslBytes);
2405                     PRIVATE_KEY_LOCK();
2406                 }
2407             } while (ret == WC_PENDING_E);
2408         }
2409 
2410         if (keyInit)
2411             wc_FreeDhKey(&dhKey);
2412 
2413     #ifdef WOLFSSL_SNIFFER_STATS
2414         if (ret != 0)
2415             INC_STAT(SnifferStats.sslKeyFails);
2416     #endif
2417 
2418         /* left-padded with zeros up to the size of the prime */
2419         if (ret == 0 && p_len > session->sslServer->arrays->preMasterSz) {
2420             word32 diff = p_len - session->sslServer->arrays->preMasterSz;
2421             XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff,
2422                     session->sslServer->arrays->preMasterSecret,
2423                     session->sslServer->arrays->preMasterSz);
2424             XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff);
2425             session->sslServer->arrays->preMasterSz = p_len;
2426         }
2427     }
2428 #endif /* !NO_DH && WOLFSSL_DH_EXTRA */
2429 
2430 #ifdef HAVE_ECC
2431     /* Static ECC Key */
2432     if (useCurveId >= 0 && keyBuf == NULL
2433     #ifdef HAVE_CURVE25519
2434         && useCurveId != ECC_X25519
2435     #endif
2436     #ifdef HAVE_CURVE448
2437         && useCurveId != ECC_X448
2438     #endif
2439     ) {
2440         ecc_key key, pubKey;
2441         int length, keyInit = 0, pubKeyInit = 0;
2442 
2443         /* try and load static ephemeral */
2444     #ifdef WOLFSSL_STATIC_EPHEMERAL
2445         #ifndef SINGLE_THREADED
2446         int keyLocked = 0;
2447         if (ctx->staticKELockInit &&
2448             wc_LockMutex(&ctx->staticKELock) == 0)
2449         #endif
2450         {
2451         #ifndef SINGLE_THREADED
2452             keyLocked = 1;
2453         #endif
2454             keyBuf = ssl->staticKE.ecKey;
2455             if (keyBuf == NULL)
2456                 keyBuf = ctx->staticKE.ecKey;
2457         }
2458     #endif
2459 
2460         /* try static ECC */
2461         if (keyBuf == NULL) {
2462             keyBuf = session->sslServer->buffers.key;
2463         }
2464 
2465         ret = 0;
2466     #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2467         if (KeyCb != NULL && ksInfo) {
2468             if (keyBuf == NULL) {
2469                 ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
2470                 if (ret == 0)
2471                     keyBufFree = 1;
2472             }
2473             ret = KeyCb(session, ksInfo->named_group,
2474                 session->srvKs.key, session->srvKs.key_len,
2475                 session->cliKs.key, session->cliKs.key_len,
2476                 keyBuf, KeyCbCtx, error);
2477             if (ret != 0) {
2478                 SetError(-1, error, session, FATAL_ERROR_STATE);
2479             }
2480         }
2481     #endif
2482 
2483         if (ret == 0 && keyBuf == NULL) {
2484             ret = BUFFER_E;
2485         }
2486         if (ret == 0) {
2487             ret = wc_ecc_init_ex(&key, NULL, devId);
2488             if (ret == 0)
2489                 keyInit = 1;
2490         }
2491     #if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
2492         (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
2493         !defined(HAVE_SELFTEST)
2494         if (ret == 0) {
2495             ret = wc_ecc_set_rng(&key, session->sslServer->rng);
2496         }
2497     #endif
2498         if (ret == 0) {
2499             idx = 0;
2500             ret = wc_EccPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length);
2501             if (ret != 0) {
2502                 SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
2503             }
2504         }
2505 
2506     #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
2507         if (keyLocked) {
2508             wc_UnLockMutex(&ctx->staticKELock);
2509         }
2510     #endif
2511 
2512         if (ret == 0) {
2513             length = wc_ecc_size(&key) * 2 + 1;
2514             /* The length should be 2 times the key size (x and y), plus 1
2515              * for the type byte. */
2516             if (!IsAtLeastTLSv1_3(session->sslServer->version)) {
2517                 input += 1; /* Don't include the TLS length for the key. */
2518             }
2519 
2520             if (length > *sslBytes) {
2521                 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
2522                 ret = -1;
2523             }
2524 
2525             /* if curve not provided in key share data, then use private key curve */
2526             if (useCurveId == 0 && key.dp) {
2527                 useCurveId = key.dp->id;
2528             }
2529         }
2530         if (ret == 0) {
2531             ret = wc_ecc_init(&pubKey);
2532             if (ret == 0)
2533                 pubKeyInit = 1;
2534         }
2535         if (ret == 0) {
2536             ret = wc_ecc_import_x963_ex(input, length, &pubKey, useCurveId);
2537             if (ret != 0) {
2538                 SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
2539             }
2540         }
2541         if (ret == 0) {
2542             session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE;
2543             /* Length is in bytes. Subtract 1 for the ECC key type. Divide
2544              * by two as the key is in (x,y) coordinates, where x and y are
2545              * the same size, the key size. Convert from bytes to bits. */
2546             session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
2547 
2548             do {
2549             #ifdef WOLFSSL_ASYNC_CRYPT
2550                 ret = wc_AsyncWait(ret, &key.asyncDev,
2551                         WC_ASYNC_FLAG_CALL_AGAIN);
2552             #endif
2553                 if (ret >= 0) {
2554                     PRIVATE_KEY_UNLOCK();
2555                     ret = wc_ecc_shared_secret(&key, &pubKey,
2556                           session->sslServer->arrays->preMasterSecret,
2557                           &session->sslServer->arrays->preMasterSz);
2558                     PRIVATE_KEY_LOCK();
2559                 }
2560             } while (ret == WC_PENDING_E);
2561         }
2562 
2563     #ifdef WOLFSSL_SNIFFER_STATS
2564         if (ret != 0)
2565             INC_STAT(SnifferStats.sslKeyFails);
2566     #endif
2567 
2568         if (keyInit)
2569             wc_ecc_free(&key);
2570         if (pubKeyInit)
2571             wc_ecc_free(&pubKey);
2572     }
2573 #endif /* HAVE_ECC */
2574 
2575 #ifdef HAVE_CURVE25519
2576     /* Static Curve25519 Key */
2577     if (useCurveId == ECC_X25519) {
2578         curve25519_key key, pubKey;
2579         int length, keyInit = 0, pubKeyInit = 0;
2580 
2581         /* try and load static ephemeral */
2582 #ifdef WOLFSSL_STATIC_EPHEMERAL
2583     #ifndef SINGLE_THREADED
2584         int keyLocked = 0;
2585         if (ctx->staticKELockInit &&
2586             wc_LockMutex(&ctx->staticKELock) == 0)
2587     #endif
2588         {
2589         #ifndef SINGLE_THREADED
2590             keyLocked = 1;
2591         #endif
2592             keyBuf = ssl->staticKE.x25519Key;
2593             if (keyBuf == NULL)
2594                 keyBuf = ctx->staticKE.x25519Key;
2595         }
2596 #endif
2597 
2598         ret = 0;
2599 #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2600         if (KeyCb != NULL && ksInfo) {
2601             if (keyBuf == NULL) {
2602                 ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
2603                 if (ret == 0)
2604                     keyBufFree = 1;
2605             }
2606             ret = KeyCb(session, ksInfo->named_group,
2607                 session->srvKs.key, session->srvKs.key_len,
2608                 session->cliKs.key, session->cliKs.key_len,
2609                 keyBuf, KeyCbCtx, error);
2610             if (ret != 0) {
2611                 SetError(-1, error, session, FATAL_ERROR_STATE);
2612                 return ret;
2613             }
2614         }
2615 #endif
2616 
2617         if (ret == 0 && keyBuf == NULL) {
2618             ret = BUFFER_E;
2619         }
2620         if (ret == 0) {
2621             ret = wc_curve25519_init_ex(&key, NULL, devId);
2622             if (ret == 0)
2623                 keyInit = 1;
2624         }
2625         if (ret == 0) {
2626             idx = 0;
2627             ret = wc_Curve25519PrivateKeyDecode(keyBuf->buffer, &idx, &key,
2628                 keyBuf->length);
2629             if (ret != 0) {
2630                 SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
2631             }
2632         }
2633 
2634 #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
2635         if (keyLocked) {
2636             wc_UnLockMutex(&ctx->staticKELock);
2637         }
2638 #endif
2639 
2640         if (ret == 0) {
2641             length = CURVE25519_KEYSIZE;
2642             if (length > *sslBytes) {
2643                 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
2644                 ret = -1;
2645             }
2646         }
2647         if (ret == 0) {
2648             ret = wc_curve25519_init(&pubKey);
2649             if (ret == 0)
2650                 pubKeyInit = 1;
2651         }
2652         if (ret == 0) {
2653             ret = wc_curve25519_import_public_ex(input, length, &pubKey,
2654                 EC25519_LITTLE_ENDIAN);
2655             if (ret != 0) {
2656                 SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
2657             }
2658         }
2659 
2660         if (ret == 0) {
2661             /* For Curve25519 length is always 32 */
2662             session->keySz = CURVE25519_KEYSIZE;
2663             session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
2664 
2665             ret = wc_curve25519_shared_secret_ex(&key, &pubKey,
2666                 session->sslServer->arrays->preMasterSecret,
2667                 &session->sslServer->arrays->preMasterSz, EC25519_LITTLE_ENDIAN);
2668         }
2669 
2670 #ifdef WOLFSSL_SNIFFER_STATS
2671         if (ret != 0)
2672             INC_STAT(SnifferStats.sslKeyFails);
2673 #endif
2674 
2675         if (keyInit)
2676             wc_curve25519_free(&key);
2677         if (pubKeyInit)
2678             wc_curve25519_free(&pubKey);
2679     }
2680 #endif /* HAVE_CURVE25519 */
2681 
2682 #ifdef HAVE_CURVE448
2683     /* Static Curve448 Key */
2684     if (useCurveId == ECC_X448) {
2685         curve448_key key, pubKey;
2686         int length, keyInit = 0, pubKeyInit = 0;
2687 
2688         /* try and load static ephemeral */
2689 #ifdef WOLFSSL_STATIC_EPHEMERAL
2690     #ifndef SINGLE_THREADED
2691         int keyLocked = 0;
2692         if (ctx->staticKELockInit &&
2693             wc_LockMutex(&ctx->staticKELock) == 0)
2694     #endif
2695         {
2696         #ifndef SINGLE_THREADED
2697             keyLocked = 1;
2698         #endif
2699             keyBuf = ssl->staticKE.x448Key;
2700             if (keyBuf == NULL)
2701                 keyBuf = ctx->staticKE.x448Key;
2702         }
2703 #endif
2704 
2705         ret = 0;
2706 #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
2707         if (KeyCb != NULL && ksInfo) {
2708             if (keyBuf == NULL) {
2709                 ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
2710                 if (ret == 0)
2711                     keyBufFree = 1;
2712             }
2713             ret = KeyCb(session, ksInfo->named_group,
2714                 session->srvKs.key, session->srvKs.key_len,
2715                 session->cliKs.key, session->cliKs.key_len,
2716                 keyBuf, KeyCbCtx, error);
2717             if (ret != 0) {
2718                 SetError(-1, error, session, FATAL_ERROR_STATE);
2719                 return ret;
2720             }
2721         }
2722 #endif
2723 
2724         if (ret == 0 && keyBuf == NULL) {
2725             ret = BUFFER_E;
2726         }
2727         if (ret == 0) {
2728             ret = wc_curve448_init(&key);
2729             if (ret == 0)
2730                 keyInit = 1;
2731         }
2732         if (ret == 0) {
2733             idx = 0;
2734             ret = wc_Curve448PrivateKeyDecode(keyBuf->buffer, &idx, &key,
2735                 keyBuf->length);
2736             if (ret != 0) {
2737                 SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
2738             }
2739         }
2740 
2741 #if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
2742         if (keyLocked) {
2743             wc_UnLockMutex(&ctx->staticKELock);
2744         }
2745 #endif
2746 
2747         if (ret == 0) {
2748             length = CURVE448_KEY_SIZE;
2749             if (length > *sslBytes) {
2750                 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
2751                 ret = -1;
2752             }
2753         }
2754         if (ret == 0) {
2755             ret = wc_curve448_init(&pubKey);
2756             if (ret == 0)
2757                 pubKeyInit = 1;
2758         }
2759         if (ret == 0) {
2760             ret = wc_curve448_import_public_ex(input, length, &pubKey,
2761                 EC448_LITTLE_ENDIAN);
2762             if (ret != 0) {
2763                 SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
2764             }
2765         }
2766 
2767         if (ret == 0) {
2768             session->keySz = CURVE448_KEY_SIZE;
2769             session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
2770 
2771             ret = wc_curve448_shared_secret_ex(&key, &pubKey,
2772                 session->sslServer->arrays->preMasterSecret,
2773                 &session->sslServer->arrays->preMasterSz, EC448_LITTLE_ENDIAN);
2774         }
2775 
2776 #ifdef WOLFSSL_SNIFFER_STATS
2777         if (ret != 0)
2778             INC_STAT(SnifferStats.sslKeyFails);
2779 #endif
2780 
2781         if (keyInit)
2782             wc_curve448_free(&key);
2783         if (pubKeyInit)
2784             wc_curve448_free(&pubKey);
2785     }
2786 #endif /* HAVE_CURVE448 */
2787 
2788     if (keyBufFree && keyBuf != NULL) {
2789         FreeDer(&keyBuf);
2790     }
2791 
2792     /* store for client side as well */
2793     XMEMCPY(session->sslClient->arrays->preMasterSecret,
2794            session->sslServer->arrays->preMasterSecret,
2795            session->sslServer->arrays->preMasterSz);
2796     session->sslClient->arrays->preMasterSz =
2797         session->sslServer->arrays->preMasterSz;
2798 
2799 #ifdef SHOW_SECRETS
2800     PrintSecret("pre master secret",
2801                 session->sslServer->arrays->preMasterSecret,
2802                 session->sslServer->arrays->preMasterSz);
2803 #endif
2804 
2805     if (SetCipherSpecs(session->sslServer) != 0) {
2806         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2807         return -1;
2808     }
2809 
2810     if (SetCipherSpecs(session->sslClient) != 0) {
2811         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2812         return -1;
2813     }
2814 
2815 #ifdef WOLFSSL_TLS13
2816     /* TLS v1.3 derive handshake key */
2817     if (IsAtLeastTLSv1_3(session->sslServer->version)) {
2818         ret  = DeriveEarlySecret(session->sslServer);
2819         ret += DeriveEarlySecret(session->sslClient);
2820         ret += DeriveHandshakeSecret(session->sslServer);
2821         ret += DeriveHandshakeSecret(session->sslClient);
2822         ret += DeriveTls13Keys(session->sslServer, handshake_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
2823         ret += DeriveTls13Keys(session->sslClient, handshake_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
2824     #ifdef WOLFSSL_EARLY_DATA
2825         ret += SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
2826         ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
2827     #else
2828         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
2829         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
2830     #endif
2831     }
2832     else
2833 #endif
2834     {
2835         ret  = MakeMasterSecret(session->sslServer);
2836         ret += MakeMasterSecret(session->sslClient);
2837         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
2838         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
2839     }
2840     if (ret != 0) {
2841         SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
2842         return -1;
2843     }
2844 
2845 #ifdef SHOW_SECRETS
2846     #ifdef WOLFSSL_TLS13
2847     if (!IsAtLeastTLSv1_3(session->sslServer->version))
2848     #endif
2849         ShowTlsSecrets(session);
2850 #endif
2851 
2852     CallConnectionCb(session);
2853 
2854     return ret;
2855 }
2856 
2857 /* Process Client Key Exchange */
2858 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
2859                             SnifferSession* session, char* error)
2860 {
2861     int ret;
2862 
2863 #ifndef WOLFSSL_STATIC_EPHEMERAL
2864     if (session->sslServer->buffers.key == NULL ||
2865         session->sslServer->buffers.key->buffer == NULL ||
2866         session->sslServer->buffers.key->length == 0) {
2867 
2868         SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
2869         return -1;
2870     }
2871 #endif
2872 
2873     ret = SetupKeys(input, sslBytes, session, error, NULL);
2874 
2875     return ret;
2876 }
2877 
2878 #ifdef WOLFSSL_TLS13
2879 static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
2880     word16 filter_group)
2881 {
2882     int index = 0;
2883     while (index < len) {
2884         /* clear info (reset dh_key_bits and curve_id) */
2885         XMEMSET(info, 0, sizeof(KeyShareInfo));
2886 
2887         /* Named group and public key */
2888         info->named_group = (word16)((input[index] << 8) | input[index+1]);
2889         index += OPAQUE16_LEN;
2890         info->key_len = 0;
2891         info->key = NULL;
2892         /* If key was provided... (a hello_retry_request will not send a key) */
2893         if (index + 2 <= len) {
2894             info->key_len = (word16)((input[index] << 8) | input[index+1]);
2895             index += OPAQUE16_LEN;
2896             if (info->key_len == 0 || info->key_len > len - index) {
2897                 return -1;
2898             }
2899             info->key = &input[index];
2900             index += info->key_len;
2901         }
2902 
2903         switch (info->named_group) {
2904     #ifndef NO_DH
2905         #ifdef HAVE_FFDHE_2048
2906             case WOLFSSL_FFDHE_2048:
2907                 info->dh_key_bits = 2048;
2908                 break;
2909         #endif
2910         #ifdef HAVE_FFDHE_3072
2911             case WOLFSSL_FFDHE_3072:
2912                 info->dh_key_bits = 3072;
2913                 break;
2914         #endif
2915         #ifdef HAVE_FFDHE_4096
2916             case WOLFSSL_FFDHE_4096:
2917                 info->dh_key_bits = 4096;
2918                 break;
2919         #endif
2920         #ifdef HAVE_FFDHE_6144
2921             case WOLFSSL_FFDHE_6144:
2922                 info->dh_key_bits = 6144;
2923                 break;
2924         #endif
2925         #ifdef HAVE_FFDHE_8192
2926             case WOLFSSL_FFDHE_8192:
2927                 info->dh_key_bits = 8192;
2928                 break;
2929         #endif
2930     #endif /* !NO_DH */
2931     #ifdef HAVE_ECC
2932         #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
2933             #ifndef NO_ECC_SECP
2934             case WOLFSSL_ECC_SECP256R1:
2935                 info->curve_id = ECC_SECP256R1;
2936                 break;
2937             #endif /* !NO_ECC_SECP */
2938         #endif
2939         #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
2940             #ifndef NO_ECC_SECP
2941             case WOLFSSL_ECC_SECP384R1:
2942                 info->curve_id = ECC_SECP384R1;
2943                 break;
2944             #endif /* !NO_ECC_SECP */
2945         #endif
2946         #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
2947             #ifndef NO_ECC_SECP
2948             case WOLFSSL_ECC_SECP521R1:
2949                 info->curve_id = ECC_SECP521R1;
2950                 break;
2951             #endif /* !NO_ECC_SECP */
2952         #endif
2953     #endif /* HAVE_ECC */
2954         #ifdef HAVE_CURVE25519
2955             case WOLFSSL_ECC_X25519:
2956                 info->curve_id = ECC_X25519;
2957                 break;
2958         #endif
2959         #ifdef HAVE_CURVE448
2960             case WOLFSSL_ECC_X448:
2961                 info->curve_id = ECC_X448;
2962                 break;
2963         #endif
2964             default:
2965                 /* do not throw error here, keep iterating the client key share */
2966                 break;
2967         }
2968 
2969         if (filter_group == 0 || filter_group == info->named_group) {
2970             return 0;
2971         }
2972     }
2973     return NO_PEER_KEY; /* unsupported key type */
2974 }
2975 
2976 static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int len,
2977     char* error)
2978 {
2979     int ret;
2980 
2981     if (session->cliKeyShare == NULL || session->cliKeyShareSz == 0) {
2982         /* session->cliKeyShareSz could not be provided yet if the client_hello
2983             did not send a key share to force a hello_retry_request */
2984         return 0;
2985     }
2986 
2987     /* Get server_hello key share (and key) */
2988     ret = ProcessKeyShare(&session->srvKs, input, len, 0);
2989     if (ret == 0 && session->srvKs.key_len > 0) {
2990         /* Get client_hello key share */
2991         ret = ProcessKeyShare(&session->cliKs, session->cliKeyShare,
2992             session->cliKeyShareSz, session->srvKs.named_group);
2993     }
2994     if (ret != 0) {
2995         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
2996         return -1;
2997     }
2998 
2999     return ret;
3000 }
3001 #endif /* WOLFSSL_TLS13 */
3002 
3003 /* Process Session Ticket */
3004 static int ProcessSessionTicket(const byte* input, int* sslBytes,
3005                                 SnifferSession* session, char* error)
3006 {
3007     word16 len;
3008 
3009 #ifdef WOLFSSL_TLS13
3010     WOLFSSL* ssl;
3011 
3012     if (session->flags.side == WOLFSSL_SERVER_END)
3013         ssl = session->sslServer;
3014     else
3015         ssl = session->sslClient;
3016 #endif
3017 
3018     /* make sure can read through hint len */
3019     if (TICKET_HINT_LEN > *sslBytes) {
3020         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3021         return -1;
3022     }
3023     input     += TICKET_HINT_LEN; /* skip over hint len */
3024     *sslBytes -= TICKET_HINT_LEN;
3025 
3026 #ifdef WOLFSSL_TLS13
3027     /* TLS v1.3 has hint age and nonce */
3028     if (IsAtLeastTLSv1_3(ssl->version)) {
3029         /* make sure can read through hint age and nonce len */
3030         if (TICKET_HINT_AGE_LEN + 1 > *sslBytes) {
3031             SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3032             return -1;
3033         }
3034         input     += TICKET_HINT_AGE_LEN; /* skip over hint age */
3035         *sslBytes -= TICKET_HINT_AGE_LEN;
3036 
3037         /* ticket nonce */
3038         len = input[0];
3039         if (len > MAX_TICKET_NONCE_SZ) {
3040             SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3041             return -1;
3042         }
3043         input += OPAQUE8_LEN;
3044         *sslBytes -= OPAQUE8_LEN;
3045     #ifdef HAVE_SESSION_TICKET
3046         /* store nonce in server for DeriveResumptionPSK */
3047         session->sslServer->session.ticketNonce.len = len;
3048         if (len > 0)
3049             XMEMCPY(&session->sslServer->session.ticketNonce.data, input, len);
3050     #endif
3051         input += len;
3052         *sslBytes -= len;
3053     }
3054 #endif
3055 
3056     /* make sure can read through len */
3057     if (OPAQUE16_LEN > *sslBytes) {
3058         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3059         return -1;
3060     }
3061 
3062     len = (word16)((input[0] << 8) | input[1]);
3063     input     += OPAQUE16_LEN;
3064     *sslBytes -= OPAQUE16_LEN;
3065 
3066     /* make sure can read through ticket */
3067     if (len > *sslBytes) {
3068         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3069         return -1;
3070     }
3071 
3072 #ifdef WOLFSSL_TLS13
3073     /* TLS v1.3 has hint age and nonce */
3074     if (IsAtLeastTLSv1_3(ssl->version)) {
3075         /* Note: Must use server session for sessions */
3076     #ifdef HAVE_SESSION_TICKET
3077         if (SetTicket(session->sslServer, input, len) != 0) {
3078             SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3079             return -1;
3080         }
3081 
3082         /* set haveSessionId to use the wolfSession cache */
3083         session->sslServer->options.haveSessionId = 1;
3084 
3085         /* Use the wolf Session cache to retain resumption secret */
3086         if (session->flags.cached == 0) {
3087             WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
3088             if (sess == NULL) {
3089                 AddSession(session->sslServer); /* don't re add */
3090             #ifdef WOLFSSL_SNIFFER_STATS
3091                 INC_STAT(SnifferStats.sslResumptionInserts);
3092             #endif
3093             }
3094             session->flags.cached = 1;
3095         }
3096     #endif /* HAVE_SESSION_TICKET */
3097     }
3098     else
3099 #endif /* WOLFSSL_TLS13 */
3100     {
3101         /* capture last part of sessionID as macID (32 bytes) */
3102         if (len < ID_LEN) {
3103             SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
3104             return -1;
3105         }
3106         /* store session with macID as sessionID */
3107         session->sslServer->options.haveSessionId = 1;
3108         if (session->sslServer->arrays) {
3109             XMEMCPY(session->sslServer->arrays->sessionID,
3110                 input + len - ID_LEN, ID_LEN);
3111         }
3112     }
3113 
3114     return 0;
3115 }
3116 
3117 static int DoResume(SnifferSession* session, char* error)
3118 {
3119     int ret = 0;
3120     WOLFSSL_SESSION* resume;
3121 
3122 #ifdef WOLFSSL_TLS13
3123     if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3124         resume = GetSession(session->sslServer,
3125                             session->sslServer->session.masterSecret, 0);
3126         if (resume == NULL) {
3127             /* TLS v1.3 with hello_retry uses session_id even for new session,
3128                 so ignore error here */
3129             return 0;
3130         }
3131     }
3132     else
3133 #endif
3134     {
3135         resume = GetSession(session->sslServer,
3136                             session->sslServer->arrays->masterSecret, 0);
3137         if (resume == NULL) {
3138         #ifdef WOLFSSL_SNIFFER_STATS
3139             INC_STAT(SnifferStats.sslResumeMisses);
3140         #endif
3141             SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
3142             return -1;
3143         }
3144     }
3145 
3146     /* make sure client has master secret too */
3147 #ifdef WOLFSSL_TLS13
3148     if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3149         XMEMCPY(session->sslClient->session.masterSecret,
3150                 session->sslServer->session.masterSecret, SECRET_LEN);
3151     }
3152     else
3153 #endif
3154     {
3155         XMEMCPY(session->sslClient->arrays->masterSecret,
3156                 session->sslServer->arrays->masterSecret, SECRET_LEN);
3157     }
3158     session->flags.resuming = 1;
3159 
3160     Trace(SERVER_DID_RESUMPTION_STR);
3161 #ifdef WOLFSSL_SNIFFER_STATS
3162     INC_STAT(SnifferStats.sslResumedConns);
3163 #endif
3164     if (SetCipherSpecs(session->sslServer) != 0) {
3165         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3166         return -1;
3167     }
3168 
3169     if (SetCipherSpecs(session->sslClient) != 0) {
3170         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
3171         return -1;
3172     }
3173 
3174 #ifdef WOLFSSL_TLS13
3175     if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3176     #ifdef HAVE_SESSION_TICKET
3177         /* Resumption PSK is resumption master secret. */
3178         session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size;
3179         session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size;
3180         ret  = DeriveResumptionPSK(session->sslServer,
3181             session->sslServer->session.ticketNonce.data,
3182             session->sslServer->session.ticketNonce.len,
3183             session->sslServer->arrays->psk_key);
3184         /* Copy resumption PSK to client */
3185         XMEMCPY(session->sslClient->arrays->psk_key,
3186             session->sslServer->arrays->psk_key,
3187             session->sslServer->arrays->psk_keySz);
3188     #endif
3189         /* handshake key setup below and traffic keys done in SetupKeys */
3190     }
3191     else
3192 #endif
3193     {
3194         if (IsTLS(session->sslServer)) {
3195             ret =  DeriveTlsKeys(session->sslServer);
3196             ret += DeriveTlsKeys(session->sslClient);
3197         }
3198         else {
3199 #ifndef NO_OLD_TLS
3200             ret =  DeriveKeys(session->sslServer);
3201             ret += DeriveKeys(session->sslClient);
3202 #endif
3203         }
3204         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
3205         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
3206     }
3207 
3208     if (ret != 0) {
3209         SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
3210         return -1;
3211     }
3212 
3213     return ret;
3214 }
3215 
3216 /* Process Server Hello */
3217 static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
3218                               SnifferSession* session, char* error)
3219 {
3220     int             ret = 0;
3221     ProtocolVersion pv;
3222     byte            b, b0;
3223     int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
3224     int             doResume = 0;
3225     const byte*     inputHello = input;
3226     int             initialBytes = *sslBytes;
3227 
3228     (void)msgSz;
3229 
3230     /* make sure we didn't miss ClientHello */
3231     if (session->flags.clientHello == 0 || session->sslClient->arrays == NULL) {
3232         SetError(MISSED_CLIENT_HELLO_STR, error, session, 0);
3233         return 0; /* do not throw error, just ignore packet */
3234     }
3235 
3236     /* make sure can read through session len */
3237     if (toRead > *sslBytes) {
3238         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3239         return -1;
3240     }
3241 
3242     XMEMCPY(&pv, input, VERSION_SZ);
3243     input     += VERSION_SZ;
3244     *sslBytes -= VERSION_SZ;
3245 
3246     session->sslServer->version = pv;
3247     session->sslClient->version = pv;
3248     if (pv.minor >= TLSv1_MINOR) {
3249         session->sslServer->options.tls = 1;
3250         session->sslClient->options.tls = 1;
3251     }
3252 
3253     XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
3254     XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
3255     input     += RAN_LEN;
3256     *sslBytes -= RAN_LEN;
3257 
3258     b = *input++;
3259     *sslBytes -= 1;
3260 
3261     /* make sure can read through compression */
3262     if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
3263         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3264         return -1;
3265     }
3266     if (b) {
3267     #ifdef WOLFSSL_TLS13
3268         XMEMCPY(session->sslServer->session.sessionID, input, ID_LEN);
3269     #endif
3270         XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
3271         session->sslServer->options.haveSessionId = 1;
3272     }
3273     input     += b;
3274     *sslBytes -= b;
3275 
3276     /* cipher suite */
3277     b0 = *input++;  /* first byte, ECC or not */
3278     session->sslServer->options.cipherSuite0 = b0;
3279     session->sslClient->options.cipherSuite0 = b0;
3280     b = *input++;
3281     session->sslServer->options.cipherSuite = b;
3282     session->sslClient->options.cipherSuite = b;
3283     *sslBytes -= SUITE_LEN;
3284 
3285 #ifdef WOLFSSL_SNIFFER_STATS
3286     {
3287         const CipherSuiteInfo* suites = GetCipherNames();
3288         int suitesSz = GetCipherNamesSize();
3289         int match = 0;
3290 
3291         while (suitesSz) {
3292             if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) {
3293                 match = 1;
3294                 break;
3295             }
3296             suites++;
3297             suitesSz--;
3298         }
3299         if (!match)
3300             INC_STAT(SnifferStats.sslCiphersUnsupported);
3301     }
3302 #endif /* WOLFSSL_SNIFFER_STATS */
3303 
3304     /* compression */
3305     b = *input++;
3306     *sslBytes -= ENUM_LEN;
3307 
3308     if (b) {
3309         SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
3310         return -1;
3311     }
3312 
3313     /* extensions */
3314     if ((initialBytes - *sslBytes) < msgSz) {
3315         word16 len;
3316 
3317         /* skip extensions until extended master secret */
3318         /* make sure can read len */
3319         if (SUITE_LEN > *sslBytes) {
3320             SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3321             return -1;
3322         }
3323         len = (word16)((input[0] << 8) | input[1]);
3324         input     += SUITE_LEN;
3325         *sslBytes -= SUITE_LEN;
3326         /* make sure can read through all extensions */
3327         if (len > *sslBytes) {
3328             SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3329             return -1;
3330         }
3331 
3332         while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
3333             word16 extType;
3334             word16 extLen;
3335 
3336             extType    = (word16)((input[0] << 8) | input[1]);
3337             input     += EXT_TYPE_SZ;
3338             *sslBytes -= EXT_TYPE_SZ;
3339 
3340             extLen     = (word16)((input[0] << 8) | input[1]);
3341             input     += LENGTH_SZ;
3342             *sslBytes -= LENGTH_SZ;
3343 
3344             /* make sure can read through individual extension */
3345             if (extLen > *sslBytes) {
3346                 SetError(SERVER_HELLO_INPUT_STR, error, session,
3347                          FATAL_ERROR_STATE);
3348                 return -1;
3349             }
3350         #ifdef DEBUG_SNIFFER
3351             printf("\tserver_hello ext: 0x%02x (len %d)\n", extType, extLen);
3352         #endif
3353 
3354             switch (extType) {
3355         #ifdef WOLFSSL_TLS13
3356             case EXT_KEY_SHARE:
3357                 ret = ProcessServerKeyShare(session, input, extLen, error);
3358                 if (ret != 0) {
3359                     SetError(SERVER_HELLO_INPUT_STR, error, session,
3360                         FATAL_ERROR_STATE);
3361                     return -1;
3362                 }
3363                 break;
3364         #endif
3365         #ifdef HAVE_SESSION_TICKET
3366             case EXT_PRE_SHARED_KEY:
3367                 /* indicates we want to use resumption */
3368                 session->sslServer->options.resuming = 1;
3369                 session->sslClient->options.resuming = 1;
3370             #ifdef WOLFSSL_TLS13
3371                 /* default nonce to len = 1, data = 0 */
3372                 session->sslServer->session.ticketNonce.len = 1;
3373                 session->sslServer->session.ticketNonce.data[0] = 0;
3374                 session->sslClient->session.ticketNonce.len = 1;
3375                 session->sslClient->session.ticketNonce.data[0] = 0;
3376             #endif
3377                 break;
3378         #endif
3379         #ifdef HAVE_MAX_FRAGMENT
3380             case EXT_MAX_FRAGMENT_LENGTH:
3381             {
3382                 word16 max_fragment = MAX_RECORD_SIZE;
3383                 switch (input[0]) {
3384                     case WOLFSSL_MFL_2_8 : max_fragment =  256; break;
3385                     case WOLFSSL_MFL_2_9 : max_fragment =  512; break;
3386                     case WOLFSSL_MFL_2_10: max_fragment = 1024; break;
3387                     case WOLFSSL_MFL_2_11: max_fragment = 2048; break;
3388                     case WOLFSSL_MFL_2_12: max_fragment = 4096; break;
3389                     case WOLFSSL_MFL_2_13: max_fragment = 8192; break;
3390                     default: break;
3391                 }
3392                 session->sslServer->max_fragment = max_fragment;
3393                 session->sslClient->max_fragment = max_fragment;
3394                 break;
3395             }
3396         #endif
3397             case EXT_SUPPORTED_VERSIONS:
3398                 session->sslServer->version.major = input[0];
3399                 session->sslServer->version.minor = input[1];
3400                 session->sslClient->version.major = input[0];
3401                 session->sslClient->version.minor = input[1];
3402                 if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3403                     /* The server side handshake encryption is on for future packets */
3404                     session->flags.serverCipherOn = 1;
3405                 }
3406                 break;
3407             case EXT_MASTER_SECRET:
3408             #ifdef HAVE_EXTENDED_MASTER
3409                 session->flags.expectEms = 1;
3410             #endif
3411                 break;
3412             case EXT_RENEGOTIATION_INFO:
3413                 session->flags.secRenegEn = 1;
3414                 break;
3415             } /* switch (extType) */
3416 
3417             input     += extLen;
3418             *sslBytes -= extLen;
3419             len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
3420         }
3421     }
3422 
3423 #ifdef HAVE_EXTENDED_MASTER
3424     if (!session->flags.expectEms) {
3425         XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
3426         session->hash = NULL;
3427     }
3428 #endif
3429 
3430     if (session->sslServer->options.haveSessionId) {
3431         if (XMEMCMP(session->sslServer->arrays->sessionID,
3432                 session->sslClient->arrays->sessionID, ID_LEN) == 0) {
3433             doResume = 1;
3434         }
3435     }
3436     else if (session->sslClient->options.haveSessionId == 0 &&
3437              session->sslServer->options.haveSessionId == 0 &&
3438              session->ticketID) {
3439         doResume = 1;
3440     }
3441 
3442     if (session->ticketID && doResume) {
3443         /* use ticketID to retrieve from session, prefer over sessionID */
3444         XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
3445         session->sslServer->options.haveSessionId = 1;  /* may not have
3446                                                            actual sessionID */
3447     }
3448 
3449 #ifdef WOLFSSL_TLS13
3450     /* Is TLS v1.3 hello_retry_request? */
3451     if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
3452         Trace(GOT_HELLO_RETRY_REQ_STR);
3453 
3454         /* do not compute keys yet */
3455         session->flags.serverCipherOn = 0;
3456 
3457         /* make sure the mac and digest size are set */
3458         SetCipherSpecs(session->sslServer);
3459         SetCipherSpecs(session->sslClient);
3460 
3461         /* reset hashes */
3462         RestartHandshakeHash(session->sslServer);
3463         RestartHandshakeHash(session->sslClient);
3464 
3465         doResume = 0;
3466     }
3467 #endif
3468 
3469     /* hash server_hello */
3470     HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
3471         initialBytes + HANDSHAKE_HEADER_SZ);
3472     HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
3473         initialBytes + HANDSHAKE_HEADER_SZ);
3474 
3475     if (doResume) {
3476         ret = DoResume(session, error);
3477         if (ret != 0) {
3478             return ret;
3479         }
3480     }
3481     else {
3482 #ifdef WOLFSSL_SNIFFER_STATS
3483         INC_STAT(SnifferStats.sslStandardConns);
3484 #endif
3485     }
3486 
3487 #ifdef SHOW_SECRETS
3488     printf("cipher suite = 0x%02x\n", session->sslServer->options.cipherSuite);
3489     PrintSecret("server random", session->sslServer->arrays->serverRandom, RAN_LEN);
3490 #endif
3491 
3492 #ifdef WOLFSSL_TLS13
3493     /* Setup handshake keys */
3494     if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len > 0) {
3495         ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
3496             session, error, &session->cliKs);
3497         if (ret != 0) {
3498             SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3499             return ret;
3500         }
3501 
3502         if (session->flags.side == WOLFSSL_SERVER_END)
3503             session->flags.serverCipherOn = 1;
3504         else
3505             session->flags.clientCipherOn = 1;
3506     }
3507 #endif
3508 
3509     return 0;
3510 }
3511 
3512 #ifdef HAVE_SNI
3513 /* Function return value must be 0 for success */
3514 static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz)
3515 {
3516     int ret = 0;
3517     WOLFSSL* ssl = session->sslServer;
3518     NamedKey* namedKey;
3519 
3520     wc_LockMutex(&session->context->namedKeysMutex);
3521     namedKey = session->context->namedKeys;
3522     while (namedKey != NULL) {
3523         if (nameSz == namedKey->nameSz &&
3524                     XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
3525         #ifdef WOLFSSL_STATIC_EPHEMERAL
3526             if (namedKey->isEphemeralKey) {
3527                 /* auto detect key type with WC_PK_TYPE_NONE */
3528                 ret = wolfSSL_set_ephemeral_key(ssl,
3529                     WC_PK_TYPE_NONE, (const char*)namedKey->key,
3530                     namedKey->keySz, WOLFSSL_FILETYPE_ASN1);
3531             }
3532             else
3533         #endif
3534             {
3535                 ret = wolfSSL_use_PrivateKey_buffer(ssl,
3536                     namedKey->key, namedKey->keySz,
3537                     WOLFSSL_FILETYPE_ASN1);
3538                 /* translate return code */
3539                 ret = (ret == WOLFSSL_SUCCESS) ? 0 : -1;
3540             }
3541             if (ret == 0) {
3542                 session->sni = namedKey->name;
3543             }
3544             break;
3545         }
3546         namedKey = namedKey->next;
3547     }
3548     wc_UnLockMutex(&session->context->namedKeysMutex);
3549     return ret;
3550 }
3551 #endif
3552 
3553 /* Process normal Client Hello */
3554 static int ProcessClientHello(const byte* input, int* sslBytes,
3555                               SnifferSession* session, char* error)
3556 {
3557     int ret = 0;
3558     byte   bLen;
3559     word16 len;
3560     int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
3561     const byte* inputHello = input;
3562     int inputHelloSz = *sslBytes;
3563     WOLFSSL* ssl = session->sslServer;
3564     int didHash = 0;
3565 
3566     session->flags.clientHello = 1;  /* don't process again */
3567 
3568     /* make sure can read up to session len */
3569     if (toRead > *sslBytes) {
3570         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3571         return -1;
3572     }
3573 
3574     /* skip, get negotiated one from server hello */
3575     input     += VERSION_SZ;
3576     *sslBytes -= VERSION_SZ;
3577 
3578     /* for secure renegotiation server arrays can be NULL */
3579     if (session->sslServer->arrays)
3580         XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
3581     if (session->sslClient->arrays)
3582         XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
3583 
3584     input     += RAN_LEN;
3585     *sslBytes -= RAN_LEN;
3586 
3587     /* store session in case trying to resume */
3588     bLen = *input++;
3589     *sslBytes -= ENUM_LEN;
3590     if (bLen) {
3591         if (ID_LEN > *sslBytes) {
3592             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3593             return -1;
3594         }
3595         Trace(CLIENT_RESUME_TRY_STR);
3596 #ifdef WOLFSSL_TLS13
3597         XMEMCPY(session->sslClient->session.sessionID, input, ID_LEN);
3598 #endif
3599         if (session->sslClient->arrays)
3600             XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
3601         session->sslClient->options.haveSessionId = 1;
3602     }
3603 
3604 #ifdef SHOW_SECRETS
3605     if (ssl->arrays)
3606         PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN);
3607 #endif
3608 
3609     input     += bLen;
3610     *sslBytes -= bLen;
3611 
3612     /* skip cipher suites */
3613     /* make sure can read len */
3614     if (SUITE_LEN > *sslBytes) {
3615         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3616         return -1;
3617     }
3618     len = (word16)((input[0] << 8) | input[1]);
3619     input     += SUITE_LEN;
3620     *sslBytes -= SUITE_LEN;
3621     /* make sure can read suites + comp len */
3622     if (len + ENUM_LEN > *sslBytes) {
3623         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3624         return -1;
3625     }
3626     input     += len;
3627     *sslBytes -= len;
3628 
3629     /* skip compression */
3630     bLen       = *input++;
3631     *sslBytes -= ENUM_LEN;
3632     /* make sure can read len */
3633     if (bLen > *sslBytes) {
3634         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3635         return -1;
3636     }
3637     input     += bLen;
3638     *sslBytes -= bLen;
3639 
3640     if (*sslBytes == 0) {
3641         /* no extensions */
3642         return 0;
3643     }
3644 
3645     /* skip extensions until session ticket */
3646     /* make sure can read len */
3647     if (SUITE_LEN > *sslBytes) {
3648         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3649         return -1;
3650     }
3651     len = (word16)((input[0] << 8) | input[1]);
3652     input     += SUITE_LEN;
3653     *sslBytes -= SUITE_LEN;
3654     /* make sure can read through all extensions */
3655     if (len > *sslBytes) {
3656         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3657         return -1;
3658     }
3659 
3660     while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
3661         word16 extType;
3662         word16 extLen;
3663 
3664         extType    = (word16)((input[0] << 8) | input[1]);
3665         input     += EXT_TYPE_SZ;
3666         *sslBytes -= EXT_TYPE_SZ;
3667 
3668         extLen     = (word16)((input[0] << 8) | input[1]);
3669         input     += LENGTH_SZ;
3670         *sslBytes -= LENGTH_SZ;
3671 
3672         /* make sure can read through individual extension */
3673         if (extLen > *sslBytes) {
3674             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3675             return -1;
3676         }
3677 
3678     #ifdef DEBUG_SNIFFER
3679         printf("\tclient_hello ext: 0x%02x (len %d)\n", extType, extLen);
3680     #endif
3681 
3682         switch (extType) {
3683     #ifdef HAVE_SNI
3684         case EXT_SERVER_NAME:
3685         {
3686             word16 listLen = 0, offset = 0;
3687 
3688             ato16(input + offset, &listLen);
3689             offset += OPAQUE16_LEN;
3690 
3691             if (extLen < offset + listLen)
3692                 return BUFFER_ERROR;
3693 
3694             while (listLen > ENUM_LEN + OPAQUE16_LEN) {
3695                 byte   sniType = input[offset++];
3696                 word16 sniLen;
3697 
3698                 ato16(input + offset, &sniLen);
3699                 offset += OPAQUE16_LEN;
3700 
3701                 if (extLen < offset + sniLen)
3702                     return BUFFER_ERROR;
3703 
3704                 if (sniType == WOLFSSL_SNI_HOST_NAME) {
3705                     ret = LoadNamedKey(session, input + offset, sniLen);
3706                     if (ret < 0) {
3707                         /* don't treat this as fatal error */
3708                         SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, 0);
3709                         break;
3710                     }
3711                 }
3712                 offset  += sniLen;
3713                 listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
3714             }
3715             break;
3716         }
3717     #endif
3718     #ifdef WOLFSSL_TLS13
3719         case EXT_KEY_SHARE:
3720         {
3721             word16 ksLen = (word16)((input[0] << 8) | input[1]);
3722             if (ksLen + OPAQUE16_LEN > extLen) {
3723                 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3724                 return -1;
3725             }
3726             /* cache key share data till server_hello */
3727             session->cliKeyShareSz = ksLen;
3728             session->cliKeyShare = (byte*)XMALLOC(ksLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
3729             if (session->cliKeyShare == NULL) {
3730                 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3731                 break;
3732             }
3733             XMEMCPY(session->cliKeyShare, &input[2], ksLen);
3734             break;
3735         }
3736         #ifdef HAVE_SESSION_TICKET
3737         case EXT_PRE_SHARED_KEY:
3738         {
3739             word16 idsLen, idLen, bindersLen, idx = 0;
3740             word32 ticketAge;
3741             const byte *identity, *binders;
3742 
3743             idsLen = (word16)((input[idx] << 8) | input[idx+1]);
3744             if (idsLen + OPAQUE16_LEN + idx > extLen) {
3745                 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3746                 return -1;
3747             }
3748             idx += OPAQUE16_LEN;
3749 
3750             /* PSK identity */
3751             idLen = (word16)((input[idx] << 8) | input[idx+1]);
3752             if (idLen + OPAQUE16_LEN + idx > extLen) {
3753                 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3754                 return -1;
3755             }
3756             idx += OPAQUE16_LEN;
3757             identity = &input[idx];
3758             idx += idLen;
3759 
3760             /* Obfuscated Ticket Age 32-bits */
3761             ticketAge = (word32)((input[idx] << 24) | (input[idx+1] << 16) |
3762                                  (input[idx+2] << 8) | input[idx+3]);
3763             (void)ticketAge; /* not used */
3764             idx += OPAQUE32_LEN;
3765 
3766             /* binders - all binders */
3767             bindersLen = (word16)((input[idx] << 8) | input[idx+1]);
3768             if (bindersLen + OPAQUE16_LEN + idx > extLen) {
3769                 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
3770                 return -1;
3771             }
3772             idx += OPAQUE16_LEN;
3773             binders = &input[idx];
3774             bindersLen += OPAQUE16_LEN; /* includes 2 bytes for total len */
3775             (void)binders; /* not used */
3776 
3777             /* Hash data up to binders for deriving binders in PSK extension. */
3778             HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
3779                 inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
3780             HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
3781                 inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
3782 
3783             /* call to decrypt session ticket */
3784             if (DoClientTicket(ssl, identity, idLen) != WOLFSSL_TICKET_RET_OK) {
3785                 /* we aren't decrypting the resumption, since we know the master secret */
3786                 /* ignore errors */
3787             }
3788             ssl->options.resuming  = 1;
3789 
3790             /* Hash the rest of the ClientHello. */
3791             HashRaw(session->sslServer, inputHello + inputHelloSz - bindersLen, bindersLen);
3792             HashRaw(session->sslClient, inputHello + inputHelloSz - bindersLen, bindersLen);
3793             didHash = 1;
3794             break;
3795         }
3796         #endif /* HAVE_SESSION_TICKET */
3797     #endif /* WOLFSSL_TLS13 */
3798         case EXT_SUPPORTED_VERSIONS:
3799             break;
3800         case EXT_TICKET_ID:
3801             /* make sure can read through ticket if there is a non blank one */
3802             if (extLen && extLen < ID_LEN) {
3803                 SetError(CLIENT_HELLO_INPUT_STR, error, session,
3804                          FATAL_ERROR_STATE);
3805                 return -1;
3806             }
3807             if (extLen) {
3808                 if (session->ticketID == NULL) {
3809                     session->ticketID = (byte*)XMALLOC(ID_LEN,
3810                             NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID);
3811                     if (session->ticketID == 0) {
3812                         SetError(MEMORY_STR, error, session,
3813                                  FATAL_ERROR_STATE);
3814                         return -1;
3815                     }
3816                 }
3817             #ifdef HAVE_SESSION_TICKET
3818                 ssl->options.useTicket = 1;
3819             #endif
3820                 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
3821             }
3822             break;
3823         }
3824 
3825         input     += extLen;
3826         *sslBytes -= extLen;
3827         len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
3828     }
3829 
3830     if (!didHash) {
3831         HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
3832             inputHelloSz + HANDSHAKE_HEADER_SZ);
3833         HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
3834             inputHelloSz + HANDSHAKE_HEADER_SZ);
3835     }
3836 
3837     (void)ssl;
3838 
3839     return ret;
3840 }
3841 
3842 
3843 #ifdef WOLFSSL_SNIFFER_WATCH
3844 
3845 static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
3846     char* error)
3847 {
3848     int ret;
3849     Sha256 sha;
3850     byte digest[SHA256_DIGEST_SIZE];
3851 
3852     if (WatchCb == NULL) {
3853         SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE);
3854         return -1;
3855     }
3856 
3857     ret = wc_InitSha256(&sha);
3858     if (ret == 0)
3859         ret = wc_Sha256Update(&sha, data, dataSz);
3860     if (ret == 0)
3861         ret = wc_Sha256Final(&sha, digest);
3862     if (ret != 0) {
3863         SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE);
3864         return -1;
3865     }
3866 
3867     ret = WatchCb((void*)session, digest, sizeof(digest),
3868             data, dataSz, WatchCbCtx, error);
3869     if (ret != 0) {
3870 #ifdef WOLFSSL_SNIFFER_STATS
3871         INC_STAT(SnifferStats.sslKeysUnmatched);
3872 #endif
3873         SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE);
3874         ret = -1;
3875     }
3876     else {
3877 #ifdef WOLFSSL_SNIFFER_STATS
3878         INC_STAT(SnifferStats.sslKeyMatches);
3879 #endif
3880     }
3881     return ret;
3882 }
3883 
3884 /* Process Certificate */
3885 static int ProcessCertificate(const byte* input, int* sslBytes,
3886         SnifferSession* session, char* error)
3887 {
3888     word32 certChainSz;
3889     word32 certSz;
3890 
3891     /* If the receiver is the server, this is the client certificate message,
3892      * and it should be ignored at this point. */
3893     if (session->flags.side == WOLFSSL_SERVER_END)
3894         return 0;
3895 
3896     if (*sslBytes < CERT_HEADER_SZ) {
3897         SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
3898         return -1;
3899     }
3900 
3901 #ifdef WOLFSSL_TLS13
3902     if (IsAtLeastTLSv1_3(session->sslServer->version)) {
3903         /* skip 1 byte (Request context len) */
3904         input += OPAQUE8_LEN;
3905         *sslBytes -= OPAQUE8_LEN;
3906     }
3907 #endif
3908 
3909     ato24(input, &certChainSz);
3910     *sslBytes -= CERT_HEADER_SZ;
3911     input += CERT_HEADER_SZ;
3912 
3913     if (*sslBytes < (int)certChainSz) {
3914         SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
3915         return -1;
3916     }
3917 
3918     ato24(input, &certSz);
3919     input += OPAQUE24_LEN;
3920     if (*sslBytes < (int)certSz) {
3921         SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
3922         return -1;
3923     }
3924 
3925     *sslBytes -= certChainSz;
3926 
3927     return KeyWatchCall(session, input, certSz, error);
3928 }
3929 
3930 #endif /* WOLFSSL_SNIFFER_WATCH */
3931 
3932 
3933 /* Process Finished */
3934 static int ProcessFinished(const byte* input, int size, int* sslBytes,
3935                            SnifferSession* session, char* error)
3936 {
3937     WOLFSSL* ssl;
3938     word32 inOutIdx = 0;
3939     int    ret;
3940 
3941     if (session->flags.side == WOLFSSL_SERVER_END)
3942         ssl = session->sslServer;
3943     else
3944         ssl = session->sslClient;
3945 
3946 #ifdef WOLFSSL_TLS13
3947     if (IsAtLeastTLSv1_3(ssl->version)) {
3948         ret = DoTls13Finished(ssl, input, &inOutIdx, (word32)size,
3949             (word32)*sslBytes, SNIFF);
3950 
3951         ssl->options.handShakeState = HANDSHAKE_DONE;
3952         ssl->options.handShakeDone  = 1;
3953     }
3954     else
3955 #endif
3956     {
3957         ret = DoFinished(ssl, input, &inOutIdx, (word32)size,
3958             (word32)*sslBytes, SNIFF);
3959     }
3960     *sslBytes -= (int)inOutIdx;
3961 
3962     if (ret < 0) {
3963         SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
3964         return ret;
3965     }
3966 
3967     if (ret == 0 && session->flags.cached == 0) {
3968         if (session->sslServer->options.haveSessionId) {
3969         #ifndef NO_SESSION_CACHE
3970             WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
3971             if (sess == NULL) {
3972                 AddSession(session->sslServer); /* don't re add */
3973             #ifdef WOLFSSL_SNIFFER_STATS
3974                 INC_STAT(SnifferStats.sslResumptionInserts);
3975             #endif
3976             }
3977             session->flags.cached = 1;
3978         #endif
3979          }
3980     }
3981 
3982 #ifdef WOLFSSL_TLS13
3983     /* Derive TLS v1.3 traffic keys */
3984     if (IsAtLeastTLSv1_3(ssl->version)) {
3985         if (!session->flags.gotFinished) {
3986             /* When either side gets "finished" derive master secret and keys */
3987             ret  = DeriveMasterSecret(session->sslServer);
3988             ret += DeriveMasterSecret(session->sslClient);
3989         #ifdef WOLFSSL_EARLY_DATA
3990             ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
3991             ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
3992         #else
3993             ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
3994             ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
3995         #endif
3996 
3997             if (ret != 0) {
3998                 SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
3999                 return -1;
4000             }
4001 
4002             session->flags.gotFinished = 1;
4003         #ifdef SHOW_SECRETS
4004             ShowTlsSecrets(session);
4005         #endif
4006         }
4007 
4008         if (session->flags.side == WOLFSSL_SERVER_END) {
4009             /* finished from client to server */
4010             ret  = SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
4011             ret += SetKeysSide(session->sslClient, ENCRYPT_SIDE_ONLY);
4012 
4013         #ifdef HAVE_SESSION_TICKET
4014             /* derive resumption secret for next session - on finished (from client) */
4015             ret += DeriveResumptionSecret(session->sslClient,
4016                 session->sslClient->session.masterSecret);
4017 
4018             /* copy resumption secret to server */
4019             XMEMCPY(session->sslServer->session.masterSecret,
4020                     session->sslClient->session.masterSecret, SECRET_LEN);
4021             #ifdef SHOW_SECRETS
4022             PrintSecret("resumption secret",
4023                 session->sslClient->session.masterSecret, SECRET_LEN);
4024             #endif
4025         #endif
4026         }
4027         else {
4028             /* finished from server to client */
4029             ret  = SetKeysSide(session->sslServer, ENCRYPT_SIDE_ONLY);
4030             ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
4031         }
4032 
4033         if (ret != 0) {
4034             SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
4035             return -1;
4036         }
4037     }
4038 #endif
4039 
4040     /* Do not free handshake resources yet if secure renegotiation */
4041     if (session->flags.secRenegEn == 0) {
4042         /* If receiving a finished message from one side, free the resources
4043          * from the other side's tracker. */
4044         if (session->flags.side == WOLFSSL_SERVER_END)
4045             FreeHandshakeResources(session->sslClient);
4046         else
4047             FreeHandshakeResources(session->sslServer);
4048     }
4049 
4050     return ret;
4051 }
4052 
4053 
4054 /* Process HandShake input */
4055 static int DoHandShake(const byte* input, int* sslBytes,
4056                        SnifferSession* session, char* error, word16 rhSize)
4057 {
4058     byte type;
4059     int  size;
4060     int  ret = 0;
4061     WOLFSSL* ssl;
4062     int startBytes;
4063 
4064     (void)rhSize;
4065 
4066 #ifdef HAVE_MAX_FRAGMENT
4067     if (session->tlsFragBuf) {
4068         XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
4069         session->tlsFragOffset += rhSize;
4070         *sslBytes -= rhSize;
4071 
4072         if (session->tlsFragOffset < session->tlsFragSize) {
4073             return 0;
4074         }
4075 
4076         /* reassembled complete fragment */
4077         input = session->tlsFragBuf;
4078         *sslBytes = session->tlsFragSize;
4079         rhSize = session->tlsFragSize;
4080     }
4081 #endif
4082 
4083     if (*sslBytes < HANDSHAKE_HEADER_SZ) {
4084         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
4085         return -1;
4086     }
4087     type = input[0];
4088     size = (input[1] << 16) | (input[2] << 8) | input[3];
4089 
4090     input     += HANDSHAKE_HEADER_SZ;
4091     *sslBytes -= HANDSHAKE_HEADER_SZ;
4092     startBytes = *sslBytes;
4093 
4094     if (*sslBytes < size) {
4095         Trace(SPLIT_HANDSHAKE_MSG_STR);
4096         *sslBytes = 0;
4097         return ret;
4098     }
4099 
4100     if (session->flags.side == WOLFSSL_SERVER_END)
4101         ssl = session->sslServer;
4102     else
4103         ssl = session->sslClient;
4104 
4105 #ifdef HAVE_MAX_FRAGMENT
4106     if (rhSize < size) {
4107         /* partial fragment, let's reassemble */
4108         if (session->tlsFragBuf == NULL) {
4109             session->tlsFragOffset = 0;
4110             session->tlsFragSize = size + HANDSHAKE_HEADER_SZ;
4111             session->tlsFragBuf = (byte*)XMALLOC(session->tlsFragSize, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4112             if (session->tlsFragBuf == NULL) {
4113                 SetError(MEMORY_STR, error, NULL, 0);
4114                 return 0;
4115             }
4116 
4117             /* include the handshake header */
4118             input -= HANDSHAKE_HEADER_SZ;
4119             *sslBytes += HANDSHAKE_HEADER_SZ;
4120         }
4121 
4122         XMEMCPY(session->tlsFragBuf + session->tlsFragOffset, input, rhSize);
4123         session->tlsFragOffset += rhSize;
4124         *sslBytes -= rhSize;
4125         return 0;
4126     }
4127 #endif
4128 
4129 #ifdef WOLFSSL_TLS13
4130     if (type != client_hello && type != server_hello) {
4131         /* For resumption the hash is before / after client_hello PSK binder */
4132         /* hash the packet including header */
4133         /* TLS v1.3 requires the hash for the handshake and transfer key derivation */
4134         /* we hash even for non TLS v1.3, since we don't know if its actually
4135             TLS v1.3 till later at EXT_SUPPORTED_VERSIONS in server_hello */
4136         /* hello retry request restarts hash prior to server_hello hash calc */
4137         HashRaw(session->sslServer, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
4138         HashRaw(session->sslClient, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
4139     }
4140 #endif
4141 #ifdef HAVE_EXTENDED_MASTER
4142     if (session->hash) {
4143         if (HashUpdate(session->hash, input, size) != 0) {
4144             SetError(EXTENDED_MASTER_HASH_STR, error,
4145                      session, FATAL_ERROR_STATE);
4146             ret = -1;
4147             goto exit;
4148         }
4149     }
4150 #endif
4151 
4152     switch (type) {
4153         case hello_verify_request:
4154             Trace(GOT_HELLO_VERIFY_STR);
4155             break;
4156         case hello_request:
4157             Trace(GOT_HELLO_REQUEST_STR);
4158             break;
4159         case session_ticket:
4160             Trace(GOT_SESSION_TICKET_STR);
4161             ret = ProcessSessionTicket(input, sslBytes, session, error);
4162             break;
4163         case server_hello:
4164             Trace(GOT_SERVER_HELLO_STR);
4165             ret = ProcessServerHello(size, input, sslBytes, session, error);
4166             break;
4167         case certificate_request:
4168             Trace(GOT_CERT_REQ_STR);
4169             break;
4170         case server_key_exchange:
4171 #ifdef WOLFSSL_SNIFFER_STATS
4172             INC_STAT(SnifferStats.sslEphemeralMisses);
4173 #endif
4174             Trace(GOT_SERVER_KEY_EX_STR);
4175             /* can't know temp key passively */
4176             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
4177             ret = -1;
4178             break;
4179         case encrypted_extensions:
4180             Trace(GOT_ENC_EXT_STR);
4181             ssl->msgsReceived.got_encrypted_extensions = 1;
4182             break;
4183         case certificate:
4184             Trace(GOT_CERT_STR);
4185             if (session->flags.side == WOLFSSL_SERVER_END) {
4186 #ifdef WOLFSSL_SNIFFER_STATS
4187                 INC_STAT(SnifferStats.sslClientAuthConns);
4188 #endif
4189             }
4190 #ifdef WOLFSSL_SNIFFER_WATCH
4191             ret = ProcessCertificate(input, sslBytes, session, error);
4192 #endif
4193             break;
4194         case server_hello_done:
4195             Trace(GOT_SERVER_HELLO_DONE_STR);
4196             break;
4197         case finished:
4198             Trace(GOT_FINISHED_STR);
4199             ret = ProcessFinished(input, size, sslBytes, session, error);
4200             break;
4201         case client_hello:
4202             Trace(GOT_CLIENT_HELLO_STR);
4203             ret = ProcessClientHello(input, sslBytes, session, error);
4204             break;
4205         case client_key_exchange:
4206             Trace(GOT_CLIENT_KEY_EX_STR);
4207 #ifdef HAVE_EXTENDED_MASTER
4208             if (session->flags.expectEms && session->hash != NULL) {
4209                 if (HashCopy(session->sslServer->hsHashes,
4210                              session->hash) == 0 &&
4211                     HashCopy(session->sslClient->hsHashes,
4212                              session->hash) == 0) {
4213 
4214                     session->sslServer->options.haveEMS = 1;
4215                     session->sslClient->options.haveEMS = 1;
4216                 }
4217                 else {
4218                     SetError(EXTENDED_MASTER_HASH_STR, error,
4219                              session, FATAL_ERROR_STATE);
4220                     ret = -1;
4221                 }
4222                 XMEMSET(session->hash, 0, sizeof(HsHashes));
4223                 XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES);
4224                 session->hash = NULL;
4225             }
4226             else {
4227                 session->sslServer->options.haveEMS = 0;
4228                 session->sslClient->options.haveEMS = 0;
4229             }
4230 #endif
4231             if (ret == 0) {
4232                 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
4233                 if (ret != 0)
4234                     SetError(GOT_CLIENT_KEY_EX_STR, error, session, FATAL_ERROR_STATE);
4235             }
4236             break;
4237         case certificate_verify:
4238             Trace(GOT_CERT_VER_STR);
4239             break;
4240         case certificate_status:
4241             Trace(GOT_CERT_STATUS_STR);
4242             break;
4243         default:
4244             SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
4245             ret = -1;
4246             break;
4247     }
4248 
4249 #ifdef HAVE_EXTENDED_MASTER
4250 exit:
4251 #endif
4252 #ifdef HAVE_MAX_FRAGMENT
4253     if (session->tlsFragBuf) {
4254         XFREE(session->tlsFragBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
4255         session->tlsFragBuf = NULL;
4256     }
4257 #endif
4258 
4259     *sslBytes = startBytes - size;  /* actual bytes of full process */
4260 
4261     return ret;
4262 }
4263 
4264 
4265 /* Decrypt input into plain output, 0 on success */
4266 static int Decrypt(WOLFSSL* ssl, byte* output, const byte* input, word32 sz)
4267 {
4268     int ret = 0;
4269 
4270     (void)output;
4271     (void)input;
4272     (void)sz;
4273 
4274     switch (ssl->specs.bulk_cipher_algorithm) {
4275         #ifdef BUILD_ARC4
4276         case wolfssl_rc4:
4277             wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
4278             break;
4279         #endif
4280 
4281         #ifdef BUILD_DES3
4282         case wolfssl_triple_des:
4283             ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
4284             break;
4285         #endif
4286 
4287         #ifdef BUILD_AES
4288         case wolfssl_aes:
4289             ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
4290             break;
4291         #endif
4292 
4293         #ifdef HAVE_HC128
4294         case wolfssl_hc128:
4295             wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
4296             break;
4297         #endif
4298 
4299         #ifdef BUILD_RABBIT
4300         case wolfssl_rabbit:
4301             wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
4302             break;
4303         #endif
4304 
4305         #ifdef HAVE_CAMELLIA
4306         case wolfssl_camellia:
4307             wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
4308             break;
4309         #endif
4310 
4311         #ifdef HAVE_IDEA
4312         case wolfssl_idea:
4313             wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
4314             break;
4315         #endif
4316 
4317         #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM)
4318         case wolfssl_aes_gcm:
4319         case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */
4320             if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size)) {
4321                 /* scratch buffer, sniffer ignores auth tag */
4322                 wc_AesAuthEncryptFunc aes_auth_fn;
4323                 byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
4324                 byte nonce[AESGCM_NONCE_SZ];
4325                 XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
4326                 XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
4327 
4328                 /* use encrypt because we don't care about authtag */
4329             #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM)
4330                 aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm)
4331                                 ? wc_AesGcmEncrypt : wc_AesCcmEncrypt;
4332             #elif defined(BUILD_AESGCM)
4333                 aes_auth_fn = wc_AesGcmEncrypt;
4334             #else
4335                 aes_auth_fn = wc_AesCcmEncrypt;
4336             #endif
4337                 if (aes_auth_fn(ssl->decrypt.aes,
4338                             output,
4339                             input + AESGCM_EXP_IV_SZ,
4340                             sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
4341                             nonce, AESGCM_NONCE_SZ,
4342                             authTag, sizeof(authTag),
4343                             NULL, 0) < 0) {
4344                     Trace(BAD_DECRYPT);
4345                     ret = -1;
4346                 }
4347                 ForceZero(nonce, AESGCM_NONCE_SZ);
4348             }
4349             else {
4350                 Trace(BAD_DECRYPT_SIZE);
4351                 ret = -1;
4352             }
4353             break;
4354         #endif
4355 
4356         #ifdef HAVE_NULL_CIPHER
4357         case wolfssl_cipher_null:
4358             XMEMCPY(output, input, sz);
4359             break;
4360         #endif
4361 
4362         default:
4363             Trace(BAD_DECRYPT_TYPE);
4364             ret = -1;
4365             break;
4366     }
4367 
4368     return ret;
4369 }
4370 
4371 
4372 /* Decrypt input message into output, adjust output steam if needed */
4373 static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz,
4374                 byte* output, int* error, int* advance, RecordLayerHeader* rh)
4375 {
4376     int ivExtra = 0;
4377     int ret;
4378 
4379 #ifdef WOLFSSL_TLS13
4380     if (IsAtLeastTLSv1_3(ssl->version)) {
4381         ret = DecryptTls13(ssl, output, input, sz, (byte*)rh, RECORD_HEADER_SZ);
4382     }
4383     else
4384 #endif
4385     {
4386         ret = Decrypt(ssl, output, input, sz);
4387     }
4388     if (ret != 0) {
4389         *error = ret;
4390         return NULL;
4391     }
4392 
4393     ssl->keys.encryptSz = sz;
4394     if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
4395         output += ssl->specs.block_size; /* go past TLSv1.1 IV */
4396         ivExtra = ssl->specs.block_size;
4397         *advance = ssl->specs.block_size;
4398     }
4399 
4400     if (ssl->specs.cipher_type == aead) {
4401         *advance = ssl->specs.aead_mac_size;
4402         ssl->keys.padSz = ssl->specs.aead_mac_size;
4403     }
4404     else
4405         ssl->keys.padSz = ssl->specs.hash_size;
4406 
4407     if (ssl->specs.cipher_type == block) {
4408         /* last pad bytes indicates length */
4409         word32 pad = 0;
4410         if ((int)sz > ivExtra) {
4411             /* get value of last pad byte */
4412             pad = *(output + sz - ivExtra - 1) + 1;
4413         }
4414         ssl->keys.padSz += pad;
4415     }
4416 
4417 #ifdef WOLFSSL_TLS13
4418     if (IsAtLeastTLSv1_3(ssl->version)) {
4419         word16 i = (word16)(sz - ssl->keys.padSz);
4420         /* Remove padding from end of plain text. */
4421         for (--i; i > 0; i--) {
4422             if (output[i] != 0)
4423                 break;
4424         }
4425         /* Get the real content type from the end of the data. */
4426         rh->type = output[i];
4427         ssl->keys.padSz = sz - i;
4428     }
4429 #endif
4430     (void)rh;
4431 
4432     return output;
4433 }
4434 
4435 
4436 /* remove session from table, use rowHint if no info (means we have a lock) */
4437 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
4438                         TcpInfo* tcpInfo, word32 rowHint)
4439 {
4440     SnifferSession* previous = 0;
4441     SnifferSession* current;
4442     word32          row = rowHint;
4443     int             haveLock = 0;
4444 
4445     Trace(REMOVE_SESSION_STR);
4446 
4447     if (ipInfo && tcpInfo)
4448         row = SessionHash(ipInfo, tcpInfo);
4449     else
4450         haveLock = 1;
4451 
4452     if (row >= HASH_SIZE)
4453         return;
4454 
4455     if (!haveLock)
4456         wc_LockMutex(&SessionMutex);
4457 
4458     current = SessionTable[row];
4459 
4460     while (current) {
4461         if (current == session) {
4462             if (previous)
4463                 previous->next = current->next;
4464             else
4465                 SessionTable[row] = current->next;
4466             FreeSnifferSession(session);
4467             TraceRemovedSession();
4468             break;
4469         }
4470         previous = current;
4471         current  = current->next;
4472     }
4473 
4474     if (!haveLock)
4475         wc_UnLockMutex(&SessionMutex);
4476 }
4477 
4478 
4479 /* Remove stale sessions from the Session Table, have a lock */
4480 static void RemoveStaleSessions(void)
4481 {
4482     word32 i;
4483     SnifferSession* session;
4484 
4485     for (i = 0; i < HASH_SIZE; i++) {
4486         session = SessionTable[i];
4487         while (session) {
4488             SnifferSession* next = session->next;
4489             if (XTIME(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
4490                 TraceStaleSession();
4491                 RemoveSession(session, NULL, NULL, i);
4492             }
4493             session = next;
4494         }
4495     }
4496 }
4497 
4498 
4499 /* Create a new Sniffer Session */
4500 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
4501                                      char* error)
4502 {
4503     SnifferSession* session = 0;
4504     int row;
4505 
4506     Trace(NEW_SESSION_STR);
4507     /* create a new one */
4508     session = (SnifferSession*)XMALLOC(sizeof(SnifferSession),
4509             NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4510     if (session == NULL) {
4511         SetError(MEMORY_STR, error, NULL, 0);
4512         return 0;
4513     }
4514     InitSession(session);
4515 #ifdef HAVE_EXTENDED_MASTER
4516     {
4517         HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes),
4518                 NULL, DYNAMIC_TYPE_HASHES);
4519         if (newHash == NULL) {
4520             SetError(MEMORY_STR, error, NULL, 0);
4521             XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4522             return 0;
4523         }
4524         if (HashInit(newHash) != 0) {
4525             SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
4526             XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4527             return 0;
4528         }
4529         session->hash = newHash;
4530     }
4531 #endif
4532     session->server  = ipInfo->dst;
4533     session->client  = ipInfo->src;
4534     session->srvPort = (word16)tcpInfo->dstPort;
4535     session->cliPort = (word16)tcpInfo->srcPort;
4536     session->cliSeqStart = tcpInfo->sequence;
4537     session->cliExpected = 1;  /* relative */
4538     session->lastUsed= XTIME(NULL);
4539     session->keySz = 0;
4540 #ifdef HAVE_SNI
4541     session->sni = NULL;
4542 #endif
4543 
4544     session->context = GetSnifferServer(ipInfo, tcpInfo);
4545     if (session->context == NULL) {
4546         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
4547         XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4548         return 0;
4549     }
4550 
4551     session->sslServer = wolfSSL_new(session->context->ctx);
4552     if (session->sslServer == NULL) {
4553         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
4554         XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4555         return 0;
4556     }
4557     session->sslClient = wolfSSL_new(session->context->ctx);
4558     if (session->sslClient == NULL) {
4559         wolfSSL_free(session->sslServer);
4560         session->sslServer = 0;
4561 
4562         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
4563         XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION);
4564         return 0;
4565     }
4566     /* put server back into server mode */
4567     session->sslServer->options.side = WOLFSSL_SERVER_END;
4568 
4569     row = SessionHash(ipInfo, tcpInfo);
4570 
4571     /* add it to the session table */
4572     wc_LockMutex(&SessionMutex);
4573 
4574     session->next = SessionTable[row];
4575     SessionTable[row] = session;
4576 
4577     SessionCount++;
4578 
4579     if ( (SessionCount % HASH_SIZE) == 0) {
4580         TraceFindingStale();
4581         RemoveStaleSessions();
4582     }
4583 
4584     wc_UnLockMutex(&SessionMutex);
4585 
4586     /* CreateSession is called in response to a SYN packet, we know this
4587      * is headed to the server. Also we know the server is one we care
4588      * about as we've passed the GetSnifferServer() successfully. */
4589     session->flags.side = WOLFSSL_SERVER_END;
4590 
4591     return session;
4592 }
4593 
4594 
4595 #ifdef OLD_HELLO_ALLOWED
4596 
4597 /* Process Old Client Hello Input */
4598 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
4599                       int* rhSize, int* sslBytes, char* error)
4600 {
4601     const byte* input = sslFrame;
4602     byte        b0, b1;
4603     word32      idx = 0;
4604     int         ret;
4605 
4606     Trace(GOT_OLD_CLIENT_HELLO_STR);
4607     session->flags.clientHello = 1;    /* don't process again */
4608     b0 = *input++;
4609     b1 = *input++;
4610     *sslBytes -= 2;
4611     *rhSize = ((b0 & 0x7f) << 8) | b1;
4612 
4613     if (*rhSize > *sslBytes) {
4614         SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
4615         return -1;
4616     }
4617 
4618     ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
4619                                 (word16)*rhSize);
4620     if (ret < 0 && ret != MATCH_SUITE_ERROR) {
4621         SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
4622         return -1;
4623     }
4624 
4625     Trace(OLD_CLIENT_OK_STR);
4626     XMEMCPY(session->sslClient->arrays->clientRandom,
4627            session->sslServer->arrays->clientRandom, RAN_LEN);
4628 
4629     *sslBytes -= *rhSize;
4630     return 0;
4631 }
4632 
4633 #endif /* OLD_HELLO_ALLOWED */
4634 
4635 
4636 #if 0
4637 /* Calculate the TCP checksum, see RFC 1071 */
4638 /* return 0 for success, -1 on error */
4639 /* can be called from decode() with
4640    TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
4641    could also add a 64bit version if type available and using this
4642 */
4643 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
4644                 const byte* packet)
4645 {
4646     TcpPseudoHdr  pseudo;
4647     int           count = PSEUDO_HDR_SZ;
4648     const word16* data = (word16*)&pseudo;
4649     word32        sum = 0;
4650     word16        checksum;
4651 
4652     pseudo.src = ipInfo->src;
4653     pseudo.dst = ipInfo->dst;
4654     pseudo.rsv = 0;
4655     pseudo.protocol = TCP_PROTO;
4656     pseudo.length = htons(tcpInfo->length + dataLen);
4657 
4658     /* pseudo header sum */
4659     while (count >= 2) {
4660         sum   += *data++;
4661         count -= 2;
4662     }
4663 
4664     count = tcpInfo->length + dataLen;
4665     data = (word16*)packet;
4666 
4667     /* main sum */
4668     while (count > 1) {
4669         sum   += *data++;
4670         count -=2;
4671     }
4672 
4673     /* get left-over, if any */
4674     packet = (byte*)data;
4675     if (count > 0) {
4676         sum += *packet;
4677     }
4678 
4679     /* fold 32bit sum into 16 bits */
4680     while (sum >> 16)
4681         sum = (sum & 0xffff) + (sum >> 16);
4682 
4683     checksum = (word16)~sum;
4684     /* checksum should now equal 0, since included already calcd checksum */
4685     /* field, but tcp checksum offloading could negate calculation */
4686     if (checksum == 0)
4687         return 0;
4688     return -1;
4689 }
4690 #endif
4691 
4692 
4693 /* Check IP and TCP headers, set payload */
4694 /* returns 0 on success, -1 on error */
4695 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
4696                   int length, const byte** sslFrame, int* sslBytes, char* error)
4697 {
4698     IpHdr* iphdr = (IpHdr*)packet;
4699     int version;
4700 
4701     TraceHeader();
4702     TracePacket();
4703 
4704     /* ip header */
4705     if (length < IP_HDR_SZ) {
4706         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
4707         return -1;
4708     }
4709 
4710     version = IP_V(iphdr);
4711     if (version != IPV6 && version != IPV4) {
4712         /* Is this VLAN IEEE 802.1Q Frame? TPID = 0x8100 */
4713         if (packet[2] == 0x81 && packet[3] == 0x00) {
4714             /* trim VLAN header and try again */
4715             packet += 8;
4716             length -= 8;
4717         }
4718     }
4719 
4720     if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
4721         return -1;
4722 
4723     /* tcp header */
4724     if (length < (ipInfo->length + TCP_HDR_SZ)) {
4725         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
4726         return -1;
4727     }
4728     if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
4729         return -1;
4730 
4731     /* setup */
4732     *sslFrame = packet + ipInfo->length + tcpInfo->length;
4733     if (*sslFrame > packet + length) {
4734         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
4735         return -1;
4736     }
4737 
4738     /* We only care about the data in the TCP/IP record. There may be extra
4739      * data after the IP record for the FCS for Ethernet. */
4740     *sslBytes = (int)(packet + ipInfo->total - *sslFrame);
4741 
4742     return 0;
4743 }
4744 
4745 
4746 /* Create or Find existing session */
4747 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
4748 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
4749                         SnifferSession** session, char* error)
4750 {
4751     /* create a new SnifferSession on client SYN */
4752     if (tcpInfo->syn && !tcpInfo->ack) {
4753         TraceClientSyn(tcpInfo->sequence);
4754 #ifdef WOLFSSL_SNIFFER_STATS
4755         INC_STAT(SnifferStats.sslEncryptedConns);
4756 #endif
4757         *session = CreateSession(ipInfo, tcpInfo, error);
4758         if (*session == NULL) {
4759             *session = GetSnifferSession(ipInfo, tcpInfo);
4760             /* already had existing, so OK */
4761             if (*session)
4762                 return 1;
4763 
4764             SetError(MEMORY_STR, error, NULL, 0);
4765             return -1;
4766         }
4767         return 1;
4768     }
4769     /* get existing sniffer session */
4770     else {
4771         *session = GetSnifferSession(ipInfo, tcpInfo);
4772         if (*session == NULL) {
4773             /* don't worry about extraneous RST or duplicate FINs */
4774             if (tcpInfo->fin || tcpInfo->rst)
4775                 return 1;
4776             /* don't worry about duplicate ACKs either */
4777             if (sslBytes == 0 && tcpInfo->ack)
4778                 return 1;
4779 
4780 #ifdef WOLFSSL_SNIFFER_STATS
4781             LOCK_STAT();
4782             NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
4783             NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
4784             UNLOCK_STAT();
4785 #endif
4786 
4787             SetError(BAD_SESSION_STR, error, NULL, 0);
4788             return -1;
4789         }
4790     }
4791     return 0;
4792 }
4793 
4794 
4795 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
4796 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
4797                                   int* bytesLeft)
4798 {
4799     PacketBuffer* pb;
4800     int added = (int)(end - *begin + 1);
4801 
4802     if (added <= 0) {
4803         return NULL;
4804     }
4805 
4806     pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer),
4807             NULL, DYNAMIC_TYPE_SNIFFER_PB);
4808     if (pb == NULL) return NULL;
4809 
4810     pb->next  = 0;
4811     pb->begin = *begin;
4812     pb->end   = end;
4813     pb->data  = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER);
4814 
4815     if (pb->data == NULL) {
4816         XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB);
4817         return NULL;
4818     }
4819     XMEMCPY(pb->data, data, added);
4820 
4821     *bytesLeft -= added;
4822     *begin      = pb->end + 1;
4823 
4824     return pb;
4825 }
4826 
4827 
4828 /* Add sslFrame to Reassembly List */
4829 /* returns 1 (end) on success, -1, on error */
4830 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
4831                            int sslBytes, SnifferSession* session, char* error)
4832 {
4833     PacketBuffer*  add;
4834     PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
4835                        &session->cliReassemblyList: &session->srvReassemblyList;
4836     PacketBuffer*  curr = *front;
4837     PacketBuffer*  prev = curr;
4838 
4839     word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
4840                   &session->cliReassemblyMemory : &session->srvReassemblyMemory;
4841     word32  startSeq = seq;
4842     int     added;
4843     int     bytesLeft = sslBytes;  /* could be overlapping fragment */
4844 
4845     /* if list is empty add full frame to front */
4846     if (!curr) {
4847         if (MaxRecoveryMemory != -1 &&
4848                       (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
4849             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
4850             return -1;
4851         }
4852         add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
4853         if (add == NULL) {
4854             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
4855             return -1;
4856         }
4857         *front = add;
4858         *reassemblyMemory += sslBytes;
4859         return 1;
4860     }
4861 
4862     /* add to front if before current front, up to next->begin */
4863     if (seq < curr->begin) {
4864         word32 end = seq + sslBytes - 1;
4865 
4866         if (end >= curr->begin)
4867             end = curr->begin - 1;
4868 
4869         if (MaxRecoveryMemory -1 &&
4870                       (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
4871             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
4872             return -1;
4873         }
4874         add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
4875         if (add == NULL) {
4876             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
4877             return -1;
4878         }
4879         add->next = curr;
4880         *front = add;
4881         *reassemblyMemory += sslBytes;
4882     }
4883 
4884     /* while we have bytes left, try to find a gap to fill */
4885     while (bytesLeft > 0) {
4886         /* get previous packet in list */
4887         while (curr && (seq >= curr->begin)) {
4888             prev = curr;
4889             curr = curr->next;
4890         }
4891 
4892         /* don't add  duplicate data */
4893         if (prev->end >= seq) {
4894             if ( (seq + bytesLeft - 1) <= prev->end)
4895                 return 1;
4896             seq = prev->end + 1;
4897             bytesLeft = startSeq + sslBytes - seq;
4898         }
4899 
4900         if (!curr)
4901             /* we're at the end */
4902             added = bytesLeft;
4903         else
4904             /* we're in between two frames */
4905             added = min(bytesLeft, (int)(curr->begin - seq));
4906 
4907         /* data already there */
4908         if (added <= 0)
4909             continue;
4910 
4911         if (MaxRecoveryMemory != -1 &&
4912                          (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
4913             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
4914             return -1;
4915         }
4916         add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
4917                            &bytesLeft);
4918         if (add == NULL) {
4919             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
4920             return -1;
4921         }
4922         add->next  = prev->next;
4923         prev->next = add;
4924         *reassemblyMemory += added;
4925     }
4926     return 1;
4927 }
4928 
4929 
4930 /* Add out of order FIN capture */
4931 /* returns 1 for success (end) */
4932 static int AddFinCapture(SnifferSession* session, word32 sequence)
4933 {
4934     if (session->flags.side == WOLFSSL_SERVER_END) {
4935         if (session->finCapture.cliCounted == 0)
4936             session->finCapture.cliFinSeq = sequence;
4937     }
4938     else {
4939         if (session->finCapture.srvCounted == 0)
4940             session->finCapture.srvFinSeq = sequence;
4941     }
4942     return 1;
4943 }
4944 
4945 static int FindPrevAck(SnifferSession* session, word32 realAck)
4946 {
4947     int i;
4948     word32* acks = (session->flags.side == WOLFSSL_SERVER_END) ?
4949         session->cliAcks : session->srvAcks;
4950     /* if previous ack found return 1, otherwise 0 */
4951     for (i=0; i<WC_SNIFFER_HS_ACK_HIST_MAX; i++) {
4952         if (acks[i] == realAck) {
4953             return 1;
4954         }
4955 
4956     }
4957     return 0;
4958 }
4959 static void AddAck(SnifferSession* session, word32 realAck)
4960 {
4961     int i;
4962     word32* acks = (session->flags.side == WOLFSSL_SERVER_END) ?
4963         session->cliAcks : session->srvAcks;
4964     /* find first empty ack slot */
4965     for (i=0; i<WC_SNIFFER_HS_ACK_HIST_MAX; i++) {
4966         if (acks[i] == 0) {
4967             break;
4968         }
4969     }
4970     /* if out of slots, find oldest */
4971     if (i == WC_SNIFFER_HS_ACK_HIST_MAX) {
4972         int idx = 0;
4973         word32 lastAck = realAck;
4974         for (i=0; i<WC_SNIFFER_HS_ACK_HIST_MAX; i++) {
4975             if (acks[i] < lastAck) {
4976                 idx = i;
4977                 lastAck = acks[i];
4978             }
4979         }
4980         i  = idx;
4981     }
4982 
4983     acks[i] = realAck;
4984 }
4985 
4986 /* Adjust incoming sequence based on side */
4987 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
4988 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
4989                           int* sslBytes, const byte** sslFrame, char* error)
4990 {
4991     int ret = 0;
4992     word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
4993                                      session->cliSeqStart :session->srvSeqStart;
4994     word32  real     = tcpInfo->sequence - seqStart;
4995     word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
4996                                   &session->cliExpected : &session->srvExpected;
4997     PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
4998                         session->cliReassemblyList : session->srvReassemblyList;
4999     byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
5000                                 session->flags.srvSkipPartial :
5001                                 session->flags.cliSkipPartial;
5002 
5003     /* handle rollover of sequence */
5004     if (tcpInfo->sequence < seqStart)
5005         real = 0xffffffffU - seqStart + tcpInfo->sequence + 1;
5006 
5007     TraceRelativeSequence(*expected, real);
5008 
5009     if (real < *expected) {
5010 
5011         if (real + *sslBytes > *expected) {
5012             Trace(OVERLAP_DUPLICATE_STR);
5013 
5014             /* The following conditional block is duplicated below. It is the
5015              * same action but for a different setup case. If changing this
5016              * block be sure to also update the block below. */
5017             if (reassemblyList) {
5018                 int overlap = *expected - real;
5019                 word32 newEnd;
5020 
5021                 /* adjust to expected, remove duplicate */
5022                 *sslFrame += overlap;
5023                 *sslBytes = (*sslBytes > overlap) ? *sslBytes - overlap : 0;
5024 
5025                 newEnd = *expected + *sslBytes;
5026                 if (newEnd > reassemblyList->begin) {
5027                     int covered_data_len;
5028 
5029                     Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
5030 
5031                     /* remove bytes already on reassembly list */
5032                     covered_data_len = newEnd - reassemblyList->begin;
5033                     *sslFrame += covered_data_len;
5034                     *sslBytes = (*sslBytes > covered_data_len) ?
5035                                  *sslBytes - covered_data_len : 0;
5036                 }
5037                 if ((*sslBytes  > 0) && (newEnd > reassemblyList->end)) {
5038                     Trace(OVERLAP_REASSEMBLY_END_STR);
5039 
5040                     /* may be past reassembly list end (could have more on list)
5041                        so try to add what's past the front->end */
5042                     AddToReassembly(session->flags.side, reassemblyList->end + 1,
5043                              *sslFrame + (reassemblyList->end - *expected + 1),
5044                                  newEnd - reassemblyList->end, session, error);
5045                 }
5046             }
5047             else {
5048                 /* DUP overlap, allow */
5049                 if (*sslBytes > 0) {
5050                     skipPartial = 0; /* do not reset sslBytes */
5051                 }
5052             }
5053             ret = 0;
5054         }
5055         else {
5056             /* This can happen with unseen acks, out of order packets, or
5057              * possible spurious retransmission. */
5058             if (*sslBytes > 0) {
5059                 /* If packet has data attempt to process packet, if hasn't
5060                  * already been ack'd during handshake */
5061                 if (FindPrevAck(session, real)) {
5062                     Trace(DUPLICATE_STR);
5063                     ret = 1;
5064                 }
5065                 else {
5066                     /* DUP: allow */
5067                     skipPartial = 0; /* do not reset sslBytes */
5068                     ret = 0;
5069                 }
5070             }
5071             else {
5072                 /* DUP empty, ignore */
5073                 ret = 1;
5074             }
5075         }
5076     }
5077     else if (real > *expected) {
5078         Trace(OUT_OF_ORDER_STR);
5079         if (*sslBytes > 0) {
5080             int addResult = AddToReassembly(session->flags.side, real,
5081                                           *sslFrame, *sslBytes, session, error);
5082             ret = (skipPartial) ? 0 : addResult;
5083         }
5084         else if (tcpInfo->fin) {
5085             ret = AddFinCapture(session, real);
5086         }
5087     }
5088     else if (*sslBytes > 0) {
5089         if (skipPartial) {
5090             AddToReassembly(session->flags.side, real,
5091                                           *sslFrame, *sslBytes, session, error);
5092             ret = 0;
5093         }
5094         /* The following conditional block is duplicated above. It is the
5095          * same action but for a different setup case. If changing this
5096          * block be sure to also update the block above. */
5097         else if (reassemblyList) {
5098             word32 newEnd = *expected + *sslBytes;
5099 
5100             if (newEnd > reassemblyList->begin) {
5101                 int covered_data_len;
5102 
5103                 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
5104 
5105                 /* remove bytes already on reassembly list */
5106                 covered_data_len = newEnd - reassemblyList->begin;
5107                 *sslFrame += covered_data_len;
5108                 *sslBytes = (*sslBytes > covered_data_len) ?
5109                              *sslBytes - covered_data_len : 0;
5110             }
5111             if ((*sslBytes > 0) && (newEnd > reassemblyList->end)) {
5112                 Trace(OVERLAP_REASSEMBLY_END_STR);
5113 
5114                 /* may be past reassembly list end (could have more on list)
5115                    so try to add what's past the front->end */
5116                 AddToReassembly(session->flags.side, reassemblyList->end + 1,
5117                          *sslFrame + (reassemblyList->end - *expected + 1),
5118                              newEnd - reassemblyList->end, session, error);
5119             }
5120         }
5121     }
5122     else {
5123         /* no data present */
5124     }
5125 
5126     if (ret == 0) {
5127         /* got expected sequence */
5128         *expected += *sslBytes;
5129         if (tcpInfo->fin)
5130             *expected += 1;
5131     }
5132     if (*sslBytes > 0) {
5133         AddAck(session, real);
5134     }
5135     if (*sslBytes > 0 && skipPartial) {
5136         *sslBytes = 0;
5137     }
5138 
5139     return ret;
5140 }
5141 
5142 
5143 static int FindNextRecordInAssembly(SnifferSession* session,
5144                                     const byte** sslFrame, int* sslBytes,
5145                                     const byte** end, char* error)
5146 {
5147     PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
5148                                     &session->cliReassemblyList :
5149                                     &session->srvReassemblyList;
5150     PacketBuffer*       curr = *front;
5151     PacketBuffer*       prev = NULL;
5152     byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
5153                                     &session->flags.srvSkipPartial :
5154                                     &session->flags.cliSkipPartial;
5155     int* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
5156                                     (int*)&session->cliReassemblyMemory :
5157                                     (int*)&session->srvReassemblyMemory;
5158     WOLFSSL*             ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
5159                                     session->sslServer :
5160                                     session->sslClient;
5161     ProtocolVersion       pv = ssl->version;
5162     word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5163                                     &session->cliExpected :
5164                                     &session->srvExpected;
5165 
5166     while (curr != NULL) {
5167         *expected = curr->end + 1;
5168 
5169         if (curr->data[0] == application_data &&
5170             curr->data[1] == pv.major &&
5171             curr->data[2] == pv.minor) {
5172 
5173             if (ssl->buffers.inputBuffer.length > 0)
5174                 Trace(DROPPING_PARTIAL_RECORD);
5175 
5176             *sslBytes = (int)(curr->end - curr->begin + 1);
5177             if ( *sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
5178                 if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
5179                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5180                     return -1;
5181                 }
5182             }
5183 
5184             XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
5185 
5186             *front = curr->next;
5187             *reassemblyMemory -= *sslBytes;
5188             FreePacketBuffer(curr);
5189 
5190             ssl->buffers.inputBuffer.length = *sslBytes;
5191             *sslFrame = ssl->buffers.inputBuffer.buffer;
5192             *end = *sslFrame + *sslBytes;
5193             *skipPartial = 0;
5194 
5195             return 0;
5196         }
5197         else if (ssl->specs.cipher_type == block) {
5198             int ivPos = (int)(curr->end - curr->begin -
5199                                                      ssl->specs.block_size + 1);
5200             if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
5201 #ifdef BUILD_AES
5202                 if (ivPos >= 0)
5203                     wc_AesSetIV(ssl->decrypt.aes, curr->data + ivPos);
5204 #endif
5205             }
5206             else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
5207 #ifdef BUILD_DES3
5208                 if (ivPos >= 0)
5209                     wc_Des3_SetIV(ssl->decrypt.des3, curr->data + ivPos);
5210 #endif
5211             }
5212         }
5213 
5214         Trace(DROPPING_LOST_FRAG_STR);
5215 #ifdef WOLFSSL_SNIFFER_STATS
5216         INC_STAT(SnifferStats.sslDecodeFails);
5217 #endif
5218         prev = curr;
5219         curr = curr->next;
5220         *reassemblyMemory -= (int)(prev->end - prev->begin + 1);
5221         FreePacketBuffer(prev);
5222     }
5223 
5224     *front = curr;
5225 
5226     return 0;
5227 }
5228 
5229 
5230 static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
5231 {
5232     word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5233                                 &session->srvExpected : &session->cliExpected;
5234     word32    seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
5235                                 session->srvSeqStart : session->cliSeqStart;
5236     PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
5237                                 session->srvReassemblyList :
5238                                 session->cliReassemblyList;
5239     byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
5240                                 &session->flags.srvSkipPartial :
5241                                 &session->flags.cliSkipPartial;
5242 
5243     *skipPartial = 1;
5244 
5245     if (list != NULL)
5246         *expected = list->begin;
5247     else
5248         *expected = tcpInfo->ackNumber - seqStart;
5249 
5250     return 1;
5251 }
5252 
5253 
5254 /* Check latest ack number for missing packets
5255    return 0 ok, <0 on error */
5256 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
5257 {
5258     if (tcpInfo->ack) {
5259         word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
5260                                      session->srvSeqStart :session->cliSeqStart;
5261         word32  real     = tcpInfo->ackNumber - seqStart;
5262         word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5263                                   session->srvExpected : session->cliExpected;
5264 
5265         /* handle rollover of sequence */
5266         if (tcpInfo->ackNumber < seqStart)
5267             real = 0xffffffffU - seqStart + tcpInfo->ackNumber + 1;
5268 
5269         TraceAck(real, expected);
5270 
5271         if (real > expected)
5272             return -1;  /* we missed a packet, ACKing data we never saw */
5273     }
5274     return 0;
5275 }
5276 
5277 
5278 /* Check TCP Sequence status */
5279 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
5280 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
5281                          SnifferSession* session, int* sslBytes,
5282                          const byte** sslFrame, char* error)
5283 {
5284     int actualLen;
5285     byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
5286                         &session->flags.cliAckFault :
5287                         &session->flags.srvAckFault;
5288 
5289     /* init SEQ from server to client - if not ack fault */
5290     if (tcpInfo->syn && tcpInfo->ack && !*ackFault) {
5291         session->srvSeqStart = tcpInfo->sequence;
5292         session->srvExpected = 1;
5293         TraceServerSyn(tcpInfo->sequence);
5294         return 1;
5295     }
5296 
5297     /* adjust potential ethernet trailer */
5298     actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
5299     if (*sslBytes > actualLen) {
5300         *sslBytes = actualLen;
5301     }
5302 
5303     TraceSequence(tcpInfo->sequence, *sslBytes);
5304     if (CheckAck(tcpInfo, session) < 0) {
5305         if (!RecoveryEnabled) {
5306             UpdateMissedDataSessions();
5307             SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
5308             return -1;
5309         }
5310         else {
5311             SetError(ACK_MISSED_STR, error, session, 0);
5312             if (*ackFault == 0) {
5313                 *ackFault = 1;
5314                 UpdateMissedDataSessions();
5315             }
5316             return FixSequence(tcpInfo, session);
5317         }
5318     }
5319 
5320     if (*ackFault) {
5321         Trace(CLEAR_ACK_FAULT);
5322         *ackFault = 0;
5323     }
5324 
5325     return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
5326 }
5327 
5328 
5329 /* Check Status before record processing */
5330 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
5331 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
5332                           const byte** sslFrame, SnifferSession** session,
5333                           int* sslBytes, const byte** end,
5334                           void* vChain, word32 chainSz, char* error)
5335 {
5336     word32 length;
5337     WOLFSSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
5338                                   (*session)->sslServer : (*session)->sslClient;
5339     byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
5340                         (*session)->flags.srvSkipPartial :
5341                         (*session)->flags.cliSkipPartial;
5342     /* remove SnifferSession on 2nd FIN or RST */
5343     if (tcpInfo->fin || tcpInfo->rst) {
5344         /* flag FIN and RST */
5345         if (tcpInfo->fin)
5346             (*session)->flags.finCount += 1;
5347         else if (tcpInfo->rst)
5348             (*session)->flags.finCount += 2;
5349 
5350         if ((*session)->flags.finCount >= 2) {
5351             RemoveSession(*session, ipInfo, tcpInfo, 0);
5352             *session = NULL;
5353             return 1;
5354         }
5355     }
5356 
5357     if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
5358         SetError(FATAL_ERROR_STR, error, NULL, 0);
5359         return -1;
5360     }
5361 
5362     if (skipPartial) {
5363         if (FindNextRecordInAssembly(*session,
5364                                      sslFrame, sslBytes, end, error) < 0) {
5365             return -1;
5366         }
5367     }
5368 
5369     if (*sslBytes <= 0) {
5370         Trace(NO_DATA_STR);
5371         return 1;
5372     }
5373 
5374     /* if current partial data, add to end of partial */
5375     /* if skipping, the data is already at the end of partial */
5376     length = ssl->buffers.inputBuffer.length;
5377     if ( !skipPartial && length ) {
5378         Trace(PARTIAL_ADD_STR);
5379 
5380         if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
5381             if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
5382                 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
5383                 return -1;
5384             }
5385         }
5386         if (vChain == NULL) {
5387             XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
5388                     *sslFrame, *sslBytes);
5389             *sslBytes += length;
5390             ssl->buffers.inputBuffer.length = *sslBytes;
5391             *sslFrame = ssl->buffers.inputBuffer.buffer;
5392             *end = *sslFrame + *sslBytes;
5393         }
5394 
5395         if (vChain != NULL) {
5396     #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
5397             struct iovec* chain = (struct iovec*)vChain;
5398             word32 i, offset, headerSz, qty, remainder;
5399 
5400             Trace(CHAIN_INPUT_STR);
5401             headerSz = (word32)((const byte*)*sslFrame - (const byte*)chain[0].iov_base);
5402             remainder = *sslBytes;
5403 
5404             if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
5405                 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
5406                     SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
5407                     return -1;
5408                 }
5409             }
5410 
5411             qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz);
5412             XMEMCPY(&ssl->buffers.inputBuffer.buffer[length],
5413                 (byte*)chain[0].iov_base + headerSz, qty);
5414             offset = length;
5415             for (i = 1; i < chainSz; i++) {
5416                 offset += qty;
5417                 remainder -= qty;
5418 
5419                 if (chain[i].iov_len > remainder)
5420                     qty = remainder;
5421                 else
5422                     qty = (word32)chain[i].iov_len;
5423                 XMEMCPY(ssl->buffers.inputBuffer.buffer + offset,
5424                         chain[i].iov_base, qty);
5425             }
5426 
5427             *sslBytes += length;
5428             ssl->buffers.inputBuffer.length = *sslBytes;
5429             *sslFrame = ssl->buffers.inputBuffer.buffer;
5430             *end = *sslFrame + *sslBytes;
5431     #endif
5432             (void)chainSz;
5433         }
5434     }
5435 
5436     if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
5437         /* Sanity check the packet for an old style client hello. */
5438         int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
5439 
5440         if ((rhSize <= (*sslBytes - 2)) &&
5441             (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
5442 #ifdef OLD_HELLO_ALLOWED
5443         int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
5444         if (ret < 0)
5445             return -1;  /* error already set */
5446         if (*sslBytes <= 0)
5447             return 1;
5448 #endif
5449         }
5450         else {
5451 #ifdef STARTTLS_ALLOWED
5452             if (ssl->buffers.inputBuffer.dynamicFlag) {
5453                 ssl->buffers.inputBuffer.length = 0;
5454                 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
5455             }
5456             return 1;
5457 #endif
5458         }
5459     }
5460 
5461     return 0;
5462 }
5463 
5464 
5465 /* See if input on the reassembly list is ready for consuming */
5466 /* returns 1 for TRUE, 0 for FALSE */
5467 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
5468                          int* sslBytes, const byte** end, char* error)
5469 {
5470     /* sequence and reassembly based on from, not to */
5471     int            moreInput = 0;
5472     PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
5473                       &session->cliReassemblyList : &session->srvReassemblyList;
5474     word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
5475                                   &session->cliExpected : &session->srvExpected;
5476     /* buffer is on receiving end */
5477     word32*          length = (session->flags.side == WOLFSSL_SERVER_END) ?
5478                                &session->sslServer->buffers.inputBuffer.length :
5479                                &session->sslClient->buffers.inputBuffer.length;
5480     byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
5481                                &session->sslServer->buffers.inputBuffer.buffer :
5482                                &session->sslClient->buffers.inputBuffer.buffer;
5483     word32*      bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
5484                            &session->sslServer->buffers.inputBuffer.bufferSize :
5485                            &session->sslClient->buffers.inputBuffer.bufferSize;
5486     WOLFSSL*           ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
5487                             session->sslServer : session->sslClient;
5488     word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
5489                   &session->cliReassemblyMemory : &session->srvReassemblyMemory;
5490 
5491     while (*front && ((*front)->begin == *expected) ) {
5492         int room = (int)(*bufferSize - *length);
5493         int packetLen = (int)((*front)->end - (*front)->begin + 1);
5494 
5495         if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
5496             if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
5497                 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5498                 return 0;
5499             }
5500             room = *bufferSize - *length;   /* bufferSize is now bigger */
5501         }
5502 
5503         if (packetLen <= room) {
5504             PacketBuffer* del = *front;
5505             byte*         buf = *myBuffer;
5506 
5507             XMEMCPY(&buf[*length], (*front)->data, packetLen);
5508             *length   += packetLen;
5509             *expected += packetLen;
5510 
5511             /* remove used packet */
5512             *front = (*front)->next;
5513 
5514             *reassemblyMemory -= packetLen;
5515             FreePacketBuffer(del);
5516 
5517             moreInput = 1;
5518         }
5519         else
5520             break;
5521     }
5522     if (moreInput) {
5523         *sslFrame = *myBuffer;
5524         *sslBytes = *length;
5525         *end      = *myBuffer + *length;
5526     }
5527     return moreInput;
5528 }
5529 
5530 
5531 
5532 /* Process Message(s) from sslFrame */
5533 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
5534 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
5535                           int sslBytes, byte** data, const byte* end,
5536                           void* ctx, char* error)
5537 {
5538     const byte*       sslBegin = sslFrame;
5539     const byte*       recordEnd;   /* end of record indicator */
5540     const byte*       inRecordEnd; /* indicator from input stream not decrypt */
5541     RecordLayerHeader rh;
5542     int               rhSize = 0;
5543     int               ret;
5544     int               errCode = 0;
5545     int               decoded = 0;      /* bytes stored for user in data */
5546     int               notEnough;        /* notEnough bytes yet flag */
5547     int               decrypted = 0;    /* was current msg decrypted */
5548     WOLFSSL*          ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
5549                             session->sslServer : session->sslClient;
5550 doMessage:
5551     notEnough = 0;
5552     if (sslBytes < 0) {
5553         SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
5554         return -1;
5555     }
5556     if (sslBytes >= RECORD_HEADER_SZ) {
5557         if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
5558             /* ignore packet if record header errors */
5559             SetError(BAD_RECORD_HDR_STR, error, session, 0);
5560             return 0;
5561         }
5562     }
5563     else
5564         notEnough = 1;
5565 
5566     if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
5567         /* don't have enough input yet to process full SSL record */
5568         Trace(PARTIAL_INPUT_STR);
5569 
5570         /* store partial if not there already or we advanced */
5571         if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
5572             if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
5573                 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
5574                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5575                     return -1;
5576                 }
5577             }
5578             XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
5579             ssl->buffers.inputBuffer.length = sslBytes;
5580         }
5581         if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
5582             goto doMessage;
5583         return decoded;
5584     }
5585     sslFrame += RECORD_HEADER_SZ;
5586     sslBytes -= RECORD_HEADER_SZ;
5587     recordEnd = sslFrame + rhSize;   /* may have more than one record */
5588     inRecordEnd = recordEnd;
5589 
5590     /* Make sure cipher is on for client, if we get an application data packet
5591      * and handhsake is done for server. This workaround is required if client
5592      * handshake packets were missed, retransmitted or sent out of order. */
5593     if ((enum ContentType)rh.type == application_data &&
5594                   ssl->options.handShakeDone && session->flags.serverCipherOn) {
5595         session->flags.clientCipherOn = 1;
5596         session->sslClient->options.handShakeState = HANDSHAKE_DONE;
5597         session->sslClient->options.handShakeDone  = 1;
5598     }
5599 
5600     /* decrypt if needed */
5601     if ((session->flags.side == WOLFSSL_SERVER_END &&
5602                                                session->flags.serverCipherOn)
5603      || (session->flags.side == WOLFSSL_CLIENT_END &&
5604                                                session->flags.clientCipherOn)) {
5605         int ivAdvance = 0;  /* TLSv1.1 advance amount */
5606 
5607         /* change_cipher_spec is not encrypted */
5608         if (rh.type == change_cipher_spec) {
5609             goto doPart;
5610         }
5611         if (ssl->decrypt.setup != 1) {
5612             SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
5613             return -1;
5614         }
5615         if (CheckAvailableSize(ssl, rhSize) < 0) {
5616             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
5617             return -1;
5618         }
5619 
5620         sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
5621                                   ssl->buffers.outputBuffer.buffer, &errCode,
5622                                   &ivAdvance, &rh);
5623         recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
5624                                                        should recordEnd */
5625         decrypted = 1;
5626 
5627 #ifdef WOLFSSL_SNIFFER_STATS
5628         if (errCode != 0) {
5629             INC_STAT(SnifferStats.sslKeyFails);
5630         }
5631         else {
5632             LOCK_STAT();
5633             NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets);
5634             NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes);
5635             UNLOCK_STAT();
5636         }
5637 #endif
5638         if (errCode != 0) {
5639             if ((enum ContentType)rh.type == application_data) {
5640                 SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
5641                 return -1;
5642             }
5643             /* do not end session for failures on handshake packets */
5644             return 0;
5645         }
5646     }
5647 
5648 doPart:
5649 
5650     switch ((enum ContentType)rh.type) {
5651         case handshake:
5652             {
5653                 int startIdx = sslBytes;
5654                 int used;
5655 
5656                 Trace(GOT_HANDSHAKE_STR);
5657                 ret = DoHandShake(sslFrame, &sslBytes, session, error, rhSize);
5658                 if (ret != 0 || sslBytes > startIdx) {
5659                     if (session->flags.fatalError == 0)
5660                         SetError(BAD_HANDSHAKE_STR, error, session,
5661                                  FATAL_ERROR_STATE);
5662                     return -1;
5663                 }
5664 
5665                 /* DoHandShake now fully decrements sslBytes to remaining */
5666                 used = startIdx - sslBytes;
5667                 sslFrame += used;
5668                 if (decrypted)
5669                     sslFrame += ssl->keys.padSz;
5670             }
5671             break;
5672         case change_cipher_spec:
5673             if (session->flags.side == WOLFSSL_SERVER_END) {
5674             #ifdef WOLFSSL_TLS13
5675                 if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
5676                     session->flags.serverCipherOn = 0;
5677                 }
5678                 else
5679             #endif
5680                 {
5681                     session->flags.serverCipherOn = 1;
5682                 }
5683             }
5684             else
5685                 session->flags.clientCipherOn = 1;
5686             Trace(GOT_CHANGE_CIPHER_STR);
5687             ssl->options.handShakeState = HANDSHAKE_DONE;
5688             ssl->options.handShakeDone  = 1;
5689 
5690             sslFrame += 1;
5691             sslBytes -= 1;
5692 
5693             break;
5694         case application_data:
5695             Trace(GOT_APP_DATA_STR);
5696             {
5697                 word32 inOutIdx = 0;
5698 
5699                 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx, SNIFF);
5700                 if (ret == 0) {
5701                     ret = ssl->buffers.clearOutputBuffer.length;
5702                     TraceGotData(ret);
5703                     if (ret) {  /* may be blank message */
5704                         if (data != NULL) {
5705                             byte* tmpData;  /* don't leak on realloc free */
5706                             /* add an extra byte at end of allocation in case
5707                              * user wants to null terminate plaintext */
5708                             tmpData = (byte*)XREALLOC(*data, decoded + ret + 1,
5709                                     NULL, DYNAMIC_TYPE_TMP_BUFFER);
5710                             if (tmpData == NULL) {
5711                                 ForceZero(*data, decoded);
5712                                 XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
5713                                 *data = NULL;
5714                                 SetError(MEMORY_STR, error, session,
5715                                          FATAL_ERROR_STATE);
5716                                 return -1;
5717                             }
5718                             *data = tmpData;
5719                             XMEMCPY(*data + decoded,
5720                                     ssl->buffers.clearOutputBuffer.buffer, ret);
5721                         }
5722                         else {
5723 #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
5724                             if (StoreDataCb) {
5725                                 const byte* buf;
5726                                 word32 offset = 0;
5727                                 word32 bufSz;
5728                                 int stored;
5729 
5730                                 buf = ssl->buffers.clearOutputBuffer.buffer;
5731                                 bufSz = ssl->buffers.clearOutputBuffer.length;
5732                                 do {
5733                                     stored = StoreDataCb(buf, bufSz, offset,
5734                                             ctx);
5735                                     if (stored <= 0) {
5736                                         return -1;
5737                                     }
5738                                     offset += stored;
5739                                 } while (offset < bufSz);
5740                             }
5741                             else {
5742                                 SetError(STORE_DATA_CB_MISSING_STR, error,
5743                                         session, FATAL_ERROR_STATE);
5744                                 return -1;
5745                             }
5746 #else
5747                             (void)ctx;
5748                             SetError(NO_DATA_DEST_STR, error, session,
5749                                     FATAL_ERROR_STATE);
5750                             return -1;
5751 #endif
5752                         }
5753                         TraceAddedData(ret, decoded);
5754                         decoded += ret;
5755                         ssl->buffers.clearOutputBuffer.length = 0;
5756                     }
5757                 }
5758                 else {
5759                     /* set error, but do not treat fatal */
5760                     SetError(BAD_APP_DATA_STR, error,session, 0);
5761                     return -1;
5762                 }
5763                 if (ssl->buffers.outputBuffer.dynamicFlag)
5764                     ShrinkOutputBuffer(ssl);
5765 
5766                 sslFrame += inOutIdx;
5767                 sslBytes -= inOutIdx;
5768             }
5769             break;
5770         case alert:
5771             Trace(GOT_ALERT_STR);
5772 #ifdef WOLFSSL_SNIFFER_STATS
5773             INC_STAT(SnifferStats.sslAlerts);
5774 #endif
5775             sslFrame += rhSize;
5776             sslBytes -= rhSize;
5777             break;
5778         case no_type:
5779         default:
5780             SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
5781             return -1;
5782     }
5783 
5784     /* do we have another msg in record ? */
5785     if (sslFrame < recordEnd) {
5786         Trace(ANOTHER_MSG_STR);
5787         goto doPart;
5788     }
5789 
5790     /* back to input stream instead of potential decrypt buffer */
5791     recordEnd = inRecordEnd;
5792 
5793     /* do we have more records ? */
5794     if (recordEnd < end) {
5795         Trace(ANOTHER_MSG_STR);
5796         sslFrame = recordEnd;
5797         sslBytes = (int)(end - recordEnd);
5798         goto doMessage;
5799     }
5800 
5801     /* clear used input */
5802     ssl->buffers.inputBuffer.length = 0;
5803 
5804     /* could have more input ready now */
5805     if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
5806         goto doMessage;
5807 
5808     if (ssl->buffers.inputBuffer.dynamicFlag)
5809         ShrinkInputBuffer(ssl, NO_FORCED_FREE);
5810 
5811     return decoded;
5812 }
5813 
5814 
5815 /* See if we need to process any pending FIN captures */
5816 /* Return 0=normal, else = session removed */
5817 static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
5818                             SnifferSession* session)
5819 {
5820     int ret = 0;
5821     if (session->finCapture.cliFinSeq && session->finCapture.cliFinSeq <=
5822                                          session->cliExpected) {
5823         if (session->finCapture.cliCounted == 0) {
5824             session->flags.finCount += 1;
5825             session->finCapture.cliCounted = 1;
5826             TraceClientFin(session->finCapture.cliFinSeq, session->cliExpected);
5827         }
5828     }
5829 
5830     if (session->finCapture.srvFinSeq && session->finCapture.srvFinSeq <=
5831                                          session->srvExpected) {
5832         if (session->finCapture.srvCounted == 0) {
5833             session->flags.finCount += 1;
5834             session->finCapture.srvCounted = 1;
5835             TraceServerFin(session->finCapture.srvFinSeq, session->srvExpected);
5836         }
5837     }
5838 
5839     if (session->flags.finCount >= 2) {
5840         RemoveSession(session, ipInfo, tcpInfo, 0);
5841         ret = 1;
5842     }
5843     return ret;
5844 }
5845 
5846 
5847 /* If session is in fatal error state free resources now
5848    return true if removed, 0 otherwise */
5849 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
5850                               SnifferSession* session, char* error)
5851 {
5852     if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
5853         RemoveSession(session, ipInfo, tcpInfo, 0);
5854         SetError(FATAL_ERROR_STR, error, NULL, 0);
5855         return 1;
5856     }
5857     return 0;
5858 }
5859 
5860 
5861 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
5862 /* returns Number of bytes on success, 0 for no data yet, and
5863  * WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state
5864  * error
5865  */
5866 static int ssl_DecodePacketInternal(const byte* packet, int length,
5867                                     void* vChain, word32 chainSz,
5868                                     byte** data, SSLInfo* sslInfo,
5869                                     void* ctx, char* error)
5870 {
5871     TcpInfo           tcpInfo;
5872     IpInfo            ipInfo;
5873     const byte*       sslFrame;
5874     const byte*       end;
5875     int               sslBytes;                /* ssl bytes unconsumed */
5876     int               ret;
5877     SnifferSession*   session = 0;
5878 
5879 #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
5880     if (packet == NULL && vChain != NULL) {
5881         struct iovec* chain = (struct iovec*)vChain;
5882         word32 i;
5883 
5884         length = 0;
5885         for (i = 0; i < chainSz; i++)
5886             length += chain[i].iov_len;
5887         packet = (const byte*)chain[0].iov_base;
5888     }
5889 #endif
5890 
5891     if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
5892                      error) != 0)
5893         return WOLFSSL_SNIFFER_ERROR;
5894 
5895     end = sslFrame + sslBytes;
5896 
5897     ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
5898     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
5899         return WOLFSSL_SNIFFER_FATAL_ERROR;
5900     else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
5901     else if (ret ==  1) {
5902 #ifdef WOLFSSL_SNIFFER_STATS
5903         if (sslBytes > 0) {
5904             LOCK_STAT();
5905             NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
5906             NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
5907             UNLOCK_STAT();
5908         }
5909         else
5910             INC_STAT(SnifferStats.sslDecryptedPackets);
5911 #endif
5912          return  0;   /* done for now */
5913     }
5914 
5915     ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
5916     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
5917         return WOLFSSL_SNIFFER_FATAL_ERROR;
5918     else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
5919     else if (ret ==  1) {
5920 #ifdef WOLFSSL_SNIFFER_STATS
5921         INC_STAT(SnifferStats.sslDecryptedPackets);
5922 #endif
5923         return  0;   /* done for now */
5924     }
5925 
5926     ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
5927                          &end, vChain, chainSz, error);
5928     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
5929         return WOLFSSL_SNIFFER_FATAL_ERROR;
5930     else if (ret == -1) return WOLFSSL_SNIFFER_ERROR;
5931     else if (ret ==  1) {
5932 #ifdef WOLFSSL_SNIFFER_STATS
5933         INC_STAT(SnifferStats.sslDecryptedPackets);
5934 #endif
5935         return  0;   /* done for now */
5936     }
5937 
5938 #ifdef WOLFSSL_SNIFFER_STATS
5939     if (sslBytes > 0) {
5940         LOCK_STAT();
5941         NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets);
5942         NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes);
5943         UNLOCK_STAT();
5944     }
5945     else
5946         INC_STAT(SnifferStats.sslDecryptedPackets);
5947 #endif
5948 
5949     ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error);
5950     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error))
5951         return WOLFSSL_SNIFFER_FATAL_ERROR;
5952     if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) {
5953         CopySessionInfo(session, sslInfo);
5954     }
5955 
5956     return ret;
5957 }
5958 
5959 
5960 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
5961 /* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
5962  * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
5963 /* Also returns Session Info if available */
5964 int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length,
5965     unsigned char** data, SSLInfo* sslInfo, char* error)
5966 {
5967     return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo,
5968             NULL, error);
5969 }
5970 
5971 
5972 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
5973 /* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
5974  * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
5975 int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
5976 {
5977     return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL,
5978             error);
5979 }
5980 
5981 
5982 #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
5983 
5984 /* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
5985  * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
5986 int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet,
5987         int length, void* ctx, SSLInfo* sslInfo, char* error)
5988 {
5989     return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo,
5990             ctx, error);
5991 }
5992 
5993 #endif
5994 
5995 
5996 #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT
5997 
5998 /* returns Number of bytes on success, 0 for no data yet, WOLFSSL_SNIFFER_ERROR.
5999  * on error and WOLFSSL_SNIFFER_FATAL_ERROR on fatal state error */
6000 int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data,
6001         char* error)
6002 {
6003     return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL,
6004             error);
6005 }
6006 
6007 #endif
6008 
6009 
6010 #if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \
6011      defined(WOLFSSL_SNIFFER_STORE_DATA_CB)
6012 
6013 /*
6014  * returns WOLFSSL_SNIFFER_ERROR on error and WOLFSSL_SNIFFER_FATAL_ERROR on
6015  * fatal state error
6016  */
6017 int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz,
6018         void* ctx, SSLInfo* sslInfo, char* error)
6019 {
6020     return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo,
6021             ctx, error);
6022 }
6023 
6024 #endif
6025 
6026 
6027 /* Deallocator for the decoded data buffer. */
6028 /* returns 0 on success, -1 on error */
6029 int ssl_FreeDecodeBuffer(byte** data, char* error)
6030 {
6031     return ssl_FreeZeroDecodeBuffer(data, 0, error);
6032 }
6033 
6034 
6035 /* Deallocator for the decoded data buffer, zeros out buffer. */
6036 /* returns 0 on success, -1 on error */
6037 int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
6038 {
6039     (void)error;
6040 
6041     if (sz < 0) {
6042         return -1;
6043     }
6044 
6045     if (data != NULL) {
6046         ForceZero(*data, (word32)sz);
6047         XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
6048         *data = NULL;
6049     }
6050 
6051     return 0;
6052 }
6053 
6054 
6055 /* Enables (if traceFile)/ Disables debug tracing */
6056 /* returns 0 on success, -1 on error */
6057 int ssl_Trace(const char* traceFile, char* error)
6058 {
6059     if (traceFile) {
6060         /* Don't try to reopen the file */
6061         if (TraceFile == NULL) {
6062             TraceFile = XFOPEN(traceFile, "a");
6063             if (!TraceFile) {
6064                 SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
6065                 return -1;
6066              }
6067             TraceOn = 1;
6068         }
6069     }
6070     else
6071         TraceOn = 0;
6072 
6073     return 0;
6074 }
6075 
6076 
6077 /* Enables/Disables Recovery of missed data if later packets allow
6078  * maxMemory is number of bytes to use for reassembly buffering per session,
6079  * -1 means unlimited
6080  * returns 0 on success, -1 on error */
6081 int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
6082 {
6083     (void)error;
6084 
6085     RecoveryEnabled = onOff;
6086     if (onOff)
6087         MaxRecoveryMemory = maxMemory;
6088 
6089     return 0;
6090 }
6091 
6092 
6093 
6094 #if defined(WOLFSSL_SESSION_STATS) && !defined(NO_SESSION_CACHE)
6095 
6096 int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
6097                         unsigned int* peak,       unsigned int* maxSessions,
6098                         unsigned int* missedData, unsigned int* reassemblyMem,
6099                         char* error)
6100 {
6101     int ret;
6102 
6103     if (missedData) {
6104         wc_LockMutex(&RecoveryMutex);
6105         *missedData = MissedDataSessions;
6106         wc_UnLockMutex(&RecoveryMutex);
6107     }
6108 
6109     if (reassemblyMem) {
6110         SnifferSession* session;
6111         int i;
6112 
6113         *reassemblyMem = 0;
6114         wc_LockMutex(&SessionMutex);
6115         for (i = 0; i < HASH_SIZE; i++) {
6116             session = SessionTable[i];
6117             while (session) {
6118                 *reassemblyMem += session->cliReassemblyMemory;
6119                 *reassemblyMem += session->srvReassemblyMemory;
6120                 session = session->next;
6121             }
6122         }
6123         wc_UnLockMutex(&SessionMutex);
6124     }
6125 
6126     ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
6127 
6128     if (ret == WOLFSSL_SUCCESS)
6129         return 0;
6130     else {
6131         SetError(BAD_SESSION_STATS, error, NULL, 0);
6132         return -1;
6133     }
6134 }
6135 
6136 #endif
6137 
6138 
6139 
6140 int ssl_SetConnectionCb(SSLConnCb cb)
6141 {
6142     ConnectionCb = cb;
6143     return 0;
6144 }
6145 
6146 
6147 
6148 int ssl_SetConnectionCtx(void* ctx)
6149 {
6150     ConnectionCbCtx = ctx;
6151     return 0;
6152 }
6153 
6154 
6155 #ifdef WOLFSSL_SNIFFER_STATS
6156 
6157 /* Resets the statistics tracking global structure.
6158  * returns 0 on success, -1 on error */
6159 int ssl_ResetStatistics(void)
6160 {
6161     wc_LockMutex(&StatsMutex);
6162     XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
6163     wc_UnLockMutex(&StatsMutex);
6164     return 0;
6165 }
6166 
6167 
6168 /* Copies the SSL statistics into the provided stats record.
6169  * returns 0 on success, -1 on error */
6170 int ssl_ReadStatistics(SSLStats* stats)
6171 {
6172     if (stats == NULL)
6173         return -1;
6174 
6175     LOCK_STAT();
6176     XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
6177     UNLOCK_STAT();
6178     return 0;
6179 }
6180 
6181 /* Copies the SSL statistics into the provided stats record then
6182  * resets the statistics tracking global structure.
6183  * returns 0 on success, -1 on error */
6184 int ssl_ReadResetStatistics(SSLStats* stats)
6185 {
6186     if (stats == NULL)
6187         return -1;
6188 
6189     LOCK_STAT();
6190     XMEMCPY(stats, &SnifferStats, sizeof(SSLStats));
6191     XMEMSET(&SnifferStats, 0, sizeof(SSLStats));
6192     UNLOCK_STAT();
6193     return 0;
6194 }
6195 
6196 #endif /* WOLFSSL_SNIFFER_STATS */
6197 
6198 
6199 #ifdef WOLFSSL_SNIFFER_WATCH
6200 
6201 int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error)
6202 {
6203 #ifdef WOLF_CRYPTO_CB
6204     if (CryptoDeviceId == INVALID_DEVID)
6205         CryptoDeviceId = devId;
6206 #else
6207     (void)devId;
6208 #endif
6209     WatchCb = cb;
6210     return CreateWatchSnifferServer(error);
6211 }
6212 
6213 int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error)
6214 {
6215     WatchCb = cb;
6216     return CreateWatchSnifferServer(error);
6217 }
6218 
6219 int ssl_SetWatchKeyCtx(void* ctx, char* error)
6220 {
6221     (void)error;
6222     WatchCbCtx = ctx;
6223     return 0;
6224 }
6225 
6226 int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz,
6227         int keyType, char* error)
6228 {
6229     SnifferSession* sniffer;
6230     int ret;
6231 
6232     if (vSniffer == NULL) {
6233         return -1;
6234     }
6235     if (key == NULL || keySz == 0) {
6236         return -1;
6237     }
6238 
6239     sniffer = (SnifferSession*)vSniffer;
6240     /* Remap the keyType from what the user can use to
6241      * what wolfSSL_use_PrivateKey_buffer expects. */
6242     keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
6243                                           WOLFSSL_FILETYPE_ASN1;
6244 
6245 #ifdef WOLFSSL_STATIC_EPHEMERAL
6246     /* try setting static ephemeral first */
6247     /* auto detect key type with WC_PK_TYPE_NONE */
6248     ret = wolfSSL_set_ephemeral_key(sniffer->sslServer,
6249         WC_PK_TYPE_NONE, (const char*)key, keySz,
6250             WOLFSSL_FILETYPE_ASN1);
6251     if (ret != 0) {
6252     #ifdef DEBUG_SNIFFER
6253         /* print warnings */
6254         printf("key watch set ephemeral failed %d\n", ret);
6255     #endif
6256     }
6257 #endif
6258 
6259     /* always try and load private key */
6260     ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer,
6261         key, keySz, keyType);
6262 
6263     if (ret != WOLFSSL_SUCCESS) {
6264         SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE);
6265         return -1;
6266     }
6267 
6268     return 0;
6269 }
6270 
6271 int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType,
6272         const char* password, char* error)
6273 {
6274     byte* keyBuf = NULL;
6275     word32 keyBufSz = 0;
6276     int ret;
6277 
6278     if (vSniffer == NULL) {
6279         return -1;
6280     }
6281     if (keyFile == NULL) {
6282         return -1;
6283     }
6284 
6285     /* Remap the keyType from what the user can use to
6286      * what LoadKeyFile expects. */
6287     keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
6288                                           WOLFSSL_FILETYPE_ASN1;
6289 
6290     ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, 0, keyType, password);
6291     if (ret < 0) {
6292         SetError(KEY_FILE_STR, error, NULL, 0);
6293         XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
6294         return -1;
6295     }
6296 
6297     ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER,
6298             error);
6299     XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509);
6300 
6301     return ret;
6302 }
6303 
6304 #endif /* WOLFSSL_SNIFFER_WATCH */
6305 
6306 
6307 #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB
6308 
6309 int ssl_SetStoreDataCallback(SSLStoreDataCb cb)
6310 {
6311     StoreDataCb = cb;
6312     return 0;
6313 }
6314 
6315 #endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
6316 
6317 #ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
6318 int ssl_SetKeyCallback(SSLKeyCb cb, void* cbCtx)
6319 {
6320     KeyCb = cb;
6321     KeyCbCtx = cbCtx;
6322     return 0;
6323 }
6324 #endif
6325 
6326 #endif /* WOLFSSL_SNIFFER */
6327 #endif /* WOLFCRYPT_ONLY */
6328