sslsnce.c (74232B)
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) 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) 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 #else 241 #define MAX_SID_CACHE_LOCKS 256 242 #endif 243 244 #define SID_HOWMANY(val, size) (((val) + ((size)-1)) / (size)) 245 #define SID_ROUNDUP(val, size) ((size)*SID_HOWMANY((val), (size))) 246 247 static sslPID myPid; 248 static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS; 249 250 /* forward static function declarations */ 251 static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, 252 unsigned nl); 253 #if defined(XP_UNIX) 254 static SECStatus LaunchLockPoller(cacheDesc *cache); 255 static SECStatus StopLockPoller(cacheDesc *cache); 256 #endif 257 258 struct inheritanceStr { 259 PRUint32 cacheMemSize; 260 PRUint32 fmStrLen; 261 }; 262 263 typedef struct inheritanceStr inheritance; 264 265 #if defined(_WIN32) 266 267 #define DEFAULT_CACHE_DIRECTORY "\\temp" 268 269 #endif /* _win32 */ 270 271 #if defined(XP_UNIX) 272 273 #define DEFAULT_CACHE_DIRECTORY "/tmp" 274 275 #endif /* XP_UNIX */ 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 static void 866 CloseCache(cacheDesc *cache) 867 { 868 int locks_initialized = cache->numSIDCacheLocksInitialized; 869 870 if (cache->cacheMem) { 871 if (cache->sharedCache) { 872 sidCacheLock *pLock = cache->sidCacheLocks; 873 for (; locks_initialized > 0; --locks_initialized, ++pLock) { 874 /* If everInherited is true, this shared cache was (and may 875 ** still be) in use by multiple processes. We do not wish to 876 ** destroy the mutexes while they are still in use, but we do 877 ** want to free mutex resources associated with this process. 878 */ 879 sslMutex_Destroy(&pLock->mutex, 880 cache->sharedCache->everInherited); 881 } 882 } 883 if (cache->shared) { 884 PR_MemUnmap(cache->cacheMem, cache->cacheMemSize); 885 } else { 886 PORT_Free(cache->cacheMem); 887 } 888 cache->cacheMem = NULL; 889 } 890 if (cache->cacheMemMap) { 891 PR_CloseFileMap(cache->cacheMemMap); 892 cache->cacheMemMap = NULL; 893 } 894 memset(cache, 0, sizeof *cache); 895 } 896 897 static SECStatus 898 InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries, 899 int maxSrvNameCacheEntries, PRUint32 ssl3_timeout, 900 const char *directory, PRBool shared) 901 { 902 ptrdiff_t ptr; 903 sidCacheLock *pLock; 904 char *cacheMem; 905 PRFileMap *cacheMemMap; 906 char *cfn = NULL; /* cache file name */ 907 int locks_initialized = 0; 908 int locks_to_initialize = 0; 909 PRUint32 init_time; 910 911 if ((!cache) || (maxCacheEntries < 0) || (!directory)) { 912 PORT_SetError(SEC_ERROR_INVALID_ARGS); 913 return SECFailure; 914 } 915 916 if (cache->cacheMem) { 917 /* Already done */ 918 return SECSuccess; 919 } 920 921 /* make sure loser can clean up properly */ 922 cache->shared = shared; 923 cache->cacheMem = cacheMem = NULL; 924 cache->cacheMemMap = cacheMemMap = NULL; 925 cache->sharedCache = (cacheDesc *)0; 926 927 cache->numSIDCacheLocksInitialized = 0; 928 cache->nextCertCacheEntry = 0; 929 cache->stopPolling = PR_FALSE; 930 cache->everInherited = PR_FALSE; 931 cache->poller = NULL; 932 cache->mutexTimeout = 0; 933 934 cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries 935 : DEF_SID_CACHE_ENTRIES; 936 cache->numSIDCacheSets = 937 SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET); 938 939 cache->numSIDCacheEntries = 940 cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET; 941 942 cache->numSIDCacheLocks = 943 PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks); 944 945 cache->numSIDCacheSetsPerLock = 946 SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks); 947 948 cache->numCertCacheEntries = (maxCertCacheEntries > 0) ? maxCertCacheEntries 949 : 0; 950 cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ? maxSrvNameCacheEntries 951 : DEF_NAME_CACHE_ENTRIES; 952 953 /* compute size of shared memory, and offsets of all pointers */ 954 ptr = 0; 955 cache->cacheMem = (char *)ptr; 956 ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT); 957 958 cache->sidCacheLocks = (sidCacheLock *)ptr; 959 cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks; 960 cache->certCacheLock = cache->keyCacheLock + 1; 961 cache->srvNameCacheLock = cache->certCacheLock + 1; 962 ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1); 963 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 964 965 cache->sidCacheSets = (sidCacheSet *)ptr; 966 ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets); 967 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 968 969 cache->sidCacheData = (sidCacheEntry *)ptr; 970 ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries); 971 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 972 973 cache->certCacheData = (certCacheEntry *)ptr; 974 cache->sidCacheSize = 975 (char *)cache->certCacheData - (char *)cache->sidCacheData; 976 977 if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) { 978 /* This is really a poor way to computer this! */ 979 cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry); 980 if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) 981 cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES; 982 } 983 ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries); 984 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 985 986 cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr; 987 cache->certCacheSize = 988 (char *)cache->keyCacheData - (char *)cache->certCacheData; 989 990 cache->numKeyCacheEntries = SSL_NUM_WRAP_KEYS * SSL_NUM_WRAP_MECHS; 991 ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries); 992 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 993 994 cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData; 995 996 cache->ticketKeyNameSuffix = (PRUint8 *)ptr; 997 ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix + 998 SELF_ENCRYPT_KEY_VAR_NAME_LEN); 999 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 1000 1001 cache->ticketEncKey = (encKeyCacheEntry *)ptr; 1002 ptr = (ptrdiff_t)(cache->ticketEncKey + 1); 1003 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 1004 1005 cache->ticketMacKey = (encKeyCacheEntry *)ptr; 1006 ptr = (ptrdiff_t)(cache->ticketMacKey + 1); 1007 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 1008 1009 cache->ticketKeysValid = (PRUint32 *)ptr; 1010 ptr = (ptrdiff_t)(cache->ticketKeysValid + 1); 1011 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 1012 1013 cache->srvNameCacheData = (srvNameCacheEntry *)ptr; 1014 cache->srvNameCacheSize = 1015 cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry); 1016 ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries); 1017 ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); 1018 1019 cache->cacheMemSize = ptr; 1020 1021 if (ssl3_timeout) { 1022 if (ssl3_timeout > MAX_SSL3_TIMEOUT) { 1023 ssl3_timeout = MAX_SSL3_TIMEOUT; 1024 } 1025 if (ssl3_timeout < MIN_SSL3_TIMEOUT) { 1026 ssl3_timeout = MIN_SSL3_TIMEOUT; 1027 } 1028 cache->ssl3Timeout = ssl3_timeout; 1029 } else { 1030 cache->ssl3Timeout = DEF_SSL3_TIMEOUT; 1031 } 1032 1033 if (shared) { 1034 /* Create file names */ 1035 #if defined(XP_UNIX) 1036 /* there's some confusion here about whether PR_OpenAnonFileMap wants 1037 ** a directory name or a file name for its first argument. 1038 cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid); 1039 */ 1040 cfn = PR_smprintf("%s", directory); 1041 #elif defined(XP_WIN32) 1042 cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid, 1043 GetCurrentThreadId()); 1044 #else 1045 #error "Don't know how to create file name for this platform!" 1046 #endif 1047 if (!cfn) { 1048 goto loser; 1049 } 1050 1051 /* Create cache */ 1052 cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize, 1053 PR_PROT_READWRITE); 1054 1055 PR_smprintf_free(cfn); 1056 if (!cacheMemMap) { 1057 goto loser; 1058 } 1059 1060 cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize); 1061 } else { 1062 cacheMem = PORT_Alloc(cache->cacheMemSize); 1063 } 1064 1065 if (!cacheMem) { 1066 goto loser; 1067 } 1068 1069 /* Initialize shared memory. This may not be necessary on all platforms */ 1070 memset(cacheMem, 0, cache->cacheMemSize); 1071 1072 /* Copy cache descriptor header into shared memory */ 1073 memcpy(cacheMem, cache, sizeof *cache); 1074 1075 /* save private copies of these values */ 1076 cache->cacheMemMap = cacheMemMap; 1077 cache->cacheMem = cacheMem; 1078 cache->sharedCache = (cacheDesc *)cacheMem; 1079 1080 /* Fix pointers in our private copy of cache descriptor to point to 1081 ** spaces in shared memory 1082 */ 1083 cache->sidCacheLocks = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks); 1084 cache->keyCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheLock); 1085 cache->certCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->certCacheLock); 1086 cache->srvNameCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock); 1087 cache->sidCacheSets = (sidCacheSet *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheSets); 1088 cache->sidCacheData = (sidCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheData); 1089 cache->certCacheData = (certCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->certCacheData); 1090 cache->keyCacheData = (SSLWrappedSymWrappingKey *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheData); 1091 cache->ticketKeyNameSuffix = (PRUint8 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix); 1092 cache->ticketEncKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketEncKey); 1093 cache->ticketMacKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketMacKey); 1094 cache->ticketKeysValid = (PRUint32 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid); 1095 cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData); 1096 1097 /* initialize the locks */ 1098 init_time = ssl_CacheNow(); 1099 pLock = cache->sidCacheLocks; 1100 for (locks_to_initialize = cache->numSIDCacheLocks + 3; 1101 locks_initialized < locks_to_initialize; 1102 ++locks_initialized, ++pLock) { 1103 1104 SECStatus err = sslMutex_Init(&pLock->mutex, shared); 1105 if (err) { 1106 cache->numSIDCacheLocksInitialized = locks_initialized; 1107 goto loser; 1108 } 1109 pLock->timeStamp = init_time; 1110 pLock->pid = 0; 1111 } 1112 cache->numSIDCacheLocksInitialized = locks_initialized; 1113 1114 return SECSuccess; 1115 1116 loser: 1117 CloseCache(cache); 1118 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1119 return SECFailure; 1120 } 1121 1122 PRUint32 1123 SSL_GetMaxServerCacheLocks(void) 1124 { 1125 return ssl_max_sid_cache_locks + 2; 1126 /* The extra two are the cert cache lock and the key cache lock. */ 1127 } 1128 1129 SECStatus 1130 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks) 1131 { 1132 /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock. 1133 ** We'd like to test for a maximum value, but not all platforms' header 1134 ** files provide a symbol or function or other means of determining 1135 ** the maximum, other than trial and error. 1136 */ 1137 if (maxLocks < 3) { 1138 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1139 return SECFailure; 1140 } 1141 ssl_max_sid_cache_locks = maxLocks - 2; 1142 /* The extra two are the cert cache lock and the key cache lock. */ 1143 return SECSuccess; 1144 } 1145 1146 PR_STATIC_ASSERT(sizeof(sidCacheEntry) % 16 == 0); 1147 PR_STATIC_ASSERT(sizeof(certCacheEntry) == 4096); 1148 PR_STATIC_ASSERT(sizeof(srvNameCacheEntry) == 1072); 1149 1150 static SECStatus 1151 ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache, 1152 PRUint32 ssl3_timeout, 1153 const char *directory, 1154 PRBool shared, 1155 int maxCacheEntries, 1156 int maxCertCacheEntries, 1157 int maxSrvNameCacheEntries) 1158 { 1159 SECStatus rv; 1160 1161 rv = ssl_InitSessionCache(); 1162 if (rv != SECSuccess) { 1163 return rv; 1164 } 1165 1166 myPid = SSL_GETPID(); 1167 if (!directory) { 1168 directory = DEFAULT_CACHE_DIRECTORY; 1169 } 1170 rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries, 1171 maxSrvNameCacheEntries, ssl3_timeout, directory, shared); 1172 if (rv) { 1173 return SECFailure; 1174 } 1175 1176 ssl_sid_lookup = ServerSessionIDLookup; 1177 return SECSuccess; 1178 } 1179 1180 SECStatus 1181 SSL_ConfigServerSessionIDCacheInstance(cacheDesc *cache, 1182 int maxCacheEntries, 1183 PRUint32 ssl2_timeout, 1184 PRUint32 ssl3_timeout, 1185 const char *directory, PRBool shared) 1186 { 1187 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache, 1188 ssl3_timeout, 1189 directory, 1190 shared, 1191 maxCacheEntries, 1192 -1, -1); 1193 } 1194 1195 SECStatus 1196 SSL_ConfigServerSessionIDCache(int maxCacheEntries, 1197 PRUint32 ssl2_timeout, 1198 PRUint32 ssl3_timeout, 1199 const char *directory) 1200 { 1201 ssl_InitSessionCacheLocks(PR_FALSE); 1202 return SSL_ConfigServerSessionIDCacheInstance(&globalCache, 1203 maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE); 1204 } 1205 1206 SECStatus 1207 SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache) 1208 { 1209 CloseCache(cache); 1210 return SECSuccess; 1211 } 1212 1213 SECStatus 1214 SSL_ShutdownServerSessionIDCache(void) 1215 { 1216 #if defined(XP_UNIX) 1217 /* Stop the thread that polls cache for expired locks on Unix */ 1218 StopLockPoller(&globalCache); 1219 #endif 1220 SSL3_ShutdownServerCache(); 1221 return SSL_ShutdownServerSessionIDCacheInstance(&globalCache); 1222 } 1223 1224 /* Use this function, instead of SSL_ConfigServerSessionIDCache, 1225 * if the cache will be shared by multiple processes. 1226 */ 1227 static SECStatus 1228 ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl3_timeout, 1229 const char *directory, 1230 int maxCacheEntries, 1231 int maxCertCacheEntries, 1232 int maxSrvNameCacheEntries) 1233 { 1234 char *envValue; 1235 char *inhValue; 1236 cacheDesc *cache = &globalCache; 1237 PRUint32 fmStrLen; 1238 SECStatus result; 1239 PRStatus prStatus; 1240 SECStatus putEnvFailed; 1241 inheritance inherit; 1242 char fmString[PR_FILEMAP_STRING_BUFSIZE]; 1243 1244 isMultiProcess = PR_TRUE; 1245 result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache, 1246 ssl3_timeout, directory, PR_TRUE, 1247 maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries); 1248 if (result != SECSuccess) 1249 return result; 1250 1251 prStatus = PR_ExportFileMapAsString(cache->cacheMemMap, 1252 sizeof fmString, fmString); 1253 if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) { 1254 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1255 return SECFailure; 1256 } 1257 1258 inherit.cacheMemSize = cache->cacheMemSize; 1259 inherit.fmStrLen = fmStrLen; 1260 1261 inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit); 1262 if (!inhValue || !strlen(inhValue)) { 1263 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1264 return SECFailure; 1265 } 1266 envValue = PR_smprintf("%s,%s", inhValue, fmString); 1267 if (!envValue || !strlen(envValue)) { 1268 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1269 return SECFailure; 1270 } 1271 PORT_Free(inhValue); 1272 1273 putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue); 1274 PR_smprintf_free(envValue); 1275 if (putEnvFailed) { 1276 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1277 result = SECFailure; 1278 } 1279 1280 #if defined(XP_UNIX) 1281 /* Launch thread to poll cache for expired locks on Unix */ 1282 LaunchLockPoller(cache); 1283 #endif 1284 return result; 1285 } 1286 1287 /* Use this function, instead of SSL_ConfigServerSessionIDCache, 1288 * if the cache will be shared by multiple processes. 1289 */ 1290 SECStatus 1291 SSL_ConfigMPServerSIDCache(int maxCacheEntries, 1292 PRUint32 ssl2_timeout, 1293 PRUint32 ssl3_timeout, 1294 const char *directory) 1295 { 1296 return ssl_ConfigMPServerSIDCacheWithOpt(ssl3_timeout, 1297 directory, 1298 maxCacheEntries, 1299 -1, -1); 1300 } 1301 1302 SECStatus 1303 SSL_ConfigServerSessionIDCacheWithOpt( 1304 PRUint32 ssl2_timeout, 1305 PRUint32 ssl3_timeout, 1306 const char *directory, 1307 int maxCacheEntries, 1308 int maxCertCacheEntries, 1309 int maxSrvNameCacheEntries, 1310 PRBool enableMPCache) 1311 { 1312 if (!enableMPCache) { 1313 ssl_InitSessionCacheLocks(PR_FALSE); 1314 return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache, 1315 ssl3_timeout, directory, PR_FALSE, 1316 maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries); 1317 } else { 1318 return ssl_ConfigMPServerSIDCacheWithOpt(ssl3_timeout, directory, 1319 maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries); 1320 } 1321 } 1322 1323 SECStatus 1324 SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString) 1325 { 1326 unsigned char *decoString = NULL; 1327 char *fmString = NULL; 1328 char *myEnvString = NULL; 1329 unsigned int decoLen; 1330 inheritance inherit; 1331 cacheDesc my; 1332 #ifdef WINNT 1333 sidCacheLock *newLocks; 1334 int locks_initialized = 0; 1335 int locks_to_initialize = 0; 1336 #endif 1337 SECStatus status = ssl_InitSessionCache(); 1338 1339 if (status != SECSuccess) { 1340 return status; 1341 } 1342 1343 myPid = SSL_GETPID(); 1344 1345 /* If this child was created by fork(), and not by exec() on unix, 1346 ** then isMultiProcess will already be set. 1347 ** If not, we'll set it below. 1348 */ 1349 if (isMultiProcess) { 1350 if (cache && cache->sharedCache) { 1351 cache->sharedCache->everInherited = PR_TRUE; 1352 } 1353 return SECSuccess; /* already done. */ 1354 } 1355 1356 ssl_InitSessionCacheLocks(PR_FALSE); 1357 1358 ssl_sid_lookup = ServerSessionIDLookup; 1359 1360 if (!envString) { 1361 envString = PR_GetEnvSecure(envVarName); 1362 if (!envString) { 1363 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1364 return SECFailure; 1365 } 1366 } 1367 myEnvString = PORT_Strdup(envString); 1368 if (!myEnvString) 1369 return SECFailure; 1370 fmString = strchr(myEnvString, ','); 1371 if (!fmString) 1372 goto loser; 1373 *fmString++ = 0; 1374 1375 decoString = ATOB_AsciiToData(myEnvString, &decoLen); 1376 if (!decoString) { 1377 goto loser; 1378 } 1379 if (decoLen != sizeof inherit) { 1380 goto loser; 1381 } 1382 1383 PORT_Memcpy(&inherit, decoString, sizeof inherit); 1384 1385 if (strlen(fmString) != inherit.fmStrLen) { 1386 goto loser; 1387 } 1388 1389 memset(cache, 0, sizeof *cache); 1390 cache->cacheMemSize = inherit.cacheMemSize; 1391 1392 /* Create cache */ 1393 cache->cacheMemMap = PR_ImportFileMapFromString(fmString); 1394 if (!cache->cacheMemMap) { 1395 goto loser; 1396 } 1397 cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize); 1398 if (!cache->cacheMem) { 1399 goto loser; 1400 } 1401 cache->sharedCache = (cacheDesc *)cache->cacheMem; 1402 1403 if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) { 1404 goto loser; 1405 } 1406 1407 /* We're now going to overwrite the local cache instance with the 1408 ** shared copy of the cache struct, then update several values in 1409 ** the local cache using the values for cache->cacheMemMap and 1410 ** cache->cacheMem computed just above. So, we copy cache into 1411 ** the automatic variable "my", to preserve the variables while 1412 ** cache is overwritten. 1413 */ 1414 my = *cache; /* save values computed above. */ 1415 memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */ 1416 1417 /* Fix pointers in our private copy of cache descriptor to point to 1418 ** spaces in shared memory, whose address is now in "my". 1419 */ 1420 cache->sidCacheLocks = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->sidCacheLocks); 1421 cache->keyCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->keyCacheLock); 1422 cache->certCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->certCacheLock); 1423 cache->srvNameCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock); 1424 cache->sidCacheSets = (sidCacheSet *)(my.cacheMem + (ptrdiff_t)cache->sidCacheSets); 1425 cache->sidCacheData = (sidCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->sidCacheData); 1426 cache->certCacheData = (certCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->certCacheData); 1427 cache->keyCacheData = (SSLWrappedSymWrappingKey *)(my.cacheMem + (ptrdiff_t)cache->keyCacheData); 1428 cache->ticketKeyNameSuffix = (PRUint8 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix); 1429 cache->ticketEncKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketEncKey); 1430 cache->ticketMacKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketMacKey); 1431 cache->ticketKeysValid = (PRUint32 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeysValid); 1432 cache->srvNameCacheData = (srvNameCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheData); 1433 1434 cache->cacheMemMap = my.cacheMemMap; 1435 cache->cacheMem = my.cacheMem; 1436 cache->sharedCache = (cacheDesc *)cache->cacheMem; 1437 1438 #ifdef WINNT 1439 /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers 1440 ** When NT fibers are used in a multi-process server, a second level of 1441 ** locking is needed to prevent a deadlock, in case a fiber acquires the 1442 ** cross-process mutex, yields, and another fiber is later scheduled on 1443 ** the same native thread and tries to acquire the cross-process mutex. 1444 ** We do this by using a PRLock in the sslMutex. However, it is stored in 1445 ** shared memory as part of sidCacheLocks, and we don't want to overwrite 1446 ** the PRLock of the parent process. So we need to make new, private 1447 ** copies of sidCacheLocks before modifying the sslMutex with our own 1448 ** PRLock 1449 */ 1450 1451 /* note from jpierre : this should be free'd in child processes when 1452 ** a function is added to delete the SSL session cache in the future. 1453 */ 1454 locks_to_initialize = cache->numSIDCacheLocks + 3; 1455 newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize); 1456 if (!newLocks) 1457 goto loser; 1458 /* copy the old locks */ 1459 memcpy(newLocks, cache->sidCacheLocks, 1460 locks_to_initialize * sizeof(sidCacheLock)); 1461 cache->sidCacheLocks = newLocks; 1462 /* fix the locks */ 1463 for (; locks_initialized < locks_to_initialize; ++locks_initialized) { 1464 /* now, make a local PRLock in this sslMutex for this child process */ 1465 SECStatus err; 1466 err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex); 1467 if (err != SECSuccess) { 1468 cache->numSIDCacheLocksInitialized = locks_initialized; 1469 goto loser; 1470 } 1471 } 1472 cache->numSIDCacheLocksInitialized = locks_initialized; 1473 1474 /* also fix the key and cert cache which use the last 2 lock entries */ 1475 cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks; 1476 cache->certCacheLock = cache->keyCacheLock + 1; 1477 cache->srvNameCacheLock = cache->certCacheLock + 1; 1478 #endif 1479 1480 PORT_Free(myEnvString); 1481 PORT_Free(decoString); 1482 1483 /* mark that we have inherited this. */ 1484 cache->sharedCache->everInherited = PR_TRUE; 1485 isMultiProcess = PR_TRUE; 1486 1487 return SECSuccess; 1488 1489 loser: 1490 PORT_Free(myEnvString); 1491 if (decoString) 1492 PORT_Free(decoString); 1493 CloseCache(cache); 1494 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1495 return SECFailure; 1496 } 1497 1498 SECStatus 1499 SSL_InheritMPServerSIDCache(const char *envString) 1500 { 1501 return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString); 1502 } 1503 1504 #if defined(XP_UNIX) 1505 1506 #define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */ 1507 1508 static void 1509 LockPoller(void *arg) 1510 { 1511 cacheDesc *cache = (cacheDesc *)arg; 1512 cacheDesc *sharedCache = cache->sharedCache; 1513 sidCacheLock *pLock; 1514 PRIntervalTime timeout; 1515 PRUint32 now; 1516 PRUint32 then; 1517 int locks_polled = 0; 1518 int locks_to_poll = cache->numSIDCacheLocks + 2; 1519 PRUint32 expiration = cache->mutexTimeout; 1520 1521 timeout = PR_SecondsToInterval(expiration); 1522 while (!sharedCache->stopPolling) { 1523 PR_Sleep(timeout); 1524 if (sharedCache->stopPolling) 1525 break; 1526 1527 now = ssl_CacheNow(); 1528 then = now - expiration; 1529 for (pLock = cache->sidCacheLocks, locks_polled = 0; 1530 locks_to_poll > locks_polled && !sharedCache->stopPolling; 1531 ++locks_polled, ++pLock) { 1532 pid_t pid; 1533 1534 if (pLock->timeStamp < then && 1535 pLock->timeStamp != 0 && 1536 (pid = pLock->pid) != 0) { 1537 1538 /* maybe we should try the lock? */ 1539 int result = kill(pid, 0); 1540 if (result < 0 && errno == ESRCH) { 1541 SECStatus rv; 1542 /* No process exists by that pid any more. 1543 ** Treat this mutex as abandoned. 1544 */ 1545 pLock->timeStamp = now; 1546 pLock->pid = 0; 1547 rv = sslMutex_Unlock(&pLock->mutex); 1548 if (rv != SECSuccess) { 1549 /* Now what? */ 1550 } 1551 } 1552 } 1553 } /* end of loop over locks */ 1554 } /* end of entire polling loop */ 1555 } 1556 1557 /* Launch thread to poll cache for expired locks */ 1558 static SECStatus 1559 LaunchLockPoller(cacheDesc *cache) 1560 { 1561 const char *timeoutString; 1562 PRThread *pollerThread; 1563 1564 cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT; 1565 timeoutString = PR_GetEnvSecure("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT"); 1566 if (timeoutString) { 1567 long newTime = strtol(timeoutString, 0, 0); 1568 if (newTime == 0) 1569 return SECSuccess; /* application doesn't want poller thread */ 1570 if (newTime > 0) 1571 cache->mutexTimeout = (PRUint32)newTime; 1572 /* if error (newTime < 0) ignore it and use default */ 1573 } 1574 1575 pollerThread = 1576 PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL, 1577 PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); 1578 if (!pollerThread) { 1579 return SECFailure; 1580 } 1581 cache->poller = pollerThread; 1582 return SECSuccess; 1583 } 1584 1585 /* Stop the thread that polls cache for expired locks */ 1586 static SECStatus 1587 StopLockPoller(cacheDesc *cache) 1588 { 1589 if (!cache->poller) { 1590 return SECSuccess; 1591 } 1592 cache->sharedCache->stopPolling = PR_TRUE; 1593 if (PR_Interrupt(cache->poller) != PR_SUCCESS) { 1594 return SECFailure; 1595 } 1596 if (PR_JoinThread(cache->poller) != PR_SUCCESS) { 1597 return SECFailure; 1598 } 1599 cache->poller = NULL; 1600 return SECSuccess; 1601 } 1602 #endif 1603 1604 /************************************************************************ 1605 * Code dealing with shared wrapped symmetric wrapping keys below * 1606 ************************************************************************/ 1607 1608 /* The asymmetric key we use for wrapping the self-encryption keys. This is a 1609 * global structure that can be initialized without a socket. Access is 1610 * synchronized on the reader-writer lock. This is setup either by calling 1611 * SSL_SetSessionTicketKeyPair() or by configuring a certificate of the 1612 * ssl_auth_rsa_decrypt type. */ 1613 static struct { 1614 PRCallOnceType setup; 1615 PRRWLock *lock; 1616 SECKEYPublicKey *pubKey; 1617 SECKEYPrivateKey *privKey; 1618 PRBool configured; 1619 } ssl_self_encrypt_key_pair; 1620 1621 /* The symmetric self-encryption keys. This requires a socket to construct 1622 * and requires that the global structure be initialized before use. 1623 */ 1624 static sslSelfEncryptKeys ssl_self_encrypt_keys; 1625 1626 /* Externalize the self encrypt keys. Purely used for testing. */ 1627 sslSelfEncryptKeys * 1628 ssl_GetSelfEncryptKeysInt() 1629 { 1630 return &ssl_self_encrypt_keys; 1631 } 1632 1633 static void 1634 ssl_CleanupSelfEncryptKeyPair() 1635 { 1636 if (ssl_self_encrypt_key_pair.pubKey) { 1637 PORT_Assert(ssl_self_encrypt_key_pair.privKey); 1638 SECKEY_DestroyPublicKey(ssl_self_encrypt_key_pair.pubKey); 1639 SECKEY_DestroyPrivateKey(ssl_self_encrypt_key_pair.privKey); 1640 } 1641 } 1642 1643 void 1644 ssl_ResetSelfEncryptKeys() 1645 { 1646 if (ssl_self_encrypt_keys.encKey) { 1647 PORT_Assert(ssl_self_encrypt_keys.macKey); 1648 PK11_FreeSymKey(ssl_self_encrypt_keys.encKey); 1649 PK11_FreeSymKey(ssl_self_encrypt_keys.macKey); 1650 } 1651 PORT_Memset(&ssl_self_encrypt_keys, 0, 1652 sizeof(ssl_self_encrypt_keys)); 1653 } 1654 1655 static SECStatus 1656 ssl_SelfEncryptShutdown(void *appData, void *nssData) 1657 { 1658 ssl_CleanupSelfEncryptKeyPair(); 1659 PR_DestroyRWLock(ssl_self_encrypt_key_pair.lock); 1660 PORT_Memset(&ssl_self_encrypt_key_pair, 0, 1661 sizeof(ssl_self_encrypt_key_pair)); 1662 1663 ssl_ResetSelfEncryptKeys(); 1664 return SECSuccess; 1665 } 1666 1667 static PRStatus 1668 ssl_SelfEncryptSetup(void) 1669 { 1670 SECStatus rv = NSS_RegisterShutdown(ssl_SelfEncryptShutdown, NULL); 1671 if (rv != SECSuccess) { 1672 return PR_FAILURE; 1673 } 1674 ssl_self_encrypt_key_pair.lock = PR_NewRWLock(PR_RWLOCK_RANK_NONE, NULL); 1675 if (!ssl_self_encrypt_key_pair.lock) { 1676 return PR_FAILURE; 1677 } 1678 return PR_SUCCESS; 1679 } 1680 1681 /* Configure a self encryption key pair. |explicitConfig| is set to true for 1682 * calls to SSL_SetSessionTicketKeyPair(), false for implicit configuration. 1683 * This assumes that the setup has been run. */ 1684 static SECStatus 1685 ssl_SetSelfEncryptKeyPair(SECKEYPublicKey *pubKey, 1686 SECKEYPrivateKey *privKey, 1687 PRBool explicitConfig) 1688 { 1689 SECKEYPublicKey *pubKeyCopy, *oldPubKey; 1690 SECKEYPrivateKey *privKeyCopy, *oldPrivKey; 1691 1692 PORT_Assert(ssl_self_encrypt_key_pair.lock); 1693 pubKeyCopy = SECKEY_CopyPublicKey(pubKey); 1694 privKeyCopy = SECKEY_CopyPrivateKey(privKey); 1695 1696 if (!pubKeyCopy || !privKeyCopy) { 1697 SECKEY_DestroyPublicKey(pubKeyCopy); 1698 SECKEY_DestroyPrivateKey(privKeyCopy); 1699 PORT_SetError(SEC_ERROR_NO_MEMORY); 1700 return SECFailure; 1701 } 1702 1703 PR_RWLock_Wlock(ssl_self_encrypt_key_pair.lock); 1704 oldPubKey = ssl_self_encrypt_key_pair.pubKey; 1705 oldPrivKey = ssl_self_encrypt_key_pair.privKey; 1706 ssl_self_encrypt_key_pair.pubKey = pubKeyCopy; 1707 ssl_self_encrypt_key_pair.privKey = privKeyCopy; 1708 ssl_self_encrypt_key_pair.configured = explicitConfig; 1709 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock); 1710 1711 if (oldPubKey) { 1712 PORT_Assert(oldPrivKey); 1713 SECKEY_DestroyPublicKey(oldPubKey); 1714 SECKEY_DestroyPrivateKey(oldPrivKey); 1715 } 1716 1717 return SECSuccess; 1718 } 1719 1720 /* This is really the self-encryption keys but it has the 1721 * wrong name for historical API stability reasons. */ 1722 SECStatus 1723 SSL_SetSessionTicketKeyPair(SECKEYPublicKey *pubKey, 1724 SECKEYPrivateKey *privKey) 1725 { 1726 if (SECKEY_GetPublicKeyType(pubKey) != rsaKey || 1727 SECKEY_GetPrivateKeyType(privKey) != rsaKey) { 1728 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1729 return SECFailure; 1730 } 1731 1732 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup, 1733 &ssl_SelfEncryptSetup)) { 1734 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1735 return SECFailure; 1736 } 1737 1738 return ssl_SetSelfEncryptKeyPair(pubKey, privKey, PR_TRUE); 1739 } 1740 1741 /* When configuring a server cert, we should save the RSA key in case it is 1742 * needed for self-encryption. This saves the latest copy, unless there has 1743 * been an explicit call to SSL_SetSessionTicketKeyPair(). */ 1744 SECStatus 1745 ssl_MaybeSetSelfEncryptKeyPair(const sslKeyPair *keyPair) 1746 { 1747 PRBool configured; 1748 1749 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup, 1750 &ssl_SelfEncryptSetup)) { 1751 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1752 return SECFailure; 1753 } 1754 1755 PR_RWLock_Rlock(ssl_self_encrypt_key_pair.lock); 1756 configured = ssl_self_encrypt_key_pair.configured; 1757 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock); 1758 if (configured) { 1759 return SECSuccess; 1760 } 1761 return ssl_SetSelfEncryptKeyPair(keyPair->pubKey, 1762 keyPair->privKey, PR_FALSE); 1763 } 1764 1765 static SECStatus 1766 ssl_GetSelfEncryptKeyPair(SECKEYPublicKey **pubKey, 1767 SECKEYPrivateKey **privKey) 1768 { 1769 if (PR_SUCCESS != PR_CallOnce(&ssl_self_encrypt_key_pair.setup, 1770 &ssl_SelfEncryptSetup)) { 1771 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1772 return SECFailure; 1773 } 1774 1775 SECKEYPublicKey *pubKeyCopy = NULL; 1776 SECKEYPrivateKey *privKeyCopy = NULL; 1777 PRBool noKey = PR_FALSE; 1778 1779 PR_RWLock_Rlock(ssl_self_encrypt_key_pair.lock); 1780 if (ssl_self_encrypt_key_pair.pubKey && ssl_self_encrypt_key_pair.privKey) { 1781 pubKeyCopy = SECKEY_CopyPublicKey(ssl_self_encrypt_key_pair.pubKey); 1782 privKeyCopy = SECKEY_CopyPrivateKey(ssl_self_encrypt_key_pair.privKey); 1783 } else { 1784 noKey = PR_TRUE; 1785 } 1786 PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock); 1787 1788 if (noKey) { 1789 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1790 return SECFailure; 1791 } 1792 1793 if (!pubKeyCopy || !privKeyCopy) { 1794 SECKEY_DestroyPublicKey(pubKeyCopy); 1795 SECKEY_DestroyPrivateKey(privKeyCopy); 1796 PORT_SetError(SEC_ERROR_NO_MEMORY); 1797 return SECFailure; 1798 } 1799 1800 *pubKey = pubKeyCopy; 1801 *privKey = privKeyCopy; 1802 return SECSuccess; 1803 } 1804 1805 static SECStatus 1806 ssl_GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName, 1807 PK11SymKey **aesKey, PK11SymKey **macKey); 1808 1809 static PRStatus 1810 ssl_GenerateSelfEncryptKeysOnce(void *arg) 1811 { 1812 SECStatus rv; 1813 1814 /* Get a copy of the session keys from shared memory. */ 1815 PORT_Memcpy(ssl_self_encrypt_keys.keyName, 1816 SELF_ENCRYPT_KEY_NAME_PREFIX, 1817 sizeof(SELF_ENCRYPT_KEY_NAME_PREFIX)); 1818 /* This function calls ssl_GetSelfEncryptKeyPair(), which initializes the 1819 * key pair stuff. That allows this to use the same shutdown function. */ 1820 rv = ssl_GenerateSelfEncryptKeys(arg, ssl_self_encrypt_keys.keyName, 1821 &ssl_self_encrypt_keys.encKey, 1822 &ssl_self_encrypt_keys.macKey); 1823 if (rv != SECSuccess) { 1824 return PR_FAILURE; 1825 } 1826 1827 return PR_SUCCESS; 1828 } 1829 1830 SECStatus 1831 ssl_GetSelfEncryptKeys(sslSocket *ss, PRUint8 *keyName, 1832 PK11SymKey **encKey, PK11SymKey **macKey) 1833 { 1834 if (PR_SUCCESS != PR_CallOnceWithArg(&ssl_self_encrypt_keys.setup, 1835 &ssl_GenerateSelfEncryptKeysOnce, 1836 ss->pkcs11PinArg)) { 1837 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1838 return SECFailure; 1839 } 1840 1841 if (!ssl_self_encrypt_keys.encKey || !ssl_self_encrypt_keys.macKey) { 1842 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1843 return SECFailure; 1844 } 1845 1846 PORT_Memcpy(keyName, ssl_self_encrypt_keys.keyName, 1847 sizeof(ssl_self_encrypt_keys.keyName)); 1848 *encKey = ssl_self_encrypt_keys.encKey; 1849 *macKey = ssl_self_encrypt_keys.macKey; 1850 return SECSuccess; 1851 } 1852 1853 /* If lockTime is zero, it implies that the lock is not held, and must be 1854 * aquired here. 1855 */ 1856 static SECStatus 1857 getSvrWrappingKey(unsigned int symWrapMechIndex, 1858 unsigned int wrapKeyIndex, 1859 SSLWrappedSymWrappingKey *wswk, 1860 cacheDesc *cache, 1861 PRUint32 lockTime) 1862 { 1863 PRUint32 now = 0; 1864 PRBool rv = SECFailure; 1865 1866 if (!cache->cacheMem) { /* cache is uninitialized */ 1867 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED); 1868 return SECFailure; 1869 } 1870 1871 PRUint32 ndx = (wrapKeyIndex * SSL_NUM_WRAP_MECHS) + symWrapMechIndex; 1872 SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx; 1873 1874 if (!lockTime) { 1875 now = LockSidCacheLock(cache->keyCacheLock, 0); 1876 if (!now) { 1877 return SECFailure; 1878 } 1879 } 1880 if (pwswk->wrapKeyIndex == wrapKeyIndex && 1881 pwswk->wrapMechIndex == symWrapMechIndex && 1882 pwswk->wrappedSymKeyLen != 0) { 1883 *wswk = *pwswk; 1884 rv = SECSuccess; 1885 } 1886 if (now) { 1887 UnlockSidCacheLock(cache->keyCacheLock); 1888 } 1889 return rv; 1890 } 1891 1892 SECStatus 1893 ssl_GetWrappingKey(unsigned int wrapMechIndex, 1894 unsigned int wrapKeyIndex, 1895 SSLWrappedSymWrappingKey *wswk) 1896 { 1897 PORT_Assert(wrapMechIndex < SSL_NUM_WRAP_MECHS); 1898 PORT_Assert(wrapKeyIndex < SSL_NUM_WRAP_KEYS); 1899 if (wrapMechIndex >= SSL_NUM_WRAP_MECHS || 1900 wrapKeyIndex >= SSL_NUM_WRAP_KEYS) { 1901 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1902 return SECFailure; 1903 } 1904 1905 return getSvrWrappingKey(wrapMechIndex, wrapKeyIndex, wswk, 1906 &globalCache, 0); 1907 } 1908 1909 /* Wrap and cache a session ticket key. */ 1910 static SECStatus 1911 WrapSelfEncryptKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey, 1912 const char *keyName, encKeyCacheEntry *cacheEntry) 1913 { 1914 SECItem wrappedKey = { siBuffer, NULL, 0 }; 1915 1916 wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey); 1917 PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes)); 1918 if (wrappedKey.len > sizeof(cacheEntry->bytes)) 1919 return PR_FALSE; 1920 wrappedKey.data = cacheEntry->bytes; 1921 1922 if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey) != 1923 SECSuccess) { 1924 SSL_DBG(("%d: SSL[%s]: Unable to wrap self encrypt key %s.", 1925 SSL_GETPID(), "unknown", keyName)); 1926 return SECFailure; 1927 } 1928 cacheEntry->length = wrappedKey.len; 1929 return SECSuccess; 1930 } 1931 1932 static SECStatus 1933 GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName, PK11SymKey **aesKey, 1934 PK11SymKey **macKey) 1935 { 1936 PK11SlotInfo *slot; 1937 CK_MECHANISM_TYPE mechanismArray[2]; 1938 PK11SymKey *aesKeyTmp = NULL; 1939 PK11SymKey *macKeyTmp = NULL; 1940 cacheDesc *cache = &globalCache; 1941 PRUint8 ticketKeyNameSuffixLocal[SELF_ENCRYPT_KEY_VAR_NAME_LEN]; 1942 PRUint8 *ticketKeyNameSuffix; 1943 1944 if (!cache->cacheMem) { 1945 /* cache is not initalized. Use stack buffer */ 1946 ticketKeyNameSuffix = ticketKeyNameSuffixLocal; 1947 } else { 1948 ticketKeyNameSuffix = cache->ticketKeyNameSuffix; 1949 } 1950 1951 if (PK11_GenerateRandom(ticketKeyNameSuffix, 1952 SELF_ENCRYPT_KEY_VAR_NAME_LEN) != 1953 SECSuccess) { 1954 SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.", 1955 SSL_GETPID(), "unknown")); 1956 return SECFailure; 1957 } 1958 1959 mechanismArray[0] = CKM_AES_CBC; 1960 mechanismArray[1] = CKM_SHA256_HMAC; 1961 1962 slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg); 1963 if (slot) { 1964 aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL, 1965 AES_256_KEY_LENGTH, pwArg); 1966 macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL, 1967 SHA256_LENGTH, pwArg); 1968 PK11_FreeSlot(slot); 1969 } 1970 1971 if (aesKeyTmp == NULL || macKeyTmp == NULL) { 1972 SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.", 1973 SSL_GETPID(), "unknown")); 1974 goto loser; 1975 } 1976 PORT_Memcpy(keyName, ticketKeyNameSuffix, SELF_ENCRYPT_KEY_VAR_NAME_LEN); 1977 *aesKey = aesKeyTmp; 1978 *macKey = macKeyTmp; 1979 return SECSuccess; 1980 1981 loser: 1982 if (aesKeyTmp) 1983 PK11_FreeSymKey(aesKeyTmp); 1984 if (macKeyTmp) 1985 PK11_FreeSymKey(macKeyTmp); 1986 return SECFailure; 1987 } 1988 1989 static SECStatus 1990 GenerateAndWrapSelfEncryptKeys(SECKEYPublicKey *svrPubKey, void *pwArg, 1991 PRUint8 *keyName, PK11SymKey **aesKey, 1992 PK11SymKey **macKey) 1993 { 1994 PK11SymKey *aesKeyTmp = NULL; 1995 PK11SymKey *macKeyTmp = NULL; 1996 cacheDesc *cache = &globalCache; 1997 SECStatus rv; 1998 1999 rv = GenerateSelfEncryptKeys(pwArg, keyName, &aesKeyTmp, &macKeyTmp); 2000 if (rv != SECSuccess) { 2001 return SECFailure; 2002 } 2003 2004 if (cache->cacheMem) { 2005 /* Export the keys to the shared cache in wrapped form. */ 2006 rv = WrapSelfEncryptKey(svrPubKey, aesKeyTmp, "enc key", cache->ticketEncKey); 2007 if (rv != SECSuccess) { 2008 goto loser; 2009 } 2010 rv = WrapSelfEncryptKey(svrPubKey, macKeyTmp, "mac key", cache->ticketMacKey); 2011 if (rv != SECSuccess) { 2012 goto loser; 2013 } 2014 } 2015 *aesKey = aesKeyTmp; 2016 *macKey = macKeyTmp; 2017 return SECSuccess; 2018 2019 loser: 2020 PK11_FreeSymKey(aesKeyTmp); 2021 PK11_FreeSymKey(macKeyTmp); 2022 return SECFailure; 2023 } 2024 2025 static SECStatus 2026 UnwrapCachedSelfEncryptKeys(SECKEYPrivateKey *svrPrivKey, PRUint8 *keyName, 2027 PK11SymKey **aesKey, PK11SymKey **macKey) 2028 { 2029 SECItem wrappedKey = { siBuffer, NULL, 0 }; 2030 PK11SymKey *aesKeyTmp = NULL; 2031 PK11SymKey *macKeyTmp = NULL; 2032 cacheDesc *cache = &globalCache; 2033 2034 wrappedKey.data = cache->ticketEncKey->bytes; 2035 wrappedKey.len = cache->ticketEncKey->length; 2036 PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes)); 2037 aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey, 2038 CKM_AES_CBC, CKA_DECRYPT, 0); 2039 2040 wrappedKey.data = cache->ticketMacKey->bytes; 2041 wrappedKey.len = cache->ticketMacKey->length; 2042 PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes)); 2043 macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey, 2044 CKM_SHA256_HMAC, CKA_SIGN, 0); 2045 2046 if (aesKeyTmp == NULL || macKeyTmp == NULL) { 2047 SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.", 2048 SSL_GETPID(), "unknown")); 2049 goto loser; 2050 } 2051 SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.", 2052 SSL_GETPID(), "unknown")); 2053 2054 PORT_Memcpy(keyName, cache->ticketKeyNameSuffix, 2055 SELF_ENCRYPT_KEY_VAR_NAME_LEN); 2056 *aesKey = aesKeyTmp; 2057 *macKey = macKeyTmp; 2058 return SECSuccess; 2059 2060 loser: 2061 if (aesKeyTmp) 2062 PK11_FreeSymKey(aesKeyTmp); 2063 if (macKeyTmp) 2064 PK11_FreeSymKey(macKeyTmp); 2065 return SECFailure; 2066 } 2067 2068 static SECStatus 2069 ssl_GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName, 2070 PK11SymKey **encKey, PK11SymKey **macKey) 2071 { 2072 SECKEYPrivateKey *svrPrivKey = NULL; 2073 SECKEYPublicKey *svrPubKey = NULL; 2074 PRUint32 now; 2075 cacheDesc *cache = &globalCache; 2076 2077 SECStatus rv = ssl_GetSelfEncryptKeyPair(&svrPubKey, &svrPrivKey); 2078 if (rv != SECSuccess || !cache->cacheMem) { 2079 /* No key pair for wrapping, or the cache is uninitialized. Generate 2080 * keys and return them without caching. */ 2081 rv = GenerateSelfEncryptKeys(pwArg, keyName, encKey, macKey); 2082 } else { 2083 now = LockSidCacheLock(cache->keyCacheLock, 0); 2084 if (!now) { 2085 goto loser; 2086 } 2087 2088 if (*(cache->ticketKeysValid)) { 2089 rv = UnwrapCachedSelfEncryptKeys(svrPrivKey, keyName, encKey, macKey); 2090 } else { 2091 /* Keys do not exist, create them. */ 2092 rv = GenerateAndWrapSelfEncryptKeys(svrPubKey, pwArg, keyName, 2093 encKey, macKey); 2094 if (rv == SECSuccess) { 2095 *(cache->ticketKeysValid) = 1; 2096 } 2097 } 2098 UnlockSidCacheLock(cache->keyCacheLock); 2099 } 2100 SECKEY_DestroyPublicKey(svrPubKey); 2101 SECKEY_DestroyPrivateKey(svrPrivKey); 2102 return rv; 2103 2104 loser: 2105 UnlockSidCacheLock(cache->keyCacheLock); 2106 SECKEY_DestroyPublicKey(svrPubKey); 2107 SECKEY_DestroyPrivateKey(svrPrivKey); 2108 return SECFailure; 2109 } 2110 2111 /* The caller passes in the new value it wants 2112 * to set. This code tests the wrapped sym key entry in the shared memory. 2113 * If it is uninitialized, this function writes the caller's value into 2114 * the disk entry, and returns false. 2115 * Otherwise, it overwrites the caller's wswk with the value obtained from 2116 * the disk, and returns PR_TRUE. 2117 * This is all done while holding the locks/mutexes necessary to make 2118 * the operation atomic. 2119 */ 2120 SECStatus 2121 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk) 2122 { 2123 cacheDesc *cache = &globalCache; 2124 PRBool rv = SECFailure; 2125 PRUint32 ndx; 2126 PRUint32 now; 2127 SSLWrappedSymWrappingKey myWswk; 2128 2129 if (!cache->cacheMem) { /* cache is uninitialized */ 2130 PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED); 2131 return SECFailure; 2132 } 2133 2134 PORT_Assert(wswk->wrapMechIndex < SSL_NUM_WRAP_MECHS); 2135 PORT_Assert(wswk->wrapKeyIndex < SSL_NUM_WRAP_KEYS); 2136 if (wswk->wrapMechIndex >= SSL_NUM_WRAP_MECHS || 2137 wswk->wrapKeyIndex >= SSL_NUM_WRAP_KEYS) { 2138 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 2139 return SECFailure; 2140 } 2141 2142 ndx = (wswk->wrapKeyIndex * SSL_NUM_WRAP_MECHS) + wswk->wrapMechIndex; 2143 PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */ 2144 2145 now = LockSidCacheLock(cache->keyCacheLock, 0); 2146 if (!now) { 2147 return SECFailure; 2148 } 2149 rv = getSvrWrappingKey(wswk->wrapMechIndex, wswk->wrapKeyIndex, 2150 &myWswk, cache, now); 2151 if (rv == SECSuccess) { 2152 /* we found it on disk, copy it out to the caller. */ 2153 PORT_Memcpy(wswk, &myWswk, sizeof *wswk); 2154 } else { 2155 /* Wasn't on disk, and we're still holding the lock, so write it. */ 2156 cache->keyCacheData[ndx] = *wswk; 2157 } 2158 UnlockSidCacheLock(cache->keyCacheLock); 2159 return rv; 2160 } 2161 2162 #else /* MAC version or other platform */ 2163 2164 #include "seccomon.h" 2165 #include "cert.h" 2166 #include "ssl.h" 2167 #include "sslimpl.h" 2168 2169 SECStatus 2170 SSL_ConfigServerSessionIDCache(int maxCacheEntries, 2171 PRUint32 ssl2_timeout, 2172 PRUint32 ssl3_timeout, 2173 const char *directory) 2174 { 2175 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)"); 2176 return SECFailure; 2177 } 2178 2179 SECStatus 2180 SSL_ConfigMPServerSIDCache(int maxCacheEntries, 2181 PRUint32 ssl2_timeout, 2182 PRUint32 ssl3_timeout, 2183 const char *directory) 2184 { 2185 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)"); 2186 return SECFailure; 2187 } 2188 2189 SECStatus 2190 SSL_InheritMPServerSIDCache(const char *envString) 2191 { 2192 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)"); 2193 return SECFailure; 2194 } 2195 2196 SECStatus 2197 ssl_GetWrappingKey(unsigned int wrapMechIndex, 2198 unsigned int wrapKeyIndex, 2199 SSLWrappedSymWrappingKey *wswk) 2200 { 2201 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)"); 2202 return SECFailure; 2203 } 2204 2205 /* This is a kind of test-and-set. The caller passes in the new value it wants 2206 * to set. This code tests the wrapped sym key entry in the shared memory. 2207 * If it is uninitialized, this function writes the caller's value into 2208 * the disk entry, and returns false. 2209 * Otherwise, it overwrites the caller's wswk with the value obtained from 2210 * the disk, and returns PR_TRUE. 2211 * This is all done while holding the locks/mutexes necessary to make 2212 * the operation atomic. 2213 */ 2214 SECStatus 2215 ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk) 2216 { 2217 PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)"); 2218 return SECFailure; 2219 } 2220 2221 PRUint32 2222 SSL_GetMaxServerCacheLocks(void) 2223 { 2224 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)"); 2225 return -1; 2226 } 2227 2228 SECStatus 2229 SSL_SetMaxServerCacheLocks(PRUint32 maxLocks) 2230 { 2231 PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)"); 2232 return SECFailure; 2233 } 2234 2235 #endif /* XP_UNIX || XP_WIN32 */