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/. */
8 /* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
11 * About record locking among different server processes:
13 * All processes that are part of the same conceptual server (serving on
14 * the same address and port) MUST share a common SSL session cache.
15 * This code makes the content of the shared cache accessible to all
16 * processes on the same "server". This code works on Unix and Win32 only.
18 * We use NSPR anonymous shared memory and move data to & from shared memory.
19 * We must do explicit locking of the records for all reads and writes.
20 * The set of Cache entries are divided up into "sets" of 128 entries.
21 * Each set is protected by a lock. There may be one or more sets protected
22 * by each lock. That is, locks to sets are 1:N.
23 * There is one lock for the entire cert cache.
24 * There is one lock for the set of wrapped sym wrap keys.
26 * The anonymous shared memory is laid out as if it were declared like this:
29 * cacheDescriptor desc;
30 * sidCacheLock sidCacheLocks[ numSIDCacheLocks];
31 * sidCacheLock keyCacheLock;
32 * sidCacheLock certCacheLock;
33 * sidCacheSet sidCacheSets[ numSIDCacheSets ];
34 * sidCacheEntry sidCacheData[ numSIDCacheEntries];
35 * certCacheEntry certCacheData[numCertCacheEntries];
36 * SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
37 * PRUint8 keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
38 * encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode
39 * encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode
40 * PRBool ticketKeysValid;
41 * sidCacheLock srvNameCacheLock;
42 * srvNameCacheEntry srvNameData[ numSrvNameCacheEntries ];
43 * } cacheMemCacheData;
47 #if defined(XP_UNIX) || defined(XP_WIN32) || defined (XP_OS2) || defined(XP_BEOS)
56 #ifdef NO_PKCS11_BYPASS
65 #if defined(XP_UNIX) || defined(XP_BEOS)
82 #include <sys/types.h>
84 #define SET_ERROR_CODE /* reminder */
90 ** Format of a cache entry in the shared memory.
92 struct sidCacheEntryStr
{
93 /* 16 */ PRIPv6Addr addr
; /* client's IP address */
94 /* 4 */ PRUint32 creationTime
;
95 /* 4 */ PRUint32 lastAccessTime
;
96 /* 4 */ PRUint32 expirationTime
;
97 /* 2 */ PRUint16 version
;
98 /* 1 */ PRUint8 valid
;
99 /* 1 */ PRUint8 sessionIDLength
;
100 /* 32 */ PRUint8 sessionID
[SSL3_SESSIONID_BYTES
];
101 /* 2 */ PRUint16 authAlgorithm
;
102 /* 2 */ PRUint16 authKeyBits
;
103 /* 2 */ PRUint16 keaType
;
104 /* 2 */ PRUint16 keaKeyBits
;
105 /* 72 - common header total */
109 /* 64 */ PRUint8 masterKey
[SSL_MAX_MASTER_KEY_BYTES
];
110 /* 32 */ PRUint8 cipherArg
[SSL_MAX_CYPHER_ARG_BYTES
];
112 /* 1 */ PRUint8 cipherType
;
113 /* 1 */ PRUint8 masterKeyLen
;
114 /* 1 */ PRUint8 keyBits
;
115 /* 1 */ PRUint8 secretKeyBits
;
116 /* 1 */ PRUint8 cipherArgLen
;
120 /* 2 */ ssl3CipherSuite cipherSuite
;
121 /* 2 */ PRUint16 compression
; /* SSLCompressionMethod */
123 /* 52 */ ssl3SidKeys keys
; /* keys, wrapped as needed. */
125 /* 4 */ PRUint32 masterWrapMech
;
126 /* 4 */ SSL3KEAType exchKeyType
;
127 /* 4 */ PRInt32 certIndex
;
128 /* 4 */ PRInt32 srvNameIndex
;
129 /* 32 */ PRUint8 srvNameHash
[SHA256_LENGTH
]; /* SHA256 name hash */
131 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
133 /*120 */ PRUint8 filler
[120]; /* 72+120==192, a multiple of 16 */
137 typedef struct sidCacheEntryStr sidCacheEntry
;
139 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
140 struct certCacheEntryStr
{
141 PRUint16 certLength
; /* 2 */
142 PRUint16 sessionIDLength
; /* 2 */
143 PRUint8 sessionID
[SSL3_SESSIONID_BYTES
]; /* 32 */
144 PRUint8 cert
[SSL_MAX_CACHED_CERT_LEN
]; /* 4060 */
146 typedef struct certCacheEntryStr certCacheEntry
;
148 struct sidCacheLockStr
{
153 typedef struct sidCacheLockStr sidCacheLock
;
155 struct sidCacheSetStr
{
158 typedef struct sidCacheSetStr sidCacheSet
;
160 struct encKeyCacheEntryStr
{
164 typedef struct encKeyCacheEntryStr encKeyCacheEntry
;
166 #define SSL_MAX_DNS_HOST_NAME 1024
168 struct srvNameCacheEntryStr
{
169 PRUint16 type
; /* 2 */
170 PRUint16 nameLen
; /* 2 */
171 PRUint8 name
[SSL_MAX_DNS_HOST_NAME
+ 12]; /* 1034 */
172 PRUint8 nameHash
[SHA256_LENGTH
]; /* 32 */
175 typedef struct srvNameCacheEntryStr srvNameCacheEntry
;
178 struct cacheDescStr
{
180 PRUint32 cacheMemSize
;
182 PRUint32 numSIDCacheLocks
;
183 PRUint32 numSIDCacheSets
;
184 PRUint32 numSIDCacheSetsPerLock
;
186 PRUint32 numSIDCacheEntries
;
187 PRUint32 sidCacheSize
;
189 PRUint32 numCertCacheEntries
;
190 PRUint32 certCacheSize
;
192 PRUint32 numKeyCacheEntries
;
193 PRUint32 keyCacheSize
;
195 PRUint32 numSrvNameCacheEntries
;
196 PRUint32 srvNameCacheSize
;
198 PRUint32 ssl2Timeout
;
199 PRUint32 ssl3Timeout
;
201 PRUint32 numSIDCacheLocksInitialized
;
203 /* These values are volatile, and are accessed through sharedCache-> */
204 PRUint32 nextCertCacheEntry
; /* certCacheLock protects */
206 PRBool everInherited
;
208 /* The private copies of these values are pointers into shared mem */
209 /* The copies of these values in shared memory are merely offsets */
210 sidCacheLock
* sidCacheLocks
;
211 sidCacheLock
* keyCacheLock
;
212 sidCacheLock
* certCacheLock
;
213 sidCacheLock
* srvNameCacheLock
;
214 sidCacheSet
* sidCacheSets
;
215 sidCacheEntry
* sidCacheData
;
216 certCacheEntry
* certCacheData
;
217 SSLWrappedSymWrappingKey
* keyCacheData
;
218 PRUint8
* ticketKeyNameSuffix
;
219 encKeyCacheEntry
* ticketEncKey
;
220 encKeyCacheEntry
* ticketMacKey
;
221 PRUint32
* ticketKeysValid
;
222 srvNameCacheEntry
* srvNameCacheData
;
224 /* Only the private copies of these pointers are valid */
226 struct cacheDescStr
* sharedCache
; /* shared copy of this struct */
227 PRFileMap
* cacheMemMap
;
229 PRUint32 mutexTimeout
;
232 typedef struct cacheDescStr cacheDesc
;
234 static cacheDesc globalCache
;
236 static const char envVarName
[] = { SSL_ENV_VAR_NAME
};
238 static PRBool isMultiProcess
= PR_FALSE
;
241 #define DEF_SID_CACHE_ENTRIES 10000
242 #define DEF_CERT_CACHE_ENTRIES 250
243 #define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
244 #define DEF_KEY_CACHE_ENTRIES 250
245 #define DEF_NAME_CACHE_ENTRIES 1000
247 #define SID_CACHE_ENTRIES_PER_SET 128
248 #define SID_ALIGNMENT 16
250 #define DEF_SSL2_TIMEOUT 100 /* seconds */
251 #define MAX_SSL2_TIMEOUT 100 /* seconds */
252 #define MIN_SSL2_TIMEOUT 5 /* seconds */
254 #define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
255 #define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
256 #define MIN_SSL3_TIMEOUT 5 /* seconds */
258 #if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
259 #define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
261 #define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
263 #define MAX_SID_CACHE_LOCKS 256
266 #define SID_HOWMANY(val, size) (((val) + ((size) - 1)) / (size))
267 #define SID_ROUNDUP(val, size) ((size) * SID_HOWMANY((val), (size)))
271 static PRUint32 ssl_max_sid_cache_locks
= MAX_SID_CACHE_LOCKS
;
273 /* forward static function declarations */
274 static PRUint32
SIDindex(cacheDesc
*cache
, const PRIPv6Addr
*addr
, PRUint8
*s
,
276 static SECStatus
LaunchLockPoller(cacheDesc
*cache
);
277 static SECStatus
StopLockPoller(cacheDesc
*cache
);
280 struct inheritanceStr
{
281 PRUint32 cacheMemSize
;
285 typedef struct inheritanceStr inheritance
;
287 #if defined(_WIN32) || defined(XP_OS2)
289 #define DEFAULT_CACHE_DIRECTORY "\\temp"
293 #if defined(XP_UNIX) || defined(XP_BEOS)
295 #define DEFAULT_CACHE_DIRECTORY "/tmp"
297 #endif /* XP_UNIX || XP_BEOS */
300 /************************************************************************/
303 LockSidCacheLock(sidCacheLock
*lock
, PRUint32 now
)
305 SECStatus rv
= sslMutex_Lock(&lock
->mutex
);
306 if (rv
!= SECSuccess
)
310 lock
->timeStamp
= now
;
316 UnlockSidCacheLock(sidCacheLock
*lock
)
321 rv
= sslMutex_Unlock(&lock
->mutex
);
325 /* returns the value of ssl_Time on success, zero on failure. */
327 LockSet(cacheDesc
*cache
, PRUint32 set
, PRUint32 now
)
329 PRUint32 lockNum
= set
% cache
->numSIDCacheLocks
;
330 sidCacheLock
* lock
= cache
->sidCacheLocks
+ lockNum
;
332 return LockSidCacheLock(lock
, now
);
336 UnlockSet(cacheDesc
*cache
, PRUint32 set
)
338 PRUint32 lockNum
= set
% cache
->numSIDCacheLocks
;
339 sidCacheLock
* lock
= cache
->sidCacheLocks
+ lockNum
;
341 return UnlockSidCacheLock(lock
);
344 /************************************************************************/
347 /* Put a certificate in the cache. Update the cert index in the sce.
350 CacheCert(cacheDesc
* cache
, CERTCertificate
*cert
, sidCacheEntry
*sce
)
355 if ((cert
->derCert
.len
> SSL_MAX_CACHED_CERT_LEN
) ||
356 (cert
->derCert
.len
<= 0) ||
357 (cert
->derCert
.data
== NULL
)) {
358 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
362 cce
.sessionIDLength
= sce
->sessionIDLength
;
363 PORT_Memcpy(cce
.sessionID
, sce
->sessionID
, cce
.sessionIDLength
);
365 cce
.certLength
= cert
->derCert
.len
;
366 PORT_Memcpy(cce
.cert
, cert
->derCert
.data
, cce
.certLength
);
368 /* get lock on cert cache */
369 now
= LockSidCacheLock(cache
->certCacheLock
, 0);
372 /* Find where to place the next cert cache entry. */
373 cacheDesc
* sharedCache
= cache
->sharedCache
;
374 PRUint32 ndx
= sharedCache
->nextCertCacheEntry
;
376 /* write the entry */
377 cache
->certCacheData
[ndx
] = cce
;
379 /* remember where we put it. */
380 sce
->u
.ssl3
.certIndex
= ndx
;
382 /* update the "next" cache entry index */
383 sharedCache
->nextCertCacheEntry
=
384 (ndx
+ 1) % cache
->numCertCacheEntries
;
386 UnlockSidCacheLock(cache
->certCacheLock
);
392 /* Server configuration hash tables need to account the SECITEM.type
393 * field as well. These functions accomplish that. */
395 Get32BitNameHash(const SECItem
*name
)
397 PLHashNumber rv
= SECITEM_Hash(name
);
399 PRUint8
*rvc
= (PRUint8
*)&rv
;
400 rvc
[ name
->len
% sizeof(rv
) ] ^= name
->type
;
405 /* Put a name in the cache. Update the cert index in the sce.
408 CacheSrvName(cacheDesc
* cache
, SECItem
*name
, sidCacheEntry
*sce
)
412 srvNameCacheEntry snce
;
414 if (!name
|| name
->len
<= 0 ||
415 name
->len
> SSL_MAX_DNS_HOST_NAME
) {
416 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
420 snce
.type
= name
->type
;
421 snce
.nameLen
= name
->len
;
422 PORT_Memcpy(snce
.name
, name
->data
, snce
.nameLen
);
423 #ifdef NO_PKCS11_BYPASS
424 HASH_HashBuf(HASH_AlgSHA256
, snce
.nameHash
, name
->data
, name
->len
);
426 SHA256_HashBuf(snce
.nameHash
, (unsigned char*)name
->data
,
429 /* get index of the next name */
430 ndx
= Get32BitNameHash(name
);
431 /* get lock on cert cache */
432 now
= LockSidCacheLock(cache
->srvNameCacheLock
, 0);
434 if (cache
->numSrvNameCacheEntries
> 0) {
435 /* Fit the index into array */
436 ndx
%= cache
->numSrvNameCacheEntries
;
437 /* write the entry */
438 cache
->srvNameCacheData
[ndx
] = snce
;
439 /* remember where we put it. */
440 sce
->u
.ssl3
.srvNameIndex
= ndx
;
441 /* Copy hash into sid hash */
442 PORT_Memcpy(sce
->u
.ssl3
.srvNameHash
, snce
.nameHash
, SHA256_LENGTH
);
444 UnlockSidCacheLock(cache
->srvNameCacheLock
);
450 ** Convert local SID to shared memory one
453 ConvertFromSID(sidCacheEntry
*to
, sslSessionID
*from
)
456 to
->version
= from
->version
;
457 to
->addr
= from
->addr
;
458 to
->creationTime
= from
->creationTime
;
459 to
->lastAccessTime
= from
->lastAccessTime
;
460 to
->expirationTime
= from
->expirationTime
;
461 to
->authAlgorithm
= from
->authAlgorithm
;
462 to
->authKeyBits
= from
->authKeyBits
;
463 to
->keaType
= from
->keaType
;
464 to
->keaKeyBits
= from
->keaKeyBits
;
466 if (from
->version
< SSL_LIBRARY_VERSION_3_0
) {
467 if ((from
->u
.ssl2
.masterKey
.len
> SSL_MAX_MASTER_KEY_BYTES
) ||
468 (from
->u
.ssl2
.cipherArg
.len
> SSL_MAX_CYPHER_ARG_BYTES
)) {
469 SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
470 myPid
, from
->u
.ssl2
.masterKey
.len
,
471 from
->u
.ssl2
.cipherArg
.len
));
476 to
->u
.ssl2
.cipherType
= from
->u
.ssl2
.cipherType
;
477 to
->u
.ssl2
.masterKeyLen
= from
->u
.ssl2
.masterKey
.len
;
478 to
->u
.ssl2
.cipherArgLen
= from
->u
.ssl2
.cipherArg
.len
;
479 to
->u
.ssl2
.keyBits
= from
->u
.ssl2
.keyBits
;
480 to
->u
.ssl2
.secretKeyBits
= from
->u
.ssl2
.secretKeyBits
;
481 to
->sessionIDLength
= SSL2_SESSIONID_BYTES
;
482 PORT_Memcpy(to
->sessionID
, from
->u
.ssl2
.sessionID
, SSL2_SESSIONID_BYTES
);
483 PORT_Memcpy(to
->u
.ssl2
.masterKey
, from
->u
.ssl2
.masterKey
.data
,
484 from
->u
.ssl2
.masterKey
.len
);
485 PORT_Memcpy(to
->u
.ssl2
.cipherArg
, from
->u
.ssl2
.cipherArg
.data
,
486 from
->u
.ssl2
.cipherArg
.len
);
488 PORT_Memset(to
->u
.ssl2
.masterKey
+from
->u
.ssl2
.masterKey
.len
, 0,
489 sizeof(to
->u
.ssl2
.masterKey
) - from
->u
.ssl2
.masterKey
.len
);
490 PORT_Memset(to
->u
.ssl2
.cipherArg
+from
->u
.ssl2
.cipherArg
.len
, 0,
491 sizeof(to
->u
.ssl2
.cipherArg
) - from
->u
.ssl2
.cipherArg
.len
);
493 SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
494 "time=%d addr=0x%08x%08x%08x%08x cipherType=%d", myPid
,
495 to
->u
.ssl2
.masterKeyLen
, to
->u
.ssl2
.cipherArgLen
,
496 to
->creationTime
, to
->addr
.pr_s6_addr32
[0],
497 to
->addr
.pr_s6_addr32
[1], to
->addr
.pr_s6_addr32
[2],
498 to
->addr
.pr_s6_addr32
[3], to
->u
.ssl2
.cipherType
));
500 /* This is an SSL v3 session */
502 to
->u
.ssl3
.cipherSuite
= from
->u
.ssl3
.cipherSuite
;
503 to
->u
.ssl3
.compression
= (PRUint16
)from
->u
.ssl3
.compression
;
504 to
->u
.ssl3
.keys
= from
->u
.ssl3
.keys
;
505 to
->u
.ssl3
.masterWrapMech
= from
->u
.ssl3
.masterWrapMech
;
506 to
->u
.ssl3
.exchKeyType
= from
->u
.ssl3
.exchKeyType
;
507 to
->sessionIDLength
= from
->u
.ssl3
.sessionIDLength
;
508 to
->u
.ssl3
.certIndex
= -1;
509 to
->u
.ssl3
.srvNameIndex
= -1;
511 PORT_Memcpy(to
->sessionID
, from
->u
.ssl3
.sessionID
,
512 to
->sessionIDLength
);
514 SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
516 myPid
, to
->creationTime
, to
->addr
.pr_s6_addr32
[0],
517 to
->addr
.pr_s6_addr32
[1], to
->addr
.pr_s6_addr32
[2],
518 to
->addr
.pr_s6_addr32
[3], to
->u
.ssl3
.cipherSuite
));
523 ** Convert shared memory cache-entry to local memory based one
524 ** This is only called from ServerSessionIDLookup().
526 static sslSessionID
*
527 ConvertToSID(sidCacheEntry
* from
,
528 certCacheEntry
* pcce
,
529 srvNameCacheEntry
*psnce
,
530 CERTCertDBHandle
* dbHandle
)
533 PRUint16 version
= from
->version
;
535 to
= PORT_ZNew(sslSessionID
);
540 if (version
< SSL_LIBRARY_VERSION_3_0
) {
541 /* This is an SSL v2 session */
542 to
->u
.ssl2
.masterKey
.data
=
543 (unsigned char*) PORT_Alloc(from
->u
.ssl2
.masterKeyLen
);
544 if (!to
->u
.ssl2
.masterKey
.data
) {
547 if (from
->u
.ssl2
.cipherArgLen
) {
548 to
->u
.ssl2
.cipherArg
.data
=
549 (unsigned char*)PORT_Alloc(from
->u
.ssl2
.cipherArgLen
);
550 if (!to
->u
.ssl2
.cipherArg
.data
) {
553 PORT_Memcpy(to
->u
.ssl2
.cipherArg
.data
, from
->u
.ssl2
.cipherArg
,
554 from
->u
.ssl2
.cipherArgLen
);
557 to
->u
.ssl2
.cipherType
= from
->u
.ssl2
.cipherType
;
558 to
->u
.ssl2
.masterKey
.len
= from
->u
.ssl2
.masterKeyLen
;
559 to
->u
.ssl2
.cipherArg
.len
= from
->u
.ssl2
.cipherArgLen
;
560 to
->u
.ssl2
.keyBits
= from
->u
.ssl2
.keyBits
;
561 to
->u
.ssl2
.secretKeyBits
= from
->u
.ssl2
.secretKeyBits
;
562 /* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
563 PORT_Memcpy(to
->u
.ssl2
.sessionID
, from
->sessionID
, SSL2_SESSIONID_BYTES
);
564 PORT_Memcpy(to
->u
.ssl2
.masterKey
.data
, from
->u
.ssl2
.masterKey
,
565 from
->u
.ssl2
.masterKeyLen
);
567 SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
568 "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
569 myPid
, to
->u
.ssl2
.masterKey
.len
,
570 to
->u
.ssl2
.cipherArg
.len
, to
->creationTime
,
571 to
->addr
.pr_s6_addr32
[0], to
->addr
.pr_s6_addr32
[1],
572 to
->addr
.pr_s6_addr32
[2], to
->addr
.pr_s6_addr32
[3],
573 to
->u
.ssl2
.cipherType
));
575 /* This is an SSL v3 session */
577 to
->u
.ssl3
.sessionIDLength
= from
->sessionIDLength
;
578 to
->u
.ssl3
.cipherSuite
= from
->u
.ssl3
.cipherSuite
;
579 to
->u
.ssl3
.compression
= (SSLCompressionMethod
)from
->u
.ssl3
.compression
;
580 to
->u
.ssl3
.keys
= from
->u
.ssl3
.keys
;
581 to
->u
.ssl3
.masterWrapMech
= from
->u
.ssl3
.masterWrapMech
;
582 to
->u
.ssl3
.exchKeyType
= from
->u
.ssl3
.exchKeyType
;
583 if (from
->u
.ssl3
.srvNameIndex
!= -1 && psnce
) {
586 name
.type
= psnce
->type
;
587 name
.len
= psnce
->nameLen
;
588 name
.data
= psnce
->name
;
589 rv
= SECITEM_CopyItem(NULL
, &to
->u
.ssl3
.srvName
, &name
);
590 if (rv
!= SECSuccess
) {
595 PORT_Memcpy(to
->u
.ssl3
.sessionID
, from
->sessionID
, from
->sessionIDLength
);
597 /* the portions of the SID that are only restored on the client
598 * are set to invalid values on the server.
600 to
->u
.ssl3
.clientWriteKey
= NULL
;
601 to
->u
.ssl3
.serverWriteKey
= NULL
;
603 to
->urlSvrName
= NULL
;
605 to
->u
.ssl3
.masterModuleID
= (SECMODModuleID
)-1; /* invalid value */
606 to
->u
.ssl3
.masterSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
607 to
->u
.ssl3
.masterWrapIndex
= 0;
608 to
->u
.ssl3
.masterWrapSeries
= 0;
609 to
->u
.ssl3
.masterValid
= PR_FALSE
;
611 to
->u
.ssl3
.clAuthModuleID
= (SECMODModuleID
)-1; /* invalid value */
612 to
->u
.ssl3
.clAuthSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
613 to
->u
.ssl3
.clAuthSeries
= 0;
614 to
->u
.ssl3
.clAuthValid
= PR_FALSE
;
616 if (from
->u
.ssl3
.certIndex
!= -1 && pcce
) {
619 derCert
.len
= pcce
->certLength
;
620 derCert
.data
= pcce
->cert
;
622 to
->peerCert
= CERT_NewTempCertificate(dbHandle
, &derCert
, NULL
,
624 if (to
->peerCert
== NULL
)
629 to
->version
= from
->version
;
630 to
->creationTime
= from
->creationTime
;
631 to
->lastAccessTime
= from
->lastAccessTime
;
632 to
->expirationTime
= from
->expirationTime
;
633 to
->cached
= in_server_cache
;
634 to
->addr
= from
->addr
;
636 to
->authAlgorithm
= from
->authAlgorithm
;
637 to
->authKeyBits
= from
->authKeyBits
;
638 to
->keaType
= from
->keaType
;
639 to
->keaKeyBits
= from
->keaKeyBits
;
645 if (version
< SSL_LIBRARY_VERSION_3_0
) {
646 if (to
->u
.ssl2
.masterKey
.data
)
647 PORT_Free(to
->u
.ssl2
.masterKey
.data
);
648 if (to
->u
.ssl2
.cipherArg
.data
)
649 PORT_Free(to
->u
.ssl2
.cipherArg
.data
);
651 SECITEM_FreeItem(&to
->u
.ssl3
.srvName
, PR_FALSE
);
661 ** Perform some mumbo jumbo on the ip-address and the session-id value to
662 ** compute a hash value.
665 SIDindex(cacheDesc
*cache
, const PRIPv6Addr
*addr
, PRUint8
*s
, unsigned nl
)
670 memset(x
, 0, sizeof x
);
675 rv
= (addr
->pr_s6_addr32
[0] ^ addr
->pr_s6_addr32
[1] ^
676 addr
->pr_s6_addr32
[2] ^ addr
->pr_s6_addr32
[3] ^
677 x
[0] ^ x
[1] ^ x
[2] ^ x
[3] ^ x
[4] ^ x
[5] ^ x
[6] ^ x
[7])
678 % cache
->numSIDCacheSets
;
685 ** Look something up in the cache. This will invalidate old entries
686 ** in the process. Caller has locked the cache set!
687 ** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
689 static sidCacheEntry
*
690 FindSID(cacheDesc
*cache
, PRUint32 setNum
, PRUint32 now
,
691 const PRIPv6Addr
*addr
, unsigned char *sessionID
,
692 unsigned sessionIDLength
)
694 PRUint32 ndx
= cache
->sidCacheSets
[setNum
].next
;
697 sidCacheEntry
* set
= cache
->sidCacheData
+
698 (setNum
* SID_CACHE_ENTRIES_PER_SET
);
700 for (i
= SID_CACHE_ENTRIES_PER_SET
; i
> 0; --i
) {
703 ndx
= (ndx
- 1) % SID_CACHE_ENTRIES_PER_SET
;
709 if (now
> sce
->expirationTime
) {
710 /* SessionID has timed out. Invalidate the entry. */
711 SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
713 myPid
, sce
->addr
.pr_s6_addr32
[0],
714 sce
->addr
.pr_s6_addr32
[1], sce
->addr
.pr_s6_addr32
[2],
715 sce
->addr
.pr_s6_addr32
[3], now
,
716 sce
->expirationTime
));
722 ** Next, examine specific session-id/addr data to see if the cache
723 ** entry matches our addr+session-id value
725 if (sessionIDLength
== sce
->sessionIDLength
&&
726 !memcmp(&sce
->addr
, addr
, sizeof(PRIPv6Addr
)) &&
727 !memcmp(sce
->sessionID
, sessionID
, sessionIDLength
)) {
733 PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND
);
737 /************************************************************************/
739 /* This is the primary function for finding entries in the server's sid cache.
740 * Although it is static, this function is called via the global function
741 * pointer ssl_sid_lookup.
743 static sslSessionID
*
744 ServerSessionIDLookup(const PRIPv6Addr
*addr
,
745 unsigned char *sessionID
,
746 unsigned int sessionIDLength
,
747 CERTCertDBHandle
* dbHandle
)
749 sslSessionID
* sid
= 0;
750 sidCacheEntry
* psce
;
751 certCacheEntry
*pcce
= 0;
752 srvNameCacheEntry
*psnce
= 0;
753 cacheDesc
* cache
= &globalCache
;
759 srvNameCacheEntry snce
;
761 set
= SIDindex(cache
, addr
, sessionID
, sessionIDLength
);
762 now
= LockSet(cache
, set
, 0);
766 psce
= FindSID(cache
, set
, now
, addr
, sessionID
, sessionIDLength
);
768 if (psce
->version
>= SSL_LIBRARY_VERSION_3_0
) {
769 if ((cndx
= psce
->u
.ssl3
.certIndex
) != -1) {
771 PRUint32 gotLock
= LockSidCacheLock(cache
->certCacheLock
, now
);
773 pcce
= &cache
->certCacheData
[cndx
];
775 /* See if the cert's session ID matches the sce cache. */
776 if ((pcce
->sessionIDLength
== psce
->sessionIDLength
) &&
777 !PORT_Memcmp(pcce
->sessionID
, psce
->sessionID
,
778 pcce
->sessionIDLength
)) {
781 /* The cert doesen't match the SID cache entry,
782 ** so invalidate the SID cache entry.
788 UnlockSidCacheLock(cache
->certCacheLock
);
790 /* what the ??. Didn't get the cert cache lock.
791 ** Don't invalidate the SID cache entry, but don't find it.
793 PORT_Assert(!("Didn't get cert Cache Lock!"));
798 if (psce
&& ((cndx
= psce
->u
.ssl3
.srvNameIndex
) != -1)) {
799 PRUint32 gotLock
= LockSidCacheLock(cache
->srvNameCacheLock
,
802 psnce
= &cache
->srvNameCacheData
[cndx
];
804 if (!PORT_Memcmp(psnce
->nameHash
, psce
->u
.ssl3
.srvNameHash
,
808 /* The name doesen't match the SID cache entry,
809 ** so invalidate the SID cache entry.
815 UnlockSidCacheLock(cache
->srvNameCacheLock
);
817 /* what the ??. Didn't get the cert cache lock.
818 ** Don't invalidate the SID cache entry, but don't find it.
820 PORT_Assert(!("Didn't get name Cache Lock!"));
828 psce
->lastAccessTime
= now
;
829 sce
= *psce
; /* grab a copy while holding the lock */
832 UnlockSet(cache
, set
);
834 /* sce conains a copy of the cache entry.
835 ** Convert shared memory format to local format
837 sid
= ConvertToSID(&sce
, pcce
? &cce
: 0, psnce
? &snce
: 0, dbHandle
);
843 ** Place a sid into the cache, if it isn't already there.
846 ServerSessionIDCache(sslSessionID
*sid
)
850 PRUint16 version
= sid
->version
;
851 cacheDesc
* cache
= &globalCache
;
853 if ((version
>= SSL_LIBRARY_VERSION_3_0
) &&
854 (sid
->u
.ssl3
.sessionIDLength
== 0)) {
858 if (sid
->cached
== never_cached
|| sid
->cached
== invalid_cache
) {
861 PORT_Assert(sid
->creationTime
!= 0);
862 if (!sid
->creationTime
)
863 sid
->lastAccessTime
= sid
->creationTime
= ssl_Time();
864 if (version
< SSL_LIBRARY_VERSION_3_0
) {
865 /* override caller's expiration time, which uses client timeout
866 * duration, not server timeout duration.
868 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl2Timeout
;
869 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
870 "cipher=%d", myPid
, sid
->cached
,
871 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
872 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
873 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
874 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl2
.sessionID
,
875 SSL2_SESSIONID_BYTES
));
876 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
877 sid
->u
.ssl2
.masterKey
.len
));
878 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
879 sid
->u
.ssl2
.cipherArg
.len
));
882 /* override caller's expiration time, which uses client timeout
883 * duration, not server timeout duration.
885 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl3Timeout
;
886 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
887 "cipherSuite=%d", myPid
, sid
->cached
,
888 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
889 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
890 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
891 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl3
.sessionID
,
892 sid
->u
.ssl3
.sessionIDLength
));
895 ConvertFromSID(&sce
, sid
);
897 if (version
>= SSL_LIBRARY_VERSION_3_0
) {
898 SECItem
*name
= &sid
->u
.ssl3
.srvName
;
899 if (name
->len
&& name
->data
) {
900 now
= CacheSrvName(cache
, name
, &sce
);
902 if (sid
->peerCert
!= NULL
) {
903 now
= CacheCert(cache
, sid
->peerCert
, &sce
);
907 set
= SIDindex(cache
, &sce
.addr
, sce
.sessionID
, sce
.sessionIDLength
);
908 now
= LockSet(cache
, set
, now
);
910 PRUint32 next
= cache
->sidCacheSets
[set
].next
;
911 PRUint32 ndx
= set
* SID_CACHE_ENTRIES_PER_SET
+ next
;
913 /* Write out new cache entry */
914 cache
->sidCacheData
[ndx
] = sce
;
916 cache
->sidCacheSets
[set
].next
=
917 (next
+ 1) % SID_CACHE_ENTRIES_PER_SET
;
919 UnlockSet(cache
, set
);
920 sid
->cached
= in_server_cache
;
926 ** Although this is static, it is called from ssl via global function pointer
927 ** ssl_sid_uncache. This invalidates the referenced cache entry.
930 ServerSessionIDUncache(sslSessionID
*sid
)
932 cacheDesc
* cache
= &globalCache
;
934 unsigned int sessionIDLength
;
943 /* Uncaching a SID should never change the error code.
944 ** So save it here and restore it before exiting.
948 if (sid
->version
< SSL_LIBRARY_VERSION_3_0
) {
949 sessionID
= sid
->u
.ssl2
.sessionID
;
950 sessionIDLength
= SSL2_SESSIONID_BYTES
;
951 SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
952 "cipher=%d", myPid
, sid
->cached
,
953 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
954 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
955 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
956 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
957 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
958 sid
->u
.ssl2
.masterKey
.len
));
959 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
960 sid
->u
.ssl2
.cipherArg
.len
));
962 sessionID
= sid
->u
.ssl3
.sessionID
;
963 sessionIDLength
= sid
->u
.ssl3
.sessionIDLength
;
964 SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
965 "cipherSuite=%d", myPid
, sid
->cached
,
966 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
967 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
968 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
969 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
971 set
= SIDindex(cache
, &sid
->addr
, sessionID
, sessionIDLength
);
972 now
= LockSet(cache
, set
, 0);
974 psce
= FindSID(cache
, set
, now
, &sid
->addr
, sessionID
, sessionIDLength
);
978 UnlockSet(cache
, set
);
980 sid
->cached
= invalid_cache
;
986 #define INCL_DOSPROCESS
993 DosGetInfoBlocks(&ptib
, &ppib
);
994 return ((long)ptib
->tib_ordinal
); /* thread id */
999 CloseCache(cacheDesc
*cache
)
1001 int locks_initialized
= cache
->numSIDCacheLocksInitialized
;
1003 if (cache
->cacheMem
) {
1004 if (cache
->sharedCache
) {
1005 sidCacheLock
*pLock
= cache
->sidCacheLocks
;
1006 for (; locks_initialized
> 0; --locks_initialized
, ++pLock
) {
1007 /* If everInherited is true, this shared cache was (and may
1008 ** still be) in use by multiple processes. We do not wish to
1009 ** destroy the mutexes while they are still in use, but we do
1010 ** want to free mutex resources associated with this process.
1012 sslMutex_Destroy(&pLock
->mutex
,
1013 cache
->sharedCache
->everInherited
);
1016 if (cache
->shared
) {
1017 PR_MemUnmap(cache
->cacheMem
, cache
->cacheMemSize
);
1019 PORT_Free(cache
->cacheMem
);
1021 cache
->cacheMem
= NULL
;
1023 if (cache
->cacheMemMap
) {
1024 PR_CloseFileMap(cache
->cacheMemMap
);
1025 cache
->cacheMemMap
= NULL
;
1027 memset(cache
, 0, sizeof *cache
);
1031 InitCache(cacheDesc
*cache
, int maxCacheEntries
, int maxCertCacheEntries
,
1032 int maxSrvNameCacheEntries
, PRUint32 ssl2_timeout
,
1033 PRUint32 ssl3_timeout
, const char *directory
, PRBool shared
)
1036 sidCacheLock
*pLock
;
1038 PRFileMap
* cacheMemMap
;
1039 char * cfn
= NULL
; /* cache file name */
1040 int locks_initialized
= 0;
1041 int locks_to_initialize
= 0;
1044 if ( (!cache
) || (maxCacheEntries
< 0) || (!directory
) ) {
1045 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1049 if (cache
->cacheMem
) {
1054 /* make sure loser can clean up properly */
1055 cache
->shared
= shared
;
1056 cache
->cacheMem
= cacheMem
= NULL
;
1057 cache
->cacheMemMap
= cacheMemMap
= NULL
;
1058 cache
->sharedCache
= (cacheDesc
*)0;
1060 cache
->numSIDCacheLocksInitialized
= 0;
1061 cache
->nextCertCacheEntry
= 0;
1062 cache
->stopPolling
= PR_FALSE
;
1063 cache
->everInherited
= PR_FALSE
;
1064 cache
->poller
= NULL
;
1065 cache
->mutexTimeout
= 0;
1067 cache
->numSIDCacheEntries
= maxCacheEntries
? maxCacheEntries
1068 : DEF_SID_CACHE_ENTRIES
;
1069 cache
->numSIDCacheSets
=
1070 SID_HOWMANY(cache
->numSIDCacheEntries
, SID_CACHE_ENTRIES_PER_SET
);
1072 cache
->numSIDCacheEntries
=
1073 cache
->numSIDCacheSets
* SID_CACHE_ENTRIES_PER_SET
;
1075 cache
->numSIDCacheLocks
=
1076 PR_MIN(cache
->numSIDCacheSets
, ssl_max_sid_cache_locks
);
1078 cache
->numSIDCacheSetsPerLock
=
1079 SID_HOWMANY(cache
->numSIDCacheSets
, cache
->numSIDCacheLocks
);
1081 cache
->numCertCacheEntries
= (maxCertCacheEntries
> 0) ?
1082 maxCertCacheEntries
: 0;
1083 cache
->numSrvNameCacheEntries
= (maxSrvNameCacheEntries
>= 0) ?
1084 maxSrvNameCacheEntries
: DEF_NAME_CACHE_ENTRIES
;
1086 /* compute size of shared memory, and offsets of all pointers */
1088 cache
->cacheMem
= (char *)ptr
;
1089 ptr
+= SID_ROUNDUP(sizeof(cacheDesc
), SID_ALIGNMENT
);
1091 cache
->sidCacheLocks
= (sidCacheLock
*)ptr
;
1092 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1093 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1094 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1095 ptr
= (ptrdiff_t)(cache
->srvNameCacheLock
+ 1);
1096 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1098 cache
->sidCacheSets
= (sidCacheSet
*)ptr
;
1099 ptr
= (ptrdiff_t)(cache
->sidCacheSets
+ cache
->numSIDCacheSets
);
1100 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1102 cache
->sidCacheData
= (sidCacheEntry
*)ptr
;
1103 ptr
= (ptrdiff_t)(cache
->sidCacheData
+ cache
->numSIDCacheEntries
);
1104 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1106 cache
->certCacheData
= (certCacheEntry
*)ptr
;
1107 cache
->sidCacheSize
=
1108 (char *)cache
->certCacheData
- (char *)cache
->sidCacheData
;
1110 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
) {
1111 /* This is really a poor way to computer this! */
1112 cache
->numCertCacheEntries
= cache
->sidCacheSize
/ sizeof(certCacheEntry
);
1113 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
)
1114 cache
->numCertCacheEntries
= MIN_CERT_CACHE_ENTRIES
;
1116 ptr
= (ptrdiff_t)(cache
->certCacheData
+ cache
->numCertCacheEntries
);
1117 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1119 cache
->keyCacheData
= (SSLWrappedSymWrappingKey
*)ptr
;
1120 cache
->certCacheSize
=
1121 (char *)cache
->keyCacheData
- (char *)cache
->certCacheData
;
1123 cache
->numKeyCacheEntries
= kt_kea_size
* SSL_NUM_WRAP_MECHS
;
1124 ptr
= (ptrdiff_t)(cache
->keyCacheData
+ cache
->numKeyCacheEntries
);
1125 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1127 cache
->keyCacheSize
= (char *)ptr
- (char *)cache
->keyCacheData
;
1129 cache
->ticketKeyNameSuffix
= (PRUint8
*)ptr
;
1130 ptr
= (ptrdiff_t)(cache
->ticketKeyNameSuffix
+
1131 SESS_TICKET_KEY_VAR_NAME_LEN
);
1132 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1134 cache
->ticketEncKey
= (encKeyCacheEntry
*)ptr
;
1135 ptr
= (ptrdiff_t)(cache
->ticketEncKey
+ 1);
1136 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1138 cache
->ticketMacKey
= (encKeyCacheEntry
*)ptr
;
1139 ptr
= (ptrdiff_t)(cache
->ticketMacKey
+ 1);
1140 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1142 cache
->ticketKeysValid
= (PRUint32
*)ptr
;
1143 ptr
= (ptrdiff_t)(cache
->ticketKeysValid
+ 1);
1144 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1146 cache
->srvNameCacheData
= (srvNameCacheEntry
*)ptr
;
1147 cache
->srvNameCacheSize
=
1148 cache
->numSrvNameCacheEntries
* sizeof(srvNameCacheEntry
);
1149 ptr
= (ptrdiff_t)(cache
->srvNameCacheData
+ cache
->numSrvNameCacheEntries
);
1150 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1152 cache
->cacheMemSize
= ptr
;
1155 if (ssl2_timeout
> MAX_SSL2_TIMEOUT
) {
1156 ssl2_timeout
= MAX_SSL2_TIMEOUT
;
1158 if (ssl2_timeout
< MIN_SSL2_TIMEOUT
) {
1159 ssl2_timeout
= MIN_SSL2_TIMEOUT
;
1161 cache
->ssl2Timeout
= ssl2_timeout
;
1163 cache
->ssl2Timeout
= DEF_SSL2_TIMEOUT
;
1167 if (ssl3_timeout
> MAX_SSL3_TIMEOUT
) {
1168 ssl3_timeout
= MAX_SSL3_TIMEOUT
;
1170 if (ssl3_timeout
< MIN_SSL3_TIMEOUT
) {
1171 ssl3_timeout
= MIN_SSL3_TIMEOUT
;
1173 cache
->ssl3Timeout
= ssl3_timeout
;
1175 cache
->ssl3Timeout
= DEF_SSL3_TIMEOUT
;
1179 /* Create file names */
1180 #if defined(XP_UNIX) || defined(XP_BEOS)
1181 /* there's some confusion here about whether PR_OpenAnonFileMap wants
1182 ** a directory name or a file name for its first argument.
1183 cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1185 cfn
= PR_smprintf("%s", directory
);
1186 #elif defined(XP_WIN32)
1187 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1188 GetCurrentThreadId());
1189 #elif defined(XP_OS2)
1190 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1193 #error "Don't know how to create file name for this platform!"
1200 cacheMemMap
= PR_OpenAnonFileMap(cfn
, cache
->cacheMemSize
,
1203 PR_smprintf_free(cfn
);
1208 cacheMem
= PR_MemMap(cacheMemMap
, 0, cache
->cacheMemSize
);
1210 cacheMem
= PORT_Alloc(cache
->cacheMemSize
);
1217 /* Initialize shared memory. This may not be necessary on all platforms */
1218 memset(cacheMem
, 0, cache
->cacheMemSize
);
1220 /* Copy cache descriptor header into shared memory */
1221 memcpy(cacheMem
, cache
, sizeof *cache
);
1223 /* save private copies of these values */
1224 cache
->cacheMemMap
= cacheMemMap
;
1225 cache
->cacheMem
= cacheMem
;
1226 cache
->sharedCache
= (cacheDesc
*)cacheMem
;
1228 /* Fix pointers in our private copy of cache descriptor to point to
1229 ** spaces in shared memory
1231 ptr
= (ptrdiff_t)cache
->cacheMem
;
1232 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1233 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1234 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1235 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1236 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1237 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1238 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1239 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1240 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1241 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1242 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1243 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1244 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1246 /* initialize the locks */
1247 init_time
= ssl_Time();
1248 pLock
= cache
->sidCacheLocks
;
1249 for (locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1250 locks_initialized
< locks_to_initialize
;
1251 ++locks_initialized
, ++pLock
) {
1253 SECStatus err
= sslMutex_Init(&pLock
->mutex
, shared
);
1255 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1258 pLock
->timeStamp
= init_time
;
1261 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1271 SSL_GetMaxServerCacheLocks(void)
1273 return ssl_max_sid_cache_locks
+ 2;
1274 /* The extra two are the cert cache lock and the key cache lock. */
1278 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
1280 /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1281 ** We'd like to test for a maximum value, but not all platforms' header
1282 ** files provide a symbol or function or other means of determining
1283 ** the maximum, other than trial and error.
1286 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1289 ssl_max_sid_cache_locks
= maxLocks
- 2;
1290 /* The extra two are the cert cache lock and the key cache lock. */
1295 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc
*cache
,
1296 PRUint32 ssl2_timeout
,
1297 PRUint32 ssl3_timeout
,
1298 const char * directory
,
1300 int maxCacheEntries
,
1301 int maxCertCacheEntries
,
1302 int maxSrvNameCacheEntries
)
1306 PORT_Assert(sizeof(sidCacheEntry
) == 192);
1307 PORT_Assert(sizeof(certCacheEntry
) == 4096);
1308 PORT_Assert(sizeof(srvNameCacheEntry
) == 1072);
1311 if (rv
!= SECSuccess
) {
1315 myPid
= SSL_GETPID();
1317 directory
= DEFAULT_CACHE_DIRECTORY
;
1319 rv
= InitCache(cache
, maxCacheEntries
, maxCertCacheEntries
,
1320 maxSrvNameCacheEntries
, ssl2_timeout
, ssl3_timeout
,
1327 ssl_sid_lookup
= ServerSessionIDLookup
;
1328 ssl_sid_cache
= ServerSessionIDCache
;
1329 ssl_sid_uncache
= ServerSessionIDUncache
;
1334 SSL_ConfigServerSessionIDCacheInstance( cacheDesc
*cache
,
1335 int maxCacheEntries
,
1336 PRUint32 ssl2_timeout
,
1337 PRUint32 ssl3_timeout
,
1338 const char * directory
, PRBool shared
)
1340 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1350 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
1351 PRUint32 ssl2_timeout
,
1352 PRUint32 ssl3_timeout
,
1353 const char * directory
)
1355 ssl_InitSessionCacheLocks();
1356 return SSL_ConfigServerSessionIDCacheInstance(&globalCache
,
1357 maxCacheEntries
, ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
);
1361 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc
*cache
)
1368 SSL_ShutdownServerSessionIDCache(void)
1370 #if defined(XP_UNIX) || defined(XP_BEOS)
1371 /* Stop the thread that polls cache for expired locks on Unix */
1372 StopLockPoller(&globalCache
);
1374 SSL3_ShutdownServerCache();
1375 return SSL_ShutdownServerSessionIDCacheInstance(&globalCache
);
1378 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1379 * if the cache will be shared by multiple processes.
1382 ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout
,
1383 PRUint32 ssl3_timeout
,
1384 const char * directory
,
1385 int maxCacheEntries
,
1386 int maxCertCacheEntries
,
1387 int maxSrvNameCacheEntries
)
1391 cacheDesc
* cache
= &globalCache
;
1395 SECStatus putEnvFailed
;
1396 inheritance inherit
;
1397 char fmString
[PR_FILEMAP_STRING_BUFSIZE
];
1399 isMultiProcess
= PR_TRUE
;
1400 result
= ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1401 ssl2_timeout
, ssl3_timeout
, directory
, PR_TRUE
,
1402 maxCacheEntries
, maxCacheEntries
, maxSrvNameCacheEntries
);
1403 if (result
!= SECSuccess
)
1406 prStatus
= PR_ExportFileMapAsString(cache
->cacheMemMap
,
1407 sizeof fmString
, fmString
);
1408 if ((prStatus
!= PR_SUCCESS
) || !(fmStrLen
= strlen(fmString
))) {
1413 inherit
.cacheMemSize
= cache
->cacheMemSize
;
1414 inherit
.fmStrLen
= fmStrLen
;
1416 inhValue
= BTOA_DataToAscii((unsigned char *)&inherit
, sizeof inherit
);
1417 if (!inhValue
|| !strlen(inhValue
)) {
1421 envValue
= PR_smprintf("%s,%s", inhValue
, fmString
);
1422 if (!envValue
|| !strlen(envValue
)) {
1426 PORT_Free(inhValue
);
1428 putEnvFailed
= (SECStatus
)NSS_PutEnv(envVarName
, envValue
);
1429 PR_smprintf_free(envValue
);
1432 result
= SECFailure
;
1435 #if defined(XP_UNIX) || defined(XP_BEOS)
1436 /* Launch thread to poll cache for expired locks on Unix */
1437 LaunchLockPoller(cache
);
1442 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1443 * if the cache will be shared by multiple processes.
1446 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
1447 PRUint32 ssl2_timeout
,
1448 PRUint32 ssl3_timeout
,
1449 const char * directory
)
1451 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
,
1459 SSL_ConfigServerSessionIDCacheWithOpt(
1460 PRUint32 ssl2_timeout
,
1461 PRUint32 ssl3_timeout
,
1462 const char * directory
,
1463 int maxCacheEntries
,
1464 int maxCertCacheEntries
,
1465 int maxSrvNameCacheEntries
,
1466 PRBool enableMPCache
)
1468 if (!enableMPCache
) {
1469 ssl_InitSessionCacheLocks();
1470 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache
,
1471 ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
,
1472 maxCacheEntries
, maxCertCacheEntries
, maxSrvNameCacheEntries
);
1474 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
, ssl3_timeout
,
1475 directory
, maxCacheEntries
, maxCertCacheEntries
,
1476 maxSrvNameCacheEntries
);
1481 SSL_InheritMPServerSIDCacheInstance(cacheDesc
*cache
, const char * envString
)
1483 unsigned char * decoString
= NULL
;
1484 char * fmString
= NULL
;
1485 char * myEnvString
= NULL
;
1486 unsigned int decoLen
;
1488 inheritance inherit
;
1491 sidCacheLock
* newLocks
;
1492 int locks_initialized
= 0;
1493 int locks_to_initialize
= 0;
1495 SECStatus status
= ssl_Init();
1497 if (status
!= SECSuccess
) {
1501 myPid
= SSL_GETPID();
1503 /* If this child was created by fork(), and not by exec() on unix,
1504 ** then isMultiProcess will already be set.
1505 ** If not, we'll set it below.
1507 if (isMultiProcess
) {
1508 if (cache
&& cache
->sharedCache
) {
1509 cache
->sharedCache
->everInherited
= PR_TRUE
;
1511 return SECSuccess
; /* already done. */
1514 ssl_InitSessionCacheLocks();
1516 ssl_sid_lookup
= ServerSessionIDLookup
;
1517 ssl_sid_cache
= ServerSessionIDCache
;
1518 ssl_sid_uncache
= ServerSessionIDUncache
;
1521 envString
= getenv(envVarName
);
1527 myEnvString
= PORT_Strdup(envString
);
1530 fmString
= strchr(myEnvString
, ',');
1535 decoString
= ATOB_AsciiToData(myEnvString
, &decoLen
);
1540 if (decoLen
!= sizeof inherit
) {
1545 PORT_Memcpy(&inherit
, decoString
, sizeof inherit
);
1547 if (strlen(fmString
) != inherit
.fmStrLen
) {
1551 memset(cache
, 0, sizeof *cache
);
1552 cache
->cacheMemSize
= inherit
.cacheMemSize
;
1555 cache
->cacheMemMap
= PR_ImportFileMapFromString(fmString
);
1556 if(! cache
->cacheMemMap
) {
1559 cache
->cacheMem
= PR_MemMap(cache
->cacheMemMap
, 0, cache
->cacheMemSize
);
1560 if (! cache
->cacheMem
) {
1563 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1565 if (cache
->sharedCache
->cacheMemSize
!= cache
->cacheMemSize
) {
1570 /* We're now going to overwrite the local cache instance with the
1571 ** shared copy of the cache struct, then update several values in
1572 ** the local cache using the values for cache->cacheMemMap and
1573 ** cache->cacheMem computed just above. So, we copy cache into
1574 ** the automatic variable "my", to preserve the variables while
1575 ** cache is overwritten.
1577 my
= *cache
; /* save values computed above. */
1578 memcpy(cache
, cache
->sharedCache
, sizeof *cache
); /* overwrite */
1580 /* Fix pointers in our private copy of cache descriptor to point to
1581 ** spaces in shared memory, whose address is now in "my".
1583 ptr
= (ptrdiff_t)my
.cacheMem
;
1584 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1585 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1586 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1587 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1588 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1589 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1590 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1591 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1592 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1593 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1594 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1595 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1596 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1598 cache
->cacheMemMap
= my
.cacheMemMap
;
1599 cache
->cacheMem
= my
.cacheMem
;
1600 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1603 /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1604 ** When NT fibers are used in a multi-process server, a second level of
1605 ** locking is needed to prevent a deadlock, in case a fiber acquires the
1606 ** cross-process mutex, yields, and another fiber is later scheduled on
1607 ** the same native thread and tries to acquire the cross-process mutex.
1608 ** We do this by using a PRLock in the sslMutex. However, it is stored in
1609 ** shared memory as part of sidCacheLocks, and we don't want to overwrite
1610 ** the PRLock of the parent process. So we need to make new, private
1611 ** copies of sidCacheLocks before modifying the sslMutex with our own
1615 /* note from jpierre : this should be free'd in child processes when
1616 ** a function is added to delete the SSL session cache in the future.
1618 locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1619 newLocks
= PORT_NewArray(sidCacheLock
, locks_to_initialize
);
1622 /* copy the old locks */
1623 memcpy(newLocks
, cache
->sidCacheLocks
,
1624 locks_to_initialize
* sizeof(sidCacheLock
));
1625 cache
->sidCacheLocks
= newLocks
;
1627 for (; locks_initialized
< locks_to_initialize
; ++locks_initialized
) {
1628 /* now, make a local PRLock in this sslMutex for this child process */
1630 err
= sslMutex_2LevelInit(&newLocks
[locks_initialized
].mutex
);
1631 if (err
!= SECSuccess
) {
1632 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1636 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1638 /* also fix the key and cert cache which use the last 2 lock entries */
1639 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1640 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1641 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1644 PORT_Free(myEnvString
);
1645 PORT_Free(decoString
);
1647 /* mark that we have inherited this. */
1648 cache
->sharedCache
->everInherited
= PR_TRUE
;
1649 isMultiProcess
= PR_TRUE
;
1654 PORT_Free(myEnvString
);
1656 PORT_Free(decoString
);
1662 SSL_InheritMPServerSIDCache(const char * envString
)
1664 return SSL_InheritMPServerSIDCacheInstance(&globalCache
, envString
);
1667 #if defined(XP_UNIX) || defined(XP_BEOS)
1669 #define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
1672 LockPoller(void * arg
)
1674 cacheDesc
* cache
= (cacheDesc
*)arg
;
1675 cacheDesc
* sharedCache
= cache
->sharedCache
;
1676 sidCacheLock
* pLock
;
1677 PRIntervalTime timeout
;
1680 int locks_polled
= 0;
1681 int locks_to_poll
= cache
->numSIDCacheLocks
+ 2;
1682 PRUint32 expiration
= cache
->mutexTimeout
;
1684 timeout
= PR_SecondsToInterval(expiration
);
1685 while(!sharedCache
->stopPolling
) {
1687 if (sharedCache
->stopPolling
)
1691 then
= now
- expiration
;
1692 for (pLock
= cache
->sidCacheLocks
, locks_polled
= 0;
1693 locks_to_poll
> locks_polled
&& !sharedCache
->stopPolling
;
1694 ++locks_polled
, ++pLock
) {
1697 if (pLock
->timeStamp
< then
&&
1698 pLock
->timeStamp
!= 0 &&
1699 (pid
= pLock
->pid
) != 0) {
1701 /* maybe we should try the lock? */
1702 int result
= kill(pid
, 0);
1703 if (result
< 0 && errno
== ESRCH
) {
1705 /* No process exists by that pid any more.
1706 ** Treat this mutex as abandoned.
1708 pLock
->timeStamp
= now
;
1710 rv
= sslMutex_Unlock(&pLock
->mutex
);
1711 if (rv
!= SECSuccess
) {
1716 } /* end of loop over locks */
1717 } /* end of entire polling loop */
1720 /* Launch thread to poll cache for expired locks */
1722 LaunchLockPoller(cacheDesc
*cache
)
1724 const char * timeoutString
;
1725 PRThread
* pollerThread
;
1727 cache
->mutexTimeout
= SID_LOCK_EXPIRATION_TIMEOUT
;
1728 timeoutString
= getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1729 if (timeoutString
) {
1730 long newTime
= strtol(timeoutString
, 0, 0);
1732 return SECSuccess
; /* application doesn't want poller thread */
1734 cache
->mutexTimeout
= (PRUint32
)newTime
;
1735 /* if error (newTime < 0) ignore it and use default */
1739 PR_CreateThread(PR_USER_THREAD
, LockPoller
, cache
, PR_PRIORITY_NORMAL
,
1740 PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
1741 if (!pollerThread
) {
1744 cache
->poller
= pollerThread
;
1748 /* Stop the thread that polls cache for expired locks */
1750 StopLockPoller(cacheDesc
*cache
)
1752 if (!cache
->poller
) {
1755 cache
->sharedCache
->stopPolling
= PR_TRUE
;
1756 if (PR_Interrupt(cache
->poller
) != PR_SUCCESS
) {
1759 if (PR_JoinThread(cache
->poller
) != PR_SUCCESS
) {
1762 cache
->poller
= NULL
;
1767 /************************************************************************
1768 * Code dealing with shared wrapped symmetric wrapping keys below *
1769 ************************************************************************/
1771 /* If now is zero, it implies that the lock is not held, and must be
1775 getSvrWrappingKey(PRInt32 symWrapMechIndex
,
1776 SSL3KEAType exchKeyType
,
1777 SSLWrappedSymWrappingKey
*wswk
,
1781 PRUint32 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
1782 SSLWrappedSymWrappingKey
* pwswk
= cache
->keyCacheData
+ ndx
;
1784 PRBool rv
= PR_FALSE
;
1786 if (!cache
->cacheMem
) { /* cache is uninitialized */
1787 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
1791 lockTime
= now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
1796 if (pwswk
->exchKeyType
== exchKeyType
&&
1797 pwswk
->symWrapMechIndex
== symWrapMechIndex
&&
1798 pwswk
->wrappedSymKeyLen
!= 0) {
1803 UnlockSidCacheLock(cache
->keyCacheLock
);
1809 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
1810 SSL3KEAType exchKeyType
,
1811 SSLWrappedSymWrappingKey
*wswk
)
1815 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
1816 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
1817 if ((unsigned)exchKeyType
< kt_kea_size
&&
1818 (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
) {
1819 rv
= getSvrWrappingKey(symWrapMechIndex
, exchKeyType
, wswk
,
1828 /* Wrap and cache a session ticket key. */
1830 WrapTicketKey(SECKEYPublicKey
*svrPubKey
, PK11SymKey
*symKey
,
1831 const char *keyName
, encKeyCacheEntry
* cacheEntry
)
1833 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1835 wrappedKey
.len
= SECKEY_PublicKeyStrength(svrPubKey
);
1836 PORT_Assert(wrappedKey
.len
<= sizeof(cacheEntry
->bytes
));
1837 if (wrappedKey
.len
> sizeof(cacheEntry
->bytes
))
1839 wrappedKey
.data
= cacheEntry
->bytes
;
1841 if (PK11_PubWrapSymKey(CKM_RSA_PKCS
, svrPubKey
, symKey
, &wrappedKey
)
1843 SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
1844 SSL_GETPID(), "unknown", keyName
));
1847 cacheEntry
->length
= wrappedKey
.len
;
1852 GenerateTicketKeys(void *pwArg
, unsigned char *keyName
, PK11SymKey
**aesKey
,
1853 PK11SymKey
**macKey
)
1856 CK_MECHANISM_TYPE mechanismArray
[2];
1857 PK11SymKey
*aesKeyTmp
= NULL
;
1858 PK11SymKey
*macKeyTmp
= NULL
;
1859 cacheDesc
*cache
= &globalCache
;
1860 PRUint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
1861 PRUint8
*ticketKeyNameSuffix
;
1863 if (!cache
->cacheMem
) {
1864 /* cache is not initalized. Use stack buffer */
1865 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
1867 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
1870 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
1871 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
) {
1872 SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
1873 SSL_GETPID(), "unknown"));
1877 mechanismArray
[0] = CKM_AES_CBC
;
1878 mechanismArray
[1] = CKM_SHA256_HMAC
;
1880 slot
= PK11_GetBestSlotMultiple(mechanismArray
, 2, pwArg
);
1882 aesKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[0], NULL
,
1883 AES_256_KEY_LENGTH
, pwArg
);
1884 macKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[1], NULL
,
1885 SHA256_LENGTH
, pwArg
);
1886 PK11_FreeSlot(slot
);
1889 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1890 SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
1891 SSL_GETPID(), "unknown"));
1894 PORT_Memcpy(keyName
, ticketKeyNameSuffix
, SESS_TICKET_KEY_VAR_NAME_LEN
);
1895 *aesKey
= aesKeyTmp
;
1896 *macKey
= macKeyTmp
;
1901 PK11_FreeSymKey(aesKeyTmp
);
1903 PK11_FreeSymKey(macKeyTmp
);
1908 GenerateAndWrapTicketKeys(SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1909 unsigned char *keyName
, PK11SymKey
**aesKey
,
1910 PK11SymKey
**macKey
)
1912 PK11SymKey
*aesKeyTmp
= NULL
;
1913 PK11SymKey
*macKeyTmp
= NULL
;
1914 cacheDesc
*cache
= &globalCache
;
1916 if (!GenerateTicketKeys(pwArg
, keyName
, &aesKeyTmp
, &macKeyTmp
)) {
1920 if (cache
->cacheMem
) {
1921 /* Export the keys to the shared cache in wrapped form. */
1922 if (!WrapTicketKey(svrPubKey
, aesKeyTmp
, "enc key", cache
->ticketEncKey
))
1924 if (!WrapTicketKey(svrPubKey
, macKeyTmp
, "mac key", cache
->ticketMacKey
))
1927 *aesKey
= aesKeyTmp
;
1928 *macKey
= macKeyTmp
;
1933 PK11_FreeSymKey(aesKeyTmp
);
1935 PK11_FreeSymKey(macKeyTmp
);
1940 UnwrapCachedTicketKeys(SECKEYPrivateKey
*svrPrivKey
, unsigned char *keyName
,
1941 PK11SymKey
**aesKey
, PK11SymKey
**macKey
)
1943 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1944 PK11SymKey
*aesKeyTmp
= NULL
;
1945 PK11SymKey
*macKeyTmp
= NULL
;
1946 cacheDesc
*cache
= &globalCache
;
1948 wrappedKey
.data
= cache
->ticketEncKey
->bytes
;
1949 wrappedKey
.len
= cache
->ticketEncKey
->length
;
1950 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketEncKey
->bytes
));
1951 aesKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1952 CKM_AES_CBC
, CKA_DECRYPT
, 0);
1954 wrappedKey
.data
= cache
->ticketMacKey
->bytes
;
1955 wrappedKey
.len
= cache
->ticketMacKey
->length
;
1956 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketMacKey
->bytes
));
1957 macKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1958 CKM_SHA256_HMAC
, CKA_SIGN
, 0);
1960 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1961 SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
1962 SSL_GETPID(), "unknown"));
1965 SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
1966 SSL_GETPID(), "unknown"));
1968 PORT_Memcpy(keyName
, cache
->ticketKeyNameSuffix
,
1969 SESS_TICKET_KEY_VAR_NAME_LEN
);
1970 *aesKey
= aesKeyTmp
;
1971 *macKey
= macKeyTmp
;
1976 PK11_FreeSymKey(aesKeyTmp
);
1978 PK11_FreeSymKey(macKeyTmp
);
1983 ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey
*svrPrivKey
,
1984 SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1985 unsigned char *keyName
, PK11SymKey
**aesKey
,
1986 PK11SymKey
**macKey
)
1989 PRBool rv
= PR_FALSE
;
1990 PRBool keysGenerated
= PR_FALSE
;
1991 cacheDesc
*cache
= &globalCache
;
1993 if (!cache
->cacheMem
) {
1994 /* cache is uninitialized. Generate keys and return them
1995 * without caching. */
1996 return GenerateTicketKeys(pwArg
, keyName
, aesKey
, macKey
);
1999 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2003 if (!*(cache
->ticketKeysValid
)) {
2004 /* Keys do not exist, create them. */
2005 if (!GenerateAndWrapTicketKeys(svrPubKey
, pwArg
, keyName
,
2008 keysGenerated
= PR_TRUE
;
2009 *(cache
->ticketKeysValid
) = 1;
2015 UnlockSidCacheLock(cache
->keyCacheLock
);
2016 if (rv
&& !keysGenerated
)
2017 rv
= UnwrapCachedTicketKeys(svrPrivKey
, keyName
, aesKey
, macKey
);
2022 ssl_GetSessionTicketKeys(unsigned char *keyName
, unsigned char *encKey
,
2023 unsigned char *macKey
)
2025 PRBool rv
= PR_FALSE
;
2027 cacheDesc
*cache
= &globalCache
;
2028 PRUint8 ticketMacKey
[SHA256_LENGTH
], ticketEncKey
[AES_256_KEY_LENGTH
];
2029 PRUint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
2030 PRUint8
*ticketMacKeyPtr
, *ticketEncKeyPtr
, *ticketKeyNameSuffix
;
2031 PRBool cacheIsEnabled
= PR_TRUE
;
2033 if (!cache
->cacheMem
) { /* cache is uninitialized */
2034 cacheIsEnabled
= PR_FALSE
;
2035 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
2036 ticketEncKeyPtr
= ticketEncKey
;
2037 ticketMacKeyPtr
= ticketMacKey
;
2039 /* these values have constant memory locations in the cache.
2040 * Ok to reference them without holding the lock. */
2041 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
2042 ticketEncKeyPtr
= cache
->ticketEncKey
->bytes
;
2043 ticketMacKeyPtr
= cache
->ticketMacKey
->bytes
;
2046 if (cacheIsEnabled
) {
2047 /* Grab lock if initialized. */
2048 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2052 /* Going to regenerate keys on every call if cache was not
2054 if (!cacheIsEnabled
|| !*(cache
->ticketKeysValid
)) {
2055 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
2056 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
)
2058 if (PK11_GenerateRandom(ticketEncKeyPtr
,
2059 AES_256_KEY_LENGTH
) != SECSuccess
)
2061 if (PK11_GenerateRandom(ticketMacKeyPtr
,
2062 SHA256_LENGTH
) != SECSuccess
)
2064 if (cacheIsEnabled
) {
2065 *(cache
->ticketKeysValid
) = 1;
2072 if (cacheIsEnabled
) {
2073 UnlockSidCacheLock(cache
->keyCacheLock
);
2076 PORT_Memcpy(keyName
, ticketKeyNameSuffix
,
2077 SESS_TICKET_KEY_VAR_NAME_LEN
);
2078 PORT_Memcpy(encKey
, ticketEncKeyPtr
, AES_256_KEY_LENGTH
);
2079 PORT_Memcpy(macKey
, ticketMacKeyPtr
, SHA256_LENGTH
);
2084 /* The caller passes in the new value it wants
2085 * to set. This code tests the wrapped sym key entry in the shared memory.
2086 * If it is uninitialized, this function writes the caller's value into
2087 * the disk entry, and returns false.
2088 * Otherwise, it overwrites the caller's wswk with the value obtained from
2089 * the disk, and returns PR_TRUE.
2090 * This is all done while holding the locks/mutexes necessary to make
2091 * the operation atomic.
2094 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2096 cacheDesc
* cache
= &globalCache
;
2097 PRBool rv
= PR_FALSE
;
2098 SSL3KEAType exchKeyType
= wswk
->exchKeyType
;
2099 /* type of keys used to wrap SymWrapKey*/
2100 PRInt32 symWrapMechIndex
= wswk
->symWrapMechIndex
;
2103 SSLWrappedSymWrappingKey myWswk
;
2105 if (!cache
->cacheMem
) { /* cache is uninitialized */
2106 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
2110 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
2111 if ((unsigned)exchKeyType
>= kt_kea_size
)
2114 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
2115 if ((unsigned)symWrapMechIndex
>= SSL_NUM_WRAP_MECHS
)
2118 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
2119 PORT_Memset(&myWswk
, 0, sizeof myWswk
); /* eliminate UMRs. */
2121 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2123 rv
= getSvrWrappingKey(wswk
->symWrapMechIndex
, wswk
->exchKeyType
,
2124 &myWswk
, cache
, now
);
2126 /* we found it on disk, copy it out to the caller. */
2127 PORT_Memcpy(wswk
, &myWswk
, sizeof *wswk
);
2129 /* Wasn't on disk, and we're still holding the lock, so write it. */
2130 cache
->keyCacheData
[ndx
] = *wswk
;
2132 UnlockSidCacheLock(cache
->keyCacheLock
);
2137 #else /* MAC version or other platform */
2139 #include "seccomon.h"
2142 #include "sslimpl.h"
2145 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
2146 PRUint32 ssl2_timeout
,
2147 PRUint32 ssl3_timeout
,
2148 const char * directory
)
2150 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
2155 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
2156 PRUint32 ssl2_timeout
,
2157 PRUint32 ssl3_timeout
,
2158 const char * directory
)
2160 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
2165 SSL_InheritMPServerSIDCache(const char * envString
)
2167 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
2172 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
2173 SSL3KEAType exchKeyType
,
2174 SSLWrappedSymWrappingKey
*wswk
)
2176 PRBool rv
= PR_FALSE
;
2177 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
2181 /* This is a kind of test-and-set. The caller passes in the new value it wants
2182 * to set. This code tests the wrapped sym key entry in the shared memory.
2183 * If it is uninitialized, this function writes the caller's value into
2184 * the disk entry, and returns false.
2185 * Otherwise, it overwrites the caller's wswk with the value obtained from
2186 * the disk, and returns PR_TRUE.
2187 * This is all done while holding the locks/mutexes necessary to make
2188 * the operation atomic.
2191 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2193 PRBool rv
= PR_FALSE
;
2194 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
2199 SSL_GetMaxServerCacheLocks(void)
2201 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
2206 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
2208 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
2212 #endif /* XP_UNIX || XP_WIN32 */