Remove X509_PUBKEY lock.

Cache the decoded public key when an X509_PUBKEY structure is initially
parsed so no locking is required. Ignore any decode errors.

When an application calls X509_PUBKEY_get0() subsequently it will either
get the cached key or the decode operation will be repeated which will
return an appropriate error.

Reviewed-by: Rich Salz <rsalz@openssl.org>
This commit is contained in:
Dr. Stephen Henson 2016-03-23 21:04:49 +00:00
parent 703f44e73c
commit d2ec189fdd

View File

@ -69,23 +69,26 @@ struct X509_pubkey_st {
X509_ALGOR *algor;
ASN1_BIT_STRING *public_key;
EVP_PKEY *pkey;
CRYPTO_RWLOCK *lock;
};
/* Minor tweak to operation: free up EVP_PKEY */
static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
if (operation == ASN1_OP_NEW_POST) {
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
pubkey->lock = CRYPTO_THREAD_lock_new();
if (pubkey->lock == NULL)
return 0;
}
if (operation == ASN1_OP_FREE_POST) {
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
CRYPTO_THREAD_lock_free(pubkey->lock);
EVP_PKEY_free(pubkey->pkey);
} else if (operation == ASN1_OP_D2I_POST) {
/* Attempt to decode public key and cache in pubkey structure. */
X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
EVP_PKEY_free(pubkey->pkey);
/*
* Remove any errors from the queue: subsequent decode attempts will
* return an appropriate error.
*/
ERR_set_mark();
pubkey->pkey = X509_PUBKEY_get0(pubkey);
ERR_pop_to_mark();
}
return 1;
}
@ -165,17 +168,6 @@ EVP_PKEY *X509_PUBKEY_get0(X509_PUBKEY *key)
goto error;
}
/* Check to see if another thread set key->pkey first */
CRYPTO_THREAD_write_lock(key->lock);
if (key->pkey) {
CRYPTO_THREAD_unlock(key->lock);
EVP_PKEY_free(ret);
ret = key->pkey;
} else {
key->pkey = ret;
CRYPTO_THREAD_unlock(key->lock);
}
return ret;
error: