PR: 2813
[openssl.git] / crypto / asn1 / x_pubkey.c
index 311e3bf30cffa1f5c93e3ae2091052d58855f482..b649e1fcf96ce322d5a1422cd5ae58b8ae1715fe 100644 (file)
@@ -60,6 +60,7 @@
 #include "cryptlib.h"
 #include <openssl/asn1t.h>
 #include <openssl/x509.h>
+#include "asn1_locl.h"
 #ifndef OPENSSL_NO_RSA
 #include <openssl/rsa.h>
 #endif
@@ -89,19 +90,16 @@ IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
        {
        X509_PUBKEY *pk=NULL;
-       const EVP_PKEY_ASN1_METHOD *meth;
 
        if (x == NULL) return(0);
 
        if ((pk=X509_PUBKEY_new()) == NULL) goto error;
 
-       meth = EVP_PKEY_ASN1_find(pkey->type);
-
-       if (meth)
+       if (pkey->ameth)
                {
-               if (meth->pub_encode)
+               if (pkey->ameth->pub_encode)
                        {
-                       if (!meth->pub_encode(pk, pkey))
+                       if (!pkey->ameth->pub_encode(pk, pkey))
                                {
                                X509err(X509_F_X509_PUBKEY_SET,
                                        X509_R_PUBLIC_KEY_ENCODE_ERROR);
@@ -135,7 +133,6 @@ error:
 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
        {
        EVP_PKEY *ret=NULL;
-       const EVP_PKEY_ASN1_METHOD *meth;
 
        if (key == NULL) goto error;
 
@@ -153,33 +150,40 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
                goto error;
                }
 
-       meth = EVP_PKEY_ASN1_find(OBJ_obj2nid(key->algor->algorithm));
+       if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
+               {
+               X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
+               goto error;
+               }
 
-       if (meth)
+       if (ret->ameth->pub_decode)
                {
-               if (meth->pub_decode)
-                       {
-                       if (!meth->pub_decode(ret, key))
-                               {
-                               X509err(X509_F_X509_PUBKEY_GET,
-                                               X509_R_PUBLIC_KEY_DECODE_ERROR);
-                               goto error;
-                               }
-                       }
-               else
+               if (!ret->ameth->pub_decode(ret, key))
                        {
                        X509err(X509_F_X509_PUBKEY_GET,
-                               X509_R_METHOD_NOT_SUPPORTED);
+                                               X509_R_PUBLIC_KEY_DECODE_ERROR);
                        goto error;
                        }
                }
        else
                {
-               X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM);
+               X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED);
                goto error;
                }
 
-       key->pkey = ret;
+       /* Check to see if another thread set key->pkey first */
+       CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
+       if (key->pkey)
+               {
+               CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+               EVP_PKEY_free(ret);
+               ret = key->pkey;
+               }
+       else
+               {
+               key->pkey = ret;
+               CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+               }
        CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
 
        return ret;