source: azure_iot_hub/trunk/wolfssl-3.15.7/src/sniffer.c@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

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