1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file implements the CLIENT Session ID cache.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 
9 #include "cert.h"
10 #include "pk11pub.h"
11 #include "secitem.h"
12 #include "ssl.h"
13 #include "nss.h"
14 
15 #include "sslimpl.h"
16 #include "sslproto.h"
17 #include "nssilock.h"
18 #include "sslencode.h"
19 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)
20 #include <time.h>
21 #endif
22 
23 PRUint32 ssl3_sid_timeout = 86400L; /* 24 hours */
24 
25 static sslSessionID *cache = NULL;
26 static PZLock *cacheLock = NULL;
27 
28 /* sids can be in one of 5 states:
29  *
30  * never_cached,        created, but not yet put into cache.
31  * in_client_cache,     in the client cache's linked list.
32  * in_server_cache,     entry came from the server's cache file.
33  * invalid_cache        has been removed from the cache.
34  * in_external_cache    sid comes from an external cache.
35  */
36 
37 #define LOCK_CACHE lock_cache()
38 #define UNLOCK_CACHE PZ_Unlock(cacheLock)
39 
40 static SECStatus
ssl_InitClientSessionCacheLock(void)41 ssl_InitClientSessionCacheLock(void)
42 {
43     cacheLock = PZ_NewLock(nssILockCache);
44     return cacheLock ? SECSuccess : SECFailure;
45 }
46 
47 static SECStatus
ssl_FreeClientSessionCacheLock(void)48 ssl_FreeClientSessionCacheLock(void)
49 {
50     if (cacheLock) {
51         PZ_DestroyLock(cacheLock);
52         cacheLock = NULL;
53         return SECSuccess;
54     }
55     PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
56     return SECFailure;
57 }
58 
59 static PRBool LocksInitializedEarly = PR_FALSE;
60 
61 static SECStatus
FreeSessionCacheLocks()62 FreeSessionCacheLocks()
63 {
64     SECStatus rv1, rv2;
65     rv1 = ssl_FreeSymWrapKeysLock();
66     rv2 = ssl_FreeClientSessionCacheLock();
67     if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
68         return SECSuccess;
69     }
70     return SECFailure;
71 }
72 
73 static SECStatus
InitSessionCacheLocks(void)74 InitSessionCacheLocks(void)
75 {
76     SECStatus rv1, rv2;
77     PRErrorCode rc;
78     rv1 = ssl_InitSymWrapKeysLock();
79     rv2 = ssl_InitClientSessionCacheLock();
80     if ((SECSuccess == rv1) && (SECSuccess == rv2)) {
81         return SECSuccess;
82     }
83     rc = PORT_GetError();
84     FreeSessionCacheLocks();
85     PORT_SetError(rc);
86     return SECFailure;
87 }
88 
89 /* free the session cache locks if they were initialized early */
90 SECStatus
ssl_FreeSessionCacheLocks()91 ssl_FreeSessionCacheLocks()
92 {
93     PORT_Assert(PR_TRUE == LocksInitializedEarly);
94     if (!LocksInitializedEarly) {
95         PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
96         return SECFailure;
97     }
98     FreeSessionCacheLocks();
99     LocksInitializedEarly = PR_FALSE;
100     return SECSuccess;
101 }
102 
103 static PRCallOnceType lockOnce;
104 
105 /* free the session cache locks if they were initialized lazily */
106 static SECStatus
ssl_ShutdownLocks(void * appData,void * nssData)107 ssl_ShutdownLocks(void *appData, void *nssData)
108 {
109     PORT_Assert(PR_FALSE == LocksInitializedEarly);
110     if (LocksInitializedEarly) {
111         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
112         return SECFailure;
113     }
114     FreeSessionCacheLocks();
115     memset(&lockOnce, 0, sizeof(lockOnce));
116     return SECSuccess;
117 }
118 
119 static PRStatus
initSessionCacheLocksLazily(void)120 initSessionCacheLocksLazily(void)
121 {
122     SECStatus rv = InitSessionCacheLocks();
123     if (SECSuccess != rv) {
124         return PR_FAILURE;
125     }
126     rv = NSS_RegisterShutdown(ssl_ShutdownLocks, NULL);
127     PORT_Assert(SECSuccess == rv);
128     if (SECSuccess != rv) {
129         return PR_FAILURE;
130     }
131     return PR_SUCCESS;
132 }
133 
134 /* lazyInit means that the call is not happening during a 1-time
135  * initialization function, but rather during dynamic, lazy initialization
136  */
137 SECStatus
ssl_InitSessionCacheLocks(PRBool lazyInit)138 ssl_InitSessionCacheLocks(PRBool lazyInit)
139 {
140     if (LocksInitializedEarly) {
141         return SECSuccess;
142     }
143 
144     if (lazyInit) {
145         return (PR_SUCCESS ==
146                 PR_CallOnce(&lockOnce, initSessionCacheLocksLazily))
147                    ? SECSuccess
148                    : SECFailure;
149     }
150 
151     if (SECSuccess == InitSessionCacheLocks()) {
152         LocksInitializedEarly = PR_TRUE;
153         return SECSuccess;
154     }
155 
156     return SECFailure;
157 }
158 
159 static void
lock_cache(void)160 lock_cache(void)
161 {
162     ssl_InitSessionCacheLocks(PR_TRUE);
163     PZ_Lock(cacheLock);
164 }
165 
166 /* BEWARE: This function gets called for both client and server SIDs !!
167  * If the unreferenced sid is not in the cache, Free sid and its contents.
168  */
169 void
ssl_DestroySID(sslSessionID * sid,PRBool freeIt)170 ssl_DestroySID(sslSessionID *sid, PRBool freeIt)
171 {
172     SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
173     PORT_Assert(sid->references == 0);
174     PORT_Assert(sid->cached != in_client_cache);
175 
176     if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
177         SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
178                          PR_FALSE);
179     }
180     if (sid->u.ssl3.srvName.data) {
181         SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
182     }
183     if (sid->u.ssl3.signedCertTimestamps.data) {
184         SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
185     }
186 
187     if (sid->u.ssl3.lock) {
188         PR_DestroyRWLock(sid->u.ssl3.lock);
189     }
190 
191     PORT_Free((void *)sid->peerID);
192     PORT_Free((void *)sid->urlSvrName);
193 
194     if (sid->peerCert) {
195         CERT_DestroyCertificate(sid->peerCert);
196     }
197     if (sid->peerCertStatus.items) {
198         SECITEM_FreeArray(&sid->peerCertStatus, PR_FALSE);
199     }
200 
201     if (sid->localCert) {
202         CERT_DestroyCertificate(sid->localCert);
203     }
204 
205     SECITEM_FreeItem(&sid->u.ssl3.alpnSelection, PR_FALSE);
206 
207     if (freeIt) {
208         PORT_ZFree(sid, sizeof(sslSessionID));
209     }
210 }
211 
212 /* BEWARE: This function gets called for both client and server SIDs !!
213  * Decrement reference count, and
214  *    free sid if ref count is zero, and sid is not in the cache.
215  * Does NOT remove from the cache first.
216  * If the sid is still in the cache, it is left there until next time
217  * the cache list is traversed.
218  */
219 static void
ssl_FreeLockedSID(sslSessionID * sid)220 ssl_FreeLockedSID(sslSessionID *sid)
221 {
222     PORT_Assert(sid->references >= 1);
223     if (--sid->references == 0) {
224         ssl_DestroySID(sid, PR_TRUE);
225     }
226 }
227 
228 /* BEWARE: This function gets called for both client and server SIDs !!
229  * Decrement reference count, and
230  *    free sid if ref count is zero, and sid is not in the cache.
231  * Does NOT remove from the cache first.
232  * These locks are necessary because the sid _might_ be in the cache list.
233  */
234 void
ssl_FreeSID(sslSessionID * sid)235 ssl_FreeSID(sslSessionID *sid)
236 {
237     LOCK_CACHE;
238     ssl_FreeLockedSID(sid);
239     UNLOCK_CACHE;
240 }
241 
242 /************************************************************************/
243 
244 /*
245 **  Lookup sid entry in cache by Address, port, and peerID string.
246 **  If found, Increment reference count, and return pointer to caller.
247 **  If it has timed out or ref count is zero, remove from list and free it.
248 */
249 
250 sslSessionID *
ssl_LookupSID(const PRIPv6Addr * addr,PRUint16 port,const char * peerID,const char * urlSvrName)251 ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID,
252               const char *urlSvrName)
253 {
254     sslSessionID **sidp;
255     sslSessionID *sid;
256     PRUint32 now;
257 
258     if (!urlSvrName)
259         return NULL;
260     now = ssl_TimeSec();
261     LOCK_CACHE;
262     sidp = &cache;
263     while ((sid = *sidp) != 0) {
264         PORT_Assert(sid->cached == in_client_cache);
265         PORT_Assert(sid->references >= 1);
266 
267         SSL_TRC(8, ("SSL: Lookup1: sid=0x%x", sid));
268 
269         if (sid->expirationTime < now) {
270             /*
271             ** This session-id timed out.
272             ** Don't even care who it belongs to, blow it out of our cache.
273             */
274             SSL_TRC(7, ("SSL: lookup1, throwing sid out, age=%d refs=%d",
275                         now - sid->creationTime, sid->references));
276 
277             *sidp = sid->next;                                      /* delink it from the list. */
278             sid->cached = invalid_cache;                            /* mark not on list. */
279             ssl_FreeLockedSID(sid);                                 /* drop ref count, free. */
280         } else if (!memcmp(&sid->addr, addr, sizeof(PRIPv6Addr)) && /* server IP addr matches */
281                    (sid->port == port) &&                           /* server port matches */
282                    /* proxy (peerID) matches */
283                    (((peerID == NULL) && (sid->peerID == NULL)) ||
284                     ((peerID != NULL) && (sid->peerID != NULL) &&
285                      PORT_Strcmp(sid->peerID, peerID) == 0)) &&
286                    /* is cacheable */
287                    (sid->u.ssl3.keys.resumable) &&
288                    /* server hostname matches. */
289                    (sid->urlSvrName != NULL) &&
290                    (0 == PORT_Strcmp(urlSvrName, sid->urlSvrName))) {
291             /* Hit */
292             sid->lastAccessTime = now;
293             sid->references++;
294             break;
295         } else {
296             sidp = &sid->next;
297         }
298     }
299     UNLOCK_CACHE;
300     return sid;
301 }
302 
303 /*
304 ** Add an sid to the cache or return a previously cached entry to the cache.
305 ** Although this is static, it is called via ss->sec.cache().
306 */
307 static void
CacheSID(sslSessionID * sid)308 CacheSID(sslSessionID *sid)
309 {
310     PORT_Assert(sid);
311     PORT_Assert(sid->cached == never_cached);
312 
313     SSL_TRC(8, ("SSL: Cache: sid=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
314                 "time=%x cached=%d",
315                 sid, sid->cached, sid->addr.pr_s6_addr32[0],
316                 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2],
317                 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
318                 sid->cached));
319 
320     if (!sid->urlSvrName) {
321         /* don't cache this SID because it can never be matched */
322         return;
323     }
324 
325     if (sid->u.ssl3.sessionIDLength == 0 &&
326         sid->u.ssl3.locked.sessionTicket.ticket.data == NULL)
327         return;
328 
329     /* Client generates the SessionID if this was a stateless resume. */
330     if (sid->u.ssl3.sessionIDLength == 0) {
331         SECStatus rv;
332         rv = PK11_GenerateRandom(sid->u.ssl3.sessionID,
333                                  SSL3_SESSIONID_BYTES);
334         if (rv != SECSuccess)
335             return;
336         sid->u.ssl3.sessionIDLength = SSL3_SESSIONID_BYTES;
337     }
338     PRINT_BUF(8, (0, "sessionID:",
339                   sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength));
340 
341     sid->u.ssl3.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL);
342     if (!sid->u.ssl3.lock) {
343         return;
344     }
345     PORT_Assert(sid->creationTime != 0 && sid->expirationTime != 0);
346     if (!sid->creationTime)
347         sid->lastAccessTime = sid->creationTime = ssl_TimeUsec();
348     if (!sid->expirationTime)
349         sid->expirationTime = sid->creationTime + ssl3_sid_timeout * PR_USEC_PER_SEC;
350 
351     /*
352      * Put sid into the cache.  Bump reference count to indicate that
353      * cache is holding a reference. Uncache will reduce the cache
354      * reference.
355      */
356     LOCK_CACHE;
357     sid->references++;
358     sid->cached = in_client_cache;
359     sid->next = cache;
360     cache = sid;
361     UNLOCK_CACHE;
362 }
363 
364 /*
365  * If sid "zap" is in the cache,
366  *    removes sid from cache, and decrements reference count.
367  * Caller must hold cache lock.
368  */
369 static void
UncacheSID(sslSessionID * zap)370 UncacheSID(sslSessionID *zap)
371 {
372     sslSessionID **sidp = &cache;
373     sslSessionID *sid;
374 
375     if (zap->cached != in_client_cache) {
376         return;
377     }
378 
379     SSL_TRC(8, ("SSL: Uncache: zap=0x%x cached=%d addr=0x%08x%08x%08x%08x port=0x%04x "
380                 "time=%x cipherSuite=%d",
381                 zap, zap->cached, zap->addr.pr_s6_addr32[0],
382                 zap->addr.pr_s6_addr32[1], zap->addr.pr_s6_addr32[2],
383                 zap->addr.pr_s6_addr32[3], zap->port, zap->creationTime,
384                 zap->u.ssl3.cipherSuite));
385 
386     /* See if it's in the cache, if so nuke it */
387     while ((sid = *sidp) != 0) {
388         if (sid == zap) {
389             /*
390             ** Bingo. Reduce reference count by one so that when
391             ** everyone is done with the sid we can free it up.
392             */
393             *sidp = zap->next;
394             zap->cached = invalid_cache;
395             ssl_FreeLockedSID(zap);
396             return;
397         }
398         sidp = &sid->next;
399     }
400 }
401 
402 /* If sid "zap" is in the cache,
403  *    removes sid from cache, and decrements reference count.
404  * Although this function is static, it is called externally via
405  *    ssl_UncacheSessionID.
406  */
407 static void
LockAndUncacheSID(sslSessionID * zap)408 LockAndUncacheSID(sslSessionID *zap)
409 {
410     LOCK_CACHE;
411     UncacheSID(zap);
412     UNLOCK_CACHE;
413 }
414 
415 SECStatus
ReadVariableFromBuffer(sslReader * reader,sslReadBuffer * readerBuffer,uint8_t lenBytes,SECItem * dest)416 ReadVariableFromBuffer(sslReader *reader, sslReadBuffer *readerBuffer,
417                        uint8_t lenBytes, SECItem *dest)
418 {
419     if (sslRead_ReadVariable(reader, lenBytes, readerBuffer) != SECSuccess) {
420         PORT_SetError(SEC_ERROR_INVALID_ARGS);
421         return SECFailure;
422     }
423     if (readerBuffer->len) {
424         SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer->buf,
425                              readerBuffer->len };
426         SECStatus rv = SECITEM_CopyItem(NULL, dest, &tempItem);
427         if (rv != SECSuccess) {
428             return rv;
429         }
430     }
431     return SECSuccess;
432 }
433 
434 /* Fill sid with the values from the encoded resumption token.
435  * sid has to be allocated.
436  * We don't care about locks here as this cache entry is externally stored.
437  */
438 SECStatus
ssl_DecodeResumptionToken(sslSessionID * sid,const PRUint8 * encodedToken,PRUint32 encodedTokenLen)439 ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken,
440                           PRUint32 encodedTokenLen)
441 {
442     PORT_Assert(encodedTokenLen);
443     PORT_Assert(encodedToken);
444     PORT_Assert(sid);
445     if (!sid || !encodedToken || !encodedTokenLen) {
446         PORT_SetError(SEC_ERROR_INVALID_ARGS);
447         return SECFailure;
448     }
449 
450     if (encodedToken[0] != SSLResumptionTokenVersion) {
451         /* Unknown token format version. */
452         PORT_SetError(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR);
453         return SECFailure;
454     }
455 
456     /* These variables are used across macros. Don't use them outside. */
457     sslReader reader = SSL_READER(encodedToken, encodedTokenLen);
458     reader.offset += 1; // We read the version already. Skip the first byte.
459     sslReadBuffer readerBuffer = { 0 };
460     PRUint64 tmpInt = 0;
461 
462     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
463         return SECFailure;
464     }
465     sid->lastAccessTime = (PRTime)tmpInt;
466     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
467         return SECFailure;
468     }
469     sid->expirationTime = (PRTime)tmpInt;
470     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
471         return SECFailure;
472     }
473     sid->u.ssl3.locked.sessionTicket.received_timestamp = (PRTime)tmpInt;
474 
475     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
476         return SECFailure;
477     }
478     sid->u.ssl3.locked.sessionTicket.ticket_lifetime_hint = (PRUint32)tmpInt;
479     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
480         return SECFailure;
481     }
482     sid->u.ssl3.locked.sessionTicket.flags = (PRUint32)tmpInt;
483     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
484         return SECFailure;
485     }
486     sid->u.ssl3.locked.sessionTicket.ticket_age_add = (PRUint32)tmpInt;
487     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
488         return SECFailure;
489     }
490     sid->u.ssl3.locked.sessionTicket.max_early_data_size = (PRUint32)tmpInt;
491 
492     if (sslRead_ReadVariable(&reader, 3, &readerBuffer) != SECSuccess) {
493         PORT_SetError(SEC_ERROR_INVALID_ARGS);
494         return SECFailure;
495     }
496     if (readerBuffer.len) {
497         PORT_Assert(!sid->peerCert);
498         SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf,
499                              readerBuffer.len };
500         sid->peerCert = CERT_NewTempCertificate(NULL, /* dbHandle */
501                                                 &tempItem,
502                                                 NULL, PR_FALSE, PR_TRUE);
503         if (!sid->peerCert) {
504             return SECFailure;
505         }
506     }
507 
508     if (sslRead_ReadVariable(&reader, 2, &readerBuffer) != SECSuccess) {
509         PORT_SetError(SEC_ERROR_INVALID_ARGS);
510         return SECFailure;
511     }
512     if (readerBuffer.len) {
513         SECITEM_AllocArray(NULL, &sid->peerCertStatus, 1);
514         if (!sid->peerCertStatus.items) {
515             return SECFailure;
516         }
517         SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf,
518                              readerBuffer.len };
519         SECITEM_CopyItem(NULL, &sid->peerCertStatus.items[0], &tempItem);
520     }
521 
522     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
523         PORT_SetError(SEC_ERROR_INVALID_ARGS);
524         return SECFailure;
525     }
526     if (readerBuffer.len) {
527         PORT_Assert(readerBuffer.buf);
528         sid->peerID = PORT_Strdup((const char *)readerBuffer.buf);
529     }
530 
531     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
532         PORT_SetError(SEC_ERROR_INVALID_ARGS);
533         return SECFailure;
534     }
535     if (readerBuffer.len) {
536         if (sid->urlSvrName) {
537             PORT_Free((void *)sid->urlSvrName);
538         }
539         PORT_Assert(readerBuffer.buf);
540         sid->urlSvrName = PORT_Strdup((const char *)readerBuffer.buf);
541     }
542 
543     if (sslRead_ReadVariable(&reader, 3, &readerBuffer) != SECSuccess) {
544         PORT_SetError(SEC_ERROR_INVALID_ARGS);
545         return SECFailure;
546     }
547     if (readerBuffer.len) {
548         PORT_Assert(!sid->localCert);
549         SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer.buf,
550                              readerBuffer.len };
551         sid->localCert = CERT_NewTempCertificate(NULL, /* dbHandle */
552                                                  &tempItem,
553                                                  NULL, PR_FALSE, PR_TRUE);
554     }
555 
556     if (sslRead_ReadNumber(&reader, 8, &sid->addr.pr_s6_addr64[0]) != SECSuccess) {
557         return SECFailure;
558     }
559     if (sslRead_ReadNumber(&reader, 8, &sid->addr.pr_s6_addr64[1]) != SECSuccess) {
560         return SECFailure;
561     }
562 
563     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
564         return SECFailure;
565     }
566     sid->port = (PRUint16)tmpInt;
567     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
568         return SECFailure;
569     }
570     sid->version = (PRUint16)tmpInt;
571 
572     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
573         return SECFailure;
574     }
575     sid->creationTime = (PRTime)tmpInt;
576 
577     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
578         return SECFailure;
579     }
580     sid->authType = (SSLAuthType)tmpInt;
581     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
582         return SECFailure;
583     }
584     sid->authKeyBits = (PRUint32)tmpInt;
585     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
586         return SECFailure;
587     }
588     sid->keaType = (SSLKEAType)tmpInt;
589     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
590         return SECFailure;
591     }
592     sid->keaKeyBits = (PRUint32)tmpInt;
593     if (sslRead_ReadNumber(&reader, 3, &tmpInt) != SECSuccess) {
594         return SECFailure;
595     }
596     sid->keaGroup = (SSLNamedGroup)tmpInt;
597 
598     if (sslRead_ReadNumber(&reader, 3, &tmpInt) != SECSuccess) {
599         return SECFailure;
600     }
601     sid->sigScheme = (SSLSignatureScheme)tmpInt;
602 
603     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
604         return SECFailure;
605     }
606     sid->u.ssl3.sessionIDLength = (PRUint8)tmpInt;
607 
608     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
609         PORT_SetError(SEC_ERROR_INVALID_ARGS);
610         return SECFailure;
611     }
612     if (readerBuffer.len) {
613         PORT_Assert(readerBuffer.buf);
614         PORT_Memcpy(sid->u.ssl3.sessionID, readerBuffer.buf, readerBuffer.len);
615     }
616 
617     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
618         return SECFailure;
619     }
620     sid->u.ssl3.cipherSuite = (PRUint16)tmpInt;
621     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
622         return SECFailure;
623     }
624     sid->u.ssl3.policy = (PRUint8)tmpInt;
625 
626     if (sslRead_ReadVariable(&reader, 1, &readerBuffer) != SECSuccess) {
627         PORT_SetError(SEC_ERROR_INVALID_ARGS);
628         return SECFailure;
629     }
630     PORT_Assert(readerBuffer.len == WRAPPED_MASTER_SECRET_SIZE);
631     if (readerBuffer.len != WRAPPED_MASTER_SECRET_SIZE) {
632         PORT_SetError(SEC_ERROR_INVALID_ARGS);
633         return SECFailure;
634     }
635     PORT_Assert(readerBuffer.buf);
636     PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret, readerBuffer.buf,
637                 readerBuffer.len);
638 
639     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
640         return SECFailure;
641     }
642     sid->u.ssl3.keys.wrapped_master_secret_len = (PRUint8)tmpInt;
643     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
644         return SECFailure;
645     }
646     sid->u.ssl3.keys.extendedMasterSecretUsed = (PRUint8)tmpInt;
647 
648     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
649         return SECFailure;
650     }
651     sid->u.ssl3.masterWrapMech = (unsigned long)tmpInt;
652     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
653         return SECFailure;
654     }
655     sid->u.ssl3.masterModuleID = (unsigned long)tmpInt;
656     if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) {
657         return SECFailure;
658     }
659     sid->u.ssl3.masterSlotID = (unsigned long)tmpInt;
660 
661     if (sslRead_ReadNumber(&reader, 4, &tmpInt) != SECSuccess) {
662         return SECFailure;
663     }
664     sid->u.ssl3.masterWrapIndex = (PRUint32)tmpInt;
665     if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) {
666         return SECFailure;
667     }
668     sid->u.ssl3.masterWrapSeries = (PRUint16)tmpInt;
669 
670     if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) {
671         return SECFailure;
672     }
673     sid->u.ssl3.masterValid = (char)tmpInt;
674 
675     if (ReadVariableFromBuffer(&reader, &readerBuffer, 1,
676                                &sid->u.ssl3.srvName) != SECSuccess) {
677         return SECFailure;
678     }
679     if (ReadVariableFromBuffer(&reader, &readerBuffer, 2,
680                                &sid->u.ssl3.signedCertTimestamps) != SECSuccess) {
681         return SECFailure;
682     }
683     if (ReadVariableFromBuffer(&reader, &readerBuffer, 1,
684                                &sid->u.ssl3.alpnSelection) != SECSuccess) {
685         return SECFailure;
686     }
687     if (ReadVariableFromBuffer(&reader, &readerBuffer, 2,
688                                &sid->u.ssl3.locked.sessionTicket.ticket) != SECSuccess) {
689         return SECFailure;
690     }
691     if (!sid->u.ssl3.locked.sessionTicket.ticket.len) {
692         PORT_SetError(SEC_ERROR_INVALID_ARGS);
693         return SECFailure;
694     }
695 
696     /* At this point we must have read everything. */
697     PORT_Assert(reader.offset == reader.buf.len);
698     if (reader.offset != reader.buf.len) {
699         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
700         return SECFailure;
701     }
702 
703     return SECSuccess;
704 }
705 
706 PRBool
ssl_IsResumptionTokenValid(sslSocket * ss)707 ssl_IsResumptionTokenValid(sslSocket *ss)
708 {
709     PORT_Assert(ss);
710     sslSessionID *sid = ss->sec.ci.sid;
711     PORT_Assert(sid);
712 
713     // Check that the ticket didn't expire.
714     PRTime endTime = 0;
715     NewSessionTicket *ticket = &sid->u.ssl3.locked.sessionTicket;
716     if (ticket->ticket_lifetime_hint != 0) {
717         endTime = ticket->received_timestamp +
718                   (PRTime)(ticket->ticket_lifetime_hint * PR_USEC_PER_SEC);
719         if (endTime < ssl_TimeUsec()) {
720             return PR_FALSE;
721         }
722     }
723 
724     // Check that the session entry didn't expire.
725     if (sid->expirationTime < ssl_TimeUsec()) {
726         return PR_FALSE;
727     }
728 
729     // Check that the server name (SNI) matches the one set for this session.
730     // Don't use the token if there's no server name.
731     if (sid->urlSvrName == NULL || PORT_Strcmp(ss->url, sid->urlSvrName) != 0) {
732         return PR_FALSE;
733     }
734 
735     // This shouldn't be false, but let's check it anyway.
736     if (!sid->u.ssl3.keys.resumable) {
737         return PR_FALSE;
738     }
739 
740     return PR_TRUE;
741 }
742 
743 /* Encode a session ticket into a byte array that can be handed out to a cache.
744  * Needed memory in encodedToken has to be allocated according to
745  * *encodedTokenLen. */
746 static SECStatus
ssl_EncodeResumptionToken(sslSessionID * sid,sslBuffer * encodedTokenBuf)747 ssl_EncodeResumptionToken(sslSessionID *sid, sslBuffer *encodedTokenBuf)
748 {
749     PORT_Assert(encodedTokenBuf);
750     PORT_Assert(sid);
751     if (!sid || !sid->u.ssl3.locked.sessionTicket.ticket.len ||
752         !encodedTokenBuf || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) {
753         PORT_SetError(SEC_ERROR_INVALID_ARGS);
754         return SECFailure;
755     }
756 
757     /* Encoding format:
758      * 0-byte: version
759      * Integers are encoded according to their length.
760      * SECItems are prepended with a 64-bit length field followed by the bytes.
761      * Optional bytes are encoded as a 0-length item if not present.
762      */
763     SECStatus rv = sslBuffer_AppendNumber(encodedTokenBuf,
764                                           SSLResumptionTokenVersion, 1);
765     if (rv != SECSuccess) {
766         return SECFailure;
767     }
768 
769     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->lastAccessTime, 8);
770     if (rv != SECSuccess) {
771         PORT_SetError(SEC_ERROR_INVALID_ARGS);
772         return SECFailure;
773     }
774     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->expirationTime, 8);
775     if (rv != SECSuccess) {
776         PORT_SetError(SEC_ERROR_INVALID_ARGS);
777         return SECFailure;
778     }
779 
780     // session ticket
781     rv = sslBuffer_AppendNumber(encodedTokenBuf,
782                                 sid->u.ssl3.locked.sessionTicket.received_timestamp,
783                                 8);
784     if (rv != SECSuccess) {
785         PORT_SetError(SEC_ERROR_INVALID_ARGS);
786         return SECFailure;
787     }
788     rv = sslBuffer_AppendNumber(encodedTokenBuf,
789                                 sid->u.ssl3.locked.sessionTicket.ticket_lifetime_hint,
790                                 4);
791     if (rv != SECSuccess) {
792         PORT_SetError(SEC_ERROR_INVALID_ARGS);
793         return SECFailure;
794     }
795     rv = sslBuffer_AppendNumber(encodedTokenBuf,
796                                 sid->u.ssl3.locked.sessionTicket.flags,
797                                 4);
798     if (rv != SECSuccess) {
799         PORT_SetError(SEC_ERROR_INVALID_ARGS);
800         return SECFailure;
801     }
802     rv = sslBuffer_AppendNumber(encodedTokenBuf,
803                                 sid->u.ssl3.locked.sessionTicket.ticket_age_add,
804                                 4);
805     if (rv != SECSuccess) {
806         PORT_SetError(SEC_ERROR_INVALID_ARGS);
807         return SECFailure;
808     }
809     rv = sslBuffer_AppendNumber(encodedTokenBuf,
810                                 sid->u.ssl3.locked.sessionTicket.max_early_data_size,
811                                 4);
812     if (rv != SECSuccess) {
813         PORT_SetError(SEC_ERROR_INVALID_ARGS);
814         return SECFailure;
815     }
816 
817     rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->peerCert->derCert.data,
818                                   sid->peerCert->derCert.len, 3);
819     if (rv != SECSuccess) {
820         return SECFailure;
821     }
822 
823     if (sid->peerCertStatus.len > 1) {
824         /* This is not implemented so it shouldn't happen.
825          * If it gets implemented, this has to change.
826          */
827         PORT_Assert(0);
828         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
829         return SECFailure;
830     }
831 
832     if (sid->peerCertStatus.len == 1 && sid->peerCertStatus.items[0].len) {
833         rv = sslBuffer_AppendVariable(encodedTokenBuf,
834                                       sid->peerCertStatus.items[0].data,
835                                       sid->peerCertStatus.items[0].len, 2);
836         if (rv != SECSuccess) {
837             return SECFailure;
838         }
839     } else {
840         rv = sslBuffer_AppendVariable(encodedTokenBuf, NULL, 0, 2);
841         if (rv != SECSuccess) {
842             return SECFailure;
843         }
844     }
845 
846     PRUint64 len = sid->peerID ? strlen(sid->peerID) : 0;
847     if (len > PR_UINT8_MAX) {
848         // This string really shouldn't be that long.
849         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
850         return SECFailure;
851     }
852     rv = sslBuffer_AppendVariable(encodedTokenBuf,
853                                   (const unsigned char *)sid->peerID, len, 1);
854     if (rv != SECSuccess) {
855         return SECFailure;
856     }
857 
858     len = sid->urlSvrName ? strlen(sid->urlSvrName) : 0;
859     if (!len) {
860         PORT_SetError(SEC_ERROR_INVALID_ARGS);
861         return SECFailure;
862     }
863     if (len > PR_UINT8_MAX) {
864         // This string really shouldn't be that long.
865         PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
866         return SECFailure;
867     }
868     rv = sslBuffer_AppendVariable(encodedTokenBuf,
869                                   (const unsigned char *)sid->urlSvrName,
870                                   len, 1);
871     if (rv != SECSuccess) {
872         return SECFailure;
873     }
874 
875     if (sid->localCert) {
876         rv = sslBuffer_AppendVariable(encodedTokenBuf,
877                                       sid->localCert->derCert.data,
878                                       sid->localCert->derCert.len, 3);
879         if (rv != SECSuccess) {
880             return SECFailure;
881         }
882     } else {
883         rv = sslBuffer_AppendVariable(encodedTokenBuf, NULL, 0, 3);
884         if (rv != SECSuccess) {
885             return SECFailure;
886         }
887     }
888 
889     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->addr.pr_s6_addr64[0], 8);
890     if (rv != SECSuccess) {
891         PORT_SetError(SEC_ERROR_INVALID_ARGS);
892         return SECFailure;
893     }
894     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->addr.pr_s6_addr64[1], 8);
895     if (rv != SECSuccess) {
896         PORT_SetError(SEC_ERROR_INVALID_ARGS);
897         return SECFailure;
898     }
899     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->port, 2);
900     if (rv != SECSuccess) {
901         PORT_SetError(SEC_ERROR_INVALID_ARGS);
902         return SECFailure;
903     }
904     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->version, 2);
905     if (rv != SECSuccess) {
906         PORT_SetError(SEC_ERROR_INVALID_ARGS);
907         return SECFailure;
908     }
909     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->creationTime, 8);
910     if (rv != SECSuccess) {
911         PORT_SetError(SEC_ERROR_INVALID_ARGS);
912         return SECFailure;
913     }
914     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->authType, 2);
915     if (rv != SECSuccess) {
916         PORT_SetError(SEC_ERROR_INVALID_ARGS);
917         return SECFailure;
918     }
919     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->authKeyBits, 4);
920     if (rv != SECSuccess) {
921         PORT_SetError(SEC_ERROR_INVALID_ARGS);
922         return SECFailure;
923     }
924     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaType, 2);
925     if (rv != SECSuccess) {
926         PORT_SetError(SEC_ERROR_INVALID_ARGS);
927         return SECFailure;
928     }
929     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaKeyBits, 4);
930     if (rv != SECSuccess) {
931         PORT_SetError(SEC_ERROR_INVALID_ARGS);
932         return SECFailure;
933     }
934     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->keaGroup, 3);
935     if (rv != SECSuccess) {
936         PORT_SetError(SEC_ERROR_INVALID_ARGS);
937         return SECFailure;
938     }
939     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->sigScheme, 3);
940     if (rv != SECSuccess) {
941         PORT_SetError(SEC_ERROR_INVALID_ARGS);
942         return SECFailure;
943     }
944 
945     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.sessionIDLength, 1);
946     if (rv != SECSuccess) {
947         PORT_SetError(SEC_ERROR_INVALID_ARGS);
948         return SECFailure;
949     }
950     rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.sessionID,
951                                   SSL3_SESSIONID_BYTES, 1);
952     if (rv != SECSuccess) {
953         return SECFailure;
954     }
955 
956     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.cipherSuite, 2);
957     if (rv != SECSuccess) {
958         PORT_SetError(SEC_ERROR_INVALID_ARGS);
959         return SECFailure;
960     }
961     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.policy, 1);
962     if (rv != SECSuccess) {
963         PORT_SetError(SEC_ERROR_INVALID_ARGS);
964         return SECFailure;
965     }
966 
967     rv = sslBuffer_AppendVariable(encodedTokenBuf,
968                                   sid->u.ssl3.keys.wrapped_master_secret,
969                                   WRAPPED_MASTER_SECRET_SIZE, 1);
970     if (rv != SECSuccess) {
971         return SECFailure;
972     }
973 
974     rv = sslBuffer_AppendNumber(encodedTokenBuf,
975                                 sid->u.ssl3.keys.wrapped_master_secret_len,
976                                 1);
977     if (rv != SECSuccess) {
978         PORT_SetError(SEC_ERROR_INVALID_ARGS);
979         return SECFailure;
980     }
981     rv = sslBuffer_AppendNumber(encodedTokenBuf,
982                                 sid->u.ssl3.keys.extendedMasterSecretUsed,
983                                 1);
984     if (rv != SECSuccess) {
985         PORT_SetError(SEC_ERROR_INVALID_ARGS);
986         return SECFailure;
987     }
988 
989     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapMech, 8);
990     if (rv != SECSuccess) {
991         PORT_SetError(SEC_ERROR_INVALID_ARGS);
992         return SECFailure;
993     }
994     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterModuleID, 8);
995     if (rv != SECSuccess) {
996         PORT_SetError(SEC_ERROR_INVALID_ARGS);
997         return SECFailure;
998     }
999     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterSlotID, 8);
1000     if (rv != SECSuccess) {
1001         PORT_SetError(SEC_ERROR_INVALID_ARGS);
1002         return SECFailure;
1003     }
1004     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapIndex, 4);
1005     if (rv != SECSuccess) {
1006         PORT_SetError(SEC_ERROR_INVALID_ARGS);
1007         return SECFailure;
1008     }
1009     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterWrapSeries, 2);
1010     if (rv != SECSuccess) {
1011         PORT_SetError(SEC_ERROR_INVALID_ARGS);
1012         return SECFailure;
1013     }
1014 
1015     rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterValid, 1);
1016     if (rv != SECSuccess) {
1017         PORT_SetError(SEC_ERROR_INVALID_ARGS);
1018         return SECFailure;
1019     }
1020 
1021     rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.srvName.data,
1022                                   sid->u.ssl3.srvName.len, 1);
1023     if (rv != SECSuccess) {
1024         return SECFailure;
1025     }
1026     rv = sslBuffer_AppendVariable(encodedTokenBuf,
1027                                   sid->u.ssl3.signedCertTimestamps.data,
1028                                   sid->u.ssl3.signedCertTimestamps.len, 2);
1029     if (rv != SECSuccess) {
1030         return SECFailure;
1031     }
1032 
1033     rv = sslBuffer_AppendVariable(encodedTokenBuf,
1034                                   sid->u.ssl3.alpnSelection.data,
1035                                   sid->u.ssl3.alpnSelection.len, 1);
1036     if (rv != SECSuccess) {
1037         return SECFailure;
1038     }
1039 
1040     PORT_Assert(sid->u.ssl3.locked.sessionTicket.ticket.len > 1);
1041     rv = sslBuffer_AppendVariable(encodedTokenBuf,
1042                                   sid->u.ssl3.locked.sessionTicket.ticket.data,
1043                                   sid->u.ssl3.locked.sessionTicket.ticket.len,
1044                                   2);
1045     if (rv != SECSuccess) {
1046         return SECFailure;
1047     }
1048 
1049     return SECSuccess;
1050 }
1051 
1052 void
ssl_CacheExternalToken(sslSocket * ss)1053 ssl_CacheExternalToken(sslSocket *ss)
1054 {
1055     PORT_Assert(ss);
1056     sslSessionID *sid = ss->sec.ci.sid;
1057     PORT_Assert(sid);
1058     PORT_Assert(sid->cached == never_cached);
1059     PORT_Assert(ss->resumptionTokenCallback);
1060 
1061     SSL_TRC(8, ("SSL [%d]: Cache External: sid=0x%x cached=%d "
1062                 "addr=0x%08x%08x%08x%08x port=0x%04x time=%x cached=%d",
1063                 ss->fd,
1064                 sid, sid->cached, sid->addr.pr_s6_addr32[0],
1065                 sid->addr.pr_s6_addr32[1], sid->addr.pr_s6_addr32[2],
1066                 sid->addr.pr_s6_addr32[3], sid->port, sid->creationTime,
1067                 sid->cached));
1068 
1069     /* This is only available for stateless resumption. */
1070     if (sid->u.ssl3.locked.sessionTicket.ticket.data == NULL) {
1071         return;
1072     }
1073 
1074     /* Don't export token if the session used client authentication. */
1075     if (sid->u.ssl3.clAuthValid) {
1076         return;
1077     }
1078 
1079     if (!sid->creationTime) {
1080         sid->lastAccessTime = sid->creationTime = ssl_TimeUsec();
1081     }
1082     if (!sid->expirationTime) {
1083         sid->expirationTime = sid->creationTime + ssl3_sid_timeout;
1084     }
1085 
1086     sslBuffer encodedToken = SSL_BUFFER_EMPTY;
1087 
1088     if (ssl_EncodeResumptionToken(sid, &encodedToken) != SECSuccess) {
1089         SSL_TRC(3, ("SSL [%d]: encoding resumption token failed", ss->fd));
1090         return;
1091     }
1092     PORT_Assert(SSL_BUFFER_LEN(&encodedToken) > 0);
1093     PRINT_BUF(40, (ss, "SSL: encoded resumption token",
1094                    SSL_BUFFER_BASE(&encodedToken),
1095                    SSL_BUFFER_LEN(&encodedToken)));
1096     ss->resumptionTokenCallback(ss->fd, SSL_BUFFER_BASE(&encodedToken),
1097                                 SSL_BUFFER_LEN(&encodedToken),
1098                                 ss->resumptionTokenContext);
1099 
1100     sslBuffer_Clear(&encodedToken);
1101 }
1102 
1103 void
ssl_CacheSessionID(sslSocket * ss)1104 ssl_CacheSessionID(sslSocket *ss)
1105 {
1106     sslSecurityInfo *sec = &ss->sec;
1107     PORT_Assert(sec);
1108 
1109     if (sec->ci.sid && !sec->ci.sid->u.ssl3.keys.resumable) {
1110         return;
1111     }
1112 
1113     if (!ss->sec.isServer && ss->resumptionTokenCallback) {
1114         ssl_CacheExternalToken(ss);
1115         return;
1116     }
1117 
1118     PORT_Assert(!ss->resumptionTokenCallback);
1119     if (sec->isServer) {
1120         ssl_ServerCacheSessionID(sec->ci.sid);
1121         return;
1122     }
1123 
1124     CacheSID(sec->ci.sid);
1125 }
1126 
1127 void
ssl_UncacheSessionID(sslSocket * ss)1128 ssl_UncacheSessionID(sslSocket *ss)
1129 {
1130     if (ss->opt.noCache) {
1131         return;
1132     }
1133 
1134     sslSecurityInfo *sec = &ss->sec;
1135     PORT_Assert(sec);
1136 
1137     if (sec->ci.sid) {
1138         if (sec->isServer) {
1139             ssl_ServerUncacheSessionID(sec->ci.sid);
1140         } else if (!ss->resumptionTokenCallback) {
1141             LockAndUncacheSID(sec->ci.sid);
1142         }
1143     }
1144 }
1145 
1146 /* wipe out the entire client session cache. */
1147 void
SSL_ClearSessionCache(void)1148 SSL_ClearSessionCache(void)
1149 {
1150     LOCK_CACHE;
1151     while (cache != NULL)
1152         UncacheSID(cache);
1153     UNLOCK_CACHE;
1154 }
1155 
1156 /* returns an unsigned int containing the number of seconds in PR_Now() */
1157 PRUint32
ssl_TimeSec(void)1158 ssl_TimeSec(void)
1159 {
1160 #ifdef UNSAFE_FUZZER_MODE
1161     return 1234;
1162 #endif
1163 
1164     PRUint32 myTime;
1165 #if defined(XP_UNIX) || defined(XP_WIN) || defined(_WINDOWS) || defined(XP_BEOS)
1166     myTime = time(NULL); /* accurate until the year 2038. */
1167 #else
1168     /* portable, but possibly slower */
1169     PRTime now;
1170     PRInt64 ll;
1171 
1172     now = PR_Now();
1173     LL_I2L(ll, 1000000L);
1174     LL_DIV(now, now, ll);
1175     LL_L2UI(myTime, now);
1176 #endif
1177     return myTime;
1178 }
1179 
1180 PRBool
ssl_TicketTimeValid(const NewSessionTicket * ticket)1181 ssl_TicketTimeValid(const NewSessionTicket *ticket)
1182 {
1183     PRTime endTime;
1184 
1185     if (ticket->ticket_lifetime_hint == 0) {
1186         return PR_TRUE;
1187     }
1188 
1189     endTime = ticket->received_timestamp +
1190               (PRTime)(ticket->ticket_lifetime_hint * PR_USEC_PER_SEC);
1191     return endTime > ssl_TimeUsec();
1192 }
1193 
1194 void
ssl3_SetSIDSessionTicket(sslSessionID * sid,NewSessionTicket * newSessionTicket)1195 ssl3_SetSIDSessionTicket(sslSessionID *sid,
1196                          /*in/out*/ NewSessionTicket *newSessionTicket)
1197 {
1198     PORT_Assert(sid);
1199     PORT_Assert(newSessionTicket);
1200     PORT_Assert(newSessionTicket->ticket.data);
1201     PORT_Assert(newSessionTicket->ticket.len != 0);
1202 
1203     /* if sid->u.ssl3.lock, we are updating an existing entry that is already
1204      * cached or was once cached, so we need to acquire and release the write
1205      * lock. Otherwise, this is a new session that isn't shared with anything
1206      * yet, so no locking is needed.
1207      */
1208     if (sid->u.ssl3.lock) {
1209         PR_RWLock_Wlock(sid->u.ssl3.lock);
1210         if (sid->u.ssl3.locked.sessionTicket.ticket.data) {
1211             SECITEM_FreeItem(&sid->u.ssl3.locked.sessionTicket.ticket,
1212                              PR_FALSE);
1213         }
1214     }
1215 
1216     PORT_Assert(!sid->u.ssl3.locked.sessionTicket.ticket.data);
1217 
1218     /* Do a shallow copy, moving the ticket data. */
1219     sid->u.ssl3.locked.sessionTicket = *newSessionTicket;
1220     newSessionTicket->ticket.data = NULL;
1221     newSessionTicket->ticket.len = 0;
1222 
1223     if (sid->u.ssl3.lock) {
1224         PR_RWLock_Unlock(sid->u.ssl3.lock);
1225     }
1226 }
1227