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().
525 ** Caller must hold cache lock when calling this.
527 static sslSessionID
*
528 ConvertToSID(sidCacheEntry
* from
,
529 certCacheEntry
* pcce
,
530 srvNameCacheEntry
*psnce
,
531 CERTCertDBHandle
* dbHandle
)
534 PRUint16 version
= from
->version
;
536 to
= PORT_ZNew(sslSessionID
);
541 if (version
< SSL_LIBRARY_VERSION_3_0
) {
542 /* This is an SSL v2 session */
543 to
->u
.ssl2
.masterKey
.data
=
544 (unsigned char*) PORT_Alloc(from
->u
.ssl2
.masterKeyLen
);
545 if (!to
->u
.ssl2
.masterKey
.data
) {
548 if (from
->u
.ssl2
.cipherArgLen
) {
549 to
->u
.ssl2
.cipherArg
.data
=
550 (unsigned char*)PORT_Alloc(from
->u
.ssl2
.cipherArgLen
);
551 if (!to
->u
.ssl2
.cipherArg
.data
) {
554 PORT_Memcpy(to
->u
.ssl2
.cipherArg
.data
, from
->u
.ssl2
.cipherArg
,
555 from
->u
.ssl2
.cipherArgLen
);
558 to
->u
.ssl2
.cipherType
= from
->u
.ssl2
.cipherType
;
559 to
->u
.ssl2
.masterKey
.len
= from
->u
.ssl2
.masterKeyLen
;
560 to
->u
.ssl2
.cipherArg
.len
= from
->u
.ssl2
.cipherArgLen
;
561 to
->u
.ssl2
.keyBits
= from
->u
.ssl2
.keyBits
;
562 to
->u
.ssl2
.secretKeyBits
= from
->u
.ssl2
.secretKeyBits
;
563 /* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
564 PORT_Memcpy(to
->u
.ssl2
.sessionID
, from
->sessionID
, SSL2_SESSIONID_BYTES
);
565 PORT_Memcpy(to
->u
.ssl2
.masterKey
.data
, from
->u
.ssl2
.masterKey
,
566 from
->u
.ssl2
.masterKeyLen
);
568 SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
569 "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
570 myPid
, to
->u
.ssl2
.masterKey
.len
,
571 to
->u
.ssl2
.cipherArg
.len
, to
->creationTime
,
572 to
->addr
.pr_s6_addr32
[0], to
->addr
.pr_s6_addr32
[1],
573 to
->addr
.pr_s6_addr32
[2], to
->addr
.pr_s6_addr32
[3],
574 to
->u
.ssl2
.cipherType
));
576 /* This is an SSL v3 session */
578 to
->u
.ssl3
.sessionIDLength
= from
->sessionIDLength
;
579 to
->u
.ssl3
.cipherSuite
= from
->u
.ssl3
.cipherSuite
;
580 to
->u
.ssl3
.compression
= (SSLCompressionMethod
)from
->u
.ssl3
.compression
;
581 to
->u
.ssl3
.keys
= from
->u
.ssl3
.keys
;
582 to
->u
.ssl3
.masterWrapMech
= from
->u
.ssl3
.masterWrapMech
;
583 to
->u
.ssl3
.exchKeyType
= from
->u
.ssl3
.exchKeyType
;
584 if (from
->u
.ssl3
.srvNameIndex
!= -1 && psnce
) {
587 name
.type
= psnce
->type
;
588 name
.len
= psnce
->nameLen
;
589 name
.data
= psnce
->name
;
590 rv
= SECITEM_CopyItem(NULL
, &to
->u
.ssl3
.srvName
, &name
);
591 if (rv
!= SECSuccess
) {
596 PORT_Memcpy(to
->u
.ssl3
.sessionID
, from
->sessionID
, from
->sessionIDLength
);
598 /* the portions of the SID that are only restored on the client
599 * are set to invalid values on the server.
601 to
->u
.ssl3
.clientWriteKey
= NULL
;
602 to
->u
.ssl3
.serverWriteKey
= NULL
;
604 to
->urlSvrName
= NULL
;
606 to
->u
.ssl3
.masterModuleID
= (SECMODModuleID
)-1; /* invalid value */
607 to
->u
.ssl3
.masterSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
608 to
->u
.ssl3
.masterWrapIndex
= 0;
609 to
->u
.ssl3
.masterWrapSeries
= 0;
610 to
->u
.ssl3
.masterValid
= PR_FALSE
;
612 to
->u
.ssl3
.clAuthModuleID
= (SECMODModuleID
)-1; /* invalid value */
613 to
->u
.ssl3
.clAuthSlotID
= (CK_SLOT_ID
)-1; /* invalid value */
614 to
->u
.ssl3
.clAuthSeries
= 0;
615 to
->u
.ssl3
.clAuthValid
= PR_FALSE
;
617 if (from
->u
.ssl3
.certIndex
!= -1 && pcce
) {
620 derCert
.len
= pcce
->certLength
;
621 derCert
.data
= pcce
->cert
;
623 to
->peerCert
= CERT_NewTempCertificate(dbHandle
, &derCert
, NULL
,
625 if (to
->peerCert
== NULL
)
630 to
->version
= from
->version
;
631 to
->creationTime
= from
->creationTime
;
632 to
->lastAccessTime
= from
->lastAccessTime
;
633 to
->expirationTime
= from
->expirationTime
;
634 to
->cached
= in_server_cache
;
635 to
->addr
= from
->addr
;
637 to
->authAlgorithm
= from
->authAlgorithm
;
638 to
->authKeyBits
= from
->authKeyBits
;
639 to
->keaType
= from
->keaType
;
640 to
->keaKeyBits
= from
->keaKeyBits
;
646 if (version
< SSL_LIBRARY_VERSION_3_0
) {
647 if (to
->u
.ssl2
.masterKey
.data
)
648 PORT_Free(to
->u
.ssl2
.masterKey
.data
);
649 if (to
->u
.ssl2
.cipherArg
.data
)
650 PORT_Free(to
->u
.ssl2
.cipherArg
.data
);
652 SECITEM_FreeItem(&to
->u
.ssl3
.srvName
, PR_FALSE
);
662 ** Perform some mumbo jumbo on the ip-address and the session-id value to
663 ** compute a hash value.
666 SIDindex(cacheDesc
*cache
, const PRIPv6Addr
*addr
, PRUint8
*s
, unsigned nl
)
671 memset(x
, 0, sizeof x
);
676 rv
= (addr
->pr_s6_addr32
[0] ^ addr
->pr_s6_addr32
[1] ^
677 addr
->pr_s6_addr32
[2] ^ addr
->pr_s6_addr32
[3] ^
678 x
[0] ^ x
[1] ^ x
[2] ^ x
[3] ^ x
[4] ^ x
[5] ^ x
[6] ^ x
[7])
679 % cache
->numSIDCacheSets
;
686 ** Look something up in the cache. This will invalidate old entries
687 ** in the process. Caller has locked the cache set!
688 ** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
690 static sidCacheEntry
*
691 FindSID(cacheDesc
*cache
, PRUint32 setNum
, PRUint32 now
,
692 const PRIPv6Addr
*addr
, unsigned char *sessionID
,
693 unsigned sessionIDLength
)
695 PRUint32 ndx
= cache
->sidCacheSets
[setNum
].next
;
698 sidCacheEntry
* set
= cache
->sidCacheData
+
699 (setNum
* SID_CACHE_ENTRIES_PER_SET
);
701 for (i
= SID_CACHE_ENTRIES_PER_SET
; i
> 0; --i
) {
704 ndx
= (ndx
- 1) % SID_CACHE_ENTRIES_PER_SET
;
710 if (now
> sce
->expirationTime
) {
711 /* SessionID has timed out. Invalidate the entry. */
712 SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
714 myPid
, sce
->addr
.pr_s6_addr32
[0],
715 sce
->addr
.pr_s6_addr32
[1], sce
->addr
.pr_s6_addr32
[2],
716 sce
->addr
.pr_s6_addr32
[3], now
,
717 sce
->expirationTime
));
723 ** Next, examine specific session-id/addr data to see if the cache
724 ** entry matches our addr+session-id value
726 if (sessionIDLength
== sce
->sessionIDLength
&&
727 !memcmp(&sce
->addr
, addr
, sizeof(PRIPv6Addr
)) &&
728 !memcmp(sce
->sessionID
, sessionID
, sessionIDLength
)) {
734 PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND
);
738 /************************************************************************/
740 /* This is the primary function for finding entries in the server's sid cache.
741 * Although it is static, this function is called via the global function
742 * pointer ssl_sid_lookup.
744 static sslSessionID
*
745 ServerSessionIDLookup(const PRIPv6Addr
*addr
,
746 unsigned char *sessionID
,
747 unsigned int sessionIDLength
,
748 CERTCertDBHandle
* dbHandle
)
750 sslSessionID
* sid
= 0;
751 sidCacheEntry
* psce
;
752 certCacheEntry
*pcce
= 0;
753 srvNameCacheEntry
*psnce
= 0;
754 cacheDesc
* cache
= &globalCache
;
760 srvNameCacheEntry snce
;
762 set
= SIDindex(cache
, addr
, sessionID
, sessionIDLength
);
763 now
= LockSet(cache
, set
, 0);
767 psce
= FindSID(cache
, set
, now
, addr
, sessionID
, sessionIDLength
);
769 if (psce
->version
>= SSL_LIBRARY_VERSION_3_0
) {
770 if ((cndx
= psce
->u
.ssl3
.certIndex
) != -1) {
772 PRUint32 gotLock
= LockSidCacheLock(cache
->certCacheLock
, now
);
774 pcce
= &cache
->certCacheData
[cndx
];
776 /* See if the cert's session ID matches the sce cache. */
777 if ((pcce
->sessionIDLength
== psce
->sessionIDLength
) &&
778 !PORT_Memcmp(pcce
->sessionID
, psce
->sessionID
,
779 pcce
->sessionIDLength
)) {
782 /* The cert doesen't match the SID cache entry,
783 ** so invalidate the SID cache entry.
789 UnlockSidCacheLock(cache
->certCacheLock
);
791 /* what the ??. Didn't get the cert cache lock.
792 ** Don't invalidate the SID cache entry, but don't find it.
794 PORT_Assert(!("Didn't get cert Cache Lock!"));
799 if (psce
&& ((cndx
= psce
->u
.ssl3
.srvNameIndex
) != -1)) {
800 PRUint32 gotLock
= LockSidCacheLock(cache
->srvNameCacheLock
,
803 psnce
= &cache
->srvNameCacheData
[cndx
];
805 if (!PORT_Memcmp(psnce
->nameHash
, psce
->u
.ssl3
.srvNameHash
,
809 /* The name doesen't match the SID cache entry,
810 ** so invalidate the SID cache entry.
816 UnlockSidCacheLock(cache
->srvNameCacheLock
);
818 /* what the ??. Didn't get the cert cache lock.
819 ** Don't invalidate the SID cache entry, but don't find it.
821 PORT_Assert(!("Didn't get name Cache Lock!"));
829 psce
->lastAccessTime
= now
;
830 sce
= *psce
; /* grab a copy while holding the lock */
833 UnlockSet(cache
, set
);
835 /* sce conains a copy of the cache entry.
836 ** Convert shared memory format to local format
838 sid
= ConvertToSID(&sce
, pcce
? &cce
: 0, psnce
? &snce
: 0, dbHandle
);
844 ** Place a sid into the cache, if it isn't already there.
847 ServerSessionIDCache(sslSessionID
*sid
)
851 PRUint16 version
= sid
->version
;
852 cacheDesc
* cache
= &globalCache
;
854 if ((version
>= SSL_LIBRARY_VERSION_3_0
) &&
855 (sid
->u
.ssl3
.sessionIDLength
== 0)) {
859 if (sid
->cached
== never_cached
|| sid
->cached
== invalid_cache
) {
862 PORT_Assert(sid
->creationTime
!= 0);
863 if (!sid
->creationTime
)
864 sid
->lastAccessTime
= sid
->creationTime
= ssl_Time();
865 if (version
< SSL_LIBRARY_VERSION_3_0
) {
866 /* override caller's expiration time, which uses client timeout
867 * duration, not server timeout duration.
869 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl2Timeout
;
870 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
871 "cipher=%d", myPid
, sid
->cached
,
872 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
873 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
874 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
875 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl2
.sessionID
,
876 SSL2_SESSIONID_BYTES
));
877 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
878 sid
->u
.ssl2
.masterKey
.len
));
879 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
880 sid
->u
.ssl2
.cipherArg
.len
));
883 /* override caller's expiration time, which uses client timeout
884 * duration, not server timeout duration.
886 sid
->expirationTime
= sid
->creationTime
+ cache
->ssl3Timeout
;
887 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
888 "cipherSuite=%d", myPid
, sid
->cached
,
889 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
890 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
891 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
892 PRINT_BUF(8, (0, "sessionID:", sid
->u
.ssl3
.sessionID
,
893 sid
->u
.ssl3
.sessionIDLength
));
896 ConvertFromSID(&sce
, sid
);
898 if (version
>= SSL_LIBRARY_VERSION_3_0
) {
899 SECItem
*name
= &sid
->u
.ssl3
.srvName
;
900 if (name
->len
&& name
->data
) {
901 now
= CacheSrvName(cache
, name
, &sce
);
903 if (sid
->peerCert
!= NULL
) {
904 now
= CacheCert(cache
, sid
->peerCert
, &sce
);
908 set
= SIDindex(cache
, &sce
.addr
, sce
.sessionID
, sce
.sessionIDLength
);
909 now
= LockSet(cache
, set
, now
);
911 PRUint32 next
= cache
->sidCacheSets
[set
].next
;
912 PRUint32 ndx
= set
* SID_CACHE_ENTRIES_PER_SET
+ next
;
914 /* Write out new cache entry */
915 cache
->sidCacheData
[ndx
] = sce
;
917 cache
->sidCacheSets
[set
].next
=
918 (next
+ 1) % SID_CACHE_ENTRIES_PER_SET
;
920 UnlockSet(cache
, set
);
921 sid
->cached
= in_server_cache
;
927 ** Although this is static, it is called from ssl via global function pointer
928 ** ssl_sid_uncache. This invalidates the referenced cache entry.
931 ServerSessionIDUncache(sslSessionID
*sid
)
933 cacheDesc
* cache
= &globalCache
;
935 unsigned int sessionIDLength
;
944 /* Uncaching a SID should never change the error code.
945 ** So save it here and restore it before exiting.
949 if (sid
->version
< SSL_LIBRARY_VERSION_3_0
) {
950 sessionID
= sid
->u
.ssl2
.sessionID
;
951 sessionIDLength
= SSL2_SESSIONID_BYTES
;
952 SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
953 "cipher=%d", myPid
, sid
->cached
,
954 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
955 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
956 sid
->creationTime
, sid
->u
.ssl2
.cipherType
));
957 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
958 PRINT_BUF(8, (0, "masterKey:", sid
->u
.ssl2
.masterKey
.data
,
959 sid
->u
.ssl2
.masterKey
.len
));
960 PRINT_BUF(8, (0, "cipherArg:", sid
->u
.ssl2
.cipherArg
.data
,
961 sid
->u
.ssl2
.cipherArg
.len
));
963 sessionID
= sid
->u
.ssl3
.sessionID
;
964 sessionIDLength
= sid
->u
.ssl3
.sessionIDLength
;
965 SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
966 "cipherSuite=%d", myPid
, sid
->cached
,
967 sid
->addr
.pr_s6_addr32
[0], sid
->addr
.pr_s6_addr32
[1],
968 sid
->addr
.pr_s6_addr32
[2], sid
->addr
.pr_s6_addr32
[3],
969 sid
->creationTime
, sid
->u
.ssl3
.cipherSuite
));
970 PRINT_BUF(8, (0, "sessionID:", sessionID
, sessionIDLength
));
972 set
= SIDindex(cache
, &sid
->addr
, sessionID
, sessionIDLength
);
973 now
= LockSet(cache
, set
, 0);
975 psce
= FindSID(cache
, set
, now
, &sid
->addr
, sessionID
, sessionIDLength
);
979 UnlockSet(cache
, set
);
981 sid
->cached
= invalid_cache
;
987 #define INCL_DOSPROCESS
994 DosGetInfoBlocks(&ptib
, &ppib
);
995 return ((long)ptib
->tib_ordinal
); /* thread id */
1000 CloseCache(cacheDesc
*cache
)
1002 int locks_initialized
= cache
->numSIDCacheLocksInitialized
;
1004 if (cache
->cacheMem
) {
1005 if (cache
->sharedCache
) {
1006 sidCacheLock
*pLock
= cache
->sidCacheLocks
;
1007 for (; locks_initialized
> 0; --locks_initialized
, ++pLock
) {
1008 /* If everInherited is true, this shared cache was (and may
1009 ** still be) in use by multiple processes. We do not wish to
1010 ** destroy the mutexes while they are still in use, but we do
1011 ** want to free mutex resources associated with this process.
1013 sslMutex_Destroy(&pLock
->mutex
,
1014 cache
->sharedCache
->everInherited
);
1017 if (cache
->shared
) {
1018 PR_MemUnmap(cache
->cacheMem
, cache
->cacheMemSize
);
1020 PORT_Free(cache
->cacheMem
);
1022 cache
->cacheMem
= NULL
;
1024 if (cache
->cacheMemMap
) {
1025 PR_CloseFileMap(cache
->cacheMemMap
);
1026 cache
->cacheMemMap
= NULL
;
1028 memset(cache
, 0, sizeof *cache
);
1032 InitCache(cacheDesc
*cache
, int maxCacheEntries
, int maxCertCacheEntries
,
1033 int maxSrvNameCacheEntries
, PRUint32 ssl2_timeout
,
1034 PRUint32 ssl3_timeout
, const char *directory
, PRBool shared
)
1037 sidCacheLock
*pLock
;
1039 PRFileMap
* cacheMemMap
;
1040 char * cfn
= NULL
; /* cache file name */
1041 int locks_initialized
= 0;
1042 int locks_to_initialize
= 0;
1045 if ( (!cache
) || (maxCacheEntries
< 0) || (!directory
) ) {
1046 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1050 if (cache
->cacheMem
) {
1055 /* make sure loser can clean up properly */
1056 cache
->shared
= shared
;
1057 cache
->cacheMem
= cacheMem
= NULL
;
1058 cache
->cacheMemMap
= cacheMemMap
= NULL
;
1059 cache
->sharedCache
= (cacheDesc
*)0;
1061 cache
->numSIDCacheLocksInitialized
= 0;
1062 cache
->nextCertCacheEntry
= 0;
1063 cache
->stopPolling
= PR_FALSE
;
1064 cache
->everInherited
= PR_FALSE
;
1065 cache
->poller
= NULL
;
1066 cache
->mutexTimeout
= 0;
1068 cache
->numSIDCacheEntries
= maxCacheEntries
? maxCacheEntries
1069 : DEF_SID_CACHE_ENTRIES
;
1070 cache
->numSIDCacheSets
=
1071 SID_HOWMANY(cache
->numSIDCacheEntries
, SID_CACHE_ENTRIES_PER_SET
);
1073 cache
->numSIDCacheEntries
=
1074 cache
->numSIDCacheSets
* SID_CACHE_ENTRIES_PER_SET
;
1076 cache
->numSIDCacheLocks
=
1077 PR_MIN(cache
->numSIDCacheSets
, ssl_max_sid_cache_locks
);
1079 cache
->numSIDCacheSetsPerLock
=
1080 SID_HOWMANY(cache
->numSIDCacheSets
, cache
->numSIDCacheLocks
);
1082 cache
->numCertCacheEntries
= (maxCertCacheEntries
> 0) ?
1083 maxCertCacheEntries
: 0;
1084 cache
->numSrvNameCacheEntries
= (maxSrvNameCacheEntries
>= 0) ?
1085 maxSrvNameCacheEntries
: DEF_NAME_CACHE_ENTRIES
;
1087 /* compute size of shared memory, and offsets of all pointers */
1089 cache
->cacheMem
= (char *)ptr
;
1090 ptr
+= SID_ROUNDUP(sizeof(cacheDesc
), SID_ALIGNMENT
);
1092 cache
->sidCacheLocks
= (sidCacheLock
*)ptr
;
1093 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1094 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1095 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1096 ptr
= (ptrdiff_t)(cache
->srvNameCacheLock
+ 1);
1097 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1099 cache
->sidCacheSets
= (sidCacheSet
*)ptr
;
1100 ptr
= (ptrdiff_t)(cache
->sidCacheSets
+ cache
->numSIDCacheSets
);
1101 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1103 cache
->sidCacheData
= (sidCacheEntry
*)ptr
;
1104 ptr
= (ptrdiff_t)(cache
->sidCacheData
+ cache
->numSIDCacheEntries
);
1105 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1107 cache
->certCacheData
= (certCacheEntry
*)ptr
;
1108 cache
->sidCacheSize
=
1109 (char *)cache
->certCacheData
- (char *)cache
->sidCacheData
;
1111 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
) {
1112 /* This is really a poor way to computer this! */
1113 cache
->numCertCacheEntries
= cache
->sidCacheSize
/ sizeof(certCacheEntry
);
1114 if (cache
->numCertCacheEntries
< MIN_CERT_CACHE_ENTRIES
)
1115 cache
->numCertCacheEntries
= MIN_CERT_CACHE_ENTRIES
;
1117 ptr
= (ptrdiff_t)(cache
->certCacheData
+ cache
->numCertCacheEntries
);
1118 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1120 cache
->keyCacheData
= (SSLWrappedSymWrappingKey
*)ptr
;
1121 cache
->certCacheSize
=
1122 (char *)cache
->keyCacheData
- (char *)cache
->certCacheData
;
1124 cache
->numKeyCacheEntries
= kt_kea_size
* SSL_NUM_WRAP_MECHS
;
1125 ptr
= (ptrdiff_t)(cache
->keyCacheData
+ cache
->numKeyCacheEntries
);
1126 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1128 cache
->keyCacheSize
= (char *)ptr
- (char *)cache
->keyCacheData
;
1130 cache
->ticketKeyNameSuffix
= (PRUint8
*)ptr
;
1131 ptr
= (ptrdiff_t)(cache
->ticketKeyNameSuffix
+
1132 SESS_TICKET_KEY_VAR_NAME_LEN
);
1133 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1135 cache
->ticketEncKey
= (encKeyCacheEntry
*)ptr
;
1136 ptr
= (ptrdiff_t)(cache
->ticketEncKey
+ 1);
1137 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1139 cache
->ticketMacKey
= (encKeyCacheEntry
*)ptr
;
1140 ptr
= (ptrdiff_t)(cache
->ticketMacKey
+ 1);
1141 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1143 cache
->ticketKeysValid
= (PRUint32
*)ptr
;
1144 ptr
= (ptrdiff_t)(cache
->ticketKeysValid
+ 1);
1145 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1147 cache
->srvNameCacheData
= (srvNameCacheEntry
*)ptr
;
1148 cache
->srvNameCacheSize
=
1149 cache
->numSrvNameCacheEntries
* sizeof(srvNameCacheEntry
);
1150 ptr
= (ptrdiff_t)(cache
->srvNameCacheData
+ cache
->numSrvNameCacheEntries
);
1151 ptr
= SID_ROUNDUP(ptr
, SID_ALIGNMENT
);
1153 cache
->cacheMemSize
= ptr
;
1156 if (ssl2_timeout
> MAX_SSL2_TIMEOUT
) {
1157 ssl2_timeout
= MAX_SSL2_TIMEOUT
;
1159 if (ssl2_timeout
< MIN_SSL2_TIMEOUT
) {
1160 ssl2_timeout
= MIN_SSL2_TIMEOUT
;
1162 cache
->ssl2Timeout
= ssl2_timeout
;
1164 cache
->ssl2Timeout
= DEF_SSL2_TIMEOUT
;
1168 if (ssl3_timeout
> MAX_SSL3_TIMEOUT
) {
1169 ssl3_timeout
= MAX_SSL3_TIMEOUT
;
1171 if (ssl3_timeout
< MIN_SSL3_TIMEOUT
) {
1172 ssl3_timeout
= MIN_SSL3_TIMEOUT
;
1174 cache
->ssl3Timeout
= ssl3_timeout
;
1176 cache
->ssl3Timeout
= DEF_SSL3_TIMEOUT
;
1180 /* Create file names */
1181 #if defined(XP_UNIX) || defined(XP_BEOS)
1182 /* there's some confusion here about whether PR_OpenAnonFileMap wants
1183 ** a directory name or a file name for its first argument.
1184 cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1186 cfn
= PR_smprintf("%s", directory
);
1187 #elif defined(XP_WIN32)
1188 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1189 GetCurrentThreadId());
1190 #elif defined(XP_OS2)
1191 cfn
= PR_smprintf("%s/svrcache_%d_%x.ssl", directory
, myPid
,
1194 #error "Don't know how to create file name for this platform!"
1201 cacheMemMap
= PR_OpenAnonFileMap(cfn
, cache
->cacheMemSize
,
1204 PR_smprintf_free(cfn
);
1209 cacheMem
= PR_MemMap(cacheMemMap
, 0, cache
->cacheMemSize
);
1211 cacheMem
= PORT_Alloc(cache
->cacheMemSize
);
1218 /* Initialize shared memory. This may not be necessary on all platforms */
1219 memset(cacheMem
, 0, cache
->cacheMemSize
);
1221 /* Copy cache descriptor header into shared memory */
1222 memcpy(cacheMem
, cache
, sizeof *cache
);
1224 /* save private copies of these values */
1225 cache
->cacheMemMap
= cacheMemMap
;
1226 cache
->cacheMem
= cacheMem
;
1227 cache
->sharedCache
= (cacheDesc
*)cacheMem
;
1229 /* Fix pointers in our private copy of cache descriptor to point to
1230 ** spaces in shared memory
1232 ptr
= (ptrdiff_t)cache
->cacheMem
;
1233 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1234 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1235 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1236 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1237 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1238 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1239 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1240 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1241 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1242 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1243 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1244 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1245 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1247 /* initialize the locks */
1248 init_time
= ssl_Time();
1249 pLock
= cache
->sidCacheLocks
;
1250 for (locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1251 locks_initialized
< locks_to_initialize
;
1252 ++locks_initialized
, ++pLock
) {
1254 SECStatus err
= sslMutex_Init(&pLock
->mutex
, shared
);
1256 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1259 pLock
->timeStamp
= init_time
;
1262 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1272 SSL_GetMaxServerCacheLocks(void)
1274 return ssl_max_sid_cache_locks
+ 2;
1275 /* The extra two are the cert cache lock and the key cache lock. */
1279 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
1281 /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1282 ** We'd like to test for a maximum value, but not all platforms' header
1283 ** files provide a symbol or function or other means of determining
1284 ** the maximum, other than trial and error.
1287 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
1290 ssl_max_sid_cache_locks
= maxLocks
- 2;
1291 /* The extra two are the cert cache lock and the key cache lock. */
1296 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc
*cache
,
1297 PRUint32 ssl2_timeout
,
1298 PRUint32 ssl3_timeout
,
1299 const char * directory
,
1301 int maxCacheEntries
,
1302 int maxCertCacheEntries
,
1303 int maxSrvNameCacheEntries
)
1307 PORT_Assert(sizeof(sidCacheEntry
) == 192);
1308 PORT_Assert(sizeof(certCacheEntry
) == 4096);
1309 PORT_Assert(sizeof(srvNameCacheEntry
) == 1072);
1312 if (rv
!= SECSuccess
) {
1316 myPid
= SSL_GETPID();
1318 directory
= DEFAULT_CACHE_DIRECTORY
;
1320 rv
= InitCache(cache
, maxCacheEntries
, maxCertCacheEntries
,
1321 maxSrvNameCacheEntries
, ssl2_timeout
, ssl3_timeout
,
1328 ssl_sid_lookup
= ServerSessionIDLookup
;
1329 ssl_sid_cache
= ServerSessionIDCache
;
1330 ssl_sid_uncache
= ServerSessionIDUncache
;
1335 SSL_ConfigServerSessionIDCacheInstance( cacheDesc
*cache
,
1336 int maxCacheEntries
,
1337 PRUint32 ssl2_timeout
,
1338 PRUint32 ssl3_timeout
,
1339 const char * directory
, PRBool shared
)
1341 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1351 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
1352 PRUint32 ssl2_timeout
,
1353 PRUint32 ssl3_timeout
,
1354 const char * directory
)
1356 ssl_InitSessionCacheLocks();
1357 return SSL_ConfigServerSessionIDCacheInstance(&globalCache
,
1358 maxCacheEntries
, ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
);
1362 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc
*cache
)
1369 SSL_ShutdownServerSessionIDCache(void)
1371 #if defined(XP_UNIX) || defined(XP_BEOS)
1372 /* Stop the thread that polls cache for expired locks on Unix */
1373 StopLockPoller(&globalCache
);
1375 SSL3_ShutdownServerCache();
1376 return SSL_ShutdownServerSessionIDCacheInstance(&globalCache
);
1379 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1380 * if the cache will be shared by multiple processes.
1383 ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout
,
1384 PRUint32 ssl3_timeout
,
1385 const char * directory
,
1386 int maxCacheEntries
,
1387 int maxCertCacheEntries
,
1388 int maxSrvNameCacheEntries
)
1392 cacheDesc
* cache
= &globalCache
;
1396 SECStatus putEnvFailed
;
1397 inheritance inherit
;
1398 char fmString
[PR_FILEMAP_STRING_BUFSIZE
];
1400 isMultiProcess
= PR_TRUE
;
1401 result
= ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache
,
1402 ssl2_timeout
, ssl3_timeout
, directory
, PR_TRUE
,
1403 maxCacheEntries
, maxCacheEntries
, maxSrvNameCacheEntries
);
1404 if (result
!= SECSuccess
)
1407 prStatus
= PR_ExportFileMapAsString(cache
->cacheMemMap
,
1408 sizeof fmString
, fmString
);
1409 if ((prStatus
!= PR_SUCCESS
) || !(fmStrLen
= strlen(fmString
))) {
1414 inherit
.cacheMemSize
= cache
->cacheMemSize
;
1415 inherit
.fmStrLen
= fmStrLen
;
1417 inhValue
= BTOA_DataToAscii((unsigned char *)&inherit
, sizeof inherit
);
1418 if (!inhValue
|| !strlen(inhValue
)) {
1422 envValue
= PR_smprintf("%s,%s", inhValue
, fmString
);
1423 if (!envValue
|| !strlen(envValue
)) {
1427 PORT_Free(inhValue
);
1429 putEnvFailed
= (SECStatus
)NSS_PutEnv(envVarName
, envValue
);
1430 PR_smprintf_free(envValue
);
1433 result
= SECFailure
;
1436 #if defined(XP_UNIX) || defined(XP_BEOS)
1437 /* Launch thread to poll cache for expired locks on Unix */
1438 LaunchLockPoller(cache
);
1443 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1444 * if the cache will be shared by multiple processes.
1447 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
1448 PRUint32 ssl2_timeout
,
1449 PRUint32 ssl3_timeout
,
1450 const char * directory
)
1452 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
,
1460 SSL_ConfigServerSessionIDCacheWithOpt(
1461 PRUint32 ssl2_timeout
,
1462 PRUint32 ssl3_timeout
,
1463 const char * directory
,
1464 int maxCacheEntries
,
1465 int maxCertCacheEntries
,
1466 int maxSrvNameCacheEntries
,
1467 PRBool enableMPCache
)
1469 if (!enableMPCache
) {
1470 ssl_InitSessionCacheLocks();
1471 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache
,
1472 ssl2_timeout
, ssl3_timeout
, directory
, PR_FALSE
,
1473 maxCacheEntries
, maxCertCacheEntries
, maxSrvNameCacheEntries
);
1475 return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout
, ssl3_timeout
,
1476 directory
, maxCacheEntries
, maxCertCacheEntries
,
1477 maxSrvNameCacheEntries
);
1482 SSL_InheritMPServerSIDCacheInstance(cacheDesc
*cache
, const char * envString
)
1484 unsigned char * decoString
= NULL
;
1485 char * fmString
= NULL
;
1486 char * myEnvString
= NULL
;
1487 unsigned int decoLen
;
1489 inheritance inherit
;
1492 sidCacheLock
* newLocks
;
1493 int locks_initialized
= 0;
1494 int locks_to_initialize
= 0;
1496 SECStatus status
= ssl_Init();
1498 if (status
!= SECSuccess
) {
1502 myPid
= SSL_GETPID();
1504 /* If this child was created by fork(), and not by exec() on unix,
1505 ** then isMultiProcess will already be set.
1506 ** If not, we'll set it below.
1508 if (isMultiProcess
) {
1509 if (cache
&& cache
->sharedCache
) {
1510 cache
->sharedCache
->everInherited
= PR_TRUE
;
1512 return SECSuccess
; /* already done. */
1515 ssl_InitSessionCacheLocks();
1517 ssl_sid_lookup
= ServerSessionIDLookup
;
1518 ssl_sid_cache
= ServerSessionIDCache
;
1519 ssl_sid_uncache
= ServerSessionIDUncache
;
1522 envString
= getenv(envVarName
);
1528 myEnvString
= PORT_Strdup(envString
);
1531 fmString
= strchr(myEnvString
, ',');
1536 decoString
= ATOB_AsciiToData(myEnvString
, &decoLen
);
1541 if (decoLen
!= sizeof inherit
) {
1546 PORT_Memcpy(&inherit
, decoString
, sizeof inherit
);
1548 if (strlen(fmString
) != inherit
.fmStrLen
) {
1552 memset(cache
, 0, sizeof *cache
);
1553 cache
->cacheMemSize
= inherit
.cacheMemSize
;
1556 cache
->cacheMemMap
= PR_ImportFileMapFromString(fmString
);
1557 if(! cache
->cacheMemMap
) {
1560 cache
->cacheMem
= PR_MemMap(cache
->cacheMemMap
, 0, cache
->cacheMemSize
);
1561 if (! cache
->cacheMem
) {
1564 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1566 if (cache
->sharedCache
->cacheMemSize
!= cache
->cacheMemSize
) {
1571 /* We're now going to overwrite the local cache instance with the
1572 ** shared copy of the cache struct, then update several values in
1573 ** the local cache using the values for cache->cacheMemMap and
1574 ** cache->cacheMem computed just above. So, we copy cache into
1575 ** the automatic variable "my", to preserve the variables while
1576 ** cache is overwritten.
1578 my
= *cache
; /* save values computed above. */
1579 memcpy(cache
, cache
->sharedCache
, sizeof *cache
); /* overwrite */
1581 /* Fix pointers in our private copy of cache descriptor to point to
1582 ** spaces in shared memory, whose address is now in "my".
1584 ptr
= (ptrdiff_t)my
.cacheMem
;
1585 *(ptrdiff_t *)(&cache
->sidCacheLocks
) += ptr
;
1586 *(ptrdiff_t *)(&cache
->keyCacheLock
) += ptr
;
1587 *(ptrdiff_t *)(&cache
->certCacheLock
) += ptr
;
1588 *(ptrdiff_t *)(&cache
->srvNameCacheLock
) += ptr
;
1589 *(ptrdiff_t *)(&cache
->sidCacheSets
) += ptr
;
1590 *(ptrdiff_t *)(&cache
->sidCacheData
) += ptr
;
1591 *(ptrdiff_t *)(&cache
->certCacheData
) += ptr
;
1592 *(ptrdiff_t *)(&cache
->keyCacheData
) += ptr
;
1593 *(ptrdiff_t *)(&cache
->ticketKeyNameSuffix
) += ptr
;
1594 *(ptrdiff_t *)(&cache
->ticketEncKey
) += ptr
;
1595 *(ptrdiff_t *)(&cache
->ticketMacKey
) += ptr
;
1596 *(ptrdiff_t *)(&cache
->ticketKeysValid
) += ptr
;
1597 *(ptrdiff_t *)(&cache
->srvNameCacheData
) += ptr
;
1599 cache
->cacheMemMap
= my
.cacheMemMap
;
1600 cache
->cacheMem
= my
.cacheMem
;
1601 cache
->sharedCache
= (cacheDesc
*)cache
->cacheMem
;
1604 /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1605 ** When NT fibers are used in a multi-process server, a second level of
1606 ** locking is needed to prevent a deadlock, in case a fiber acquires the
1607 ** cross-process mutex, yields, and another fiber is later scheduled on
1608 ** the same native thread and tries to acquire the cross-process mutex.
1609 ** We do this by using a PRLock in the sslMutex. However, it is stored in
1610 ** shared memory as part of sidCacheLocks, and we don't want to overwrite
1611 ** the PRLock of the parent process. So we need to make new, private
1612 ** copies of sidCacheLocks before modifying the sslMutex with our own
1616 /* note from jpierre : this should be free'd in child processes when
1617 ** a function is added to delete the SSL session cache in the future.
1619 locks_to_initialize
= cache
->numSIDCacheLocks
+ 3;
1620 newLocks
= PORT_NewArray(sidCacheLock
, locks_to_initialize
);
1623 /* copy the old locks */
1624 memcpy(newLocks
, cache
->sidCacheLocks
,
1625 locks_to_initialize
* sizeof(sidCacheLock
));
1626 cache
->sidCacheLocks
= newLocks
;
1628 for (; locks_initialized
< locks_to_initialize
; ++locks_initialized
) {
1629 /* now, make a local PRLock in this sslMutex for this child process */
1631 err
= sslMutex_2LevelInit(&newLocks
[locks_initialized
].mutex
);
1632 if (err
!= SECSuccess
) {
1633 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1637 cache
->numSIDCacheLocksInitialized
= locks_initialized
;
1639 /* also fix the key and cert cache which use the last 2 lock entries */
1640 cache
->keyCacheLock
= cache
->sidCacheLocks
+ cache
->numSIDCacheLocks
;
1641 cache
->certCacheLock
= cache
->keyCacheLock
+ 1;
1642 cache
->srvNameCacheLock
= cache
->certCacheLock
+ 1;
1645 PORT_Free(myEnvString
);
1646 PORT_Free(decoString
);
1648 /* mark that we have inherited this. */
1649 cache
->sharedCache
->everInherited
= PR_TRUE
;
1650 isMultiProcess
= PR_TRUE
;
1655 PORT_Free(myEnvString
);
1657 PORT_Free(decoString
);
1663 SSL_InheritMPServerSIDCache(const char * envString
)
1665 return SSL_InheritMPServerSIDCacheInstance(&globalCache
, envString
);
1668 #if defined(XP_UNIX) || defined(XP_BEOS)
1670 #define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
1673 LockPoller(void * arg
)
1675 cacheDesc
* cache
= (cacheDesc
*)arg
;
1676 cacheDesc
* sharedCache
= cache
->sharedCache
;
1677 sidCacheLock
* pLock
;
1678 PRIntervalTime timeout
;
1681 int locks_polled
= 0;
1682 int locks_to_poll
= cache
->numSIDCacheLocks
+ 2;
1683 PRUint32 expiration
= cache
->mutexTimeout
;
1685 timeout
= PR_SecondsToInterval(expiration
);
1686 while(!sharedCache
->stopPolling
) {
1688 if (sharedCache
->stopPolling
)
1692 then
= now
- expiration
;
1693 for (pLock
= cache
->sidCacheLocks
, locks_polled
= 0;
1694 locks_to_poll
> locks_polled
&& !sharedCache
->stopPolling
;
1695 ++locks_polled
, ++pLock
) {
1698 if (pLock
->timeStamp
< then
&&
1699 pLock
->timeStamp
!= 0 &&
1700 (pid
= pLock
->pid
) != 0) {
1702 /* maybe we should try the lock? */
1703 int result
= kill(pid
, 0);
1704 if (result
< 0 && errno
== ESRCH
) {
1706 /* No process exists by that pid any more.
1707 ** Treat this mutex as abandoned.
1709 pLock
->timeStamp
= now
;
1711 rv
= sslMutex_Unlock(&pLock
->mutex
);
1712 if (rv
!= SECSuccess
) {
1717 } /* end of loop over locks */
1718 } /* end of entire polling loop */
1721 /* Launch thread to poll cache for expired locks */
1723 LaunchLockPoller(cacheDesc
*cache
)
1725 const char * timeoutString
;
1726 PRThread
* pollerThread
;
1728 cache
->mutexTimeout
= SID_LOCK_EXPIRATION_TIMEOUT
;
1729 timeoutString
= getenv("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1730 if (timeoutString
) {
1731 long newTime
= strtol(timeoutString
, 0, 0);
1733 return SECSuccess
; /* application doesn't want poller thread */
1735 cache
->mutexTimeout
= (PRUint32
)newTime
;
1736 /* if error (newTime < 0) ignore it and use default */
1740 PR_CreateThread(PR_USER_THREAD
, LockPoller
, cache
, PR_PRIORITY_NORMAL
,
1741 PR_GLOBAL_THREAD
, PR_JOINABLE_THREAD
, 0);
1742 if (!pollerThread
) {
1745 cache
->poller
= pollerThread
;
1749 /* Stop the thread that polls cache for expired locks */
1751 StopLockPoller(cacheDesc
*cache
)
1753 if (!cache
->poller
) {
1756 cache
->sharedCache
->stopPolling
= PR_TRUE
;
1757 if (PR_Interrupt(cache
->poller
) != PR_SUCCESS
) {
1760 if (PR_JoinThread(cache
->poller
) != PR_SUCCESS
) {
1763 cache
->poller
= NULL
;
1768 /************************************************************************
1769 * Code dealing with shared wrapped symmetric wrapping keys below *
1770 ************************************************************************/
1772 /* If now is zero, it implies that the lock is not held, and must be
1776 getSvrWrappingKey(PRInt32 symWrapMechIndex
,
1777 SSL3KEAType exchKeyType
,
1778 SSLWrappedSymWrappingKey
*wswk
,
1782 PRUint32 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
1783 SSLWrappedSymWrappingKey
* pwswk
= cache
->keyCacheData
+ ndx
;
1785 PRBool rv
= PR_FALSE
;
1787 if (!cache
->cacheMem
) { /* cache is uninitialized */
1788 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
1792 lockTime
= now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
1797 if (pwswk
->exchKeyType
== exchKeyType
&&
1798 pwswk
->symWrapMechIndex
== symWrapMechIndex
&&
1799 pwswk
->wrappedSymKeyLen
!= 0) {
1804 UnlockSidCacheLock(cache
->keyCacheLock
);
1810 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
1811 SSL3KEAType exchKeyType
,
1812 SSLWrappedSymWrappingKey
*wswk
)
1816 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
1817 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
1818 if ((unsigned)exchKeyType
< kt_kea_size
&&
1819 (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
) {
1820 rv
= getSvrWrappingKey(symWrapMechIndex
, exchKeyType
, wswk
,
1829 /* Wrap and cache a session ticket key. */
1831 WrapTicketKey(SECKEYPublicKey
*svrPubKey
, PK11SymKey
*symKey
,
1832 const char *keyName
, encKeyCacheEntry
* cacheEntry
)
1834 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1836 wrappedKey
.len
= SECKEY_PublicKeyStrength(svrPubKey
);
1837 PORT_Assert(wrappedKey
.len
<= sizeof(cacheEntry
->bytes
));
1838 if (wrappedKey
.len
> sizeof(cacheEntry
->bytes
))
1840 wrappedKey
.data
= cacheEntry
->bytes
;
1842 if (PK11_PubWrapSymKey(CKM_RSA_PKCS
, svrPubKey
, symKey
, &wrappedKey
)
1844 SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
1845 SSL_GETPID(), "unknown", keyName
));
1848 cacheEntry
->length
= wrappedKey
.len
;
1853 GenerateTicketKeys(void *pwArg
, unsigned char *keyName
, PK11SymKey
**aesKey
,
1854 PK11SymKey
**macKey
)
1857 CK_MECHANISM_TYPE mechanismArray
[2];
1858 PK11SymKey
*aesKeyTmp
= NULL
;
1859 PK11SymKey
*macKeyTmp
= NULL
;
1860 cacheDesc
*cache
= &globalCache
;
1861 PRUint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
1862 PRUint8
*ticketKeyNameSuffix
;
1864 if (!cache
->cacheMem
) {
1865 /* cache is not initalized. Use stack buffer */
1866 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
1868 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
1871 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
1872 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
) {
1873 SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
1874 SSL_GETPID(), "unknown"));
1878 mechanismArray
[0] = CKM_AES_CBC
;
1879 mechanismArray
[1] = CKM_SHA256_HMAC
;
1881 slot
= PK11_GetBestSlotMultiple(mechanismArray
, 2, pwArg
);
1883 aesKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[0], NULL
,
1884 AES_256_KEY_LENGTH
, pwArg
);
1885 macKeyTmp
= PK11_KeyGen(slot
, mechanismArray
[1], NULL
,
1886 SHA256_LENGTH
, pwArg
);
1887 PK11_FreeSlot(slot
);
1890 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1891 SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
1892 SSL_GETPID(), "unknown"));
1895 PORT_Memcpy(keyName
, ticketKeyNameSuffix
, SESS_TICKET_KEY_VAR_NAME_LEN
);
1896 *aesKey
= aesKeyTmp
;
1897 *macKey
= macKeyTmp
;
1902 PK11_FreeSymKey(aesKeyTmp
);
1904 PK11_FreeSymKey(macKeyTmp
);
1909 GenerateAndWrapTicketKeys(SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1910 unsigned char *keyName
, PK11SymKey
**aesKey
,
1911 PK11SymKey
**macKey
)
1913 PK11SymKey
*aesKeyTmp
= NULL
;
1914 PK11SymKey
*macKeyTmp
= NULL
;
1915 cacheDesc
*cache
= &globalCache
;
1917 if (!GenerateTicketKeys(pwArg
, keyName
, &aesKeyTmp
, &macKeyTmp
)) {
1921 if (cache
->cacheMem
) {
1922 /* Export the keys to the shared cache in wrapped form. */
1923 if (!WrapTicketKey(svrPubKey
, aesKeyTmp
, "enc key", cache
->ticketEncKey
))
1925 if (!WrapTicketKey(svrPubKey
, macKeyTmp
, "mac key", cache
->ticketMacKey
))
1928 *aesKey
= aesKeyTmp
;
1929 *macKey
= macKeyTmp
;
1934 PK11_FreeSymKey(aesKeyTmp
);
1936 PK11_FreeSymKey(macKeyTmp
);
1941 UnwrapCachedTicketKeys(SECKEYPrivateKey
*svrPrivKey
, unsigned char *keyName
,
1942 PK11SymKey
**aesKey
, PK11SymKey
**macKey
)
1944 SECItem wrappedKey
= {siBuffer
, NULL
, 0};
1945 PK11SymKey
*aesKeyTmp
= NULL
;
1946 PK11SymKey
*macKeyTmp
= NULL
;
1947 cacheDesc
*cache
= &globalCache
;
1949 wrappedKey
.data
= cache
->ticketEncKey
->bytes
;
1950 wrappedKey
.len
= cache
->ticketEncKey
->length
;
1951 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketEncKey
->bytes
));
1952 aesKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1953 CKM_AES_CBC
, CKA_DECRYPT
, 0);
1955 wrappedKey
.data
= cache
->ticketMacKey
->bytes
;
1956 wrappedKey
.len
= cache
->ticketMacKey
->length
;
1957 PORT_Assert(wrappedKey
.len
<= sizeof(cache
->ticketMacKey
->bytes
));
1958 macKeyTmp
= PK11_PubUnwrapSymKey(svrPrivKey
, &wrappedKey
,
1959 CKM_SHA256_HMAC
, CKA_SIGN
, 0);
1961 if (aesKeyTmp
== NULL
|| macKeyTmp
== NULL
) {
1962 SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
1963 SSL_GETPID(), "unknown"));
1966 SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
1967 SSL_GETPID(), "unknown"));
1969 PORT_Memcpy(keyName
, cache
->ticketKeyNameSuffix
,
1970 SESS_TICKET_KEY_VAR_NAME_LEN
);
1971 *aesKey
= aesKeyTmp
;
1972 *macKey
= macKeyTmp
;
1977 PK11_FreeSymKey(aesKeyTmp
);
1979 PK11_FreeSymKey(macKeyTmp
);
1984 ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey
*svrPrivKey
,
1985 SECKEYPublicKey
*svrPubKey
, void *pwArg
,
1986 unsigned char *keyName
, PK11SymKey
**aesKey
,
1987 PK11SymKey
**macKey
)
1990 PRBool rv
= PR_FALSE
;
1991 PRBool keysGenerated
= PR_FALSE
;
1992 cacheDesc
*cache
= &globalCache
;
1994 if (!cache
->cacheMem
) {
1995 /* cache is uninitialized. Generate keys and return them
1996 * without caching. */
1997 return GenerateTicketKeys(pwArg
, keyName
, aesKey
, macKey
);
2000 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2004 if (!*(cache
->ticketKeysValid
)) {
2005 /* Keys do not exist, create them. */
2006 if (!GenerateAndWrapTicketKeys(svrPubKey
, pwArg
, keyName
,
2009 keysGenerated
= PR_TRUE
;
2010 *(cache
->ticketKeysValid
) = 1;
2016 UnlockSidCacheLock(cache
->keyCacheLock
);
2017 if (rv
&& !keysGenerated
)
2018 rv
= UnwrapCachedTicketKeys(svrPrivKey
, keyName
, aesKey
, macKey
);
2023 ssl_GetSessionTicketKeys(unsigned char *keyName
, unsigned char *encKey
,
2024 unsigned char *macKey
)
2026 PRBool rv
= PR_FALSE
;
2028 cacheDesc
*cache
= &globalCache
;
2029 PRUint8 ticketMacKey
[SHA256_LENGTH
], ticketEncKey
[AES_256_KEY_LENGTH
];
2030 PRUint8 ticketKeyNameSuffixLocal
[SESS_TICKET_KEY_VAR_NAME_LEN
];
2031 PRUint8
*ticketMacKeyPtr
, *ticketEncKeyPtr
, *ticketKeyNameSuffix
;
2032 PRBool cacheIsEnabled
= PR_TRUE
;
2034 if (!cache
->cacheMem
) { /* cache is uninitialized */
2035 cacheIsEnabled
= PR_FALSE
;
2036 ticketKeyNameSuffix
= ticketKeyNameSuffixLocal
;
2037 ticketEncKeyPtr
= ticketEncKey
;
2038 ticketMacKeyPtr
= ticketMacKey
;
2040 /* these values have constant memory locations in the cache.
2041 * Ok to reference them without holding the lock. */
2042 ticketKeyNameSuffix
= cache
->ticketKeyNameSuffix
;
2043 ticketEncKeyPtr
= cache
->ticketEncKey
->bytes
;
2044 ticketMacKeyPtr
= cache
->ticketMacKey
->bytes
;
2047 if (cacheIsEnabled
) {
2048 /* Grab lock if initialized. */
2049 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2053 /* Going to regenerate keys on every call if cache was not
2055 if (!cacheIsEnabled
|| !*(cache
->ticketKeysValid
)) {
2056 if (PK11_GenerateRandom(ticketKeyNameSuffix
,
2057 SESS_TICKET_KEY_VAR_NAME_LEN
) != SECSuccess
)
2059 if (PK11_GenerateRandom(ticketEncKeyPtr
,
2060 AES_256_KEY_LENGTH
) != SECSuccess
)
2062 if (PK11_GenerateRandom(ticketMacKeyPtr
,
2063 SHA256_LENGTH
) != SECSuccess
)
2065 if (cacheIsEnabled
) {
2066 *(cache
->ticketKeysValid
) = 1;
2073 if (cacheIsEnabled
) {
2074 UnlockSidCacheLock(cache
->keyCacheLock
);
2077 PORT_Memcpy(keyName
, ticketKeyNameSuffix
,
2078 SESS_TICKET_KEY_VAR_NAME_LEN
);
2079 PORT_Memcpy(encKey
, ticketEncKeyPtr
, AES_256_KEY_LENGTH
);
2080 PORT_Memcpy(macKey
, ticketMacKeyPtr
, SHA256_LENGTH
);
2085 /* The caller passes in the new value it wants
2086 * to set. This code tests the wrapped sym key entry in the shared memory.
2087 * If it is uninitialized, this function writes the caller's value into
2088 * the disk entry, and returns false.
2089 * Otherwise, it overwrites the caller's wswk with the value obtained from
2090 * the disk, and returns PR_TRUE.
2091 * This is all done while holding the locks/mutexes necessary to make
2092 * the operation atomic.
2095 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2097 cacheDesc
* cache
= &globalCache
;
2098 PRBool rv
= PR_FALSE
;
2099 SSL3KEAType exchKeyType
= wswk
->exchKeyType
;
2100 /* type of keys used to wrap SymWrapKey*/
2101 PRInt32 symWrapMechIndex
= wswk
->symWrapMechIndex
;
2104 SSLWrappedSymWrappingKey myWswk
;
2106 if (!cache
->cacheMem
) { /* cache is uninitialized */
2107 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED
);
2111 PORT_Assert( (unsigned)exchKeyType
< kt_kea_size
);
2112 if ((unsigned)exchKeyType
>= kt_kea_size
)
2115 PORT_Assert( (unsigned)symWrapMechIndex
< SSL_NUM_WRAP_MECHS
);
2116 if ((unsigned)symWrapMechIndex
>= SSL_NUM_WRAP_MECHS
)
2119 ndx
= (exchKeyType
* SSL_NUM_WRAP_MECHS
) + symWrapMechIndex
;
2120 PORT_Memset(&myWswk
, 0, sizeof myWswk
); /* eliminate UMRs. */
2122 now
= LockSidCacheLock(cache
->keyCacheLock
, now
);
2124 rv
= getSvrWrappingKey(wswk
->symWrapMechIndex
, wswk
->exchKeyType
,
2125 &myWswk
, cache
, now
);
2127 /* we found it on disk, copy it out to the caller. */
2128 PORT_Memcpy(wswk
, &myWswk
, sizeof *wswk
);
2130 /* Wasn't on disk, and we're still holding the lock, so write it. */
2131 cache
->keyCacheData
[ndx
] = *wswk
;
2133 UnlockSidCacheLock(cache
->keyCacheLock
);
2138 #else /* MAC version or other platform */
2140 #include "seccomon.h"
2143 #include "sslimpl.h"
2146 SSL_ConfigServerSessionIDCache( int maxCacheEntries
,
2147 PRUint32 ssl2_timeout
,
2148 PRUint32 ssl3_timeout
,
2149 const char * directory
)
2151 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
2156 SSL_ConfigMPServerSIDCache( int maxCacheEntries
,
2157 PRUint32 ssl2_timeout
,
2158 PRUint32 ssl3_timeout
,
2159 const char * directory
)
2161 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
2166 SSL_InheritMPServerSIDCache(const char * envString
)
2168 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
2173 ssl_GetWrappingKey( PRInt32 symWrapMechIndex
,
2174 SSL3KEAType exchKeyType
,
2175 SSLWrappedSymWrappingKey
*wswk
)
2177 PRBool rv
= PR_FALSE
;
2178 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
2182 /* This is a kind of test-and-set. The caller passes in the new value it wants
2183 * to set. This code tests the wrapped sym key entry in the shared memory.
2184 * If it is uninitialized, this function writes the caller's value into
2185 * the disk entry, and returns false.
2186 * Otherwise, it overwrites the caller's wswk with the value obtained from
2187 * the disk, and returns PR_TRUE.
2188 * This is all done while holding the locks/mutexes necessary to make
2189 * the operation atomic.
2192 ssl_SetWrappingKey(SSLWrappedSymWrappingKey
*wswk
)
2194 PRBool rv
= PR_FALSE
;
2195 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
2200 SSL_GetMaxServerCacheLocks(void)
2202 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
2207 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks
)
2209 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
2213 #endif /* XP_UNIX || XP_WIN32 */