summaryrefslogtreecommitdiffstats
path: root/src/crypto/x509/x_pubkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/x509/x_pubkey.c')
-rw-r--r--src/crypto/x509/x_pubkey.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
index d6512ae..c2e0863 100644
--- a/src/crypto/x509/x_pubkey.c
+++ b/src/crypto/x509/x_pubkey.c
@@ -64,6 +64,7 @@
#include <openssl/x509.h>
#include "../evp/internal.h"
+#include "../internal.h"
/* Minor tweak to operation: free up EVP_PKEY */
@@ -126,16 +127,25 @@ error:
return 0;
}
+/* g_pubkey_lock is used to protect the initialisation of the |pkey| member of
+ * |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t|
+ * inside it for this, but |CRYPTO_once_t| is private and |X509_PUBKEY| is
+ * not. */
+static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT;
+
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
{
EVP_PKEY *ret=NULL;
if (key == NULL) goto error;
+ CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
if (key->pkey != NULL)
{
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
return EVP_PKEY_up_ref(key->pkey);
}
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
if (key->public_key == NULL) goto error;
@@ -166,17 +176,17 @@ EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
}
/* Check to see if another thread set key->pkey first */
- CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
+ CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
if (key->pkey)
{
- CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
EVP_PKEY_free(ret);
ret = key->pkey;
}
else
{
key->pkey = ret;
- CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+ CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
}
return EVP_PKEY_up_ref(ret);