Coverage Report

Created: 2018-09-25 14:53

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