1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This file implements the SERVER Session ID cache.
3 * NOTE: The contents of this file are NOT used by the client.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8
9 /* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
10 * cache sids!
11 *
12 * About record locking among different server processes:
13 *
14 * All processes that are part of the same conceptual server (serving on
15 * the same address and port) MUST share a common SSL session cache.
16 * This code makes the content of the shared cache accessible to all
17 * processes on the same "server". This code works on Unix and Win32 only.
18 *
19 * We use NSPR anonymous shared memory and move data to & from shared memory.
20 * We must do explicit locking of the records for all reads and writes.
21 * The set of Cache entries are divided up into "sets" of 128 entries.
22 * Each set is protected by a lock. There may be one or more sets protected
23 * by each lock. That is, locks to sets are 1:N.
24 * There is one lock for the entire cert cache.
25 * There is one lock for the set of wrapped sym wrap keys.
26 *
27 * The anonymous shared memory is laid out as if it were declared like this:
28 *
29 * struct {
30 * cacheDescriptor desc;
31 * sidCacheLock sidCacheLocks[ numSIDCacheLocks];
32 * sidCacheLock keyCacheLock;
33 * sidCacheLock certCacheLock;
34 * sidCacheSet sidCacheSets[ numSIDCacheSets ];
35 * sidCacheEntry sidCacheData[ numSIDCacheEntries];
36 * certCacheEntry certCacheData[numCertCacheEntries];
37 * SSLWrappedSymWrappingKey keyCacheData[SSL_NUM_WRAP_KEYS][SSL_NUM_WRAP_MECHS];
38 * PRUint8 keyNameSuffix[SELF_ENCRYPT_KEY_VAR_NAME_LEN]
39 * encKeyCacheEntry ticketEncKey; // Wrapped
40 * encKeyCacheEntry ticketMacKey; // Wrapped
41 * PRBool ticketKeysValid;
42 * sidCacheLock srvNameCacheLock;
43 * srvNameCacheEntry srvNameData[ numSrvNameCacheEntries ];
44 * } cacheMemCacheData;
45 */
46 #include "seccomon.h"
47
48 #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
49
50 #include "cert.h"
51 #include "ssl.h"
52 #include "sslimpl.h"
53 #include "sslproto.h"
54 #include "pk11func.h"
55 #include "base64.h"
56 #include "keyhi.h"
57 #include "blapit.h"
58 #include "nss.h" /* for NSS_RegisterShutdown */
59 #include "sechash.h"
60 #include "selfencrypt.h"
61 #include <stdio.h>
62
63 #if defined(XP_UNIX) || defined(XP_BEOS)
64
65 #include <syslog.h>
66 #include <fcntl.h>
67 #include <unistd.h>
68 #include <errno.h>
69 #include <signal.h>
70 #include "unix_err.h"
71
72 #else
73
74 #ifdef XP_WIN32
75 #include <wtypes.h>
76 #include "win32err.h"
77 #endif
78
79 #endif
80 #include <sys/types.h>
81
82 #include <nspr.h>
83 #include "sslmutex.h"
84
85 /*
86 ** Format of a cache entry in the shared memory.
87 */
88 PR_STATIC_ASSERT(sizeof(PRTime) == 8);
89 struct sidCacheEntryStr {
90 /* 16 */ PRIPv6Addr addr; /* client's IP address */
91 /* 8 */ PRTime creationTime;
92 /* 8 */ PRTime lastAccessTime;
93 /* 8 */ PRTime expirationTime;
94 /* 2 */ PRUint16 version;
95 /* 1 */ PRUint8 valid;
96 /* 1 */ PRUint8 sessionIDLength;
97 /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
98 /* 2 */ PRUint16 authType;
99 /* 2 */ PRUint16 authKeyBits;
100 /* 2 */ PRUint16 keaType;
101 /* 2 */ PRUint16 keaKeyBits;
102 /* 4 */ PRUint32 signatureScheme;
103 /* 4 */ PRUint32 keaGroup;
104 /* 92 - common header total */
105
106 union {
107 struct {
108 /* 2 */ ssl3CipherSuite cipherSuite;
109 /* 52 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
110
111 /* 4 */ PRUint32 masterWrapMech;
112 /* 4 */ PRInt32 certIndex;
113 /* 4 */ PRInt32 srvNameIndex;
114 /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
115 /* 2 */ PRUint16 namedCurve;
116 /*100 */} ssl3;
117
118 /* force sizeof(sidCacheEntry) to be a multiple of cache line size */
119 struct {
120 /*116 */ PRUint8 filler[116]; /* 92+116==208, a multiple of 16 */
121 } forceSize;
122 } u;
123 };
124 typedef struct sidCacheEntryStr sidCacheEntry;
125
126 /* The length of this struct is supposed to be a power of 2, e.g. 4KB */
127 struct certCacheEntryStr {
128 PRUint16 certLength; /* 2 */
129 PRUint16 sessionIDLength; /* 2 */
130 PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /* 32 */
131 PRUint8 cert[SSL_MAX_CACHED_CERT_LEN]; /* 4060 */
132 }; /* total 4096 */
133 typedef struct certCacheEntryStr certCacheEntry;
134
135 struct sidCacheLockStr {
136 PRUint32 timeStamp;
137 sslMutex mutex;
138 sslPID pid;
139 };
140 typedef struct sidCacheLockStr sidCacheLock;
141
142 struct sidCacheSetStr {
143 PRIntn next;
144 };
145 typedef struct sidCacheSetStr sidCacheSet;
146
147 struct encKeyCacheEntryStr {
148 PRUint8 bytes[512];
149 PRInt32 length;
150 };
151 typedef struct encKeyCacheEntryStr encKeyCacheEntry;
152
153 #define SSL_MAX_DNS_HOST_NAME 1024
154
155 struct srvNameCacheEntryStr {
156 PRUint16 type; /* 2 */
157 PRUint16 nameLen; /* 2 */
158 PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
159 PRUint8 nameHash[SHA256_LENGTH]; /* 32 */
160 /* 1072 */
161 };
162 typedef struct srvNameCacheEntryStr srvNameCacheEntry;
163
164 struct cacheDescStr {
165
166 PRUint32 cacheMemSize;
167
168 PRUint32 numSIDCacheLocks;
169 PRUint32 numSIDCacheSets;
170 PRUint32 numSIDCacheSetsPerLock;
171
172 PRUint32 numSIDCacheEntries;
173 PRUint32 sidCacheSize;
174
175 PRUint32 numCertCacheEntries;
176 PRUint32 certCacheSize;
177
178 PRUint32 numKeyCacheEntries;
179 PRUint32 keyCacheSize;
180
181 PRUint32 numSrvNameCacheEntries;
182 PRUint32 srvNameCacheSize;
183
184 PRUint32 ssl3Timeout;
185
186 PRUint32 numSIDCacheLocksInitialized;
187
188 /* These values are volatile, and are accessed through sharedCache-> */
189 PRUint32 nextCertCacheEntry; /* certCacheLock protects */
190 PRBool stopPolling;
191 PRBool everInherited;
192
193 /* The private copies of these values are pointers into shared mem */
194 /* The copies of these values in shared memory are merely offsets */
195 sidCacheLock *sidCacheLocks;
196 sidCacheLock *keyCacheLock;
197 sidCacheLock *certCacheLock;
198 sidCacheLock *srvNameCacheLock;
199 sidCacheSet *sidCacheSets;
200 sidCacheEntry *sidCacheData;
201 certCacheEntry *certCacheData;
202 SSLWrappedSymWrappingKey *keyCacheData;
203 PRUint8 *ticketKeyNameSuffix;
204 encKeyCacheEntry *ticketEncKey;
205 encKeyCacheEntry *ticketMacKey;
206 PRUint32 *ticketKeysValid;
207 srvNameCacheEntry *srvNameCacheData;
208
209 /* Only the private copies of these pointers are valid */
210 char *cacheMem;
211 struct cacheDescStr *sharedCache; /* shared copy of this struct */
212 PRFileMap *cacheMemMap;
213 PRThread *poller;
214 PRUint32 mutexTimeout;
215 PRBool shared;
216 };
217 typedef struct cacheDescStr cacheDesc;
218
219 static cacheDesc globalCache;
220
221 static const char envVarName[] = { SSL_ENV_VAR_NAME };
222
223 static PRBool isMultiProcess = PR_FALSE;
224
225 #define DEF_SID_CACHE_ENTRIES 10000
226 #define DEF_CERT_CACHE_ENTRIES 250
227 #define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
228 #define DEF_KEY_CACHE_ENTRIES 250
229 #define DEF_NAME_CACHE_ENTRIES 1000
230
231 #define SID_CACHE_ENTRIES_PER_SET 128
232 #define SID_ALIGNMENT 16
233
234 #define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
235 #define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
236 #define MIN_SSL3_TIMEOUT 5 /* seconds */
237
238 #if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
239 #define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
240 #elif defined(OSF1)
241 #define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
242 #else
243 #define MAX_SID_CACHE_LOCKS 256
244 #endif
245
246 #define SID_HOWMANY(val, size) (((val) + ((size)-1)) / (size))
247 #define SID_ROUNDUP(val, size) ((size)*SID_HOWMANY((val), (size)))
248
249 static sslPID myPid;
250 static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
251
252 /* forward static function declarations */
253 static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
254 unsigned nl);
255 static SECStatus LaunchLockPoller(cacheDesc *cache);
256 static SECStatus StopLockPoller(cacheDesc *cache);
257
258 struct inheritanceStr {
259 PRUint32 cacheMemSize;
260 PRUint32 fmStrLen;
261 };
262
263 typedef struct inheritanceStr inheritance;
264
265 #if defined(_WIN32) || defined(XP_OS2)
266
267 #define DEFAULT_CACHE_DIRECTORY "\\temp"
268
269 #endif /* _win32 */
270
271 #if defined(XP_UNIX) || defined(XP_BEOS)
272
273 #define DEFAULT_CACHE_DIRECTORY "/tmp"
274
275 #endif /* XP_UNIX || XP_BEOS */
276
277 /************************************************************************/
278
279 /* SSL Session Cache has a smaller set of functions to initialize than
280 * ssl does. some ssl_functions can't be initialized before NSS has been
281 * initialized, and the cache may be configured before NSS is initialized
282 * so thus the special init function */
283 static SECStatus
ssl_InitSessionCache()284 ssl_InitSessionCache()
285 {
286 /* currently only one function, which is itself idempotent */
287 return ssl_InitializePRErrorTable();
288 }
289
290 /* This is used to set locking times for the cache. It is not used to set the
291 * PRTime attributes of sessions, which are driven by ss->now(). */
292 static PRUint32
ssl_CacheNow()293 ssl_CacheNow()
294 {
295 return PR_Now() / PR_USEC_PER_SEC;
296 }
297
298 static PRUint32
LockSidCacheLock(sidCacheLock * lock,PRUint32 now)299 LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
300 {
301 SECStatus rv = sslMutex_Lock(&lock->mutex);
302 if (rv != SECSuccess)
303 return 0;
304 if (!now) {
305 now = ssl_CacheNow();
306 }
307
308 lock->timeStamp = now;
309 lock->pid = myPid;
310 return now;
311 }
312
313 static SECStatus
UnlockSidCacheLock(sidCacheLock * lock)314 UnlockSidCacheLock(sidCacheLock *lock)
315 {
316 SECStatus rv;
317
318 lock->pid = 0;
319 rv = sslMutex_Unlock(&lock->mutex);
320 return rv;
321 }
322
323 /* Returns non-zero |now| or ssl_CacheNow() on success, zero on failure. */
324 static PRUint32
LockSet(cacheDesc * cache,PRUint32 set,PRUint32 now)325 LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
326 {
327 PRUint32 lockNum = set % cache->numSIDCacheLocks;
328 sidCacheLock *lock = cache->sidCacheLocks + lockNum;
329
330 return LockSidCacheLock(lock, now);
331 }
332
333 static SECStatus
UnlockSet(cacheDesc * cache,PRUint32 set)334 UnlockSet(cacheDesc *cache, PRUint32 set)
335 {
336 PRUint32 lockNum = set % cache->numSIDCacheLocks;
337 sidCacheLock *lock = cache->sidCacheLocks + lockNum;
338
339 return UnlockSidCacheLock(lock);
340 }
341
342 /************************************************************************/
343
344 /* Put a certificate in the cache. Update the cert index in the sce.
345 */
346 static PRUint32
CacheCert(cacheDesc * cache,CERTCertificate * cert,sidCacheEntry * sce)347 CacheCert(cacheDesc *cache, CERTCertificate *cert, sidCacheEntry *sce)
348 {
349 PRUint32 now;
350 certCacheEntry cce;
351
352 if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
353 (cert->derCert.len <= 0) ||
354 (cert->derCert.data == NULL)) {
355 PORT_SetError(SEC_ERROR_INVALID_ARGS);
356 return 0;
357 }
358
359 cce.sessionIDLength = sce->sessionIDLength;
360 PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
361
362 cce.certLength = cert->derCert.len;
363 PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
364
365 /* get lock on cert cache */
366 now = LockSidCacheLock(cache->certCacheLock, 0);
367 if (now) {
368
369 /* Find where to place the next cert cache entry. */
370 cacheDesc *sharedCache = cache->sharedCache;
371 PRUint32 ndx = sharedCache->nextCertCacheEntry;
372
373 /* write the entry */
374 cache->certCacheData[ndx] = cce;
375
376 /* remember where we put it. */
377 sce->u.ssl3.certIndex = ndx;
378
379 /* update the "next" cache entry index */
380 sharedCache->nextCertCacheEntry =
381 (ndx + 1) % cache->numCertCacheEntries;
382
383 UnlockSidCacheLock(cache->certCacheLock);
384 }
385 return now;
386 }
387
388 /* Server configuration hash tables need to account the SECITEM.type
389 * field as well. These functions accomplish that. */
390 static PLHashNumber
Get32BitNameHash(const SECItem * name)391 Get32BitNameHash(const SECItem *name)
392 {
393 PLHashNumber rv = SECITEM_Hash(name);
394
395 PRUint8 *rvc = (PRUint8 *)&rv;
396 rvc[name->len % sizeof(rv)] ^= name->type;
397
398 return rv;
399 }
400
401 /* Put a name in the cache. Update the cert index in the sce.
402 */
403 static PRUint32
CacheSrvName(cacheDesc * cache,SECItem * name,sidCacheEntry * sce)404 CacheSrvName(cacheDesc *cache, SECItem *name, sidCacheEntry *sce)
405 {
406 PRUint32 now;
407 PRUint32 ndx;
408 srvNameCacheEntry snce;
409
410 if (!name || name->len <= 0 ||
411 name->len > SSL_MAX_DNS_HOST_NAME) {
412 PORT_SetError(SEC_ERROR_INVALID_ARGS);
413 return 0;
414 }
415
416 snce.type = name->type;
417 snce.nameLen = name->len;
418 PORT_Memcpy(snce.name, name->data, snce.nameLen);
419 HASH_HashBuf(HASH_AlgSHA256, snce.nameHash, name->data, name->len);
420
421 /* get index of the next name */
422 ndx = Get32BitNameHash(name);
423 /* get lock on cert cache */
424 now = LockSidCacheLock(cache->srvNameCacheLock, 0);
425 if (now) {
426 if (cache->numSrvNameCacheEntries > 0) {
427 /* Fit the index into array */
428 ndx %= cache->numSrvNameCacheEntries;
429 /* write the entry */
430 cache->srvNameCacheData[ndx] = snce;
431 /* remember where we put it. */
432 sce->u.ssl3.srvNameIndex = ndx;
433 /* Copy hash into sid hash */
434 PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
435 }
436 UnlockSidCacheLock(cache->srvNameCacheLock);
437 }
438 return now;
439 }
440
441 /*
442 ** Convert local SID to shared memory one
443 */
444 static void
ConvertFromSID(sidCacheEntry * to,sslSessionID * from)445 ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
446 {
447 to->valid = 1;
448 to->version = from->version;
449 to->addr = from->addr;
450 to->creationTime = from->creationTime;
451 to->lastAccessTime = from->lastAccessTime;
452 to->expirationTime = from->expirationTime;
453 to->authType = from->authType;
454 to->authKeyBits = from->authKeyBits;
455 to->keaType = from->keaType;
456 to->keaKeyBits = from->keaKeyBits;
457 to->keaGroup = from->keaGroup;
458 to->signatureScheme = from->sigScheme;
459
460 to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
461 to->u.ssl3.keys = from->u.ssl3.keys;
462 to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
463 to->sessionIDLength = from->u.ssl3.sessionIDLength;
464 to->u.ssl3.certIndex = -1;
465 to->u.ssl3.srvNameIndex = -1;
466 PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
467 to->sessionIDLength);
468 to->u.ssl3.namedCurve = 0U;
469 if (from->authType == ssl_auth_ecdsa ||
470 from->authType == ssl_auth_ecdh_rsa ||
471 from->authType == ssl_auth_ecdh_ecdsa) {
472 PORT_Assert(from->namedCurve);
473 to->u.ssl3.namedCurve = (PRUint16)from->namedCurve->name;
474 }
475
476 SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
477 "cipherSuite=%d",
478 myPid, to->creationTime / PR_USEC_PER_SEC,
479 to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
480 to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
481 to->u.ssl3.cipherSuite));
482 }
483
484 /*
485 ** Convert shared memory cache-entry to local memory based one
486 ** This is only called from ServerSessionIDLookup().
487 */
488 static sslSessionID *
ConvertToSID(sidCacheEntry * from,certCacheEntry * pcce,srvNameCacheEntry * psnce,CERTCertDBHandle * dbHandle)489 ConvertToSID(sidCacheEntry *from,
490 certCacheEntry *pcce,
491 srvNameCacheEntry *psnce,
492 CERTCertDBHandle *dbHandle)
493 {
494 sslSessionID *to;
495
496 to = PORT_ZNew(sslSessionID);
497 if (!to) {
498 return 0;
499 }
500
501 to->u.ssl3.sessionIDLength = from->sessionIDLength;
502 to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
503 to->u.ssl3.keys = from->u.ssl3.keys;
504 to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
505 if (from->u.ssl3.srvNameIndex != -1 && psnce) {
506 SECItem name;
507 SECStatus rv;
508 name.type = psnce->type;
509 name.len = psnce->nameLen;
510 name.data = psnce->name;
511 rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
512 if (rv != SECSuccess) {
513 goto loser;
514 }
515 }
516
517 PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
518
519 to->urlSvrName = NULL;
520
521 to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
522 to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */
523 to->u.ssl3.masterWrapIndex = 0;
524 to->u.ssl3.masterWrapSeries = 0;
525 to->u.ssl3.masterValid = PR_FALSE;
526
527 to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
528 to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */
529 to->u.ssl3.clAuthSeries = 0;
530 to->u.ssl3.clAuthValid = PR_FALSE;
531
532 if (from->u.ssl3.certIndex != -1 && pcce) {
533 SECItem derCert;
534
535 derCert.len = pcce->certLength;
536 derCert.data = pcce->cert;
537
538 to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
539 PR_FALSE, PR_TRUE);
540 if (to->peerCert == NULL)
541 goto loser;
542 }
543 if (from->authType == ssl_auth_ecdsa ||
544 from->authType == ssl_auth_ecdh_rsa ||
545 from->authType == ssl_auth_ecdh_ecdsa) {
546 to->namedCurve =
547 ssl_LookupNamedGroup((SSLNamedGroup)from->u.ssl3.namedCurve);
548 }
549
550 to->version = from->version;
551 to->creationTime = from->creationTime;
552 to->lastAccessTime = from->lastAccessTime;
553 to->expirationTime = from->expirationTime;
554 to->cached = in_server_cache;
555 to->addr = from->addr;
556 to->references = 1;
557 to->authType = from->authType;
558 to->authKeyBits = from->authKeyBits;
559 to->keaType = from->keaType;
560 to->keaKeyBits = from->keaKeyBits;
561 to->keaGroup = from->keaGroup;
562 to->sigScheme = from->signatureScheme;
563
564 return to;
565
566 loser:
567 if (to) {
568 SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
569 PORT_Free(to);
570 }
571 return NULL;
572 }
573
574 /*
575 ** Perform some mumbo jumbo on the ip-address and the session-id value to
576 ** compute a hash value.
577 */
578 static PRUint32
SIDindex(cacheDesc * cache,const PRIPv6Addr * addr,PRUint8 * s,unsigned nl)579 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
580 {
581 PRUint32 rv;
582 PRUint32 x[8];
583
584 memset(x, 0, sizeof x);
585 if (nl > sizeof x)
586 nl = sizeof x;
587 memcpy(x, s, nl);
588
589 rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
590 addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
591 x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7]) %
592 cache->numSIDCacheSets;
593 return rv;
594 }
595
596 /*
597 ** Look something up in the cache. This will invalidate old entries
598 ** in the process. Caller has locked the cache set!
599 ** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
600 */
601 static sidCacheEntry *
FindSID(cacheDesc * cache,PRUint32 setNum,PRUint32 now,const PRIPv6Addr * addr,unsigned char * sessionID,unsigned sessionIDLength)602 FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
603 const PRIPv6Addr *addr, unsigned char *sessionID,
604 unsigned sessionIDLength)
605 {
606 PRUint32 ndx = cache->sidCacheSets[setNum].next;
607 int i;
608
609 sidCacheEntry *set = cache->sidCacheData +
610 (setNum * SID_CACHE_ENTRIES_PER_SET);
611
612 for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
613 sidCacheEntry *sce;
614
615 ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
616 sce = set + ndx;
617
618 if (!sce->valid)
619 continue;
620
621 if (now > sce->expirationTime) {
622 /* SessionID has timed out. Invalidate the entry. */
623 SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
624 "time+=%x",
625 myPid, sce->addr.pr_s6_addr32[0],
626 sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
627 sce->addr.pr_s6_addr32[3], now,
628 sce->expirationTime));
629 sce->valid = 0;
630 continue;
631 }
632
633 /*
634 ** Next, examine specific session-id/addr data to see if the cache
635 ** entry matches our addr+session-id value
636 */
637 if (sessionIDLength == sce->sessionIDLength &&
638 !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
639 !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
640 /* Found it */
641 return sce;
642 }
643 }
644
645 PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
646 return NULL;
647 }
648
649 /************************************************************************/
650
651 /* This is the primary function for finding entries in the server's sid cache.
652 * Although it is static, this function is called via the global function
653 * pointer ssl_sid_lookup.
654 *
655 * sslNow is the time that the calling socket understands, which might be
656 * different than what the cache uses to maintain its locks.
657 */
658 static sslSessionID *
ServerSessionIDLookup(PRTime sslNow,const PRIPv6Addr * addr,unsigned char * sessionID,unsigned int sessionIDLength,CERTCertDBHandle * dbHandle)659 ServerSessionIDLookup(PRTime sslNow, const PRIPv6Addr *addr,
660 unsigned char *sessionID,
661 unsigned int sessionIDLength,
662 CERTCertDBHandle *dbHandle)
663 {
664 sslSessionID *sid = 0;
665 sidCacheEntry *psce;
666 certCacheEntry *pcce = 0;
667 srvNameCacheEntry *psnce = 0;
668 cacheDesc *cache = &globalCache;
669 PRUint32 now;
670 PRUint32 set;
671 PRInt32 cndx;
672 sidCacheEntry sce;
673 certCacheEntry cce;
674 srvNameCacheEntry snce;
675
676 set = SIDindex(cache, addr, sessionID, sessionIDLength);
677 now = LockSet(cache, set, 0);
678 if (!now)
679 return NULL;
680
681 psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
682 if (psce) {
683 if ((cndx = psce->u.ssl3.certIndex) != -1) {
684 PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
685 if (gotLock) {
686 pcce = &cache->certCacheData[cndx];
687
688 /* See if the cert's session ID matches the sce cache. */
689 if ((pcce->sessionIDLength == psce->sessionIDLength) &&
690 !PORT_Memcmp(pcce->sessionID, psce->sessionID,
691 pcce->sessionIDLength)) {
692 cce = *pcce;
693 } else {
694 /* The cert doesen't match the SID cache entry,
695 ** so invalidate the SID cache entry.
696 */
697 psce->valid = 0;
698 psce = 0;
699 pcce = 0;
700 }
701 UnlockSidCacheLock(cache->certCacheLock);
702 } else {
703 /* what the ??. Didn't get the cert cache lock.
704 ** Don't invalidate the SID cache entry, but don't find it.
705 */
706 PORT_AssertNotReached("Didn't get cert Cache Lock!");
707 psce = 0;
708 pcce = 0;
709 }
710 }
711 if (psce && ((cndx = psce->u.ssl3.srvNameIndex) != -1)) {
712 PRUint32 gotLock = LockSidCacheLock(cache->srvNameCacheLock,
713 now);
714 if (gotLock) {
715 psnce = &cache->srvNameCacheData[cndx];
716
717 if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
718 SHA256_LENGTH)) {
719 snce = *psnce;
720 } else {
721 /* The name doesen't match the SID cache entry,
722 ** so invalidate the SID cache entry.
723 */
724 psce->valid = 0;
725 psce = 0;
726 psnce = 0;
727 }
728 UnlockSidCacheLock(cache->srvNameCacheLock);
729 } else {
730 /* what the ??. Didn't get the cert cache lock.
731 ** Don't invalidate the SID cache entry, but don't find it.
732 */
733 PORT_AssertNotReached("Didn't get name Cache Lock!");
734 psce = 0;
735 psnce = 0;
736 }
737 }
738 if (psce) {
739 psce->lastAccessTime = sslNow;
740 sce = *psce; /* grab a copy while holding the lock */
741 }
742 }
743 UnlockSet(cache, set);
744 if (psce) {
745 /* sce conains a copy of the cache entry.
746 ** Convert shared memory format to local format
747 */
748 sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
749 }
750 return sid;
751 }
752
753 /*
754 ** Place a sid into the cache, if it isn't already there.
755 */
756 void
ssl_ServerCacheSessionID(sslSessionID * sid,PRTime creationTime)757 ssl_ServerCacheSessionID(sslSessionID *sid, PRTime creationTime)
758 {
759 PORT_Assert(sid);
760
761 sidCacheEntry sce;
762 PRUint32 now = 0;
763 cacheDesc *cache = &globalCache;
764
765 if (sid->u.ssl3.sessionIDLength == 0) {
766 return;
767 }
768
769 if (sid->cached == never_cached || sid->cached == invalid_cache) {
770 PRUint32 set;
771 SECItem *name;
772
773 PORT_Assert(sid->creationTime != 0);
774 if (!sid->creationTime)
775 sid->lastAccessTime = sid->creationTime = creationTime;
776 /* override caller's expiration time, which uses client timeout
777 * duration, not server timeout duration.
778 */
779 sid->expirationTime =
780 sid->creationTime + cache->ssl3Timeout * PR_USEC_PER_SEC;
781 SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
782 "cipherSuite=%d",
783 myPid, sid->cached,
784 sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
785 sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
786 sid->creationTime / PR_USEC_PER_SEC,
787 sid->u.ssl3.cipherSuite));
788 PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
789 sid->u.ssl3.sessionIDLength));
790
791 ConvertFromSID(&sce, sid);
792
793 name = &sid->u.ssl3.srvName;
794 if (name->len && name->data) {
795 now = CacheSrvName(cache, name, &sce);
796 }
797 if (sid->peerCert != NULL) {
798 now = CacheCert(cache, sid->peerCert, &sce);
799 }
800
801 set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
802 now = LockSet(cache, set, now);
803 if (now) {
804 PRUint32 next = cache->sidCacheSets[set].next;
805 PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
806
807 /* Write out new cache entry */
808 cache->sidCacheData[ndx] = sce;
809
810 cache->sidCacheSets[set].next =
811 (next + 1) % SID_CACHE_ENTRIES_PER_SET;
812
813 UnlockSet(cache, set);
814 sid->cached = in_server_cache;
815 }
816 }
817 }
818
819 /*
820 ** Although this is static, it is called from ssl via global function pointer
821 ** ssl_sid_uncache. This invalidates the referenced cache entry.
822 */
823 void
ssl_ServerUncacheSessionID(sslSessionID * sid)824 ssl_ServerUncacheSessionID(sslSessionID *sid)
825 {
826 cacheDesc *cache = &globalCache;
827 PRUint8 *sessionID;
828 unsigned int sessionIDLength;
829 PRErrorCode err;
830 PRUint32 set;
831 PRUint32 now;
832 sidCacheEntry *psce;
833
834 if (sid == NULL)
835 return;
836
837 /* Uncaching a SID should never change the error code.
838 ** So save it here and restore it before exiting.
839 */
840 err = PR_GetError();
841
842 sessionID = sid->u.ssl3.sessionID;
843 sessionIDLength = sid->u.ssl3.sessionIDLength;
844 SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
845 "cipherSuite=%d",
846 myPid, sid->cached,
847 sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
848 sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
849 sid->creationTime / PR_USEC_PER_SEC,
850 sid->u.ssl3.cipherSuite));
851 PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
852 set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
853 now = LockSet(cache, set, 0);
854 if (now) {
855 psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
856 if (psce) {
857 psce->valid = 0;
858 }
859 UnlockSet(cache, set);
860 }
861 sid->cached = invalid_cache;
862 PORT_SetError(err);
863 }
864
865 #ifdef XP_OS2
866
867 #define INCL_DOSPROCESS
868 #include <os2.h>
869
870 long
gettid(void)871 gettid(void)
872 {
873 PTIB ptib;
874 PPIB ppib;
875 DosGetInfoBlocks(&ptib, &ppib);
876 return ((long)ptib->tib_ordinal); /* thread id */
877 }
878 #endif
879
880 static void
CloseCache(cacheDesc * cache)881 CloseCache(cacheDesc *cache)
882 {
883 int locks_initialized = cache->numSIDCacheLocksInitialized;
884
885 if (cache->cacheMem) {
886 if (cache->sharedCache) {
887 sidCacheLock *pLock = cache->sidCacheLocks;
888 for (; locks_initialized > 0; --locks_initialized, ++pLock) {
889 /* If everInherited is true, this shared cache was (and may
890 ** still be) in use by multiple processes. We do not wish to
891 ** destroy the mutexes while they are still in use, but we do
892 ** want to free mutex resources associated with this process.
893 */
894 sslMutex_Destroy(&pLock->mutex,
895 cache->sharedCache->everInherited);
896 }
897 }
898 if (cache->shared) {
899 PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
900 } else {
901 PORT_Free(cache->cacheMem);
902 }
903 cache->cacheMem = NULL;
904 }
905 if (cache->cacheMemMap) {
906 PR_CloseFileMap(cache->cacheMemMap);
907 cache->cacheMemMap = NULL;
908 }
909 memset(cache, 0, sizeof *cache);
910 }
911
912 static SECStatus
InitCache(cacheDesc * cache,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries,PRUint32 ssl3_timeout,const char * directory,PRBool shared)913 InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
914 int maxSrvNameCacheEntries, PRUint32 ssl3_timeout,
915 const char *directory, PRBool shared)
916 {
917 ptrdiff_t ptr;
918 sidCacheLock *pLock;
919 char *cacheMem;
920 PRFileMap *cacheMemMap;
921 char *cfn = NULL; /* cache file name */
922 int locks_initialized = 0;
923 int locks_to_initialize = 0;
924 PRUint32 init_time;
925
926 if ((!cache) || (maxCacheEntries < 0) || (!directory)) {
927 PORT_SetError(SEC_ERROR_INVALID_ARGS);
928 return SECFailure;
929 }
930
931 if (cache->cacheMem) {
932 /* Already done */
933 return SECSuccess;
934 }
935
936 /* make sure loser can clean up properly */
937 cache->shared = shared;
938 cache->cacheMem = cacheMem = NULL;
939 cache->cacheMemMap = cacheMemMap = NULL;
940 cache->sharedCache = (cacheDesc *)0;
941
942 cache->numSIDCacheLocksInitialized = 0;
943 cache->nextCertCacheEntry = 0;
944 cache->stopPolling = PR_FALSE;
945 cache->everInherited = PR_FALSE;
946 cache->poller = NULL;
947 cache->mutexTimeout = 0;
948
949 cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
950 : DEF_SID_CACHE_ENTRIES;
951 cache->numSIDCacheSets =
952 SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
953
954 cache->numSIDCacheEntries =
955 cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
956
957 cache->numSIDCacheLocks =
958 PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
959
960 cache->numSIDCacheSetsPerLock =
961 SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
962
963 cache->numCertCacheEntries = (maxCertCacheEntries > 0) ? maxCertCacheEntries
964 : 0;
965 cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ? maxSrvNameCacheEntries
966 : DEF_NAME_CACHE_ENTRIES;
967
968 /* compute size of shared memory, and offsets of all pointers */
969 ptr = 0;
970 cache->cacheMem = (char *)ptr;
971 ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
972
973 cache->sidCacheLocks = (sidCacheLock *)ptr;
974 cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
975 cache->certCacheLock = cache->keyCacheLock + 1;
976 cache->srvNameCacheLock = cache->certCacheLock + 1;
977 ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
978 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
979
980 cache->sidCacheSets = (sidCacheSet *)ptr;
981 ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
982 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
983
984 cache->sidCacheData = (sidCacheEntry *)ptr;
985 ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
986 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
987
988 cache->certCacheData = (certCacheEntry *)ptr;
989 cache->sidCacheSize =
990 (char *)cache->certCacheData - (char *)cache->sidCacheData;
991
992 if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
993 /* This is really a poor way to computer this! */
994 cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
995 if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
996 cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
997 }
998 ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
999 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1000
1001 cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
1002 cache->certCacheSize =
1003 (char *)cache->keyCacheData - (char *)cache->certCacheData;
1004
1005 cache->numKeyCacheEntries = SSL_NUM_WRAP_KEYS * SSL_NUM_WRAP_MECHS;
1006 ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
1007 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1008
1009 cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
1010
1011 cache->ticketKeyNameSuffix = (PRUint8 *)ptr;
1012 ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
1013 SELF_ENCRYPT_KEY_VAR_NAME_LEN);
1014 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1015
1016 cache->ticketEncKey = (encKeyCacheEntry *)ptr;
1017 ptr = (ptrdiff_t)(cache->ticketEncKey + 1);
1018 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1019
1020 cache->ticketMacKey = (encKeyCacheEntry *)ptr;
1021 ptr = (ptrdiff_t)(cache->ticketMacKey + 1);
1022 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1023
1024 cache->ticketKeysValid = (PRUint32 *)ptr;
1025 ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
1026 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1027
1028 cache->srvNameCacheData = (srvNameCacheEntry *)ptr;
1029 cache->srvNameCacheSize =
1030 cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry);
1031 ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries);
1032 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
1033
1034 cache->cacheMemSize = ptr;
1035
1036 if (ssl3_timeout) {
1037 if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
1038 ssl3_timeout = MAX_SSL3_TIMEOUT;
1039 }
1040 if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
1041 ssl3_timeout = MIN_SSL3_TIMEOUT;
1042 }
1043 cache->ssl3Timeout = ssl3_timeout;
1044 } else {
1045 cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
1046 }
1047
1048 if (shared) {
1049 /* Create file names */
1050 #if defined(XP_UNIX) || defined(XP_BEOS)
1051 /* there's some confusion here about whether PR_OpenAnonFileMap wants
1052 ** a directory name or a file name for its first argument.
1053 cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
1054 */
1055 cfn = PR_smprintf("%s", directory);
1056 #elif defined(XP_WIN32)
1057 cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1058 GetCurrentThreadId());
1059 #elif defined(XP_OS2)
1060 cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
1061 gettid());
1062 #else
1063 #error "Don't know how to create file name for this platform!"
1064 #endif
1065 if (!cfn) {
1066 goto loser;
1067 }
1068
1069 /* Create cache */
1070 cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
1071 PR_PROT_READWRITE);
1072
1073 PR_smprintf_free(cfn);
1074 if (!cacheMemMap) {
1075 goto loser;
1076 }
1077
1078 cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
1079 } else {
1080 cacheMem = PORT_Alloc(cache->cacheMemSize);
1081 }
1082
1083 if (!cacheMem) {
1084 goto loser;
1085 }
1086
1087 /* Initialize shared memory. This may not be necessary on all platforms */
1088 memset(cacheMem, 0, cache->cacheMemSize);
1089
1090 /* Copy cache descriptor header into shared memory */
1091 memcpy(cacheMem, cache, sizeof *cache);
1092
1093 /* save private copies of these values */
1094 cache->cacheMemMap = cacheMemMap;
1095 cache->cacheMem = cacheMem;
1096 cache->sharedCache = (cacheDesc *)cacheMem;
1097
1098 /* Fix pointers in our private copy of cache descriptor to point to
1099 ** spaces in shared memory
1100 */
1101 cache->sidCacheLocks = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks);
1102 cache->keyCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheLock);
1103 cache->certCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->certCacheLock);
1104 cache->srvNameCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
1105 cache->sidCacheSets = (sidCacheSet *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheSets);
1106 cache->sidCacheData = (sidCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheData);
1107 cache->certCacheData = (certCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->certCacheData);
1108 cache->keyCacheData = (SSLWrappedSymWrappingKey *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheData);
1109 cache->ticketKeyNameSuffix = (PRUint8 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
1110 cache->ticketEncKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketEncKey);
1111 cache->ticketMacKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketMacKey);
1112 cache->ticketKeysValid = (PRUint32 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid);
1113 cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
1114
1115 /* initialize the locks */
1116 init_time = ssl_CacheNow();
1117 pLock = cache->sidCacheLocks;
1118 for (locks_to_initialize = cache->numSIDCacheLocks + 3;
1119 locks_initialized < locks_to_initialize;
1120 ++locks_initialized, ++pLock) {
1121
1122 SECStatus err = sslMutex_Init(&pLock->mutex, shared);
1123 if (err) {
1124 cache->numSIDCacheLocksInitialized = locks_initialized;
1125 goto loser;
1126 }
1127 pLock->timeStamp = init_time;
1128 pLock->pid = 0;
1129 }
1130 cache->numSIDCacheLocksInitialized = locks_initialized;
1131
1132 return SECSuccess;
1133
1134 loser:
1135 CloseCache(cache);
1136 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1137 return SECFailure;
1138 }
1139
1140 PRUint32
SSL_GetMaxServerCacheLocks(void)1141 SSL_GetMaxServerCacheLocks(void)
1142 {
1143 return ssl_max_sid_cache_locks + 2;
1144 /* The extra two are the cert cache lock and the key cache lock. */
1145 }
1146
1147 SECStatus
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)1148 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
1149 {
1150 /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
1151 ** We'd like to test for a maximum value, but not all platforms' header
1152 ** files provide a symbol or function or other means of determining
1153 ** the maximum, other than trial and error.
1154 */
1155 if (maxLocks < 3) {
1156 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1157 return SECFailure;
1158 }
1159 ssl_max_sid_cache_locks = maxLocks - 2;
1160 /* The extra two are the cert cache lock and the key cache lock. */
1161 return SECSuccess;
1162 }
1163
1164 PR_STATIC_ASSERT(sizeof(sidCacheEntry) % 16 == 0);
1165 PR_STATIC_ASSERT(sizeof(certCacheEntry) == 4096);
1166 PR_STATIC_ASSERT(sizeof(srvNameCacheEntry) == 1072);
1167
1168 static SECStatus
ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc * cache,PRUint32 ssl3_timeout,const char * directory,PRBool shared,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries)1169 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
1170 PRUint32 ssl3_timeout,
1171 const char *directory,
1172 PRBool shared,
1173 int maxCacheEntries,
1174 int maxCertCacheEntries,
1175 int maxSrvNameCacheEntries)
1176 {
1177 SECStatus rv;
1178
1179 rv = ssl_InitSessionCache();
1180 if (rv != SECSuccess) {
1181 return rv;
1182 }
1183
1184 myPid = SSL_GETPID();
1185 if (!directory) {
1186 directory = DEFAULT_CACHE_DIRECTORY;
1187 }
1188 rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
1189 maxSrvNameCacheEntries, ssl3_timeout, directory, shared);
1190 if (rv) {
1191 return SECFailure;
1192 }
1193
1194 ssl_sid_lookup = ServerSessionIDLookup;
1195 return SECSuccess;
1196 }
1197
1198 SECStatus
SSL_ConfigServerSessionIDCacheInstance(cacheDesc * cache,int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,PRBool shared)1199 SSL_ConfigServerSessionIDCacheInstance(cacheDesc *cache,
1200 int maxCacheEntries,
1201 PRUint32 ssl2_timeout,
1202 PRUint32 ssl3_timeout,
1203 const char *directory, PRBool shared)
1204 {
1205 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
1206 ssl3_timeout,
1207 directory,
1208 shared,
1209 maxCacheEntries,
1210 -1, -1);
1211 }
1212
1213 SECStatus
SSL_ConfigServerSessionIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)1214 SSL_ConfigServerSessionIDCache(int maxCacheEntries,
1215 PRUint32 ssl2_timeout,
1216 PRUint32 ssl3_timeout,
1217 const char *directory)
1218 {
1219 ssl_InitSessionCacheLocks(PR_FALSE);
1220 return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
1221 maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
1222 }
1223
1224 SECStatus
SSL_ShutdownServerSessionIDCacheInstance(cacheDesc * cache)1225 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
1226 {
1227 CloseCache(cache);
1228 return SECSuccess;
1229 }
1230
1231 SECStatus
SSL_ShutdownServerSessionIDCache(void)1232 SSL_ShutdownServerSessionIDCache(void)
1233 {
1234 #if defined(XP_UNIX) || defined(XP_BEOS)
1235 /* Stop the thread that polls cache for expired locks on Unix */
1236 StopLockPoller(&globalCache);
1237 #endif
1238 SSL3_ShutdownServerCache();
1239 return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
1240 }
1241
1242 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1243 * if the cache will be shared by multiple processes.
1244 */
1245 static SECStatus
ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl3_timeout,const char * directory,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries)1246 ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl3_timeout,
1247 const char *directory,
1248 int maxCacheEntries,
1249 int maxCertCacheEntries,
1250 int maxSrvNameCacheEntries)
1251 {
1252 char *envValue;
1253 char *inhValue;
1254 cacheDesc *cache = &globalCache;
1255 PRUint32 fmStrLen;
1256 SECStatus result;
1257 PRStatus prStatus;
1258 SECStatus putEnvFailed;
1259 inheritance inherit;
1260 char fmString[PR_FILEMAP_STRING_BUFSIZE];
1261
1262 isMultiProcess = PR_TRUE;
1263 result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
1264 ssl3_timeout, directory, PR_TRUE,
1265 maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
1266 if (result != SECSuccess)
1267 return result;
1268
1269 prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
1270 sizeof fmString, fmString);
1271 if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
1272 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1273 return SECFailure;
1274 }
1275
1276 inherit.cacheMemSize = cache->cacheMemSize;
1277 inherit.fmStrLen = fmStrLen;
1278
1279 inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
1280 if (!inhValue || !strlen(inhValue)) {
1281 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1282 return SECFailure;
1283 }
1284 envValue = PR_smprintf("%s,%s", inhValue, fmString);
1285 if (!envValue || !strlen(envValue)) {
1286 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1287 return SECFailure;
1288 }
1289 PORT_Free(inhValue);
1290
1291 putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
1292 PR_smprintf_free(envValue);
1293 if (putEnvFailed) {
1294 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1295 result = SECFailure;
1296 }
1297
1298 #if defined(XP_UNIX) || defined(XP_BEOS)
1299 /* Launch thread to poll cache for expired locks on Unix */
1300 LaunchLockPoller(cache);
1301 #endif
1302 return result;
1303 }
1304
1305 /* Use this function, instead of SSL_ConfigServerSessionIDCache,
1306 * if the cache will be shared by multiple processes.
1307 */
1308 SECStatus
SSL_ConfigMPServerSIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)1309 SSL_ConfigMPServerSIDCache(int maxCacheEntries,
1310 PRUint32 ssl2_timeout,
1311 PRUint32 ssl3_timeout,
1312 const char *directory)
1313 {
1314 return ssl_ConfigMPServerSIDCacheWithOpt(ssl3_timeout,
1315 directory,
1316 maxCacheEntries,
1317 -1, -1);
1318 }
1319
1320 SECStatus
SSL_ConfigServerSessionIDCacheWithOpt(PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory,int maxCacheEntries,int maxCertCacheEntries,int maxSrvNameCacheEntries,PRBool enableMPCache)1321 SSL_ConfigServerSessionIDCacheWithOpt(
1322 PRUint32 ssl2_timeout,
1323 PRUint32 ssl3_timeout,
1324 const char *directory,
1325 int maxCacheEntries,
1326 int maxCertCacheEntries,
1327 int maxSrvNameCacheEntries,
1328 PRBool enableMPCache)
1329 {
1330 if (!enableMPCache) {
1331 ssl_InitSessionCacheLocks(PR_FALSE);
1332 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
1333 ssl3_timeout, directory, PR_FALSE,
1334 maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
1335 } else {
1336 return ssl_ConfigMPServerSIDCacheWithOpt(ssl3_timeout, directory,
1337 maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
1338 }
1339 }
1340
1341 SECStatus
SSL_InheritMPServerSIDCacheInstance(cacheDesc * cache,const char * envString)1342 SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
1343 {
1344 unsigned char *decoString = NULL;
1345 char *fmString = NULL;
1346 char *myEnvString = NULL;
1347 unsigned int decoLen;
1348 inheritance inherit;
1349 cacheDesc my;
1350 #ifdef WINNT
1351 sidCacheLock *newLocks;
1352 int locks_initialized = 0;
1353 int locks_to_initialize = 0;
1354 #endif
1355 SECStatus status = ssl_InitSessionCache();
1356
1357 if (status != SECSuccess) {
1358 return status;
1359 }
1360
1361 myPid = SSL_GETPID();
1362
1363 /* If this child was created by fork(), and not by exec() on unix,
1364 ** then isMultiProcess will already be set.
1365 ** If not, we'll set it below.
1366 */
1367 if (isMultiProcess) {
1368 if (cache && cache->sharedCache) {
1369 cache->sharedCache->everInherited = PR_TRUE;
1370 }
1371 return SECSuccess; /* already done. */
1372 }
1373
1374 ssl_InitSessionCacheLocks(PR_FALSE);
1375
1376 ssl_sid_lookup = ServerSessionIDLookup;
1377
1378 if (!envString) {
1379 envString = PR_GetEnvSecure(envVarName);
1380 if (!envString) {
1381 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1382 return SECFailure;
1383 }
1384 }
1385 myEnvString = PORT_Strdup(envString);
1386 if (!myEnvString)
1387 return SECFailure;
1388 fmString = strchr(myEnvString, ',');
1389 if (!fmString)
1390 goto loser;
1391 *fmString++ = 0;
1392
1393 decoString = ATOB_AsciiToData(myEnvString, &decoLen);
1394 if (!decoString) {
1395 goto loser;
1396 }
1397 if (decoLen != sizeof inherit) {
1398 goto loser;
1399 }
1400
1401 PORT_Memcpy(&inherit, decoString, sizeof inherit);
1402
1403 if (strlen(fmString) != inherit.fmStrLen) {
1404 goto loser;
1405 }
1406
1407 memset(cache, 0, sizeof *cache);
1408 cache->cacheMemSize = inherit.cacheMemSize;
1409
1410 /* Create cache */
1411 cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
1412 if (!cache->cacheMemMap) {
1413 goto loser;
1414 }
1415 cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
1416 if (!cache->cacheMem) {
1417 goto loser;
1418 }
1419 cache->sharedCache = (cacheDesc *)cache->cacheMem;
1420
1421 if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
1422 goto loser;
1423 }
1424
1425 /* We're now going to overwrite the local cache instance with the
1426 ** shared copy of the cache struct, then update several values in
1427 ** the local cache using the values for cache->cacheMemMap and
1428 ** cache->cacheMem computed just above. So, we copy cache into
1429 ** the automatic variable "my", to preserve the variables while
1430 ** cache is overwritten.
1431 */
1432 my = *cache; /* save values computed above. */
1433 memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
1434
1435 /* Fix pointers in our private copy of cache descriptor to point to
1436 ** spaces in shared memory, whose address is now in "my".
1437 */
1438 cache->sidCacheLocks = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->sidCacheLocks);
1439 cache->keyCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->keyCacheLock);
1440 cache->certCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->certCacheLock);
1441 cache->srvNameCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
1442 cache->sidCacheSets = (sidCacheSet *)(my.cacheMem + (ptrdiff_t)cache->sidCacheSets);
1443 cache->sidCacheData = (sidCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->sidCacheData);
1444 cache->certCacheData = (certCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->certCacheData);
1445 cache->keyCacheData = (SSLWrappedSymWrappingKey *)(my.cacheMem + (ptrdiff_t)cache->keyCacheData);
1446 cache->ticketKeyNameSuffix = (PRUint8 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
1447 cache->ticketEncKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketEncKey);
1448 cache->ticketMacKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketMacKey);
1449 cache->ticketKeysValid = (PRUint32 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeysValid);
1450 cache->srvNameCacheData = (srvNameCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheData);
1451
1452 cache->cacheMemMap = my.cacheMemMap;
1453 cache->cacheMem = my.cacheMem;
1454 cache->sharedCache = (cacheDesc *)cache->cacheMem;
1455
1456 #ifdef WINNT
1457 /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
1458 ** When NT fibers are used in a multi-process server, a second level of
1459 ** locking is needed to prevent a deadlock, in case a fiber acquires the
1460 ** cross-process mutex, yields, and another fiber is later scheduled on
1461 ** the same native thread and tries to acquire the cross-process mutex.
1462 ** We do this by using a PRLock in the sslMutex. However, it is stored in
1463 ** shared memory as part of sidCacheLocks, and we don't want to overwrite
1464 ** the PRLock of the parent process. So we need to make new, private
1465 ** copies of sidCacheLocks before modifying the sslMutex with our own
1466 ** PRLock
1467 */
1468
1469 /* note from jpierre : this should be free'd in child processes when
1470 ** a function is added to delete the SSL session cache in the future.
1471 */
1472 locks_to_initialize = cache->numSIDCacheLocks + 3;
1473 newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
1474 if (!newLocks)
1475 goto loser;
1476 /* copy the old locks */
1477 memcpy(newLocks, cache->sidCacheLocks,
1478 locks_to_initialize * sizeof(sidCacheLock));
1479 cache->sidCacheLocks = newLocks;
1480 /* fix the locks */
1481 for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
1482 /* now, make a local PRLock in this sslMutex for this child process */
1483 SECStatus err;
1484 err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
1485 if (err != SECSuccess) {
1486 cache->numSIDCacheLocksInitialized = locks_initialized;
1487 goto loser;
1488 }
1489 }
1490 cache->numSIDCacheLocksInitialized = locks_initialized;
1491
1492 /* also fix the key and cert cache which use the last 2 lock entries */
1493 cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
1494 cache->certCacheLock = cache->keyCacheLock + 1;
1495 cache->srvNameCacheLock = cache->certCacheLock + 1;
1496 #endif
1497
1498 PORT_Free(myEnvString);
1499 PORT_Free(decoString);
1500
1501 /* mark that we have inherited this. */
1502 cache->sharedCache->everInherited = PR_TRUE;
1503 isMultiProcess = PR_TRUE;
1504
1505 return SECSuccess;
1506
1507 loser:
1508 PORT_Free(myEnvString);
1509 if (decoString)
1510 PORT_Free(decoString);
1511 CloseCache(cache);
1512 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1513 return SECFailure;
1514 }
1515
1516 SECStatus
SSL_InheritMPServerSIDCache(const char * envString)1517 SSL_InheritMPServerSIDCache(const char *envString)
1518 {
1519 return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
1520 }
1521
1522 #if defined(XP_UNIX) || defined(XP_BEOS)
1523
1524 #define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
1525
1526 static void
LockPoller(void * arg)1527 LockPoller(void *arg)
1528 {
1529 cacheDesc *cache = (cacheDesc *)arg;
1530 cacheDesc *sharedCache = cache->sharedCache;
1531 sidCacheLock *pLock;
1532 PRIntervalTime timeout;
1533 PRUint32 now;
1534 PRUint32 then;
1535 int locks_polled = 0;
1536 int locks_to_poll = cache->numSIDCacheLocks + 2;
1537 PRUint32 expiration = cache->mutexTimeout;
1538
1539 timeout = PR_SecondsToInterval(expiration);
1540 while (!sharedCache->stopPolling) {
1541 PR_Sleep(timeout);
1542 if (sharedCache->stopPolling)
1543 break;
1544
1545 now = ssl_CacheNow();
1546 then = now - expiration;
1547 for (pLock = cache->sidCacheLocks, locks_polled = 0;
1548 locks_to_poll > locks_polled && !sharedCache->stopPolling;
1549 ++locks_polled, ++pLock) {
1550 pid_t pid;
1551
1552 if (pLock->timeStamp < then &&
1553 pLock->timeStamp != 0 &&
1554 (pid = pLock->pid) != 0) {
1555
1556 /* maybe we should try the lock? */
1557 int result = kill(pid, 0);
1558 if (result < 0 && errno == ESRCH) {
1559 SECStatus rv;
1560 /* No process exists by that pid any more.
1561 ** Treat this mutex as abandoned.
1562 */
1563 pLock->timeStamp = now;
1564 pLock->pid = 0;
1565 rv = sslMutex_Unlock(&pLock->mutex);
1566 if (rv != SECSuccess) {
1567 /* Now what? */
1568 }
1569 }
1570 }
1571 } /* end of loop over locks */
1572 } /* end of entire polling loop */
1573 }
1574
1575 /* Launch thread to poll cache for expired locks */
1576 static SECStatus
LaunchLockPoller(cacheDesc * cache)1577 LaunchLockPoller(cacheDesc *cache)
1578 {
1579 const char *timeoutString;
1580 PRThread *pollerThread;
1581
1582 cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
1583 timeoutString = PR_GetEnvSecure("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
1584 if (timeoutString) {
1585 long newTime = strtol(timeoutString, 0, 0);
1586 if (newTime == 0)
1587 return SECSuccess; /* application doesn't want poller thread */
1588 if (newTime > 0)
1589 cache->mutexTimeout = (PRUint32)newTime;
1590 /* if error (newTime < 0) ignore it and use default */
1591 }
1592
1593 pollerThread =
1594 PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
1595 PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
1596 if (!pollerThread) {
1597 return SECFailure;
1598 }
1599 cache->poller = pollerThread;
1600 return SECSuccess;
1601 }
1602
1603 /* Stop the thread that polls cache for expired locks */
1604 static SECStatus
StopLockPoller(cacheDesc * cache)1605 StopLockPoller(cacheDesc *cache)
1606 {
1607 if (!cache->poller) {
1608 return SECSuccess;
1609 }
1610 cache->sharedCache->stopPolling = PR_TRUE;
1611 if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
1612 return SECFailure;
1613 }
1614 if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
1615 return SECFailure;
1616 }
1617 cache->poller = NULL;
1618 return SECSuccess;
1619 }
1620 #endif
1621
1622 /************************************************************************
1623 * Code dealing with shared wrapped symmetric wrapping keys below *
1624 ************************************************************************/
1625
1626 /* The asymmetric key we use for wrapping the self-encryption keys. This is a
1627 * global structure that can be initialized without a socket. Access is
1628 * synchronized on the reader-writer lock. This is setup either by calling
1629 * SSL_SetSessionTicketKeyPair() or by configuring a certificate of the
1630 * ssl_auth_rsa_decrypt type. */
1631 static struct {
1632 PRCallOnceType setup;
1633 PRRWLock *lock;
1634 SECKEYPublicKey *pubKey;
1635 SECKEYPrivateKey *privKey;
1636 PRBool configured;
1637 } ssl_self_encrypt_key_pair;
1638
1639 /* The symmetric self-encryption keys. This requires a socket to construct
1640 * and requires that the global structure be initialized before use.
1641 */
1642 static sslSelfEncryptKeys ssl_self_encrypt_keys;
1643
1644 /* Externalize the self encrypt keys. Purely used for testing. */
1645 sslSelfEncryptKeys *
ssl_GetSelfEncryptKeysInt()1646 ssl_GetSelfEncryptKeysInt()
1647 {
1648 return &ssl_self_encrypt_keys;
1649 }
1650
1651 static void
ssl_CleanupSelfEncryptKeyPair()1652 ssl_CleanupSelfEncryptKeyPair()
1653 {
1654 if (ssl_self_encrypt_key_pair.pubKey) {
1655 PORT_Assert(ssl_self_encrypt_key_pair.privKey);
1656 SECKEY_DestroyPublicKey(ssl_self_encrypt_key_pair.pubKey);
1657 SECKEY_DestroyPrivateKey(ssl_self_encrypt_key_pair.privKey);
1658 }
1659 }
1660
1661 void
ssl_ResetSelfEncryptKeys()1662 ssl_ResetSelfEncryptKeys()
1663 {
1664 if (ssl_self_encrypt_keys.encKey) {
1665 PORT_Assert(ssl_self_encrypt_keys.macKey);
1666 PK11_FreeSymKey(ssl_self_encrypt_keys.encKey);
1667 PK11_FreeSymKey(ssl_self_encrypt_keys.macKey);
1668 }
1669 PORT_Memset(&ssl_self_encrypt_keys, 0,
1670 sizeof(ssl_self_encrypt_keys));
1671 }
1672
1673 static SECStatus
ssl_SelfEncryptShutdown(void * appData,void * nssData)1674 ssl_SelfEncryptShutdown(void *appData, void *nssData)
1675 {
1676 ssl_CleanupSelfEncryptKeyPair();
1677 PR_DestroyRWLock(ssl_self_encrypt_key_pair.lock);
1678 PORT_Memset(&ssl_self_encrypt_key_pair, 0,
1679 sizeof(ssl_self_encrypt_key_pair));
1680
1681 ssl_ResetSelfEncryptKeys();
1682 return SECSuccess;
1683 }
1684
1685 static PRStatus
ssl_SelfEncryptSetup(void)1686 ssl_SelfEncryptSetup(void)
1687 {
1688 SECStatus rv = NSS_RegisterShutdown(ssl_SelfEncryptShutdown, NULL);
1689 if (rv != SECSuccess) {
1690 return PR_FAILURE;
1691 }
1692 ssl_self_encrypt_key_pair.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL);
1693 if (!ssl_self_encrypt_key_pair.lock) {
1694 return PR_FAILURE;
1695 }
1696 return PR_SUCCESS;
1697 }
1698
1699 /* Configure a self encryption key pair. |explicitConfig| is set to true for
1700 * calls to SSL_SetSessionTicketKeyPair(), false for implicit configuration.
1701 * This assumes that the setup has been run. */
1702 static SECStatus
ssl_SetSelfEncryptKeyPair(SECKEYPublicKey * pubKey,SECKEYPrivateKey * privKey,PRBool explicitConfig)1703 ssl_SetSelfEncryptKeyPair(SECKEYPublicKey *pubKey,
1704 SECKEYPrivateKey *privKey,
1705 PRBool explicitConfig)
1706 {
1707 SECKEYPublicKey *pubKeyCopy, *oldPubKey;
1708 SECKEYPrivateKey *privKeyCopy, *oldPrivKey;
1709
1710 PORT_Assert(ssl_self_encrypt_key_pair.lock);
1711 pubKeyCopy = SECKEY_CopyPublicKey(pubKey);
1712 privKeyCopy = SECKEY_CopyPrivateKey(privKey);
1713
1714 if (!pubKeyCopy || !privKeyCopy) {
1715 SECKEY_DestroyPublicKey(pubKeyCopy);
1716 SECKEY_DestroyPrivateKey(privKeyCopy);
1717 PORT_SetError(SEC_ERROR_NO_MEMORY);
1718 return SECFailure;
1719 }
1720
1721 PR_RWLock_Wlock(ssl_self_encrypt_key_pair.lock);
1722 oldPubKey = ssl_self_encrypt_key_pair.pubKey;
1723 oldPrivKey = ssl_self_encrypt_key_pair.privKey;
1724 ssl_self_encrypt_key_pair.pubKey = pubKeyCopy;
1725 ssl_self_encrypt_key_pair.privKey = privKeyCopy;
1726 ssl_self_encrypt_key_pair.configured = explicitConfig;
1727 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock);
1728
1729 if (oldPubKey) {
1730 PORT_Assert(oldPrivKey);
1731 SECKEY_DestroyPublicKey(oldPubKey);
1732 SECKEY_DestroyPrivateKey(oldPrivKey);
1733 }
1734
1735 return SECSuccess;
1736 }
1737
1738 /* This is really the self-encryption keys but it has the
1739 * wrong name for historical API stability reasons. */
1740 SECStatus
SSL_SetSessionTicketKeyPair(SECKEYPublicKey * pubKey,SECKEYPrivateKey * privKey)1741 SSL_SetSessionTicketKeyPair(SECKEYPublicKey *pubKey,
1742 SECKEYPrivateKey *privKey)
1743 {
1744 if (SECKEY_GetPublicKeyType(pubKey) != rsaKey ||
1745 SECKEY_GetPrivateKeyType(privKey) != rsaKey) {
1746 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1747 return SECFailure;
1748 }
1749
1750 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup,
1751 &ssl_SelfEncryptSetup)) {
1752 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1753 return SECFailure;
1754 }
1755
1756 return ssl_SetSelfEncryptKeyPair(pubKey, privKey, PR_TRUE);
1757 }
1758
1759 /* When configuring a server cert, we should save the RSA key in case it is
1760 * needed for self-encryption. This saves the latest copy, unless there has
1761 * been an explicit call to SSL_SetSessionTicketKeyPair(). */
1762 SECStatus
ssl_MaybeSetSelfEncryptKeyPair(const sslKeyPair * keyPair)1763 ssl_MaybeSetSelfEncryptKeyPair(const sslKeyPair *keyPair)
1764 {
1765 PRBool configured;
1766
1767 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup,
1768 &ssl_SelfEncryptSetup)) {
1769 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1770 return SECFailure;
1771 }
1772
1773 PR_RWLock_Rlock(ssl_self_encrypt_key_pair.lock);
1774 configured = ssl_self_encrypt_key_pair.configured;
1775 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock);
1776 if (configured) {
1777 return SECSuccess;
1778 }
1779 return ssl_SetSelfEncryptKeyPair(keyPair->pubKey,
1780 keyPair->privKey, PR_FALSE);
1781 }
1782
1783 static SECStatus
ssl_GetSelfEncryptKeyPair(SECKEYPublicKey ** pubKey,SECKEYPrivateKey ** privKey)1784 ssl_GetSelfEncryptKeyPair(SECKEYPublicKey **pubKey,
1785 SECKEYPrivateKey **privKey)
1786 {
1787 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup,
1788 &ssl_SelfEncryptSetup)) {
1789 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1790 return SECFailure;
1791 }
1792
1793 SECKEYPublicKey *pubKeyCopy = NULL;
1794 SECKEYPrivateKey *privKeyCopy = NULL;
1795 PRBool noKey = PR_FALSE;
1796
1797 PR_RWLock_Rlock(ssl_self_encrypt_key_pair.lock);
1798 if (ssl_self_encrypt_key_pair.pubKey && ssl_self_encrypt_key_pair.privKey) {
1799 pubKeyCopy = SECKEY_CopyPublicKey(ssl_self_encrypt_key_pair.pubKey);
1800 privKeyCopy = SECKEY_CopyPrivateKey(ssl_self_encrypt_key_pair.privKey);
1801 } else {
1802 noKey = PR_TRUE;
1803 }
1804 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock);
1805
1806 if (noKey) {
1807 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1808 return SECFailure;
1809 }
1810
1811 if (!pubKeyCopy || !privKeyCopy) {
1812 SECKEY_DestroyPublicKey(pubKeyCopy);
1813 SECKEY_DestroyPrivateKey(privKeyCopy);
1814 PORT_SetError(SEC_ERROR_NO_MEMORY);
1815 return SECFailure;
1816 }
1817
1818 *pubKey = pubKeyCopy;
1819 *privKey = privKeyCopy;
1820 return SECSuccess;
1821 }
1822
1823 static PRBool
1824 ssl_GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName,
1825 PK11SymKey **aesKey, PK11SymKey **macKey);
1826
1827 static PRStatus
ssl_GenerateSelfEncryptKeysOnce(void * arg)1828 ssl_GenerateSelfEncryptKeysOnce(void *arg)
1829 {
1830 SECStatus rv;
1831
1832 /* Get a copy of the session keys from shared memory. */
1833 PORT_Memcpy(ssl_self_encrypt_keys.keyName,
1834 SELF_ENCRYPT_KEY_NAME_PREFIX,
1835 sizeof(SELF_ENCRYPT_KEY_NAME_PREFIX));
1836 /* This function calls ssl_GetSelfEncryptKeyPair(), which initializes the
1837 * key pair stuff. That allows this to use the same shutdown function. */
1838 rv = ssl_GenerateSelfEncryptKeys(arg, ssl_self_encrypt_keys.keyName,
1839 &ssl_self_encrypt_keys.encKey,
1840 &ssl_self_encrypt_keys.macKey);
1841 if (rv != SECSuccess) {
1842 return PR_FAILURE;
1843 }
1844
1845 return PR_SUCCESS;
1846 }
1847
1848 SECStatus
ssl_GetSelfEncryptKeys(sslSocket * ss,PRUint8 * keyName,PK11SymKey ** encKey,PK11SymKey ** macKey)1849 ssl_GetSelfEncryptKeys(sslSocket *ss, PRUint8 *keyName,
1850 PK11SymKey **encKey, PK11SymKey **macKey)
1851 {
1852 if (PR_SUCCESS != PR_CallOnceWithArg(&ssl_self_encrypt_keys.setup,
1853 &ssl_GenerateSelfEncryptKeysOnce,
1854 ss->pkcs11PinArg)) {
1855 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1856 return SECFailure;
1857 }
1858
1859 if (!ssl_self_encrypt_keys.encKey || !ssl_self_encrypt_keys.macKey) {
1860 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1861 return SECFailure;
1862 }
1863
1864 PORT_Memcpy(keyName, ssl_self_encrypt_keys.keyName,
1865 sizeof(ssl_self_encrypt_keys.keyName));
1866 *encKey = ssl_self_encrypt_keys.encKey;
1867 *macKey = ssl_self_encrypt_keys.macKey;
1868 return SECSuccess;
1869 }
1870
1871 /* If lockTime is zero, it implies that the lock is not held, and must be
1872 * aquired here.
1873 */
1874 static SECStatus
getSvrWrappingKey(unsigned int symWrapMechIndex,unsigned int wrapKeyIndex,SSLWrappedSymWrappingKey * wswk,cacheDesc * cache,PRUint32 lockTime)1875 getSvrWrappingKey(unsigned int symWrapMechIndex,
1876 unsigned int wrapKeyIndex,
1877 SSLWrappedSymWrappingKey *wswk,
1878 cacheDesc *cache,
1879 PRUint32 lockTime)
1880 {
1881 PRUint32 ndx = (wrapKeyIndex * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
1882 SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx;
1883 PRUint32 now = 0;
1884 PRBool rv = SECFailure;
1885
1886 if (!cache->cacheMem) { /* cache is uninitialized */
1887 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
1888 return SECFailure;
1889 }
1890 if (!lockTime) {
1891 now = LockSidCacheLock(cache->keyCacheLock, 0);
1892 if (!now) {
1893 return SECFailure;
1894 }
1895 }
1896 if (pwswk->wrapKeyIndex == wrapKeyIndex &&
1897 pwswk->wrapMechIndex == symWrapMechIndex &&
1898 pwswk->wrappedSymKeyLen != 0) {
1899 *wswk = *pwswk;
1900 rv = SECSuccess;
1901 }
1902 if (now) {
1903 UnlockSidCacheLock(cache->keyCacheLock);
1904 }
1905 return rv;
1906 }
1907
1908 SECStatus
ssl_GetWrappingKey(unsigned int wrapMechIndex,unsigned int wrapKeyIndex,SSLWrappedSymWrappingKey * wswk)1909 ssl_GetWrappingKey(unsigned int wrapMechIndex,
1910 unsigned int wrapKeyIndex,
1911 SSLWrappedSymWrappingKey *wswk)
1912 {
1913 PORT_Assert(wrapMechIndex < SSL_NUM_WRAP_MECHS);
1914 PORT_Assert(wrapKeyIndex < SSL_NUM_WRAP_KEYS);
1915 if (wrapMechIndex >= SSL_NUM_WRAP_MECHS ||
1916 wrapKeyIndex >= SSL_NUM_WRAP_KEYS) {
1917 PORT_SetError(SEC_ERROR_INVALID_ARGS);
1918 return SECFailure;
1919 }
1920
1921 return getSvrWrappingKey(wrapMechIndex, wrapKeyIndex, wswk,
1922 &globalCache, 0);
1923 }
1924
1925 /* Wrap and cache a session ticket key. */
1926 static SECStatus
WrapSelfEncryptKey(SECKEYPublicKey * svrPubKey,PK11SymKey * symKey,const char * keyName,encKeyCacheEntry * cacheEntry)1927 WrapSelfEncryptKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey,
1928 const char *keyName, encKeyCacheEntry *cacheEntry)
1929 {
1930 SECItem wrappedKey = { siBuffer, NULL, 0 };
1931
1932 wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
1933 PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes));
1934 if (wrappedKey.len > sizeof(cacheEntry->bytes))
1935 return PR_FALSE;
1936 wrappedKey.data = cacheEntry->bytes;
1937
1938 if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey) !=
1939 SECSuccess) {
1940 SSL_DBG(("%d: SSL[%s]: Unable to wrap self encrypt key %s.",
1941 SSL_GETPID(), "unknown", keyName));
1942 return SECFailure;
1943 }
1944 cacheEntry->length = wrappedKey.len;
1945 return SECSuccess;
1946 }
1947
1948 static SECStatus
GenerateSelfEncryptKeys(void * pwArg,PRUint8 * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)1949 GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName, PK11SymKey **aesKey,
1950 PK11SymKey **macKey)
1951 {
1952 PK11SlotInfo *slot;
1953 CK_MECHANISM_TYPE mechanismArray[2];
1954 PK11SymKey *aesKeyTmp = NULL;
1955 PK11SymKey *macKeyTmp = NULL;
1956 cacheDesc *cache = &globalCache;
1957 PRUint8 ticketKeyNameSuffixLocal[SELF_ENCRYPT_KEY_VAR_NAME_LEN];
1958 PRUint8 *ticketKeyNameSuffix;
1959
1960 if (!cache->cacheMem) {
1961 /* cache is not initalized. Use stack buffer */
1962 ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
1963 } else {
1964 ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
1965 }
1966
1967 if (PK11_GenerateRandom(ticketKeyNameSuffix,
1968 SELF_ENCRYPT_KEY_VAR_NAME_LEN) !=
1969 SECSuccess) {
1970 SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
1971 SSL_GETPID(), "unknown"));
1972 return SECFailure;
1973 }
1974
1975 mechanismArray[0] = CKM_AES_CBC;
1976 mechanismArray[1] = CKM_SHA256_HMAC;
1977
1978 slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
1979 if (slot) {
1980 aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
1981 AES_256_KEY_LENGTH, pwArg);
1982 macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
1983 SHA256_LENGTH, pwArg);
1984 PK11_FreeSlot(slot);
1985 }
1986
1987 if (aesKeyTmp == NULL || macKeyTmp == NULL) {
1988 SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
1989 SSL_GETPID(), "unknown"));
1990 goto loser;
1991 }
1992 PORT_Memcpy(keyName, ticketKeyNameSuffix, SELF_ENCRYPT_KEY_VAR_NAME_LEN);
1993 *aesKey = aesKeyTmp;
1994 *macKey = macKeyTmp;
1995 return SECSuccess;
1996
1997 loser:
1998 if (aesKeyTmp)
1999 PK11_FreeSymKey(aesKeyTmp);
2000 if (macKeyTmp)
2001 PK11_FreeSymKey(macKeyTmp);
2002 return SECFailure;
2003 }
2004
2005 static SECStatus
GenerateAndWrapSelfEncryptKeys(SECKEYPublicKey * svrPubKey,void * pwArg,PRUint8 * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)2006 GenerateAndWrapSelfEncryptKeys(SECKEYPublicKey *svrPubKey, void *pwArg,
2007 PRUint8 *keyName, PK11SymKey **aesKey,
2008 PK11SymKey **macKey)
2009 {
2010 PK11SymKey *aesKeyTmp = NULL;
2011 PK11SymKey *macKeyTmp = NULL;
2012 cacheDesc *cache = &globalCache;
2013 SECStatus rv;
2014
2015 rv = GenerateSelfEncryptKeys(pwArg, keyName, &aesKeyTmp, &macKeyTmp);
2016 if (rv != SECSuccess) {
2017 return SECFailure;
2018 }
2019
2020 if (cache->cacheMem) {
2021 /* Export the keys to the shared cache in wrapped form. */
2022 rv = WrapSelfEncryptKey(svrPubKey, aesKeyTmp, "enc key", cache->ticketEncKey);
2023 if (rv != SECSuccess) {
2024 goto loser;
2025 }
2026 rv = WrapSelfEncryptKey(svrPubKey, macKeyTmp, "mac key", cache->ticketMacKey);
2027 if (rv != SECSuccess) {
2028 goto loser;
2029 }
2030 }
2031 *aesKey = aesKeyTmp;
2032 *macKey = macKeyTmp;
2033 return SECSuccess;
2034
2035 loser:
2036 PK11_FreeSymKey(aesKeyTmp);
2037 PK11_FreeSymKey(macKeyTmp);
2038 return SECFailure;
2039 }
2040
2041 static SECStatus
UnwrapCachedSelfEncryptKeys(SECKEYPrivateKey * svrPrivKey,PRUint8 * keyName,PK11SymKey ** aesKey,PK11SymKey ** macKey)2042 UnwrapCachedSelfEncryptKeys(SECKEYPrivateKey *svrPrivKey, PRUint8 *keyName,
2043 PK11SymKey **aesKey, PK11SymKey **macKey)
2044 {
2045 SECItem wrappedKey = { siBuffer, NULL, 0 };
2046 PK11SymKey *aesKeyTmp = NULL;
2047 PK11SymKey *macKeyTmp = NULL;
2048 cacheDesc *cache = &globalCache;
2049
2050 wrappedKey.data = cache->ticketEncKey->bytes;
2051 wrappedKey.len = cache->ticketEncKey->length;
2052 PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes));
2053 aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
2054 CKM_AES_CBC, CKA_DECRYPT, 0);
2055
2056 wrappedKey.data = cache->ticketMacKey->bytes;
2057 wrappedKey.len = cache->ticketMacKey->length;
2058 PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes));
2059 macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
2060 CKM_SHA256_HMAC, CKA_SIGN, 0);
2061
2062 if (aesKeyTmp == NULL || macKeyTmp == NULL) {
2063 SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
2064 SSL_GETPID(), "unknown"));
2065 goto loser;
2066 }
2067 SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
2068 SSL_GETPID(), "unknown"));
2069
2070 PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
2071 SELF_ENCRYPT_KEY_VAR_NAME_LEN);
2072 *aesKey = aesKeyTmp;
2073 *macKey = macKeyTmp;
2074 return SECSuccess;
2075
2076 loser:
2077 if (aesKeyTmp)
2078 PK11_FreeSymKey(aesKeyTmp);
2079 if (macKeyTmp)
2080 PK11_FreeSymKey(macKeyTmp);
2081 return SECFailure;
2082 }
2083
2084 static SECStatus
ssl_GenerateSelfEncryptKeys(void * pwArg,PRUint8 * keyName,PK11SymKey ** encKey,PK11SymKey ** macKey)2085 ssl_GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName,
2086 PK11SymKey **encKey, PK11SymKey **macKey)
2087 {
2088 SECKEYPrivateKey *svrPrivKey = NULL;
2089 SECKEYPublicKey *svrPubKey = NULL;
2090 PRUint32 now;
2091 cacheDesc *cache = &globalCache;
2092
2093 SECStatus rv = ssl_GetSelfEncryptKeyPair(&svrPubKey, &svrPrivKey);
2094 if (rv != SECSuccess || !cache->cacheMem) {
2095 /* No key pair for wrapping, or the cache is uninitialized. Generate
2096 * keys and return them without caching. */
2097 rv = GenerateSelfEncryptKeys(pwArg, keyName, encKey, macKey);
2098 } else {
2099 now = LockSidCacheLock(cache->keyCacheLock, 0);
2100 if (!now) {
2101 goto loser;
2102 }
2103
2104 if (*(cache->ticketKeysValid)) {
2105 rv = UnwrapCachedSelfEncryptKeys(svrPrivKey, keyName, encKey, macKey);
2106 } else {
2107 /* Keys do not exist, create them. */
2108 rv = GenerateAndWrapSelfEncryptKeys(svrPubKey, pwArg, keyName,
2109 encKey, macKey);
2110 if (rv == SECSuccess) {
2111 *(cache->ticketKeysValid) = 1;
2112 }
2113 }
2114 UnlockSidCacheLock(cache->keyCacheLock);
2115 }
2116 SECKEY_DestroyPublicKey(svrPubKey);
2117 SECKEY_DestroyPrivateKey(svrPrivKey);
2118 return rv;
2119
2120 loser:
2121 UnlockSidCacheLock(cache->keyCacheLock);
2122 SECKEY_DestroyPublicKey(svrPubKey);
2123 SECKEY_DestroyPrivateKey(svrPrivKey);
2124 return SECFailure;
2125 }
2126
2127 /* The caller passes in the new value it wants
2128 * to set. This code tests the wrapped sym key entry in the shared memory.
2129 * If it is uninitialized, this function writes the caller's value into
2130 * the disk entry, and returns false.
2131 * Otherwise, it overwrites the caller's wswk with the value obtained from
2132 * the disk, and returns PR_TRUE.
2133 * This is all done while holding the locks/mutexes necessary to make
2134 * the operation atomic.
2135 */
2136 SECStatus
ssl_SetWrappingKey(SSLWrappedSymWrappingKey * wswk)2137 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
2138 {
2139 cacheDesc *cache = &globalCache;
2140 PRBool rv = SECFailure;
2141 PRUint32 ndx;
2142 PRUint32 now;
2143 SSLWrappedSymWrappingKey myWswk;
2144
2145 if (!cache->cacheMem) { /* cache is uninitialized */
2146 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
2147 return SECFailure;
2148 }
2149
2150 PORT_Assert(wswk->wrapMechIndex < SSL_NUM_WRAP_MECHS);
2151 PORT_Assert(wswk->wrapKeyIndex < SSL_NUM_WRAP_KEYS);
2152 if (wswk->wrapMechIndex >= SSL_NUM_WRAP_MECHS ||
2153 wswk->wrapKeyIndex >= SSL_NUM_WRAP_KEYS) {
2154 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
2155 return SECFailure;
2156 }
2157
2158 ndx = (wswk->wrapKeyIndex * SSL_NUM_WRAP_MECHS) + wswk->wrapMechIndex;
2159 PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
2160
2161 now = LockSidCacheLock(cache->keyCacheLock, 0);
2162 if (!now) {
2163 return SECFailure;
2164 }
2165 rv = getSvrWrappingKey(wswk->wrapMechIndex, wswk->wrapKeyIndex,
2166 &myWswk, cache, now);
2167 if (rv == SECSuccess) {
2168 /* we found it on disk, copy it out to the caller. */
2169 PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
2170 } else {
2171 /* Wasn't on disk, and we're still holding the lock, so write it. */
2172 cache->keyCacheData[ndx] = *wswk;
2173 }
2174 UnlockSidCacheLock(cache->keyCacheLock);
2175 return rv;
2176 }
2177
2178 #else /* MAC version or other platform */
2179
2180 #include "seccomon.h"
2181 #include "cert.h"
2182 #include "ssl.h"
2183 #include "sslimpl.h"
2184
2185 SECStatus
SSL_ConfigServerSessionIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)2186 SSL_ConfigServerSessionIDCache(int maxCacheEntries,
2187 PRUint32 ssl2_timeout,
2188 PRUint32 ssl3_timeout,
2189 const char *directory)
2190 {
2191 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
2192 return SECFailure;
2193 }
2194
2195 SECStatus
SSL_ConfigMPServerSIDCache(int maxCacheEntries,PRUint32 ssl2_timeout,PRUint32 ssl3_timeout,const char * directory)2196 SSL_ConfigMPServerSIDCache(int maxCacheEntries,
2197 PRUint32 ssl2_timeout,
2198 PRUint32 ssl3_timeout,
2199 const char *directory)
2200 {
2201 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
2202 return SECFailure;
2203 }
2204
2205 SECStatus
SSL_InheritMPServerSIDCache(const char * envString)2206 SSL_InheritMPServerSIDCache(const char *envString)
2207 {
2208 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
2209 return SECFailure;
2210 }
2211
2212 SECStatus
ssl_GetWrappingKey(unsigned int wrapMechIndex,unsigned int wrapKeyIndex,SSLWrappedSymWrappingKey * wswk)2213 ssl_GetWrappingKey(unsigned int wrapMechIndex,
2214 unsigned int wrapKeyIndex,
2215 SSLWrappedSymWrappingKey *wswk)
2216 {
2217 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
2218 return SECFailure;
2219 }
2220
2221 /* This is a kind of test-and-set. The caller passes in the new value it wants
2222 * to set. This code tests the wrapped sym key entry in the shared memory.
2223 * If it is uninitialized, this function writes the caller's value into
2224 * the disk entry, and returns false.
2225 * Otherwise, it overwrites the caller's wswk with the value obtained from
2226 * the disk, and returns PR_TRUE.
2227 * This is all done while holding the locks/mutexes necessary to make
2228 * the operation atomic.
2229 */
2230 SECStatus
ssl_SetWrappingKey(SSLWrappedSymWrappingKey * wswk)2231 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
2232 {
2233 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
2234 return SECFailure;
2235 }
2236
2237 PRUint32
SSL_GetMaxServerCacheLocks(void)2238 SSL_GetMaxServerCacheLocks(void)
2239 {
2240 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
2241 return -1;
2242 }
2243
2244 SECStatus
SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)2245 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
2246 {
2247 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
2248 return SECFailure;
2249 }
2250
2251 #endif /* XP_UNIX || XP_WIN32 */
2252