?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * SSLv3 Protocol Client and Server Implementation
4 * Module for Microchip TCP/IP Stack
5 * - Implements an SSL layer supporting both client and server
6 * operation for any given TCP socket.
7 *
8 **********************************************************************
9 * FileName: SSL.c
10 * Dependencies: TCPIP.h
11 * SSL.h
12 * TCP.h
13 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
14 * Compiler: Microchip C32 v1.05 or higher
15 * Microchip C30 v3.12 or higher
16 * Microchip C18 v3.30 or higher
17 * Company: Microchip Technology, Inc.
18 *
19 * Software License Agreement
20 *
21 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
22 * reserved.
23 *
24 * Microchip licenses to you the right to use, modify, copy, and
25 * distribute:
26 * (i) the Software when embedded on a Microchip microcontroller or
27 * digital signal controller product ("Device") which is
28 * integrated into Licensee's product; or
29 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
30 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
31 * used in conjunction with a Microchip ethernet controller for
32 * the sole purpose of interfacing with the ethernet controller.
33 *
34 * You should refer to the license agreement accompanying this
35 * Software for additional information regarding your rights and
36 * obligations.
37 *
38 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
39 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
40 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
41 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
42 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
43 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
44 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
45 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
46 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
47 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
48 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
49 *
50 *
51 * Author Date Comment
52 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 * Elliott Wood 6/20/07 Original
54 * Elliott Wood 12/17/07 Rewritten to integrate with TCP
55 * and support both client & server
56 ********************************************************************/
57 #define __SSL_C
58  
59 #include "TCPIPConfig.h"
60  
61 #if defined(STACK_USE_SSL_SERVER) || defined(STACK_USE_SSL_CLIENT)
62  
63 #include "TCPIP Stack/TCPIP.h"
64  
65 /****************************************************************************
66 Section:
67 SSL Connection State Global Variables
68 ***************************************************************************/
69 #if defined(__18CXX) && !defined(HI_TECH_C)
70 #pragma udata SSL_STATE_RAM
71 #endif
72 static SSL_STUB sslStub; // The current SSL stub
73 static BYTE sslStubID; // Which SSL_STUB is loaded
74 static SSL_KEYS sslKeys; // The current SSL session
75 static BYTE sslKeysID; // Which SSL_KEYS are loaded
76 static BYTE sslBufferID; // Which buffer is loaded
77 static BYTE sslHashID; // Which hash is loaded
78 static BYTE sslSessionID; // Which session is loaded
79 static BOOL sslSessionUpdated; // Whether or not it has been updated
80 static BYTE sslRSAStubID; // Which stub is using RSA, if any
81  
82 #if defined(__18CXX) && !defined(HI_TECH_C)
83 #pragma udata SSL_LARGE_RAM
84 #endif
85 SSL_BUFFER sslBuffer; // SBox and RSA storage
86  
87 #if defined(__18CXX) && !defined(HI_TECH_C)
88 #pragma udata SSL_HASH_RAM
89 #endif
90 HASH_SUM sslHash; // Hash storage
91  
92 #if defined(__18CXX) && !defined(HI_TECH_C)
93 #pragma udata SSL_SESSION_RAM
94 #endif
95 SSL_SESSION sslSession; // Current session data
96  
97 // 8 byte session stubs
98 SSL_SESSION_STUB sslSessionStubs[MAX_SSL_SESSIONS];
99  
100 BYTE *ptrHS; // Used in buffering handshake results
101  
102 extern ROM WORD SSL_CERT_LEN; // RSA public certificate length ?
103 extern ROM BYTE SSL_CERT[]; // RSA public certificate data ?
104  
105 #if defined(__18CXX) && !defined(HI_TECH_C)
106 #pragma udata
107 #endif
108  
109 /****************************************************************************
110 Section:
111 Function Prototypes
112 ***************************************************************************/
113 // Section: Cryptographic Calculation Functions
114 static RSA_STATUS SSLRSAOperation(void);
115 static void GenerateHashRounds(BYTE num, BYTE* rand1, BYTE* rand2);
116 static void CalculateFinishedHash(BYTE hashID, BOOL fromClient, BYTE *result);
117 static void GenerateSessionKeys(void);
118  
119 // Section: Ethernet Buffer RAM Management
120 static void SSLStubSync(BYTE id);
121 static BOOL SSLStubAlloc(void);
122 static void SSLStubFree(BYTE id);
123 static void SSLKeysSync(BYTE id);
124 static void SSLHashSync(BYTE id);
125 static void SSLHashAlloc(BYTE *id);
126 static void SSLHashFree(BYTE *id);
127 static void SSLBufferSync(BYTE id);
128 static void SSLBufferAlloc(BYTE *id);
129 static void SSLBufferFree(BYTE *id);
130 static BYTE SSLSessionNew(void);
131 static void SSLSessionSync(BYTE id);
132 #define SSLSessionUpdated() sslSessionUpdated = TRUE;
133 static void SaveOffChip(BYTE *ramAddr, PTR_BASE ethAddr, WORD len);
134 static void LoadOffChip(BYTE *ramAddr, PTR_BASE ethAddr, WORD len);
135  
136 // Section: Handshake Hash and I/O Functions
137 static void HSStart(void);
138 static void HSEnd(void);
139 static WORD HSGet(TCP_SOCKET skt, BYTE *b);
140 static WORD HSGetWord(TCP_SOCKET skt, WORD *w);
141 static WORD HSGetArray(TCP_SOCKET skt, BYTE *data, WORD len);
142 static WORD HSPut(TCP_SOCKET skt, BYTE b);
143 static WORD HSPutWord(TCP_SOCKET skt, WORD w);
144 static WORD HSPutArray(TCP_SOCKET skt, BYTE *data, WORD len);
145 #if defined(STACK_USE_SSL_SERVER)
146 static WORD HSPutROMArray(TCP_SOCKET skt, ROM BYTE *data, WORD len);
147 #endif
148  
149 // Section: Client messages
150 #if defined(STACK_USE_SSL_CLIENT)
151 static BYTE SSLSessionMatchIP(IP_ADDR ip);
152 static void SSLTxClientHello(TCP_SOCKET hTCP);
153 static void SSLRxServerHello(TCP_SOCKET hTCP);
154 static void SSLRxServerCertificate(TCP_SOCKET hTCP);
155 static void SSLTxClientKeyExchange(TCP_SOCKET hTCP);
156 #endif
157  
158 // Section: Server messages
159 #if defined(STACK_USE_SSL_SERVER)
160 static BYTE SSLSessionMatchID(BYTE* SessionID);
161 static void SSLRxAntiqueClientHello(TCP_SOCKET hTCP);
162 static void SSLRxClientHello(TCP_SOCKET hTCP);
163 static void SSLTxServerHello(TCP_SOCKET hTCP);
164 static void SSLTxServerCertificate(TCP_SOCKET hTCP);
165 static void SSLTxServerHelloDone(TCP_SOCKET hTCP);
166 static void SSLRxClientKeyExchange(TCP_SOCKET hTCP);
167 #endif
168  
169 // Section: Client and server messages
170 static void SSLTxCCSFin(TCP_SOCKET hTCP);
171 static void SSLRxCCS(TCP_SOCKET hTCP);
172 static void SSLRxFinished(TCP_SOCKET hTCP);
173 static void SSLRxAlert(TCP_SOCKET hTCP);
174  
175 /****************************************************************************
176 Section:
177 Macros and Definitions
178 ***************************************************************************/
179 #define mMIN(a, b) ((a<b)?a:b)
180  
181 #define SSL_RSA_EXPORT_WITH_ARCFOUR_40_MD5 0x0003u
182 #define SSL_RSA_WITH_ARCFOUR_128_MD5 0x0004u
183  
184 /****************************************************************************
185 Section:
186 Resource Management Variables
187 ***************************************************************************/
188 WORD isStubUsed; // Indicates which stubs are in use
189 WORD isHashUsed; // Indicates which hashes are in use
190 WORD isBufferUsed; // Indicates which buffers are in use
191  
192 // Masks for each bit in the is*Used variables
193 static ROM WORD masks[16] = { 0x0001, 0x0002, 0x0004, 0x0008,
194 0x0010, 0x0020, 0x0040, 0x0080,
195 0x0100, 0x0200, 0x0400, 0x0800,
196 0x1000, 0x2000, 0x4000, 0x8000 };
197  
198 // Base address for SSL stubs
199 #define SSL_BASE_STUB_ADDR (BASE_SSLB_ADDR)
200  
201 // Base address for SSL keys
202 #define SSL_BASE_KEYS_ADDR (BASE_SSLB_ADDR + SSL_STUB_SPACE)
203  
204 // Base address for SSL hashes
205 #define SSL_BASE_HASH_ADDR (BASE_SSLB_ADDR + SSL_STUB_SPACE + SSL_KEYS_SPACE)
206  
207 // Base address for SSL buffers
208 #define SSL_BASE_BUFFER_ADDR (BASE_SSLB_ADDR + SSL_STUB_SPACE + SSL_KEYS_SPACE + SSL_HASH_SPACE)
209  
210 // Base address for SSL sessions
211 #define SSL_BASE_SESSION_ADDR (BASE_SSLB_ADDR + SSL_STUB_SPACE + SSL_KEYS_SPACE + SSL_HASH_SPACE + SSL_BUFFER_SPACE)
212  
213  
214 /****************************************************************************
215 ===========================================================================
216 Section:
217 SSL Management Functions
218 ===========================================================================
219 ***************************************************************************/
220  
221 /*****************************************************************************
222 Function:
223 void SSLInit(void)
224  
225 Description:
226 Initializes the SSL engine.
227  
228 Precondition:
229 None
230  
231 Parameters:
232 None
233  
234 Returns:
235 None
236  
237 Remarks:
238 This function is called only one during lifetime of the application.
239 ***************************************************************************/
240 void SSLInit(void)
241 {
242 // Set all resources to unused
243 isStubUsed = 0;
244 isHashUsed = 0;
245 isBufferUsed = 0;
246 for(sslSessionID = 0; sslSessionID < MAX_SSL_SESSIONS; sslSessionID++)
247 sslSessionStubs[sslSessionID].tag.Val = 0;
248  
249 // Indicate that nothing is loaded
250 sslHashID = SSL_INVALID_ID;
251 sslStubID = SSL_INVALID_ID;
252 sslSessionID = SSL_INVALID_ID;
253 sslKeysID = SSL_INVALID_ID;
254 sslBufferID = SSL_INVALID_ID;
255 sslSessionUpdated = FALSE;
256 sslRSAStubID = SSL_INVALID_ID;
257 }
258  
259 /*****************************************************************************
260 Function:
261 void SSLPeriodic(TCP_SOCKET hTCP, BYTE id)
262  
263 Summary:
264 Performs any periodic tasks for the SSL module.
265  
266 Description:
267 This function performs periodic tasks for the SSL module. This includes
268 processing for RSA operations.
269  
270 Precondition:
271 SSL has already been initialized.
272  
273 Parameters:
274 hTCP - the socket for which to perform periodic functions
275 id - the SSL stub to use
276  
277 Returns:
278 None
279  
280 ***************************************************************************/
281 void SSLPeriodic(TCP_SOCKET hTCP, BYTE id)
282 {
283 // Sync the SSL Stub
284 SSLStubSync(id);
285  
286 // For new sessions, try to claim a session
287 if(sslStub.Flags.bNewSession && sslStub.idSession == SSL_INVALID_ID)
288 {
289 sslStub.idSession = SSLSessionNew();
290 }
291  
292 // If RSA is in progress, do some RSA work
293 if(sslStub.Flags.bRSAInProgress)
294 {
295 if(SSLRSAOperation() == RSA_DONE)
296 {// Move on with the connection
297 sslStub.Flags.bRSAInProgress = 0;
298  
299 // For clients, request the CKE message
300 #if defined(STACK_USE_SSL_CLIENT)
301 if(!sslStub.Flags.bIsServer)
302 TCPRequestSSLMessage(hTCP, SSL_CLIENT_KEY_EXCHANGE);
303 #endif
304  
305 // For servers, copy the decoded message to the session data
306 #if defined(STACK_USE_SSL_SERVER)
307 if(sslStub.Flags.bIsServer)
308 {
309 // Copy over the pre-master secret
310 SSLSessionSync(sslStub.idSession);
311 memcpy((void*)sslSession.masterSecret, (void*)&sslBuffer.full[16], 48);
312  
313 // Generate the Master Secret
314 SSLKeysSync(sslStubID);
315 SSLBufferSync(SSL_INVALID_ID);
316 GenerateHashRounds(3, sslKeys.Remote.random, sslKeys.Local.random);
317 memcpy(sslSession.masterSecret, (void*)sslBuffer.hashRounds.temp, 48);
318  
319 // Note the new session data and release RSA engine
320 SSLSessionUpdated();
321 RSAEndUsage();
322 sslRSAStubID = SSL_INVALID_ID;
323 }
324  
325 // Continue receiving the CCS and Finished messages
326 TCPSSLHandleIncoming(hTCP);
327 #endif
328 }
329 }
330 }
331  
332 /*****************************************************************************
333 Function:
334 BYTE SSLStartSession(TCP_SOCKET hTCP, BYTE * buffer, BYTE supDataType)
335  
336 Description:
337 Begins a new SSL session for the given TCP connection.
338  
339 Precondition:
340 SSL has been initialized and hTCP is connected.
341  
342 Parameters:
343 hTCP - the socket to begin the SSL connection on
344 buffer - pointer to a supplementary data buffer
345 supDataType - type of supplementary data to store
346  
347 Return Values:
348 SSL_INVALID_ID - insufficient SSL resources to start a new connection
349 others - the allocated SSL stub ID
350 ***************************************************************************/
351 BYTE SSLStartSession(TCP_SOCKET hTCP, void * buffer, BYTE supDataType)
352 {
353 BYTE i;
354  
355 // Allocate a stub for use, or fail
356 if(!SSLStubAlloc())
357 return SSL_INVALID_ID;
358  
359 // Clear stub state
360 sslStub.wRxBytesRem = 0;
361 sslStub.wRxHsBytesRem = 0;
362 *(WORD*)&sslStub.Flags = 0x0000;
363  
364 // Clear any allocations
365 sslStub.idSession = SSL_INVALID_ID;
366 sslStub.idRxHash = SSL_INVALID_ID;
367 sslStub.idMD5 = SSL_INVALID_ID;
368 sslStub.idSHA1 = SSL_INVALID_ID;
369 sslStub.idRxBuffer = SSL_INVALID_ID;
370 sslStub.idTxBuffer = SSL_INVALID_ID;
371 sslStub.requestedMessage = SSL_NO_MESSAGE;
372 sslStub.dwTemp.Val = 0;
373 sslStub.supplementaryBuffer = buffer;
374 sslStub.supplementaryDataType = supDataType;
375  
376 // Allocate handshake hashes for use, or fail
377 SSLHashAlloc(&sslStub.idMD5);
378 SSLHashAlloc(&sslStub.idSHA1);
379 if(sslStub.idMD5 == SSL_INVALID_ID || sslStub.idSHA1 == SSL_INVALID_ID)
380 {
381 SSLHashFree(&sslStub.idMD5);
382 SSLHashFree(&sslStub.idSHA1);
383 SSLStubFree(sslStubID);
384 return SSL_INVALID_ID;
385 }
386  
387 // Initialize the handshake hashes
388 SSLHashSync(sslStub.idSHA1);
389 SHA1Initialize(&sslHash);
390 SSLHashSync(sslStub.idMD5);
391 MD5Initialize(&sslHash);
392  
393 // Set up Local.random (4 byte UTC time, 28 bytes random)
394 SSLKeysSync(sslStubID);
395 #if defined(STACK_USE_SNTP_CLIENT)
396 {
397 DWORD_VAL temp;
398  
399 temp.Val = SNTPGetUTCSeconds();
400 sslKeys.Local.random[0] = temp.v[3];
401 sslKeys.Local.random[1] = temp.v[2];
402 sslKeys.Local.random[2] = temp.v[1];
403 sslKeys.Local.random[3] = temp.v[0];
404 i = 4;
405 }
406 #else
407 i = 0;
408 #endif
409 while(i < 32u)
410 sslKeys.Local.random[i++] = RandomGet();
411  
412 // Return the ID
413 return sslStubID;
414 }
415  
416 /*****************************************************************************
417 Function:
418 void SSLTerminate(BYTE id)
419  
420 Description:
421 Terminates an SSL connection and releases allocated resources.
422  
423 Precondition:
424 None
425  
426 Parameters:
427 id - the SSL stub ID to terminate
428  
429 Returns:
430 None
431 ***************************************************************************/
432 void SSLTerminate(BYTE id)
433 {
434 // Sync in the right stub
435 SSLStubSync(id);
436  
437 // If no CloseNotify, then invalidate the session so it cannot resume
438 // ( This restriction is not presently enforced. IE incorrectly
439 // completes the handshake, then disconnects without a CloseNotify
440 // when it decides to prompt the user whether or not to accept a
441 // unverifiable certificate. )
442 //if(!sslStub.Flags.bCloseNotify)
443 //{
444 // sslSessionStubs[sslStub.idSession].tag.Val = 0;
445 //}
446  
447 // Free up resources
448 SSLBufferFree(&sslStub.idRxBuffer);
449 SSLBufferFree(&sslStub.idTxBuffer);
450 SSLHashFree(&sslStub.idMD5);
451 SSLHashFree(&sslStub.idSHA1);
452 SSLHashFree(&sslStub.idRxHash);
453 SSLStubFree(id);
454 if(sslRSAStubID == id)
455 {
456 sslRSAStubID = SSL_INVALID_ID;
457 RSAEndUsage();
458 }
459  
460 }
461  
462 /****************************************************************************
463 ===========================================================================
464 Section:
465 SSL Record Processing Functions
466 ===========================================================================
467 ***************************************************************************/
468  
469 /*****************************************************************************
470 Function:
471 WORD SSLRxRecord(TCP_SOCKET hTCP, BYTE id)
472  
473 Summary:
474 Receives an SSL record.
475  
476 Description:
477 Reads at most one SSL Record header from the TCP stream and determines what
478 to do with the rest of the data. If not all of the data is available for
479 the record, then the function returns and future call(s) to SSLRxRecord()
480 will process the remaining data until the end of the record is reached.
481 If this call process data from a past record, the next record will not be
482 started until the next call.
483  
484 Precondition:
485 The specified SSL stub is initialized and the TCP socket is connected.
486  
487 Parameters:
488 hTCP - The TCP socket from which to read
489 id - The active SSL stub ID
490  
491 Returns:
492 WORD indicating the number of data bytes there were decrypted but left in
493 the stream.
494  
495 Remarks:
496 SSL record headers, MAC footers, and symetric cipher block padding (if any)
497 will be extracted from the TCP stream by this function. Data will be
498 decrypted but left in the stream.
499 ***************************************************************************/
500 WORD SSLRxRecord(TCP_SOCKET hTCP, BYTE id)
501 {
502 BYTE temp[32];
503 WORD wLen;
504  
505 SSLStubSync(id);
506  
507 // Don't do anything for terminated connections
508 if(sslStub.Flags.bDone)
509 return 0;
510  
511 // If this is a new record, then read the header
512 // When bytes remain, a message is not yet fully read, so
513 // the switch statement will continue handling the data
514 if(sslStub.wRxBytesRem == 0u)
515 {
516 // See if we expect a MAC
517 if(sslStub.Flags.bExpectingMAC)
518 {// Receive and verify the MAC
519 if(TCPIsGetReady(hTCP) < 16u)
520 return 0;
521  
522 // Read the MAC
523 TCPGetArray(hTCP, temp, 16);
524  
525 // Calculate the expected MAC
526 SSLBufferSync(sslStub.idRxBuffer);
527 SSLKeysSync(id);
528 SSLHashSync(sslStub.idRxHash);
529  
530 ARCFOURCrypt(&sslKeys.Remote.app.cryptCtx, temp, 16);
531 SSLMACCalc(sslKeys.Remote.app.MACSecret, &temp[16]);
532  
533 // MAC no longer expected
534 sslStub.Flags.bExpectingMAC = 0;
535  
536 // Verify the MAC
537 if(memcmp((void*)temp, (void*)&temp[16], 16) != 0)
538 {// MAC fails
539 TCPRequestSSLMessage(hTCP, SSL_ALERT_BAD_RECORD_MAC);
540 return 0;
541 }
542 }
543  
544 // Check if a new header is available
545 // Also ignore data if SSL is terminated
546 if(TCPIsGetReady(hTCP) < 5u)
547 return 0;
548  
549 // Read the record type (BYTE)
550 TCPGet(hTCP, &sslStub.rxProtocol);
551  
552 #if defined(STACK_USE_SSL_SERVER)
553 // Check if we've received an SSLv2 ClientHello message
554 // Client-only implementations don't need to deal with this
555 if((sslStub.rxProtocol & 0x80) == 0x80)
556 {
557 // After MSB, next 15 bits are the length
558 ((BYTE*)&sslStub.wRxBytesRem)[1] = sslStub.rxProtocol & 0x7F;
559 TCPGet(hTCP, ((BYTE*)&sslStub.wRxBytesRem));
560  
561 // Tell the handshaker what message to expect
562 sslStub.wRxHsBytesRem = sslStub.wRxBytesRem;
563 sslStub.rxProtocol = SSL_HANDSHAKE;
564 sslStub.rxHSType = SSL_ANTIQUE_CLIENT_HELLO;
565 }
566  
567 // Otherwise, this is a normal SSLv3 message
568 // Read the rest of the record header and proceed normally
569 else
570 #endif
571 {
572 // Read version (WORD, currently ignored)
573 TCPGet(hTCP, NULL);
574 TCPGet(hTCP, NULL);
575  
576 // Read length (WORD)
577 TCPGet(hTCP, ((BYTE*)&sslStub.wRxBytesRem)+1);
578 TCPGet(hTCP, ((BYTE*)&sslStub.wRxBytesRem));
579  
580 // Determine if a MAC is expected
581 if(sslStub.Flags.bRemoteChangeCipherSpec)
582 {
583 sslStub.Flags.bExpectingMAC = 1;
584 sslStub.wRxBytesRem -= 16;
585  
586 // Set up the MAC
587 SSLKeysSync(sslStubID);
588 SSLHashSync(sslStub.idRxHash);
589 SSLMACBegin(sslKeys.Remote.app.MACSecret,
590 sslKeys.Remote.app.sequence++,
591 sslStub.rxProtocol, sslStub.wRxBytesRem);
592 }
593 }
594  
595 }
596  
597 // See if data is ready that needs decryption
598 wLen = TCPIsGetReady(hTCP);
599  
600 // Decrypt and MAC if necessary
601 if(sslStub.Flags.bRemoteChangeCipherSpec && wLen)
602 {// Need to decrypt the data
603  
604 // Only decrypt up to end of record
605 if(wLen > sslStub.wRxBytesRem)
606 wLen = sslStub.wRxBytesRem;
607  
608 // Prepare for decryption
609 SSLKeysSync(id);
610 SSLBufferSync(sslStub.idRxBuffer);
611 SSLHashSync(sslStub.idRxHash);
612  
613 // Decrypt application data to proper location, non-app in place
614 TCPSSLDecryptMAC(hTCP, &sslKeys.Remote.app.cryptCtx, wLen);
615 }
616  
617 // Determine what to do with the rest of the data
618 switch(sslStub.rxProtocol)
619 {
620 case SSL_HANDSHAKE:
621 SSLRxHandshake(hTCP);
622 break;
623  
624 case SSL_CHANGE_CIPHER_SPEC:
625 SSLRxCCS(hTCP);
626 break;
627  
628 case SSL_APPLICATION:
629 // Data was handled above
630 // Just note that it's all been read
631 sslStub.wRxBytesRem -= wLen;
632 return wLen;
633  
634 case SSL_ALERT:
635 SSLRxAlert(hTCP);
636 break;
637 }
638  
639 return 0;
640 }
641  
642 /*****************************************************************************
643 Function:
644 void SSLTxRecord(TCP_SOCKET hTCP, BYTE id, BYTE txProtocol)
645  
646 Summary:
647 Transmits an SSL record.
648  
649 Description:
650 Transmits all pending data in the TCP TX buffer as an SSL record using
651 the specified protocol. This function transparently encrypts and MACs
652 the data if there is an active cipher spec.
653  
654 Precondition:
655 The specified SSL stub is initialized and the TCP socket is connected.
656  
657 Parameters:
658 hTCP - The TCP socket with data waiting to be transmitted
659 id - The active SSL stub ID
660 txPortocol - The SSL protocol number to attach to this record
661  
662 Returns:
663 None
664 ***************************************************************************/
665 void SSLTxRecord(TCP_SOCKET hTCP, BYTE id, BYTE txProtocol)
666 {
667 WORD_VAL wLen;
668 BYTE hdr[5];
669  
670 SSLStubSync(id);
671  
672 // If stub is done, prevent writing data
673 if(sslStub.Flags.bDone)
674 return;
675  
676 // Determine how many bytes are ready to write
677 wLen.Val = TCPSSLGetPendingTxSize(hTCP);
678 if(wLen.Val == 0u)
679 return;
680  
681 // Determine if a MAC is required
682 if(sslStub.Flags.bLocalChangeCipherSpec)
683 {// Perform the encryption and MAC
684 // Sync needed data
685 SSLKeysSync(sslStubID);
686 SSLHashSync(SSL_INVALID_ID);
687 SSLBufferSync(sslStub.idTxBuffer);
688  
689 // Start the MAC calculation
690 SSLMACBegin(sslKeys.Local.app.MACSecret,
691 sslKeys.Local.app.sequence, txProtocol, wLen.Val);
692 sslKeys.Local.app.sequence++;
693  
694 // Get ready to send
695 TCPSSLInPlaceMACEncrypt(hTCP, &sslKeys.Local.app.cryptCtx,
696 sslKeys.Local.app.MACSecret, wLen.Val);
697  
698 // Add MAC length to the data length
699 wLen.Val += 16;
700 }
701  
702 // Prepare the header
703 hdr[0] = txProtocol;
704 hdr[1] = SSL_VERSION_HI;
705 hdr[2] = SSL_VERSION_LO;
706 hdr[3] = wLen.v[1];
707 hdr[4] = wLen.v[0];
708  
709 // Put the record header and send the data
710 TCPSSLPutRecordHeader(hTCP, hdr, TRUE);
711  
712 }
713  
714 /*****************************************************************************
715 Function:
716 void SSLStartPartialRecord(TCP_SOCKET hTCP, BYTE id, BYTE txProtocol,
717 WORD wLen)
718  
719 Summary:
720 Begins a long SSL record.
721  
722 Description:
723 This function allows messages longer than the TCP buffer to be sent,
724 which is frequently the case for the Certificate handshake message. The
725 final message length is required to be known in order to transmit the
726 header. Once called, SSLFlushPartialRecord and SSLFinishPartialRecord
727 must be called to write remaining data, finalize, and prepare for a new
728 record.
729  
730 Precondition:
731 The specified SSL stub is initialized and the TCP socket is connected.
732  
733 Parameters:
734 hTCP - The TCP socket with data waiting to be transmitted
735 id - The active SSL stub ID
736 txPortocol - The SSL protocol number to attach to this record
737 wLen - The length of all the data to be sent
738  
739 Returns:
740 None
741  
742 Remarks:
743 Partial messages do not support the current cipher spec, so this can
744 only be used during the handshake procedure.
745 ***************************************************************************/
746 #if defined(STACK_USE_SSL_SERVER)
747 void SSLStartPartialRecord(TCP_SOCKET hTCP, BYTE id, BYTE txProtocol, WORD wLen)
748 {
749 BYTE hdr[5];
750  
751 SSLStubSync(id);
752  
753 // Prepare the header
754 hdr[0] = txProtocol;
755 hdr[1] = SSL_VERSION_HI;
756 hdr[2] = SSL_VERSION_LO;
757 hdr[3] = wLen >> 8;
758 hdr[4] = wLen;
759  
760 // Put the record header and send the data
761 TCPSSLPutRecordHeader(hTCP, hdr, FALSE);
762  
763 }
764 #endif
765  
766 /*****************************************************************************
767 Function:
768 void SSLTxMessage(TCP_SOCKET hTCP, BYTE id, BYTE msg)
769  
770 Summary:
771 Transmits an SSL message.
772  
773 Description:
774 This function transmits a specific SSL message for handshakes and alert
775 messages. Supported messages are listed in SSL_MESSAGES.
776  
777 Precondition:
778 The specified SSL stub is initialized and the TCP socket is connected.
779  
780 Parameters:
781 hTCP - The TCP socket with data waiting to be transmitted
782 id - The active SSL stub ID
783 msg - One of the SSL_MESSAGES types to send
784  
785 Returns:
786 None
787 ***************************************************************************/
788 void SSLTxMessage(TCP_SOCKET hTCP, BYTE id, BYTE msg)
789 {
790 SSLStubSync(id);
791  
792 // Don't do anything for terminated connections
793 if(sslStub.Flags.bDone)
794 return;
795  
796 // Transmit the requested message
797 switch(msg)
798 {
799 #if defined(STACK_USE_SSL_CLIENT)
800 case SSL_CLIENT_HELLO:
801 SSLTxClientHello(hTCP);
802 break;
803 case SSL_CLIENT_KEY_EXCHANGE:
804 SSLTxClientKeyExchange(hTCP);
805 break;
806 #endif
807  
808 #if defined(STACK_USE_SSL_SERVER)
809 case SSL_SERVER_HELLO:
810 SSLTxServerHello(hTCP);
811 break;
812 case SSL_CERTIFICATE:
813 SSLTxServerCertificate(hTCP);
814 break;
815 case SSL_SERVER_HELLO_DONE:
816 SSLTxServerHelloDone(hTCP);
817 break;
818 #endif
819  
820 case SSL_CHANGE_CIPHER_SPEC:
821 SSLTxCCSFin(hTCP);
822 break;
823  
824 // Handle all alert messages
825 default:
826 if((msg & 0x80) != 0x80)
827 break;
828  
829 // Make sure we can write the message
830 if(TCPIsPutReady(hTCP) < 2u)
831 break;
832  
833 // Select FATAL or WARNING
834 if(msg == SSL_ALERT_CLOSE_NOTIFY)
835 {
836 TCPPut(hTCP, SSL_ALERT_WARNING);
837 sslStub.Flags.bCloseNotify = 1;
838 }
839 else
840 TCPPut(hTCP, SSL_ALERT_FATAL);
841  
842 // Put the message byte
843 TCPPut(hTCP, msg - 0x80);
844  
845 // Flush the message
846 SSLTxRecord(hTCP, sslStubID, SSL_ALERT);
847 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
848  
849 // Mark session as terminated
850 sslStub.Flags.bDone = 1;
851 }
852  
853 }
854  
855 /*****************************************************************************
856 Function:
857 void SSLRxHandshake(TCP_SOCKET hTCP)
858  
859 Summary:
860 Receives a handshake message.
861  
862 Description:
863 This function receives handshake messages, reads the handshake header,
864 and passes the data off to the appropriate handshake parser.
865  
866 Precondition:
867 The specified SSL stub is initialized and the TCP socket is connected.
868 Also requires that rxBytesRem has been populated and the current SSL stub
869 has been synced into memory.
870  
871 Parameters:
872 hTCP - The TCP socket to read a handshake message from
873  
874 Returns:
875 None
876 ***************************************************************************/
877 void SSLRxHandshake(TCP_SOCKET hTCP)
878 {
879 WORD wLen;
880  
881 // Start reading handshake data
882 HSStart();
883  
884 // If this is a new handshake message, read the header
885 // If the message has already been started, there will
886 // still be bytes remaining and the switch statement will
887 // handle the rest.
888 if(sslStub.wRxHsBytesRem == 0u)
889 {
890 // Make sure entire header is in the buffer
891 if(TCPIsGetReady(hTCP) < 4u)
892 return;
893  
894 // Read the message type (BYTE)
895 HSGet(hTCP, &sslStub.rxHSType);
896  
897 // Read the length (3 BYTES)
898 HSGet(hTCP, NULL);
899 HSGetWord(hTCP, &wLen);
900 sslStub.wRxHsBytesRem = wLen;
901 }
902  
903 // Determine what to do with the rest of the data
904 switch(sslStub.rxHSType)
905 {
906 #if defined(STACK_USE_SSL_CLIENT)
907 case SSL_SERVER_HELLO:
908 SSLRxServerHello(hTCP);
909 break;
910  
911 case SSL_CERTIFICATE:
912 SSLRxServerCertificate(hTCP);
913 break;
914  
915 case SSL_SERVER_HELLO_DONE:
916 // This message contains no data
917 // Record that message was received
918 sslStub.Flags.bServerHelloDone = 1;
919 break;
920 #endif
921  
922 #if defined(STACK_USE_SSL_SERVER)
923 case SSL_ANTIQUE_CLIENT_HELLO:
924 SSLRxAntiqueClientHello(hTCP);
925 break;
926  
927 case SSL_CLIENT_HELLO:
928 SSLRxClientHello(hTCP);
929 break;
930  
931 case SSL_CLIENT_KEY_EXCHANGE:
932 SSLRxClientKeyExchange(hTCP);
933 break;
934 #endif
935  
936 case SSL_FINISHED:
937 SSLRxFinished(hTCP);
938 break;
939 }
940  
941 // End reading handshake data
942 HSEnd();
943  
944 }
945  
946  
947 /****************************************************************************
948 ===========================================================================
949 Section:
950 SSL Message Processing Functions
951 ===========================================================================
952 ***************************************************************************/
953  
954 /*********************************************************************
955 * Function: BYTE SSLTxClientHello(TCP_SOCKET hTCP)
956 *
957 * PreCondition: Enough space is available in hTCP to write the
958 * entire message.
959 *
960 * Input: hTCP - the TCP Socket to send the message to
961 *
962 * Output: None
963 *
964 * Side Effects: None
965 *
966 * Overview: Transmits the ClientHello message to initiate a
967 * new SSL session with the server.
968 *
969 * Note: None
970 ********************************************************************/
971 #if defined(STACK_USE_SSL_CLIENT)
972 static void SSLTxClientHello(TCP_SOCKET hTCP)
973 {
974 // Restart the handshake hasher
975 HSStart();
976  
977 // Indicate that we're the client
978 //sslStub.Flags.bIsServer = 0; // This is the default already
979  
980 // Make sure enough space is available to transmit
981 if(TCPIsPutReady(hTCP) < 100u)
982 return;
983  
984 // Look for a valid session to reuse
985 sslStub.idSession = SSLSessionMatchIP(TCPGetRemoteInfo(hTCP)->remote.IPAddr);
986 sslStub.Flags.bNewSession = (sslStub.idSession == SSL_INVALID_ID);
987  
988 // If none is found, generate a new one
989 if(sslStub.Flags.bNewSession)
990 {
991 sslStub.idSession = SSLSessionNew();
992 if(sslStub.idSession == SSL_INVALID_ID)
993 {// No free sessions, so abort
994 return;
995 }
996  
997 // Mark session as using this IP
998 memcpy((void*)&sslSessionStubs[sslStub.idSession].tag.v[0],
999 (void*)&(TCPGetRemoteInfo(hTCP)->remote.IPAddr), 4);
1000 }
1001  
1002 // Send handshake message header (hashed)
1003 HSPut(hTCP, SSL_CLIENT_HELLO);
1004 HSPut(hTCP, 0x00);
1005 HSPut(hTCP, 0x00); // Message length is 40 bytes,
1006 if(sslStub.Flags.bNewSession) // plus 32 more if a session
1007 HSPut(hTCP, 43); // ID is being included.
1008 else
1009 HSPut(hTCP, 43+32);
1010  
1011 // Send
1012 HSPut(hTCP, SSL_VERSION_HI);
1013 HSPut(hTCP, SSL_VERSION_LO);
1014  
1015 // Put Client.Random
1016 HSPutArray(hTCP, sslKeys.Local.random, 32);
1017  
1018 // Put Session ID
1019 if(sslStub.Flags.bNewSession)
1020 {// Send no session ID
1021 HSPut(hTCP, 0x00);
1022 }
1023 else
1024 {// Send the requested Session ID
1025 SSLSessionSync(sslStub.idSession);
1026 HSPut(hTCP, 0x20);
1027 HSPutArray(hTCP, sslSession.sessionID, 32);
1028 }
1029  
1030 // Put Cipher Suites List
1031 HSPutWord(hTCP, 0x0004);
1032 HSPutWord(hTCP, SSL_RSA_WITH_ARCFOUR_128_MD5);
1033 HSPutWord(hTCP, SSL_RSA_EXPORT_WITH_ARCFOUR_40_MD5);
1034  
1035 // Put Compression Methods List (just null)
1036 HSPut(hTCP, 0x01);
1037 HSPut(hTCP, 0x00);
1038  
1039 // End the handshake and save the hash
1040 HSEnd();
1041  
1042 // Send record
1043 SSLTxRecord(hTCP, sslStubID, SSL_HANDSHAKE);
1044  
1045 // Record that message was sent
1046 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
1047 sslStub.Flags.bClientHello = 1;
1048  
1049 }
1050 #endif
1051  
1052 /*********************************************************************
1053 * Function: BYTE SSLRxClientHello(TCP_SOCKET hTCP)
1054 *
1055 * PreCondition: Handshake hasher is started, and SSL has a stub
1056 * assigned.
1057 *
1058 * Input: hTCP - the TCP Socket to send the message to
1059 *
1060 * Output: None
1061 *
1062 * Side Effects: None
1063 *
1064 * Overview: Receives the ClientHello message, initiating a
1065 * new SSL session with a client
1066 *
1067 * Note: None
1068 ********************************************************************/
1069 #if defined(STACK_USE_SSL_SERVER)
1070 static void SSLRxClientHello(TCP_SOCKET hTCP)
1071 {
1072 WORD w;
1073 BYTE c, *ptrID;
1074  
1075 // Make sure entire message is ready
1076 if(TCPIsGetReady(hTCP) < sslStub.wRxHsBytesRem)
1077 return;
1078  
1079 // Verify handshake message sequence
1080 if(sslStub.Flags.bClientHello)
1081 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1082  
1083 // Indicate that we're the server
1084 sslStub.Flags.bIsServer = 1;
1085  
1086 // Read the version again
1087 HSGetWord(hTCP, &w);
1088 // Ignore the version here. It must be at least 3.0 to receive this type
1089 // of message, and Safari 3.1 sends 0x0301 (TLS 1.0) even when the last
1090 // connection was only 0x0300 (SSL 3.0)
1091  
1092 // Make sure the session keys are synced
1093 SSLKeysSync(sslStubID);
1094  
1095 // Read the Client.Random array
1096 HSGetArray(hTCP, sslKeys.Remote.random, 32);
1097  
1098 // Read the Session ID length
1099 HSGet(hTCP, &c);
1100  
1101 // Read the Session ID if it exists
1102 sslStub.Flags.bNewSession = TRUE;
1103 if(c > 0u)
1104 {
1105 // Note where it will be stored in RAM
1106 ptrID = ptrHS;
1107 HSGetArray(hTCP, NULL, c);
1108  
1109 // Try to match it with a known session
1110 sslStub.idSession = SSLSessionMatchID(ptrID);
1111 if(sslStub.idSession != SSL_INVALID_ID)
1112 sslStub.Flags.bNewSession = FALSE;
1113 }
1114  
1115 // If we we're starting a new session, try to obtain a free one
1116 if(sslStub.Flags.bNewSession)
1117 sslStub.idSession = SSLSessionNew();
1118  
1119 // Read CipherSuites length
1120 HSGetWord(hTCP, &w);
1121  
1122 // Check for an acceptable CipherSuite
1123 // Right now we just ignore this and assume support for
1124 // SSL_RSA_WITH_ARCFOUR_128_MD5. If we request this suite later
1125 // and it isn't supported, the client will kill the connection.
1126 HSGetArray(hTCP, NULL, w);
1127  
1128 // Read the Compression Methods length
1129 HSGet(hTCP, &c);
1130  
1131 // Check for an acceptable Compression Method
1132 // Right now we just ignore this and assume support for
1133 // NULL_COMPRESSION. If we request this later and the client
1134 // doesn't really support it, they'll kill the connection.
1135 HSGetArray(hTCP, NULL, c);
1136  
1137 // For TLS compatibility, we must ignore further bytes in ClientHello.
1138 // FF2+ may send "extensions" ad other things we don't support
1139 HSGetArray(hTCP, NULL, sslStub.wRxBytesRem);
1140  
1141 // Mark message as received and request a ServerHello
1142 sslStub.Flags.bClientHello = 1;
1143 TCPRequestSSLMessage(hTCP, SSL_SERVER_HELLO);
1144  
1145 }
1146 #endif
1147  
1148 /*********************************************************************
1149 * Function: BYTE SSLRxAntiqueClientHello(TCP_SOCKET hTCP)
1150 *
1151 * PreCondition: Handshake hasher is started, and SSL has a stub
1152 * assigned.
1153 *
1154 * Input: hTCP - the TCP Socket to send the message to
1155 *
1156 * Output: None
1157 *
1158 * Side Effects: None
1159 *
1160 * Overview: Receives the SSLv2 ClientHello message, initiating
1161 * a new SSL session with a client
1162 *
1163 * Note: This is the only SSLv2 message we support, and
1164 * is provided for browsers seeking backwards
1165 * compatibility. Connections must be upgraded to
1166 * SSLv3.0 immediately following, otherwise the
1167 * connection will fail.
1168 ********************************************************************/
1169 #if defined(STACK_USE_SSL_SERVER)
1170 static void SSLRxAntiqueClientHello(TCP_SOCKET hTCP)
1171 {
1172 WORD suiteLen, idLen, randLen;
1173 BYTE c;
1174  
1175 // Make sure entire message is ready
1176 if(TCPIsGetReady(hTCP) < sslStub.wRxHsBytesRem)
1177 return;
1178  
1179 // Verify handshake message sequence
1180 if(sslStub.Flags.bClientHello)
1181 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1182  
1183 // Indicate that we're the server
1184 sslStub.Flags.bIsServer = 1;
1185  
1186 // Make sure the session keys are synced
1187 SSLKeysSync(sslStubID);
1188  
1189 // Read and verify the handshake message type
1190 HSGet(hTCP, &c);
1191 if(c != 0x01u)
1192 {// This message is not supported, so handshake fails
1193 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1194 return;
1195 }
1196  
1197 // Read and verify the version
1198 HSGet(hTCP, &c);
1199 if(c != SSL_VERSION_HI)
1200 {// Version is too low, so handshake fails
1201 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1202 return;
1203 }
1204 HSGet(hTCP, &c); // Ignore low byte of version number
1205  
1206 // Read the CipherSuite length
1207 HSGetWord(hTCP, &suiteLen);
1208  
1209 // Read Session ID Length
1210 HSGetWord(hTCP, &idLen);
1211  
1212 // Read Challenge (Client.Random) length
1213 HSGetWord(hTCP, &randLen);
1214  
1215 // Check for an acceptable CipherSuite
1216 // Right now we just ignore this and assume support for
1217 // SSL_RSA_WITH_ARCFOUR_128_MD5. If we request this suite later
1218 // and it isn't supported, the client will kill the connection.
1219 HSGetArray(hTCP, NULL, suiteLen);
1220  
1221 // Read the SessionID
1222 // SSLv3 clients will send a v3 ClientHello when resuming, so
1223 // this is always a new session. Therefore, ignore the ID
1224 HSGetArray(hTCP, NULL, idLen);
1225  
1226 // Obtain a new session
1227 sslStub.idSession = SSLSessionNew();
1228 sslStub.Flags.bNewSession = 1;
1229  
1230 // Read Client.Random
1231 // This needs to be 32 bytes, so zero-pad the left side
1232 for(c = 0; c < 32 - randLen; c++)
1233 sslKeys.Remote.random[c] = 0;
1234 HSGetArray(hTCP, &sslKeys.Remote.random[c], randLen);
1235  
1236 // Mark message as received and request a ServerHello
1237 TCPRequestSSLMessage(hTCP, SSL_SERVER_HELLO);
1238 sslStub.Flags.bClientHello = 1;
1239 }
1240 #endif
1241  
1242 /*********************************************************************
1243 * Function: void SSLRxServerHello(TCP_SOCKET hTCP)
1244 *
1245 * PreCondition: sslStub is synchronized and HSStart() has been
1246 * called.
1247 *
1248 * Input: hTCP - the TCP Socket to read from
1249 *
1250 * Output: None
1251 *
1252 * Side Effects: None
1253 *
1254 * Overview: Receives the ServerHello from the remote server
1255 *
1256 * Note: None
1257 ********************************************************************/
1258 #if defined(STACK_USE_SSL_CLIENT)
1259 static void SSLRxServerHello(TCP_SOCKET hTCP)
1260 {
1261 BYTE b, sessionID[32];
1262 WORD w;
1263  
1264 // Make sure entire message is ready
1265 if(TCPIsGetReady(hTCP) < sslStub.wRxHsBytesRem)
1266 return;
1267  
1268 // Verify handshake message sequence
1269 if(!sslStub.Flags.bClientHello || sslStub.Flags.bServerHello)
1270 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1271  
1272 // Make sure correct session and key set are loaded
1273 SSLKeysSync(sslStubID);
1274  
1275 // Read Version (2)
1276 HSGetWord(hTCP, NULL);
1277  
1278 // Read Server.Random (32)
1279 HSGetArray(hTCP, sslKeys.Remote.random, 32);
1280  
1281 // Read Session ID Length (byte)
1282 HSGet(hTCP, &b);
1283  
1284 // Read Session ID (if any)
1285 SSLSessionSync(sslStub.idSession);
1286 if(b != 0u)
1287 {
1288 HSGetArray(hTCP, sessionID, b);
1289  
1290 // If reusing a session, check if our session ID was accepted
1291 if(!sslStub.Flags.bNewSession &&
1292 memcmp((void*)sslSession.sessionID, (void*)sessionID, 32) == 0)
1293 {// Session restart was accepted
1294 // Nothing to do here...move along
1295 }
1296 else
1297 {// This is a new session
1298 memcpy((void*)sslSession.sessionID, (void*)sessionID, 32);
1299  
1300 // Reset the RxServerCertificate state machine
1301 sslStub.dwTemp.v[0] = RX_SERVER_CERT_START;
1302 }
1303 }
1304 else
1305 {
1306 // Session is non-resumable, so invalidate its tag
1307 sslSessionStubs[sslStub.idSession].tag.Val = 0;
1308 }
1309  
1310 // Read and verify Cipher Suite (WORD)
1311 HSGetWord(hTCP, &w);
1312 if(w != SSL_RSA_WITH_ARCFOUR_128_MD5)
1313 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1314  
1315 // Read and verify Compression Method (BYTE)
1316 HSGet(hTCP, &b);
1317 if(b != 0x00u)
1318 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1319  
1320 // Note that message was received
1321 sslStub.Flags.bServerHello = 1;
1322  
1323 // Note that we updated session data
1324 SSLSessionUpdated();
1325 }
1326 #endif
1327  
1328 /*********************************************************************
1329 * Function: BYTE SSLTxServerHello(TCP_SOCKET hTCP)
1330 *
1331 * PreCondition: None
1332 *
1333 * Input: hTCP - the TCP Socket to send the message to
1334 *
1335 * Output: None
1336 *
1337 * Side Effects: None
1338 *
1339 * Overview: Transmits the ServerHello message.
1340 *
1341 * Note: None
1342 ********************************************************************/
1343 #if defined(STACK_USE_SSL_SERVER)
1344 static void SSLTxServerHello(TCP_SOCKET hTCP)
1345 {
1346 BYTE i;
1347  
1348 // Only continue if the session has been obtained
1349 if(sslStub.idSession == SSL_INVALID_ID)
1350 return;
1351  
1352 // Make sure enough space is available to transmit
1353 if(TCPIsPutReady(hTCP) < 78u)
1354 return;
1355  
1356 // Restart the handshake hasher
1357 HSStart();
1358  
1359 // Sync the session and keys
1360 SSLKeysSync(sslStubID);
1361 SSLSessionSync(sslStub.idSession);
1362  
1363 // If this session is new, generate an ID
1364 if(sslStub.Flags.bNewSession)
1365 {
1366 for(i = 0; i < 32u; i++)
1367 sslSession.sessionID[i] = RandomGet();
1368 SSLSessionUpdated();
1369  
1370 // Tag this session identifier
1371 memcpy((void*)&sslSessionStubs[sslStub.idSession].tag.v[1],
1372 (void*)(sslSession.sessionID), 3);
1373 }
1374  
1375 // Send handshake message header (hashed)
1376 HSPut(hTCP, SSL_SERVER_HELLO);
1377 HSPut(hTCP, 0x00);
1378 HSPut(hTCP, 0x00);
1379 HSPut(hTCP, 70);
1380  
1381 // Send the version number
1382 HSPut(hTCP, SSL_VERSION_HI);
1383 HSPut(hTCP, SSL_VERSION_LO);
1384  
1385 // Put Server.Random
1386 #if defined(STACK_USE_SNTP_CLIENT)
1387 {
1388 DWORD_VAL temp;
1389  
1390 temp.Val = SNTPGetUTCSeconds();
1391 sslKeys.Local.random[0] = temp.v[3];
1392 sslKeys.Local.random[1] = temp.v[2];
1393 sslKeys.Local.random[2] = temp.v[1];
1394 sslKeys.Local.random[3] = temp.v[0];
1395 i = 4;
1396 }
1397 #else
1398 i = 0;
1399 #endif
1400 while(i < 32u)
1401 sslKeys.Local.random[i++] = RandomGet();
1402 HSPutArray(hTCP, sslKeys.Local.random, 32);
1403  
1404 // Put Session ID
1405 HSPut(hTCP, 0x20);
1406 HSPutArray(hTCP, sslSession.sessionID, 32);
1407  
1408 // Put Cipher Suites
1409 HSPutWord(hTCP, SSL_RSA_WITH_ARCFOUR_128_MD5);
1410  
1411 // Put Compression Method (just null)
1412 HSPut(hTCP, 0x00);
1413  
1414 // End the handshake and save the hash
1415 HSEnd();
1416  
1417 // Send record
1418 SSLTxRecord(hTCP, sslStubID, SSL_HANDSHAKE);
1419  
1420 // Record that message was sent and request the next message
1421 sslStub.Flags.bServerHello = 1;
1422 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
1423 if(sslStub.Flags.bNewSession)
1424 TCPRequestSSLMessage(hTCP, SSL_CERTIFICATE);
1425 else
1426 TCPRequestSSLMessage(hTCP, SSL_CHANGE_CIPHER_SPEC);
1427  
1428 // Set up to transmit certificate
1429 sslStub.dwTemp.Val = SSL_CERT_LEN;
1430 }
1431 #endif
1432  
1433 /*********************************************************************
1434 * Function: void SSLRxServerCertificate(TCP_SOCKET hTCP)
1435 *
1436 * PreCondition: sslStub is synchronized and HSStart() has been
1437 * called.
1438 *
1439 * Input: hTCP - the TCP Socket to read from
1440 *
1441 * Output: None
1442 *
1443 * Side Effects: None
1444 *
1445 * Overview: Receives ServerCertificate from the remote server,
1446 * locates the public key information, and executes
1447 * RSA operation.
1448 *
1449 * Note: This shortcuts full parsing of the certificate by
1450 * just finding the Public Key Algorithm identifier
1451 * for RSA. From there, the following ASN.1 struct
1452 * is the public key. That struct consists of the
1453 * value for N, followed by the value for E.
1454 ********************************************************************/
1455 #if defined(STACK_USE_SSL_CLIENT)
1456 static void SSLRxServerCertificate(TCP_SOCKET hTCP)
1457 {
1458 WORD len;
1459 BYTE i, e[3];
1460  
1461 // Verify handshake message sequence
1462 if(!sslStub.Flags.bServerHello || sslStub.Flags.bServerCertificate)
1463 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1464  
1465 // Check state machine variable
1466 switch(sslStub.dwTemp.v[0]) {
1467  
1468 case RX_SERVER_CERT_START:
1469 // Find RSA Public Key Algorithm identifier
1470 len = TCPFindROMArray(hTCP, (ROM BYTE*)"\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01", 9, 0, FALSE);
1471  
1472 if(len == 0xFFFFu)
1473 {// If not found, clear most of buffer and return to wait
1474 HSGetArray(hTCP, NULL, TCPIsGetReady(hTCP) - 10);
1475 return;
1476 }
1477  
1478 // Otherwise, read it and move on
1479 HSGetArray(hTCP, NULL, len + 9);
1480 sslStub.dwTemp.v[0]++;
1481  
1482 case RX_SERVER_CERT_FIND_KEY:
1483 // Search for beginning of struct
1484 len = TCPFind(hTCP, 0x30, 0, FALSE);
1485  
1486 if(len == 0xFFFFu)
1487 {// Not found, so clear and return
1488 HSGetArray(hTCP, NULL, TCPIsGetReady(hTCP));
1489 }
1490  
1491 // Clear up through the 0x30
1492 HSGetArray(hTCP, NULL, len + 1);
1493  
1494 // Make sure 2 more bytes remain
1495 if(TCPIsGetReady(hTCP) < 3u)
1496 return;
1497  
1498 // Read 1 or 2 length bytes (ignore)
1499 HSGet(hTCP, &i);
1500 if(i > 0x80)
1501 HSGet(hTCP, &i);
1502  
1503 // Increment and continue
1504 sslStub.dwTemp.v[0]++;
1505  
1506 case RX_SERVER_CERT_FIND_N:
1507 // Make sure tag and length bytes are ready, plus one more
1508 if(TCPIsGetReady(hTCP) < 4u)
1509 return;
1510  
1511 // Read 0x02 (integer identifier)
1512 HSGet(hTCP, NULL);
1513  
1514 // Read 1 or 2 length bytes to sslStub.dwTemp.v[1]
1515 HSGet(hTCP, &i);
1516 if(i > 0x80)
1517 HSGet(hTCP, &i);
1518 sslStub.dwTemp.v[1] = i;
1519  
1520 // If there's one odd byte, it's a leading zero that we don't need
1521 if(sslStub.dwTemp.v[1] & 0x01)
1522 {
1523 HSGet(hTCP, NULL);
1524 sslStub.dwTemp.v[1]--;
1525 }
1526  
1527 // The max modulus we support is 1024 bits
1528 if(sslStub.dwTemp.v[1] > 0x80)
1529 {
1530 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1531 sslStub.dwTemp.v[1] = 0x80;
1532 }
1533  
1534 // Increment and continue
1535 sslStub.dwTemp.v[0]++;
1536  
1537 case RX_SERVER_CERT_READ_N:
1538 // Make sure sslStub.dwTemp.v[1] bytes are ready
1539 if(TCPIsGetReady(hTCP) < sslStub.dwTemp.v[1])
1540 return;
1541  
1542 // N will be stored in sslBuffer, which is currently in use
1543 // for handshaking. We can stop the handshake hashing, read
1544 // and hash this data, then resume more handshake hashing
1545 HSEnd();
1546  
1547 // Claim an SSL Buffer for RSA operations
1548 SSLBufferAlloc(&sslStub.idRxBuffer);
1549 if(sslStub.idRxBuffer == SSL_INVALID_ID)
1550 return;
1551  
1552 // Make sure we can claim RSA Engine
1553 if(!RSABeginEncrypt(sslStub.dwTemp.v[1]))
1554 return;
1555 sslRSAStubID = sslStubID;
1556  
1557 // Read N to proper location
1558 for(i = 0; i < 128u - sslStub.dwTemp.v[1]; i++)
1559 sslBuffer.full[i] = 0x00;
1560 HSGetArray(hTCP, sslBuffer.full, sslStub.dwTemp.v[1]);
1561  
1562 if (sslStub.supplementaryDataType == SSL_SUPPLEMENTARY_DATA_CERT_PUBLIC_KEY)
1563 {
1564 SSL_PKEY_INFO * tmpPKeyPtr = ((SSL_PKEY_INFO *)sslStub.supplementaryBuffer);
1565 tmpPKeyPtr->pub_size_bytes = sslStub.dwTemp.v[1];
1566 if (tmpPKeyPtr->pub_size_bytes <= sizeof (tmpPKeyPtr->pub_key))
1567 memcpy (&tmpPKeyPtr->pub_key[0], sslBuffer.full, tmpPKeyPtr->pub_size_bytes);
1568 }
1569  
1570  
1571 // Hash what we just read
1572 SSLHashSync(sslStub.idSHA1);
1573 HashAddData(&sslHash, sslBuffer.full, sslStub.dwTemp.v[1]);
1574 SSLHashSync(sslStub.idMD5);
1575 HashAddData(&sslHash, sslBuffer.full, sslStub.dwTemp.v[1]);
1576  
1577 // Generate { SSL_VERSION rand[46] } as pre-master secret & save
1578 SSLSessionSync(sslStub.idSession);
1579 sslSession.masterSecret[0] = SSL_VERSION_HI;
1580 sslSession.masterSecret[1] = SSL_VERSION_LO;
1581 for(i = 2; i < 48u; i++)
1582 sslSession.masterSecret[i] = RandomGet();
1583 SSLSessionUpdated();
1584  
1585 // Set RSA engine to use this data and key
1586 RSASetData(sslSession.masterSecret, 48, RSA_BIG_ENDIAN);
1587 RSASetN(sslBuffer.full, RSA_BIG_ENDIAN);
1588 RSASetResult(sslBuffer.full+128, RSA_BIG_ENDIAN);
1589  
1590 // Start a new hash
1591 HSStart();
1592  
1593 // Increment and continue
1594 sslStub.dwTemp.v[0]++;
1595  
1596 case RX_SERVER_CERT_READ_E:
1597 // Make sure 5 bytes are ready
1598 if(TCPIsGetReady(hTCP) < 5u)
1599 return;
1600  
1601 // Read 0x02
1602 HSGet(hTCP, NULL);
1603  
1604 // Read 1 length byte to temp
1605 HSGet(hTCP, &i);
1606 if(i > 3u)
1607 i = 3;
1608  
1609 // Read E to temp
1610 HSGetArray(hTCP, e, i);
1611  
1612 if (sslStub.supplementaryDataType == SSL_SUPPLEMENTARY_DATA_CERT_PUBLIC_KEY)
1613 {
1614 SSL_PKEY_INFO * tmpPKeyPtr = ((SSL_PKEY_INFO *)sslStub.supplementaryBuffer);
1615 if (i <= sizeof (tmpPKeyPtr->pub_e))
1616 memcpy (&tmpPKeyPtr->pub_e[0], e, i);
1617 }
1618  
1619 // Set RSA engine to encrypt with E
1620 RSASetE(e, i, RSA_BIG_ENDIAN);
1621  
1622 // Increment and continue
1623 sslStub.dwTemp.v[0]++;
1624  
1625 case RX_SERVER_CERT_CLEAR:
1626 // Clear up to sslStub.wRxHsBytesRem from hTCP
1627 len = TCPIsGetReady(hTCP);
1628 if(len > sslStub.wRxHsBytesRem)
1629 len = sslStub.wRxHsBytesRem;
1630 HSGetArray(hTCP, NULL, len);
1631  
1632 // If we're done, kick off the RSA encryption next
1633 if(sslStub.wRxHsBytesRem == 0u)
1634 {
1635 // Set periodic function to do RSA operation
1636 sslStub.Flags.bRSAInProgress = 1;
1637 sslSessionStubs[sslStub.idSession].lastUsed += SSL_RSA_LIFETIME_EXTENSION;
1638  
1639 // Note that we've received this message
1640 sslStub.Flags.bServerCertificate = 1;
1641 }
1642  
1643 break;
1644 }
1645 }
1646 #endif
1647  
1648 /*********************************************************************
1649 * Function: BYTE SSLTxServerCertificate(TCP_SOCKET hTCP)
1650 *
1651 * PreCondition: None
1652 *
1653 * Input: hTCP - the TCP Socket to send the message to
1654 *
1655 * Output: None
1656 *
1657 * Side Effects: None
1658 *
1659 * Overview: Transmits the Certificate message with the
1660 * server's specified public key certificate.
1661 *
1662 * Note: Certificate is defined in CustomSSLCert.c.
1663 * This function requires special handling for
1664 * partial records because the certificate will
1665 * likely be larger than the TCP buffer, and SSL
1666 * handshake messages are constrained to fit in a
1667 * single SSL handshake record
1668 ********************************************************************/
1669 #if defined(STACK_USE_SSL_SERVER)
1670 static void SSLTxServerCertificate(TCP_SOCKET hTCP)
1671 {
1672 WORD len;
1673 ROM BYTE* loc;
1674  
1675 // Restart the handshake hasher
1676 HSStart();
1677  
1678 // See how much we can write
1679 len = TCPIsPutReady(hTCP);
1680  
1681 // If full certificate remains, write the headers
1682 if(sslStub.dwTemp.Val == SSL_CERT_LEN)
1683 {
1684 // Make sure we can send all headers plus one byte
1685 if(len < 11u)
1686 return;
1687  
1688 // Transmit the handshake headers
1689 HSPut(hTCP, SSL_CERTIFICATE);
1690 HSPut(hTCP, 0x00);
1691 HSPutWord(hTCP, SSL_CERT_LEN + 3 + 3);
1692  
1693 // Send length of all certificates
1694 HSPut(hTCP, 0x00);
1695 HSPutWord(hTCP, SSL_CERT_LEN + 3);
1696  
1697 // Send length of this (only) certificate
1698 HSPut(hTCP, 0x00);
1699 HSPutWord(hTCP, SSL_CERT_LEN);
1700  
1701 // Put in the record header and begin the partial record sending
1702 SSLStartPartialRecord(hTCP, sslStubID, SSL_HANDSHAKE, SSL_CERT_LEN + 3 + 3 + 4);
1703  
1704 // Update free space
1705 len -= 10;
1706 }
1707  
1708 // Figure out where to start, and how much to send
1709 loc = SSL_CERT + (SSL_CERT_LEN - sslStub.dwTemp.Val);
1710 if(sslStub.dwTemp.Val < len)
1711 len = sslStub.dwTemp.Val;
1712  
1713 // Write the bytes
1714 HSPutROMArray(hTCP, loc, len);
1715 sslStub.dwTemp.Val -= len;
1716  
1717 // End the handshake and save the hash
1718 HSEnd();
1719  
1720 // Send record
1721 SSLFlushPartialRecord(hTCP);
1722  
1723 // Check if entire certificate was sent
1724 if(sslStub.dwTemp.Val == 0u)
1725 {
1726 // Finish the partial record
1727 SSLFinishPartialRecord(hTCP);
1728  
1729 // Record that message was sent and request a Certificate
1730 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
1731 TCPRequestSSLMessage(hTCP, SSL_SERVER_HELLO_DONE);
1732 sslStub.Flags.bServerCertificate = 1;
1733 }
1734 }
1735 #endif
1736  
1737 /*********************************************************************
1738 * Function: BYTE SSLTxServerHelloDone(TCP_SOCKET hTCP)
1739 *
1740 * PreCondition: None
1741 *
1742 * Input: hTCP - the TCP Socket to send the message to
1743 *
1744 * Output: None
1745 *
1746 * Side Effects: None
1747 *
1748 * Overview: Transmits the ServerHelloDone message.
1749 *
1750 * Note: None
1751 ********************************************************************/
1752 #if defined(STACK_USE_SSL_SERVER)
1753 static void SSLTxServerHelloDone(TCP_SOCKET hTCP)
1754 {
1755 // Make sure enough space is available to transmit
1756 if(TCPIsPutReady(hTCP) < 4u)
1757 return;
1758  
1759 // Restart the handshake hasher
1760 HSStart();
1761  
1762 // Send handshake message header (hashed)
1763 HSPut(hTCP, SSL_SERVER_HELLO_DONE);
1764 HSPut(hTCP, 0x00);
1765 HSPut(hTCP, 0x00);
1766 HSPut(hTCP, 0x00);
1767  
1768 // Message has no content, so we're done
1769  
1770 // End the handshake and save the hash
1771 HSEnd();
1772  
1773 // Send record
1774 SSLTxRecord(hTCP, sslStubID, SSL_HANDSHAKE);
1775  
1776 // Record that message was sent
1777 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
1778 sslStub.Flags.bServerHelloDone = 1;
1779 }
1780 #endif
1781  
1782 /*********************************************************************
1783 * Function: void SSLTxClientKeyExchange(TCP_SOCKET hTCP)
1784 *
1785 * PreCondition: sslStub is synchronized, sslStub.dwTemp.v[1]
1786 * contains the length of the public key, and
1787 * the RxBuffer contains the encrypted pre-master
1788 * secret at address 0x80.
1789 *
1790 * Input: hTCP - the TCP Socket to write the message to
1791 *
1792 * Output: None
1793 *
1794 * Side Effects: None
1795 *
1796 * Overview: Transmits the encrypted pre-master secret to the
1797 * server and requests the Change Cipher Spec. Also
1798 * generates the Master Secret from the pre-master
1799 * secret that was used.
1800 *
1801 * Note: None
1802 ********************************************************************/
1803 #if defined(STACK_USE_SSL_CLIENT)
1804 static void SSLTxClientKeyExchange(TCP_SOCKET hTCP)
1805 {
1806 BYTE len;
1807  
1808 // Load length of modulus from RxServerCertificate
1809 len = sslStub.dwTemp.v[1];
1810  
1811 // Make sure there's len+9 bytes free
1812 if(TCPIsPutReady(hTCP) < len + 9)
1813 return;
1814  
1815 // Start the handshake processor
1816 HSStart();
1817  
1818 // Send handshake message header (hashed)
1819 HSPut(hTCP, SSL_CLIENT_KEY_EXCHANGE);
1820 HSPut(hTCP, 0x00);
1821 HSPut(hTCP, 0x00); // Message length is (length of key) bytes
1822 HSPut(hTCP, len);
1823  
1824 // Suspend the handshake hasher and load the buffer
1825 HSEnd();
1826 SSLBufferSync(sslStub.idRxBuffer);
1827  
1828 // Send encrypted pre-master secret
1829 TCPPutArray(hTCP, (BYTE*) sslBuffer.full + 0x80, len);
1830  
1831 // Free the RSA Engine
1832 RSAEndUsage();
1833 sslRSAStubID = SSL_INVALID_ID;
1834  
1835 // Hash what we just sent
1836 SSLHashSync(sslStub.idSHA1);
1837 HashAddData(&sslHash, sslBuffer.full + 0x80, len);
1838 SSLHashSync(sslStub.idMD5);
1839 HashAddData(&sslHash, sslBuffer.full + 0x80, len);
1840  
1841 // Generate the Master Secret
1842 SSLKeysSync(sslStubID);
1843 SSLSessionSync(sslStub.idSession);
1844 GenerateHashRounds(3, sslKeys.Local.random, sslKeys.Remote.random);
1845 memcpy(sslSession.masterSecret, (void*)sslBuffer.hashRounds.temp, 48);
1846 SSLSessionUpdated();
1847  
1848 // Free the buffer with the encrypted pre-master secret
1849 SSLBufferFree(&sslStub.idRxBuffer);
1850  
1851 // Restart the handshaker
1852 HSStart();
1853  
1854 // Send the record
1855 SSLTxRecord(hTCP, sslStubID, SSL_HANDSHAKE);
1856  
1857 // Request a Change Cipher Spec and Finished message
1858 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
1859 TCPRequestSSLMessage(hTCP, SSL_CHANGE_CIPHER_SPEC);
1860  
1861 // Note that this message was sent
1862 sslStub.Flags.bClientKeyExchange = 1;
1863 }
1864 #endif
1865  
1866 /*********************************************************************
1867 * Function: void SSLRxClientKeyExchange(TCP_SOCKET hTCP)
1868 *
1869 * PreCondition: sslStub is synchronized and HSStart() has been
1870 * called.
1871 *
1872 * Input: hTCP - the TCP Socket to read from
1873 *
1874 * Output: None
1875 *
1876 * Side Effects: None
1877 *
1878 * Overview: Receives the ClientKeyExchange message and begins
1879 * the decryption process.
1880 *
1881 * Note: None
1882 ********************************************************************/
1883 #if defined(STACK_USE_SSL_SERVER)
1884 static void SSLRxClientKeyExchange(TCP_SOCKET hTCP)
1885 {
1886 WORD wKeyLength;
1887  
1888 // TODO: Add a sanity check here to see if sslStub.wRxHsBytesRem is equal
1889 // to the chosen RSA modulus length (ex: 128 for 1024 bit). If it is
1890 // wrong, we need to generate a failure alert.
1891  
1892 // Make sure entire message is ready
1893 if(TCPIsGetReady(hTCP) < sslStub.wRxHsBytesRem)
1894 return;
1895  
1896 // Verify handshake message sequence
1897 if(!sslStub.Flags.bServerHello || sslStub.Flags.bClientKeyExchange)
1898 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
1899  
1900 // Obtain a buffer to use
1901 SSLBufferAlloc(&sslStub.idRxBuffer);
1902 if(sslStub.idRxBuffer == SSL_INVALID_ID)
1903 return;
1904  
1905 // Claim the RSA engine
1906 if(!RSABeginDecrypt())
1907 return;
1908 sslRSAStubID = sslStubID;
1909  
1910 // Read the data
1911 wKeyLength = sslStub.wRxHsBytesRem;
1912 HSEnd();
1913 HSStart();
1914 HSGetArray(hTCP, NULL, wKeyLength);
1915 HSEnd();
1916 RSASetData(sslBuffer.full, wKeyLength, RSA_BIG_ENDIAN);
1917 sslBufferID = sslStub.idRxBuffer;
1918  
1919 // Note that message was received
1920 sslStub.Flags.bClientKeyExchange = 1;
1921  
1922 // Kick off the RSA decryptor
1923 sslStub.Flags.bRSAInProgress = 1;
1924 sslSessionStubs[sslStub.idSession].lastUsed += SSL_RSA_LIFETIME_EXTENSION;
1925  
1926 }
1927 #endif
1928  
1929 /*********************************************************************
1930 * Function: void SSLTxCCSFin(TCP_SOCKET hTCP)
1931 *
1932 * PreCondition: sslStub is synchronized, and the current session
1933 * has a valid pre-master secret to use.
1934 *
1935 * Input: hTCP - the TCP Socket to write the message to
1936 *
1937 * Output: None
1938 *
1939 * Side Effects: None
1940 *
1941 * Overview: Generates the session keys from the master secret,
1942 * then allocates and generates the encryption
1943 * context. Once processing is complete, transmits
1944 * the Change Cipher Spec message and the Finished
1945 * handshake message to the server.
1946 *
1947 * Note: None
1948 ********************************************************************/
1949 static void SSLTxCCSFin(TCP_SOCKET hTCP)
1950 {
1951 BYTE data[20];
1952  
1953 // Make sure enough space is available for both
1954 if(TCPIsPutReady(hTCP) < 68u)
1955 return;
1956  
1957 // Sync up the session
1958 SSLSessionSync(sslStub.idSession);
1959 SSLKeysSync(sslStubID);
1960 SSLBufferSync(SSL_INVALID_ID);
1961  
1962 // Send the CCS (not a handshake message)
1963 TCPPut(hTCP, 1);
1964 SSLTxRecord(hTCP, sslStubID, SSL_CHANGE_CIPHER_SPEC);
1965 sslStub.Flags.bLocalChangeCipherSpec = 1;
1966  
1967 // If keys are not ready, generate them
1968 if(!sslStub.Flags.bKeysValid)
1969 {
1970 // Obtain two full buffers for the Sboxes
1971 SSLBufferAlloc(&sslStub.idTxBuffer);
1972 SSLBufferAlloc(&sslStub.idRxBuffer);
1973 if(sslStub.idTxBuffer == SSL_INVALID_ID || sslStub.idRxBuffer == SSL_INVALID_ID)
1974 return;
1975  
1976 // Generate the keys
1977 SSLHashSync(SSL_INVALID_ID);
1978 GenerateSessionKeys();
1979 sslStub.Flags.bKeysValid = 1;
1980 }
1981  
1982 // Reset the sequence counters
1983 sslKeys.Local.app.sequence = 0;
1984  
1985 // Start the handshake data processor
1986 HSStart();
1987  
1988 // First, write the handshake header
1989 HSPut(hTCP, SSL_FINISHED);
1990 HSPut(hTCP, 0x00);
1991 HSPut(hTCP, 0x00);
1992 HSPut(hTCP, 0x24);
1993  
1994 // Calculate the Finished hashes
1995 CalculateFinishedHash(sslStub.idMD5, !sslStub.Flags.bIsServer, data);
1996 HSPutArray(hTCP, data, 16);
1997 CalculateFinishedHash(sslStub.idSHA1, !sslStub.Flags.bIsServer, data);
1998 HSPutArray(hTCP, data, 20);
1999  
2000 // Hash this message to the handshake hash
2001 HSEnd();
2002  
2003 // Send the record
2004 SSLTxRecord(hTCP, sslStubID, SSL_HANDSHAKE);
2005  
2006 // Update the connection state
2007 TCPRequestSSLMessage(hTCP, SSL_NO_MESSAGE);
2008 sslStub.Flags.bLocalFinished = 1;
2009  
2010 // If complete, note that
2011 if(sslStub.Flags.bRemoteFinished)
2012 {
2013 TCPSSLHandshakeComplete(hTCP);
2014 SSLHashFree(&sslStub.idMD5);
2015 SSLHashFree(&sslStub.idSHA1);
2016 }
2017  
2018 }
2019  
2020 /*********************************************************************
2021 * Function: void SSLRxCCS(TCP_SOCKET hTCP)
2022 *
2023 * PreCondition: sslStub is synchronized.
2024 *
2025 * Input: hTCP - the TCP Socket to read from
2026 *
2027 * Output: None
2028 *
2029 * Side Effects: None
2030 *
2031 * Overview: Receives a ChangeCipherSpec from the remote server
2032 *
2033 * Note: None
2034 ********************************************************************/
2035 static void SSLRxCCS(TCP_SOCKET hTCP)
2036 {
2037 // Only proceed if RSA is done
2038 if(sslStub.Flags.bRSAInProgress)
2039 return;
2040  
2041 // Verify handshake message sequence
2042 if(!sslStub.Flags.bClientHello || !sslStub.Flags.bServerHello)
2043 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
2044  
2045 // Allocate a hash for MACing data
2046 SSLHashAlloc(&sslStub.idRxHash);
2047  
2048 // Make sure entire message is ready and an RX hash is allocated
2049 if(TCPIsGetReady(hTCP) < sslStub.wRxBytesRem
2050 || sslStub.idRxHash == SSL_INVALID_ID)
2051 return;
2052  
2053 // If keys are not ready, generate them
2054 if(!sslStub.Flags.bKeysValid)
2055 {
2056 // Sync up the session
2057 SSLSessionSync(sslStub.idSession);
2058 SSLKeysSync(sslStubID);
2059 SSLBufferSync(SSL_INVALID_ID);
2060  
2061 // Obtain two full buffers for the Sboxes
2062 SSLBufferAlloc(&sslStub.idTxBuffer);
2063 SSLBufferAlloc(&sslStub.idRxBuffer);
2064 if(sslStub.idTxBuffer == SSL_INVALID_ID || sslStub.idRxBuffer == SSL_INVALID_ID)
2065 return;
2066  
2067 // Generate the keys
2068 SSLHashSync(SSL_INVALID_ID);
2069 GenerateSessionKeys();
2070 sslStub.Flags.bKeysValid = 1;
2071 }
2072  
2073 // Read the CCS message (ignoring its contents)
2074 sslStub.wRxBytesRem -= TCPGetArray(hTCP, NULL, sslStub.wRxBytesRem);
2075  
2076 // Note that message was received
2077 SSLKeysSync(sslStubID);
2078 sslKeys.Remote.app.sequence = 0;
2079 sslStub.Flags.bRemoteChangeCipherSpec = 1;
2080 }
2081  
2082 /*********************************************************************
2083 * Function: void SSLRxFinished(TCP_SOCKET hTCP)
2084 *
2085 * PreCondition: sslStub is synchronized and HSStart() has been
2086 * called.
2087 *
2088 * Input: hTCP - the TCP Socket to read from
2089 *
2090 * Output: None
2091 *
2092 * Side Effects: None
2093 *
2094 * Overview: Receives the Finished message from remote node
2095 *
2096 * Note: None
2097 ********************************************************************/
2098 static void SSLRxFinished(TCP_SOCKET hTCP)
2099 {
2100 BYTE rxHash[20], expectedHash[20];
2101  
2102 // Make sure entire message is ready
2103 if(TCPIsGetReady(hTCP) < sslStub.wRxHsBytesRem)
2104 return;
2105  
2106 // Verify handshake message sequence
2107 if(!sslStub.Flags.bRemoteChangeCipherSpec)
2108 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
2109  
2110 // Make sure correct session and key set are loaded
2111 SSLSessionSync(sslStub.idSession);
2112 SSLKeysSync(sslStubID);
2113  
2114 // Read md5_sum to temporary location
2115 HSGetArray(hTCP, rxHash, 16);
2116  
2117 // Calculate expected MD5 hash
2118 CalculateFinishedHash(sslStub.idMD5, sslStub.Flags.bIsServer, expectedHash);
2119 if(memcmp((void*)rxHash, (void*)expectedHash, 16) != 0)
2120 {// Handshake hash fails
2121 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
2122 }
2123  
2124 // Read sha_sum to temporary location
2125 HSGetArray(hTCP, rxHash, 20);
2126  
2127 // Calculate expected SHA-1 hash
2128 CalculateFinishedHash(sslStub.idSHA1, sslStub.Flags.bIsServer, expectedHash);
2129 if(memcmp((void*)rxHash, (void*)expectedHash, 20) != 0)
2130 {// Handshake hash fails
2131 TCPRequestSSLMessage(hTCP, SSL_ALERT_HANDSHAKE_FAILURE);
2132 }
2133  
2134 // Note that message was received
2135 sslStub.Flags.bRemoteFinished = 1;
2136  
2137 // If complete, note that, otherwise, request our own CCS message
2138 if(sslStub.Flags.bLocalFinished)
2139 {
2140 TCPSSLHandshakeComplete(hTCP);
2141 SSLHashFree(&sslStub.idMD5);
2142 SSLHashFree(&sslStub.idSHA1);
2143 }
2144 else
2145 TCPRequestSSLMessage(hTCP, SSL_CHANGE_CIPHER_SPEC);
2146  
2147 }
2148  
2149 /*********************************************************************
2150 * Function: void SSLRxAlert(TCP_SOCKET hTCP)
2151 *
2152 * PreCondition: sslStub is synchronized
2153 *
2154 * Input: hTCP - the TCP Socket to read from
2155 *
2156 * Output: None
2157 *
2158 * Side Effects: None
2159 *
2160 * Overview: Receives an alert message and decides what to do
2161 *
2162 * Note: None
2163 ********************************************************************/
2164 static void SSLRxAlert(TCP_SOCKET hTCP)
2165 {
2166 BYTE bLevel, bDesc;
2167  
2168 // Make sure entire message is ready
2169 if(TCPIsGetReady(hTCP) < sslStub.wRxBytesRem)
2170 return;
2171  
2172 // Read the alert message
2173 TCPGet(hTCP, &bLevel);
2174 TCPGet(hTCP, &bDesc);
2175 sslStub.wRxBytesRem -= 2;
2176  
2177 // Determine what to do
2178 switch(bLevel)
2179 {
2180 case SSL_ALERT_WARNING:
2181 // Check if a close notify was received
2182 if(bDesc + 0x80 == SSL_ALERT_CLOSE_NOTIFY)
2183 sslStub.Flags.bCloseNotify = 1;
2184  
2185 // We don't support non-fatal warnings besides CloseNotify,
2186 // so the connection is always done now. When the TCP
2187 // session closes, the resources will be cleaned up.
2188  
2189 // No break here:
2190 // Session is terminated, so still mark Done below
2191  
2192 case SSL_ALERT_FATAL:
2193 // Mark session as terminated
2194 sslStub.Flags.bDone = 1;
2195 }
2196  
2197 }
2198  
2199 /****************************************************************************
2200 ===========================================================================
2201 Section:
2202 SSL Key Processing Functions
2203 ===========================================================================
2204 ***************************************************************************/
2205  
2206 /*********************************************************************
2207 * Function: RSA_STATUS SSLRSAOperation(void)
2208 *
2209 * PreCondition: The RSA Module has been secured, an RSA operation
2210 * is pending, sslStub.wRxHsBytesRem is the value of
2211 * sslStub.wRxBytesRem after completion, and
2212 * sslStub.wRxBytesRem is the value of
2213 * sslStub.rxProtocol after completion. Also requires
2214 * sslStub to be synchronized.
2215 *
2216 * Input: None
2217 *
2218 * Output: None
2219 *
2220 * Side Effects: None
2221 *
2222 * Overview: Pauses connection processing until RSA calculation
2223 * is complete.
2224 *
2225 * Note: This function exists outside of the handshaking
2226 * functions so that the system does not incur the
2227 * expense of resuming and suspending handshake
2228 * hashes.
2229 ********************************************************************/
2230 RSA_STATUS SSLRSAOperation(void)
2231 {
2232 SSLBufferSync(sslStub.idRxBuffer);
2233  
2234 // Call RSAStep to perform some RSA processing
2235 return RSAStep();
2236 }
2237  
2238 /*********************************************************************
2239 * Function: void GenerateHashRounds(BYTE num, BYTE* rand1,
2240 * BYTE* rand2)
2241 *
2242 * PreCondition: The SSL buffer is allocated for temporary usage
2243 * and the data to run rounds on is in
2244 * sslSession.masterSecret
2245 *
2246 * Input: num - how many rounds to compute
2247 * rand1 - the first random data block to use
2248 * rand2 - the second random data block to use
2249 *
2250 * Output: None
2251 *
2252 * Side Effects: Destroys the SSL Buffer space
2253 *
2254 * Overview: Generates hash rounds to find either the
2255 * Master Secret or the Key Block.
2256 *
2257 * Note: This function will overflow the buffer after 7
2258 * rounds, but in practice num = 3 or num = 4.
2259 ********************************************************************/
2260 void GenerateHashRounds(BYTE num, BYTE* rand1, BYTE* rand2)
2261 {
2262 BYTE i, j, c, *res;
2263  
2264 c = 'A';
2265 res = sslBuffer.hashRounds.temp;
2266  
2267 for(i = 1; i <= num; i++, c++, res += 16)
2268 {
2269 SHA1Initialize(&sslBuffer.hashRounds.hash);
2270 for(j = 0; j < i; j++)
2271 HashAddData(&sslBuffer.hashRounds.hash, &c, 1);
2272 HashAddData(&sslBuffer.hashRounds.hash, sslSession.masterSecret, 48);
2273 HashAddData(&sslBuffer.hashRounds.hash, rand1, 32);
2274 HashAddData(&sslBuffer.hashRounds.hash, rand2, 32);
2275 SHA1Calculate(&sslBuffer.hashRounds.hash, sslBuffer.hashRounds.sha_hash);
2276 MD5Initialize(&sslBuffer.hashRounds.hash);
2277 HashAddData(&sslBuffer.hashRounds.hash, sslSession.masterSecret, 48);
2278 HashAddData(&sslBuffer.hashRounds.hash, sslBuffer.hashRounds.sha_hash, 20);
2279 MD5Calculate(&sslBuffer.hashRounds.hash, res);
2280 }
2281 }
2282  
2283 /*********************************************************************
2284 * Function: void GenerateSessionKeys(void)
2285 *
2286 * PreCondition: The SSL buffer is allocated for temporary usage,
2287 * session keys are synced, and the TX and RX buffers
2288 * are allocated for S-boxes.
2289 *
2290 * Input: None
2291 *
2292 * Output: None
2293 *
2294 * Side Effects: Destroys the SSL Buffer Space
2295 *
2296 * Overview: Generates the session write keys and MAC secrets
2297 *
2298 * Note: None
2299 ********************************************************************/
2300 void GenerateSessionKeys(void)
2301 {
2302 // This functionality differs slightly for client and server operations
2303  
2304 #if defined(STACK_USE_SSL_SERVER)
2305 if(sslStub.Flags.bIsServer)
2306 {
2307 // Generate the key expansion block
2308 GenerateHashRounds(4, sslKeys.Local.random, sslKeys.Remote.random);
2309 memcpy(sslKeys.Remote.app.MACSecret, (void*)sslBuffer.hashRounds.temp, 16);
2310 memcpy(sslKeys.Local.app.MACSecret, (void*)sslBuffer.hashRounds.temp+16, 16);
2311  
2312 // Save write keys elsewhere temporarily
2313 SSLHashSync(SSL_INVALID_ID);
2314 memcpy(&sslHash, (void*)sslBuffer.hashRounds.temp+32, 32);
2315  
2316 // Generate ARCFOUR Sboxes
2317 SSLBufferSync(sslStub.idRxBuffer);
2318 sslKeys.Remote.app.cryptCtx.Sbox = sslBuffer.full;
2319 ARCFOURInitialize(&(sslKeys.Remote.app.cryptCtx), (BYTE*)(&sslHash), 16);
2320 SSLBufferSync(sslStub.idTxBuffer);
2321 sslKeys.Local.app.cryptCtx.Sbox = sslBuffer.full;
2322 ARCFOURInitialize(&(sslKeys.Local.app.cryptCtx), (BYTE*)(&sslHash)+16, 16);
2323  
2324 return;
2325 }
2326 #endif
2327  
2328 #if defined(STACK_USE_SSL_CLIENT)
2329 // Generate the key expansion block
2330 GenerateHashRounds(4, sslKeys.Remote.random, sslKeys.Local.random);
2331 memcpy(sslKeys.Local.app.MACSecret, (void*)sslBuffer.hashRounds.temp, 16);
2332 memcpy(sslKeys.Remote.app.MACSecret, (void*)sslBuffer.hashRounds.temp+16, 16);
2333  
2334 // Save write keys elsewhere temporarily
2335 SSLHashSync(SSL_INVALID_ID);
2336 memcpy(&sslHash, (void*)sslBuffer.hashRounds.temp+32, 32);
2337  
2338 // Generate ARCFOUR Sboxes
2339 SSLBufferSync(sslStub.idTxBuffer);
2340 sslKeys.Local.app.cryptCtx.Sbox = sslBuffer.full;
2341 ARCFOURInitialize(&(sslKeys.Local.app.cryptCtx), (BYTE*)(&sslHash), 16);
2342 SSLBufferSync(sslStub.idRxBuffer);
2343 sslKeys.Remote.app.cryptCtx.Sbox = sslBuffer.full;
2344 ARCFOURInitialize(&(sslKeys.Remote.app.cryptCtx), (BYTE*)(&sslHash)+16, 16);
2345 #endif
2346  
2347 }
2348  
2349 /*********************************************************************
2350 * Function: static void CalculateFinishedHash(BYTE hashID,
2351 * BOOL fromClient, BYTE *result)
2352 *
2353 * PreCondition: hashID has all handshake data hashed so far and
2354 * the current session is synced in.
2355 *
2356 * Input: hashID - the hash sum to use
2357 * fromClient - TRUE if client is sender
2358 * result - where to store results
2359 *
2360 * Output: None
2361 *
2362 * Side Effects: None
2363 *
2364 * Overview: Calculates the handshake hash over the data.
2365 * hashID can be either MD5 or SHA-1, and this
2366 * function will calculate accordingly.
2367 *
2368 * Note: None
2369 ********************************************************************/
2370 static void CalculateFinishedHash(BYTE hashID, BOOL fromClient, BYTE *result)
2371 {
2372 BYTE i;
2373  
2374 // Load the hash, but make sure updates aren't saved
2375 SSLHashSync(hashID);
2376 sslHashID = SSL_INVALID_ID;
2377  
2378 // Sync the session data so masterSecret is available
2379 SSLSessionSync(sslStub.idSession);
2380  
2381 // Hash in the sender phrase & master secret
2382 if(fromClient)
2383 HashAddROMData(&sslHash, (ROM BYTE*)"CLNT", 4);
2384 else
2385 HashAddROMData(&sslHash, (ROM BYTE*)"SRVR", 4);
2386 HashAddData(&sslHash, sslSession.masterSecret, 48);
2387  
2388 // Hash in the pad1
2389 i = 6;
2390 if(sslHash.hashType == HASH_SHA1)
2391 i--;
2392 for(; i > 0u; i--)
2393 HashAddROMData(&sslHash, (ROM BYTE*)"\x36\x36\x36\x36\x36\x36\x36\x36", 8);
2394  
2395 // Calculate the inner hash result and store, start new hash
2396 if(sslHash.hashType == HASH_MD5)
2397 {
2398 MD5Calculate(&sslHash, result);
2399 MD5Initialize(&sslHash);
2400 }
2401 else
2402 {
2403 SHA1Calculate(&sslHash, result);
2404 SHA1Initialize(&sslHash);
2405 }
2406  
2407 // Hash in master secret
2408 HashAddData(&sslHash, sslSession.masterSecret, 48);
2409  
2410 // Hash in pad2
2411 i = 6;
2412 if(sslHash.hashType == HASH_SHA1)
2413 i--;
2414 for(; i > 0u; i--)
2415 HashAddROMData(&sslHash, (ROM BYTE*)"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c", 8);
2416  
2417 // Hash in the inner hash result and calculate
2418 if(sslHash.hashType == HASH_MD5)
2419 {
2420 HashAddData(&sslHash, result, 16);
2421 MD5Calculate(&sslHash, result);
2422 }
2423 else
2424 {
2425 HashAddData(&sslHash, result, 20);
2426 SHA1Calculate(&sslHash, result);
2427 }
2428  
2429 }
2430  
2431  
2432 /****************************************************************************
2433 ===========================================================================
2434 Section:
2435 SSL Memory Management Functions
2436 ===========================================================================
2437 ***************************************************************************/
2438  
2439 #define Debug(a,b) //do{putrsUART("\r\n" a); while(BusyUART()); WriteUART(b+'0');} while(0)
2440  
2441  
2442 /*********************************************************************
2443 * Function: static void SSLStubAlloc(void)
2444 *
2445 * PreCondition: None
2446 *
2447 * Inputs: None
2448 *
2449 * Outputs: None
2450 *
2451 * Returns: TRUE if stub was allocated, FALSE otherwise
2452 *
2453 * Side Effects: None
2454 *
2455 * Overview: Allocates a stub for use.
2456 *
2457 * Note: None
2458 ********************************************************************/
2459 static BOOL SSLStubAlloc(void)
2460 {
2461 BYTE i;
2462  
2463 // Search for a free stub
2464 for(i = 0; i != MAX_SSL_CONNECTIONS; i++)
2465 {
2466 if(!(isStubUsed & masks[i]))
2467 {// Stub is free, so claim it
2468 isStubUsed |= masks[i];
2469  
2470 // Save stub currently in RAM
2471 if(sslStubID != SSL_INVALID_ID)
2472 SaveOffChip((BYTE*)&sslStub,
2473 SSL_BASE_STUB_ADDR+SSL_STUB_SIZE*sslStubID,
2474 SSL_STUB_SIZE);
2475  
2476 // Switch to new stub and return
2477 Debug("S",i);
2478 sslStubID = i;
2479 return TRUE;
2480 }
2481 }
2482  
2483 // No stub was found to be free
2484 return FALSE;
2485  
2486 }
2487  
2488 /*********************************************************************
2489 * Function: static void SSLStubFree(BYTE id)
2490 *
2491 * PreCondition: None
2492 *
2493 * Inputs: id - the stub ID to free
2494 *
2495 * Outputs: None
2496 *
2497 * Returns: None
2498 *
2499 * Side Effects: None
2500 *
2501 * Overview: Specified stub is released
2502 *
2503 * Note: None
2504 ********************************************************************/
2505 static void SSLStubFree(BYTE id)
2506 {
2507 // If ID is not valid
2508 if(id >= MAX_SSL_CONNECTIONS)
2509 return;
2510  
2511 // If currently in RAM, mark as unused
2512 if(sslStubID == id)
2513 sslStubID = SSL_INVALID_ID;
2514  
2515 // Release the stub
2516 Debug("s",id);
2517 isStubUsed &= ~masks[id];
2518 }
2519  
2520 /*********************************************************************
2521 * Function: static void SSLStubSync(BYTE id)
2522 *
2523 * PreCondition: None
2524 *
2525 * Input: id - the stub ID to sync to RAM
2526 *
2527 * Output: None
2528 *
2529 * Side Effects: None
2530 *
2531 * Overview: Specified stub is loaded to RAM. Only loads if
2532 * necessary, and saves any current stub before
2533 * switching.
2534 *
2535 * Note: None
2536 ********************************************************************/
2537 static void SSLStubSync(BYTE id)
2538 {
2539 // Check if already loaded
2540 if(sslStubID == id)
2541 return;
2542  
2543 // Save old stub
2544 if(sslStubID != SSL_INVALID_ID)
2545 SaveOffChip((BYTE*)&sslStub,
2546 SSL_BASE_STUB_ADDR+SSL_STUB_SIZE*sslStubID,
2547 SSL_STUB_SIZE);
2548  
2549 // Load new stub
2550 LoadOffChip((BYTE*)&sslStub,
2551 SSL_BASE_STUB_ADDR+SSL_STUB_SIZE*id,
2552 SSL_STUB_SIZE);
2553 sslStubID = id;
2554 }
2555  
2556 /*********************************************************************
2557 * Function: static void SSLKeysSync(BYTE id)
2558 *
2559 * PreCondition: None
2560 *
2561 * Input: id - the key set ID to sync to RAM
2562 *
2563 * Output: None
2564 *
2565 * Side Effects: None
2566 *
2567 * Overview: Specified key set is loaded to RAM. Only loads if
2568 * necessary, and saves any current key set before
2569 * switching.
2570 *
2571 * Note: None
2572 ********************************************************************/
2573 static void SSLKeysSync(BYTE id)
2574 {
2575 // Check if already loaded
2576 if(sslKeysID == id)
2577 return;
2578  
2579 // Save old stub
2580 if(sslKeysID != SSL_INVALID_ID)
2581 SaveOffChip((BYTE*)&sslKeys,
2582 SSL_BASE_KEYS_ADDR+SSL_KEYS_SIZE*sslKeysID,
2583 SSL_KEYS_SIZE);
2584  
2585 // Load new stub
2586 LoadOffChip((BYTE*)&sslKeys,
2587 SSL_BASE_KEYS_ADDR+SSL_KEYS_SIZE*id,
2588 SSL_KEYS_SIZE);
2589 sslKeysID = id;
2590 }
2591  
2592 /*********************************************************************
2593 * Function: static void SSLHashAlloc(BYTE *id)
2594 *
2595 * PreCondition: None
2596 *
2597 * Inputs: id - Where to store the allocated ID
2598 *
2599 * Outputs: id - Allocated hash ID, or SSL_INVALID_ID if
2600 * none available
2601 *
2602 * Side Effects: None
2603 *
2604 * Overview: Allocates a hash for use.
2605 *
2606 * Note: None
2607 ********************************************************************/
2608 static void SSLHashAlloc(BYTE *id)
2609 {
2610 BYTE i;
2611  
2612 // If already allocated, just load it up
2613 if(*id != SSL_INVALID_ID)
2614 {
2615 SSLHashSync(*id);
2616 return;
2617 }
2618  
2619 // Search for a free hash
2620 for(i = 0; i != MAX_SSL_HASHES; i++)
2621 {
2622 if(!(isHashUsed & masks[i]))
2623 {// Hash is free, so claim it
2624 isHashUsed |= masks[i];
2625  
2626 // Save hash currently in RAM
2627 if(sslHashID != SSL_INVALID_ID)
2628 SaveOffChip((BYTE*)&sslHash,
2629 SSL_BASE_HASH_ADDR+SSL_HASH_SIZE*sslHashID,
2630 SSL_HASH_SIZE);
2631  
2632 // Switch to new hash and return
2633 Debug("H",i);
2634 sslHashID = i;
2635 *id = i;
2636 return;
2637 }
2638 }
2639 }
2640  
2641 /*********************************************************************
2642 * Function: static void SSLHashFree(BYTE *id)
2643 *
2644 * PreCondition: None
2645 *
2646 * Inputs: id - the hash ID to free
2647 *
2648 * Outputs: id - SSL_INVALID_ID
2649 *
2650 * Side Effects: None
2651 *
2652 * Overview: Specified hash is released
2653 *
2654 * Note: None
2655 ********************************************************************/
2656 static void SSLHashFree(BYTE *id)
2657 {
2658 // Nothing to do for invalid hashes
2659 if(*id > MAX_SSL_HASHES)
2660 return;
2661  
2662 // Purge from RAM if not used
2663 if(sslHashID == *id)
2664 sslHashID = SSL_INVALID_ID;
2665  
2666 // Release the hash
2667 Debug("h",*id);
2668 isHashUsed &= ~masks[*id];
2669 *id = SSL_INVALID_ID;
2670 }
2671  
2672 /*********************************************************************
2673 * Function: static void SSLHashSync(BYTE id)
2674 *
2675 * PreCondition: None
2676 *
2677 * Input: id - the hash ID to sync to RAM
2678 *
2679 * Output: None
2680 *
2681 * Side Effects: None
2682 *
2683 * Overview: Specified hash is loaded to RAM. Only loads if
2684 * necessary, and saves any current hash before
2685 * switching.
2686 *
2687 * Note: None
2688 ********************************************************************/
2689 static void SSLHashSync(BYTE id)
2690 {
2691 // Check if already loaded
2692 if(sslHashID == id)
2693 return;
2694  
2695 // Save old hash
2696 if(sslHashID != SSL_INVALID_ID)
2697 SaveOffChip((BYTE*)&sslHash,
2698 SSL_BASE_HASH_ADDR+SSL_HASH_SIZE*sslHashID,
2699 SSL_HASH_SIZE);
2700  
2701 // Load new hash if not requesting a temporary hash
2702 if(id != SSL_INVALID_ID)
2703 LoadOffChip((BYTE*)&sslHash,
2704 SSL_BASE_HASH_ADDR+SSL_HASH_SIZE*id,
2705 SSL_HASH_SIZE);
2706 sslHashID = id;
2707 }
2708  
2709 /*********************************************************************
2710 * Function: static void SSLBufferAlloc(BYTE *id)
2711 *
2712 * PreCondition: None
2713 *
2714 * Input: id - Where to store the allocated ID
2715 *
2716 * Output: id - Allocated buffer ID, or SSL_INVALID_ID if
2717 * none available
2718 *
2719 * Side Effects: None
2720 *
2721 * Overview: Allocates a buffer for use.
2722 *
2723 * Note: None
2724 ********************************************************************/
2725 static void SSLBufferAlloc(BYTE *id)
2726 {
2727 BYTE i;
2728  
2729 // If already allocated, just load it up
2730 if(*id != SSL_INVALID_ID)
2731 {
2732 SSLBufferSync(*id);
2733 return;
2734 }
2735  
2736 // Search for a free buffer
2737 for(i = 0; i != MAX_SSL_BUFFERS; i++)
2738 {
2739 if(!(isBufferUsed & masks[i]))
2740 {// Buffer is free, so claim it
2741 isBufferUsed |= masks[i];
2742  
2743 // Save buffer currently in RAM
2744 if(sslBufferID != SSL_INVALID_ID)
2745 SaveOffChip((BYTE*)&sslBuffer,
2746 SSL_BASE_BUFFER_ADDR+SSL_BUFFER_SIZE*sslBufferID,
2747 SSL_BUFFER_SIZE);
2748  
2749 // Switch to new buffer and return
2750 Debug("B",i);
2751 sslBufferID = i;
2752 *id = i;
2753 return;
2754 }
2755 }
2756 }
2757  
2758 /*********************************************************************
2759 * Function: static void SSLBufferFree(BYTE *id)
2760 *
2761 * PreCondition: None
2762 *
2763 * Inputs: id - the buffer ID to free
2764 *
2765 * Outputs: id - SSL_INVALID_ID
2766 *
2767 * Side Effects: None
2768 *
2769 * Overview: Specified buffer is released
2770 *
2771 * Note: None
2772 ********************************************************************/
2773 static void SSLBufferFree(BYTE *id)
2774 {
2775 // Nothing to do for invalid hashes
2776 if(*id > MAX_SSL_BUFFERS)
2777 return;
2778  
2779 // Purge from RAM if not used
2780 if(sslBufferID == *id)
2781 sslBufferID = SSL_INVALID_ID;\
2782  
2783 // Release the buffer
2784 Debug("b",*id);
2785 isBufferUsed &= ~masks[*id];
2786 *id = SSL_INVALID_ID;
2787 }
2788  
2789 /*********************************************************************
2790 * Function: static void SSLBufferSync(BYTE id)
2791 *
2792 * PreCondition: None
2793 *
2794 * Input: id - the buffer ID to sync to RAM
2795 *
2796 * Output: None
2797 *
2798 * Side Effects: None
2799 *
2800 * Overview: Specified buffer is loaded to RAM. Only loads if
2801 * necessary, and saves any current buffer before
2802 * switching.
2803 *
2804 * Note: None
2805 ********************************************************************/
2806 static void SSLBufferSync(BYTE id)
2807 {
2808 // Check if already loaded
2809 if(sslBufferID == id)
2810 return;
2811  
2812 // Save old buffer
2813 if(sslBufferID != SSL_INVALID_ID)
2814 SaveOffChip((BYTE*)&sslBuffer,
2815 SSL_BASE_BUFFER_ADDR+SSL_BUFFER_SIZE*sslBufferID,
2816 SSL_BUFFER_SIZE);
2817  
2818 // Load new buffer if not requesting temporary space
2819 if(id != SSL_INVALID_ID)
2820 LoadOffChip((BYTE*)&sslBuffer,
2821 SSL_BASE_BUFFER_ADDR+SSL_BUFFER_SIZE*id,
2822 SSL_BUFFER_SIZE);
2823 sslBufferID = id;
2824 }
2825  
2826 /*********************************************************************
2827 * Function: static BYTE SSLSessionNew(void)
2828 *
2829 * PreCondition: None
2830 *
2831 * Input: None
2832 *
2833 * Output: Allocated Session ID, or SSL_INVALID_ID if none available
2834 *
2835 * Side Effects: None
2836 *
2837 * Overview: Finds space for a new SSL session
2838 *
2839 * Note: None
2840 ********************************************************************/
2841 static BYTE SSLSessionNew(void)
2842 {
2843 BYTE id, oldestID;
2844 DWORD now, age, oldest;
2845  
2846 // Set up the search
2847 oldestID = SSL_INVALID_ID;
2848 oldest = SSL_MIN_SESSION_LIFETIME;
2849 now = TickGet();
2850  
2851 // Search for a free session
2852 for(id = 0; id != MAX_SSL_SESSIONS; id++)
2853 {
2854 if(sslSessionStubs[id].tag.Val == 0u)
2855 {// Unused session, so claim immediately
2856 break;
2857 }
2858  
2859 // Check how old this session is
2860 age = now - sslSessionStubs[id].lastUsed;
2861 if(age > oldest)
2862 {// This is now the oldest one
2863 oldest = age;
2864 oldestID = id;
2865 }
2866 }
2867  
2868 // Check if we can claim a session
2869 if(id == MAX_SSL_SESSIONS && oldestID != SSL_INVALID_ID)
2870 id = oldestID;
2871  
2872 // If a valid ID was found, claim it
2873 if(id < MAX_SSL_SESSIONS)
2874 {
2875 // Save old one if needed
2876 if(sslSessionUpdated)
2877 SaveOffChip((BYTE*)&sslSession,
2878 SSL_BASE_SESSION_ADDR+SSL_SESSION_SIZE*sslSessionID,
2879 SSL_SESSION_SIZE);
2880  
2881 // Set up the new session
2882 sslSessionID = id;
2883 sslSessionStubs[id].lastUsed = now;
2884 SSLSessionUpdated();
2885 return id;
2886 }
2887  
2888 return SSL_INVALID_ID;
2889 }
2890  
2891 /*********************************************************************
2892 * Function: static BYTE SSLSessionMatchID(BYTE* SessionID)
2893 *
2894 * PreCondition: None
2895 *
2896 * Input: SessionID - the session identifier to match
2897 *
2898 * Output: The matched session ID, or SSL_INVALID_ID if not found
2899 *
2900 * Side Effects: None
2901 *
2902 * Overview: Locates a cached SSL session for reuse. Syncs
2903 * found session into RAM.
2904 *
2905 * Note: None
2906 ********************************************************************/
2907 #if defined(STACK_USE_SSL_SERVER)
2908 static BYTE SSLSessionMatchID(BYTE* SessionID)
2909 {
2910 BYTE i;
2911  
2912 for(i = 0; i < MAX_SSL_SESSIONS; i++)
2913 {
2914 // Check if tag matches the ID
2915 if(sslSessionStubs[i].tag.v[0] == 0u &&
2916 !memcmp((void*)&sslSessionStubs[i].tag.v[1], (void*)SessionID, 3) )
2917 {
2918 // Found a partial match, so load it to memory
2919 SSLSessionSync(i);
2920  
2921 // Verify complete match
2922 if(memcmp((void*)sslSession.sessionID, (void*)SessionID, 32) != 0)
2923 continue;
2924  
2925 // Mark it as being used now
2926 sslSessionStubs[i].lastUsed = TickGet();
2927  
2928 // Return this session for use
2929 return i;
2930 }
2931 }
2932  
2933 return SSL_INVALID_ID;
2934  
2935 }
2936 #endif
2937  
2938 /*********************************************************************
2939 * Function: static BYTE SSLSessionMatchHost(IP_ADDR ip)
2940 *
2941 * PreCondition: None
2942 *
2943 * Input: ip - the host session to match
2944 *
2945 * Output: The matched session ID, or SSL_INVALID_ID if not found
2946 *
2947 * Side Effects: None
2948 *
2949 * Overview: Locates a cached SSL session for reuse
2950 *
2951 * Note: None
2952 ********************************************************************/
2953 #if defined(STACK_USE_SSL_CLIENT)
2954 static BYTE SSLSessionMatchIP(IP_ADDR ip)
2955 {
2956 BYTE i;
2957  
2958 for(i = 0; i < MAX_SSL_SESSIONS; i++)
2959 {
2960 // Check if tag matches the IP
2961 if(!memcmp((void*)&sslSessionStubs[i].tag.v[0], (void*)&ip, 4))
2962 {
2963 // Found a match, so load it to memory
2964 SSLSessionSync(i);
2965  
2966 // Mark it as being used now
2967 sslSessionStubs[i].lastUsed = TickGet();
2968  
2969 // Return this session for use
2970 return i;
2971 }
2972 }
2973  
2974 // No match so return invalid
2975 return SSL_INVALID_ID;
2976 }
2977 #endif
2978  
2979 /*********************************************************************
2980 * Function: static void SSLSessionSync(BYTE id)
2981 *
2982 * PreCondition: None
2983 *
2984 * Input: id - the session ID to sync to RAM
2985 *
2986 * Output: None
2987 *
2988 * Side Effects: None
2989 *
2990 * Overview: Specified session is loaded to RAM. Only loads if
2991 * necessary, and saves any current session before
2992 * switching if it has been updated.
2993 *
2994 * Note: None
2995 ********************************************************************/
2996 static void SSLSessionSync(BYTE id)
2997 {
2998 // Check if already loaded
2999 if(sslSessionID == id)
3000 return;
3001  
3002 // Save old buffer
3003 if(sslSessionUpdated && sslSessionID != SSL_INVALID_ID)
3004 SaveOffChip((BYTE*)&sslSession,
3005 SSL_BASE_SESSION_ADDR+SSL_SESSION_SIZE*sslSessionID,
3006 SSL_SESSION_SIZE);
3007  
3008 // Load new buffer
3009 LoadOffChip((BYTE*)&sslSession,
3010 SSL_BASE_SESSION_ADDR+SSL_SESSION_SIZE*id,
3011 SSL_SESSION_SIZE);
3012 sslSessionID = id;
3013 sslSessionUpdated = FALSE;
3014 }
3015  
3016 /*********************************************************************
3017 * Function: static void SaveOffChip(BYTE *ramAddr,
3018 * WORD ethAddr, WORD len)
3019 *
3020 * PreCondition: None
3021 *
3022 * Input: ramAddr - source address in RAM
3023 * ethAddr - destination address in Ethernet RAM
3024 * len - number of bytes to copy
3025 *
3026 * Output: None
3027 *
3028 * Side Effects: None
3029 *
3030 * Overview: Copies data in PIC RAM to the Ethernet RAM
3031 *
3032 * Note: None
3033 ********************************************************************/
3034 static void SaveOffChip(BYTE *ramAddr, PTR_BASE ethAddr, WORD len)
3035 {
3036 PTR_BASE oldPtr;
3037  
3038 oldPtr = MACSetWritePtr(ethAddr);
3039 MACPutArray(ramAddr, len);
3040 MACSetWritePtr(oldPtr);
3041 }
3042  
3043 /*********************************************************************
3044 * Function: static void LoadOffChip(BYTE *ramAddr,
3045 * WORD ethAddr, WORD len)
3046 *
3047 * PreCondition: None
3048 *
3049 * Input: ramAddr - destination address in RAM
3050 * ethAddr - source address in Ethernet RAM
3051 * len - number of bytes to copy
3052 *
3053 * Output: None
3054 *
3055 * Side Effects: None
3056 *
3057 * Overview: Copies data from Ethernet RAM to local RAM
3058 *
3059 * Note: None
3060 ********************************************************************/
3061 static void LoadOffChip(BYTE *ramAddr, PTR_BASE ethAddr, WORD len)
3062 {
3063 PTR_BASE oldPtr;
3064  
3065 oldPtr = MACSetReadPtr(ethAddr);
3066 MACGetArray(ramAddr, len);
3067 MACSetReadPtr(oldPtr);
3068 }
3069  
3070  
3071 /****************************************************************************
3072 ===========================================================================
3073 Section:
3074 SSL Handshake Hashing Functions
3075 ===========================================================================
3076 ***************************************************************************/
3077  
3078 /*********************************************************************
3079 * Function: static void HSStart()
3080 *
3081 * PreCondition: None
3082 *
3083 * Input: None
3084 *
3085 * Output: None
3086 *
3087 * Side Effects: None
3088 *
3089 * Overview: Sets up the buffer to store data for handshake
3090 * hash tracking
3091 *
3092 * Note: None
3093 ********************************************************************/
3094 static void HSStart()
3095 {
3096 // Allocate temporary storage and set the pointer to it
3097 SSLBufferSync(SSL_INVALID_ID);
3098 ptrHS = sslBuffer.full;
3099 }
3100  
3101 /*********************************************************************
3102 * Function: static void HSEnd()
3103 *
3104 * PreCondition: None
3105 *
3106 * Input: None
3107 *
3108 * Output: None
3109 *
3110 * Side Effects: None
3111 *
3112 * Overview: Hashes the message contents into the Handshake
3113 * hash structures and begins a new handshake hash.
3114 *
3115 * Note: None
3116 ********************************************************************/
3117 static void HSEnd()
3118 {
3119 // Hash in the received data and reset the pointer
3120 if(sslHashID == sslStub.idMD5)
3121 {
3122 HashAddData(&sslHash, sslBuffer.full, ptrHS - sslBuffer.full);
3123 SSLHashSync(sslStub.idSHA1);
3124 HashAddData(&sslHash, sslBuffer.full, ptrHS - sslBuffer.full);
3125 }
3126 else
3127 {
3128 SSLHashSync(sslStub.idSHA1);
3129 HashAddData(&sslHash, sslBuffer.full, ptrHS - sslBuffer.full);
3130 SSLHashSync(sslStub.idMD5);
3131 HashAddData(&sslHash, sslBuffer.full, ptrHS - sslBuffer.full);
3132 }
3133 ptrHS = sslBuffer.full;
3134 }
3135  
3136 /*********************************************************************
3137 * Function: static WORD HSGet(TCP_SOCKET skt, BYTE *b)
3138 *
3139 * PreCondition: None
3140 *
3141 * Input: skt - socket to read data from
3142 * b - byte to read into
3143 *
3144 * Output: Number of bytes read
3145 *
3146 * Side Effects: None
3147 *
3148 * Overview: Reads data from socket, transparently hashing it
3149 * into the handshake hashes.
3150 *
3151 * Note: None
3152 ********************************************************************/
3153 static WORD HSGet(TCP_SOCKET skt, BYTE *b)
3154 {
3155 BYTE c;
3156  
3157 // Must read to &c in case b is NULL (we still need to hash it)
3158 if(!TCPGet(skt, &c))
3159 return 0;
3160  
3161 *ptrHS = c;
3162 if(b)
3163 *b = c;
3164 ptrHS++;
3165  
3166 sslStub.wRxBytesRem--;
3167 sslStub.wRxHsBytesRem--;
3168  
3169 if(ptrHS > sslBuffer.full + 128)
3170 {
3171 HSEnd();
3172 HSStart();
3173 }
3174  
3175 return 1;
3176 }
3177  
3178 /*********************************************************************
3179 * Function: static WORD HSGetWord(TCP_SOCKET skt, WORD *w)
3180 *
3181 * PreCondition: None
3182 *
3183 * Input: skt - socket to read data from
3184 * w - word to read into
3185 *
3186 * Output: Number of bytes read
3187 *
3188 * Side Effects: None
3189 *
3190 * Overview: Reads data from socket, transparently hashing it
3191 * into the handshake hashes.
3192 *
3193 * Note: None
3194 ********************************************************************/
3195 static WORD HSGetWord(TCP_SOCKET skt, WORD *w)
3196 {
3197 if(w == NULL)
3198 return HSGet(skt, (BYTE*)w) + HSGet(skt, (BYTE*)w);
3199 else
3200 return HSGet(skt, (BYTE*)w+1) + HSGet(skt, (BYTE*)w);
3201 }
3202  
3203 /*********************************************************************
3204 * Function: static WORD HSGetArray(TCP_SOCKET skt,
3205 BYTE *data, WORD len)
3206 *
3207 * PreCondition: None
3208 *
3209 * Input: skt - socket to read data from
3210 * data - array to read into, or NULL
3211 * len - number of bytes to read
3212 *
3213 * Output: Number of bytes read
3214 *
3215 * Side Effects: None
3216 *
3217 * Overview: Reads data from socket, transparently hashing it
3218 * into the handshake hashes.
3219 *
3220 * Note: None
3221 ********************************************************************/
3222 static WORD HSGetArray(TCP_SOCKET skt, BYTE *data, WORD len)
3223 {
3224 WORD w;
3225  
3226 /*
3227 WORD wLenActual;
3228 WORD wChunkLen;
3229  
3230 wLenActual = 0;
3231 // Add all of this data to the running hash
3232 while(len)
3233 {
3234 wChunkLen = sizeof(sslBuffer.full) - (ptrHS - sslBuffer.full);
3235 if(wChunkLen == 0u)
3236 {
3237 HSEnd();
3238 wChunkLen = sizeof(sslBuffer.full);
3239 }
3240 if(len < wChunkLen)
3241 wChunkLen = len;
3242  
3243 // Obtain data from TCP
3244 w = TCPGetArray(skt, ptrHS, wChunkLen);
3245 if(w == 0u)
3246 return wLenActual;
3247  
3248 // Copy data from hash area to *data area if a non-NULL pointer was
3249 // provided
3250 if(data)
3251 {
3252 memcpy((void*)data, ptrHS, w);
3253 data += w;
3254 }
3255  
3256 // Update all tracking variables
3257 ptrHS += w;
3258 len -= w;
3259 wLenActual += w;
3260 sslStub.wRxBytesRem -= w;
3261 sslStub.wRxHsBytesRem -= w;
3262 }
3263  
3264 return wLenActual;
3265 */
3266  
3267 //if reading to NULL, we still have to hash
3268 if(!data)
3269 {
3270 WORD i, rem;
3271 for(i = 0; i < len; )
3272 {
3273 // Determine how much we can read
3274 rem = (sslBuffer.full + 255) - ptrHS;
3275 if(rem > len - i)
3276 rem = len - i;
3277  
3278 // Read that much
3279 rem = TCPGetArray(skt, ptrHS, rem);
3280 sslStub.wRxBytesRem -= rem;
3281 sslStub.wRxHsBytesRem -= rem;
3282  
3283 // Hash what we've got
3284 ptrHS += rem;
3285 HSEnd();
3286 HSStart();
3287  
3288 i += rem;
3289  
3290 // Make sure we aren't in an infinite loop
3291 if(rem == 0u)
3292 break;
3293 }
3294  
3295 return i;
3296 }
3297  
3298 len = TCPGetArray(skt, data, len);
3299 w = len;
3300  
3301 // TODO: BUG!!!: This must be fixed somehow so that buffer overflow is not
3302 // possible
3303 memcpy(ptrHS, (void*)data, len);
3304 ptrHS += len;
3305  
3306  
3307 // // Add all of this data to the running hash
3308 // while(w)
3309 // {
3310 // WORD wChunkLen = sizeof(sslBuffer.full) - (ptrHS - sslBuffer.full);
3311 // if(wChunkLen == 0u)
3312 // {
3313 // HSEnd();
3314 // HSStart();
3315 // wChunkLen = sizeof(sslBuffer.full);
3316 // }
3317 // if(w < wChunkLen)
3318 // wChunkLen = w;
3319 // memcpy(ptrHS, (void*)data, wChunkLen);
3320 // ptrHS += wChunkLen;
3321 // w -= wChunkLen;
3322 // }
3323  
3324 sslStub.wRxBytesRem -= len;
3325 sslStub.wRxHsBytesRem -= len;
3326  
3327 if(ptrHS > sslBuffer.full + 128)
3328 {
3329 HSEnd();
3330 HSStart();
3331 }
3332  
3333 return len;
3334 }
3335  
3336 /*********************************************************************
3337 * Function: static WORD HSPut(TCP_SOCKET skt, BYTE b)
3338 *
3339 * PreCondition: None
3340 *
3341 * Input: skt - socket to write data to
3342 * b - byte to write
3343 *
3344 * Output: Number of bytes written
3345 *
3346 * Side Effects: None
3347 *
3348 * Overview: Writes data to socket, transparently hashing it
3349 * into the handshake hashes.
3350 *
3351 * Note: None
3352 ********************************************************************/
3353 static WORD HSPut(TCP_SOCKET skt, BYTE b)
3354 {
3355 if(!TCPPut(skt, b))
3356 return 0;
3357  
3358 // Ensure we don't overflow the Hash buffer
3359 if(sizeof(sslBuffer.full) - (ptrHS - sslBuffer.full) == 0u)
3360 HSEnd();
3361  
3362 // Add this byte of data to the running hash
3363 *ptrHS = b;
3364 ptrHS++;
3365  
3366 return 1;
3367 }
3368  
3369 /*********************************************************************
3370 * Function: static WORD HSPutWord(TCP_SOCKET skt, WORD w)
3371 *
3372 * PreCondition: None
3373 *
3374 * Input: skt - socket to write data to
3375 * w - word to write
3376 *
3377 * Output: Number of bytes written
3378 *
3379 * Side Effects: None
3380 *
3381 * Overview: Writes data to socket, transparently hashing it
3382 * into the handshake hashes.
3383 *
3384 * Note: None
3385 ********************************************************************/
3386 static WORD HSPutWord(TCP_SOCKET skt, WORD w)
3387 {
3388 return HSPut(skt, (BYTE)(w>>8)) + HSPut(skt, (BYTE)w);
3389 }
3390  
3391 /*********************************************************************
3392 * Function: static WORD HSPutArray(TCP_SOCKET skt,
3393 BYTE *data, BYTE len)
3394 *
3395 * PreCondition: None
3396 *
3397 * Input: skt - socket to write data to
3398 * data - data to write
3399 * len - number of bytes to write
3400 *
3401 * Output: Number of bytes written
3402 *
3403 * Side Effects: None
3404 *
3405 * Overview: Writes data to socket, transparently hashing it
3406 * into the handshake hashes.
3407 *
3408 * Note: None
3409 ********************************************************************/
3410 static WORD HSPutArray(TCP_SOCKET skt, BYTE *data, WORD len)
3411 {
3412 WORD w;
3413  
3414 len = TCPPutArray(skt, data, len);
3415 w = len;
3416  
3417 // Add all of this data to the running hash
3418 while(w)
3419 {
3420 WORD wChunkLen = sizeof(sslBuffer.full) - (ptrHS - sslBuffer.full);
3421 if(wChunkLen == 0u)
3422 {
3423 HSEnd();
3424 wChunkLen = sizeof(sslBuffer.full);
3425 }
3426 if(w < wChunkLen)
3427 wChunkLen = w;
3428 memcpy(ptrHS, (void*)data, wChunkLen);
3429 data += wChunkLen;
3430 ptrHS += wChunkLen;
3431 w -= wChunkLen;
3432 }
3433  
3434 return len;
3435 }
3436  
3437 #if defined(STACK_USE_SSL_SERVER)
3438 static WORD HSPutROMArray(TCP_SOCKET skt, ROM BYTE *data, WORD len)
3439 {
3440 WORD w;
3441  
3442 len = TCPPutROMArray(skt, data, len);
3443 w = len;
3444  
3445 // Add all of this data to the running hash
3446 while(w)
3447 {
3448 WORD wChunkLen = sizeof(sslBuffer.full) - (ptrHS - sslBuffer.full);
3449 if(wChunkLen == 0u)
3450 {
3451 HSEnd();
3452 wChunkLen = sizeof(sslBuffer.full);
3453 }
3454 if(w < wChunkLen)
3455 wChunkLen = w;
3456 memcpypgm2ram(ptrHS, (ROM void*)data, wChunkLen);
3457 data += wChunkLen;
3458 ptrHS += wChunkLen;
3459 w -= wChunkLen;
3460 }
3461  
3462 return len;
3463 }
3464 #endif
3465  
3466 /****************************************************************************
3467 ===========================================================================
3468 Section:
3469 SSL MAC Hashing Functions
3470 ===========================================================================
3471 ***************************************************************************/
3472  
3473 /*********************************************************************
3474 * Function: static void SSLMACBegin(BYTE *MACSecret, DWORD seq,
3475 * BYTE protocol, WORD len)
3476 *
3477 * PreCondition: sslHash is ready to be written
3478 * (any pending data saved, nothing useful stored)
3479 *
3480 * Input: MACSecret - the MAC write secret
3481 * seq - the sequence number for this message
3482 * protocol - the SSL_PROTOCOL for this message
3483 * len - the length of the message being MAC'd
3484 *
3485 * Output: None
3486 *
3487 * Side Effects: None
3488 *
3489 * Overview: Begins a MAC calculation in sslHash
3490 *
3491 * Note: None
3492 ********************************************************************/
3493 void SSLMACBegin(BYTE *MACSecret, DWORD seq, BYTE protocol, WORD len)
3494 {
3495 BYTE i, temp[7];
3496  
3497 MD5Initialize(&sslHash);
3498  
3499 // Form the temp array
3500 temp[0] = *((BYTE*)&seq+3);
3501 temp[1] = *((BYTE*)&seq+2);
3502 temp[2] = *((BYTE*)&seq+1);
3503 temp[3] = *((BYTE*)&seq+0);
3504 temp[4] = protocol;
3505 temp[5] = *((BYTE*)&len+1);
3506 temp[6] = *((BYTE*)&len+0);
3507  
3508 // Hash the initial data (secret, padding, seq, protcol, len)
3509 HashAddData(&sslHash, MACSecret, 16);
3510  
3511 // Add in the padding
3512 for(i = 0; i < 6u; i++)
3513 {
3514 HashAddROMData(&sslHash, (ROM BYTE*)"\x36\x36\x36\x36\x36\x36\x36\x36", 8);
3515 }
3516  
3517 // Hash in the data length
3518 HashAddROMData(&sslHash, (ROM BYTE*)"\0\0\0\0", 4);
3519 HashAddData(&sslHash, temp, 7);
3520 }
3521  
3522 /*********************************************************************
3523 * Function: void SSLMACAdd(BYTE *data, WORD len)
3524 *
3525 * PreCondition: sslHash is ready to be written
3526 * (any pending data saved, SSLMACBegin called)
3527 *
3528 * Input: data - the data to add to the MAC
3529 * len - the length of data
3530 *
3531 * Output: None
3532 *
3533 * Side Effects: None
3534 *
3535 * Overview: Adds more data to a MAC in progress
3536 *
3537 * Note: None
3538 ********************************************************************/
3539 void SSLMACAdd(BYTE *data, WORD len)
3540 {
3541 HashAddData(&sslHash, data, len);
3542 }
3543  
3544 /*********************************************************************
3545 * Function: static void SSLMACCalc(BYTE *result)
3546 *
3547 * PreCondition: sslHash is ready to be written
3548 * (any pending data saved, SSLMACBegin called)
3549 *
3550 * Input: MACSecret - the MAC write secret
3551 * result - a 16 byte buffer to store result
3552 *
3553 * Output: None
3554 *
3555 * Side Effects: None
3556 *
3557 * Overview: Finishes the MAC calculation, and places the
3558 * result in the *result array
3559 *
3560 * Note: None
3561 ********************************************************************/
3562 void SSLMACCalc(BYTE *MACSecret, BYTE *result)
3563 {
3564 BYTE i;
3565  
3566 // Get inner hash result
3567 MD5Calculate(&sslHash, result);
3568  
3569 // Begin outer hash
3570 MD5Initialize(&sslHash);
3571 HashAddData(&sslHash, MACSecret, 16);
3572  
3573 // Add in padding
3574 for(i = 0; i < 6u; i++)
3575 {
3576 HashAddROMData(&sslHash, (ROM BYTE*)"\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c", 8);
3577 }
3578  
3579 // Hash in the previous result and calculate
3580 HashAddData(&sslHash, result, 16);
3581 MD5Calculate(&sslHash, result);
3582 }
3583  
3584 #endif
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3