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: