Remove X509_PUBKEY lock.
[openssl.git] / crypto / x509 / x_pubkey.c
index 158d1d26aff3c01f5989ffb88713b08778862827..b9079b58d1de076ef2c6691d3f4ecfa43d2bbe0a 100644 (file)
 #include <openssl/x509.h>
 #include "internal/asn1_int.h"
 #include "internal/evp_int.h"
+#include "internal/x509_int.h"
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
 
+struct X509_pubkey_st {
+    X509_ALGOR *algor;
+    ASN1_BIT_STRING *public_key;
+    EVP_PKEY *pkey;
+};
+
 /* 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;
 }
@@ -157,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:
@@ -375,3 +375,10 @@ int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
         *pa = pub->algor;
     return 1;
 }
+
+ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
+{
+    if (x == NULL)
+        return NULL;
+    return x->cert_info.key->public_key;
+}