Coverage Report

Created: 2025-04-22 06:18

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