3 * Copyright (C) 2006-2015 wolfSSL Inc.
5 * This file is part of wolfSSL. (formerly known as CyaSSL)
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.
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.
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-1301, USA
26 #include <wolfssl/wolfcrypt/settings.h>
28 #ifdef WOLFSSL_SNIFFER
34 #include <arpa/inet.h>
38 #define SNPRINTF _snprintf
40 #define SNPRINTF snprintf
43 #include <wolfssl/openssl/ssl.h>
44 #include <wolfssl/internal.h>
45 #include <wolfssl/error-ssl.h>
46 #include <wolfssl/sniffer.h>
47 #include <wolfssl/sniffer_error.h>
49 #include <wolfssl/wolfcrypt/misc.h>
51 #include <wolfcrypt/src/misc.c>
55 #ifndef WOLFSSL_HAVE_MIN
56 #define WOLFSSL_HAVE_MIN
58 static INLINE word32 min(word32 a, word32 b)
63 #endif /* WOLFSSL_HAVE_MIN */
65 #ifndef WOLFSSL_SNIFFER_TIMEOUT
66 #define WOLFSSL_SNIFFER_TIMEOUT 900
67 /* Cache unclosed Sessions for 15 minutes since last used */
72 MAX_SERVER_ADDRESS = 128, /* maximum server address length */
73 MAX_SERVER_NAME = 128, /* maximum server name length */
74 MAX_ERROR_LEN = 80, /* maximum error length */
75 ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
76 LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
77 TCP_PROTO = 6, /* TCP_PROTOCOL */
78 IP_HDR_SZ = 20, /* IP header legnth, min */
79 TCP_HDR_SZ = 20, /* TCP header legnth, min */
80 IPV4 = 4, /* IP version 4 */
81 TCP_PROTOCOL = 6, /* TCP Protocol id */
82 TRACE_MSG_SZ = 80, /* Trace Message buffer size */
83 HASH_SIZE = 499, /* Session Hash Table Rows */
84 PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
85 FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
86 TICKET_HINT_LEN = 4, /* Session Ticket Hint length */
87 EXT_TYPE_SZ = 2, /* Extension length */
88 MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
89 MTU_EXTRA, /* Max input sz of reassembly */
90 TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
96 static HMODULE dllModule; /* for error string resources */
98 BOOL APIENTRY DllMain( HMODULE hModule,
99 DWORD ul_reason_for_call,
103 static int didInit = 0;
105 switch (ul_reason_for_call)
107 case DLL_PROCESS_ATTACH:
114 case DLL_THREAD_ATTACH:
116 case DLL_THREAD_DETACH:
118 case DLL_PROCESS_DETACH:
131 static int TraceOn = 0; /* Trace is off by default */
132 static FILE* TraceFile = 0;
135 /* windows uses .rc table for this */
138 static const char* const msgTable[] =
142 "New SSL Sniffer Server Registered",
143 "Checking IP Header",
144 "SSL Sniffer Server Not Registered",
145 "Checking TCP Header",
148 "SSL Sniffer Server Port Not Registered",
149 "RSA Private Decrypt Error",
150 "RSA Private Decode Error",
151 "Set Cipher Spec Error",
152 "Server Hello Input Malformed",
155 "Couldn't Resume Session Error",
156 "Server Did Resumption",
157 "Client Hello Input Malformed",
158 "Client Trying to Resume",
159 "Handshake Input Malformed",
162 "Got Hello Verify msg",
163 "Got Server Hello msg",
164 "Got Cert Request msg",
165 "Got Server Key Exchange msg",
169 "Got Server Hello Done msg",
171 "Got Client Hello msg",
172 "Got Client Key Exchange msg",
173 "Got Cert Verify msg",
176 "Got Unknown Handshake msg",
177 "New SSL Sniffer Session created",
178 "Couldn't create new SSL",
179 "Got a Packet to decode",
184 "Got an Old Client Hello msg",
185 "Old Client Hello Input Malformed",
186 "Old Client Hello OK",
187 "Bad Old Client Hello",
191 "Record Header Input Malformed",
192 "Got a HandShake msg",
194 "Got a Change Cipher Spec msg",
197 "Got Application Data msg",
198 "Bad Application Data",
200 "Another msg to Process",
201 "Removing Session From Table",
206 "Wrong Protocol type",
207 "Packet Short for header processing",
208 "Got Unknown Record Type",
211 "Can't Open Trace File",
212 "Session in Fatal Error State",
213 "Partial SSL record received",
214 "Buffer Error, malformed input",
215 "Added to Partial Input",
218 "Received a Duplicate Packet",
219 "Received an Out of Order Packet",
220 "Received an Overlap Duplicate Packet",
221 "Received an Overlap Reassembly Begin Duplicate Packet",
222 "Received an Overlap Reassembly End Duplicate Packet",
225 "Missed the Client Hello Entirely",
226 "Got Hello Request msg",
227 "Got Session Ticket msg",
232 "Bad Finished Message Processing",
233 "Bad Compression Type",
234 "Bad DeriveKeys Error",
235 "Saw ACK for Missing Packet Error",
236 "Bad Decrypt Operation",
239 "Decrypt Keys Not Set Up",
240 "Late Key Load Error",
241 "Got Certificate Status msg",
242 "RSA Key Missing Error"
246 /* *nix version uses table above */
247 static void GetError(int idx, char* str)
249 XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
256 /* Windows version uses .rc table */
257 static void GetError(int idx, char* buffer)
259 if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
267 /* Packet Buffer for reassembly list and ready list */
268 typedef struct PacketBuffer {
269 word32 begin; /* relative sequence begin */
270 word32 end; /* relative sequence end */
271 byte* data; /* actual data */
272 struct PacketBuffer* next; /* next on reassembly list or ready list */
278 /* NamedKey maps a SNI name to a specific private key */
279 typedef struct NamedKey {
280 char name[MAX_SERVER_NAME]; /* server DNS name */
281 word32 nameSz; /* size of server DNS name */
282 byte* key; /* DER private key */
283 word32 keySz; /* size of DER private key */
284 struct NamedKey* next; /* for list */
290 /* Sniffer Server holds info for each server/port monitored */
291 typedef struct SnifferServer {
292 SSL_CTX* ctx; /* SSL context */
293 char address[MAX_SERVER_ADDRESS]; /* passed in server address */
294 word32 server; /* netowrk order address */
295 int port; /* server port */
297 NamedKey* namedKeys; /* mapping of names and keys */
298 wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */
300 struct SnifferServer* next; /* for list */
305 typedef struct Flags {
306 byte side; /* which end is current packet headed */
307 byte serverCipherOn; /* indicates whether cipher is active */
308 byte clientCipherOn; /* indicates whether cipher is active */
309 byte resuming; /* did this session come from resumption */
310 byte cached; /* have we cached this session yet */
311 byte clientHello; /* processed client hello yet, for SSLv2 */
312 byte finCount; /* get both FINs before removing */
313 byte fatalError; /* fatal error state */
317 /* Out of Order FIN caputre */
318 typedef struct FinCaputre {
319 word32 cliFinSeq; /* client relative sequence FIN 0 is no */
320 word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
321 byte cliCounted; /* did we count yet, detects duplicates */
322 byte srvCounted; /* did we count yet, detects duplicates */
326 /* Sniffer Session holds info for each client/server SSL/TLS session */
327 typedef struct SnifferSession {
328 SnifferServer* context; /* server context */
329 SSL* sslServer; /* SSL server side decode */
330 SSL* sslClient; /* SSL client side decode */
331 word32 server; /* server address in network byte order */
332 word32 client; /* client address in network byte order */
333 word16 srvPort; /* server port */
334 word16 cliPort; /* client port */
335 word32 cliSeqStart; /* client start sequence */
336 word32 srvSeqStart; /* server start sequence */
337 word32 cliExpected; /* client expected sequence (relative) */
338 word32 srvExpected; /* server expected sequence (relative) */
339 FinCaputre finCaputre; /* retain out of order FIN s */
340 Flags flags; /* session flags */
341 time_t lastUsed; /* last used ticks */
342 PacketBuffer* cliReassemblyList; /* client out of order packets */
343 PacketBuffer* srvReassemblyList; /* server out of order packets */
344 struct SnifferSession* next; /* for hash table list */
345 byte* ticketID; /* mac ID of session ticket */
349 /* Sniffer Server List and mutex */
350 static SnifferServer* ServerList = 0;
351 static wolfSSL_Mutex ServerListMutex;
354 /* Session Hash Table, mutex, and count */
355 static SnifferSession* SessionTable[HASH_SIZE];
356 static wolfSSL_Mutex SessionMutex;
357 static int SessionCount = 0;
360 /* Initialize overall Sniffer */
361 void ssl_InitSniffer(void)
364 InitMutex(&ServerListMutex);
365 InitMutex(&SessionMutex);
371 /* Free Named Key and the zero out the private key it holds */
372 static void FreeNamedKey(NamedKey* in)
376 ForceZero(in->key, in->keySz);
384 static void FreeNamedKeyList(NamedKey* in)
398 /* Free Sniffer Server's resources/self */
399 static void FreeSnifferServer(SnifferServer* srv)
403 LockMutex(&srv->namedKeysMutex);
404 FreeNamedKeyList(srv->namedKeys);
405 UnLockMutex(&srv->namedKeysMutex);
406 FreeMutex(&srv->namedKeysMutex);
408 SSL_CTX_free(srv->ctx);
414 /* free PacketBuffer's resources/self */
415 static void FreePacketBuffer(PacketBuffer* del)
424 /* remove PacketBuffer List */
425 static void FreePacketList(PacketBuffer* in)
429 PacketBuffer* packet = in;
433 packet = packet->next;
434 FreePacketBuffer(del);
440 /* Free Sniffer Session's resources/self */
441 static void FreeSnifferSession(SnifferSession* session)
444 SSL_free(session->sslClient);
445 SSL_free(session->sslServer);
447 FreePacketList(session->cliReassemblyList);
448 FreePacketList(session->srvReassemblyList);
450 free(session->ticketID);
456 /* Free overall Sniffer */
457 void ssl_FreeSniffer(void)
460 SnifferServer* removeServer;
461 SnifferSession* session;
462 SnifferSession* removeSession;
465 LockMutex(&ServerListMutex);
466 LockMutex(&SessionMutex);
472 FreeSnifferServer(removeServer);
475 for (i = 0; i < HASH_SIZE; i++) {
476 session = SessionTable[i];
478 removeSession = session;
479 session = session->next;
480 FreeSnifferSession(removeSession);
484 UnLockMutex(&SessionMutex);
485 UnLockMutex(&ServerListMutex);
487 FreeMutex(&SessionMutex);
488 FreeMutex(&ServerListMutex);
500 /* Initialize a SnifferServer */
501 static void InitSnifferServer(SnifferServer* sniffer)
504 XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
508 sniffer->namedKeys = 0;
509 InitMutex(&sniffer->namedKeysMutex);
515 /* Initialize session flags */
516 static void InitFlags(Flags* flags)
519 flags->serverCipherOn = 0;
520 flags->clientCipherOn = 0;
523 flags->clientHello = 0;
525 flags->fatalError = 0;
529 /* Initialize FIN Capture */
530 static void InitFinCapture(FinCaputre* cap)
539 /* Initialize a Sniffer Session */
540 static void InitSession(SnifferSession* session)
542 session->context = 0;
543 session->sslServer = 0;
544 session->sslClient = 0;
547 session->srvPort = 0;
548 session->cliPort = 0;
549 session->cliSeqStart = 0;
550 session->srvSeqStart = 0;
551 session->cliExpected = 0;
552 session->srvExpected = 0;
553 session->lastUsed = 0;
554 session->cliReassemblyList = 0;
555 session->srvReassemblyList = 0;
557 session->ticketID = 0;
559 InitFlags(&session->flags);
560 InitFinCapture(&session->finCaputre);
564 /* IP Info from IP Header */
565 typedef struct IpInfo {
566 int length; /* length of this header */
567 int total; /* total length of fragment */
568 word32 src; /* network order source address */
569 word32 dst; /* network order destination address */
573 /* TCP Info from TCP Header */
574 typedef struct TcpInfo {
575 int srcPort; /* source port */
576 int dstPort; /* source port */
577 int length; /* length of this header */
578 word32 sequence; /* sequence number */
579 word32 ackNumber; /* ack number */
580 byte fin; /* FIN set */
581 byte rst; /* RST set */
582 byte syn; /* SYN set */
583 byte ack; /* ACK set */
587 /* Tcp Pseudo Header for Checksum calculation */
588 typedef struct TcpPseudoHdr {
589 word32 src; /* source address */
590 word32 dst; /* destination address */
591 byte rsv; /* reserved, always 0 */
592 byte protocol; /* IP protocol */
593 word16 legnth; /* tcp header length + data length (doesn't include */
594 /* pseudo header length) network order */
598 /* Password Setting Callback */
599 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
602 XSTRNCPY(passwd, (const char*)userdata, sz);
603 return (int)XSTRLEN((const char*)userdata);
607 /* Ethernet Header */
608 typedef struct EthernetHdr {
609 byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */
610 byte src[ETHER_IF_ADDR_LEN]; /* source host address */
611 word16 type; /* IP, ARP, etc */
616 typedef struct IpHdr {
617 byte ver_hl; /* version/header length */
618 byte tos; /* type of service */
619 word16 length; /* total length */
620 word16 id; /* identification */
621 word16 offset; /* fragment offset field */
622 byte ttl; /* time to live */
623 byte protocol; /* protocol */
624 word16 sum; /* checksum */
625 word32 src; /* source address */
626 word32 dst; /* destination address */
630 #define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4)
631 #define IP_V(ip) ( ((ip)->ver_hl) >> 4)
634 typedef struct TcpHdr {
635 word16 srcPort; /* source port */
636 word16 dstPort; /* destination port */
637 word32 sequence; /* sequence number */
638 word32 ack; /* acknoledgment number */
639 byte offset; /* data offset, reserved */
640 byte flags; /* option flags */
641 word16 window; /* window */
642 word16 sum; /* checksum */
643 word16 urgent; /* urgent pointer */
646 #define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4)
656 /* Use platform specific GetError to write to tracfile if tracing */
657 static void Trace(int idx)
660 char myBuffer[MAX_ERROR_LEN];
661 GetError(idx, myBuffer);
662 fprintf(TraceFile, "\t%s\n", myBuffer);
664 fprintf(stderr, "\t%s\n", myBuffer);
670 /* Show TimeStamp for beginning of packet Trace */
671 static void TraceHeader(void)
674 time_t ticks = time(NULL);
675 fprintf(TraceFile, "\n%s", ctime(&ticks));
680 /* Show Set Server info for Trace */
681 static void TraceSetServer(const char* srv, int port, const char* keyFile)
684 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
685 fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
693 /* Show Set Named Server info for Trace */
694 static void TraceSetNamedServer(const char* name,
695 const char* srv, int port, const char* keyFile)
698 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
699 fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
700 name, srv, port, keyFile);
707 /* Trace got packet number */
708 static void TracePacket(void)
711 static word32 packetNumber = 0;
712 fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
718 /* Convert network byte order address into human readable */
719 static char* IpToS(word32 addr, char* str)
721 byte* p = (byte*)&addr;
723 SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
729 /* Show destination and source address from Ip Hdr for packet Trace */
730 static void TraceIP(IpHdr* iphdr)
733 char src[TRACE_MSG_SZ];
734 char dst[TRACE_MSG_SZ];
735 fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
736 IpToS(iphdr->src, src));
741 /* Show destination and source port from Tcp Hdr for packet Trace */
742 static void TraceTcp(TcpHdr* tcphdr)
745 fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
746 ntohs(tcphdr->srcPort));
751 /* Show sequence and payload length for Trace */
752 static void TraceSequence(word32 seq, int len)
755 fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
760 /* Show sequence and payload length for Trace */
761 static void TraceAck(word32 ack, word32 expected)
764 fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
769 /* Show relative expected and relative received sequences */
770 static void TraceRelativeSequence(word32 expected, word32 got)
773 fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
779 /* Show server sequence startup from SYN */
780 static void TraceServerSyn(word32 seq)
783 fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
788 /* Show client sequence startup from SYN */
789 static void TraceClientSyn(word32 seq)
792 fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
797 /* Show client FIN capture */
798 static void TraceClientFin(word32 finSeq, word32 relSeq)
801 fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
807 /* Show server FIN capture */
808 static void TraceServerFin(word32 finSeq, word32 relSeq)
811 fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
817 /* Show number of SSL data bytes decoded, could be 0 (ok) */
818 static void TraceGotData(int bytes)
821 fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
826 /* Show bytes added to old SSL App data */
827 static void TraceAddedData(int newBytes, int existingBytes)
831 "\t%d bytes added to %d exisiting bytes in User Buffer\n",
832 newBytes, existingBytes);
837 /* Show Stale Session */
838 static void TraceStaleSession(void)
841 fprintf(TraceFile, "\tFound a stale session\n");
846 /* Show Finding Stale Sessions */
847 static void TraceFindingStale(void)
850 fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
855 /* Show Removed Session */
856 static void TraceRemovedSession(void)
859 fprintf(TraceFile, "\tRemoved it\n");
864 /* Set user error string */
865 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
867 GetError(idx, error);
869 if (session && fatal == FATAL_ERROR_STATE)
870 session->flags.fatalError = 1;
874 /* See if this IPV4 network order address has been registered */
875 /* return 1 is true, 0 is false */
876 static int IsServerRegistered(word32 addr)
878 int ret = 0; /* false */
879 SnifferServer* sniffer;
881 LockMutex(&ServerListMutex);
883 sniffer = ServerList;
885 if (sniffer->server == addr) {
889 sniffer = sniffer->next;
892 UnLockMutex(&ServerListMutex);
898 /* See if this port has been registered to watch */
899 /* return 1 is true, 0 is false */
900 static int IsPortRegistered(word32 port)
902 int ret = 0; /* false */
903 SnifferServer* sniffer;
905 LockMutex(&ServerListMutex);
907 sniffer = ServerList;
909 if (sniffer->port == (int)port) {
913 sniffer = sniffer->next;
916 UnLockMutex(&ServerListMutex);
922 /* Get SnifferServer from IP and Port */
923 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
925 SnifferServer* sniffer;
927 LockMutex(&ServerListMutex);
929 sniffer = ServerList;
931 if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
933 if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
935 sniffer = sniffer->next;
938 UnLockMutex(&ServerListMutex);
944 /* Hash the Session Info, return hash row */
945 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
947 word32 hash = ipInfo->src * ipInfo->dst;
948 hash *= tcpInfo->srcPort * tcpInfo->dstPort;
950 return hash % HASH_SIZE;
954 /* Get Exisiting SnifferSession from IP and Port */
955 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
957 SnifferSession* session;
958 time_t currTime = time(NULL);
959 word32 row = SessionHash(ipInfo, tcpInfo);
961 assert(row <= HASH_SIZE);
963 LockMutex(&SessionMutex);
965 session = SessionTable[row];
967 if (session->server == ipInfo->src && session->client == ipInfo->dst &&
968 session->srvPort == tcpInfo->srcPort &&
969 session->cliPort == tcpInfo->dstPort)
971 if (session->client == ipInfo->src && session->server == ipInfo->dst &&
972 session->cliPort == tcpInfo->srcPort &&
973 session->srvPort == tcpInfo->dstPort)
976 session = session->next;
980 session->lastUsed= currTime; /* keep session alive, remove stale will */
982 UnLockMutex(&SessionMutex);
986 if (ipInfo->dst == session->context->server &&
987 tcpInfo->dstPort == session->context->port)
988 session->flags.side = WOLFSSL_SERVER_END;
990 session->flags.side = WOLFSSL_CLIENT_END;
999 static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1000 const char* keyFile, int typeKey,
1001 const char* password)
1010 if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1014 file = XFOPEN(keyFile, "rb");
1015 if (file == XBADFILE) return -1;
1016 XFSEEK(file, 0, XSEEK_END);
1017 fileSz = XFTELL(file);
1020 loadBuf = (byte*)malloc(fileSz);
1021 if (loadBuf == NULL) {
1026 ret = (int)XFREAD(loadBuf, fileSz, 1, file);
1029 if (typeKey == SSL_FILETYPE_PEM) {
1030 saveBuf = (byte*)malloc(fileSz);
1032 saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz,
1033 saveBuf, (int)fileSz, password);
1037 *keyBufSz = (word32)saveBufSz;
1041 *keyBufSz = (word32)fileSz;
1055 static int SetNamedPrivateKey(const char* name, const char* address, int port,
1056 const char* keyFile, int typeKey, const char* password, char* error)
1058 SnifferServer* sniffer;
1060 int type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
1066 NamedKey* namedKey = NULL;
1072 namedKey = (NamedKey*)malloc(sizeof(NamedKey));
1073 if (namedKey == NULL) {
1074 SetError(MEMORY_STR, error, NULL, 0);
1077 XMEMSET(namedKey, 0, sizeof(NamedKey));
1079 namedKey->nameSz = (word32)XSTRLEN(name);
1080 XSTRNCPY(namedKey->name, name, sizeof(namedKey->name));
1081 if (namedKey->nameSz >= sizeof(namedKey->name)) {
1082 namedKey->nameSz = sizeof(namedKey->name) - 1;
1083 namedKey->name[namedKey->nameSz] = '\0';
1086 ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1087 keyFile, type, password);
1089 SetError(KEY_FILE_STR, error, NULL, 0);
1090 FreeNamedKey(namedKey);
1096 serverIp = inet_addr(address);
1097 sniffer = ServerList;
1098 while (sniffer != NULL &&
1099 (sniffer->server != serverIp || sniffer->port != port)) {
1100 sniffer = sniffer->next;
1103 if (sniffer == NULL) {
1105 sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
1106 if (sniffer == NULL) {
1107 SetError(MEMORY_STR, error, NULL, 0);
1109 FreeNamedKey(namedKey);
1113 InitSnifferServer(sniffer);
1115 XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1116 sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1117 sniffer->server = serverIp;
1118 sniffer->port = port;
1120 sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
1121 if (!sniffer->ctx) {
1122 SetError(MEMORY_STR, error, NULL, 0);
1124 FreeNamedKey(namedKey);
1126 FreeSnifferServer(sniffer);
1133 SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1134 SSL_CTX_set_default_passwd_cb_userdata(
1135 sniffer->ctx, (void*)password);
1137 ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1138 if (ret != SSL_SUCCESS) {
1139 SetError(KEY_FILE_STR, error, NULL, 0);
1141 FreeSnifferServer(sniffer);
1147 LockMutex(&sniffer->namedKeysMutex);
1148 namedKey->next = sniffer->namedKeys;
1149 sniffer->namedKeys = namedKey;
1150 UnLockMutex(&sniffer->namedKeysMutex);
1155 sniffer->next = ServerList;
1156 ServerList = sniffer;
1165 /* Sets the private key for a specific name, server and port */
1166 /* returns 0 on success, -1 on error */
1167 int ssl_SetNamedPrivateKey(const char* name,
1168 const char* address, int port,
1169 const char* keyFile, int typeKey,
1170 const char* password, char* error)
1175 TraceSetNamedServer(name, address, port, keyFile);
1177 LockMutex(&ServerListMutex);
1178 ret = SetNamedPrivateKey(name, address, port, keyFile,
1179 typeKey, password, error);
1180 UnLockMutex(&ServerListMutex);
1183 Trace(NEW_SERVER_STR);
1191 /* Sets the private key for a specific server and port */
1192 /* returns 0 on success, -1 on error */
1193 int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
1194 int typeKey, const char* password, char* error)
1199 TraceSetServer(address, port, keyFile);
1201 LockMutex(&ServerListMutex);
1202 ret = SetNamedPrivateKey(NULL, address, port, keyFile,
1203 typeKey, password, error);
1204 UnLockMutex(&ServerListMutex);
1207 Trace(NEW_SERVER_STR);
1213 /* Check IP Header for IPV4, TCP, and a registered server address */
1214 /* returns 0 on success, -1 on error */
1215 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
1217 int version = IP_V(iphdr);
1220 Trace(IP_CHECK_STR);
1222 if (version != IPV4) {
1223 SetError(BAD_IPVER_STR, error, NULL, 0);
1227 if (iphdr->protocol != TCP_PROTOCOL) {
1228 SetError(BAD_PROTO_STR, error, NULL, 0);
1232 if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
1233 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1237 info->length = IP_HL(iphdr);
1238 info->total = ntohs(iphdr->length);
1239 info->src = iphdr->src;
1240 info->dst = iphdr->dst;
1242 if (info->total == 0)
1243 info->total = length; /* reassembled may be off */
1249 /* Check TCP Header for a registered port */
1250 /* returns 0 on success, -1 on error */
1251 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
1254 Trace(TCP_CHECK_STR);
1255 info->srcPort = ntohs(tcphdr->srcPort);
1256 info->dstPort = ntohs(tcphdr->dstPort);
1257 info->length = TCP_LEN(tcphdr);
1258 info->sequence = ntohl(tcphdr->sequence);
1259 info->fin = tcphdr->flags & TCP_FIN;
1260 info->rst = tcphdr->flags & TCP_RST;
1261 info->syn = tcphdr->flags & TCP_SYN;
1262 info->ack = tcphdr->flags & TCP_ACK;
1264 info->ackNumber = ntohl(tcphdr->ack);
1266 if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
1267 SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
1275 /* Decode Record Layer Header */
1276 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
1278 XMEMCPY(rh, input, RECORD_HEADER_SZ);
1279 *size = (rh->length[0] << 8) | rh->length[1];
1281 if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
1282 return LENGTH_ERROR;
1288 /* Process Client Key Exchange, RSA only */
1289 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
1290 SnifferSession* session, char* error)
1296 if (session->sslServer->buffers.key.buffer == NULL ||
1297 session->sslServer->buffers.key.length == 0) {
1299 SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
1302 ret = wc_InitRsaKey(&key, 0);
1304 ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key.buffer,
1305 &idx, &key, session->sslServer->buffers.key.length);
1307 int length = wc_RsaEncryptSize(&key);
1309 if (IsTLS(session->sslServer))
1310 input += 2; /* tls pre length */
1312 if (length > *sslBytes) {
1313 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
1314 wc_FreeRsaKey(&key);
1317 ret = wc_RsaPrivateDecrypt(input, length,
1318 session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key);
1320 if (ret != SECRET_LEN) {
1321 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1322 wc_FreeRsaKey(&key);
1325 ret = 0; /* not in error state */
1326 session->sslServer->arrays->preMasterSz = SECRET_LEN;
1328 /* store for client side as well */
1329 XMEMCPY(session->sslClient->arrays->preMasterSecret,
1330 session->sslServer->arrays->preMasterSecret, SECRET_LEN);
1331 session->sslClient->arrays->preMasterSz = SECRET_LEN;
1336 printf("pre master secret: ");
1337 for (i = 0; i < SECRET_LEN; i++)
1338 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
1344 SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
1345 wc_FreeRsaKey(&key);
1349 if (SetCipherSpecs(session->sslServer) != 0) {
1350 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1351 wc_FreeRsaKey(&key);
1355 if (SetCipherSpecs(session->sslClient) != 0) {
1356 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1357 wc_FreeRsaKey(&key);
1361 ret = MakeMasterSecret(session->sslServer);
1362 ret += MakeMasterSecret(session->sslClient);
1363 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1364 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1367 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1374 printf("server master secret: ");
1375 for (i = 0; i < SECRET_LEN; i++)
1376 printf("%02x", session->sslServer->arrays->masterSecret[i]);
1379 printf("client master secret: ");
1380 for (i = 0; i < SECRET_LEN; i++)
1381 printf("%02x", session->sslClient->arrays->masterSecret[i]);
1384 printf("server suite = %d\n", session->sslServer->options.cipherSuite);
1385 printf("client suite = %d\n", session->sslClient->options.cipherSuite);
1389 wc_FreeRsaKey(&key);
1394 /* Process Session Ticket */
1395 static int ProcessSessionTicket(const byte* input, int* sslBytes,
1396 SnifferSession* session, char* error)
1400 /* make sure can read through hint and len */
1401 if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
1402 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1406 input += TICKET_HINT_LEN; /* skip over hint */
1407 *sslBytes -= TICKET_HINT_LEN;
1409 len = (word16)((input[0] << 8) | input[1]);
1411 *sslBytes -= LENGTH_SZ;
1413 /* make sure can read through ticket */
1414 if (len > *sslBytes || len < ID_LEN) {
1415 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1419 /* store session with macID as sessionID */
1420 session->sslServer->options.haveSessionId = 1;
1421 XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
1427 /* Process Server Hello */
1428 static int ProcessServerHello(const byte* input, int* sslBytes,
1429 SnifferSession* session, char* error)
1433 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1436 /* make sure we didn't miss ClientHello */
1437 if (session->flags.clientHello == 0) {
1438 SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
1442 /* make sure can read through session len */
1443 if (toRead > *sslBytes) {
1444 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1448 XMEMCPY(&pv, input, VERSION_SZ);
1449 input += VERSION_SZ;
1450 *sslBytes -= VERSION_SZ;
1452 session->sslServer->version = pv;
1453 session->sslClient->version = pv;
1455 XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
1456 XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
1458 *sslBytes -= RAN_LEN;
1463 /* make sure can read through compression */
1464 if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
1465 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1469 XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
1470 session->sslServer->options.haveSessionId = 1;
1476 b = *input++; /* first byte, ECC or not */
1477 session->sslServer->options.cipherSuite0 = b;
1478 session->sslClient->options.cipherSuite0 = b;
1480 session->sslServer->options.cipherSuite = b;
1481 session->sslClient->options.cipherSuite = b;
1482 *sslBytes -= SUITE_LEN;
1486 *sslBytes -= ENUM_LEN;
1489 SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
1493 if (session->sslServer->options.haveSessionId &&
1494 XMEMCMP(session->sslServer->arrays->sessionID,
1495 session->sslClient->arrays->sessionID, ID_LEN) == 0)
1497 else if (session->sslClient->options.haveSessionId == 0 &&
1498 session->sslServer->options.haveSessionId == 0 &&
1502 if (session->ticketID && doResume) {
1503 /* use ticketID to retrieve from session, prefer over sessionID */
1504 XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
1505 session->sslServer->options.haveSessionId = 1; /* may not have
1511 SSL_SESSION* resume = GetSession(session->sslServer,
1512 session->sslServer->arrays->masterSecret);
1513 if (resume == NULL) {
1514 SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
1517 /* make sure client has master secret too */
1518 XMEMCPY(session->sslClient->arrays->masterSecret,
1519 session->sslServer->arrays->masterSecret, SECRET_LEN);
1520 session->flags.resuming = 1;
1522 Trace(SERVER_DID_RESUMPTION_STR);
1523 if (SetCipherSpecs(session->sslServer) != 0) {
1524 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1528 if (SetCipherSpecs(session->sslClient) != 0) {
1529 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1533 if (session->sslServer->options.tls) {
1534 ret = DeriveTlsKeys(session->sslServer);
1535 ret += DeriveTlsKeys(session->sslClient);
1538 ret = DeriveKeys(session->sslServer);
1539 ret += DeriveKeys(session->sslClient);
1541 ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1542 ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1545 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1552 printf("cipher suite = 0x%02x\n",
1553 session->sslServer->options.cipherSuite);
1554 printf("server random: ");
1555 for (i = 0; i < RAN_LEN; i++)
1556 printf("%02x", session->sslServer->arrays->serverRandom[i]);
1564 /* Process normal Client Hello */
1565 static int ProcessClientHello(const byte* input, int* sslBytes,
1566 SnifferSession* session, char* error)
1570 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1574 byte name[MAX_SERVER_NAME];
1575 word32 nameSz = sizeof(name);
1578 ret = wolfSSL_SNI_GetFromBuffer(
1579 input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
1580 *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
1581 WOLFSSL_SNI_HOST_NAME, name, &nameSz);
1583 if (ret == SSL_SUCCESS) {
1586 if (nameSz >= sizeof(name))
1587 nameSz = sizeof(name) - 1;
1589 LockMutex(&session->context->namedKeysMutex);
1590 namedKey = session->context->namedKeys;
1591 while (namedKey != NULL) {
1592 if (nameSz == namedKey->nameSz &&
1593 XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
1594 if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
1595 namedKey->key, namedKey->keySz,
1596 SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
1597 UnLockMutex(&session->context->namedKeysMutex);
1598 SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
1605 namedKey = namedKey->next;
1607 UnLockMutex(&session->context->namedKeysMutex);
1612 session->flags.clientHello = 1; /* don't process again */
1614 /* make sure can read up to session len */
1615 if (toRead > *sslBytes) {
1616 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1620 /* skip, get negotiated one from server hello */
1621 input += VERSION_SZ;
1622 *sslBytes -= VERSION_SZ;
1624 XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
1625 XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
1628 *sslBytes -= RAN_LEN;
1630 /* store session in case trying to resume */
1632 *sslBytes -= ENUM_LEN;
1634 if (ID_LEN > *sslBytes) {
1635 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1638 Trace(CLIENT_RESUME_TRY_STR);
1639 XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
1640 session->sslClient->options.haveSessionId = 1;
1645 printf("client random: ");
1646 for (i = 0; i < RAN_LEN; i++)
1647 printf("%02x", session->sslServer->arrays->clientRandom[i]);
1655 /* skip cipher suites */
1656 /* make sure can read len */
1657 if (SUITE_LEN > *sslBytes) {
1658 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1661 len = (word16)((input[0] << 8) | input[1]);
1663 *sslBytes -= SUITE_LEN;
1664 /* make sure can read suites + comp len */
1665 if (len + ENUM_LEN > *sslBytes) {
1666 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1672 /* skip compression */
1674 *sslBytes -= ENUM_LEN;
1675 /* make sure can read len */
1676 if (bLen > *sslBytes) {
1677 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1683 if (*sslBytes == 0) {
1688 /* skip extensions until session ticket */
1689 /* make sure can read len */
1690 if (SUITE_LEN > *sslBytes) {
1691 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1694 len = (word16)((input[0] << 8) | input[1]);
1696 *sslBytes -= SUITE_LEN;
1697 /* make sure can read through all extensions */
1698 if (len > *sslBytes) {
1699 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1703 while (len > EXT_TYPE_SZ + LENGTH_SZ) {
1704 byte extType[EXT_TYPE_SZ];
1707 extType[0] = input[0];
1708 extType[1] = input[1];
1709 input += EXT_TYPE_SZ;
1710 *sslBytes -= EXT_TYPE_SZ;
1712 extLen = (word16)((input[0] << 8) | input[1]);
1714 *sslBytes -= LENGTH_SZ;
1716 /* make sure can read through individual extension */
1717 if (extLen > *sslBytes) {
1718 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1722 if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
1724 /* make sure can read through ticket if there is a non blank one */
1725 if (extLen && extLen < ID_LEN) {
1726 SetError(CLIENT_HELLO_INPUT_STR, error, session,
1732 if (session->ticketID == 0) {
1733 session->ticketID = (byte*)malloc(ID_LEN);
1734 if (session->ticketID == 0) {
1735 SetError(MEMORY_STR, error, session,
1740 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
1745 *sslBytes -= extLen;
1746 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
1753 /* Process Finished */
1754 static int ProcessFinished(const byte* input, int size, int* sslBytes,
1755 SnifferSession* session, char* error)
1758 word32 inOutIdx = 0;
1761 if (session->flags.side == WOLFSSL_SERVER_END)
1762 ssl = session->sslServer;
1764 ssl = session->sslClient;
1766 ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
1768 *sslBytes -= (int)inOutIdx;
1771 SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
1775 if (ret == 0 && session->flags.cached == 0) {
1776 if (session->sslServer->options.haveSessionId) {
1777 WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL);
1779 AddSession(session->sslServer); /* don't re add */
1780 session->flags.cached = 1;
1784 /* If receiving a finished message from one side, free the resources
1785 * from the other side's tracker. */
1786 if (session->flags.side == WOLFSSL_SERVER_END)
1787 FreeHandshakeResources(session->sslClient);
1789 FreeHandshakeResources(session->sslServer);
1795 /* Process HandShake input */
1796 static int DoHandShake(const byte* input, int* sslBytes,
1797 SnifferSession* session, char* error)
1804 if (*sslBytes < HANDSHAKE_HEADER_SZ) {
1805 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
1809 size = (input[1] << 16) | (input[2] << 8) | input[3];
1811 input += HANDSHAKE_HEADER_SZ;
1812 *sslBytes -= HANDSHAKE_HEADER_SZ;
1813 startBytes = *sslBytes;
1815 if (*sslBytes < size) {
1816 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
1821 case hello_verify_request:
1822 Trace(GOT_HELLO_VERIFY_STR);
1825 Trace(GOT_HELLO_REQUEST_STR);
1827 case session_ticket:
1828 Trace(GOT_SESSION_TICKET_STR);
1829 ret = ProcessSessionTicket(input, sslBytes, session, error);
1832 Trace(GOT_SERVER_HELLO_STR);
1833 ret = ProcessServerHello(input, sslBytes, session, error);
1835 case certificate_request:
1836 Trace(GOT_CERT_REQ_STR);
1838 case server_key_exchange:
1839 Trace(GOT_SERVER_KEY_EX_STR);
1840 /* can't know temp key passively */
1841 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1845 Trace(GOT_CERT_STR);
1847 case server_hello_done:
1848 Trace(GOT_SERVER_HELLO_DONE_STR);
1851 Trace(GOT_FINISHED_STR);
1852 ret = ProcessFinished(input, size, sslBytes, session, error);
1855 Trace(GOT_CLIENT_HELLO_STR);
1856 ret = ProcessClientHello(input, sslBytes, session, error);
1858 case client_key_exchange:
1859 Trace(GOT_CLIENT_KEY_EX_STR);
1860 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
1862 case certificate_verify:
1863 Trace(GOT_CERT_VER_STR);
1865 case certificate_status:
1866 Trace(GOT_CERT_STATUS_STR);
1869 SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
1873 *sslBytes = startBytes - size; /* actual bytes of full process */
1879 /* Decrypt input into plain output, 0 on success */
1880 static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
1884 switch (ssl->specs.bulk_cipher_algorithm) {
1887 wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
1892 case wolfssl_triple_des:
1893 ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
1899 ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
1905 wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
1910 case wolfssl_rabbit:
1911 wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
1915 #ifdef HAVE_CAMELLIA
1916 case wolfssl_camellia:
1917 wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
1922 Trace(BAD_DECRYPT_TYPE);
1931 /* Decrypt input message into output, adjust output steam if needed */
1932 static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
1933 byte* output, int* error, int* advance)
1937 int ret = Decrypt(ssl, output, input, sz);
1942 ssl->keys.encryptSz = sz;
1943 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
1944 output += ssl->specs.block_size; /* go past TLSv1.1 IV */
1945 ivExtra = ssl->specs.block_size;
1946 *advance = ssl->specs.block_size;
1949 ssl->keys.padSz = ssl->specs.hash_size;
1951 if (ssl->specs.cipher_type == block)
1952 ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
1958 /* remove session from table, use rowHint if no info (means we have a lock) */
1959 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
1960 TcpInfo* tcpInfo, word32 rowHint)
1962 SnifferSession* previous = 0;
1963 SnifferSession* current;
1964 word32 row = rowHint;
1967 if (ipInfo && tcpInfo)
1968 row = SessionHash(ipInfo, tcpInfo);
1972 assert(row <= HASH_SIZE);
1973 Trace(REMOVE_SESSION_STR);
1976 LockMutex(&SessionMutex);
1978 current = SessionTable[row];
1981 if (current == session) {
1983 previous->next = current->next;
1985 SessionTable[row] = current->next;
1986 FreeSnifferSession(session);
1987 TraceRemovedSession();
1991 current = current->next;
1995 UnLockMutex(&SessionMutex);
1999 /* Remove stale sessions from the Session Table, have a lock */
2000 static void RemoveStaleSessions(void)
2003 SnifferSession* session;
2005 for (i = 0; i < HASH_SIZE; i++) {
2006 session = SessionTable[i];
2008 SnifferSession* next = session->next;
2009 if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
2010 TraceStaleSession();
2011 RemoveSession(session, NULL, NULL, i);
2019 /* Create a new Sniffer Session */
2020 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2023 SnifferSession* session = 0;
2026 Trace(NEW_SESSION_STR);
2027 /* create a new one */
2028 session = (SnifferSession*)malloc(sizeof(SnifferSession));
2029 if (session == NULL) {
2030 SetError(MEMORY_STR, error, NULL, 0);
2033 InitSession(session);
2034 session->server = ipInfo->dst;
2035 session->client = ipInfo->src;
2036 session->srvPort = (word16)tcpInfo->dstPort;
2037 session->cliPort = (word16)tcpInfo->srcPort;
2038 session->cliSeqStart = tcpInfo->sequence;
2039 session->cliExpected = 1; /* relative */
2040 session->lastUsed= time(NULL);
2042 session->context = GetSnifferServer(ipInfo, tcpInfo);
2043 if (session->context == NULL) {
2044 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
2049 session->sslServer = SSL_new(session->context->ctx);
2050 if (session->sslServer == NULL) {
2051 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2055 session->sslClient = SSL_new(session->context->ctx);
2056 if (session->sslClient == NULL) {
2057 SSL_free(session->sslServer);
2058 session->sslServer = 0;
2060 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2064 /* put server back into server mode */
2065 session->sslServer->options.side = WOLFSSL_SERVER_END;
2067 row = SessionHash(ipInfo, tcpInfo);
2069 /* add it to the session table */
2070 LockMutex(&SessionMutex);
2072 session->next = SessionTable[row];
2073 SessionTable[row] = session;
2077 if ( (SessionCount % HASH_SIZE) == 0) {
2078 TraceFindingStale();
2079 RemoveStaleSessions();
2082 UnLockMutex(&SessionMutex);
2084 /* determine headed side */
2085 if (ipInfo->dst == session->context->server &&
2086 tcpInfo->dstPort == session->context->port)
2087 session->flags.side = WOLFSSL_SERVER_END;
2089 session->flags.side = WOLFSSL_CLIENT_END;
2095 #ifdef OLD_HELLO_ALLOWED
2097 /* Process Old Client Hello Input */
2098 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
2099 int* rhSize, int* sslBytes, char* error)
2101 const byte* input = sslFrame;
2106 Trace(GOT_OLD_CLIENT_HELLO_STR);
2107 session->flags.clientHello = 1; /* don't process again */
2111 *rhSize = ((b0 & 0x7f) << 8) | b1;
2113 if (*rhSize > *sslBytes) {
2114 SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
2118 ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
2120 if (ret < 0 && ret != MATCH_SUITE_ERROR) {
2121 SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
2125 Trace(OLD_CLIENT_OK_STR);
2126 XMEMCPY(session->sslClient->arrays->clientRandom,
2127 session->sslServer->arrays->clientRandom, RAN_LEN);
2129 *sslBytes -= *rhSize;
2133 #endif /* OLD_HELLO_ALLOWED */
2137 /* Calculate the TCP checksum, see RFC 1071 */
2138 /* return 0 for success, -1 on error */
2139 /* can be called from decode() with
2140 TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
2141 could also add a 64bit version if type available and using this
2143 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
2146 TcpPseudoHdr pseudo;
2147 int count = PSEUDO_HDR_SZ;
2148 const word16* data = (word16*)&pseudo;
2152 pseudo.src = ipInfo->src;
2153 pseudo.dst = ipInfo->dst;
2155 pseudo.protocol = TCP_PROTO;
2156 pseudo.legnth = htons(tcpInfo->length + dataLen);
2158 /* pseudo header sum */
2159 while (count >= 2) {
2164 count = tcpInfo->length + dataLen;
2165 data = (word16*)packet;
2173 /* get left-over, if any */
2174 packet = (byte*)data;
2179 /* fold 32bit sum into 16 bits */
2181 sum = (sum & 0xffff) + (sum >> 16);
2183 checksum = (word16)~sum;
2184 /* checksum should now equal 0, since included already calcd checksum */
2185 /* field, but tcp checksum offloading could negate calculation */
2193 /* Check IP and TCP headers, set payload */
2194 /* returns 0 on success, -1 on error */
2195 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
2196 int length, const byte** sslFrame, int* sslBytes, char* error)
2202 if (length < IP_HDR_SZ) {
2203 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2206 if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
2210 if (length < (ipInfo->length + TCP_HDR_SZ)) {
2211 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2214 if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
2218 *sslFrame = packet + ipInfo->length + tcpInfo->length;
2219 if (*sslFrame > packet + length) {
2220 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2223 *sslBytes = (int)(packet + length - *sslFrame);
2229 /* Create or Find existing session */
2230 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2231 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
2232 SnifferSession** session, char* error)
2234 /* create a new SnifferSession on client SYN */
2235 if (tcpInfo->syn && !tcpInfo->ack) {
2236 TraceClientSyn(tcpInfo->sequence);
2237 *session = CreateSession(ipInfo, tcpInfo, error);
2238 if (*session == NULL) {
2239 *session = GetSnifferSession(ipInfo, tcpInfo);
2240 /* already had exisiting, so OK */
2244 SetError(MEMORY_STR, error, NULL, 0);
2249 /* get existing sniffer session */
2251 *session = GetSnifferSession(ipInfo, tcpInfo);
2252 if (*session == NULL) {
2253 /* don't worry about extraneous RST or duplicate FINs */
2254 if (tcpInfo->fin || tcpInfo->rst)
2256 /* don't worry about duplicate ACKs either */
2257 if (sslBytes == 0 && tcpInfo->ack)
2260 SetError(BAD_SESSION_STR, error, NULL, 0);
2268 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
2269 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
2274 int added = end - *begin + 1;
2275 assert(*begin <= end);
2277 pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
2278 if (pb == NULL) return NULL;
2283 pb->data = (byte*)malloc(added);
2285 if (pb->data == NULL) {
2289 XMEMCPY(pb->data, data, added);
2291 *bytesLeft -= added;
2292 *begin = pb->end + 1;
2298 /* Add sslFrame to Reassembly List */
2299 /* returns 1 (end) on success, -1, on error */
2300 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
2301 int sslBytes, SnifferSession* session, char* error)
2304 PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
2305 &session->cliReassemblyList: &session->srvReassemblyList;
2306 PacketBuffer* curr = *front;
2307 PacketBuffer* prev = curr;
2309 word32 startSeq = seq;
2311 int bytesLeft = sslBytes; /* could be overlapping fragment */
2313 /* if list is empty add full frame to front */
2315 add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
2317 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2324 /* add to front if before current front, up to next->begin */
2325 if (seq < curr->begin) {
2326 word32 end = seq + sslBytes - 1;
2328 if (end >= curr->begin)
2329 end = curr->begin - 1;
2331 add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
2333 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2340 /* while we have bytes left, try to find a gap to fill */
2341 while (bytesLeft > 0) {
2342 /* get previous packet in list */
2343 while (curr && (seq >= curr->begin)) {
2348 /* don't add duplicate data */
2349 if (prev->end >= seq) {
2350 if ( (seq + bytesLeft - 1) <= prev->end)
2352 seq = prev->end + 1;
2353 bytesLeft = startSeq + sslBytes - seq;
2357 /* we're at the end */
2360 /* we're in between two frames */
2361 added = min((word32)bytesLeft, curr->begin - seq);
2363 /* data already there */
2367 add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
2370 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2373 add->next = prev->next;
2380 /* Add out of order FIN capture */
2381 /* returns 1 for success (end) */
2382 static int AddFinCapture(SnifferSession* session, word32 sequence)
2384 if (session->flags.side == WOLFSSL_SERVER_END) {
2385 if (session->finCaputre.cliCounted == 0)
2386 session->finCaputre.cliFinSeq = sequence;
2389 if (session->finCaputre.srvCounted == 0)
2390 session->finCaputre.srvFinSeq = sequence;
2396 /* Adjust incoming sequence based on side */
2397 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2398 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
2399 int* sslBytes, const byte** sslFrame, char* error)
2401 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
2402 session->cliSeqStart :session->srvSeqStart;
2403 word32 real = tcpInfo->sequence - seqStart;
2404 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2405 &session->cliExpected : &session->srvExpected;
2406 PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
2407 session->cliReassemblyList : session->srvReassemblyList;
2409 /* handle rollover of sequence */
2410 if (tcpInfo->sequence < seqStart)
2411 real = 0xffffffffU - seqStart + tcpInfo->sequence;
2413 TraceRelativeSequence(*expected, real);
2415 if (real < *expected) {
2416 Trace(DUPLICATE_STR);
2417 if (real + *sslBytes > *expected) {
2418 int overlap = *expected - real;
2419 Trace(OVERLAP_DUPLICATE_STR);
2421 /* adjust to expected, remove duplicate */
2422 *sslFrame += overlap;
2423 *sslBytes -= overlap;
2425 if (reassemblyList) {
2426 word32 newEnd = *expected + *sslBytes;
2428 if (newEnd > reassemblyList->begin) {
2429 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
2431 /* remove bytes already on reassembly list */
2432 *sslBytes -= newEnd - reassemblyList->begin;
2434 if (newEnd > reassemblyList->end) {
2435 Trace(OVERLAP_REASSEMBLY_END_STR);
2437 /* may be past reassembly list end (could have more on list)
2438 so try to add what's past the front->end */
2439 AddToReassembly(session->flags.side, reassemblyList->end +1,
2440 *sslFrame + reassemblyList->end - *expected + 1,
2441 newEnd - reassemblyList->end, session, error);
2448 else if (real > *expected) {
2449 Trace(OUT_OF_ORDER_STR);
2451 return AddToReassembly(session->flags.side, real, *sslFrame,
2452 *sslBytes, session, error);
2453 else if (tcpInfo->fin)
2454 return AddFinCapture(session, real);
2456 /* got expected sequence */
2457 *expected += *sslBytes;
2465 /* Check latest ack number for missing packets
2466 return 0 ok, <0 on error */
2467 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
2470 word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
2471 session->srvSeqStart :session->cliSeqStart;
2472 word32 real = tcpInfo->ackNumber - seqStart;
2473 word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2474 session->srvExpected : session->cliExpected;
2476 /* handle rollover of sequence */
2477 if (tcpInfo->ackNumber < seqStart)
2478 real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
2480 TraceAck(real, expected);
2482 if (real > expected)
2483 return -1; /* we missed a packet, ACKing data we never saw */
2489 /* Check TCP Sequence status */
2490 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2491 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
2492 SnifferSession* session, int* sslBytes,
2493 const byte** sslFrame, char* error)
2497 /* init SEQ from server to client */
2498 if (tcpInfo->syn && tcpInfo->ack) {
2499 session->srvSeqStart = tcpInfo->sequence;
2500 session->srvExpected = 1;
2501 TraceServerSyn(tcpInfo->sequence);
2505 /* adjust potential ethernet trailer */
2506 actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
2507 if (*sslBytes > actualLen) {
2508 *sslBytes = actualLen;
2511 TraceSequence(tcpInfo->sequence, *sslBytes);
2512 if (CheckAck(tcpInfo, session) < 0) {
2513 SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
2517 return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
2521 /* Check Status before record processing */
2522 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2523 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
2524 const byte** sslFrame, SnifferSession** session,
2525 int* sslBytes, const byte** end, char* error)
2528 SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
2529 (*session)->sslServer : (*session)->sslClient;
2530 /* remove SnifferSession on 2nd FIN or RST */
2531 if (tcpInfo->fin || tcpInfo->rst) {
2532 /* flag FIN and RST */
2534 (*session)->flags.finCount += 1;
2535 else if (tcpInfo->rst)
2536 (*session)->flags.finCount += 2;
2538 if ((*session)->flags.finCount >= 2) {
2539 RemoveSession(*session, ipInfo, tcpInfo, 0);
2545 if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
2546 SetError(FATAL_ERROR_STR, error, NULL, 0);
2550 if (*sslBytes == 0) {
2555 /* if current partial data, add to end of partial */
2556 if ( (length = ssl->buffers.inputBuffer.length) ) {
2557 Trace(PARTIAL_ADD_STR);
2559 if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
2560 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
2561 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
2565 XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
2566 *sslBytes += length;
2567 ssl->buffers.inputBuffer.length = *sslBytes;
2568 *sslFrame = ssl->buffers.inputBuffer.buffer;
2569 *end = *sslFrame + *sslBytes;
2572 if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
2573 /* Sanity check the packet for an old style client hello. */
2574 int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
2576 if ((rhSize <= (*sslBytes - 2)) &&
2577 (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
2578 #ifdef OLD_HELLO_ALLOWED
2579 int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
2581 return -1; /* error already set */
2587 #ifdef STARTTLS_ALLOWED
2597 /* See if input on the reassembly list is ready for consuming */
2598 /* returns 1 for TRUE, 0 for FALSE */
2599 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
2600 int* sslBytes, const byte** end, char* error)
2602 /* sequence and reassembly based on from, not to */
2604 PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
2605 &session->cliReassemblyList : &session->srvReassemblyList;
2606 word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2607 &session->cliExpected : &session->srvExpected;
2608 /* buffer is on receiving end */
2609 word32* length = (session->flags.side == WOLFSSL_SERVER_END) ?
2610 &session->sslServer->buffers.inputBuffer.length :
2611 &session->sslClient->buffers.inputBuffer.length;
2612 byte* myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
2613 session->sslServer->buffers.inputBuffer.buffer :
2614 session->sslClient->buffers.inputBuffer.buffer;
2615 word32 bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
2616 session->sslServer->buffers.inputBuffer.bufferSize :
2617 session->sslClient->buffers.inputBuffer.bufferSize;
2618 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
2619 session->sslServer : session->sslClient;
2621 while (*front && ((*front)->begin == *expected) ) {
2622 word32 room = bufferSize - *length;
2623 word32 packetLen = (*front)->end - (*front)->begin + 1;
2625 if (packetLen > room && bufferSize < MAX_INPUT_SZ) {
2626 if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
2627 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2632 if (packetLen <= room) {
2633 PacketBuffer* del = *front;
2635 XMEMCPY(&myBuffer[*length], (*front)->data, packetLen);
2636 *length += packetLen;
2637 *expected += packetLen;
2639 /* remove used packet */
2640 *front = (*front)->next;
2641 FreePacketBuffer(del);
2649 *sslFrame = myBuffer;
2650 *sslBytes = *length;
2651 *end = myBuffer + *length;
2658 /* Process Message(s) from sslFrame */
2659 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
2660 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
2661 int sslBytes, byte* data, const byte* end,char* error)
2663 const byte* sslBegin = sslFrame;
2664 const byte* recordEnd; /* end of record indicator */
2665 const byte* inRecordEnd; /* indictor from input stream not decrypt */
2666 RecordLayerHeader rh;
2670 int decoded = 0; /* bytes stored for user in data */
2671 int notEnough; /* notEnough bytes yet flag */
2672 int decrypted = 0; /* was current msg decrypted */
2673 SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
2674 session->sslServer : session->sslClient;
2678 SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
2681 if (sslBytes >= RECORD_HEADER_SZ) {
2682 if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
2683 SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
2690 if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
2691 /* don't have enough input yet to process full SSL record */
2692 Trace(PARTIAL_INPUT_STR);
2694 /* store partial if not there already or we advanced */
2695 if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
2696 if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
2697 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
2698 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2702 XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
2703 ssl->buffers.inputBuffer.length = sslBytes;
2705 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
2709 sslFrame += RECORD_HEADER_SZ;
2710 sslBytes -= RECORD_HEADER_SZ;
2711 recordEnd = sslFrame + rhSize; /* may have more than one record */
2712 inRecordEnd = recordEnd;
2714 /* decrypt if needed */
2715 if ((session->flags.side == WOLFSSL_SERVER_END &&
2716 session->flags.serverCipherOn)
2717 || (session->flags.side == WOLFSSL_CLIENT_END &&
2718 session->flags.clientCipherOn)) {
2719 int ivAdvance = 0; /* TLSv1.1 advance amount */
2720 if (ssl->decrypt.setup != 1) {
2721 SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
2724 if (CheckAvailableSize(ssl, rhSize) < 0) {
2725 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2728 sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
2729 ssl->buffers.outputBuffer.buffer, &errCode,
2731 recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so
2735 SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
2742 switch ((enum ContentType)rh.type) {
2745 int startIdx = sslBytes;
2748 Trace(GOT_HANDSHAKE_STR);
2749 ret = DoHandShake(sslFrame, &sslBytes, session, error);
2751 if (session->flags.fatalError == 0)
2752 SetError(BAD_HANDSHAKE_STR, error, session,
2757 /* DoHandShake now fully decrements sslBytes to remaining */
2758 used = startIdx - sslBytes;
2761 sslFrame += ssl->keys.padSz;
2764 case change_cipher_spec:
2765 if (session->flags.side == WOLFSSL_SERVER_END)
2766 session->flags.serverCipherOn = 1;
2768 session->flags.clientCipherOn = 1;
2769 Trace(GOT_CHANGE_CIPHER_STR);
2770 ssl->options.handShakeState = HANDSHAKE_DONE;
2771 ssl->options.handShakeDone = 1;
2777 case application_data:
2778 Trace(GOT_APP_DATA_STR);
2780 word32 inOutIdx = 0;
2782 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
2784 ret = ssl->buffers.clearOutputBuffer.length;
2786 if (ret) { /* may be blank message */
2787 XMEMCPY(&data[decoded],
2788 ssl->buffers.clearOutputBuffer.buffer, ret);
2789 TraceAddedData(ret, decoded);
2791 ssl->buffers.clearOutputBuffer.length = 0;
2795 SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
2798 if (ssl->buffers.outputBuffer.dynamicFlag)
2799 ShrinkOutputBuffer(ssl);
2801 sslFrame += inOutIdx;
2802 sslBytes -= inOutIdx;
2806 Trace(GOT_ALERT_STR);
2812 SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
2816 /* do we have another msg in record ? */
2817 if (sslFrame < recordEnd) {
2818 Trace(ANOTHER_MSG_STR);
2822 /* back to input stream instead of potential decrypt buffer */
2823 recordEnd = inRecordEnd;
2825 /* do we have more records ? */
2826 if (recordEnd < end) {
2827 Trace(ANOTHER_MSG_STR);
2828 sslFrame = recordEnd;
2829 sslBytes = (int)(end - recordEnd);
2833 /* clear used input */
2834 ssl->buffers.inputBuffer.length = 0;
2836 /* could have more input ready now */
2837 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
2840 if (ssl->buffers.inputBuffer.dynamicFlag)
2841 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
2847 /* See if we need to process any pending FIN captures */
2848 static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
2849 SnifferSession* session)
2851 if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
2852 session->cliExpected) {
2853 if (session->finCaputre.cliCounted == 0) {
2854 session->flags.finCount += 1;
2855 session->finCaputre.cliCounted = 1;
2856 TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
2860 if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
2861 session->srvExpected) {
2862 if (session->finCaputre.srvCounted == 0) {
2863 session->flags.finCount += 1;
2864 session->finCaputre.srvCounted = 1;
2865 TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
2869 if (session->flags.finCount >= 2)
2870 RemoveSession(session, ipInfo, tcpInfo, 0);
2874 /* If session is in fatal error state free resources now
2875 return true if removed, 0 otherwise */
2876 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2877 SnifferSession* session, char* error)
2879 if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
2880 RemoveSession(session, ipInfo, tcpInfo, 0);
2881 SetError(FATAL_ERROR_STR, error, NULL, 0);
2888 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
2889 /* returns Number of bytes on success, 0 for no data yet, and -1 on error */
2890 int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error)
2894 const byte* sslFrame;
2895 const byte* end = packet + length;
2896 int sslBytes; /* ssl bytes unconsumed */
2898 SnifferSession* session = 0;
2900 if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
2904 ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
2905 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2906 else if (ret == -1) return -1;
2907 else if (ret == 1) return 0; /* done for now */
2909 ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
2910 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2911 else if (ret == -1) return -1;
2912 else if (ret == 1) return 0; /* done for now */
2914 ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
2916 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2917 else if (ret == -1) return -1;
2918 else if (ret == 1) return 0; /* done for now */
2920 ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
2921 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2922 CheckFinCapture(&ipInfo, &tcpInfo, session);
2927 /* Enables (if traceFile)/ Disables debug tracing */
2928 /* returns 0 on success, -1 on error */
2929 int ssl_Trace(const char* traceFile, char* error)
2932 TraceFile = fopen(traceFile, "a");
2934 SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
2948 #endif /* WOLFSSL_SNIFFER */