Originally found in 1.0.0j. Did not check versions between 1.0.0j and 
1.0.1c since it is still present in the current version.

I am also worried about lines 139-143:

139:        if (key->pkey != NULL)
140:                {
141:                CRYPTO_add(&key->pkey->references, 1, 
CRYPTO_LOCK_EVP_PKEY);
142:                return key->pkey;
143:                }

Assume thread 1 runs up to line 140 and some other thread does 
EVP_PKEY_free() on the key before thread 1 can get the lock starting in 
line 141. Am I overseeing some protection ?

Also note the same problem in lines 175-184:

175:        CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
176:        if (key->pkey)
177:            {
178:            EVP_KEY_free(ret);
179:            ret = key->pkey;
180:            }
181:        else
182:            key->pkey = ret;
183:        CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
184:        CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);

Assume thread 1 goes up until and finishes line 183, then thread 2 does 
EVP_PKEY_free() on key.

I would have supplied patch suggestions for those places as well but I 
am not aware of an existing openssl technique of manipulating the 
reference counter *without* aquiring a lock, in case we already have a 
lock of the correct type.

Regards,
   Thomas

diff --git a/crypto/asn1/x_pubkey.c b/crypto/asn1/x_pubkey.c
index 627ec87..d8422ca 100644
--- a/crypto/asn1/x_pubkey.c
+++ b/crypto/asn1/x_pubkey.c
@@ -133,6 +133,7 @@ error:
 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
 	{
 	EVP_PKEY *ret=NULL;
+	EVP_PKEY *pktmp=NULL;
 
 	if (key == NULL) goto error;
 
@@ -175,7 +176,7 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
 	CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
 	if (key->pkey)
 		{
-		EVP_PKEY_free(ret);
+		pktmp=ret;
 		ret = key->pkey;
 		}
 	else
@@ -183,6 +184,8 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
 	CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
 	CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
 
+	if (pktmp)
+		EVP_KEY_free(pktmp);
 	return ret;
 
 	error:

Reply via email to