tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sslnonce.c (39565B)


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