source: asp3_tinet_ecnl_rx/trunk/wolfssl-3.12.2/src/sniffer.c@ 337

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

ASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 105.5 KB
Line 
1/* sniffer.c
2 *
3 * Copyright (C) 2006-2017 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22
23#ifdef HAVE_CONFIG_H
24 #include <config.h>
25#endif
26
27#include <wolfssl/wolfcrypt/settings.h>
28
29#ifndef WOLFCRYPT_ONLY
30#ifdef WOLFSSL_SNIFFER
31
32#include <assert.h>
33#include <time.h>
34
35#ifndef _WIN32
36 #include <arpa/inet.h>
37#endif
38
39#ifdef _WIN32
40 #define SNPRINTF _snprintf
41#else
42 #define SNPRINTF snprintf
43#endif
44
45#include <wolfssl/openssl/ssl.h>
46#include <wolfssl/internal.h>
47#include <wolfssl/error-ssl.h>
48#include <wolfssl/sniffer.h>
49#include <wolfssl/sniffer_error.h>
50#ifdef NO_INLINE
51 #include <wolfssl/wolfcrypt/misc.h>
52#else
53 #define WOLFSSL_MISC_INCLUDED
54 #include <wolfcrypt/src/misc.c>
55#endif
56
57
58#ifndef WOLFSSL_SNIFFER_TIMEOUT
59 #define WOLFSSL_SNIFFER_TIMEOUT 900
60 /* Cache unclosed Sessions for 15 minutes since last used */
61#endif
62
63/* Misc constants */
64enum {
65 MAX_SERVER_ADDRESS = 128, /* maximum server address length */
66 MAX_SERVER_NAME = 128, /* maximum server name length */
67 MAX_ERROR_LEN = 80, /* maximum error length */
68 ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
69 LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
70 TCP_PROTO = 6, /* TCP_PROTOCOL */
71 IP_HDR_SZ = 20, /* IP header length, min */
72 TCP_HDR_SZ = 20, /* TCP header length, min */
73 IPV4 = 4, /* IP version 4 */
74 TCP_PROTOCOL = 6, /* TCP Protocol id */
75 TRACE_MSG_SZ = 80, /* Trace Message buffer size */
76 HASH_SIZE = 499, /* Session Hash Table Rows */
77 PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
78 FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
79 TICKET_HINT_LEN = 4, /* Session Ticket Hint length */
80 EXT_TYPE_SZ = 2, /* Extension length */
81 MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
82 MTU_EXTRA, /* Max input sz of reassembly */
83 EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */
84 TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
85};
86
87
88#ifdef _WIN32
89
90static HMODULE dllModule; /* for error string resources */
91
92BOOL APIENTRY DllMain( HMODULE hModule,
93 DWORD ul_reason_for_call,
94 LPVOID lpReserved
95 )
96{
97 static int didInit = 0;
98
99 switch (ul_reason_for_call)
100 {
101 case DLL_PROCESS_ATTACH:
102 if (didInit == 0) {
103 dllModule = hModule;
104 ssl_InitSniffer();
105 didInit = 1;
106 }
107 break;
108 case DLL_THREAD_ATTACH:
109 break;
110 case DLL_THREAD_DETACH:
111 break;
112 case DLL_PROCESS_DETACH:
113 if (didInit) {
114 ssl_FreeSniffer();
115 didInit = 0;
116 }
117 break;
118 }
119 return TRUE;
120}
121
122#endif /* _WIN32 */
123
124
125static int TraceOn = 0; /* Trace is off by default */
126static FILE* TraceFile = 0;
127
128
129/* windows uses .rc table for this */
130#ifndef _WIN32
131
132static const char* const msgTable[] =
133{
134 /* 1 */
135 "Out of Memory",
136 "New SSL Sniffer Server Registered",
137 "Checking IP Header",
138 "SSL Sniffer Server Not Registered",
139 "Checking TCP Header",
140
141 /* 6 */
142 "SSL Sniffer Server Port Not Registered",
143 "RSA Private Decrypt Error",
144 "RSA Private Decode Error",
145 "Set Cipher Spec Error",
146 "Server Hello Input Malformed",
147
148 /* 11 */
149 "Couldn't Resume Session Error",
150 "Server Did Resumption",
151 "Client Hello Input Malformed",
152 "Client Trying to Resume",
153 "Handshake Input Malformed",
154
155 /* 16 */
156 "Got Hello Verify msg",
157 "Got Server Hello msg",
158 "Got Cert Request msg",
159 "Got Server Key Exchange msg",
160 "Got Cert msg",
161
162 /* 21 */
163 "Got Server Hello Done msg",
164 "Got Finished msg",
165 "Got Client Hello msg",
166 "Got Client Key Exchange msg",
167 "Got Cert Verify msg",
168
169 /* 26 */
170 "Got Unknown Handshake msg",
171 "New SSL Sniffer Session created",
172 "Couldn't create new SSL",
173 "Got a Packet to decode",
174 "No data present",
175
176 /* 31 */
177 "Session Not Found",
178 "Got an Old Client Hello msg",
179 "Old Client Hello Input Malformed",
180 "Old Client Hello OK",
181 "Bad Old Client Hello",
182
183 /* 36 */
184 "Bad Record Header",
185 "Record Header Input Malformed",
186 "Got a HandShake msg",
187 "Bad HandShake msg",
188 "Got a Change Cipher Spec msg",
189
190 /* 41 */
191 "Got Application Data msg",
192 "Bad Application Data",
193 "Got an Alert msg",
194 "Another msg to Process",
195 "Removing Session From Table",
196
197 /* 46 */
198 "Bad Key File",
199 "Wrong IP Version",
200 "Wrong Protocol type",
201 "Packet Short for header processing",
202 "Got Unknown Record Type",
203
204 /* 51 */
205 "Can't Open Trace File",
206 "Session in Fatal Error State",
207 "Partial SSL record received",
208 "Buffer Error, malformed input",
209 "Added to Partial Input",
210
211 /* 56 */
212 "Received a Duplicate Packet",
213 "Received an Out of Order Packet",
214 "Received an Overlap Duplicate Packet",
215 "Received an Overlap Reassembly Begin Duplicate Packet",
216 "Received an Overlap Reassembly End Duplicate Packet",
217
218 /* 61 */
219 "Missed the Client Hello Entirely",
220 "Got Hello Request msg",
221 "Got Session Ticket msg",
222 "Bad Input",
223 "Bad Decrypt Type",
224
225 /* 66 */
226 "Bad Finished Message Processing",
227 "Bad Compression Type",
228 "Bad DeriveKeys Error",
229 "Saw ACK for Missing Packet Error",
230 "Bad Decrypt Operation",
231
232 /* 71 */
233 "Decrypt Keys Not Set Up",
234 "Late Key Load Error",
235 "Got Certificate Status msg",
236 "RSA Key Missing Error",
237 "Secure Renegotiation Not Supported",
238
239 /* 76 */
240 "Get Session Stats Failure",
241 "Reassembly Buffer Size Exceeded",
242 "Dropping Lost Fragment",
243 "Dropping Partial Record",
244 "Clear ACK Fault",
245
246 /* 81 */
247 "Bad Decrypt Size",
248 "Extended Master Secret Hash Error"
249};
250
251
252/* *nix version uses table above */
253static void GetError(int idx, char* str)
254{
255 XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
256}
257
258
259#else /* _WIN32 */
260
261
262/* Windows version uses .rc table */
263static void GetError(int idx, char* buffer)
264{
265 if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
266 buffer[0] = 0;
267}
268
269
270#endif /* _WIN32 */
271
272
273/* Packet Buffer for reassembly list and ready list */
274typedef struct PacketBuffer {
275 word32 begin; /* relative sequence begin */
276 word32 end; /* relative sequence end */
277 byte* data; /* actual data */
278 struct PacketBuffer* next; /* next on reassembly list or ready list */
279} PacketBuffer;
280
281
282#ifdef HAVE_SNI
283
284/* NamedKey maps a SNI name to a specific private key */
285typedef struct NamedKey {
286 char name[MAX_SERVER_NAME]; /* server DNS name */
287 word32 nameSz; /* size of server DNS name */
288 byte* key; /* DER private key */
289 word32 keySz; /* size of DER private key */
290 struct NamedKey* next; /* for list */
291} NamedKey;
292
293#endif
294
295
296/* Sniffer Server holds info for each server/port monitored */
297typedef struct SnifferServer {
298 SSL_CTX* ctx; /* SSL context */
299 char address[MAX_SERVER_ADDRESS]; /* passed in server address */
300 word32 server; /* netowrk order address */
301 int port; /* server port */
302#ifdef HAVE_SNI
303 NamedKey* namedKeys; /* mapping of names and keys */
304 wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */
305#endif
306 struct SnifferServer* next; /* for list */
307} SnifferServer;
308
309
310/* Session Flags */
311typedef struct Flags {
312 byte side; /* which end is current packet headed */
313 byte serverCipherOn; /* indicates whether cipher is active */
314 byte clientCipherOn; /* indicates whether cipher is active */
315 byte resuming; /* did this session come from resumption */
316 byte cached; /* have we cached this session yet */
317 byte clientHello; /* processed client hello yet, for SSLv2 */
318 byte finCount; /* get both FINs before removing */
319 byte fatalError; /* fatal error state */
320 byte cliAckFault; /* client acked unseen data from server */
321 byte srvAckFault; /* server acked unseen data from client */
322 byte cliSkipPartial; /* client skips partial data to catch up */
323 byte srvSkipPartial; /* server skips partial data to catch up */
324#ifdef HAVE_EXTENDED_MASTER
325 byte expectEms; /* expect extended master secret */
326#endif
327} Flags;
328
329
330/* Out of Order FIN caputre */
331typedef struct FinCaputre {
332 word32 cliFinSeq; /* client relative sequence FIN 0 is no */
333 word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
334 byte cliCounted; /* did we count yet, detects duplicates */
335 byte srvCounted; /* did we count yet, detects duplicates */
336} FinCaputre;
337
338
339typedef struct HsHashes {
340#ifndef NO_OLD_TLS
341#ifndef NO_SHA
342 wc_Sha hashSha;
343#endif
344#ifndef NO_MD5
345 wc_Md5 hashMd5;
346#endif
347#endif
348#ifndef NO_SHA256
349 wc_Sha256 hashSha256;
350#endif
351#ifdef WOLFSSL_SHA384
352 wc_Sha384 hashSha384;
353#endif
354} HsHashes;
355
356
357/* Sniffer Session holds info for each client/server SSL/TLS session */
358typedef struct SnifferSession {
359 SnifferServer* context; /* server context */
360 SSL* sslServer; /* SSL server side decode */
361 SSL* sslClient; /* SSL client side decode */
362 word32 server; /* server address in network byte order */
363 word32 client; /* client address in network byte order */
364 word16 srvPort; /* server port */
365 word16 cliPort; /* client port */
366 word32 cliSeqStart; /* client start sequence */
367 word32 srvSeqStart; /* server start sequence */
368 word32 cliExpected; /* client expected sequence (relative) */
369 word32 srvExpected; /* server expected sequence (relative) */
370 FinCaputre finCaputre; /* retain out of order FIN s */
371 Flags flags; /* session flags */
372 time_t lastUsed; /* last used ticks */
373 PacketBuffer* cliReassemblyList; /* client out of order packets */
374 PacketBuffer* srvReassemblyList; /* server out of order packets */
375 word32 cliReassemblyMemory; /* client packet memory used */
376 word32 srvReassemblyMemory; /* server packet memory used */
377 struct SnifferSession* next; /* for hash table list */
378 byte* ticketID; /* mac ID of session ticket */
379#ifdef HAVE_EXTENDED_MASTER
380 HsHashes* hash;
381#endif
382} SnifferSession;
383
384
385/* Sniffer Server List and mutex */
386static SnifferServer* ServerList = 0;
387static wolfSSL_Mutex ServerListMutex;
388
389
390/* Session Hash Table, mutex, and count */
391static SnifferSession* SessionTable[HASH_SIZE];
392static wolfSSL_Mutex SessionMutex;
393static int SessionCount = 0;
394
395/* Recovery of missed data switches and stats */
396static wolfSSL_Mutex RecoveryMutex; /* for stats */
397static int RecoveryEnabled = 0; /* global switch */
398static int MaxRecoveryMemory = -1; /* per session max recovery memory */
399static word32 MissedDataSessions = 0; /* # of sessions with missed data */
400
401
402static void UpdateMissedDataSessions(void)
403{
404 wc_LockMutex(&RecoveryMutex);
405 MissedDataSessions += 1;
406 wc_UnLockMutex(&RecoveryMutex);
407}
408
409
410/* Initialize overall Sniffer */
411void ssl_InitSniffer(void)
412{
413 wolfSSL_Init();
414 wc_InitMutex(&ServerListMutex);
415 wc_InitMutex(&SessionMutex);
416 wc_InitMutex(&RecoveryMutex);
417}
418
419
420#ifdef HAVE_SNI
421
422/* Free Named Key and the zero out the private key it holds */
423static void FreeNamedKey(NamedKey* in)
424{
425 if (in) {
426 if (in->key) {
427 ForceZero(in->key, in->keySz);
428 free(in->key);
429 }
430 free(in);
431 }
432}
433
434
435static void FreeNamedKeyList(NamedKey* in)
436{
437 NamedKey* next;
438
439 while (in) {
440 next = in->next;
441 FreeNamedKey(in);
442 in = next;
443 }
444}
445
446#endif
447
448
449/* Free Sniffer Server's resources/self */
450static void FreeSnifferServer(SnifferServer* srv)
451{
452 if (srv) {
453#ifdef HAVE_SNI
454 wc_LockMutex(&srv->namedKeysMutex);
455 FreeNamedKeyList(srv->namedKeys);
456 wc_UnLockMutex(&srv->namedKeysMutex);
457 wc_FreeMutex(&srv->namedKeysMutex);
458#endif
459 SSL_CTX_free(srv->ctx);
460 }
461 free(srv);
462}
463
464
465/* free PacketBuffer's resources/self */
466static void FreePacketBuffer(PacketBuffer* del)
467{
468 if (del) {
469 free(del->data);
470 free(del);
471 }
472}
473
474
475/* remove PacketBuffer List */
476static void FreePacketList(PacketBuffer* in)
477{
478 if (in) {
479 PacketBuffer* del;
480 PacketBuffer* packet = in;
481
482 while (packet) {
483 del = packet;
484 packet = packet->next;
485 FreePacketBuffer(del);
486 }
487 }
488}
489
490
491/* Free Sniffer Session's resources/self */
492static void FreeSnifferSession(SnifferSession* session)
493{
494 if (session) {
495 SSL_free(session->sslClient);
496 SSL_free(session->sslServer);
497
498 FreePacketList(session->cliReassemblyList);
499 FreePacketList(session->srvReassemblyList);
500
501 free(session->ticketID);
502#ifdef HAVE_EXTENDED_MASTER
503 free(session->hash);
504#endif
505 }
506 free(session);
507}
508
509
510/* Free overall Sniffer */
511void ssl_FreeSniffer(void)
512{
513 SnifferServer* srv;
514 SnifferServer* removeServer;
515 SnifferSession* session;
516 SnifferSession* removeSession;
517 int i;
518
519 wc_LockMutex(&ServerListMutex);
520 wc_LockMutex(&SessionMutex);
521
522 srv = ServerList;
523 while (srv) {
524 removeServer = srv;
525 srv = srv->next;
526 FreeSnifferServer(removeServer);
527 }
528
529 for (i = 0; i < HASH_SIZE; i++) {
530 session = SessionTable[i];
531 while (session) {
532 removeSession = session;
533 session = session->next;
534 FreeSnifferSession(removeSession);
535 }
536 }
537
538 wc_UnLockMutex(&SessionMutex);
539 wc_UnLockMutex(&ServerListMutex);
540
541 wc_FreeMutex(&RecoveryMutex);
542 wc_FreeMutex(&SessionMutex);
543 wc_FreeMutex(&ServerListMutex);
544
545 if (TraceFile) {
546 TraceOn = 0;
547 fclose(TraceFile);
548 TraceFile = NULL;
549 }
550
551 wolfSSL_Cleanup();
552}
553
554
555#ifdef HAVE_EXTENDED_MASTER
556
557static int HashInit(HsHashes* hash)
558{
559 int ret = 0;
560
561 XMEMSET(hash, 0, sizeof(HsHashes));
562
563#ifndef NO_OLD_TLS
564#ifndef NO_SHA
565 if (ret == 0)
566 ret = wc_InitSha(&hash->hashSha);
567#endif
568#ifndef NO_MD5
569 if (ret == 0) {
570 ret = wc_InitMd5(&hash->hashMd5);
571 }
572#endif
573#endif
574#ifndef NO_SHA256
575 if (ret == 0)
576 ret = wc_InitSha256(&hash->hashSha256);
577#endif
578#ifdef WOLFSSL_SHA384
579 if (ret == 0)
580 ret = wc_InitSha384(&hash->hashSha384);
581#endif
582
583 return ret;
584}
585
586
587static int HashUpdate(HsHashes* hash, const byte* input, int sz)
588{
589 int ret = 0;
590
591 input -= HANDSHAKE_HEADER_SZ;
592 sz += HANDSHAKE_HEADER_SZ;
593
594#ifndef NO_OLD_TLS
595#ifndef NO_SHA
596 if (ret == 0)
597 ret = wc_ShaUpdate(&hash->hashSha, input, sz);
598#endif
599#ifndef NO_MD5
600 if (ret == 0) {
601 ret = wc_Md5Update(&hash->hashMd5, input, sz);
602 }
603#endif
604#endif
605#ifndef NO_SHA256
606 if (ret == 0)
607 ret = wc_Sha256Update(&hash->hashSha256, input, sz);
608#endif
609#ifdef WOLFSSL_SHA384
610 if (ret == 0)
611 ret = wc_Sha384Update(&hash->hashSha384, input, sz);
612#endif
613
614 return ret;
615}
616
617
618static int HashCopy(HS_Hashes* d, HsHashes* s)
619{
620#ifndef NO_OLD_TLS
621#ifndef NO_SHA
622 XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha));
623#endif
624#ifndef NO_MD5
625 XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5));
626#endif
627#endif
628
629#ifndef NO_SHA256
630 XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256));
631#endif
632#ifdef WOLFSSL_SHA384
633 XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384));
634#endif
635
636 return 0;
637}
638
639#endif
640
641
642/* Initialize a SnifferServer */
643static void InitSnifferServer(SnifferServer* sniffer)
644{
645 sniffer->ctx = 0;
646 XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
647 sniffer->server = 0;
648 sniffer->port = 0;
649#ifdef HAVE_SNI
650 sniffer->namedKeys = 0;
651 wc_InitMutex(&sniffer->namedKeysMutex);
652#endif
653 sniffer->next = 0;
654}
655
656
657/* Initialize session flags */
658static void InitFlags(Flags* flags)
659{
660 flags->side = 0;
661 flags->serverCipherOn = 0;
662 flags->clientCipherOn = 0;
663 flags->resuming = 0;
664 flags->cached = 0;
665 flags->clientHello = 0;
666 flags->finCount = 0;
667 flags->fatalError = 0;
668 flags->cliAckFault = 0;
669 flags->srvAckFault = 0;
670 flags->cliSkipPartial = 0;
671 flags->srvSkipPartial = 0;
672#ifdef HAVE_EXTENDED_MASTER
673 flags->expectEms = 0;
674#endif
675}
676
677
678/* Initialize FIN Capture */
679static void InitFinCapture(FinCaputre* cap)
680{
681 cap->cliFinSeq = 0;
682 cap->srvFinSeq = 0;
683 cap->cliCounted = 0;
684 cap->srvCounted = 0;
685}
686
687
688/* Initialize a Sniffer Session */
689static void InitSession(SnifferSession* session)
690{
691 session->context = 0;
692 session->sslServer = 0;
693 session->sslClient = 0;
694 session->server = 0;
695 session->client = 0;
696 session->srvPort = 0;
697 session->cliPort = 0;
698 session->cliSeqStart = 0;
699 session->srvSeqStart = 0;
700 session->cliExpected = 0;
701 session->srvExpected = 0;
702 session->lastUsed = 0;
703 session->cliReassemblyList = 0;
704 session->srvReassemblyList = 0;
705 session->cliReassemblyMemory = 0;
706 session->srvReassemblyMemory = 0;
707 session->next = 0;
708 session->ticketID = 0;
709
710 InitFlags(&session->flags);
711 InitFinCapture(&session->finCaputre);
712#ifdef HAVE_EXTENDED_MASTER
713 session->hash = 0;
714#endif
715}
716
717
718/* IP Info from IP Header */
719typedef struct IpInfo {
720 int length; /* length of this header */
721 int total; /* total length of fragment */
722 word32 src; /* network order source address */
723 word32 dst; /* network order destination address */
724} IpInfo;
725
726
727/* TCP Info from TCP Header */
728typedef struct TcpInfo {
729 int srcPort; /* source port */
730 int dstPort; /* source port */
731 int length; /* length of this header */
732 word32 sequence; /* sequence number */
733 word32 ackNumber; /* ack number */
734 byte fin; /* FIN set */
735 byte rst; /* RST set */
736 byte syn; /* SYN set */
737 byte ack; /* ACK set */
738} TcpInfo;
739
740
741/* Tcp Pseudo Header for Checksum calculation */
742typedef struct TcpPseudoHdr {
743 word32 src; /* source address */
744 word32 dst; /* destination address */
745 byte rsv; /* reserved, always 0 */
746 byte protocol; /* IP protocol */
747 word16 length; /* tcp header length + data length (doesn't include */
748 /* pseudo header length) network order */
749} TcpPseudoHdr;
750
751
752/* Password Setting Callback */
753static int SetPassword(char* passwd, int sz, int rw, void* userdata)
754{
755 (void)rw;
756 XSTRNCPY(passwd, (const char*)userdata, sz);
757 return (int)XSTRLEN((const char*)userdata);
758}
759
760
761/* Ethernet Header */
762typedef struct EthernetHdr {
763 byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */
764 byte src[ETHER_IF_ADDR_LEN]; /* source host address */
765 word16 type; /* IP, ARP, etc */
766} EthernetHdr;
767
768
769/* IP Header */
770typedef struct IpHdr {
771 byte ver_hl; /* version/header length */
772 byte tos; /* type of service */
773 word16 length; /* total length */
774 word16 id; /* identification */
775 word16 offset; /* fragment offset field */
776 byte ttl; /* time to live */
777 byte protocol; /* protocol */
778 word16 sum; /* checksum */
779 word32 src; /* source address */
780 word32 dst; /* destination address */
781} IpHdr;
782
783
784#define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4)
785#define IP_V(ip) ( ((ip)->ver_hl) >> 4)
786
787/* TCP Header */
788typedef struct TcpHdr {
789 word16 srcPort; /* source port */
790 word16 dstPort; /* destination port */
791 word32 sequence; /* sequence number */
792 word32 ack; /* acknoledgment number */
793 byte offset; /* data offset, reserved */
794 byte flags; /* option flags */
795 word16 window; /* window */
796 word16 sum; /* checksum */
797 word16 urgent; /* urgent pointer */
798} TcpHdr;
799
800#define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4)
801#define TCP_FIN 0x01
802#define TCP_SYN 0x02
803#define TCP_RST 0x04
804#define TCP_ACK 0x10
805
806
807
808
809
810/* Use platform specific GetError to write to tracfile if tracing */
811static void Trace(int idx)
812{
813 if (TraceOn) {
814 char myBuffer[MAX_ERROR_LEN];
815 GetError(idx, myBuffer);
816 fprintf(TraceFile, "\t%s\n", myBuffer);
817#ifdef DEBUG_SNIFFER
818 fprintf(stderr, "\t%s\n", myBuffer);
819#endif
820 }
821}
822
823
824/* Show TimeStamp for beginning of packet Trace */
825static void TraceHeader(void)
826{
827 if (TraceOn) {
828 time_t ticks = time(NULL);
829 fprintf(TraceFile, "\n%s", ctime(&ticks));
830 }
831}
832
833
834/* Show Set Server info for Trace */
835static void TraceSetServer(const char* srv, int port, const char* keyFile)
836{
837 if (TraceOn) {
838 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
839 fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
840 keyFile);
841 }
842}
843
844
845#ifdef HAVE_SNI
846
847/* Show Set Named Server info for Trace */
848static void TraceSetNamedServer(const char* name,
849 const char* srv, int port, const char* keyFile)
850{
851 if (TraceOn) {
852 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
853 fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
854 name, srv, port, keyFile);
855 }
856}
857
858#endif
859
860
861/* Trace got packet number */
862static void TracePacket(void)
863{
864 if (TraceOn) {
865 static word32 packetNumber = 0;
866 fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
867 ++packetNumber);
868 }
869}
870
871
872/* Convert network byte order address into human readable */
873static char* IpToS(word32 addr, char* str)
874{
875 byte* p = (byte*)&addr;
876
877 SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
878
879 return str;
880}
881
882
883/* Show destination and source address from Ip Hdr for packet Trace */
884static void TraceIP(IpHdr* iphdr)
885{
886 if (TraceOn) {
887 char src[TRACE_MSG_SZ];
888 char dst[TRACE_MSG_SZ];
889 fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
890 IpToS(iphdr->src, src));
891 }
892}
893
894
895/* Show destination and source port from Tcp Hdr for packet Trace */
896static void TraceTcp(TcpHdr* tcphdr)
897{
898 if (TraceOn) {
899 fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
900 ntohs(tcphdr->srcPort));
901 }
902}
903
904
905/* Show sequence and payload length for Trace */
906static void TraceSequence(word32 seq, int len)
907{
908 if (TraceOn) {
909 fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
910 }
911}
912
913
914/* Show sequence and payload length for Trace */
915static void TraceAck(word32 ack, word32 expected)
916{
917 if (TraceOn) {
918 fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
919 }
920}
921
922
923/* Show relative expected and relative received sequences */
924static void TraceRelativeSequence(word32 expected, word32 got)
925{
926 if (TraceOn) {
927 fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
928 expected, got);
929 }
930}
931
932
933/* Show server sequence startup from SYN */
934static void TraceServerSyn(word32 seq)
935{
936 if (TraceOn) {
937 fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
938 }
939}
940
941
942/* Show client sequence startup from SYN */
943static void TraceClientSyn(word32 seq)
944{
945 if (TraceOn) {
946 fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
947 }
948}
949
950
951/* Show client FIN capture */
952static void TraceClientFin(word32 finSeq, word32 relSeq)
953{
954 if (TraceOn) {
955 fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
956 finSeq, relSeq);
957 }
958}
959
960
961/* Show server FIN capture */
962static void TraceServerFin(word32 finSeq, word32 relSeq)
963{
964 if (TraceOn) {
965 fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
966 finSeq, relSeq);
967 }
968}
969
970
971/* Show number of SSL data bytes decoded, could be 0 (ok) */
972static void TraceGotData(int bytes)
973{
974 if (TraceOn) {
975 fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
976 }
977}
978
979
980/* Show bytes added to old SSL App data */
981static void TraceAddedData(int newBytes, int existingBytes)
982{
983 if (TraceOn) {
984 fprintf(TraceFile,
985 "\t%d bytes added to %d existing bytes in User Buffer\n",
986 newBytes, existingBytes);
987 }
988}
989
990
991/* Show Stale Session */
992static void TraceStaleSession(void)
993{
994 if (TraceOn) {
995 fprintf(TraceFile, "\tFound a stale session\n");
996 }
997}
998
999
1000/* Show Finding Stale Sessions */
1001static void TraceFindingStale(void)
1002{
1003 if (TraceOn) {
1004 fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
1005 }
1006}
1007
1008
1009/* Show Removed Session */
1010static void TraceRemovedSession(void)
1011{
1012 if (TraceOn) {
1013 fprintf(TraceFile, "\tRemoved it\n");
1014 }
1015}
1016
1017
1018/* Set user error string */
1019static void SetError(int idx, char* error, SnifferSession* session, int fatal)
1020{
1021 GetError(idx, error);
1022 Trace(idx);
1023 if (session && fatal == FATAL_ERROR_STATE)
1024 session->flags.fatalError = 1;
1025}
1026
1027
1028/* See if this IPV4 network order address has been registered */
1029/* return 1 is true, 0 is false */
1030static int IsServerRegistered(word32 addr)
1031{
1032 int ret = 0; /* false */
1033 SnifferServer* sniffer;
1034
1035 wc_LockMutex(&ServerListMutex);
1036
1037 sniffer = ServerList;
1038 while (sniffer) {
1039 if (sniffer->server == addr) {
1040 ret = 1;
1041 break;
1042 }
1043 sniffer = sniffer->next;
1044 }
1045
1046 wc_UnLockMutex(&ServerListMutex);
1047
1048 return ret;
1049}
1050
1051
1052/* See if this port has been registered to watch */
1053/* return 1 is true, 0 is false */
1054static int IsPortRegistered(word32 port)
1055{
1056 int ret = 0; /* false */
1057 SnifferServer* sniffer;
1058
1059 wc_LockMutex(&ServerListMutex);
1060
1061 sniffer = ServerList;
1062 while (sniffer) {
1063 if (sniffer->port == (int)port) {
1064 ret = 1;
1065 break;
1066 }
1067 sniffer = sniffer->next;
1068 }
1069
1070 wc_UnLockMutex(&ServerListMutex);
1071
1072 return ret;
1073}
1074
1075
1076/* Get SnifferServer from IP and Port */
1077static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
1078{
1079 SnifferServer* sniffer;
1080
1081 wc_LockMutex(&ServerListMutex);
1082
1083 sniffer = ServerList;
1084 while (sniffer) {
1085 if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
1086 break;
1087 if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
1088 break;
1089 sniffer = sniffer->next;
1090 }
1091
1092 wc_UnLockMutex(&ServerListMutex);
1093
1094 return sniffer;
1095}
1096
1097
1098/* Hash the Session Info, return hash row */
1099static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
1100{
1101 word32 hash = ipInfo->src * ipInfo->dst;
1102 hash *= tcpInfo->srcPort * tcpInfo->dstPort;
1103
1104 return hash % HASH_SIZE;
1105}
1106
1107
1108/* Get Exisiting SnifferSession from IP and Port */
1109static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
1110{
1111 SnifferSession* session;
1112 time_t currTime = time(NULL);
1113 word32 row = SessionHash(ipInfo, tcpInfo);
1114
1115 assert(row <= HASH_SIZE);
1116
1117 wc_LockMutex(&SessionMutex);
1118
1119 session = SessionTable[row];
1120 while (session) {
1121 if (session->server == ipInfo->src && session->client == ipInfo->dst &&
1122 session->srvPort == tcpInfo->srcPort &&
1123 session->cliPort == tcpInfo->dstPort)
1124 break;
1125 if (session->client == ipInfo->src && session->server == ipInfo->dst &&
1126 session->cliPort == tcpInfo->srcPort &&
1127 session->srvPort == tcpInfo->dstPort)
1128 break;
1129
1130 session = session->next;
1131 }
1132
1133 if (session)
1134 session->lastUsed= currTime; /* keep session alive, remove stale will */
1135 /* leave alone */
1136 wc_UnLockMutex(&SessionMutex);
1137
1138 /* determine side */
1139 if (session) {
1140 if (ipInfo->dst == session->context->server &&
1141 tcpInfo->dstPort == session->context->port)
1142 session->flags.side = WOLFSSL_SERVER_END;
1143 else
1144 session->flags.side = WOLFSSL_CLIENT_END;
1145 }
1146
1147 return session;
1148}
1149
1150
1151#ifdef HAVE_SNI
1152
1153static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1154 const char* keyFile, int typeKey,
1155 const char* password)
1156{
1157 byte* loadBuf;
1158 long fileSz = 0;
1159 XFILE file;
1160 int ret;
1161
1162 if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1163 return -1;
1164 }
1165
1166 file = XFOPEN(keyFile, "rb");
1167 if (file == XBADFILE) return -1;
1168 XFSEEK(file, 0, XSEEK_END);
1169 fileSz = XFTELL(file);
1170 XREWIND(file);
1171
1172 loadBuf = (byte*)malloc(fileSz);
1173 if (loadBuf == NULL) {
1174 XFCLOSE(file);
1175 return -1;
1176 }
1177
1178 ret = (int)XFREAD(loadBuf, 1, fileSz, file);
1179 XFCLOSE(file);
1180
1181 if (ret != fileSz) {
1182 free(loadBuf);
1183 return -1;
1184 }
1185
1186 if (typeKey == WOLFSSL_FILETYPE_PEM) {
1187 byte* saveBuf = (byte*)malloc(fileSz);
1188 int saveBufSz = 0;
1189
1190 ret = -1;
1191 if (saveBuf != NULL) {
1192 saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz,
1193 saveBuf, (int)fileSz, password);
1194 if (saveBufSz < 0) {
1195 saveBufSz = 0;
1196 free(saveBuf);
1197 saveBuf = NULL;
1198 }
1199 else
1200 ret = 0;
1201 }
1202
1203 ForceZero(loadBuf, (word32)fileSz);
1204 free(loadBuf);
1205
1206 if (saveBuf) {
1207 *keyBuf = saveBuf;
1208 *keyBufSz = (word32)saveBufSz;
1209 }
1210 }
1211 else {
1212 *keyBuf = loadBuf;
1213 *keyBufSz = (word32)fileSz;
1214 }
1215
1216 if (ret < 0) {
1217 return -1;
1218 }
1219
1220 return ret;
1221}
1222
1223#endif
1224
1225
1226static int SetNamedPrivateKey(const char* name, const char* address, int port,
1227 const char* keyFile, int typeKey, const char* password, char* error)
1228{
1229 SnifferServer* sniffer;
1230 int ret;
1231 int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM :
1232 WOLFSSL_FILETYPE_ASN1;
1233 int isNew = 0;
1234 word32 serverIp;
1235
1236#ifdef HAVE_SNI
1237 NamedKey* namedKey = NULL;
1238#endif
1239
1240 (void)name;
1241#ifdef HAVE_SNI
1242 if (name != NULL) {
1243 namedKey = (NamedKey*)malloc(sizeof(NamedKey));
1244 if (namedKey == NULL) {
1245 SetError(MEMORY_STR, error, NULL, 0);
1246 return -1;
1247 }
1248 XMEMSET(namedKey, 0, sizeof(NamedKey));
1249
1250 namedKey->nameSz = (word32)XSTRLEN(name);
1251 XSTRNCPY(namedKey->name, name, sizeof(namedKey->name));
1252 if (namedKey->nameSz >= sizeof(namedKey->name)) {
1253 namedKey->nameSz = sizeof(namedKey->name) - 1;
1254 namedKey->name[namedKey->nameSz] = '\0';
1255 }
1256
1257 ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1258 keyFile, type, password);
1259 if (ret < 0) {
1260 SetError(KEY_FILE_STR, error, NULL, 0);
1261 FreeNamedKey(namedKey);
1262 return -1;
1263 }
1264 }
1265#endif
1266
1267 serverIp = inet_addr(address);
1268 sniffer = ServerList;
1269 while (sniffer != NULL &&
1270 (sniffer->server != serverIp || sniffer->port != port)) {
1271 sniffer = sniffer->next;
1272 }
1273
1274 if (sniffer == NULL) {
1275 isNew = 1;
1276 sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
1277 if (sniffer == NULL) {
1278 SetError(MEMORY_STR, error, NULL, 0);
1279#ifdef HAVE_SNI
1280 FreeNamedKey(namedKey);
1281#endif
1282 return -1;
1283 }
1284 InitSnifferServer(sniffer);
1285
1286 XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1287 sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1288 sniffer->server = serverIp;
1289 sniffer->port = port;
1290
1291 sniffer->ctx = SSL_CTX_new(TLSv1_client_method());
1292 if (!sniffer->ctx) {
1293 SetError(MEMORY_STR, error, NULL, 0);
1294#ifdef HAVE_SNI
1295 FreeNamedKey(namedKey);
1296#endif
1297 FreeSnifferServer(sniffer);
1298 return -1;
1299 }
1300 }
1301
1302 if (name == NULL) {
1303 if (password) {
1304 SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1305 SSL_CTX_set_default_passwd_cb_userdata(
1306 sniffer->ctx, (void*)password);
1307 }
1308 ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1309 if (ret != WOLFSSL_SUCCESS) {
1310 SetError(KEY_FILE_STR, error, NULL, 0);
1311 if (isNew)
1312 FreeSnifferServer(sniffer);
1313 return -1;
1314 }
1315 }
1316#ifdef HAVE_SNI
1317 else {
1318 wc_LockMutex(&sniffer->namedKeysMutex);
1319 namedKey->next = sniffer->namedKeys;
1320 sniffer->namedKeys = namedKey;
1321 wc_UnLockMutex(&sniffer->namedKeysMutex);
1322 }
1323#endif
1324
1325 if (isNew) {
1326 sniffer->next = ServerList;
1327 ServerList = sniffer;
1328 }
1329
1330 return 0;
1331}
1332
1333
1334#ifdef HAVE_SNI
1335
1336/* Sets the private key for a specific name, server and port */
1337/* returns 0 on success, -1 on error */
1338int ssl_SetNamedPrivateKey(const char* name,
1339 const char* address, int port,
1340 const char* keyFile, int typeKey,
1341 const char* password, char* error)
1342{
1343 int ret;
1344
1345 TraceHeader();
1346 TraceSetNamedServer(name, address, port, keyFile);
1347
1348 wc_LockMutex(&ServerListMutex);
1349 ret = SetNamedPrivateKey(name, address, port, keyFile,
1350 typeKey, password, error);
1351 wc_UnLockMutex(&ServerListMutex);
1352
1353 if (ret == 0)
1354 Trace(NEW_SERVER_STR);
1355
1356 return ret;
1357}
1358
1359#endif
1360
1361
1362/* Sets the private key for a specific server and port */
1363/* returns 0 on success, -1 on error */
1364int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
1365 int typeKey, const char* password, char* error)
1366{
1367 int ret;
1368
1369 TraceHeader();
1370 TraceSetServer(address, port, keyFile);
1371
1372 wc_LockMutex(&ServerListMutex);
1373 ret = SetNamedPrivateKey(NULL, address, port, keyFile,
1374 typeKey, password, error);
1375 wc_UnLockMutex(&ServerListMutex);
1376
1377 if (ret == 0)
1378 Trace(NEW_SERVER_STR);
1379
1380 return ret;
1381}
1382
1383
1384/* Check IP Header for IPV4, TCP, and a registered server address */
1385/* returns 0 on success, -1 on error */
1386static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
1387{
1388 int version = IP_V(iphdr);
1389
1390 TraceIP(iphdr);
1391 Trace(IP_CHECK_STR);
1392
1393 if (version != IPV4) {
1394 SetError(BAD_IPVER_STR, error, NULL, 0);
1395 return -1;
1396 }
1397
1398 if (iphdr->protocol != TCP_PROTOCOL) {
1399 SetError(BAD_PROTO_STR, error, NULL, 0);
1400 return -1;
1401 }
1402
1403 if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
1404 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1405 return -1;
1406 }
1407
1408 info->length = IP_HL(iphdr);
1409 info->total = ntohs(iphdr->length);
1410 info->src = iphdr->src;
1411 info->dst = iphdr->dst;
1412
1413 if (info->total == 0)
1414 info->total = length; /* reassembled may be off */
1415
1416 return 0;
1417}
1418
1419
1420/* Check TCP Header for a registered port */
1421/* returns 0 on success, -1 on error */
1422static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
1423{
1424 TraceTcp(tcphdr);
1425 Trace(TCP_CHECK_STR);
1426 info->srcPort = ntohs(tcphdr->srcPort);
1427 info->dstPort = ntohs(tcphdr->dstPort);
1428 info->length = TCP_LEN(tcphdr);
1429 info->sequence = ntohl(tcphdr->sequence);
1430 info->fin = tcphdr->flags & TCP_FIN;
1431 info->rst = tcphdr->flags & TCP_RST;
1432 info->syn = tcphdr->flags & TCP_SYN;
1433 info->ack = tcphdr->flags & TCP_ACK;
1434 if (info->ack)
1435 info->ackNumber = ntohl(tcphdr->ack);
1436
1437 if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
1438 SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
1439 return -1;
1440 }
1441
1442 return 0;
1443}
1444
1445
1446/* Decode Record Layer Header */
1447static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
1448{
1449 XMEMCPY(rh, input, RECORD_HEADER_SZ);
1450 *size = (rh->length[0] << 8) | rh->length[1];
1451
1452 if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
1453 return LENGTH_ERROR;
1454
1455 return 0;
1456}
1457
1458
1459/* Process Client Key Exchange, RSA only */
1460static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
1461 SnifferSession* session, char* error)
1462{
1463 word32 idx = 0;
1464 RsaKey key;
1465 int ret;
1466
1467 if (session->sslServer->buffers.key == NULL ||
1468 session->sslServer->buffers.key->buffer == NULL ||
1469 session->sslServer->buffers.key->length == 0) {
1470
1471 SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
1472 return -1;
1473 }
1474 ret = wc_InitRsaKey(&key, 0);
1475 if (ret == 0)
1476 ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key->buffer,
1477 &idx, &key, session->sslServer->buffers.key->length);
1478 if (ret == 0) {
1479 int length = wc_RsaEncryptSize(&key);
1480
1481 if (IsTLS(session->sslServer))
1482 input += 2; /* tls pre length */
1483
1484 if (length > *sslBytes) {
1485 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
1486 wc_FreeRsaKey(&key);
1487 return -1;
1488 }
1489 #ifdef WC_RSA_BLINDING
1490 ret = wc_RsaSetRNG(&key, session->sslServer->rng);
1491 if (ret != 0) {
1492 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1493 return -1;
1494 }
1495 #endif
1496 do {
1497 #ifdef WOLFSSL_ASYNC_CRYPT
1498 ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
1499 #endif
1500 if (ret >= 0) {
1501 ret = wc_RsaPrivateDecrypt(input, length,
1502 session->sslServer->arrays->preMasterSecret, SECRET_LEN,
1503 &key);
1504 }
1505 } while (ret == WC_PENDING_E);
1506 if (ret != SECRET_LEN) {
1507 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1508 wc_FreeRsaKey(&key);
1509 return -1;
1510 }
1511 session->sslServer->arrays->preMasterSz = SECRET_LEN;
1512
1513 /* store for client side as well */
1514 XMEMCPY(session->sslClient->arrays->preMasterSecret,
1515 session->sslServer->arrays->preMasterSecret, SECRET_LEN);
1516 session->sslClient->arrays->preMasterSz = SECRET_LEN;
1517
1518 #ifdef SHOW_SECRETS
1519 {
1520 int i;
1521 printf("pre master secret: ");
1522 for (i = 0; i < SECRET_LEN; i++)
1523 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
1524 printf("\n");
1525 }
1526 #endif
1527 }
1528 else {
1529 SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
1530 wc_FreeRsaKey(&key);
1531 return -1;
1532 }
1533
1534 if (SetCipherSpecs(session->sslServer) != 0) {
1535 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1536 wc_FreeRsaKey(&key);
1537 return -1;
1538 }
1539
1540 if (SetCipherSpecs(session->sslClient) != 0) {
1541 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1542 wc_FreeRsaKey(&key);
1543 return -1;
1544 }
1545
1546 ret = MakeMasterSecret(session->sslServer);
1547 ret += MakeMasterSecret(session->sslClient);
1548 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1549 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1550
1551 if (ret != 0) {
1552 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1553 return -1;
1554 }
1555
1556#ifdef SHOW_SECRETS
1557 {
1558 int i;
1559 printf("server master secret: ");
1560 for (i = 0; i < SECRET_LEN; i++)
1561 printf("%02x", session->sslServer->arrays->masterSecret[i]);
1562 printf("\n");
1563
1564 printf("client master secret: ");
1565 for (i = 0; i < SECRET_LEN; i++)
1566 printf("%02x", session->sslClient->arrays->masterSecret[i]);
1567 printf("\n");
1568
1569 printf("server suite = %d\n", session->sslServer->options.cipherSuite);
1570 printf("client suite = %d\n", session->sslClient->options.cipherSuite);
1571 }
1572#endif
1573
1574 wc_FreeRsaKey(&key);
1575 return ret;
1576}
1577
1578
1579/* Process Session Ticket */
1580static int ProcessSessionTicket(const byte* input, int* sslBytes,
1581 SnifferSession* session, char* error)
1582{
1583 word16 len;
1584
1585 /* make sure can read through hint and len */
1586 if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
1587 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1588 return -1;
1589 }
1590
1591 input += TICKET_HINT_LEN; /* skip over hint */
1592 *sslBytes -= TICKET_HINT_LEN;
1593
1594 len = (word16)((input[0] << 8) | input[1]);
1595 input += LENGTH_SZ;
1596 *sslBytes -= LENGTH_SZ;
1597
1598 /* make sure can read through ticket */
1599 if (len > *sslBytes || len < ID_LEN) {
1600 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1601 return -1;
1602 }
1603
1604 /* store session with macID as sessionID */
1605 session->sslServer->options.haveSessionId = 1;
1606 XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
1607
1608 return 0;
1609}
1610
1611
1612/* Process Server Hello */
1613static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
1614 SnifferSession* session, char* error)
1615{
1616 ProtocolVersion pv;
1617 byte b;
1618 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1619 int doResume = 0;
1620 int initialBytes = *sslBytes;
1621
1622 (void)msgSz;
1623 (void)initialBytes;
1624
1625 /* make sure we didn't miss ClientHello */
1626 if (session->flags.clientHello == 0) {
1627 SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
1628 return -1;
1629 }
1630
1631 /* make sure can read through session len */
1632 if (toRead > *sslBytes) {
1633 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1634 return -1;
1635 }
1636
1637 XMEMCPY(&pv, input, VERSION_SZ);
1638 input += VERSION_SZ;
1639 *sslBytes -= VERSION_SZ;
1640
1641 session->sslServer->version = pv;
1642 session->sslClient->version = pv;
1643
1644 XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
1645 XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
1646 input += RAN_LEN;
1647 *sslBytes -= RAN_LEN;
1648
1649 b = *input++;
1650 *sslBytes -= 1;
1651
1652 /* make sure can read through compression */
1653 if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
1654 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1655 return -1;
1656 }
1657 if (b) {
1658 XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
1659 session->sslServer->options.haveSessionId = 1;
1660 }
1661 input += b;
1662 *sslBytes -= b;
1663
1664 /* cipher suite */
1665 b = *input++; /* first byte, ECC or not */
1666 session->sslServer->options.cipherSuite0 = b;
1667 session->sslClient->options.cipherSuite0 = b;
1668 b = *input++;
1669 session->sslServer->options.cipherSuite = b;
1670 session->sslClient->options.cipherSuite = b;
1671 *sslBytes -= SUITE_LEN;
1672
1673 /* compression */
1674 b = *input++;
1675 *sslBytes -= ENUM_LEN;
1676
1677 if (b) {
1678 SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
1679 return -1;
1680 }
1681
1682#ifdef HAVE_EXTENDED_MASTER
1683 /* extensions */
1684 if ((initialBytes - *sslBytes) < msgSz) {
1685 word16 len;
1686
1687 /* skip extensions until extended master secret */
1688 /* make sure can read len */
1689 if (SUITE_LEN > *sslBytes) {
1690 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1691 return -1;
1692 }
1693 len = (word16)((input[0] << 8) | input[1]);
1694 input += SUITE_LEN;
1695 *sslBytes -= SUITE_LEN;
1696 /* make sure can read through all extensions */
1697 if (len > *sslBytes) {
1698 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1699 return -1;
1700 }
1701
1702 while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
1703 byte extType[EXT_TYPE_SZ];
1704 word16 extLen;
1705
1706 extType[0] = input[0];
1707 extType[1] = input[1];
1708 input += EXT_TYPE_SZ;
1709 *sslBytes -= EXT_TYPE_SZ;
1710
1711 extLen = (word16)((input[0] << 8) | input[1]);
1712 input += LENGTH_SZ;
1713 *sslBytes -= LENGTH_SZ;
1714
1715 /* make sure can read through individual extension */
1716 if (extLen > *sslBytes) {
1717 SetError(SERVER_HELLO_INPUT_STR, error, session,
1718 FATAL_ERROR_STATE);
1719 return -1;
1720 }
1721
1722 if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
1723 session->flags.expectEms = 1;
1724 }
1725
1726 input += extLen;
1727 *sslBytes -= extLen;
1728 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
1729 }
1730 }
1731
1732 if (!session->flags.expectEms) {
1733 free(session->hash);
1734 session->hash = NULL;
1735 }
1736#endif
1737
1738 if (session->sslServer->options.haveSessionId &&
1739 XMEMCMP(session->sslServer->arrays->sessionID,
1740 session->sslClient->arrays->sessionID, ID_LEN) == 0)
1741 doResume = 1;
1742 else if (session->sslClient->options.haveSessionId == 0 &&
1743 session->sslServer->options.haveSessionId == 0 &&
1744 session->ticketID)
1745 doResume = 1;
1746
1747 if (session->ticketID && doResume) {
1748 /* use ticketID to retrieve from session, prefer over sessionID */
1749 XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
1750 session->sslServer->options.haveSessionId = 1; /* may not have
1751 actual sessionID */
1752 }
1753
1754 if (doResume ) {
1755 int ret = 0;
1756 SSL_SESSION* resume = GetSession(session->sslServer,
1757 session->sslServer->arrays->masterSecret, 0);
1758 if (resume == NULL) {
1759 SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
1760 return -1;
1761 }
1762 /* make sure client has master secret too */
1763 XMEMCPY(session->sslClient->arrays->masterSecret,
1764 session->sslServer->arrays->masterSecret, SECRET_LEN);
1765 session->flags.resuming = 1;
1766
1767 Trace(SERVER_DID_RESUMPTION_STR);
1768 if (SetCipherSpecs(session->sslServer) != 0) {
1769 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1770 return -1;
1771 }
1772
1773 if (SetCipherSpecs(session->sslClient) != 0) {
1774 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1775 return -1;
1776 }
1777
1778 if (session->sslServer->options.tls) {
1779 ret = DeriveTlsKeys(session->sslServer);
1780 ret += DeriveTlsKeys(session->sslClient);
1781 }
1782 else {
1783 ret = DeriveKeys(session->sslServer);
1784 ret += DeriveKeys(session->sslClient);
1785 }
1786 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1787 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1788
1789 if (ret != 0) {
1790 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1791 return -1;
1792 }
1793 }
1794#ifdef SHOW_SECRETS
1795 {
1796 int i;
1797 printf("cipher suite = 0x%02x\n",
1798 session->sslServer->options.cipherSuite);
1799 printf("server random: ");
1800 for (i = 0; i < RAN_LEN; i++)
1801 printf("%02x", session->sslServer->arrays->serverRandom[i]);
1802 printf("\n");
1803 }
1804#endif
1805 return 0;
1806}
1807
1808
1809/* Process normal Client Hello */
1810static int ProcessClientHello(const byte* input, int* sslBytes,
1811 SnifferSession* session, char* error)
1812{
1813 byte bLen;
1814 word16 len;
1815 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1816
1817#ifdef HAVE_SNI
1818 {
1819 byte name[MAX_SERVER_NAME];
1820 word32 nameSz = sizeof(name);
1821 int ret;
1822
1823 ret = wolfSSL_SNI_GetFromBuffer(
1824 input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
1825 *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
1826 WOLFSSL_SNI_HOST_NAME, name, &nameSz);
1827
1828 if (ret == WOLFSSL_SUCCESS) {
1829 NamedKey* namedKey;
1830
1831 if (nameSz >= sizeof(name))
1832 nameSz = sizeof(name) - 1;
1833 name[nameSz] = 0;
1834 wc_LockMutex(&session->context->namedKeysMutex);
1835 namedKey = session->context->namedKeys;
1836 while (namedKey != NULL) {
1837 if (nameSz == namedKey->nameSz &&
1838 XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
1839 if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
1840 namedKey->key, namedKey->keySz,
1841 WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) {
1842 wc_UnLockMutex(&session->context->namedKeysMutex);
1843 SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
1844 FATAL_ERROR_STATE);
1845 return -1;
1846 }
1847 break;
1848 }
1849 else
1850 namedKey = namedKey->next;
1851 }
1852 wc_UnLockMutex(&session->context->namedKeysMutex);
1853 }
1854 }
1855#endif
1856
1857 session->flags.clientHello = 1; /* don't process again */
1858
1859 /* make sure can read up to session len */
1860 if (toRead > *sslBytes) {
1861 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1862 return -1;
1863 }
1864
1865 /* skip, get negotiated one from server hello */
1866 input += VERSION_SZ;
1867 *sslBytes -= VERSION_SZ;
1868
1869 XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
1870 XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
1871
1872 input += RAN_LEN;
1873 *sslBytes -= RAN_LEN;
1874
1875 /* store session in case trying to resume */
1876 bLen = *input++;
1877 *sslBytes -= ENUM_LEN;
1878 if (bLen) {
1879 if (ID_LEN > *sslBytes) {
1880 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1881 return -1;
1882 }
1883 Trace(CLIENT_RESUME_TRY_STR);
1884 XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
1885 session->sslClient->options.haveSessionId = 1;
1886 }
1887#ifdef SHOW_SECRETS
1888 {
1889 int i;
1890 printf("client random: ");
1891 for (i = 0; i < RAN_LEN; i++)
1892 printf("%02x", session->sslServer->arrays->clientRandom[i]);
1893 printf("\n");
1894 }
1895#endif
1896
1897 input += bLen;
1898 *sslBytes -= bLen;
1899
1900 /* skip cipher suites */
1901 /* make sure can read len */
1902 if (SUITE_LEN > *sslBytes) {
1903 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1904 return -1;
1905 }
1906 len = (word16)((input[0] << 8) | input[1]);
1907 input += SUITE_LEN;
1908 *sslBytes -= SUITE_LEN;
1909 /* make sure can read suites + comp len */
1910 if (len + ENUM_LEN > *sslBytes) {
1911 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1912 return -1;
1913 }
1914 input += len;
1915 *sslBytes -= len;
1916
1917 /* skip compression */
1918 bLen = *input++;
1919 *sslBytes -= ENUM_LEN;
1920 /* make sure can read len */
1921 if (bLen > *sslBytes) {
1922 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1923 return -1;
1924 }
1925 input += bLen;
1926 *sslBytes -= bLen;
1927
1928 if (*sslBytes == 0) {
1929 /* no extensions */
1930 return 0;
1931 }
1932
1933 /* skip extensions until session ticket */
1934 /* make sure can read len */
1935 if (SUITE_LEN > *sslBytes) {
1936 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1937 return -1;
1938 }
1939 len = (word16)((input[0] << 8) | input[1]);
1940 input += SUITE_LEN;
1941 *sslBytes -= SUITE_LEN;
1942 /* make sure can read through all extensions */
1943 if (len > *sslBytes) {
1944 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1945 return -1;
1946 }
1947
1948 while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
1949 byte extType[EXT_TYPE_SZ];
1950 word16 extLen;
1951
1952 extType[0] = input[0];
1953 extType[1] = input[1];
1954 input += EXT_TYPE_SZ;
1955 *sslBytes -= EXT_TYPE_SZ;
1956
1957 extLen = (word16)((input[0] << 8) | input[1]);
1958 input += LENGTH_SZ;
1959 *sslBytes -= LENGTH_SZ;
1960
1961 /* make sure can read through individual extension */
1962 if (extLen > *sslBytes) {
1963 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1964 return -1;
1965 }
1966
1967 if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
1968
1969 /* make sure can read through ticket if there is a non blank one */
1970 if (extLen && extLen < ID_LEN) {
1971 SetError(CLIENT_HELLO_INPUT_STR, error, session,
1972 FATAL_ERROR_STATE);
1973 return -1;
1974 }
1975
1976 if (extLen) {
1977 if (session->ticketID == 0) {
1978 session->ticketID = (byte*)malloc(ID_LEN);
1979 if (session->ticketID == 0) {
1980 SetError(MEMORY_STR, error, session,
1981 FATAL_ERROR_STATE);
1982 return -1;
1983 }
1984 }
1985 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
1986 }
1987 }
1988
1989 input += extLen;
1990 *sslBytes -= extLen;
1991 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
1992 }
1993
1994 return 0;
1995}
1996
1997
1998/* Process Finished */
1999static int ProcessFinished(const byte* input, int size, int* sslBytes,
2000 SnifferSession* session, char* error)
2001{
2002 SSL* ssl;
2003 word32 inOutIdx = 0;
2004 int ret;
2005
2006 if (session->flags.side == WOLFSSL_SERVER_END)
2007 ssl = session->sslServer;
2008 else
2009 ssl = session->sslClient;
2010
2011 ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
2012 SNIFF);
2013 *sslBytes -= (int)inOutIdx;
2014
2015 if (ret < 0) {
2016 SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
2017 return ret;
2018 }
2019
2020 if (ret == 0 && session->flags.cached == 0) {
2021 if (session->sslServer->options.haveSessionId) {
2022 WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
2023 if (sess == NULL)
2024 AddSession(session->sslServer); /* don't re add */
2025 session->flags.cached = 1;
2026 }
2027 }
2028
2029 /* If receiving a finished message from one side, free the resources
2030 * from the other side's tracker. */
2031 if (session->flags.side == WOLFSSL_SERVER_END)
2032 FreeHandshakeResources(session->sslClient);
2033 else
2034 FreeHandshakeResources(session->sslServer);
2035
2036 return ret;
2037}
2038
2039
2040/* Process HandShake input */
2041static int DoHandShake(const byte* input, int* sslBytes,
2042 SnifferSession* session, char* error)
2043{
2044 byte type;
2045 int size;
2046 int ret = 0;
2047 int startBytes;
2048
2049 if (*sslBytes < HANDSHAKE_HEADER_SZ) {
2050 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
2051 return -1;
2052 }
2053 type = input[0];
2054 size = (input[1] << 16) | (input[2] << 8) | input[3];
2055
2056 input += HANDSHAKE_HEADER_SZ;
2057 *sslBytes -= HANDSHAKE_HEADER_SZ;
2058 startBytes = *sslBytes;
2059
2060 if (*sslBytes < size) {
2061 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
2062 return -1;
2063 }
2064
2065 /* A session's arrays are released when the handshake is completed. */
2066 if (session->sslServer->arrays == NULL &&
2067 session->sslClient->arrays == NULL) {
2068
2069 SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
2070 return -1;
2071 }
2072
2073#ifdef HAVE_EXTENDED_MASTER
2074 if (session->hash) {
2075 if (HashUpdate(session->hash, input, size) != 0) {
2076 SetError(EXTENDED_MASTER_HASH_STR, error,
2077 session, FATAL_ERROR_STATE);
2078 return -1;
2079 }
2080 }
2081#endif
2082
2083 switch (type) {
2084 case hello_verify_request:
2085 Trace(GOT_HELLO_VERIFY_STR);
2086 break;
2087 case hello_request:
2088 Trace(GOT_HELLO_REQUEST_STR);
2089 break;
2090 case session_ticket:
2091 Trace(GOT_SESSION_TICKET_STR);
2092 ret = ProcessSessionTicket(input, sslBytes, session, error);
2093 break;
2094 case server_hello:
2095 Trace(GOT_SERVER_HELLO_STR);
2096 ret = ProcessServerHello(size, input, sslBytes, session, error);
2097 break;
2098 case certificate_request:
2099 Trace(GOT_CERT_REQ_STR);
2100 break;
2101 case server_key_exchange:
2102 Trace(GOT_SERVER_KEY_EX_STR);
2103 /* can't know temp key passively */
2104 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
2105 ret = -1;
2106 break;
2107 case certificate:
2108 Trace(GOT_CERT_STR);
2109 break;
2110 case server_hello_done:
2111 Trace(GOT_SERVER_HELLO_DONE_STR);
2112 break;
2113 case finished:
2114 Trace(GOT_FINISHED_STR);
2115 ret = ProcessFinished(input, size, sslBytes, session, error);
2116 break;
2117 case client_hello:
2118 Trace(GOT_CLIENT_HELLO_STR);
2119 ret = ProcessClientHello(input, sslBytes, session, error);
2120 break;
2121 case client_key_exchange:
2122 Trace(GOT_CLIENT_KEY_EX_STR);
2123#ifdef HAVE_EXTENDED_MASTER
2124 if (session->flags.expectEms && session->hash != NULL) {
2125 if (HashCopy(session->sslServer->hsHashes,
2126 session->hash) == 0 &&
2127 HashCopy(session->sslClient->hsHashes,
2128 session->hash) == 0) {
2129
2130 session->sslServer->options.haveEMS = 1;
2131 session->sslClient->options.haveEMS = 1;
2132 }
2133 else {
2134 SetError(EXTENDED_MASTER_HASH_STR, error,
2135 session, FATAL_ERROR_STATE);
2136 ret = -1;
2137 }
2138 XMEMSET(session->hash, 0, sizeof(HsHashes));
2139 free(session->hash);
2140 session->hash = NULL;
2141 }
2142 else {
2143 session->sslServer->options.haveEMS = 0;
2144 session->sslClient->options.haveEMS = 0;
2145 }
2146#endif
2147 if (ret == 0)
2148 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
2149 break;
2150 case certificate_verify:
2151 Trace(GOT_CERT_VER_STR);
2152 break;
2153 case certificate_status:
2154 Trace(GOT_CERT_STATUS_STR);
2155 break;
2156 default:
2157 SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
2158 return -1;
2159 }
2160
2161 *sslBytes = startBytes - size; /* actual bytes of full process */
2162
2163 return ret;
2164}
2165
2166
2167/* Decrypt input into plain output, 0 on success */
2168static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
2169{
2170 int ret = 0;
2171
2172 (void)output;
2173 (void)input;
2174 (void)sz;
2175
2176 switch (ssl->specs.bulk_cipher_algorithm) {
2177 #ifdef BUILD_ARC4
2178 case wolfssl_rc4:
2179 wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
2180 break;
2181 #endif
2182
2183 #ifdef BUILD_DES3
2184 case wolfssl_triple_des:
2185 ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
2186 break;
2187 #endif
2188
2189 #ifdef BUILD_AES
2190 case wolfssl_aes:
2191 ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
2192 break;
2193 #endif
2194
2195 #ifdef HAVE_HC128
2196 case wolfssl_hc128:
2197 wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
2198 break;
2199 #endif
2200
2201 #ifdef BUILD_RABBIT
2202 case wolfssl_rabbit:
2203 wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
2204 break;
2205 #endif
2206
2207 #ifdef HAVE_CAMELLIA
2208 case wolfssl_camellia:
2209 wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
2210 break;
2211 #endif
2212
2213 #ifdef HAVE_IDEA
2214 case wolfssl_idea:
2215 wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
2216 break;
2217 #endif
2218
2219 #ifdef HAVE_AESGCM
2220 case wolfssl_aes_gcm:
2221 if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
2222 {
2223 /* scratch buffer, sniffer ignores auth tag*/
2224 byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
2225
2226 byte nonce[AESGCM_NONCE_SZ];
2227 XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
2228 XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
2229
2230 if (wc_AesGcmEncrypt(ssl->decrypt.aes,
2231 output,
2232 input + AESGCM_EXP_IV_SZ,
2233 sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
2234 nonce, AESGCM_NONCE_SZ,
2235 authTag, sizeof(authTag),
2236 NULL, 0) < 0) {
2237 Trace(BAD_DECRYPT);
2238 ret = -1;
2239 }
2240 ForceZero(nonce, AESGCM_NONCE_SZ);
2241 }
2242 else {
2243 Trace(BAD_DECRYPT_SIZE);
2244 ret = -1;
2245 }
2246 break;
2247 #endif
2248
2249 default:
2250 Trace(BAD_DECRYPT_TYPE);
2251 ret = -1;
2252 break;
2253 }
2254
2255 return ret;
2256}
2257
2258
2259/* Decrypt input message into output, adjust output steam if needed */
2260static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
2261 byte* output, int* error, int* advance)
2262{
2263 int ivExtra = 0;
2264
2265 int ret = Decrypt(ssl, output, input, sz);
2266 if (ret != 0) {
2267 *error = ret;
2268 return NULL;
2269 }
2270 ssl->keys.encryptSz = sz;
2271 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
2272 output += ssl->specs.block_size; /* go past TLSv1.1 IV */
2273 ivExtra = ssl->specs.block_size;
2274 *advance = ssl->specs.block_size;
2275 }
2276
2277 if (ssl->specs.cipher_type == aead) {
2278 *advance = ssl->specs.aead_mac_size;
2279 ssl->keys.padSz = ssl->specs.aead_mac_size;
2280 }
2281 else
2282 ssl->keys.padSz = ssl->specs.hash_size;
2283
2284 if (ssl->specs.cipher_type == block)
2285 ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
2286
2287 return output;
2288}
2289
2290
2291/* remove session from table, use rowHint if no info (means we have a lock) */
2292static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
2293 TcpInfo* tcpInfo, word32 rowHint)
2294{
2295 SnifferSession* previous = 0;
2296 SnifferSession* current;
2297 word32 row = rowHint;
2298 int haveLock = 0;
2299
2300 if (ipInfo && tcpInfo)
2301 row = SessionHash(ipInfo, tcpInfo);
2302 else
2303 haveLock = 1;
2304
2305 assert(row <= HASH_SIZE);
2306 Trace(REMOVE_SESSION_STR);
2307
2308 if (!haveLock)
2309 wc_LockMutex(&SessionMutex);
2310
2311 current = SessionTable[row];
2312
2313 while (current) {
2314 if (current == session) {
2315 if (previous)
2316 previous->next = current->next;
2317 else
2318 SessionTable[row] = current->next;
2319 FreeSnifferSession(session);
2320 TraceRemovedSession();
2321 break;
2322 }
2323 previous = current;
2324 current = current->next;
2325 }
2326
2327 if (!haveLock)
2328 wc_UnLockMutex(&SessionMutex);
2329}
2330
2331
2332/* Remove stale sessions from the Session Table, have a lock */
2333static void RemoveStaleSessions(void)
2334{
2335 word32 i;
2336 SnifferSession* session;
2337
2338 for (i = 0; i < HASH_SIZE; i++) {
2339 session = SessionTable[i];
2340 while (session) {
2341 SnifferSession* next = session->next;
2342 if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
2343 TraceStaleSession();
2344 RemoveSession(session, NULL, NULL, i);
2345 }
2346 session = next;
2347 }
2348 }
2349}
2350
2351
2352/* Create a new Sniffer Session */
2353static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2354 char* error)
2355{
2356 SnifferSession* session = 0;
2357 int row;
2358
2359 Trace(NEW_SESSION_STR);
2360 /* create a new one */
2361 session = (SnifferSession*)malloc(sizeof(SnifferSession));
2362 if (session == NULL) {
2363 SetError(MEMORY_STR, error, NULL, 0);
2364 return 0;
2365 }
2366 InitSession(session);
2367#ifdef HAVE_EXTENDED_MASTER
2368 {
2369 HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
2370 if (newHash == NULL) {
2371 SetError(MEMORY_STR, error, NULL, 0);
2372 free(session);
2373 return 0;
2374 }
2375 if (HashInit(newHash) != 0) {
2376 SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
2377 free(session);
2378 return 0;
2379 }
2380 session->hash = newHash;
2381 }
2382#endif
2383 session->server = ipInfo->dst;
2384 session->client = ipInfo->src;
2385 session->srvPort = (word16)tcpInfo->dstPort;
2386 session->cliPort = (word16)tcpInfo->srcPort;
2387 session->cliSeqStart = tcpInfo->sequence;
2388 session->cliExpected = 1; /* relative */
2389 session->lastUsed= time(NULL);
2390
2391 session->context = GetSnifferServer(ipInfo, tcpInfo);
2392 if (session->context == NULL) {
2393 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
2394 free(session);
2395 return 0;
2396 }
2397
2398 session->sslServer = SSL_new(session->context->ctx);
2399 if (session->sslServer == NULL) {
2400 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2401 free(session);
2402 return 0;
2403 }
2404 session->sslClient = SSL_new(session->context->ctx);
2405 if (session->sslClient == NULL) {
2406 SSL_free(session->sslServer);
2407 session->sslServer = 0;
2408
2409 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2410 free(session);
2411 return 0;
2412 }
2413 /* put server back into server mode */
2414 session->sslServer->options.side = WOLFSSL_SERVER_END;
2415
2416 row = SessionHash(ipInfo, tcpInfo);
2417
2418 /* add it to the session table */
2419 wc_LockMutex(&SessionMutex);
2420
2421 session->next = SessionTable[row];
2422 SessionTable[row] = session;
2423
2424 SessionCount++;
2425
2426 if ( (SessionCount % HASH_SIZE) == 0) {
2427 TraceFindingStale();
2428 RemoveStaleSessions();
2429 }
2430
2431 wc_UnLockMutex(&SessionMutex);
2432
2433 /* determine headed side */
2434 if (ipInfo->dst == session->context->server &&
2435 tcpInfo->dstPort == session->context->port)
2436 session->flags.side = WOLFSSL_SERVER_END;
2437 else
2438 session->flags.side = WOLFSSL_CLIENT_END;
2439
2440 return session;
2441}
2442
2443
2444#ifdef OLD_HELLO_ALLOWED
2445
2446/* Process Old Client Hello Input */
2447static int DoOldHello(SnifferSession* session, const byte* sslFrame,
2448 int* rhSize, int* sslBytes, char* error)
2449{
2450 const byte* input = sslFrame;
2451 byte b0, b1;
2452 word32 idx = 0;
2453 int ret;
2454
2455 Trace(GOT_OLD_CLIENT_HELLO_STR);
2456 session->flags.clientHello = 1; /* don't process again */
2457 b0 = *input++;
2458 b1 = *input++;
2459 *sslBytes -= 2;
2460 *rhSize = ((b0 & 0x7f) << 8) | b1;
2461
2462 if (*rhSize > *sslBytes) {
2463 SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
2464 return -1;
2465 }
2466
2467 ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
2468 (word16)*rhSize);
2469 if (ret < 0 && ret != MATCH_SUITE_ERROR) {
2470 SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
2471 return -1;
2472 }
2473
2474 Trace(OLD_CLIENT_OK_STR);
2475 XMEMCPY(session->sslClient->arrays->clientRandom,
2476 session->sslServer->arrays->clientRandom, RAN_LEN);
2477
2478 *sslBytes -= *rhSize;
2479 return 0;
2480}
2481
2482#endif /* OLD_HELLO_ALLOWED */
2483
2484
2485#if 0
2486/* Calculate the TCP checksum, see RFC 1071 */
2487/* return 0 for success, -1 on error */
2488/* can be called from decode() with
2489 TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
2490 could also add a 64bit version if type available and using this
2491*/
2492int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
2493 const byte* packet)
2494{
2495 TcpPseudoHdr pseudo;
2496 int count = PSEUDO_HDR_SZ;
2497 const word16* data = (word16*)&pseudo;
2498 word32 sum = 0;
2499 word16 checksum;
2500
2501 pseudo.src = ipInfo->src;
2502 pseudo.dst = ipInfo->dst;
2503 pseudo.rsv = 0;
2504 pseudo.protocol = TCP_PROTO;
2505 pseudo.length = htons(tcpInfo->length + dataLen);
2506
2507 /* pseudo header sum */
2508 while (count >= 2) {
2509 sum += *data++;
2510 count -= 2;
2511 }
2512
2513 count = tcpInfo->length + dataLen;
2514 data = (word16*)packet;
2515
2516 /* main sum */
2517 while (count > 1) {
2518 sum += *data++;
2519 count -=2;
2520 }
2521
2522 /* get left-over, if any */
2523 packet = (byte*)data;
2524 if (count > 0) {
2525 sum += *packet;
2526 }
2527
2528 /* fold 32bit sum into 16 bits */
2529 while (sum >> 16)
2530 sum = (sum & 0xffff) + (sum >> 16);
2531
2532 checksum = (word16)~sum;
2533 /* checksum should now equal 0, since included already calcd checksum */
2534 /* field, but tcp checksum offloading could negate calculation */
2535 if (checksum == 0)
2536 return 0;
2537 return -1;
2538}
2539#endif
2540
2541
2542/* Check IP and TCP headers, set payload */
2543/* returns 0 on success, -1 on error */
2544static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
2545 int length, const byte** sslFrame, int* sslBytes, char* error)
2546{
2547 TraceHeader();
2548 TracePacket();
2549
2550 /* ip header */
2551 if (length < IP_HDR_SZ) {
2552 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2553 return -1;
2554 }
2555 if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
2556 return -1;
2557
2558 /* tcp header */
2559 if (length < (ipInfo->length + TCP_HDR_SZ)) {
2560 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2561 return -1;
2562 }
2563 if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
2564 return -1;
2565
2566 /* setup */
2567 *sslFrame = packet + ipInfo->length + tcpInfo->length;
2568 if (*sslFrame > packet + length) {
2569 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2570 return -1;
2571 }
2572 *sslBytes = (int)(packet + length - *sslFrame);
2573
2574 return 0;
2575}
2576
2577
2578/* Create or Find existing session */
2579/* returns 0 on success (continue), -1 on error, 1 on success (end) */
2580static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
2581 SnifferSession** session, char* error)
2582{
2583 /* create a new SnifferSession on client SYN */
2584 if (tcpInfo->syn && !tcpInfo->ack) {
2585 TraceClientSyn(tcpInfo->sequence);
2586 *session = CreateSession(ipInfo, tcpInfo, error);
2587 if (*session == NULL) {
2588 *session = GetSnifferSession(ipInfo, tcpInfo);
2589 /* already had existing, so OK */
2590 if (*session)
2591 return 1;
2592
2593 SetError(MEMORY_STR, error, NULL, 0);
2594 return -1;
2595 }
2596 return 1;
2597 }
2598 /* get existing sniffer session */
2599 else {
2600 *session = GetSnifferSession(ipInfo, tcpInfo);
2601 if (*session == NULL) {
2602 /* don't worry about extraneous RST or duplicate FINs */
2603 if (tcpInfo->fin || tcpInfo->rst)
2604 return 1;
2605 /* don't worry about duplicate ACKs either */
2606 if (sslBytes == 0 && tcpInfo->ack)
2607 return 1;
2608
2609 SetError(BAD_SESSION_STR, error, NULL, 0);
2610 return -1;
2611 }
2612 }
2613 return 0;
2614}
2615
2616
2617/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
2618static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
2619 int* bytesLeft)
2620{
2621 PacketBuffer* pb;
2622
2623 int added = end - *begin + 1;
2624 assert(*begin <= end);
2625
2626 pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
2627 if (pb == NULL) return NULL;
2628
2629 pb->next = 0;
2630 pb->begin = *begin;
2631 pb->end = end;
2632 pb->data = (byte*)malloc(added);
2633
2634 if (pb->data == NULL) {
2635 free(pb);
2636 return NULL;
2637 }
2638 XMEMCPY(pb->data, data, added);
2639
2640 *bytesLeft -= added;
2641 *begin = pb->end + 1;
2642
2643 return pb;
2644}
2645
2646
2647/* Add sslFrame to Reassembly List */
2648/* returns 1 (end) on success, -1, on error */
2649static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
2650 int sslBytes, SnifferSession* session, char* error)
2651{
2652 PacketBuffer* add;
2653 PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
2654 &session->cliReassemblyList: &session->srvReassemblyList;
2655 PacketBuffer* curr = *front;
2656 PacketBuffer* prev = curr;
2657
2658 word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
2659 &session->cliReassemblyMemory : &session->srvReassemblyMemory;
2660 word32 startSeq = seq;
2661 word32 added;
2662 int bytesLeft = sslBytes; /* could be overlapping fragment */
2663
2664 /* if list is empty add full frame to front */
2665 if (!curr) {
2666 if (MaxRecoveryMemory != -1 &&
2667 (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
2668 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
2669 return -1;
2670 }
2671 add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
2672 if (add == NULL) {
2673 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2674 return -1;
2675 }
2676 *front = add;
2677 *reassemblyMemory += sslBytes;
2678 return 1;
2679 }
2680
2681 /* add to front if before current front, up to next->begin */
2682 if (seq < curr->begin) {
2683 word32 end = seq + sslBytes - 1;
2684
2685 if (end >= curr->begin)
2686 end = curr->begin - 1;
2687
2688 if (MaxRecoveryMemory -1 &&
2689 (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
2690 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
2691 return -1;
2692 }
2693 add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
2694 if (add == NULL) {
2695 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2696 return -1;
2697 }
2698 add->next = curr;
2699 *front = add;
2700 *reassemblyMemory += sslBytes;
2701 }
2702
2703 /* while we have bytes left, try to find a gap to fill */
2704 while (bytesLeft > 0) {
2705 /* get previous packet in list */
2706 while (curr && (seq >= curr->begin)) {
2707 prev = curr;
2708 curr = curr->next;
2709 }
2710
2711 /* don't add duplicate data */
2712 if (prev->end >= seq) {
2713 if ( (seq + bytesLeft - 1) <= prev->end)
2714 return 1;
2715 seq = prev->end + 1;
2716 bytesLeft = startSeq + sslBytes - seq;
2717 }
2718
2719 if (!curr)
2720 /* we're at the end */
2721 added = bytesLeft;
2722 else
2723 /* we're in between two frames */
2724 added = min((word32)bytesLeft, curr->begin - seq);
2725
2726 /* data already there */
2727 if (added == 0)
2728 continue;
2729
2730 if (MaxRecoveryMemory != -1 &&
2731 (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
2732 SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
2733 return -1;
2734 }
2735 add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
2736 &bytesLeft);
2737 if (add == NULL) {
2738 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2739 return -1;
2740 }
2741 add->next = prev->next;
2742 prev->next = add;
2743 *reassemblyMemory += added;
2744 }
2745 return 1;
2746}
2747
2748
2749/* Add out of order FIN capture */
2750/* returns 1 for success (end) */
2751static int AddFinCapture(SnifferSession* session, word32 sequence)
2752{
2753 if (session->flags.side == WOLFSSL_SERVER_END) {
2754 if (session->finCaputre.cliCounted == 0)
2755 session->finCaputre.cliFinSeq = sequence;
2756 }
2757 else {
2758 if (session->finCaputre.srvCounted == 0)
2759 session->finCaputre.srvFinSeq = sequence;
2760 }
2761 return 1;
2762}
2763
2764
2765/* Adjust incoming sequence based on side */
2766/* returns 0 on success (continue), -1 on error, 1 on success (end) */
2767static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
2768 int* sslBytes, const byte** sslFrame, char* error)
2769{
2770 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
2771 session->cliSeqStart :session->srvSeqStart;
2772 word32 real = tcpInfo->sequence - seqStart;
2773 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2774 &session->cliExpected : &session->srvExpected;
2775 PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
2776 session->cliReassemblyList : session->srvReassemblyList;
2777 byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
2778 session->flags.srvSkipPartial :
2779 session->flags.cliSkipPartial;
2780
2781 /* handle rollover of sequence */
2782 if (tcpInfo->sequence < seqStart)
2783 real = 0xffffffffU - seqStart + tcpInfo->sequence;
2784
2785 TraceRelativeSequence(*expected, real);
2786
2787 if (real < *expected) {
2788 Trace(DUPLICATE_STR);
2789 if (real + *sslBytes > *expected) {
2790 int overlap = *expected - real;
2791 Trace(OVERLAP_DUPLICATE_STR);
2792
2793 /* adjust to expected, remove duplicate */
2794 *sslFrame += overlap;
2795 *sslBytes -= overlap;
2796
2797 /* The following conditional block is duplicated below. It is the
2798 * same action but for a different setup case. If changing this
2799 * block be sure to also update the block below. */
2800 if (reassemblyList) {
2801 word32 newEnd = *expected + *sslBytes;
2802
2803 if (newEnd > reassemblyList->begin) {
2804 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
2805
2806 /* remove bytes already on reassembly list */
2807 *sslBytes -= newEnd - reassemblyList->begin;
2808 }
2809 if (newEnd > reassemblyList->end) {
2810 Trace(OVERLAP_REASSEMBLY_END_STR);
2811
2812 /* may be past reassembly list end (could have more on list)
2813 so try to add what's past the front->end */
2814 AddToReassembly(session->flags.side, reassemblyList->end +1,
2815 *sslFrame + reassemblyList->end - *expected + 1,
2816 newEnd - reassemblyList->end, session, error);
2817 }
2818 }
2819 }
2820 else
2821 return 1;
2822 }
2823 else if (real > *expected) {
2824 Trace(OUT_OF_ORDER_STR);
2825 if (*sslBytes > 0) {
2826 int addResult = AddToReassembly(session->flags.side, real,
2827 *sslFrame, *sslBytes, session, error);
2828 if (skipPartial) {
2829 *sslBytes = 0;
2830 return 0;
2831 }
2832 else
2833 return addResult;
2834 }
2835 else if (tcpInfo->fin)
2836 return AddFinCapture(session, real);
2837 }
2838 else if (*sslBytes > 0) {
2839 if (skipPartial) {
2840 AddToReassembly(session->flags.side, real,
2841 *sslFrame, *sslBytes, session, error);
2842 *expected += *sslBytes;
2843 *sslBytes = 0;
2844 if (tcpInfo->fin)
2845 *expected += 1;
2846 return 0;
2847 }
2848 /* The following conditional block is duplicated above. It is the
2849 * same action but for a different setup case. If changing this
2850 * block be sure to also update the block above. */
2851 else if (reassemblyList) {
2852 word32 newEnd = *expected + *sslBytes;
2853
2854 if (newEnd > reassemblyList->begin) {
2855 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
2856
2857 /* remove bytes already on reassembly list */
2858 *sslBytes -= newEnd - reassemblyList->begin;
2859 }
2860 if (newEnd > reassemblyList->end) {
2861 Trace(OVERLAP_REASSEMBLY_END_STR);
2862
2863 /* may be past reassembly list end (could have more on list)
2864 so try to add what's past the front->end */
2865 AddToReassembly(session->flags.side, reassemblyList->end +1,
2866 *sslFrame + reassemblyList->end - *expected + 1,
2867 newEnd - reassemblyList->end, session, error);
2868 }
2869 }
2870 }
2871 /* got expected sequence */
2872 *expected += *sslBytes;
2873 if (tcpInfo->fin)
2874 *expected += 1;
2875
2876 return 0;
2877}
2878
2879
2880static int FindNextRecordInAssembly(SnifferSession* session,
2881 const byte** sslFrame, int* sslBytes,
2882 const byte** end, char* error)
2883{
2884 PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
2885 &session->cliReassemblyList :
2886 &session->srvReassemblyList;
2887 PacketBuffer* curr = *front;
2888 PacketBuffer* prev = NULL;
2889 byte* skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
2890 &session->flags.srvSkipPartial :
2891 &session->flags.cliSkipPartial;
2892 word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
2893 &session->cliReassemblyMemory :
2894 &session->srvReassemblyMemory;
2895 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
2896 session->sslServer :
2897 session->sslClient;
2898 ProtocolVersion pv = ssl->version;
2899 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2900 &session->cliExpected :
2901 &session->srvExpected;
2902
2903 while (curr != NULL) {
2904 *expected = curr->end + 1;
2905
2906 if (curr->data[0] == application_data &&
2907 curr->data[1] == pv.major &&
2908 curr->data[2] == pv.minor) {
2909
2910 if (ssl->buffers.inputBuffer.length > 0)
2911 Trace(DROPPING_PARTIAL_RECORD);
2912
2913 *sslBytes = curr->end - curr->begin + 1;
2914 if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
2915 if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
2916 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2917 return -1;
2918 }
2919 }
2920
2921 XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
2922
2923 *front = curr->next;
2924 *reassemblyMemory -= *sslBytes;
2925 FreePacketBuffer(curr);
2926
2927 ssl->buffers.inputBuffer.length = *sslBytes;
2928 *sslFrame = ssl->buffers.inputBuffer.buffer;
2929 *end = *sslFrame + *sslBytes;
2930 *skipPartial = 0;
2931
2932 return 0;
2933 }
2934 else if (ssl->specs.cipher_type == block) {
2935 if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
2936#ifdef BUILD_AES
2937 wc_AesSetIV(ssl->decrypt.aes,
2938 curr->data + curr->end - curr->begin
2939 - ssl->specs.block_size + 1);
2940#endif
2941 }
2942 else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
2943#ifdef BUILD_DES3
2944 wc_Des3_SetIV(ssl->decrypt.des3,
2945 curr->data + curr->end - curr->begin
2946 - ssl->specs.block_size + 1);
2947#endif
2948 }
2949 }
2950
2951 Trace(DROPPING_LOST_FRAG_STR);
2952 prev = curr;
2953 curr = curr->next;
2954 *reassemblyMemory -= (prev->end - prev->begin + 1);
2955 FreePacketBuffer(prev);
2956 }
2957
2958 *front = curr;
2959
2960 return 0;
2961}
2962
2963
2964static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
2965{
2966 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2967 &session->srvExpected : &session->cliExpected;
2968 PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
2969 session->srvReassemblyList :
2970 session->cliReassemblyList;
2971 byte* skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
2972 &session->flags.srvSkipPartial :
2973 &session->flags.cliSkipPartial;
2974
2975 *skipPartial = 1;
2976 if (list != NULL)
2977 *expected = list->begin;
2978 else {
2979 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
2980 session->srvSeqStart : session->cliSeqStart;
2981 word32 real = tcpInfo->ackNumber - seqStart;
2982
2983 *expected = real;
2984 }
2985
2986 return 1;
2987}
2988
2989
2990/* Check latest ack number for missing packets
2991 return 0 ok, <0 on error */
2992static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
2993{
2994 if (tcpInfo->ack) {
2995 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
2996 session->srvSeqStart :session->cliSeqStart;
2997 word32 real = tcpInfo->ackNumber - seqStart;
2998 word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2999 session->srvExpected : session->cliExpected;
3000
3001 /* handle rollover of sequence */
3002 if (tcpInfo->ackNumber < seqStart)
3003 real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
3004
3005 TraceAck(real, expected);
3006
3007 if (real > expected)
3008 return -1; /* we missed a packet, ACKing data we never saw */
3009 }
3010 return 0;
3011}
3012
3013
3014/* Check TCP Sequence status */
3015/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3016static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
3017 SnifferSession* session, int* sslBytes,
3018 const byte** sslFrame, char* error)
3019{
3020 int actualLen;
3021 byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
3022 &session->flags.cliAckFault :
3023 &session->flags.srvAckFault;
3024
3025 /* init SEQ from server to client */
3026 if (tcpInfo->syn && tcpInfo->ack) {
3027 session->srvSeqStart = tcpInfo->sequence;
3028 session->srvExpected = 1;
3029 TraceServerSyn(tcpInfo->sequence);
3030 return 1;
3031 }
3032
3033 /* adjust potential ethernet trailer */
3034 actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
3035 if (*sslBytes > actualLen) {
3036 *sslBytes = actualLen;
3037 }
3038
3039 TraceSequence(tcpInfo->sequence, *sslBytes);
3040 if (CheckAck(tcpInfo, session) < 0) {
3041 if (!RecoveryEnabled) {
3042 UpdateMissedDataSessions();
3043 SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
3044 return -1;
3045 }
3046 else {
3047 SetError(ACK_MISSED_STR, error, session, 0);
3048 if (*ackFault == 0) {
3049 *ackFault = 1;
3050 UpdateMissedDataSessions();
3051 }
3052 return FixSequence(tcpInfo, session);
3053 }
3054 }
3055
3056 if (*ackFault) {
3057 Trace(CLEAR_ACK_FAULT);
3058 *ackFault = 0;
3059 }
3060
3061 return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
3062}
3063
3064
3065/* Check Status before record processing */
3066/* returns 0 on success (continue), -1 on error, 1 on success (end) */
3067static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
3068 const byte** sslFrame, SnifferSession** session,
3069 int* sslBytes, const byte** end, char* error)
3070{
3071 word32 length;
3072 SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
3073 (*session)->sslServer : (*session)->sslClient;
3074 byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
3075 (*session)->flags.srvSkipPartial :
3076 (*session)->flags.cliSkipPartial;
3077 /* remove SnifferSession on 2nd FIN or RST */
3078 if (tcpInfo->fin || tcpInfo->rst) {
3079 /* flag FIN and RST */
3080 if (tcpInfo->fin)
3081 (*session)->flags.finCount += 1;
3082 else if (tcpInfo->rst)
3083 (*session)->flags.finCount += 2;
3084
3085 if ((*session)->flags.finCount >= 2) {
3086 RemoveSession(*session, ipInfo, tcpInfo, 0);
3087 *session = NULL;
3088 return 1;
3089 }
3090 }
3091
3092 if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
3093 SetError(FATAL_ERROR_STR, error, NULL, 0);
3094 return -1;
3095 }
3096
3097 if (skipPartial) {
3098 if (FindNextRecordInAssembly(*session,
3099 sslFrame, sslBytes, end, error) < 0) {
3100 return -1;
3101 }
3102 }
3103
3104 if (*sslBytes == 0) {
3105 Trace(NO_DATA_STR);
3106 return 1;
3107 }
3108
3109 /* if current partial data, add to end of partial */
3110 /* if skipping, the data is already at the end of partial */
3111 if ( !skipPartial &&
3112 (length = ssl->buffers.inputBuffer.length) ) {
3113 Trace(PARTIAL_ADD_STR);
3114
3115 if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
3116 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
3117 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
3118 return -1;
3119 }
3120 }
3121 XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
3122 *sslBytes += length;
3123 ssl->buffers.inputBuffer.length = *sslBytes;
3124 *sslFrame = ssl->buffers.inputBuffer.buffer;
3125 *end = *sslFrame + *sslBytes;
3126 }
3127
3128 if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
3129 /* Sanity check the packet for an old style client hello. */
3130 int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
3131
3132 if ((rhSize <= (*sslBytes - 2)) &&
3133 (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
3134#ifdef OLD_HELLO_ALLOWED
3135 int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
3136 if (ret < 0)
3137 return -1; /* error already set */
3138 if (*sslBytes <= 0)
3139 return 1;
3140#endif
3141 }
3142 else {
3143#ifdef STARTTLS_ALLOWED
3144 return 1;
3145#endif
3146 }
3147 }
3148
3149 return 0;
3150}
3151
3152
3153/* See if input on the reassembly list is ready for consuming */
3154/* returns 1 for TRUE, 0 for FALSE */
3155static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
3156 int* sslBytes, const byte** end, char* error)
3157{
3158 /* sequence and reassembly based on from, not to */
3159 int moreInput = 0;
3160 PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
3161 &session->cliReassemblyList : &session->srvReassemblyList;
3162 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
3163 &session->cliExpected : &session->srvExpected;
3164 /* buffer is on receiving end */
3165 word32* length = (session->flags.side == WOLFSSL_SERVER_END) ?
3166 &session->sslServer->buffers.inputBuffer.length :
3167 &session->sslClient->buffers.inputBuffer.length;
3168 byte** myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
3169 &session->sslServer->buffers.inputBuffer.buffer :
3170 &session->sslClient->buffers.inputBuffer.buffer;
3171 word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
3172 &session->sslServer->buffers.inputBuffer.bufferSize :
3173 &session->sslClient->buffers.inputBuffer.bufferSize;
3174 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
3175 session->sslServer : session->sslClient;
3176 word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
3177 &session->cliReassemblyMemory : &session->srvReassemblyMemory;
3178
3179 while (*front && ((*front)->begin == *expected) ) {
3180 word32 room = *bufferSize - *length;
3181 word32 packetLen = (*front)->end - (*front)->begin + 1;
3182
3183 if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
3184 if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
3185 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3186 return 0;
3187 }
3188 room = *bufferSize - *length; /* bufferSize is now bigger */
3189 }
3190
3191 if (packetLen <= room) {
3192 PacketBuffer* del = *front;
3193 byte* buf = *myBuffer;
3194
3195 XMEMCPY(&buf[*length], (*front)->data, packetLen);
3196 *length += packetLen;
3197 *expected += packetLen;
3198
3199 /* remove used packet */
3200 *front = (*front)->next;
3201
3202 *reassemblyMemory -= packetLen;
3203 FreePacketBuffer(del);
3204
3205 moreInput = 1;
3206 }
3207 else
3208 break;
3209 }
3210 if (moreInput) {
3211 *sslFrame = *myBuffer;
3212 *sslBytes = *length;
3213 *end = *myBuffer + *length;
3214 }
3215 return moreInput;
3216}
3217
3218
3219
3220/* Process Message(s) from sslFrame */
3221/* return Number of bytes on success, 0 for no data yet, and -1 on error */
3222static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
3223 int sslBytes, byte** data, const byte* end,
3224 char* error)
3225{
3226 const byte* sslBegin = sslFrame;
3227 const byte* recordEnd; /* end of record indicator */
3228 const byte* inRecordEnd; /* indicator from input stream not decrypt */
3229 RecordLayerHeader rh;
3230 int rhSize = 0;
3231 int ret;
3232 int errCode = 0;
3233 int decoded = 0; /* bytes stored for user in data */
3234 int notEnough; /* notEnough bytes yet flag */
3235 int decrypted = 0; /* was current msg decrypted */
3236 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
3237 session->sslServer : session->sslClient;
3238doMessage:
3239 notEnough = 0;
3240 if (sslBytes < 0) {
3241 SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
3242 return -1;
3243 }
3244 if (sslBytes >= RECORD_HEADER_SZ) {
3245 if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
3246 SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
3247 return -1;
3248 }
3249 }
3250 else
3251 notEnough = 1;
3252
3253 if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
3254 /* don't have enough input yet to process full SSL record */
3255 Trace(PARTIAL_INPUT_STR);
3256
3257 /* store partial if not there already or we advanced */
3258 if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
3259 if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
3260 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
3261 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3262 return -1;
3263 }
3264 }
3265 XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
3266 ssl->buffers.inputBuffer.length = sslBytes;
3267 }
3268 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
3269 goto doMessage;
3270 return decoded;
3271 }
3272 sslFrame += RECORD_HEADER_SZ;
3273 sslBytes -= RECORD_HEADER_SZ;
3274 recordEnd = sslFrame + rhSize; /* may have more than one record */
3275 inRecordEnd = recordEnd;
3276
3277 /* decrypt if needed */
3278 if ((session->flags.side == WOLFSSL_SERVER_END &&
3279 session->flags.serverCipherOn)
3280 || (session->flags.side == WOLFSSL_CLIENT_END &&
3281 session->flags.clientCipherOn)) {
3282 int ivAdvance = 0; /* TLSv1.1 advance amount */
3283 if (ssl->decrypt.setup != 1) {
3284 SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
3285 return -1;
3286 }
3287 if (CheckAvailableSize(ssl, rhSize) < 0) {
3288 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
3289 return -1;
3290 }
3291 sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
3292 ssl->buffers.outputBuffer.buffer, &errCode,
3293 &ivAdvance);
3294 recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so
3295 should recordEnd */
3296 decrypted = 1;
3297 if (errCode != 0) {
3298 SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
3299 return -1;
3300 }
3301 }
3302
3303doPart:
3304
3305 switch ((enum ContentType)rh.type) {
3306 case handshake:
3307 {
3308 int startIdx = sslBytes;
3309 int used;
3310
3311 Trace(GOT_HANDSHAKE_STR);
3312 ret = DoHandShake(sslFrame, &sslBytes, session, error);
3313 if (ret != 0) {
3314 if (session->flags.fatalError == 0)
3315 SetError(BAD_HANDSHAKE_STR, error, session,
3316 FATAL_ERROR_STATE);
3317 return -1;
3318 }
3319
3320 /* DoHandShake now fully decrements sslBytes to remaining */
3321 used = startIdx - sslBytes;
3322 sslFrame += used;
3323 if (decrypted)
3324 sslFrame += ssl->keys.padSz;
3325 }
3326 break;
3327 case change_cipher_spec:
3328 if (session->flags.side == WOLFSSL_SERVER_END)
3329 session->flags.serverCipherOn = 1;
3330 else
3331 session->flags.clientCipherOn = 1;
3332 Trace(GOT_CHANGE_CIPHER_STR);
3333 ssl->options.handShakeState = HANDSHAKE_DONE;
3334 ssl->options.handShakeDone = 1;
3335
3336 sslFrame += 1;
3337 sslBytes -= 1;
3338
3339 break;
3340 case application_data:
3341 Trace(GOT_APP_DATA_STR);
3342 {
3343 word32 inOutIdx = 0;
3344
3345 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
3346 if (ret == 0) {
3347 ret = ssl->buffers.clearOutputBuffer.length;
3348 TraceGotData(ret);
3349 if (ret) { /* may be blank message */
3350 byte* tmpData; /* don't leak on realloc free */
3351 /* add an extra byte at end of allocation in case user
3352 * wants to null terminate plaintext */
3353 tmpData = (byte*)realloc(*data, decoded + ret + 1);
3354 if (tmpData == NULL) {
3355 ForceZero(*data, decoded);
3356 free(*data);
3357 *data = NULL;
3358 SetError(MEMORY_STR, error, session,
3359 FATAL_ERROR_STATE);
3360 return -1;
3361 }
3362 *data = tmpData;
3363 XMEMCPY(*data + decoded,
3364 ssl->buffers.clearOutputBuffer.buffer, ret);
3365 TraceAddedData(ret, decoded);
3366 decoded += ret;
3367 ssl->buffers.clearOutputBuffer.length = 0;
3368 }
3369 }
3370 else {
3371 SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
3372 return -1;
3373 }
3374 if (ssl->buffers.outputBuffer.dynamicFlag)
3375 ShrinkOutputBuffer(ssl);
3376
3377 sslFrame += inOutIdx;
3378 sslBytes -= inOutIdx;
3379 }
3380 break;
3381 case alert:
3382 Trace(GOT_ALERT_STR);
3383 sslFrame += rhSize;
3384 sslBytes -= rhSize;
3385 break;
3386 case no_type:
3387 default:
3388 SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
3389 return -1;
3390 }
3391
3392 /* do we have another msg in record ? */
3393 if (sslFrame < recordEnd) {
3394 Trace(ANOTHER_MSG_STR);
3395 goto doPart;
3396 }
3397
3398 /* back to input stream instead of potential decrypt buffer */
3399 recordEnd = inRecordEnd;
3400
3401 /* do we have more records ? */
3402 if (recordEnd < end) {
3403 Trace(ANOTHER_MSG_STR);
3404 sslFrame = recordEnd;
3405 sslBytes = (int)(end - recordEnd);
3406 goto doMessage;
3407 }
3408
3409 /* clear used input */
3410 ssl->buffers.inputBuffer.length = 0;
3411
3412 /* could have more input ready now */
3413 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
3414 goto doMessage;
3415
3416 if (ssl->buffers.inputBuffer.dynamicFlag)
3417 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
3418
3419 return decoded;
3420}
3421
3422
3423/* See if we need to process any pending FIN captures */
3424static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
3425 SnifferSession* session)
3426{
3427 if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
3428 session->cliExpected) {
3429 if (session->finCaputre.cliCounted == 0) {
3430 session->flags.finCount += 1;
3431 session->finCaputre.cliCounted = 1;
3432 TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
3433 }
3434 }
3435
3436 if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
3437 session->srvExpected) {
3438 if (session->finCaputre.srvCounted == 0) {
3439 session->flags.finCount += 1;
3440 session->finCaputre.srvCounted = 1;
3441 TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
3442 }
3443 }
3444
3445 if (session->flags.finCount >= 2)
3446 RemoveSession(session, ipInfo, tcpInfo, 0);
3447}
3448
3449
3450/* If session is in fatal error state free resources now
3451 return true if removed, 0 otherwise */
3452static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
3453 SnifferSession* session, char* error)
3454{
3455 if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
3456 RemoveSession(session, ipInfo, tcpInfo, 0);
3457 SetError(FATAL_ERROR_STR, error, NULL, 0);
3458 return 1;
3459 }
3460 return 0;
3461}
3462
3463
3464/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
3465/* returns Number of bytes on success, 0 for no data yet, and -1 on error */
3466int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
3467{
3468 TcpInfo tcpInfo;
3469 IpInfo ipInfo;
3470 const byte* sslFrame;
3471 const byte* end = packet + length;
3472 int sslBytes; /* ssl bytes unconsumed */
3473 int ret;
3474 SnifferSession* session = 0;
3475
3476 if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
3477 error) != 0)
3478 return -1;
3479
3480 ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
3481 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
3482 else if (ret == -1) return -1;
3483 else if (ret == 1) return 0; /* done for now */
3484
3485 ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
3486 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
3487 else if (ret == -1) return -1;
3488 else if (ret == 1) return 0; /* done for now */
3489
3490 ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
3491 &end, error);
3492 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
3493 else if (ret == -1) return -1;
3494 else if (ret == 1) return 0; /* done for now */
3495
3496 ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
3497 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
3498 CheckFinCapture(&ipInfo, &tcpInfo, session);
3499 return ret;
3500}
3501
3502
3503/* Deallocator for the decoded data buffer. */
3504/* returns 0 on success, -1 on error */
3505int ssl_FreeDecodeBuffer(byte** data, char* error)
3506{
3507 return ssl_FreeZeroDecodeBuffer(data, 0, error);
3508}
3509
3510
3511/* Deallocator for the decoded data buffer, zeros out buffer. */
3512/* returns 0 on success, -1 on error */
3513int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
3514{
3515 (void)error;
3516
3517 if (sz < 0) {
3518 return -1;
3519 }
3520
3521 if (data != NULL) {
3522 ForceZero(*data, (word32)sz);
3523 free(*data);
3524 *data = NULL;
3525 }
3526
3527 return 0;
3528}
3529
3530
3531/* Enables (if traceFile)/ Disables debug tracing */
3532/* returns 0 on success, -1 on error */
3533int ssl_Trace(const char* traceFile, char* error)
3534{
3535 if (traceFile) {
3536 TraceFile = fopen(traceFile, "a");
3537 if (!TraceFile) {
3538 SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
3539 return -1;
3540 }
3541 TraceOn = 1;
3542 }
3543 else
3544 TraceOn = 0;
3545
3546 return 0;
3547}
3548
3549
3550/* Enables/Disables Recovery of missed data if later packets allow
3551 * maxMemory is number of bytes to use for reassembly buffering per session,
3552 * -1 means unlimited
3553 * returns 0 on success, -1 on error */
3554int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
3555{
3556 (void)error;
3557
3558 RecoveryEnabled = onOff;
3559 if (onOff)
3560 MaxRecoveryMemory = maxMemory;
3561
3562 return 0;
3563}
3564
3565
3566
3567int ssl_GetSessionStats(unsigned int* active, unsigned int* total,
3568 unsigned int* peak, unsigned int* maxSessions,
3569 unsigned int* missedData, unsigned int* reassemblyMem,
3570 char* error)
3571{
3572 int ret;
3573
3574 if (missedData) {
3575 wc_LockMutex(&RecoveryMutex);
3576 *missedData = MissedDataSessions;
3577 wc_UnLockMutex(&RecoveryMutex);
3578 }
3579
3580 if (reassemblyMem) {
3581 SnifferSession* session;
3582 int i;
3583
3584 *reassemblyMem = 0;
3585 wc_LockMutex(&SessionMutex);
3586 for (i = 0; i < HASH_SIZE; i++) {
3587 session = SessionTable[i];
3588 while (session) {
3589 *reassemblyMem += session->cliReassemblyMemory;
3590 *reassemblyMem += session->srvReassemblyMemory;
3591 session = session->next;
3592 }
3593 }
3594 wc_UnLockMutex(&SessionMutex);
3595 }
3596
3597 ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
3598
3599 if (ret == WOLFSSL_SUCCESS)
3600 return 0;
3601 else {
3602 SetError(BAD_SESSION_STATS, error, NULL, 0);
3603 return -1;
3604 }
3605}
3606
3607
3608
3609#endif /* WOLFSSL_SNIFFER */
3610#endif /* WOLFCRYPT_ONLY */
Note: See TracBrowser for help on using the repository browser.