Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(592)

Unified Diff: net/third_party/nss/ssl/sslsnce.c

Issue 1882433002: Removing NSS files and USE_OPENSSL flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/third_party/nss/ssl/sslsecur.c ('k') | net/third_party/nss/ssl/sslsock.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/third_party/nss/ssl/sslsnce.c
diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c
deleted file mode 100644
index e3f749e577b5969abac744c2df985abe903556f5..0000000000000000000000000000000000000000
--- a/net/third_party/nss/ssl/sslsnce.c
+++ /dev/null
@@ -1,2204 +0,0 @@
-/* This file implements the SERVER Session ID cache.
- * NOTE: The contents of this file are NOT used by the client.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
- * cache sids!
- *
- * About record locking among different server processes:
- *
- * All processes that are part of the same conceptual server (serving on
- * the same address and port) MUST share a common SSL session cache.
- * This code makes the content of the shared cache accessible to all
- * processes on the same "server". This code works on Unix and Win32 only.
- *
- * We use NSPR anonymous shared memory and move data to & from shared memory.
- * We must do explicit locking of the records for all reads and writes.
- * The set of Cache entries are divided up into "sets" of 128 entries.
- * Each set is protected by a lock. There may be one or more sets protected
- * by each lock. That is, locks to sets are 1:N.
- * There is one lock for the entire cert cache.
- * There is one lock for the set of wrapped sym wrap keys.
- *
- * The anonymous shared memory is laid out as if it were declared like this:
- *
- * struct {
- * cacheDescriptor desc;
- * sidCacheLock sidCacheLocks[ numSIDCacheLocks];
- * sidCacheLock keyCacheLock;
- * sidCacheLock certCacheLock;
- * sidCacheSet sidCacheSets[ numSIDCacheSets ];
- * sidCacheEntry sidCacheData[ numSIDCacheEntries];
- * certCacheEntry certCacheData[numCertCacheEntries];
- * SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS];
- * PRUint8 keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN]
- * encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode
- * encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode
- * PRBool ticketKeysValid;
- * sidCacheLock srvNameCacheLock;
- * srvNameCacheEntry srvNameData[ numSrvNameCacheEntries ];
- * } cacheMemCacheData;
- */
-#include "seccomon.h"
-
-#if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_OS2) || defined(XP_BEOS)
-
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-#include "sslproto.h"
-#include "pk11func.h"
-#include "base64.h"
-#include "keyhi.h"
-#ifdef NO_PKCS11_BYPASS
-#include "blapit.h"
-#include "sechash.h"
-#else
-#include "blapi.h"
-#endif
-
-#include <stdio.h>
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#include <syslog.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include "unix_err.h"
-
-#else
-
-#ifdef XP_WIN32
-#include <wtypes.h>
-#include "win32err.h"
-#endif
-
-#endif
-#include <sys/types.h>
-
-#define SET_ERROR_CODE /* reminder */
-
-#include "nspr.h"
-#include "sslmutex.h"
-
-/*
-** Format of a cache entry in the shared memory.
-*/
-struct sidCacheEntryStr {
- /* 16 */ PRIPv6Addr addr; /* client's IP address */
- /* 4 */ PRUint32 creationTime;
- /* 4 */ PRUint32 lastAccessTime;
- /* 4 */ PRUint32 expirationTime;
- /* 2 */ PRUint16 version;
- /* 1 */ PRUint8 valid;
- /* 1 */ PRUint8 sessionIDLength;
- /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES];
- /* 2 */ PRUint16 authAlgorithm;
- /* 2 */ PRUint16 authKeyBits;
- /* 2 */ PRUint16 keaType;
- /* 2 */ PRUint16 keaKeyBits;
- /* 72 - common header total */
-
- union {
- struct {
- /* 64 */ PRUint8 masterKey[SSL_MAX_MASTER_KEY_BYTES];
- /* 32 */ PRUint8 cipherArg[SSL_MAX_CYPHER_ARG_BYTES];
-
- /* 1 */ PRUint8 cipherType;
- /* 1 */ PRUint8 masterKeyLen;
- /* 1 */ PRUint8 keyBits;
- /* 1 */ PRUint8 secretKeyBits;
- /* 1 */ PRUint8 cipherArgLen;
-/*101 */} ssl2;
-
-struct {
- /* 2 */ ssl3CipherSuite cipherSuite;
- /* 2 */ PRUint16 compression; /* SSLCompressionMethod */
-
- /* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */
-
- /* 4 */ PRUint32 masterWrapMech;
- /* 4 */ SSL3KEAType exchKeyType;
- /* 4 */ PRInt32 certIndex;
- /* 4 */ PRInt32 srvNameIndex;
- /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
-/*108 */} ssl3;
-
-/* force sizeof(sidCacheEntry) to be a multiple of cache line size */
-struct {
- /*120 */ PRUint8 filler[120]; /* 72+120==192, a multiple of 16 */
-} forceSize;
- } u;
-};
-typedef struct sidCacheEntryStr sidCacheEntry;
-
-/* The length of this struct is supposed to be a power of 2, e.g. 4KB */
-struct certCacheEntryStr {
- PRUint16 certLength; /* 2 */
- PRUint16 sessionIDLength; /* 2 */
- PRUint8 sessionID[SSL3_SESSIONID_BYTES]; /* 32 */
- PRUint8 cert[SSL_MAX_CACHED_CERT_LEN]; /* 4060 */
-}; /* total 4096 */
-typedef struct certCacheEntryStr certCacheEntry;
-
-struct sidCacheLockStr {
- PRUint32 timeStamp;
- sslMutex mutex;
- sslPID pid;
-};
-typedef struct sidCacheLockStr sidCacheLock;
-
-struct sidCacheSetStr {
- PRIntn next;
-};
-typedef struct sidCacheSetStr sidCacheSet;
-
-struct encKeyCacheEntryStr {
- PRUint8 bytes[512];
- PRInt32 length;
-};
-typedef struct encKeyCacheEntryStr encKeyCacheEntry;
-
-#define SSL_MAX_DNS_HOST_NAME 1024
-
-struct srvNameCacheEntryStr {
- PRUint16 type; /* 2 */
- PRUint16 nameLen; /* 2 */
- PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
- PRUint8 nameHash[SHA256_LENGTH]; /* 32 */
- /* 1072 */
-};
-typedef struct srvNameCacheEntryStr srvNameCacheEntry;
-
-struct cacheDescStr {
-
- PRUint32 cacheMemSize;
-
- PRUint32 numSIDCacheLocks;
- PRUint32 numSIDCacheSets;
- PRUint32 numSIDCacheSetsPerLock;
-
- PRUint32 numSIDCacheEntries;
- PRUint32 sidCacheSize;
-
- PRUint32 numCertCacheEntries;
- PRUint32 certCacheSize;
-
- PRUint32 numKeyCacheEntries;
- PRUint32 keyCacheSize;
-
- PRUint32 numSrvNameCacheEntries;
- PRUint32 srvNameCacheSize;
-
- PRUint32 ssl2Timeout;
- PRUint32 ssl3Timeout;
-
- PRUint32 numSIDCacheLocksInitialized;
-
- /* These values are volatile, and are accessed through sharedCache-> */
- PRUint32 nextCertCacheEntry; /* certCacheLock protects */
- PRBool stopPolling;
- PRBool everInherited;
-
- /* The private copies of these values are pointers into shared mem */
- /* The copies of these values in shared memory are merely offsets */
- sidCacheLock *sidCacheLocks;
- sidCacheLock *keyCacheLock;
- sidCacheLock *certCacheLock;
- sidCacheLock *srvNameCacheLock;
- sidCacheSet *sidCacheSets;
- sidCacheEntry *sidCacheData;
- certCacheEntry *certCacheData;
- SSLWrappedSymWrappingKey *keyCacheData;
- PRUint8 *ticketKeyNameSuffix;
- encKeyCacheEntry *ticketEncKey;
- encKeyCacheEntry *ticketMacKey;
- PRUint32 *ticketKeysValid;
- srvNameCacheEntry *srvNameCacheData;
-
- /* Only the private copies of these pointers are valid */
- char *cacheMem;
- struct cacheDescStr *sharedCache; /* shared copy of this struct */
- PRFileMap *cacheMemMap;
- PRThread *poller;
- PRUint32 mutexTimeout;
- PRBool shared;
-};
-typedef struct cacheDescStr cacheDesc;
-
-static cacheDesc globalCache;
-
-static const char envVarName[] = { SSL_ENV_VAR_NAME };
-
-static PRBool isMultiProcess = PR_FALSE;
-
-#define DEF_SID_CACHE_ENTRIES 10000
-#define DEF_CERT_CACHE_ENTRIES 250
-#define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
-#define DEF_KEY_CACHE_ENTRIES 250
-#define DEF_NAME_CACHE_ENTRIES 1000
-
-#define SID_CACHE_ENTRIES_PER_SET 128
-#define SID_ALIGNMENT 16
-
-#define DEF_SSL2_TIMEOUT 100 /* seconds */
-#define MAX_SSL2_TIMEOUT 100 /* seconds */
-#define MIN_SSL2_TIMEOUT 5 /* seconds */
-
-#define DEF_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MAX_SSL3_TIMEOUT 86400L /* 24 hours */
-#define MIN_SSL3_TIMEOUT 5 /* seconds */
-
-#if defined(AIX) || defined(LINUX) || defined(NETBSD) || defined(OPENBSD)
-#define MAX_SID_CACHE_LOCKS 8 /* two FDs per lock */
-#elif defined(OSF1)
-#define MAX_SID_CACHE_LOCKS 16 /* one FD per lock */
-#else
-#define MAX_SID_CACHE_LOCKS 256
-#endif
-
-#define SID_HOWMANY(val, size) (((val) + ((size)-1)) / (size))
-#define SID_ROUNDUP(val, size) ((size)*SID_HOWMANY((val), (size)))
-
-static sslPID myPid;
-static PRUint32 ssl_max_sid_cache_locks = MAX_SID_CACHE_LOCKS;
-
-/* forward static function declarations */
-static PRUint32 SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s,
- unsigned nl);
-static SECStatus LaunchLockPoller(cacheDesc *cache);
-static SECStatus StopLockPoller(cacheDesc *cache);
-
-struct inheritanceStr {
- PRUint32 cacheMemSize;
- PRUint32 fmStrLen;
-};
-
-typedef struct inheritanceStr inheritance;
-
-#if defined(_WIN32) || defined(XP_OS2)
-
-#define DEFAULT_CACHE_DIRECTORY "\\temp"
-
-#endif /* _win32 */
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#define DEFAULT_CACHE_DIRECTORY "/tmp"
-
-#endif /* XP_UNIX || XP_BEOS */
-
-/************************************************************************/
-
-static PRUint32
-LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
-{
- SECStatus rv = sslMutex_Lock(&lock->mutex);
- if (rv != SECSuccess)
- return 0;
- if (!now)
- now = ssl_Time();
- lock->timeStamp = now;
- lock->pid = myPid;
- return now;
-}
-
-static SECStatus
-UnlockSidCacheLock(sidCacheLock *lock)
-{
- SECStatus rv;
-
- lock->pid = 0;
- rv = sslMutex_Unlock(&lock->mutex);
- return rv;
-}
-
-/* returns the value of ssl_Time on success, zero on failure. */
-static PRUint32
-LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
-{
- PRUint32 lockNum = set % cache->numSIDCacheLocks;
- sidCacheLock *lock = cache->sidCacheLocks + lockNum;
-
- return LockSidCacheLock(lock, now);
-}
-
-static SECStatus
-UnlockSet(cacheDesc *cache, PRUint32 set)
-{
- PRUint32 lockNum = set % cache->numSIDCacheLocks;
- sidCacheLock *lock = cache->sidCacheLocks + lockNum;
-
- return UnlockSidCacheLock(lock);
-}
-
-/************************************************************************/
-
-/* Put a certificate in the cache. Update the cert index in the sce.
-*/
-static PRUint32
-CacheCert(cacheDesc *cache, CERTCertificate *cert, sidCacheEntry *sce)
-{
- PRUint32 now;
- certCacheEntry cce;
-
- if ((cert->derCert.len > SSL_MAX_CACHED_CERT_LEN) ||
- (cert->derCert.len <= 0) ||
- (cert->derCert.data == NULL)) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return 0;
- }
-
- cce.sessionIDLength = sce->sessionIDLength;
- PORT_Memcpy(cce.sessionID, sce->sessionID, cce.sessionIDLength);
-
- cce.certLength = cert->derCert.len;
- PORT_Memcpy(cce.cert, cert->derCert.data, cce.certLength);
-
- /* get lock on cert cache */
- now = LockSidCacheLock(cache->certCacheLock, 0);
- if (now) {
-
- /* Find where to place the next cert cache entry. */
- cacheDesc *sharedCache = cache->sharedCache;
- PRUint32 ndx = sharedCache->nextCertCacheEntry;
-
- /* write the entry */
- cache->certCacheData[ndx] = cce;
-
- /* remember where we put it. */
- sce->u.ssl3.certIndex = ndx;
-
- /* update the "next" cache entry index */
- sharedCache->nextCertCacheEntry =
- (ndx + 1) % cache->numCertCacheEntries;
-
- UnlockSidCacheLock(cache->certCacheLock);
- }
- return now;
-}
-
-/* Server configuration hash tables need to account the SECITEM.type
- * field as well. These functions accomplish that. */
-static PLHashNumber
-Get32BitNameHash(const SECItem *name)
-{
- PLHashNumber rv = SECITEM_Hash(name);
-
- PRUint8 *rvc = (PRUint8 *)&rv;
- rvc[name->len % sizeof(rv)] ^= name->type;
-
- return rv;
-}
-
-/* Put a name in the cache. Update the cert index in the sce.
-*/
-static PRUint32
-CacheSrvName(cacheDesc *cache, SECItem *name, sidCacheEntry *sce)
-{
- PRUint32 now;
- PRUint32 ndx;
- srvNameCacheEntry snce;
-
- if (!name || name->len <= 0 ||
- name->len > SSL_MAX_DNS_HOST_NAME) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return 0;
- }
-
- snce.type = name->type;
- snce.nameLen = name->len;
- PORT_Memcpy(snce.name, name->data, snce.nameLen);
-#ifdef NO_PKCS11_BYPASS
- HASH_HashBuf(HASH_AlgSHA256, snce.nameHash, name->data, name->len);
-#else
- SHA256_HashBuf(snce.nameHash, (unsigned char *)name->data,
- name->len);
-#endif
- /* get index of the next name */
- ndx = Get32BitNameHash(name);
- /* get lock on cert cache */
- now = LockSidCacheLock(cache->srvNameCacheLock, 0);
- if (now) {
- if (cache->numSrvNameCacheEntries > 0) {
- /* Fit the index into array */
- ndx %= cache->numSrvNameCacheEntries;
- /* write the entry */
- cache->srvNameCacheData[ndx] = snce;
- /* remember where we put it. */
- sce->u.ssl3.srvNameIndex = ndx;
- /* Copy hash into sid hash */
- PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
- }
- UnlockSidCacheLock(cache->srvNameCacheLock);
- }
- return now;
-}
-
-/*
-** Convert local SID to shared memory one
-*/
-static void
-ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
-{
- to->valid = 1;
- to->version = from->version;
- to->addr = from->addr;
- to->creationTime = from->creationTime;
- to->lastAccessTime = from->lastAccessTime;
- to->expirationTime = from->expirationTime;
- to->authAlgorithm = from->authAlgorithm;
- to->authKeyBits = from->authKeyBits;
- to->keaType = from->keaType;
- to->keaKeyBits = from->keaKeyBits;
-
- if (from->version < SSL_LIBRARY_VERSION_3_0) {
- if ((from->u.ssl2.masterKey.len > SSL_MAX_MASTER_KEY_BYTES) ||
- (from->u.ssl2.cipherArg.len > SSL_MAX_CYPHER_ARG_BYTES)) {
- SSL_DBG(("%d: SSL: masterKeyLen=%d cipherArgLen=%d",
- myPid, from->u.ssl2.masterKey.len,
- from->u.ssl2.cipherArg.len));
- to->valid = 0;
- return;
- }
-
- to->u.ssl2.cipherType = from->u.ssl2.cipherType;
- to->u.ssl2.masterKeyLen = from->u.ssl2.masterKey.len;
- to->u.ssl2.cipherArgLen = from->u.ssl2.cipherArg.len;
- to->u.ssl2.keyBits = from->u.ssl2.keyBits;
- to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
- to->sessionIDLength = SSL2_SESSIONID_BYTES;
- PORT_Memcpy(to->sessionID, from->u.ssl2.sessionID, SSL2_SESSIONID_BYTES);
- PORT_Memcpy(to->u.ssl2.masterKey, from->u.ssl2.masterKey.data,
- from->u.ssl2.masterKey.len);
- PORT_Memcpy(to->u.ssl2.cipherArg, from->u.ssl2.cipherArg.data,
- from->u.ssl2.cipherArg.len);
-#ifdef DEBUG
- PORT_Memset(to->u.ssl2.masterKey + from->u.ssl2.masterKey.len, 0,
- sizeof(to->u.ssl2.masterKey) - from->u.ssl2.masterKey.len);
- PORT_Memset(to->u.ssl2.cipherArg + from->u.ssl2.cipherArg.len, 0,
- sizeof(to->u.ssl2.cipherArg) - from->u.ssl2.cipherArg.len);
-#endif
- SSL_TRC(8, ("%d: SSL: ConvertSID: masterKeyLen=%d cipherArgLen=%d "
- "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
- myPid,
- to->u.ssl2.masterKeyLen, to->u.ssl2.cipherArgLen,
- to->creationTime, to->addr.pr_s6_addr32[0],
- to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
- to->addr.pr_s6_addr32[3], to->u.ssl2.cipherType));
- } else {
- /* This is an SSL v3 session */
-
- to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
- to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
- to->u.ssl3.keys = from->u.ssl3.keys;
- to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
- to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
- to->sessionIDLength = from->u.ssl3.sessionIDLength;
- to->u.ssl3.certIndex = -1;
- to->u.ssl3.srvNameIndex = -1;
- PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
- to->sessionIDLength);
-
- SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x "
- "cipherSuite=%d",
- myPid, to->creationTime, to->addr.pr_s6_addr32[0],
- to->addr.pr_s6_addr32[1], to->addr.pr_s6_addr32[2],
- to->addr.pr_s6_addr32[3], to->u.ssl3.cipherSuite));
- }
-}
-
-/*
-** Convert shared memory cache-entry to local memory based one
-** This is only called from ServerSessionIDLookup().
-*/
-static sslSessionID *
-ConvertToSID(sidCacheEntry *from,
- certCacheEntry *pcce,
- srvNameCacheEntry *psnce,
- CERTCertDBHandle *dbHandle)
-{
- sslSessionID *to;
- PRUint16 version = from->version;
-
- to = PORT_ZNew(sslSessionID);
- if (!to) {
- return 0;
- }
-
- if (version < SSL_LIBRARY_VERSION_3_0) {
- /* This is an SSL v2 session */
- to->u.ssl2.masterKey.data =
- (unsigned char *)PORT_Alloc(from->u.ssl2.masterKeyLen);
- if (!to->u.ssl2.masterKey.data) {
- goto loser;
- }
- if (from->u.ssl2.cipherArgLen) {
- to->u.ssl2.cipherArg.data =
- (unsigned char *)PORT_Alloc(from->u.ssl2.cipherArgLen);
- if (!to->u.ssl2.cipherArg.data) {
- goto loser;
- }
- PORT_Memcpy(to->u.ssl2.cipherArg.data, from->u.ssl2.cipherArg,
- from->u.ssl2.cipherArgLen);
- }
-
- to->u.ssl2.cipherType = from->u.ssl2.cipherType;
- to->u.ssl2.masterKey.len = from->u.ssl2.masterKeyLen;
- to->u.ssl2.cipherArg.len = from->u.ssl2.cipherArgLen;
- to->u.ssl2.keyBits = from->u.ssl2.keyBits;
- to->u.ssl2.secretKeyBits = from->u.ssl2.secretKeyBits;
- /* to->sessionIDLength = SSL2_SESSIONID_BYTES; */
- PORT_Memcpy(to->u.ssl2.sessionID, from->sessionID, SSL2_SESSIONID_BYTES);
- PORT_Memcpy(to->u.ssl2.masterKey.data, from->u.ssl2.masterKey,
- from->u.ssl2.masterKeyLen);
-
- SSL_TRC(8, ("%d: SSL: ConvertToSID: masterKeyLen=%d cipherArgLen=%d "
- "time=%d addr=0x%08x%08x%08x%08x cipherType=%d",
- myPid, to->u.ssl2.masterKey.len,
- to->u.ssl2.cipherArg.len, to->creationTime,
- to->addr.pr_s6_addr32[0], to->addr.pr_s6_addr32[1],
- to->addr.pr_s6_addr32[2], to->addr.pr_s6_addr32[3],
- to->u.ssl2.cipherType));
- } else {
- /* This is an SSL v3 session */
-
- to->u.ssl3.sessionIDLength = from->sessionIDLength;
- to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
- to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression;
- to->u.ssl3.keys = from->u.ssl3.keys;
- to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
- to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
- if (from->u.ssl3.srvNameIndex != -1 && psnce) {
- SECItem name;
- SECStatus rv;
- name.type = psnce->type;
- name.len = psnce->nameLen;
- name.data = psnce->name;
- rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
- if (rv != SECSuccess) {
- goto loser;
- }
- }
-
- PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
-
- /* the portions of the SID that are only restored on the client
- * are set to invalid values on the server.
- */
- to->u.ssl3.clientWriteKey = NULL;
- to->u.ssl3.serverWriteKey = NULL;
-
- to->urlSvrName = NULL;
-
- to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */
- to->u.ssl3.masterSlotID = (CK_SLOT_ID)-1; /* invalid value */
- to->u.ssl3.masterWrapIndex = 0;
- to->u.ssl3.masterWrapSeries = 0;
- to->u.ssl3.masterValid = PR_FALSE;
-
- to->u.ssl3.clAuthModuleID = (SECMODModuleID)-1; /* invalid value */
- to->u.ssl3.clAuthSlotID = (CK_SLOT_ID)-1; /* invalid value */
- to->u.ssl3.clAuthSeries = 0;
- to->u.ssl3.clAuthValid = PR_FALSE;
-
- if (from->u.ssl3.certIndex != -1 && pcce) {
- SECItem derCert;
-
- derCert.len = pcce->certLength;
- derCert.data = pcce->cert;
-
- to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL,
- PR_FALSE, PR_TRUE);
- if (to->peerCert == NULL)
- goto loser;
- }
- }
-
- to->version = from->version;
- to->creationTime = from->creationTime;
- to->lastAccessTime = from->lastAccessTime;
- to->expirationTime = from->expirationTime;
- to->cached = in_server_cache;
- to->addr = from->addr;
- to->references = 1;
- to->authAlgorithm = from->authAlgorithm;
- to->authKeyBits = from->authKeyBits;
- to->keaType = from->keaType;
- to->keaKeyBits = from->keaKeyBits;
-
- return to;
-
-loser:
- if (to) {
- if (version < SSL_LIBRARY_VERSION_3_0) {
- if (to->u.ssl2.masterKey.data)
- PORT_Free(to->u.ssl2.masterKey.data);
- if (to->u.ssl2.cipherArg.data)
- PORT_Free(to->u.ssl2.cipherArg.data);
- } else {
- SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
- }
- PORT_Free(to);
- }
- return NULL;
-}
-
-/*
-** Perform some mumbo jumbo on the ip-address and the session-id value to
-** compute a hash value.
-*/
-static PRUint32
-SIDindex(cacheDesc *cache, const PRIPv6Addr *addr, PRUint8 *s, unsigned nl)
-{
- PRUint32 rv;
- PRUint32 x[8];
-
- memset(x, 0, sizeof x);
- if (nl > sizeof x)
- nl = sizeof x;
- memcpy(x, s, nl);
-
- rv = (addr->pr_s6_addr32[0] ^ addr->pr_s6_addr32[1] ^
- addr->pr_s6_addr32[2] ^ addr->pr_s6_addr32[3] ^
- x[0] ^ x[1] ^ x[2] ^ x[3] ^ x[4] ^ x[5] ^ x[6] ^ x[7]) %
- cache->numSIDCacheSets;
- return rv;
-}
-
-/*
-** Look something up in the cache. This will invalidate old entries
-** in the process. Caller has locked the cache set!
-** Returns PR_TRUE if found a valid match. PR_FALSE otherwise.
-*/
-static sidCacheEntry *
-FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
- const PRIPv6Addr *addr, unsigned char *sessionID,
- unsigned sessionIDLength)
-{
- PRUint32 ndx = cache->sidCacheSets[setNum].next;
- int i;
-
- sidCacheEntry *set = cache->sidCacheData +
- (setNum * SID_CACHE_ENTRIES_PER_SET);
-
- for (i = SID_CACHE_ENTRIES_PER_SET; i > 0; --i) {
- sidCacheEntry *sce;
-
- ndx = (ndx - 1) % SID_CACHE_ENTRIES_PER_SET;
- sce = set + ndx;
-
- if (!sce->valid)
- continue;
-
- if (now > sce->expirationTime) {
- /* SessionID has timed out. Invalidate the entry. */
- SSL_TRC(7, ("%d: timed out sid entry addr=%08x%08x%08x%08x now=%x "
- "time+=%x",
- myPid, sce->addr.pr_s6_addr32[0],
- sce->addr.pr_s6_addr32[1], sce->addr.pr_s6_addr32[2],
- sce->addr.pr_s6_addr32[3], now,
- sce->expirationTime));
- sce->valid = 0;
- continue;
- }
-
- /*
- ** Next, examine specific session-id/addr data to see if the cache
- ** entry matches our addr+session-id value
- */
- if (sessionIDLength == sce->sessionIDLength &&
- !memcmp(&sce->addr, addr, sizeof(PRIPv6Addr)) &&
- !memcmp(sce->sessionID, sessionID, sessionIDLength)) {
- /* Found it */
- return sce;
- }
- }
-
- PORT_SetError(SSL_ERROR_SESSION_NOT_FOUND);
- return NULL;
-}
-
-/************************************************************************/
-
-/* This is the primary function for finding entries in the server's sid cache.
- * Although it is static, this function is called via the global function
- * pointer ssl_sid_lookup.
- */
-static sslSessionID *
-ServerSessionIDLookup(const PRIPv6Addr *addr,
- unsigned char *sessionID,
- unsigned int sessionIDLength,
- CERTCertDBHandle *dbHandle)
-{
- sslSessionID *sid = 0;
- sidCacheEntry *psce;
- certCacheEntry *pcce = 0;
- srvNameCacheEntry *psnce = 0;
- cacheDesc *cache = &globalCache;
- PRUint32 now;
- PRUint32 set;
- PRInt32 cndx;
- sidCacheEntry sce;
- certCacheEntry cce;
- srvNameCacheEntry snce;
-
- set = SIDindex(cache, addr, sessionID, sessionIDLength);
- now = LockSet(cache, set, 0);
- if (!now)
- return NULL;
-
- psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
- if (psce) {
- if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
- if ((cndx = psce->u.ssl3.certIndex) != -1) {
-
- PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
- if (gotLock) {
- pcce = &cache->certCacheData[cndx];
-
- /* See if the cert's session ID matches the sce cache. */
- if ((pcce->sessionIDLength == psce->sessionIDLength) &&
- !PORT_Memcmp(pcce->sessionID, psce->sessionID,
- pcce->sessionIDLength)) {
- cce = *pcce;
- } else {
- /* The cert doesen't match the SID cache entry,
- ** so invalidate the SID cache entry.
- */
- psce->valid = 0;
- psce = 0;
- pcce = 0;
- }
- UnlockSidCacheLock(cache->certCacheLock);
- } else {
- /* what the ??. Didn't get the cert cache lock.
- ** Don't invalidate the SID cache entry, but don't find it.
- */
- PORT_Assert(!("Didn't get cert Cache Lock!"));
- psce = 0;
- pcce = 0;
- }
- }
- if (psce && ((cndx = psce->u.ssl3.srvNameIndex) != -1)) {
- PRUint32 gotLock = LockSidCacheLock(cache->srvNameCacheLock,
- now);
- if (gotLock) {
- psnce = &cache->srvNameCacheData[cndx];
-
- if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
- SHA256_LENGTH)) {
- snce = *psnce;
- } else {
- /* The name doesen't match the SID cache entry,
- ** so invalidate the SID cache entry.
- */
- psce->valid = 0;
- psce = 0;
- psnce = 0;
- }
- UnlockSidCacheLock(cache->srvNameCacheLock);
- } else {
- /* what the ??. Didn't get the cert cache lock.
- ** Don't invalidate the SID cache entry, but don't find it.
- */
- PORT_Assert(!("Didn't get name Cache Lock!"));
- psce = 0;
- psnce = 0;
- }
- }
- }
- if (psce) {
- psce->lastAccessTime = now;
- sce = *psce; /* grab a copy while holding the lock */
- }
- }
- UnlockSet(cache, set);
- if (psce) {
- /* sce conains a copy of the cache entry.
- ** Convert shared memory format to local format
- */
- sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
- }
- return sid;
-}
-
-/*
-** Place a sid into the cache, if it isn't already there.
-*/
-static void
-ServerSessionIDCache(sslSessionID *sid)
-{
- sidCacheEntry sce;
- PRUint32 now = 0;
- PRUint16 version = sid->version;
- cacheDesc *cache = &globalCache;
-
- if ((version >= SSL_LIBRARY_VERSION_3_0) &&
- (sid->u.ssl3.sessionIDLength == 0)) {
- return;
- }
-
- if (sid->cached == never_cached || sid->cached == invalid_cache) {
- PRUint32 set;
-
- PORT_Assert(sid->creationTime != 0);
- if (!sid->creationTime)
- sid->lastAccessTime = sid->creationTime = ssl_Time();
- if (version < SSL_LIBRARY_VERSION_3_0) {
- /* override caller's expiration time, which uses client timeout
- * duration, not server timeout duration.
- */
- sid->expirationTime = sid->creationTime + cache->ssl2Timeout;
- SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipher=%d",
- myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl2.cipherType));
- PRINT_BUF(8, (0, "sessionID:", sid->u.ssl2.sessionID,
- SSL2_SESSIONID_BYTES));
- PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
- sid->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
- sid->u.ssl2.cipherArg.len));
- } else {
- /* override caller's expiration time, which uses client timeout
- * duration, not server timeout duration.
- */
- sid->expirationTime = sid->creationTime + cache->ssl3Timeout;
- SSL_TRC(8, ("%d: SSL: CacheMT: cached=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipherSuite=%d",
- myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl3.cipherSuite));
- PRINT_BUF(8, (0, "sessionID:", sid->u.ssl3.sessionID,
- sid->u.ssl3.sessionIDLength));
- }
-
- ConvertFromSID(&sce, sid);
-
- if (version >= SSL_LIBRARY_VERSION_3_0) {
- SECItem *name = &sid->u.ssl3.srvName;
- if (name->len && name->data) {
- now = CacheSrvName(cache, name, &sce);
- }
- if (sid->peerCert != NULL) {
- now = CacheCert(cache, sid->peerCert, &sce);
- }
- }
-
- set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
- now = LockSet(cache, set, now);
- if (now) {
- PRUint32 next = cache->sidCacheSets[set].next;
- PRUint32 ndx = set * SID_CACHE_ENTRIES_PER_SET + next;
-
- /* Write out new cache entry */
- cache->sidCacheData[ndx] = sce;
-
- cache->sidCacheSets[set].next =
- (next + 1) % SID_CACHE_ENTRIES_PER_SET;
-
- UnlockSet(cache, set);
- sid->cached = in_server_cache;
- }
- }
-}
-
-/*
-** Although this is static, it is called from ssl via global function pointer
-** ssl_sid_uncache. This invalidates the referenced cache entry.
-*/
-static void
-ServerSessionIDUncache(sslSessionID *sid)
-{
- cacheDesc *cache = &globalCache;
- PRUint8 *sessionID;
- unsigned int sessionIDLength;
- PRErrorCode err;
- PRUint32 set;
- PRUint32 now;
- sidCacheEntry *psce;
-
- if (sid == NULL)
- return;
-
- /* Uncaching a SID should never change the error code.
- ** So save it here and restore it before exiting.
- */
- err = PR_GetError();
-
- if (sid->version < SSL_LIBRARY_VERSION_3_0) {
- sessionID = sid->u.ssl2.sessionID;
- sessionIDLength = SSL2_SESSIONID_BYTES;
- SSL_TRC(8, ("%d: SSL: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipher=%d",
- myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl2.cipherType));
- PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
- PRINT_BUF(8, (0, "masterKey:", sid->u.ssl2.masterKey.data,
- sid->u.ssl2.masterKey.len));
- PRINT_BUF(8, (0, "cipherArg:", sid->u.ssl2.cipherArg.data,
- sid->u.ssl2.cipherArg.len));
- } else {
- sessionID = sid->u.ssl3.sessionID;
- sessionIDLength = sid->u.ssl3.sessionIDLength;
- SSL_TRC(8, ("%d: SSL3: UncacheMT: valid=%d addr=0x%08x%08x%08x%08x time=%x "
- "cipherSuite=%d",
- myPid, sid->cached,
- sid->addr.pr_s6_addr32[0], sid->addr.pr_s6_addr32[1],
- sid->addr.pr_s6_addr32[2], sid->addr.pr_s6_addr32[3],
- sid->creationTime, sid->u.ssl3.cipherSuite));
- PRINT_BUF(8, (0, "sessionID:", sessionID, sessionIDLength));
- }
- set = SIDindex(cache, &sid->addr, sessionID, sessionIDLength);
- now = LockSet(cache, set, 0);
- if (now) {
- psce = FindSID(cache, set, now, &sid->addr, sessionID, sessionIDLength);
- if (psce) {
- psce->valid = 0;
- }
- UnlockSet(cache, set);
- }
- sid->cached = invalid_cache;
- PORT_SetError(err);
-}
-
-#ifdef XP_OS2
-
-#define INCL_DOSPROCESS
-#include <os2.h>
-
-long
-gettid(void)
-{
- PTIB ptib;
- PPIB ppib;
- DosGetInfoBlocks(&ptib, &ppib);
- return ((long)ptib->tib_ordinal); /* thread id */
-}
-#endif
-
-static void
-CloseCache(cacheDesc *cache)
-{
- int locks_initialized = cache->numSIDCacheLocksInitialized;
-
- if (cache->cacheMem) {
- if (cache->sharedCache) {
- sidCacheLock *pLock = cache->sidCacheLocks;
- for (; locks_initialized > 0; --locks_initialized, ++pLock) {
- /* If everInherited is true, this shared cache was (and may
- ** still be) in use by multiple processes. We do not wish to
- ** destroy the mutexes while they are still in use, but we do
- ** want to free mutex resources associated with this process.
- */
- sslMutex_Destroy(&pLock->mutex,
- cache->sharedCache->everInherited);
- }
- }
- if (cache->shared) {
- PR_MemUnmap(cache->cacheMem, cache->cacheMemSize);
- } else {
- PORT_Free(cache->cacheMem);
- }
- cache->cacheMem = NULL;
- }
- if (cache->cacheMemMap) {
- PR_CloseFileMap(cache->cacheMemMap);
- cache->cacheMemMap = NULL;
- }
- memset(cache, 0, sizeof *cache);
-}
-
-static SECStatus
-InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
- int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout, const char *directory, PRBool shared)
-{
- ptrdiff_t ptr;
- sidCacheLock *pLock;
- char *cacheMem;
- PRFileMap *cacheMemMap;
- char *cfn = NULL; /* cache file name */
- int locks_initialized = 0;
- int locks_to_initialize = 0;
- PRUint32 init_time;
-
- if ((!cache) || (maxCacheEntries < 0) || (!directory)) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
-
- if (cache->cacheMem) {
- /* Already done */
- return SECSuccess;
- }
-
- /* make sure loser can clean up properly */
- cache->shared = shared;
- cache->cacheMem = cacheMem = NULL;
- cache->cacheMemMap = cacheMemMap = NULL;
- cache->sharedCache = (cacheDesc *)0;
-
- cache->numSIDCacheLocksInitialized = 0;
- cache->nextCertCacheEntry = 0;
- cache->stopPolling = PR_FALSE;
- cache->everInherited = PR_FALSE;
- cache->poller = NULL;
- cache->mutexTimeout = 0;
-
- cache->numSIDCacheEntries = maxCacheEntries ? maxCacheEntries
- : DEF_SID_CACHE_ENTRIES;
- cache->numSIDCacheSets =
- SID_HOWMANY(cache->numSIDCacheEntries, SID_CACHE_ENTRIES_PER_SET);
-
- cache->numSIDCacheEntries =
- cache->numSIDCacheSets * SID_CACHE_ENTRIES_PER_SET;
-
- cache->numSIDCacheLocks =
- PR_MIN(cache->numSIDCacheSets, ssl_max_sid_cache_locks);
-
- cache->numSIDCacheSetsPerLock =
- SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
-
- cache->numCertCacheEntries = (maxCertCacheEntries > 0) ? maxCertCacheEntries
- : 0;
- cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries >= 0) ? maxSrvNameCacheEntries
- : DEF_NAME_CACHE_ENTRIES;
-
- /* compute size of shared memory, and offsets of all pointers */
- ptr = 0;
- cache->cacheMem = (char *)ptr;
- ptr += SID_ROUNDUP(sizeof(cacheDesc), SID_ALIGNMENT);
-
- cache->sidCacheLocks = (sidCacheLock *)ptr;
- cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
- cache->certCacheLock = cache->keyCacheLock + 1;
- cache->srvNameCacheLock = cache->certCacheLock + 1;
- ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->sidCacheSets = (sidCacheSet *)ptr;
- ptr = (ptrdiff_t)(cache->sidCacheSets + cache->numSIDCacheSets);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->sidCacheData = (sidCacheEntry *)ptr;
- ptr = (ptrdiff_t)(cache->sidCacheData + cache->numSIDCacheEntries);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->certCacheData = (certCacheEntry *)ptr;
- cache->sidCacheSize =
- (char *)cache->certCacheData - (char *)cache->sidCacheData;
-
- if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
- /* This is really a poor way to computer this! */
- cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
- if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
- cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
- }
- ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)ptr;
- cache->certCacheSize =
- (char *)cache->keyCacheData - (char *)cache->certCacheData;
-
- cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS;
- ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->keyCacheSize = (char *)ptr - (char *)cache->keyCacheData;
-
- cache->ticketKeyNameSuffix = (PRUint8 *)ptr;
- ptr = (ptrdiff_t)(cache->ticketKeyNameSuffix +
- SESS_TICKET_KEY_VAR_NAME_LEN);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->ticketEncKey = (encKeyCacheEntry *)ptr;
- ptr = (ptrdiff_t)(cache->ticketEncKey + 1);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->ticketMacKey = (encKeyCacheEntry *)ptr;
- ptr = (ptrdiff_t)(cache->ticketMacKey + 1);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->ticketKeysValid = (PRUint32 *)ptr;
- ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->srvNameCacheData = (srvNameCacheEntry *)ptr;
- cache->srvNameCacheSize =
- cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry);
- ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries);
- ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
-
- cache->cacheMemSize = ptr;
-
- if (ssl2_timeout) {
- if (ssl2_timeout > MAX_SSL2_TIMEOUT) {
- ssl2_timeout = MAX_SSL2_TIMEOUT;
- }
- if (ssl2_timeout < MIN_SSL2_TIMEOUT) {
- ssl2_timeout = MIN_SSL2_TIMEOUT;
- }
- cache->ssl2Timeout = ssl2_timeout;
- } else {
- cache->ssl2Timeout = DEF_SSL2_TIMEOUT;
- }
-
- if (ssl3_timeout) {
- if (ssl3_timeout > MAX_SSL3_TIMEOUT) {
- ssl3_timeout = MAX_SSL3_TIMEOUT;
- }
- if (ssl3_timeout < MIN_SSL3_TIMEOUT) {
- ssl3_timeout = MIN_SSL3_TIMEOUT;
- }
- cache->ssl3Timeout = ssl3_timeout;
- } else {
- cache->ssl3Timeout = DEF_SSL3_TIMEOUT;
- }
-
- if (shared) {
- /* Create file names */
-#if defined(XP_UNIX) || defined(XP_BEOS)
- /* there's some confusion here about whether PR_OpenAnonFileMap wants
- ** a directory name or a file name for its first argument.
- cfn = PR_smprintf("%s/.sslsvrcache.%d", directory, myPid);
- */
- cfn = PR_smprintf("%s", directory);
-#elif defined(XP_WIN32)
- cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
- GetCurrentThreadId());
-#elif defined(XP_OS2)
- cfn = PR_smprintf("%s/svrcache_%d_%x.ssl", directory, myPid,
- gettid());
-#else
-#error "Don't know how to create file name for this platform!"
-#endif
- if (!cfn) {
- goto loser;
- }
-
- /* Create cache */
- cacheMemMap = PR_OpenAnonFileMap(cfn, cache->cacheMemSize,
- PR_PROT_READWRITE);
-
- PR_smprintf_free(cfn);
- if (!cacheMemMap) {
- goto loser;
- }
-
- cacheMem = PR_MemMap(cacheMemMap, 0, cache->cacheMemSize);
- } else {
- cacheMem = PORT_Alloc(cache->cacheMemSize);
- }
-
- if (!cacheMem) {
- goto loser;
- }
-
- /* Initialize shared memory. This may not be necessary on all platforms */
- memset(cacheMem, 0, cache->cacheMemSize);
-
- /* Copy cache descriptor header into shared memory */
- memcpy(cacheMem, cache, sizeof *cache);
-
- /* save private copies of these values */
- cache->cacheMemMap = cacheMemMap;
- cache->cacheMem = cacheMem;
- cache->sharedCache = (cacheDesc *)cacheMem;
-
- /* Fix pointers in our private copy of cache descriptor to point to
- ** spaces in shared memory
- */
- cache->sidCacheLocks = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheLocks);
- cache->keyCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheLock);
- cache->certCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->certCacheLock);
- cache->srvNameCacheLock = (sidCacheLock *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
- cache->sidCacheSets = (sidCacheSet *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheSets);
- cache->sidCacheData = (sidCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->sidCacheData);
- cache->certCacheData = (certCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->certCacheData);
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)(cache->cacheMem + (ptrdiff_t)cache->keyCacheData);
- cache->ticketKeyNameSuffix = (PRUint8 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
- cache->ticketEncKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketEncKey);
- cache->ticketMacKey = (encKeyCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->ticketMacKey);
- cache->ticketKeysValid = (PRUint32 *)(cache->cacheMem + (ptrdiff_t)cache->ticketKeysValid);
- cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
-
- /* initialize the locks */
- init_time = ssl_Time();
- pLock = cache->sidCacheLocks;
- for (locks_to_initialize = cache->numSIDCacheLocks + 3;
- locks_initialized < locks_to_initialize;
- ++locks_initialized, ++pLock) {
-
- SECStatus err = sslMutex_Init(&pLock->mutex, shared);
- if (err) {
- cache->numSIDCacheLocksInitialized = locks_initialized;
- goto loser;
- }
- pLock->timeStamp = init_time;
- pLock->pid = 0;
- }
- cache->numSIDCacheLocksInitialized = locks_initialized;
-
- return SECSuccess;
-
-loser:
- CloseCache(cache);
- return SECFailure;
-}
-
-PRUint32
-SSL_GetMaxServerCacheLocks(void)
-{
- return ssl_max_sid_cache_locks + 2;
- /* The extra two are the cert cache lock and the key cache lock. */
-}
-
-SECStatus
-SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
-{
- /* Minimum is 1 sid cache lock, 1 cert cache lock and 1 key cache lock.
- ** We'd like to test for a maximum value, but not all platforms' header
- ** files provide a symbol or function or other means of determining
- ** the maximum, other than trial and error.
- */
- if (maxLocks < 3) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- ssl_max_sid_cache_locks = maxLocks - 2;
- /* The extra two are the cert cache lock and the key cache lock. */
- return SECSuccess;
-}
-
-static SECStatus
-ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory,
- PRBool shared,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries)
-{
- SECStatus rv;
-
- PORT_Assert(sizeof(sidCacheEntry) == 192);
- PORT_Assert(sizeof(certCacheEntry) == 4096);
- PORT_Assert(sizeof(srvNameCacheEntry) == 1072);
-
- rv = ssl_Init();
- if (rv != SECSuccess) {
- return rv;
- }
-
- myPid = SSL_GETPID();
- if (!directory) {
- directory = DEFAULT_CACHE_DIRECTORY;
- }
- rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
- maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
- directory, shared);
- if (rv) {
- SET_ERROR_CODE
- return SECFailure;
- }
-
- ssl_sid_lookup = ServerSessionIDLookup;
- ssl_sid_cache = ServerSessionIDCache;
- ssl_sid_uncache = ServerSessionIDUncache;
- return SECSuccess;
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCacheInstance(cacheDesc *cache,
- int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory, PRBool shared)
-{
- return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
- ssl2_timeout,
- ssl3_timeout,
- directory,
- shared,
- maxCacheEntries,
- -1, -1);
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCache(int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory)
-{
- ssl_InitSessionCacheLocks();
- return SSL_ConfigServerSessionIDCacheInstance(&globalCache,
- maxCacheEntries, ssl2_timeout, ssl3_timeout, directory, PR_FALSE);
-}
-
-SECStatus
-SSL_ShutdownServerSessionIDCacheInstance(cacheDesc *cache)
-{
- CloseCache(cache);
- return SECSuccess;
-}
-
-SECStatus
-SSL_ShutdownServerSessionIDCache(void)
-{
-#if defined(XP_UNIX) || defined(XP_BEOS)
- /* Stop the thread that polls cache for expired locks on Unix */
- StopLockPoller(&globalCache);
-#endif
- SSL3_ShutdownServerCache();
- return SSL_ShutdownServerSessionIDCacheInstance(&globalCache);
-}
-
-/* Use this function, instead of SSL_ConfigServerSessionIDCache,
- * if the cache will be shared by multiple processes.
- */
-static SECStatus
-ssl_ConfigMPServerSIDCacheWithOpt(PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries)
-{
- char *envValue;
- char *inhValue;
- cacheDesc *cache = &globalCache;
- PRUint32 fmStrLen;
- SECStatus result;
- PRStatus prStatus;
- SECStatus putEnvFailed;
- inheritance inherit;
- char fmString[PR_FILEMAP_STRING_BUFSIZE];
-
- isMultiProcess = PR_TRUE;
- result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
- ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
- maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
- if (result != SECSuccess)
- return result;
-
- prStatus = PR_ExportFileMapAsString(cache->cacheMemMap,
- sizeof fmString, fmString);
- if ((prStatus != PR_SUCCESS) || !(fmStrLen = strlen(fmString))) {
- SET_ERROR_CODE
- return SECFailure;
- }
-
- inherit.cacheMemSize = cache->cacheMemSize;
- inherit.fmStrLen = fmStrLen;
-
- inhValue = BTOA_DataToAscii((unsigned char *)&inherit, sizeof inherit);
- if (!inhValue || !strlen(inhValue)) {
- SET_ERROR_CODE
- return SECFailure;
- }
- envValue = PR_smprintf("%s,%s", inhValue, fmString);
- if (!envValue || !strlen(envValue)) {
- SET_ERROR_CODE
- return SECFailure;
- }
- PORT_Free(inhValue);
-
- putEnvFailed = (SECStatus)NSS_PutEnv(envVarName, envValue);
- PR_smprintf_free(envValue);
- if (putEnvFailed) {
- SET_ERROR_CODE
- result = SECFailure;
- }
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
- /* Launch thread to poll cache for expired locks on Unix */
- LaunchLockPoller(cache);
-#endif
- return result;
-}
-
-/* Use this function, instead of SSL_ConfigServerSessionIDCache,
- * if the cache will be shared by multiple processes.
- */
-SECStatus
-SSL_ConfigMPServerSIDCache(int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory)
-{
- return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout,
- ssl3_timeout,
- directory,
- maxCacheEntries,
- -1, -1);
-}
-
-SECStatus
-SSL_ConfigServerSessionIDCacheWithOpt(
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory,
- int maxCacheEntries,
- int maxCertCacheEntries,
- int maxSrvNameCacheEntries,
- PRBool enableMPCache)
-{
- if (!enableMPCache) {
- ssl_InitSessionCacheLocks();
- return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
- ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
- maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
- } else {
- return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
- directory, maxCacheEntries, maxCertCacheEntries,
- maxSrvNameCacheEntries);
- }
-}
-
-SECStatus
-SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char *envString)
-{
- unsigned char *decoString = NULL;
- char *fmString = NULL;
- char *myEnvString = NULL;
- unsigned int decoLen;
- inheritance inherit;
- cacheDesc my;
-#ifdef WINNT
- sidCacheLock *newLocks;
- int locks_initialized = 0;
- int locks_to_initialize = 0;
-#endif
- SECStatus status = ssl_Init();
-
- if (status != SECSuccess) {
- return status;
- }
-
- myPid = SSL_GETPID();
-
- /* If this child was created by fork(), and not by exec() on unix,
- ** then isMultiProcess will already be set.
- ** If not, we'll set it below.
- */
- if (isMultiProcess) {
- if (cache && cache->sharedCache) {
- cache->sharedCache->everInherited = PR_TRUE;
- }
- return SECSuccess; /* already done. */
- }
-
- ssl_InitSessionCacheLocks();
-
- ssl_sid_lookup = ServerSessionIDLookup;
- ssl_sid_cache = ServerSessionIDCache;
- ssl_sid_uncache = ServerSessionIDUncache;
-
- if (!envString) {
- envString = PR_GetEnvSecure(envVarName);
- if (!envString) {
- SET_ERROR_CODE
- return SECFailure;
- }
- }
- myEnvString = PORT_Strdup(envString);
- if (!myEnvString)
- return SECFailure;
- fmString = strchr(myEnvString, ',');
- if (!fmString)
- goto loser;
- *fmString++ = 0;
-
- decoString = ATOB_AsciiToData(myEnvString, &decoLen);
- if (!decoString) {
- SET_ERROR_CODE
- goto loser;
- }
- if (decoLen != sizeof inherit) {
- SET_ERROR_CODE
- goto loser;
- }
-
- PORT_Memcpy(&inherit, decoString, sizeof inherit);
-
- if (strlen(fmString) != inherit.fmStrLen) {
- goto loser;
- }
-
- memset(cache, 0, sizeof *cache);
- cache->cacheMemSize = inherit.cacheMemSize;
-
- /* Create cache */
- cache->cacheMemMap = PR_ImportFileMapFromString(fmString);
- if (!cache->cacheMemMap) {
- goto loser;
- }
- cache->cacheMem = PR_MemMap(cache->cacheMemMap, 0, cache->cacheMemSize);
- if (!cache->cacheMem) {
- goto loser;
- }
- cache->sharedCache = (cacheDesc *)cache->cacheMem;
-
- if (cache->sharedCache->cacheMemSize != cache->cacheMemSize) {
- SET_ERROR_CODE
- goto loser;
- }
-
- /* We're now going to overwrite the local cache instance with the
- ** shared copy of the cache struct, then update several values in
- ** the local cache using the values for cache->cacheMemMap and
- ** cache->cacheMem computed just above. So, we copy cache into
- ** the automatic variable "my", to preserve the variables while
- ** cache is overwritten.
- */
- my = *cache; /* save values computed above. */
- memcpy(cache, cache->sharedCache, sizeof *cache); /* overwrite */
-
- /* Fix pointers in our private copy of cache descriptor to point to
- ** spaces in shared memory, whose address is now in "my".
- */
- cache->sidCacheLocks = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->sidCacheLocks);
- cache->keyCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->keyCacheLock);
- cache->certCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->certCacheLock);
- cache->srvNameCacheLock = (sidCacheLock *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheLock);
- cache->sidCacheSets = (sidCacheSet *)(my.cacheMem + (ptrdiff_t)cache->sidCacheSets);
- cache->sidCacheData = (sidCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->sidCacheData);
- cache->certCacheData = (certCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->certCacheData);
- cache->keyCacheData = (SSLWrappedSymWrappingKey *)(my.cacheMem + (ptrdiff_t)cache->keyCacheData);
- cache->ticketKeyNameSuffix = (PRUint8 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeyNameSuffix);
- cache->ticketEncKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketEncKey);
- cache->ticketMacKey = (encKeyCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->ticketMacKey);
- cache->ticketKeysValid = (PRUint32 *)(my.cacheMem + (ptrdiff_t)cache->ticketKeysValid);
- cache->srvNameCacheData = (srvNameCacheEntry *)(my.cacheMem + (ptrdiff_t)cache->srvNameCacheData);
-
- cache->cacheMemMap = my.cacheMemMap;
- cache->cacheMem = my.cacheMem;
- cache->sharedCache = (cacheDesc *)cache->cacheMem;
-
-#ifdef WINNT
- /* On Windows NT we need to "fix" the sidCacheLocks here to support fibers
- ** When NT fibers are used in a multi-process server, a second level of
- ** locking is needed to prevent a deadlock, in case a fiber acquires the
- ** cross-process mutex, yields, and another fiber is later scheduled on
- ** the same native thread and tries to acquire the cross-process mutex.
- ** We do this by using a PRLock in the sslMutex. However, it is stored in
- ** shared memory as part of sidCacheLocks, and we don't want to overwrite
- ** the PRLock of the parent process. So we need to make new, private
- ** copies of sidCacheLocks before modifying the sslMutex with our own
- ** PRLock
- */
-
- /* note from jpierre : this should be free'd in child processes when
- ** a function is added to delete the SSL session cache in the future.
- */
- locks_to_initialize = cache->numSIDCacheLocks + 3;
- newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
- if (!newLocks)
- goto loser;
- /* copy the old locks */
- memcpy(newLocks, cache->sidCacheLocks,
- locks_to_initialize * sizeof(sidCacheLock));
- cache->sidCacheLocks = newLocks;
- /* fix the locks */
- for (; locks_initialized < locks_to_initialize; ++locks_initialized) {
- /* now, make a local PRLock in this sslMutex for this child process */
- SECStatus err;
- err = sslMutex_2LevelInit(&newLocks[locks_initialized].mutex);
- if (err != SECSuccess) {
- cache->numSIDCacheLocksInitialized = locks_initialized;
- goto loser;
- }
- }
- cache->numSIDCacheLocksInitialized = locks_initialized;
-
- /* also fix the key and cert cache which use the last 2 lock entries */
- cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
- cache->certCacheLock = cache->keyCacheLock + 1;
- cache->srvNameCacheLock = cache->certCacheLock + 1;
-#endif
-
- PORT_Free(myEnvString);
- PORT_Free(decoString);
-
- /* mark that we have inherited this. */
- cache->sharedCache->everInherited = PR_TRUE;
- isMultiProcess = PR_TRUE;
-
- return SECSuccess;
-
-loser:
- PORT_Free(myEnvString);
- if (decoString)
- PORT_Free(decoString);
- CloseCache(cache);
- return SECFailure;
-}
-
-SECStatus
-SSL_InheritMPServerSIDCache(const char *envString)
-{
- return SSL_InheritMPServerSIDCacheInstance(&globalCache, envString);
-}
-
-#if defined(XP_UNIX) || defined(XP_BEOS)
-
-#define SID_LOCK_EXPIRATION_TIMEOUT 30 /* seconds */
-
-static void
-LockPoller(void *arg)
-{
- cacheDesc *cache = (cacheDesc *)arg;
- cacheDesc *sharedCache = cache->sharedCache;
- sidCacheLock *pLock;
- PRIntervalTime timeout;
- PRUint32 now;
- PRUint32 then;
- int locks_polled = 0;
- int locks_to_poll = cache->numSIDCacheLocks + 2;
- PRUint32 expiration = cache->mutexTimeout;
-
- timeout = PR_SecondsToInterval(expiration);
- while (!sharedCache->stopPolling) {
- PR_Sleep(timeout);
- if (sharedCache->stopPolling)
- break;
-
- now = ssl_Time();
- then = now - expiration;
- for (pLock = cache->sidCacheLocks, locks_polled = 0;
- locks_to_poll > locks_polled && !sharedCache->stopPolling;
- ++locks_polled, ++pLock) {
- pid_t pid;
-
- if (pLock->timeStamp < then &&
- pLock->timeStamp != 0 &&
- (pid = pLock->pid) != 0) {
-
- /* maybe we should try the lock? */
- int result = kill(pid, 0);
- if (result < 0 && errno == ESRCH) {
- SECStatus rv;
- /* No process exists by that pid any more.
- ** Treat this mutex as abandoned.
- */
- pLock->timeStamp = now;
- pLock->pid = 0;
- rv = sslMutex_Unlock(&pLock->mutex);
- if (rv != SECSuccess) {
- /* Now what? */
- }
- }
- }
- } /* end of loop over locks */
- } /* end of entire polling loop */
-}
-
-/* Launch thread to poll cache for expired locks */
-static SECStatus
-LaunchLockPoller(cacheDesc *cache)
-{
- const char *timeoutString;
- PRThread *pollerThread;
-
- cache->mutexTimeout = SID_LOCK_EXPIRATION_TIMEOUT;
- timeoutString = PR_GetEnvSecure("NSS_SSL_SERVER_CACHE_MUTEX_TIMEOUT");
- if (timeoutString) {
- long newTime = strtol(timeoutString, 0, 0);
- if (newTime == 0)
- return SECSuccess; /* application doesn't want poller thread */
- if (newTime > 0)
- cache->mutexTimeout = (PRUint32)newTime;
- /* if error (newTime < 0) ignore it and use default */
- }
-
- pollerThread =
- PR_CreateThread(PR_USER_THREAD, LockPoller, cache, PR_PRIORITY_NORMAL,
- PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
- if (!pollerThread) {
- return SECFailure;
- }
- cache->poller = pollerThread;
- return SECSuccess;
-}
-
-/* Stop the thread that polls cache for expired locks */
-static SECStatus
-StopLockPoller(cacheDesc *cache)
-{
- if (!cache->poller) {
- return SECSuccess;
- }
- cache->sharedCache->stopPolling = PR_TRUE;
- if (PR_Interrupt(cache->poller) != PR_SUCCESS) {
- return SECFailure;
- }
- if (PR_JoinThread(cache->poller) != PR_SUCCESS) {
- return SECFailure;
- }
- cache->poller = NULL;
- return SECSuccess;
-}
-#endif
-
-/************************************************************************
- * Code dealing with shared wrapped symmetric wrapping keys below *
- ************************************************************************/
-
-/* If now is zero, it implies that the lock is not held, and must be
-** aquired here.
-*/
-static PRBool
-getSvrWrappingKey(PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk,
- cacheDesc *cache,
- PRUint32 lockTime)
-{
- PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
- SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx;
- PRUint32 now = 0;
- PRBool rv = PR_FALSE;
-
- if (!cache->cacheMem) { /* cache is uninitialized */
- PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
- return rv;
- }
- if (!lockTime) {
- lockTime = now = LockSidCacheLock(cache->keyCacheLock, now);
- if (!lockTime) {
- return rv;
- }
- }
- if (pwswk->exchKeyType == exchKeyType &&
- pwswk->symWrapMechIndex == symWrapMechIndex &&
- pwswk->wrappedSymKeyLen != 0) {
- *wswk = *pwswk;
- rv = PR_TRUE;
- }
- if (now) {
- UnlockSidCacheLock(cache->keyCacheLock);
- }
- return rv;
-}
-
-PRBool
-ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk)
-{
- PRBool rv;
-
- PORT_Assert((unsigned)exchKeyType < kt_kea_size);
- PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
- if ((unsigned)exchKeyType < kt_kea_size &&
- (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) {
- rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk,
- &globalCache, 0);
- } else {
- rv = PR_FALSE;
- }
-
- return rv;
-}
-
-/* Wrap and cache a session ticket key. */
-static PRBool
-WrapTicketKey(SECKEYPublicKey *svrPubKey, PK11SymKey *symKey,
- const char *keyName, encKeyCacheEntry *cacheEntry)
-{
- SECItem wrappedKey = { siBuffer, NULL, 0 };
-
- wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey);
- PORT_Assert(wrappedKey.len <= sizeof(cacheEntry->bytes));
- if (wrappedKey.len > sizeof(cacheEntry->bytes))
- return PR_FALSE;
- wrappedKey.data = cacheEntry->bytes;
-
- if (PK11_PubWrapSymKey(CKM_RSA_PKCS, svrPubKey, symKey, &wrappedKey) !=
- SECSuccess) {
- SSL_DBG(("%d: SSL[%s]: Unable to wrap session ticket %s.",
- SSL_GETPID(), "unknown", keyName));
- return PR_FALSE;
- }
- cacheEntry->length = wrappedKey.len;
- return PR_TRUE;
-}
-
-static PRBool
-GenerateTicketKeys(void *pwArg, unsigned char *keyName, PK11SymKey **aesKey,
- PK11SymKey **macKey)
-{
- PK11SlotInfo *slot;
- CK_MECHANISM_TYPE mechanismArray[2];
- PK11SymKey *aesKeyTmp = NULL;
- PK11SymKey *macKeyTmp = NULL;
- cacheDesc *cache = &globalCache;
- PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
- PRUint8 *ticketKeyNameSuffix;
-
- if (!cache->cacheMem) {
- /* cache is not initalized. Use stack buffer */
- ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
- } else {
- ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
- }
-
- if (PK11_GenerateRandom(ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN) !=
- SECSuccess) {
- SSL_DBG(("%d: SSL[%s]: Unable to generate random key name bytes.",
- SSL_GETPID(), "unknown"));
- goto loser;
- }
-
- mechanismArray[0] = CKM_AES_CBC;
- mechanismArray[1] = CKM_SHA256_HMAC;
-
- slot = PK11_GetBestSlotMultiple(mechanismArray, 2, pwArg);
- if (slot) {
- aesKeyTmp = PK11_KeyGen(slot, mechanismArray[0], NULL,
- AES_256_KEY_LENGTH, pwArg);
- macKeyTmp = PK11_KeyGen(slot, mechanismArray[1], NULL,
- SHA256_LENGTH, pwArg);
- PK11_FreeSlot(slot);
- }
-
- if (aesKeyTmp == NULL || macKeyTmp == NULL) {
- SSL_DBG(("%d: SSL[%s]: Unable to generate session ticket keys.",
- SSL_GETPID(), "unknown"));
- goto loser;
- }
- PORT_Memcpy(keyName, ticketKeyNameSuffix, SESS_TICKET_KEY_VAR_NAME_LEN);
- *aesKey = aesKeyTmp;
- *macKey = macKeyTmp;
- return PR_TRUE;
-
-loser:
- if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
- if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
- return PR_FALSE;
-}
-
-static PRBool
-GenerateAndWrapTicketKeys(SECKEYPublicKey *svrPubKey, void *pwArg,
- unsigned char *keyName, PK11SymKey **aesKey,
- PK11SymKey **macKey)
-{
- PK11SymKey *aesKeyTmp = NULL;
- PK11SymKey *macKeyTmp = NULL;
- cacheDesc *cache = &globalCache;
-
- if (!GenerateTicketKeys(pwArg, keyName, &aesKeyTmp, &macKeyTmp)) {
- goto loser;
- }
-
- if (cache->cacheMem) {
- /* Export the keys to the shared cache in wrapped form. */
- if (!WrapTicketKey(svrPubKey, aesKeyTmp, "enc key", cache->ticketEncKey))
- goto loser;
- if (!WrapTicketKey(svrPubKey, macKeyTmp, "mac key", cache->ticketMacKey))
- goto loser;
- }
- *aesKey = aesKeyTmp;
- *macKey = macKeyTmp;
- return PR_TRUE;
-
-loser:
- if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
- if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
- return PR_FALSE;
-}
-
-static PRBool
-UnwrapCachedTicketKeys(SECKEYPrivateKey *svrPrivKey, unsigned char *keyName,
- PK11SymKey **aesKey, PK11SymKey **macKey)
-{
- SECItem wrappedKey = { siBuffer, NULL, 0 };
- PK11SymKey *aesKeyTmp = NULL;
- PK11SymKey *macKeyTmp = NULL;
- cacheDesc *cache = &globalCache;
-
- wrappedKey.data = cache->ticketEncKey->bytes;
- wrappedKey.len = cache->ticketEncKey->length;
- PORT_Assert(wrappedKey.len <= sizeof(cache->ticketEncKey->bytes));
- aesKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
- CKM_AES_CBC, CKA_DECRYPT, 0);
-
- wrappedKey.data = cache->ticketMacKey->bytes;
- wrappedKey.len = cache->ticketMacKey->length;
- PORT_Assert(wrappedKey.len <= sizeof(cache->ticketMacKey->bytes));
- macKeyTmp = PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey,
- CKM_SHA256_HMAC, CKA_SIGN, 0);
-
- if (aesKeyTmp == NULL || macKeyTmp == NULL) {
- SSL_DBG(("%d: SSL[%s]: Unable to unwrap session ticket keys.",
- SSL_GETPID(), "unknown"));
- goto loser;
- }
- SSL_DBG(("%d: SSL[%s]: Successfully unwrapped session ticket keys.",
- SSL_GETPID(), "unknown"));
-
- PORT_Memcpy(keyName, cache->ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN);
- *aesKey = aesKeyTmp;
- *macKey = macKeyTmp;
- return PR_TRUE;
-
-loser:
- if (aesKeyTmp)
- PK11_FreeSymKey(aesKeyTmp);
- if (macKeyTmp)
- PK11_FreeSymKey(macKeyTmp);
- return PR_FALSE;
-}
-
-PRBool
-ssl_GetSessionTicketKeysPKCS11(SECKEYPrivateKey *svrPrivKey,
- SECKEYPublicKey *svrPubKey, void *pwArg,
- unsigned char *keyName, PK11SymKey **aesKey,
- PK11SymKey **macKey)
-{
- PRUint32 now = 0;
- PRBool rv = PR_FALSE;
- PRBool keysGenerated = PR_FALSE;
- cacheDesc *cache = &globalCache;
-
- if (!cache->cacheMem) {
- /* cache is uninitialized. Generate keys and return them
- * without caching. */
- return GenerateTicketKeys(pwArg, keyName, aesKey, macKey);
- }
-
- now = LockSidCacheLock(cache->keyCacheLock, now);
- if (!now)
- return rv;
-
- if (!*(cache->ticketKeysValid)) {
- /* Keys do not exist, create them. */
- if (!GenerateAndWrapTicketKeys(svrPubKey, pwArg, keyName,
- aesKey, macKey))
- goto loser;
- keysGenerated = PR_TRUE;
- *(cache->ticketKeysValid) = 1;
- }
-
- rv = PR_TRUE;
-
-loser:
- UnlockSidCacheLock(cache->keyCacheLock);
- if (rv && !keysGenerated)
- rv = UnwrapCachedTicketKeys(svrPrivKey, keyName, aesKey, macKey);
- return rv;
-}
-
-PRBool
-ssl_GetSessionTicketKeys(unsigned char *keyName, unsigned char *encKey,
- unsigned char *macKey)
-{
- PRBool rv = PR_FALSE;
- PRUint32 now = 0;
- cacheDesc *cache = &globalCache;
- PRUint8 ticketMacKey[SHA256_LENGTH], ticketEncKey[AES_256_KEY_LENGTH];
- PRUint8 ticketKeyNameSuffixLocal[SESS_TICKET_KEY_VAR_NAME_LEN];
- PRUint8 *ticketMacKeyPtr, *ticketEncKeyPtr, *ticketKeyNameSuffix;
- PRBool cacheIsEnabled = PR_TRUE;
-
- if (!cache->cacheMem) { /* cache is uninitialized */
- cacheIsEnabled = PR_FALSE;
- ticketKeyNameSuffix = ticketKeyNameSuffixLocal;
- ticketEncKeyPtr = ticketEncKey;
- ticketMacKeyPtr = ticketMacKey;
- } else {
- /* these values have constant memory locations in the cache.
- * Ok to reference them without holding the lock. */
- ticketKeyNameSuffix = cache->ticketKeyNameSuffix;
- ticketEncKeyPtr = cache->ticketEncKey->bytes;
- ticketMacKeyPtr = cache->ticketMacKey->bytes;
- }
-
- if (cacheIsEnabled) {
- /* Grab lock if initialized. */
- now = LockSidCacheLock(cache->keyCacheLock, now);
- if (!now)
- return rv;
- }
- /* Going to regenerate keys on every call if cache was not
- * initialized. */
- if (!cacheIsEnabled || !*(cache->ticketKeysValid)) {
- if (PK11_GenerateRandom(ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN) !=
- SECSuccess)
- goto loser;
- if (PK11_GenerateRandom(ticketEncKeyPtr,
- AES_256_KEY_LENGTH) != SECSuccess)
- goto loser;
- if (PK11_GenerateRandom(ticketMacKeyPtr,
- SHA256_LENGTH) != SECSuccess)
- goto loser;
- if (cacheIsEnabled) {
- *(cache->ticketKeysValid) = 1;
- }
- }
-
- rv = PR_TRUE;
-
-loser:
- if (cacheIsEnabled) {
- UnlockSidCacheLock(cache->keyCacheLock);
- }
- if (rv) {
- PORT_Memcpy(keyName, ticketKeyNameSuffix,
- SESS_TICKET_KEY_VAR_NAME_LEN);
- PORT_Memcpy(encKey, ticketEncKeyPtr, AES_256_KEY_LENGTH);
- PORT_Memcpy(macKey, ticketMacKeyPtr, SHA256_LENGTH);
- }
- return rv;
-}
-
-/* The caller passes in the new value it wants
- * to set. This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
- * the operation atomic.
- */
-PRBool
-ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
-{
- cacheDesc *cache = &globalCache;
- PRBool rv = PR_FALSE;
- SSL3KEAType exchKeyType = wswk->exchKeyType;
- /* type of keys used to wrap SymWrapKey*/
- PRInt32 symWrapMechIndex = wswk->symWrapMechIndex;
- PRUint32 ndx;
- PRUint32 now = 0;
- SSLWrappedSymWrappingKey myWswk;
-
- if (!cache->cacheMem) { /* cache is uninitialized */
- PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);
- return 0;
- }
-
- PORT_Assert((unsigned)exchKeyType < kt_kea_size);
- if ((unsigned)exchKeyType >= kt_kea_size)
- return 0;
-
- PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS);
- if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS)
- return 0;
-
- ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex;
- PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */
-
- now = LockSidCacheLock(cache->keyCacheLock, now);
- if (now) {
- rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType,
- &myWswk, cache, now);
- if (rv) {
- /* we found it on disk, copy it out to the caller. */
- PORT_Memcpy(wswk, &myWswk, sizeof *wswk);
- } else {
- /* Wasn't on disk, and we're still holding the lock, so write it. */
- cache->keyCacheData[ndx] = *wswk;
- }
- UnlockSidCacheLock(cache->keyCacheLock);
- }
- return rv;
-}
-
-#else /* MAC version or other platform */
-
-#include "seccomon.h"
-#include "cert.h"
-#include "ssl.h"
-#include "sslimpl.h"
-
-SECStatus
-SSL_ConfigServerSessionIDCache(int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory)
-{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigServerSessionIDCache)");
- return SECFailure;
-}
-
-SECStatus
-SSL_ConfigMPServerSIDCache(int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char *directory)
-{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_ConfigMPServerSIDCache)");
- return SECFailure;
-}
-
-SECStatus
-SSL_InheritMPServerSIDCache(const char *envString)
-{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_InheritMPServerSIDCache)");
- return SECFailure;
-}
-
-PRBool
-ssl_GetWrappingKey(PRInt32 symWrapMechIndex,
- SSL3KEAType exchKeyType,
- SSLWrappedSymWrappingKey *wswk)
-{
- PRBool rv = PR_FALSE;
- PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_GetWrappingKey)");
- return rv;
-}
-
-/* This is a kind of test-and-set. The caller passes in the new value it wants
- * to set. This code tests the wrapped sym key entry in the shared memory.
- * If it is uninitialized, this function writes the caller's value into
- * the disk entry, and returns false.
- * Otherwise, it overwrites the caller's wswk with the value obtained from
- * the disk, and returns PR_TRUE.
- * This is all done while holding the locks/mutexes necessary to make
- * the operation atomic.
- */
-PRBool
-ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk)
-{
- PRBool rv = PR_FALSE;
- PR_ASSERT(!"SSL servers are not supported on this platform. (ssl_SetWrappingKey)");
- return rv;
-}
-
-PRUint32
-SSL_GetMaxServerCacheLocks(void)
-{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_GetMaxServerCacheLocks)");
- return -1;
-}
-
-SECStatus
-SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
-{
- PR_ASSERT(!"SSL servers are not supported on this platform. (SSL_SetMaxServerCacheLocks)");
- return SECFailure;
-}
-
-#endif /* XP_UNIX || XP_WIN32 */
« no previous file with comments | « net/third_party/nss/ssl/sslsecur.c ('k') | net/third_party/nss/ssl/sslsock.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698