tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */