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 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 293 ssl_CacheNow() 294 { 295 return PR_Now() / PR_USEC_PER_SEC; 296 } 297 298 static PRUint32 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 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 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 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 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 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 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 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 * 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 1225 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache) 1226 { 1227 CloseCache(cache); 1228 return SECSuccess; 1229 } 1230 1231 SECStatus 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 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 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 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 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 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 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 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 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 * 1646 ssl_GetSelfEncryptKeysInt() 1647 { 1648 return &ssl_self_encrypt_keys; 1649 } 1650 1651 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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