summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslsnce.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslsnce.c')
-rw-r--r--security/nss/lib/ssl/sslsnce.c128
1 files changed, 85 insertions, 43 deletions
diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c
index d7abb3dc3..36c82117e 100644
--- a/security/nss/lib/ssl/sslsnce.c
+++ b/security/nss/lib/ssl/sslsnce.c
@@ -276,14 +276,24 @@ typedef struct inheritanceStr inheritance;
/************************************************************************/
+/* This is used to set locking times for the cache. It is not used to set the
+ * PRTime attributes of sessions, which are driven by ss->now(). */
+static PRUint32
+ssl_CacheNow()
+{
+ return PR_Now() / PR_USEC_PER_SEC;
+}
+
static PRUint32
LockSidCacheLock(sidCacheLock *lock, PRUint32 now)
{
SECStatus rv = sslMutex_Lock(&lock->mutex);
if (rv != SECSuccess)
return 0;
- if (!now)
- now = ssl_TimeSec();
+ if (!now) {
+ now = ssl_CacheNow();
+ }
+
lock->timeStamp = now;
lock->pid = myPid;
return now;
@@ -299,7 +309,7 @@ UnlockSidCacheLock(sidCacheLock *lock)
return rv;
}
-/* returns the value of ssl_TimeSec on success, zero on failure. */
+/* Returns non-zero |now| or ssl_CacheNow() on success, zero on failure. */
static PRUint32
LockSet(cacheDesc *cache, PRUint32 set, PRUint32 now)
{
@@ -630,9 +640,12 @@ FindSID(cacheDesc *cache, PRUint32 setNum, PRUint32 now,
/* 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.
+ *
+ * sslNow is the time that the calling socket understands, which might be
+ * different than what the cache uses to maintain its locks.
*/
static sslSessionID *
-ServerSessionIDLookup(const PRIPv6Addr *addr,
+ServerSessionIDLookup(PRTime sslNow, const PRIPv6Addr *addr,
unsigned char *sessionID,
unsigned int sessionIDLength,
CERTCertDBHandle *dbHandle)
@@ -712,7 +725,7 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
}
}
if (psce) {
- psce->lastAccessTime = now;
+ psce->lastAccessTime = sslNow;
sce = *psce; /* grab a copy while holding the lock */
}
}
@@ -730,7 +743,7 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
** Place a sid into the cache, if it isn't already there.
*/
void
-ssl_ServerCacheSessionID(sslSessionID *sid)
+ssl_ServerCacheSessionID(sslSessionID *sid, PRTime creationTime)
{
PORT_Assert(sid);
@@ -748,7 +761,7 @@ ssl_ServerCacheSessionID(sslSessionID *sid)
PORT_Assert(sid->creationTime != 0);
if (!sid->creationTime)
- sid->lastAccessTime = sid->creationTime = ssl_TimeUsec();
+ sid->lastAccessTime = sid->creationTime = creationTime;
/* override caller's expiration time, which uses client timeout
* duration, not server timeout duration.
*/
@@ -1089,7 +1102,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
cache->srvNameCacheData = (srvNameCacheEntry *)(cache->cacheMem + (ptrdiff_t)cache->srvNameCacheData);
/* initialize the locks */
- init_time = ssl_TimeSec();
+ init_time = ssl_CacheNow();
pLock = cache->sidCacheLocks;
for (locks_to_initialize = cache->numSIDCacheLocks + 3;
locks_initialized < locks_to_initialize;
@@ -1518,7 +1531,7 @@ LockPoller(void *arg)
if (sharedCache->stopPolling)
break;
- now = ssl_TimeSec();
+ now = ssl_CacheNow();
then = now - expiration;
for (pLock = cache->sidCacheLocks, locks_polled = 0;
locks_to_poll > locks_polled && !sharedCache->stopPolling;
@@ -1680,30 +1693,34 @@ ssl_SetSelfEncryptKeyPair(SECKEYPublicKey *pubKey,
SECKEYPrivateKey *privKey,
PRBool explicitConfig)
{
- SECKEYPublicKey *pubKeyCopy;
- SECKEYPrivateKey *privKeyCopy;
+ SECKEYPublicKey *pubKeyCopy, *oldPubKey;
+ SECKEYPrivateKey *privKeyCopy, *oldPrivKey;
PORT_Assert(ssl_self_encrypt_key_pair.lock);
-
pubKeyCopy = SECKEY_CopyPublicKey(pubKey);
- if (!pubKeyCopy) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return SECFailure;
- }
-
privKeyCopy = SECKEY_CopyPrivateKey(privKey);
- if (!privKeyCopy) {
+
+ if (!pubKeyCopy || !privKeyCopy) {
SECKEY_DestroyPublicKey(pubKeyCopy);
+ SECKEY_DestroyPrivateKey(privKeyCopy);
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
PR_RWLock_Wlock(ssl_self_encrypt_key_pair.lock);
- ssl_CleanupSelfEncryptKeyPair();
+ oldPubKey = ssl_self_encrypt_key_pair.pubKey;
+ oldPrivKey = ssl_self_encrypt_key_pair.privKey;
ssl_self_encrypt_key_pair.pubKey = pubKeyCopy;
ssl_self_encrypt_key_pair.privKey = privKeyCopy;
ssl_self_encrypt_key_pair.configured = explicitConfig;
PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock);
+
+ if (oldPubKey) {
+ PORT_Assert(oldPrivKey);
+ SECKEY_DestroyPublicKey(oldPubKey);
+ SECKEY_DestroyPrivateKey(oldPrivKey);
+ }
+
return SECSuccess;
}
@@ -1762,16 +1779,33 @@ ssl_GetSelfEncryptKeyPair(SECKEYPublicKey **pubKey,
return SECFailure;
}
+ SECKEYPublicKey *pubKeyCopy;
+ SECKEYPrivateKey *privKeyCopy;
+ PRBool noKey = PR_FALSE;
+
PR_RWLock_Rlock(ssl_self_encrypt_key_pair.lock);
- *pubKey = ssl_self_encrypt_key_pair.pubKey;
- *privKey = ssl_self_encrypt_key_pair.privKey;
+ if (ssl_self_encrypt_key_pair.pubKey && ssl_self_encrypt_key_pair.privKey) {
+ pubKeyCopy = SECKEY_CopyPublicKey(ssl_self_encrypt_key_pair.pubKey);
+ privKeyCopy = SECKEY_CopyPrivateKey(ssl_self_encrypt_key_pair.privKey);
+ } else {
+ noKey = PR_TRUE;
+ }
PR_RWLock_Unlock(ssl_self_encrypt_key_pair.lock);
- if (!*pubKey) {
- PORT_Assert(!*privKey);
+
+ if (noKey) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
- PORT_Assert(*privKey);
+
+ if (!pubKeyCopy || !privKeyCopy) {
+ SECKEY_DestroyPublicKey(pubKeyCopy);
+ SECKEY_DestroyPrivateKey(privKeyCopy);
+ PORT_SetError(SEC_ERROR_NO_MEMORY);
+ return SECFailure;
+ }
+
+ *pubKey = pubKeyCopy;
+ *privKey = privKeyCopy;
return SECSuccess;
}
@@ -2040,35 +2074,43 @@ static SECStatus
ssl_GenerateSelfEncryptKeys(void *pwArg, PRUint8 *keyName,
PK11SymKey **encKey, PK11SymKey **macKey)
{
- SECKEYPrivateKey *svrPrivKey;
- SECKEYPublicKey *svrPubKey;
+ SECKEYPrivateKey *svrPrivKey = NULL;
+ SECKEYPublicKey *svrPubKey = NULL;
PRUint32 now;
- SECStatus rv;
cacheDesc *cache = &globalCache;
- rv = ssl_GetSelfEncryptKeyPair(&svrPubKey, &svrPrivKey);
+ SECStatus rv = ssl_GetSelfEncryptKeyPair(&svrPubKey, &svrPrivKey);
if (rv != SECSuccess || !cache->cacheMem) {
/* No key pair for wrapping, or the cache is uninitialized. Generate
* keys and return them without caching. */
- return GenerateSelfEncryptKeys(pwArg, keyName, encKey, macKey);
- }
-
- now = LockSidCacheLock(cache->keyCacheLock, 0);
- if (!now)
- return SECFailure;
-
- if (*(cache->ticketKeysValid)) {
- rv = UnwrapCachedSelfEncryptKeys(svrPrivKey, keyName, encKey, macKey);
+ rv = GenerateSelfEncryptKeys(pwArg, keyName, encKey, macKey);
} else {
- /* Keys do not exist, create them. */
- rv = GenerateAndWrapSelfEncryptKeys(svrPubKey, pwArg, keyName,
- encKey, macKey);
- if (rv == SECSuccess) {
- *(cache->ticketKeysValid) = 1;
+ now = LockSidCacheLock(cache->keyCacheLock, 0);
+ if (!now) {
+ goto loser;
+ }
+
+ if (*(cache->ticketKeysValid)) {
+ rv = UnwrapCachedSelfEncryptKeys(svrPrivKey, keyName, encKey, macKey);
+ } else {
+ /* Keys do not exist, create them. */
+ rv = GenerateAndWrapSelfEncryptKeys(svrPubKey, pwArg, keyName,
+ encKey, macKey);
+ if (rv == SECSuccess) {
+ *(cache->ticketKeysValid) = 1;
+ }
}
+ UnlockSidCacheLock(cache->keyCacheLock);
}
- UnlockSidCacheLock(cache->keyCacheLock);
+ SECKEY_DestroyPublicKey(svrPubKey);
+ SECKEY_DestroyPrivateKey(svrPrivKey);
return rv;
+
+loser:
+ UnlockSidCacheLock(cache->keyCacheLock);
+ SECKEY_DestroyPublicKey(svrPubKey);
+ SECKEY_DestroyPrivateKey(svrPrivKey);
+ return SECFailure;
}
/* The caller passes in the new value it wants