1 /* This file implements the SERVER Session ID cache.
2 * NOTE: The contents of this file are NOT used by the client.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* $Id: sslsnce.c,v 1.63 2012/06/14 19:04:59 wtc%google.com Exp $ */
9 /* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
12 * About record locking among different server processes:
14 * All processes that are part of the same conceptual server (serving on
15 * the same address and port) MUST share a common SSL session cache.
16 * This code makes the content of the shared cache accessible to all
17 * processes on the same "server". This code works on Unix and Win32 only.
19 * We use NSPR anonymous shared memory and move data to & from shared memory.
20 * We must do explicit locking of the records for all reads and writes.
21 * The set of Cache entries are divided up into "sets" of 128 entries.
22 * Each set is protected by a lock. There may be one or more sets protected
23 * by each lock. That is, locks to sets are 1:N.
24 * There is one lock for the entire cert cache.
25 * There is one lock for the set of wrapped sym wrap keys.
27 * The anonymous shared memory is laid out as if it were declared like this:
30 * cacheDescriptor desc;
31 * sidCacheLock sidCacheLocks[ numSIDCacheLocks];
32 * sidCacheLock keyCacheLock;
33 * sidCacheLock certCacheLock;
34 * sidCacheSet sidCacheSets[ numSIDCacheSets ];
35 * sidCacheEntry sidCacheData[ numSIDCacheEntries];
36 * certCacheEntry certCacheData[numCertCacheEntries];
37 * SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
38 * uint8 keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
39 * encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode
40 * encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode
41 * PRBool ticketKeysValid;
42 * sidCacheLock srvNameCacheLock;
43 * srvNameCacheEntry srvNameData[ numSrvNameCacheEntries ];
44 * } cacheMemCacheData;
48 #if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)
57 #ifdef NO_PKCS11_BYPASS
66 #if defined(XP_UNIX) || defined(XP_BEOS)
83 #include <sys/types.h>
85 #define SET_ERROR_CODE /* reminder */
91 ** Format of a cache entry in the shared memory.
93 struct sidCacheEntryStr
{
94 /* 16 */ PRIPv6Addr addr
; /* client's IP address */
95 /* 4 */ PRUint32 creationTime
;
96 /* 4 */ PRUint32 lastAccessTime
;
97 /* 4 */ PRUint32 expirationTime
;
98 /* 2 */ PRUint16 version
;
99 /* 1 */ PRUint8 valid
;
100 /* 1 */ PRUint8 sessionIDLength
;
101 /* 32 */ PRUint8 sessionID
[SSL3_SESSIONID_BYTES
];
102 /* 2 */ PRUint16 authAlgorithm
;
103 /* 2 */ PRUint16 authKeyBits
;
104 /* 2 */ PRUint16 keaType
;
105 /* 2 */ PRUint16 keaKeyBits
;
106 /* 72 - common header total */
110 /* 64 */ PRUint8 masterKey
[SSL_MAX_MASTER_KEY_BYTES
];
111 /* 32 */ PRUint8 cipherArg
[SSL_MAX_CYPHER_ARG_BYTES
];
113 /* 1 */ PRUint8 cipherType
;
114 /* 1 */ PRUint8 masterKeyLen
;
115 /* 1 */ PRUint8 keyBits
;
116 /* 1 */ PRUint8 secretKeyBits
;
117 /* 1 */ PRUint8 cipherArgLen
;
121 /* 2 */ ssl3CipherSuite cipherSuite
;
122 /* 2 */ PRUint16 compression
; /* SSLCompressionMethod */
124 /* 52 */ ssl3SidKeys keys
; /* keys, wrapped as needed. */
126 /* 4 */ PRUint32 masterWrapMech
;
127 /* 4 */ SSL3KEAType exchKeyType
;
128 /* 4 */ PRInt32 certIndex
;
129 /* 4 */ PRInt32 srvNameIndex
;
130 /* 32 */ PRUint8 srvNameHash
[SHA256_LENGTH
]; /* SHA256 name hash */
132 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
134 /*120 */ PRUint8 filler
[120]; /* 72+120==192, a multiple of 16 */
138 typedef struct sidCacheEntryStr sidCacheEntry
;
140 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
141 struct certCacheEntryStr
{
142 PRUint16 certLength
; /* 2 */
143 PRUint16 sessionIDLength
; /* 2 */
144 PRUint8 sessionID
[SSL3_SESSIONID_BYTES
]; /* 32 */
145 PRUint8 cert
[SSL_MAX_CACHED_CERT_LEN
]; /* 4060 */
147 typedef struct certCacheEntryStr certCacheEntry
;
149 struct sidCacheLockStr
{
154 typedef struct sidCacheLockStr sidCacheLock
;
156 struct sidCacheSetStr
{
159 typedef struct sidCacheSetStr sidCacheSet
;
161 struct encKeyCacheEntryStr
{
165 typedef struct encKeyCacheEntryStr encKeyCacheEntry
;
167 #define SSL_MAX_DNS_HOST_NAME 1024
169 struct srvNameCacheEntryStr
{
170 PRUint16 type
; /* 2 */
171 PRUint16 nameLen
; /* 2 */
172 PRUint8 name
[SSL_MAX_DNS_HOST_NAME
+ 12]; /* 1034 */
173 PRUint8 nameHash
[SHA256_LENGTH
]; /* 32 */
176 typedef struct srvNameCacheEntryStr srvNameCacheEntry
;
179 struct cacheDescStr
{
181 PRUint32 cacheMemSize
;
183 PRUint32 numSIDCacheLocks
;
184 PRUint32 numSIDCacheSets
;
185 PRUint32 numSIDCacheSetsPerLock
;
187 PRUint32 numSIDCacheEntries
;
188 PRUint32 sidCacheSize
;
190 PRUint32 numCertCacheEntries
;
191 PRUint32 certCacheSize
;
193 PRUint32 numKeyCacheEntries
;
194 PRUint32 keyCacheSize
;
196 PRUint32 numSrvNameCacheEntries
;
197 PRUint32 srvNameCacheSize
;
199 PRUint32 ssl2Timeout
;
200 PRUint32 ssl3Timeout
;
202 PRUint32 numSIDCacheLocksInitialized
;
204 /* These values are volatile, and are accessed through sharedCache-> */
205 PRUint32 nextCertCacheEntry
; /* certCacheLock protects */
207 PRBool everInherited
;
209 /* The private copies of these values are pointers into shared mem */
210 /* The copies of these values in shared memory are merely offsets */
211 sidCacheLock
* sidCacheLocks
;
212 sidCacheLock
* keyCacheLock
;
213 sidCacheLock
* certCacheLock
;
214 sidCacheLock
* srvNameCacheLock
;
215 sidCacheSet
* sidCacheSets
;
216 sidCacheEntry
* sidCacheData
;
217 certCacheEntry
* certCacheData
;
218 SSLWrappedSymWrappingKey
* keyCacheData
;
219 uint8
* ticketKeyNameSuffix
;
220 encKeyCacheEntry
* ticketEncKey
;
221 encKeyCacheEntry
* ticketMacKey
;
222 PRUint32
* ticketKeysValid
;
223 srvNameCacheEntry
* srvNameCacheData
;
225 /* Only the private copies of these pointers are valid */
227 struct cacheDescStr
* sharedCache
; /* shared copy of this struct */
228 PRFileMap
* cacheMemMap
;
230 PRUint32 mutexTimeout
;
233 typedef struct cacheDescStr cacheDesc
;
235 static cacheDesc globalCache
;
237 static const char envVarName
[] = { SSL_ENV_VAR_NAME
};
239 static PRBool isMultiProcess
= PR_FALSE
;
242 #define DEF_SID_CACHE_ENTRIES 10000
243 #define DEF_CERT_CACHE_ENTRIES 250
244 #define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
245 #define DEF_KEY_CACHE_ENTRIES 250
246 #define DEF_NAME_CACHE_ENTRIES 1000
248 #define SID_CACHE_ENTRIES_PER_SET 128
249 #define SID_ALIGNMENT 16
251 #define DEF_SSL2_TIMEOUT 100 /* seconds */
252 #define MAX_SSL2_TIMEOUT 100 /* seconds */
253 #define MIN_SSL2_TIMEOUT 5 /* seconds */
255 #define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
256 #define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
257 #define MIN_SSL3_TIMEOUT 5 /* seconds */
259 #if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
260 #define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
262 #define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
264 #define MAX_SID_CACHE_LOCKS 256
267 #define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
268 #define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
272 static PRUint32 ssl_max_sid_cache_locks
= MAX_SID_CACHE_LOCKS
;
274 /* forward static function declarations */
275 static PRUint32
SIDindex(cacheDesc
*cache
, const PRIPv6Addr
*addr
, PRUint8
*s
,
277 static SECStatus
LaunchLockPoller(cacheDesc
*cache
);
278 static SECStatus
StopLockPoller(cacheDesc
*cache
);
281 struct inheritanceStr
{
282 PRUint32 cacheMemSize
;
286 typedef struct inheritanceStr inheritance
;
288 #if defined(_WIN32) || defined(XP_OS2)
290 #define DEFAULT_CACHE_DIRECTORY "\\temp"
294 #if defined(XP_UNIX) || defined(XP_BEOS)
296 #define DEFAULT_CACHE_DIRECTORY "/tmp"
298 #endif /* XP_UNIX || XP_BEOS */
301 /************************************************************************/
304 LockSidCacheLock(sidCacheLock
*lock
, PRUint32 now
)
306 SECStatus rv
= sslMutex_Lock(&lock
->mutex
);
307 if (rv
!= SECSuccess
)
311 lock
->timeStamp
= now
;
317 UnlockSidCacheLock(sidCacheLock
*lock
)
322 rv
= sslMutex_Unlock(&lock
->mutex
);
326 /* returns the value of ssl_Time on success, zero on failure. */
328 LockSet(cacheDesc
*cache
, PRUint32 set
, PRUint32 now
)
330 PRUint32 lockNum
= set
% cache
->numSIDCacheLocks
;
331 sidCacheLock
* lock
= cache
->sidCacheLocks
+ lockNum
;
333 return LockSidCacheLock(lock
, now
);
337 UnlockSet(cacheDesc
*cache
, PRUint32 set
)
339 PRUint32 lockNum
= set
% cache
->numSIDCacheLocks
;
340 sidCacheLock
* lock
= cache
->sidCacheLocks
+ lockNum
;
342 return UnlockSidCacheLock(lock
);
345 /************************************************************************/
348 /* Put a certificate in the cache. Update the cert index in the sce.
351 CacheCert(cacheDesc
* cache
, CERTCertificate
*cert
, sidCacheEntry
*sce
)
356 if ((cert
->derCert
.len
> SSL_MAX_CACHED_CERT_LEN
) ||
357 (cert
->derCert
.len
<= 0) ||
358 (cert
->derCert
.data
== NULL
)) {
359 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
363 cce
.sessionIDLength
= sce
->sessionIDLength
;
364 PORT_Memcpy(cce
.sessionID
, sce
->sessionID
, cce
.sessionIDLength
);
366 cce
.certLength
= cert
->derCert
.len
;
367 PORT_Memcpy(cce
.cert
, cert
->derCert
.data
, cce
.certLength
);
369 /* get lock on cert cache */
370 now
= LockSidCacheLock(cache
->certCacheLock
, 0);
373 /* Find where to place the next cert cache entry. */
374 cacheDesc
* sharedCache
= cache
->sharedCache
;
375 PRUint32 ndx
= sharedCache
->nextCertCacheEntry
;
377 /* write the entry */
378 cache
->certCacheData
[ndx
] = cce
;
380 /* remember where we put it. */
381 sce
->u
.ssl3
.certIndex
= ndx
;
383 /* update the "next" cache entry index */
384 sharedCache
->nextCertCacheEntry
=
385 (ndx
+ 1) % cache
->numCertCacheEntries
;
387 UnlockSidCacheLock(cache
->certCacheLock
);
393 /* Server configuration hash tables need to account the SECITEM.type
394 * field as well. These functions accomplish that. */
396 Get32BitNameHash(const SECItem
*name
)
398 PLHashNumber rv
= SECITEM_Hash(name
);
400 PRUint8
*rvc
= (PRUint8
*)&rv
;
401 rvc
[ name
->len
% sizeof(rv
) ] ^= name
->type
;
406 /* Put a name in the cache. Update the cert index in the sce.
409 CacheSrvName(cacheDesc
* cache
, SECItem
*name
, sidCacheEntry
*sce
)
413 srvNameCacheEntry snce
;
415 if (!name
|| name
->len
<= 0 ||
416 name
->len
> SSL_MAX_DNS_HOST_NAME
) {
417 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
421 snce
.type
= name
->type
;
422 snce
.nameLen
= name
->len
;
423 PORT_Memcpy(snce
.name
, name
->data
, snce
.nameLen
);
424 #ifdef NO_PKCS11_BYPASS
425 HASH_HashBuf(HASH_AlgSHA256
, snce
.nameHash
, name
->data
, name
->len
);
427 SHA256_HashBuf(snce
.nameHash
, (unsigned char*)name
->data
,
430 /* get index of the next name */
431 ndx
= Get32BitNameHash(name
);
432 /* get lock on cert cache */
433 now
= LockSidCacheLock(cache
->srvNameCacheLock
, 0);
435 if (cache
->numSrvNameCacheEntries
> 0) {
436 /* Fit the index into array */
437 ndx
%= cache
->numSrvNameCacheEntries
;
438 /* write the entry */
439 cache
->srvNameCacheData
[ndx
] = snce
;
440 /* remember where we put it. */
441 sce
->u
.ssl3
.srvNameIndex
= ndx
;
442 /* Copy hash into sid hash */
443 PORT_Memcpy(sce
->u
.ssl3
.srvNameHash
, snce
.nameHash
, SHA256_LENGTH
);
445 UnlockSidCacheLock(cache
->srvNameCacheLock
);
451 ** Convert local SID to shared memory one
454 ConvertFromSID(sidCacheEntry
*to
, sslSessionID
*from
)
457 to
->version
= from
->version
;
458 to
->addr
= from
->addr
;
459 to
->creationTime
= from
->creationTime
;
460 to
->lastAccessTime
= from
->lastAccessTime
;
461 to
->expirationTime
= from
->expirationTime
;
462 to
->authAlgorithm
= from
->authAlgorithm
;
463 to
->authKeyBits
= from
->authKeyBits
;
464 to
->keaType
= from
->keaType
;
465 to
->keaKeyBits
= from
->keaKeyBits
;
467 if (from
->version
< SSL_LIBRARY_VERSION_3_0
) {
468 if ((from
->u
.ssl2
.masterKey
.len
> SSL_MAX_MASTER_KEY_BYTES
) ||
469 (from
->u
.ssl2
.cipherArg
.len
> SSL_MAX_CYPHER_ARG_BYTES
)) {
470 SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
471 myPid
, from
->u
.ssl2
.masterKey
.len
,
472 from
->u
.ssl2
.cipherArg
.len
));
477 to
->u
.ssl2
.cipherType
= from
->u
.ssl2
.cipherType
;
478 to
->u
.ssl2
.masterKeyLen
= from
->u
.ssl2
.masterKey
.len
;
479 to
->u
.ssl2
.cipherArgLen
= from
->u
.ssl2
.cipherArg
.len
;
480 to
->u
.ssl2
.keyBits
= from
->u
.ssl2
.keyBits
;
481 to
->u
.ssl2
.secretKeyBits
= from
->u
.ssl2
.secretKeyBits
;
482 to
->sessionIDLength
= SSL2_SESSIONID_BYTES
;
483 PORT_Memcpy(to
->sessionID
, from
->u
.ssl2
.sessionID
, SSL2_SESSIONID_BYTES
);
484 PORT_Memcpy(to
->u
.ssl2
.masterKey
, from
->u
.ssl2
.masterKey
.data
,
485 from
->u
.ssl2
.masterKey
.len
);
486 PORT_Memcpy(to
->u
.ssl2
.cipherArg
, from
->u
.ssl2
.cipherArg
.data
,
487 from
->u
.ssl2
.cipherArg
.len
);
489 PORT_Memset(to
->u
.ssl2
.masterKey
+from
->u
.ssl2
.masterKey
.len
, 0,
490 sizeof(to
->u
.ssl2
.masterKey
) - from
->u
.ssl2
.masterKey
.len
);
491 PORT_Memset(to
->u
.ssl2
.cipherArg
+from
->u
.ssl2
.cipherArg
.len
, 0,
492 sizeof(to
->u
.ssl2
.cipherArg
) - from
->u
.ssl2
.cipherArg
.len
);
494 SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
495 "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid
,
496 to
->u
.ssl2
.masterKeyLen
, to
->u
.ssl2
.cipherArgLen
,
497 to
->creationTime
, to
->addr
.pr_s6_addr32
[0],
498 to
->addr
.pr_s6_addr32
[1], to
->addr
.pr_s6_addr32
[2],
499 to
->addr
.pr_s6_addr32
[3], to
->u
.ssl2
.cipherType
));
501 /* This is an SSL v3 session */
503 to
->u
.ssl3
.cipherSuite
= from
->u
.ssl3
.cipherSuite
;
504 to
->u
.ssl3
.compression
= (uint16
)from
->u
.ssl3
.compression
;
505 to
->u
.ssl3
.keys
= from
->u
.ssl3
.keys
;
506 to
->u
.ssl3
.masterWrapMech
= from
->u
.ssl3
.masterWrapMech
;
507 to
->u
.ssl3
.exchKeyType
= from
->u
.ssl3
.exchKeyType
;
508 to
->sessionIDLength
= from
->u
.ssl3
.sessionIDLength
;
509 to
->u
.ssl3
.certIndex
= -1;
510 to
->u
.ssl3
.srvNameIndex
= -1;
512 PORT_Memcpy(to
->sessionID
, from
->u
.ssl3
.sessionID
,
513 to
->sessionIDLength
);
515 SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
517 myPid
, to
->creationTime
, to
->addr
.pr_s6_addr32
[0],
518 to
->addr
.pr_s6_addr32
[1], to
->addr
.pr_s6_addr32
[2],
519 to
->addr
.pr_s6_addr32
[3], to
->u
.ssl3
.cipherSuite
));
524 ** Convert shared memory cache-entry to local memory based one
525 ** This is only called from ServerSessionIDLookup().
526 ** Caller must hold cache lock when calling this.
528 static sslSessionID
*
529 ConvertToSID(sidCacheEntry
* from
,
530 certCacheEntry
* pcce
,
531 srvNameCacheEntry
*psnce
,
532 CERTCertDBHandle
* dbHandle
)
535 uint16 version
= from
->version
;
537 to
= PORT_ZNew(sslSessionID
);
542 if (version
< SSL_LIBRARY_VERSION_3_0
) {
543 /* This is an SSL v2 session */
544 to
->u
.ssl2
.masterKey
.data
=
545 (unsigned char*) PORT_Alloc(from
->u
.ssl2
.masterKeyLen
);
546 if (!to
->u
.ssl2
.masterKey
.data
) {
549 if (from
->u
.ssl2
.cipherArgLen
) {
550 to
->u
.ssl2
.cipherArg
.data
=
551 (unsigned char*)PORT_Alloc(from
->u
.ssl2
.cipherArgLen
);
552 if (!to
->u
.ssl2
.cipherArg
.data
) {
555 PORT_Memcpy(to
->u
.ssl2
.cipherArg
.data
, from
->u
.ssl2
.cipherArg
,
556 from
->u
.ssl2
.cipherArgLen
);
559 to
->u
.ssl2
.cipherType
= from
->u
.ssl2
.cipherType
;
560 to
->u
.ssl2
.masterKey
.len
= from
->u
.ssl2
.masterKeyLen
;
561 to
->u
.ssl2
.cipherArg
.len
= from
->u
.ssl2
.cipherArgLen
;
562 to
->u
.ssl2
.keyBits
= from
->u
.ssl2
.keyBits
;
563 to
->u
.ssl2
.secretKeyBits
= from
->u
.ssl2
.secretKeyBits
;
564 /* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
565 PORT_Memcpy(to
->u
.ssl2
.sessionID
, from
->sessionID
, SSL2_SESSIONID_BYTES
);
566 PORT_Memcpy(to
->u
.ssl2
.masterKey
.data
, from
->u
.ssl2
.masterKey
,
567 from
->u
.ssl2
.masterKeyLen
);
569 SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
570 "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
571 myPid
, to
->u
.ssl2
.masterKey
.len
,
572 to
->u
.ssl2
.cipherArg
.len
, to
->creationTime
,
573 to
->addr
.pr_s6_addr32
[0], to
->addr
.pr_s6_addr32
[1],
574 to
->addr
.pr_s6_addr32
[2], to
->addr
.pr_s6_addr32
[3],
575 to
->u
.ssl2
.cipherType
));
577 /* This is an SSL v3 session */
579 to
->u
.ssl3
.sessionIDLength
= from
->sessionIDLength
;
580 to
->u
.ssl3
.cipherSuite
= from
->u
.ssl3
.cipherSuite
;
581 to
->u
.ssl3
.compression
= (SSLCompressionMethod
)from
->u
.ssl3
.compression
;
582 to
->u
.ssl3
.keys
= from
->u
.ssl3
.keys
;
583 to
->u
.ssl3
.masterWrapMech
= from
->u
.ssl3
.masterWrapMech
;
584 to
->u
.ssl3
.exchKeyType
= from
->u
.ssl3
.exchKeyType
;
585 if (from
->u
.ssl3
.srvNameIndex
!= -1 && psnce
) {
588 name
.type
= psnce
->type
;
589 name
.len
= psnce
->nameLen
;
590 name
.data
= psnce
->name
;
591 rv
= SECITEM_CopyItem(NULL
, &to
->u
.ssl3
.srvName
, &name
);
592 if (rv
!= SECSuccess
) {
597 PORT_Memcpy(to
->u
.ssl3
.sessionID
, from
->sessionID
, from
->sessionIDLength
);
599 /* the portions of the SID that are only restored on the client
600 * are set to invalid values on the server.
602 to
->u
.ssl3
.clientWriteKey
= NULL
;
603 to
->u
.ssl3
.serverWriteKey
= NULL
;
605 to
->urlSvrName
= NULL
;
607 to
->u
.ssl3
.masterModuleID
= (SECMODModuleID
)-1; /* invalid value */
608 to
->u
.ssl3
.masterSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
609 to
->u
.ssl3
.masterWrapIndex
= 0;
610 to
->u
.ssl3
.masterWrapSeries
= 0;
611 to
->u
.ssl3
.masterValid
= PR_FALSE
;
613 to
->u
.ssl3
.clAuthModuleID
= (SECMODModuleID
)-1; /* invalid value */
614 to
->u
.ssl3
.clAuthSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
615 to
->u
.ssl3
.clAuthSeries
= 0;
616 to
->u
.ssl3
.clAuthValid
= PR_FALSE
;
618 if (from
->u
.ssl3
.certIndex
!= -1 && pcce
) {
621 derCert
.len
= pcce
->certLength
;
622 derCert
.data
= pcce
->cert
;
624 to
->peerCert
= CERT_NewTempCertificate(dbHandle
, &derCert
, NULL
,
626 if (to
->peerCert
== NULL
)
631 to
->version
= from
->version
;
632 to
->creationTime
= from
->creationTime
;
633 to
->lastAccessTime
= from
->lastAccessTime
;
634 to
->expirationTime
= from
->expirationTime
;
635 to
->cached
= in_server_cache
;
636 to
->addr
= from
->addr
;
638 to
->authAlgorithm
= from
->authAlgorithm
;
639 to
->authKeyBits
= from
->authKeyBits
;
640 to
->keaType
= from
->keaType
;
641 to
->keaKeyBits
= from
->keaKeyBits
;
647 if (version
< SSL_LIBRARY_VERSION_3_0
) {
648 if (to
->u
.ssl2
.masterKey
.data
)
649 PORT_Free(to
->u
.ssl2
.masterKey
.data
);
650 if (to
->u
.ssl2
.cipherArg
.data
)
651 PORT_Free(to
->u
.ssl2
.cipherArg
.data
);
653 SECITEM_FreeItem(&to
->u
.ssl3
.srvName
, PR_FALSE
);
663 ** Perform some mumbo jumbo on the ip-address and the session-id value to
664 ** compute a hash value.
667 SIDindex(cacheDesc
*cache
, const PRIPv6Addr
*addr
, PRUint8
*s
, unsigned nl
)
672 memset(x
, 0, sizeof x
);
677 rv
= (addr
->pr_s6_addr32
[0] ^ addr
->pr_s6_addr32
[1] ^
678 addr
->pr_s6_addr32
[2] ^ addr
->pr_s6_addr32
[3] ^
679 x
[0] ^ x
[1] ^ x
[2] ^ x
[3] ^ x
[4] ^ x
[5] ^ x
[6] ^ x
[7])
680 % cache
->numSIDCacheSets
;
687 ** Look something up in the cache. This will invalidate old entries
688 ** in the process. Caller has locked the cache set!
689 ** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
691 static sidCacheEntry
*
692 FindSID(cacheDesc
*cache
, PRUint32 setNum
, PRUint32 now
,
693 const PRIPv6Addr
*addr
, unsigned char *sessionID
,
694 unsigned sessionIDLength
)
696 PRUint32 ndx
= cache
->sidCacheSets
[setNum
].next
;
699 sidCacheEntry
* set
= cache
->sidCacheData
+
700 (setNum
* SID_CACHE_ENTRIES_PER_SET
);
702 for (i
= SID_CACHE_ENTRIES_PER_SET
; i
> 0; --i
) {
705 ndx
= (ndx
- 1) % SID_CACHE_ENTRIES_PER_SET
;
711 if (now
> sce
->expirationTime
) {
712 /* SessionID has timed out. Invalidate the entry. */
713 SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
715 myPid
, sce
->addr
.pr_s6_addr32
[0],
716 sce
->addr
.pr_s6_addr32
[1], sce
->addr
.pr_s6_addr32
[2],
717 sce
->addr
.pr_s6_addr32
[3], now
,
718 sce
->expirationTime
));
724 ** Next, examine specific session-id/addr data to see if the cache
725 ** entry matches our addr+session-id value
727 if (sessionIDLength
== sce
->sessionIDLength
&&
728 !memcmp(&sce
->addr
, addr
, sizeof(PRIPv6Addr
)) &&
729 !memcmp(sce
->sessionID
, sessionID
, sessionIDLength
)) {
735 PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND
);
739 /************************************************************************/
741 /* This is the primary function for finding entries in the server's sid cache.
742 * Although it is static, this function is called via the global function
743 * pointer ssl_sid_lookup.
745 static sslSessionID
*
746 ServerSessionIDLookup(const PRIPv6Addr
*addr
,
747 unsigned char *sessionID
,
748 unsigned int sessionIDLength
,
749 CERTCertDBHandle
* dbHandle
)
751 sslSessionID
* sid
= 0;
752 sidCacheEntry
* psce
;
753 certCacheEntry
*pcce
= 0;
754 srvNameCacheEntry
*psnce
= 0;
755 cacheDesc
* cache
= &globalCache
;
761 srvNameCacheEntry snce
;
763 set
= SIDindex(cache
, addr
, sessionID
, sessionIDLength
);
764 now
= LockSet(cache
, set
, 0);
768 psce
= FindSID(cache
, set
, now
, addr
, sessionID
, sessionIDLength
);
770 if (psce
->version
>= SSL_LIBRARY_VERSION_3_0
) {
771 if ((cndx
= psce
->u
.ssl3
.certIndex
) != -1) {
773 PRUint32 gotLock
= LockSidCacheLock(cache
->certCacheLock
, now
);
775 pcce
= &cache
->certCacheData
[cndx
];
777 /* See if the cert's session ID matches the sce cache. */
778 if ((pcce
->sessionIDLength
== psce
->sessionIDLength
) &&
779 !PORT_Memcmp(pcce
->sessionID
, psce
->sessionID
,
780 pcce
->sessionIDLength
)) {
783 /* The cert doesen't match the SID cache entry,
784 ** so invalidate the SID cache entry.
790 UnlockSidCacheLock(cache
->certCacheLock
);
792 /* what the ??. Didn't get the cert cache lock.
793 ** Don't invalidate the SID cache entry, but don't find it.
795 PORT_Assert(!("Didn't get cert Cache Lock!"));
800 if (psce
&& ((cndx
= psce
->u
.ssl3
.srvNameIndex
) != -1)) {
801 PRUint32 gotLock
= LockSidCacheLock(cache
->srvNameCacheLock
,
804 psnce
= &cache
->srvNameCacheData
[cndx
];
806 if (!PORT_Memcmp(psnce
->nameHash
, psce
->u
.ssl3
.srvNameHash
,
810 /* The name doesen't match the SID cache entry,
811 ** so invalidate the SID cache entry.
817 UnlockSidCacheLock(cache
->srvNameCacheLock
);
819 /* what the ??. Didn't get the cert cache lock.
820 ** Don't invalidate the SID cache entry, but don't find it.
822 PORT_Assert(!("Didn't get name Cache Lock!"));
830 psce
->lastAccessTime
= now
;
831 sce
= *psce
; /* grab a copy while holding the lock */
834 UnlockSet(cache
, set
);
836 /* sce conains a copy of the cache entry.
837 ** Convert shared memory format to local format
839 sid
= ConvertToSID(&sce
, pcce
? &cce
: 0, psnce
? &snce
: 0, dbHandle
);
845 ** Place a sid into the cache, if it isn't already there.
848 ServerSessionIDCache(sslSessionID
*sid
)
852 uint16 version
= sid
->version
;
853 cacheDesc
* cache
= &globalCache
;
855 if ((version
>= SSL_LIBRARY_VERSION_3_0
) &&
856 (sid
->u
.ssl3
.sessionIDLength
== 0)) {
860 if (sid
->cached
== never_cached
|| sid
->cached
== invalid_cache
) {
863 PORT_Assert(sid
->creationTime
!= 0);
864 if (!sid
->creationTime
)
865 sid
->lastAccessTime
= sid
->creationTime
= ssl_Time();
866 if (version
< SSL_LIBRARY_VERSION_3_0
) {
867 /* override caller's expiration time, which uses client timeout
868 * duration, not server timeout duration.
870 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl2Timeout
;
871 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
872 "cipher=%d", myPid
, sid
->cached
,
873 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
874 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
875 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
876 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl2
.sessionID
,
877 SSL2_SESSIONID_BYTES
));
878 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
879 sid
->u
.ssl2
.masterKey
.len
));
880 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
881 sid
->u
.ssl2
.cipherArg
.len
));
884 /* override caller's expiration time, which uses client timeout
885 * duration, not server timeout duration.
887 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl3Timeout
;
888 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
889 "cipherSuite=%d", myPid
, sid
->cached
,
890 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
891 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
892 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
893 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl3
.sessionID
,
894 sid
->u
.ssl3
.sessionIDLength
));
897 ConvertFromSID(&sce
, sid
);
899 if (version
>= SSL_LIBRARY_VERSION_3_0
) {
900 SECItem
*name
= &sid
->u
.ssl3
.srvName
;
901 if (name
->len
&& name
->data
) {
902 now
= CacheSrvName(cache
, name
, &sce
);
904 if (sid
->peerCert
!= NULL
) {
905 now
= CacheCert(cache
, sid
->peerCert
, &sce
);
909 set
= SIDindex(cache
, &sce
.addr
, sce
.sessionID
, sce
.sessionIDLength
);
910 now
= LockSet(cache
, set
, now
);
912 PRUint32 next
= cache
->sidCacheSets
[set
].next
;
913 PRUint32 ndx
= set
* SID_CACHE_ENTRIES_PER_SET
+ next
;
915 /* Write out new cache entry */
916 cache
->sidCacheData
[ndx
] = sce
;
918 cache
->sidCacheSets
[set
].next
=
919 (next
+ 1) % SID_CACHE_ENTRIES_PER_SET
;
921 UnlockSet(cache
, set
);
922 sid
->cached
= in_server_cache
;
928 ** Although this is static, it is called from ssl via global function pointer
929 ** ssl_sid_uncache. This invalidates the referenced cache entry.
932 ServerSessionIDUncache(sslSessionID
*sid
)
934 cacheDesc
* cache
= &globalCache
;
936 unsigned int sessionIDLength
;
945 /* Uncaching a SID should never change the error code.
946 ** So save it here and restore it before exiting.
950 if (sid
->version
< SSL_LIBRARY_VERSION_3_0
) {
951 sessionID
= sid
->u
.ssl2
.sessionID
;
952 sessionIDLength
= SSL2_SESSIONID_BYTES
;
953 SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
954 "cipher=%d", myPid
, sid
->cached
,
955 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
956 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
957 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
958 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
959 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
960 sid
->u
.ssl2
.masterKey
.len
));
961 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
962 sid
->u
.ssl2
.cipherArg
.len
));
964 sessionID
= sid
->u
.ssl3
.sessionID
;
965 sessionIDLength
= sid
->u
.ssl3
.sessionIDLength
;
966 SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
967 "cipherSuite=%d", myPid
, sid
->cached
,
968 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
969 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
970 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
971 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
973 set
= SIDindex(cache
, &sid
->addr
, sessionID
, sessionIDLength
);
974 now
= LockSet(cache
, set
, 0);
976 psce
= FindSID(cache
, set
, now
, &sid
->addr
, sessionID
, sessionIDLength
);
980 UnlockSet(cache
, set
);
982 sid
->cached
= invalid_cache
;
988 #define INCL_DOSPROCESS
995 DosGetInfoBlocks(&ptib
, &ppib
);
996 return ((long)ptib
->tib_ordinal
); /* thread id */
1001 CloseCache(cacheDesc
*cache
)
1003 int locks_initialized
= cache
->numSIDCacheLocksInitialized
;
1005 if (cache
->cacheMem
) {
1006 if (cache
->sharedCache
) {
1007 sidCacheLock
*pLock
= cache
->sidCacheLocks
;
1008 for (; locks_initialized
> 0; --locks_initialized
, ++pLock
) {
1009 /* If everInherited is true, this shared cache was (and may
1010 ** still be) in use by multiple processes. We do not wish to
1011 ** destroy the mutexes while they are still in use, but we do
1012 ** want to free mutex resources associated with this process.
1014 sslMutex_Destroy(&pLock
->mutex
,
1015 cache
->sharedCache
->everInherited
);
1018 if (cache
->shared
) {
1019 PR_MemUnmap(cache
->cacheMem
, cache
->cacheMemSize
);
1021 PORT_Free(cache
->cacheMem
);
1023 cache
->cacheMem
= NULL
;
1025 if (cache
->cacheMemMap
) {
1026 PR_CloseFileMap(cache
->cacheMemMap
);
1027 cache
->cacheMemMap
= NULL
;
1029 memset(cache
, 0, sizeof *cache
);
1033 InitCache(cacheDesc
*cache
, int maxCacheEntries
, int maxCertCacheEntries
,
1034 int maxSrvNameCacheEntries
, PRUint32 ssl2_timeout
,
1035 PRUint32 ssl3_timeout
, const char *directory
, PRBool shared
)
1038 sidCacheLock
*pLock
;
1040 PRFileMap
* cacheMemMap
;
1041 char * cfn
= NULL
; /* cache file name */
1042 int locks_initialized
= 0;
1043 int locks_to_initialize
= 0;
1046 if ( (!cache
) || (maxCacheEntries
< 0) || (!directory
) ) {
1047 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1051 if (cache
->cacheMem
) {
1056 /* make sure loser can clean up properly */
1057 cache
->shared
= shared
;
1058 cache
->cacheMem
= cacheMem
= NULL
;
1059 cache
->cacheMemMap
= cacheMemMap
= NULL
;
1060 cache
->sharedCache
= (cacheDesc
*)0;
1062 cache
->numSIDCacheLocksInitialized
= 0;
1063 cache
->nextCertCacheEntry
= 0;
1064 cache
->stopPolling
= PR_FALSE
;
1065 cache
->everInherited
= PR_FALSE
;
1066 cache
->poller
= NULL
;
1067 cache
->mutexTimeout
= 0;
1069 cache
->numSIDCacheEntries
= maxCacheEntries
? maxCacheEntries
1070 : DEF_SID_CACHE_ENTRIES
;
1071 cache
->numSIDCacheSets
=
1072 SID_HOWMANY(cache
->numSIDCacheEntries
, SID_CACHE_ENTRIES_PER_SET
);
1074 cache
->numSIDCacheEntries
=
1075 cache
->numSIDCacheSets
* SID_CACHE_ENTRIES_PER_SET
;
1077 cache
->numSIDCacheLocks
=
1078 PR_MIN(cache
->numSIDCacheSets
, ssl_max_sid_cache_locks
);
1080 cache
->numSIDCacheSetsPerLock
=
1081 SID_HOWMANY(cache
->numSIDCacheSets
, cache
->numSIDCacheLocks
);
1083 cache
->numCertCacheEntries
= (maxCertCacheEntries
> 0) ?
1084 maxCertCacheEntries
: 0;
1085 cache
->numSrvNameCacheEntries
= (maxSrvNameCacheEntries
>= 0) ?
1086 maxSrvNameCacheEntries
: DEF_NAME_CACHE_ENTRIES
;
1088 /* compute size of shared memory, and offsets of all pointers */
1090 cache
->cacheMem
= (char *)ptr
;
1091 ptr
+= SID_ROUNDUP(sizeof(cacheDesc
), SID_ALIGNMENT
);
1093 cache
->sidCacheLocks
= (sidCacheLock
*)ptr
;
1094 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1095 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1096 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1097 ptr
= (ptrdiff_t)(cache
->srvNameCacheLock
+ 1);
1098 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1100 cache
->sidCacheSets
= (sidCacheSet
*)ptr
;
1101 ptr
= (ptrdiff_t)(cache
->sidCacheSets
+ cache
->numSIDCacheSets
);
1102 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1104 cache
->sidCacheData
= (sidCacheEntry
*)ptr
;
1105 ptr
= (ptrdiff_t)(cache
->sidCacheData
+ cache
->numSIDCacheEntries
);
1106 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1108 cache
->certCacheData
= (certCacheEntry
*)ptr
;
1109 cache
->sidCacheSize
=
1110 (char *)cache
->certCacheData
- (char *)cache
->sidCacheData
;
1112 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
) {
1113 /* This is really a poor way to computer this! */
1114 cache
->numCertCacheEntries
= cache
->sidCacheSize
/ sizeof(certCacheEntry
);
1115 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
)
1116 cache
->numCertCacheEntries
= MIN_CERT_CACHE_ENTRIES
;
1118 ptr
= (ptrdiff_t)(cache
->certCacheData
+ cache
->numCertCacheEntries
);
1119 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1121 cache
->keyCacheData
= (SSLWrappedSymWrappingKey
*)ptr
;
1122 cache
->certCacheSize
=
1123 (char *)cache
->keyCacheData
- (char *)cache
->certCacheData
;
1125 cache
->numKeyCacheEntries
= kt_kea_size
* SSL_NUM_WRAP_MECHS
;
1126 ptr
= (ptrdiff_t)(cache
->keyCacheData
+ cache
->numKeyCacheEntries
);
1127 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1129 cache
->keyCacheSize
= (char *)ptr
- (char *)cache
->keyCacheData
;
1131 cache
->ticketKeyNameSuffix
= (uint8
*)ptr
;
1132 ptr
= (ptrdiff_t)(cache
->ticketKeyNameSuffix
+
1133 SESS_TICKET_KEY_VAR_NAME_LEN
);
1134 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1136 cache
->ticketEncKey
= (encKeyCacheEntry
*)ptr
;
1137 ptr
= (ptrdiff_t)(cache
->ticketEncKey
+ 1);
1138 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1140 cache
->ticketMacKey
= (encKeyCacheEntry
*)ptr
;
1141 ptr
= (ptrdiff_t)(cache
->ticketMacKey
+ 1);
1142 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1144 cache
->ticketKeysValid
= (PRUint32
*)ptr
;
1145 ptr
= (ptrdiff_t)(cache
->ticketKeysValid
+ 1);
1146 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1148 cache
->srvNameCacheData
= (srvNameCacheEntry
*)ptr
;
1149 cache
->srvNameCacheSize
=
1150 cache
->numSrvNameCacheEntries
* sizeof(srvNameCacheEntry
);
1151 ptr
= (ptrdiff_t)(cache
->srvNameCacheData
+ cache
->numSrvNameCacheEntries
);
1152 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1154 cache
->cacheMemSize
= ptr
;
1157 if (ssl2_timeout
> MAX_SSL2_TIMEOUT
) {
1158 ssl2_timeout
= MAX_SSL2_TIMEOUT
;
1160 if (ssl2_timeout
< MIN_SSL2_TIMEOUT
) {
1161 ssl2_timeout
= MIN_SSL2_TIMEOUT
;
1163 cache
->ssl2Timeout
= ssl2_timeout
;
1165 cache
->ssl2Timeout
= DEF_SSL2_TIMEOUT
;
1169 if (ssl3_timeout
> MAX_SSL3_TIMEOUT
) {
1170 ssl3_timeout
= MAX_SSL3_TIMEOUT
;
1172 if (ssl3_timeout
< MIN_SSL3_TIMEOUT
) {
1173 ssl3_timeout
= MIN_SSL3_TIMEOUT
;
1175 cache
->ssl3Timeout
= ssl3_timeout
;
1177 cache
->ssl3Timeout
= DEF_SSL3_TIMEOUT
;
1181 /* Create file names */
1182 #if defined(XP_UNIX) || defined(XP_BEOS)
1183 /* there's some confusion here about whether PR_OpenAnonFileMap wants
1184 ** a directory name or a file name for its first argument.
1185 cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1187 cfn
= PR_smprintf("%s", directory
);
1188 #elif defined(XP_WIN32)
1189 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1190 GetCurrentThreadId());
1191 #elif defined(XP_OS2)
1192 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1195 #error "Don't know how to create file name for this platform!"
1202 cacheMemMap
= PR_OpenAnonFileMap(cfn
, cache
->cacheMemSize
,
1205 PR_smprintf_free(cfn
);
1210 cacheMem
= PR_MemMap(cacheMemMap
, 0, cache
->cacheMemSize
);
1212 cacheMem
= PORT_Alloc(cache
->cacheMemSize
);
1219 /* Initialize shared memory. This may not be necessary on all platforms */
1220 memset(cacheMem
, 0, cache
->cacheMemSize
);
1222 /* Copy cache descriptor header into shared memory */
1223 memcpy(cacheMem
, cache
, sizeof *cache
);
1225 /* save private copies of these values */
1226 cache
->cacheMemMap
= cacheMemMap
;
1227 cache
->cacheMem
= cacheMem
;
1228 cache
->sharedCache
= (cacheDesc
*)cacheMem
;
1230 /* Fix pointers in our private copy of cache descriptor to point to
1231 ** spaces in shared memory
1233 ptr
= (ptrdiff_t)cache
->cacheMem
;
1234 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1235 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1236 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1237 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1238 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1239 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1240 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1241 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1242 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1243 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1244 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1245 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1246 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1248 /* initialize the locks */
1249 init_time
= ssl_Time();
1250 pLock
= cache
->sidCacheLocks
;
1251 for (locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1252 locks_initialized
< locks_to_initialize
;
1253 ++locks_initialized
, ++pLock
) {
1255 SECStatus err
= sslMutex_Init(&pLock
->mutex
, shared
);
1257 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1260 pLock
->timeStamp
= init_time
;
1263 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1273 SSL_GetMaxServerCacheLocks(void)
1275 return ssl_max_sid_cache_locks
+ 2;
1276 /* The extra two are the cert cache lock and the key cache lock. */
1280 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
1282 /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1283 ** We'd like to test for a maximum value, but not all platforms' header
1284 ** files provide a symbol or function or other means of determining
1285 ** the maximum, other than trial and error.
1288 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1291 ssl_max_sid_cache_locks
= maxLocks
- 2;
1292 /* The extra two are the cert cache lock and the key cache lock. */
1297 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc
*cache
,
1298 PRUint32 ssl2_timeout
,
1299 PRUint32 ssl3_timeout
,
1300 const char * directory
,
1302 int maxCacheEntries
,
1303 int maxCertCacheEntries
,
1304 int maxSrvNameCacheEntries
)
1308 PORT_Assert(sizeof(sidCacheEntry
) == 192);
1309 PORT_Assert(sizeof(certCacheEntry
) == 4096);
1310 PORT_Assert(sizeof(srvNameCacheEntry
) == 1072);
1313 if (rv
!= SECSuccess
) {
1317 myPid
= SSL_GETPID();
1319 directory
= DEFAULT_CACHE_DIRECTORY
;
1321 rv
= InitCache(cache
, maxCacheEntries
, maxCertCacheEntries
,
1322 maxSrvNameCacheEntries
, ssl2_timeout
, ssl3_timeout
,
1329 ssl_sid_lookup
= ServerSessionIDLookup
;
1330 ssl_sid_cache
= ServerSessionIDCache
;
1331 ssl_sid_uncache
= ServerSessionIDUncache
;
1336 SSL_ConfigServerSessionIDCacheInstance( cacheDesc
*cache
,
1337 int maxCacheEntries
,
1338 PRUint32 ssl2_timeout
,
1339 PRUint32 ssl3_timeout
,
1340 const char * directory
, PRBool shared
)
1342 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1352 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
1353 PRUint32 ssl2_timeout
,
1354 PRUint32 ssl3_timeout
,
1355 const char * directory
)
1357 ssl_InitSessionCacheLocks(PR_FALSE
);
1358 return SSL_ConfigServerSessionIDCacheInstance(&globalCache
,
1359 maxCacheEntries
, ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
);
1363 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc
*cache
)
1370 SSL_ShutdownServerSessionIDCache(void)
1372 #if defined(XP_UNIX) || defined(XP_BEOS)
1373 /* Stop the thread that polls cache for expired locks on Unix */
1374 StopLockPoller(&globalCache
);
1376 SSL3_ShutdownServerCache();
1377 return SSL_ShutdownServerSessionIDCacheInstance(&globalCache
);
1380 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1381 * if the cache will be shared by multiple processes.
1384 ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout
,
1385 PRUint32 ssl3_timeout
,
1386 const char * directory
,
1387 int maxCacheEntries
,
1388 int maxCertCacheEntries
,
1389 int maxSrvNameCacheEntries
)
1393 cacheDesc
* cache
= &globalCache
;
1397 SECStatus putEnvFailed
;
1398 inheritance inherit
;
1399 char fmString
[PR_FILEMAP_STRING_BUFSIZE
];
1401 isMultiProcess
= PR_TRUE
;
1402 result
= ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1403 ssl2_timeout
, ssl3_timeout
, directory
, PR_TRUE
,
1404 maxCacheEntries
, maxCacheEntries
, maxSrvNameCacheEntries
);
1405 if (result
!= SECSuccess
)
1408 prStatus
= PR_ExportFileMapAsString(cache
->cacheMemMap
,
1409 sizeof fmString
, fmString
);
1410 if ((prStatus
!= PR_SUCCESS
) || !(fmStrLen
= strlen(fmString
))) {
1415 inherit
.cacheMemSize
= cache
->cacheMemSize
;
1416 inherit
.fmStrLen
= fmStrLen
;
1418 inhValue
= BTOA_DataToAscii((unsigned char *)&inherit
, sizeof inherit
);
1419 if (!inhValue
|| !strlen(inhValue
)) {
1423 envValue
= PR_smprintf("%s,%s", inhValue
, fmString
);
1424 if (!envValue
|| !strlen(envValue
)) {
1428 PORT_Free(inhValue
);
1430 putEnvFailed
= (SECStatus
)NSS_PutEnv(envVarName
, envValue
);
1431 PR_smprintf_free(envValue
);
1434 result
= SECFailure
;
1437 #if defined(XP_UNIX) || defined(XP_BEOS)
1438 /* Launch thread to poll cache for expired locks on Unix */
1439 LaunchLockPoller(cache
);
1444 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1445 * if the cache will be shared by multiple processes.
1448 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
1449 PRUint32 ssl2_timeout
,
1450 PRUint32 ssl3_timeout
,
1451 const char * directory
)
1453 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
,
1461 SSL_ConfigServerSessionIDCacheWithOpt(
1462 PRUint32 ssl2_timeout
,
1463 PRUint32 ssl3_timeout
,
1464 const char * directory
,
1465 int maxCacheEntries
,
1466 int maxCertCacheEntries
,
1467 int maxSrvNameCacheEntries
,
1468 PRBool enableMPCache
)
1470 if (!enableMPCache
) {
1471 ssl_InitSessionCacheLocks(PR_FALSE
);
1472 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache
,
1473 ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
,
1474 maxCacheEntries
, maxCertCacheEntries
, maxSrvNameCacheEntries
);
1476 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
, ssl3_timeout
,
1477 directory
, maxCacheEntries
, maxCertCacheEntries
,
1478 maxSrvNameCacheEntries
);
1483 SSL_InheritMPServerSIDCacheInstance(cacheDesc
*cache
, const char * envString
)
1485 unsigned char * decoString
= NULL
;
1486 char * fmString
= NULL
;
1487 char * myEnvString
= NULL
;
1488 unsigned int decoLen
;
1490 inheritance inherit
;
1493 sidCacheLock
* newLocks
;
1494 int locks_initialized
= 0;
1495 int locks_to_initialize
= 0;
1497 SECStatus status
= ssl_Init();
1499 if (status
!= SECSuccess
) {
1503 myPid
= SSL_GETPID();
1505 /* If this child was created by fork(), and not by exec() on unix,
1506 ** then isMultiProcess will already be set.
1507 ** If not, we'll set it below.
1509 if (isMultiProcess
) {
1510 if (cache
&& cache
->sharedCache
) {
1511 cache
->sharedCache
->everInherited
= PR_TRUE
;
1513 return SECSuccess
; /* already done. */
1516 ssl_InitSessionCacheLocks(PR_FALSE
);
1518 ssl_sid_lookup
= ServerSessionIDLookup
;
1519 ssl_sid_cache
= ServerSessionIDCache
;
1520 ssl_sid_uncache
= ServerSessionIDUncache
;
1523 envString
= getenv(envVarName
);
1529 myEnvString
= PORT_Strdup(envString
);
1532 fmString
= strchr(myEnvString
, ',');
1537 decoString
= ATOB_AsciiToData(myEnvString
, &decoLen
);
1542 if (decoLen
!= sizeof inherit
) {
1547 PORT_Memcpy(&inherit
, decoString
, sizeof inherit
);
1549 if (strlen(fmString
) != inherit
.fmStrLen
) {
1553 memset(cache
, 0, sizeof *cache
);
1554 cache
->cacheMemSize
= inherit
.cacheMemSize
;
1557 cache
->cacheMemMap
= PR_ImportFileMapFromString(fmString
);
1558 if(! cache
->cacheMemMap
) {
1561 cache
->cacheMem
= PR_MemMap(cache
->cacheMemMap
, 0, cache
->cacheMemSize
);
1562 if (! cache
->cacheMem
) {
1565 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1567 if (cache
->sharedCache
->cacheMemSize
!= cache
->cacheMemSize
) {
1572 /* We're now going to overwrite the local cache instance with the
1573 ** shared copy of the cache struct, then update several values in
1574 ** the local cache using the values for cache->cacheMemMap and
1575 ** cache->cacheMem computed just above. So, we copy cache into
1576 ** the automatic variable "my", to preserve the variables while
1577 ** cache is overwritten.
1579 my
= *cache
; /* save values computed above. */
1580 memcpy(cache
, cache
->sharedCache
, sizeof *cache
); /* overwrite */
1582 /* Fix pointers in our private copy of cache descriptor to point to
1583 ** spaces in shared memory, whose address is now in "my".
1585 ptr
= (ptrdiff_t)my
.cacheMem
;
1586 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1587 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1588 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1589 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1590 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1591 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1592 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1593 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1594 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1595 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1596 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1597 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1598 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1600 cache
->cacheMemMap
= my
.cacheMemMap
;
1601 cache
->cacheMem
= my
.cacheMem
;
1602 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1605 /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1606 ** When NT fibers are used in a multi-process server, a second level of
1607 ** locking is needed to prevent a deadlock, in case a fiber acquires the
1608 ** cross-process mutex, yields, and another fiber is later scheduled on
1609 ** the same native thread and tries to acquire the cross-process mutex.
1610 ** We do this by using a PRLock in the sslMutex. However, it is stored in
1611 ** shared memory as part of sidCacheLocks, and we don't want to overwrite
1612 ** the PRLock of the parent process. So we need to make new, private
1613 ** copies of sidCacheLocks before modifying the sslMutex with our own
1617 /* note from jpierre : this should be free'd in child processes when
1618 ** a function is added to delete the SSL session cache in the future.
1620 locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1621 newLocks
= PORT_NewArray(sidCacheLock
, locks_to_initialize
);
1624 /* copy the old locks */
1625 memcpy(newLocks
, cache
->sidCacheLocks
,
1626 locks_to_initialize
* sizeof(sidCacheLock
));
1627 cache
->sidCacheLocks
= newLocks
;
1629 for (; locks_initialized
< locks_to_initialize
; ++locks_initialized
) {
1630 /* now, make a local PRLock in this sslMutex for this child process */
1632 err
= sslMutex_2LevelInit(&newLocks
[locks_initialized
].mutex
);
1633 if (err
!= SECSuccess
) {
1634 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1638 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1640 /* also fix the key and cert cache which use the last 2 lock entries */
1641 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1642 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1643 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1646 PORT_Free(myEnvString
);
1647 PORT_Free(decoString
);
1649 /* mark that we have inherited this. */
1650 cache
->sharedCache
->everInherited
= PR_TRUE
;
1651 isMultiProcess
= PR_TRUE
;
1656 PORT_Free(myEnvString
);
1658 PORT_Free(decoString
);
1664 SSL_InheritMPServerSIDCache(const char * envString
)
1666 return SSL_InheritMPServerSIDCacheInstance(&globalCache
, envString
);
1669 #if defined(XP_UNIX) || defined(XP_BEOS)
1671 #define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
1674 LockPoller(void * arg
)
1676 cacheDesc
* cache
= (cacheDesc
*)arg
;
1677 cacheDesc
* sharedCache
= cache
->sharedCache
;
1678 sidCacheLock
* pLock
;
1679 PRIntervalTime timeout
;
1682 int locks_polled
= 0;
1683 int locks_to_poll
= cache
->numSIDCacheLocks
+ 2;
1684 PRUint32 expiration
= cache
->mutexTimeout
;
1686 timeout
= PR_SecondsToInterval(expiration
);
1687 while(!sharedCache
->stopPolling
) {
1689 if (sharedCache
->stopPolling
)
1693 then
= now
- expiration
;
1694 for (pLock
= cache
->sidCacheLocks
, locks_polled
= 0;
1695 locks_to_poll
> locks_polled
&& !sharedCache
->stopPolling
;
1696 ++locks_polled
, ++pLock
) {
1699 if (pLock
->timeStamp
< then
&&
1700 pLock
->timeStamp
!= 0 &&
1701 (pid
= pLock
->pid
) != 0) {
1703 /* maybe we should try the lock? */
1704 int result
= kill(pid
, 0);
1705 if (result
< 0 && errno
== ESRCH
) {
1707 /* No process exists by that pid any more.
1708 ** Treat this mutex as abandoned.
1710 pLock
->timeStamp
= now
;
1712 rv
= sslMutex_Unlock(&pLock
->mutex
);
1713 if (rv
!= SECSuccess
) {
1718 } /* end of loop over locks */
1719 } /* end of entire polling loop */
1722 /* Launch thread to poll cache for expired locks */
1724 LaunchLockPoller(cacheDesc
*cache
)
1726 const char * timeoutString
;
1727 PRThread
* pollerThread
;
1729 cache
->mutexTimeout
= SID_LOCK_EXPIRATION_TIMEOUT
;
1730 timeoutString
= getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1731 if (timeoutString
) {
1732 long newTime
= strtol(timeoutString
, 0, 0);
1734 return SECSuccess
; /* application doesn't want poller thread */
1736 cache
->mutexTimeout
= (PRUint32
)newTime
;
1737 /* if error (newTime < 0) ignore it and use default */
1741 PR_CreateThread(PR_USER_THREAD
, LockPoller
, cache
, PR_PRIORITY_NORMAL
,
1742 PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
1743 if (!pollerThread
) {
1746 cache
->poller
= pollerThread
;
1750 /* Stop the thread that polls cache for expired locks */
1752 StopLockPoller(cacheDesc
*cache
)
1754 if (!cache
->poller
) {
1757 cache
->sharedCache
->stopPolling
= PR_TRUE
;
1758 if (PR_Interrupt(cache
->poller
) != PR_SUCCESS
) {
1761 if (PR_JoinThread(cache
->poller
) != PR_SUCCESS
) {
1764 cache
->poller
= NULL
;
1769 /************************************************************************
1770 * Code dealing with shared wrapped symmetric wrapping keys below *
1771 ************************************************************************/
1773 /* If now is zero, it implies that the lock is not held, and must be
1777 getSvrWrappingKey(PRInt32 symWrapMechIndex
,
1778 SSL3KEAType exchKeyType
,
1779 SSLWrappedSymWrappingKey
*wswk
,
1783 PRUint32 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
1784 SSLWrappedSymWrappingKey
* pwswk
= cache
->keyCacheData
+ ndx
;
1786 PRBool rv
= PR_FALSE
;
1788 if (!cache
->cacheMem
) { /* cache is uninitialized */
1789 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
1793 lockTime
= now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
1798 if (pwswk
->exchKeyType
== exchKeyType
&&
1799 pwswk
->symWrapMechIndex
== symWrapMechIndex
&&
1800 pwswk
->wrappedSymKeyLen
!= 0) {
1805 UnlockSidCacheLock(cache
->keyCacheLock
);
1811 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
1812 SSL3KEAType exchKeyType
,
1813 SSLWrappedSymWrappingKey
*wswk
)
1817 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
1818 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
1819 if ((unsigned)exchKeyType
< kt_kea_size
&&
1820 (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
) {
1821 rv
= getSvrWrappingKey(symWrapMechIndex
, exchKeyType
, wswk
,
1830 /* Wrap and cache a session ticket key. */
1832 WrapTicketKey(SECKEYPublicKey
*svrPubKey
, PK11SymKey
*symKey
,
1833 const char *keyName
, encKeyCacheEntry
* cacheEntry
)
1835 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1837 wrappedKey
.len
= SECKEY_PublicKeyStrength(svrPubKey
);
1838 PORT_Assert(wrappedKey
.len
<= sizeof(cacheEntry
->bytes
));
1839 if (wrappedKey
.len
> sizeof(cacheEntry
->bytes
))
1841 wrappedKey
.data
= cacheEntry
->bytes
;
1843 if (PK11_PubWrapSymKey(CKM_RSA_PKCS
, svrPubKey
, symKey
, &wrappedKey
)
1845 SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
1846 SSL_GETPID(), "unknown", keyName
));
1849 cacheEntry
->length
= wrappedKey
.len
;
1854 GenerateTicketKeys(void *pwArg
, unsigned char *keyName
, PK11SymKey
**aesKey
,
1855 PK11SymKey
**macKey
)
1858 CK_MECHANISM_TYPE mechanismArray
[2];
1859 PK11SymKey
*aesKeyTmp
= NULL
;
1860 PK11SymKey
*macKeyTmp
= NULL
;
1861 cacheDesc
*cache
= &globalCache
;
1862 uint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
1863 uint8
*ticketKeyNameSuffix
;
1865 if (!cache
->cacheMem
) {
1866 /* cache is not initalized. Use stack buffer */
1867 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
1869 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
1872 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
1873 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
) {
1874 SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
1875 SSL_GETPID(), "unknown"));
1879 mechanismArray
[0] = CKM_AES_CBC
;
1880 mechanismArray
[1] = CKM_SHA256_HMAC
;
1882 slot
= PK11_GetBestSlotMultiple(mechanismArray
, 2, pwArg
);
1884 aesKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[0], NULL
,
1885 AES_256_KEY_LENGTH
, pwArg
);
1886 macKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[1], NULL
,
1887 SHA256_LENGTH
, pwArg
);
1888 PK11_FreeSlot(slot
);
1891 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1892 SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
1893 SSL_GETPID(), "unknown"));
1896 PORT_Memcpy(keyName
, ticketKeyNameSuffix
, SESS_TICKET_KEY_VAR_NAME_LEN
);
1897 *aesKey
= aesKeyTmp
;
1898 *macKey
= macKeyTmp
;
1903 PK11_FreeSymKey(aesKeyTmp
);
1905 PK11_FreeSymKey(macKeyTmp
);
1910 GenerateAndWrapTicketKeys(SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1911 unsigned char *keyName
, PK11SymKey
**aesKey
,
1912 PK11SymKey
**macKey
)
1914 PK11SymKey
*aesKeyTmp
= NULL
;
1915 PK11SymKey
*macKeyTmp
= NULL
;
1916 cacheDesc
*cache
= &globalCache
;
1918 if (!GenerateTicketKeys(pwArg
, keyName
, &aesKeyTmp
, &macKeyTmp
)) {
1922 if (cache
->cacheMem
) {
1923 /* Export the keys to the shared cache in wrapped form. */
1924 if (!WrapTicketKey(svrPubKey
, aesKeyTmp
, "enc key", cache
->ticketEncKey
))
1926 if (!WrapTicketKey(svrPubKey
, macKeyTmp
, "mac key", cache
->ticketMacKey
))
1929 *aesKey
= aesKeyTmp
;
1930 *macKey
= macKeyTmp
;
1935 PK11_FreeSymKey(aesKeyTmp
);
1937 PK11_FreeSymKey(macKeyTmp
);
1942 UnwrapCachedTicketKeys(SECKEYPrivateKey
*svrPrivKey
, unsigned char *keyName
,
1943 PK11SymKey
**aesKey
, PK11SymKey
**macKey
)
1945 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1946 PK11SymKey
*aesKeyTmp
= NULL
;
1947 PK11SymKey
*macKeyTmp
= NULL
;
1948 cacheDesc
*cache
= &globalCache
;
1950 wrappedKey
.data
= cache
->ticketEncKey
->bytes
;
1951 wrappedKey
.len
= cache
->ticketEncKey
->length
;
1952 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketEncKey
->bytes
));
1953 aesKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1954 CKM_AES_CBC
, CKA_DECRYPT
, 0);
1956 wrappedKey
.data
= cache
->ticketMacKey
->bytes
;
1957 wrappedKey
.len
= cache
->ticketMacKey
->length
;
1958 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketMacKey
->bytes
));
1959 macKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1960 CKM_SHA256_HMAC
, CKA_SIGN
, 0);
1962 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1963 SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
1964 SSL_GETPID(), "unknown"));
1967 SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
1968 SSL_GETPID(), "unknown"));
1970 PORT_Memcpy(keyName
, cache
->ticketKeyNameSuffix
,
1971 SESS_TICKET_KEY_VAR_NAME_LEN
);
1972 *aesKey
= aesKeyTmp
;
1973 *macKey
= macKeyTmp
;
1978 PK11_FreeSymKey(aesKeyTmp
);
1980 PK11_FreeSymKey(macKeyTmp
);
1985 ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey
*svrPrivKey
,
1986 SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1987 unsigned char *keyName
, PK11SymKey
**aesKey
,
1988 PK11SymKey
**macKey
)
1991 PRBool rv
= PR_FALSE
;
1992 PRBool keysGenerated
= PR_FALSE
;
1993 cacheDesc
*cache
= &globalCache
;
1995 if (!cache
->cacheMem
) {
1996 /* cache is uninitialized. Generate keys and return them
1997 * without caching. */
1998 return GenerateTicketKeys(pwArg
, keyName
, aesKey
, macKey
);
2001 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2005 if (!*(cache
->ticketKeysValid
)) {
2006 /* Keys do not exist, create them. */
2007 if (!GenerateAndWrapTicketKeys(svrPubKey
, pwArg
, keyName
,
2010 keysGenerated
= PR_TRUE
;
2011 *(cache
->ticketKeysValid
) = 1;
2017 UnlockSidCacheLock(cache
->keyCacheLock
);
2018 if (rv
&& !keysGenerated
)
2019 rv
= UnwrapCachedTicketKeys(svrPrivKey
, keyName
, aesKey
, macKey
);
2024 ssl_GetSessionTicketKeys(unsigned char *keyName
, unsigned char *encKey
,
2025 unsigned char *macKey
)
2027 PRBool rv
= PR_FALSE
;
2029 cacheDesc
*cache
= &globalCache
;
2030 uint8 ticketMacKey
[AES_256_KEY_LENGTH
], ticketEncKey
[SHA256_LENGTH
];
2031 uint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
2032 uint8
*ticketMacKeyPtr
, *ticketEncKeyPtr
, *ticketKeyNameSuffix
;
2033 PRBool cacheIsEnabled
= PR_TRUE
;
2035 if (!cache
->cacheMem
) { /* cache is uninitialized */
2036 cacheIsEnabled
= PR_FALSE
;
2037 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
2038 ticketEncKeyPtr
= ticketEncKey
;
2039 ticketMacKeyPtr
= ticketMacKey
;
2041 /* these values have constant memory locations in the cache.
2042 * Ok to reference them without holding the lock. */
2043 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
2044 ticketEncKeyPtr
= cache
->ticketEncKey
->bytes
;
2045 ticketMacKeyPtr
= cache
->ticketMacKey
->bytes
;
2048 if (cacheIsEnabled
) {
2049 /* Grab lock if initialized. */
2050 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2054 /* Going to regenerate keys on every call if cache was not
2056 if (!cacheIsEnabled
|| !*(cache
->ticketKeysValid
)) {
2057 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
2058 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
)
2060 if (PK11_GenerateRandom(ticketEncKeyPtr
,
2061 AES_256_KEY_LENGTH
) != SECSuccess
)
2063 if (PK11_GenerateRandom(ticketMacKeyPtr
,
2064 SHA256_LENGTH
) != SECSuccess
)
2066 if (cacheIsEnabled
) {
2067 *(cache
->ticketKeysValid
) = 1;
2074 if (cacheIsEnabled
) {
2075 UnlockSidCacheLock(cache
->keyCacheLock
);
2078 PORT_Memcpy(keyName
, ticketKeyNameSuffix
,
2079 SESS_TICKET_KEY_VAR_NAME_LEN
);
2080 PORT_Memcpy(encKey
, ticketEncKeyPtr
, AES_256_KEY_LENGTH
);
2081 PORT_Memcpy(macKey
, ticketMacKeyPtr
, SHA256_LENGTH
);
2086 /* The caller passes in the new value it wants
2087 * to set. This code tests the wrapped sym key entry in the shared memory.
2088 * If it is uninitialized, this function writes the caller's value into
2089 * the disk entry, and returns false.
2090 * Otherwise, it overwrites the caller's wswk with the value obtained from
2091 * the disk, and returns PR_TRUE.
2092 * This is all done while holding the locks/mutexes necessary to make
2093 * the operation atomic.
2096 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2098 cacheDesc
* cache
= &globalCache
;
2099 PRBool rv
= PR_FALSE
;
2100 SSL3KEAType exchKeyType
= wswk
->exchKeyType
;
2101 /* type of keys used to wrap SymWrapKey*/
2102 PRInt32 symWrapMechIndex
= wswk
->symWrapMechIndex
;
2105 SSLWrappedSymWrappingKey myWswk
;
2107 if (!cache
->cacheMem
) { /* cache is uninitialized */
2108 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
2112 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
2113 if ((unsigned)exchKeyType
>= kt_kea_size
)
2116 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
2117 if ((unsigned)symWrapMechIndex
>= SSL_NUM_WRAP_MECHS
)
2120 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
2121 PORT_Memset(&myWswk
, 0, sizeof myWswk
); /* eliminate UMRs. */
2123 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2125 rv
= getSvrWrappingKey(wswk
->symWrapMechIndex
, wswk
->exchKeyType
,
2126 &myWswk
, cache
, now
);
2128 /* we found it on disk, copy it out to the caller. */
2129 PORT_Memcpy(wswk
, &myWswk
, sizeof *wswk
);
2131 /* Wasn't on disk, and we're still holding the lock, so write it. */
2132 cache
->keyCacheData
[ndx
] = *wswk
;
2134 UnlockSidCacheLock(cache
->keyCacheLock
);
2139 #else /* MAC version or other platform */
2141 #include "seccomon.h"
2144 #include "sslimpl.h"
2147 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
2148 PRUint32 ssl2_timeout
,
2149 PRUint32 ssl3_timeout
,
2150 const char * directory
)
2152 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
2157 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
2158 PRUint32 ssl2_timeout
,
2159 PRUint32 ssl3_timeout
,
2160 const char * directory
)
2162 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
2167 SSL_InheritMPServerSIDCache(const char * envString
)
2169 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
2174 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
2175 SSL3KEAType exchKeyType
,
2176 SSLWrappedSymWrappingKey
*wswk
)
2178 PRBool rv
= PR_FALSE
;
2179 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
2183 /* This is a kind of test-and-set. The caller passes in the new value it wants
2184 * to set. This code tests the wrapped sym key entry in the shared memory.
2185 * If it is uninitialized, this function writes the caller's value into
2186 * the disk entry, and returns false.
2187 * Otherwise, it overwrites the caller's wswk with the value obtained from
2188 * the disk, and returns PR_TRUE.
2189 * This is all done while holding the locks/mutexes necessary to make
2190 * the operation atomic.
2193 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2195 PRBool rv
= PR_FALSE
;
2196 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
2201 SSL_GetMaxServerCacheLocks(void)
2203 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
2208 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
2210 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
2214 #endif /* XP_UNIX || XP_WIN32 */