diff options
author | Bodo Möller <bodo@openssl.org> | 2012-10-05 20:50:38 +0000 |
---|---|---|
committer | Bodo Möller <bodo@openssl.org> | 2012-10-05 20:50:38 +0000 |
commit | b626f0396c308aa10eb19862ebe2afdd6e855b29 (patch) | |
tree | 3a009ffca6b2bc358effe62a891a7d8255219d1f /crypto/ec | |
parent | 9d2006d8ed733522014035ec0514e23a312083e8 (diff) |
Fix EC_KEY initialization race.
Submitted by: Adam Langley
Diffstat (limited to 'crypto/ec')
-rw-r--r-- | crypto/ec/ec.h | 10 | ||||
-rw-r--r-- | crypto/ec/ec_key.c | 13 |
2 files changed, 20 insertions, 3 deletions
diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h index 4db11cf9d6..63abfd5149 100644 --- a/crypto/ec/ec.h +++ b/crypto/ec/ec.h @@ -808,7 +808,15 @@ void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); /* functions to set/get method specific data */ void *EC_KEY_get_key_method_data(EC_KEY *key, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); -void EC_KEY_insert_key_method_data(EC_KEY *key, void *data, +/** Sets the key method data of an EC_KEY object, if none has yet been set. + * \param key EC_KEY object + * \param data opaque data to install. + * \param dup_func a function that duplicates |data|. + * \param free_func a function that frees |data|. + * \param clear_free_func a function that wipes and frees |data|. + * \return the previously set data pointer, or NULL if |data| was inserted. + */ +void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); /* wrapper functions for the underlying EC_GROUP object */ void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index bf9fd2dc2c..7fa247593d 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -520,18 +520,27 @@ void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) void *EC_KEY_get_key_method_data(EC_KEY *key, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { - return EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); + void *ret; + + CRYPTO_r_lock(CRYPTO_LOCK_EC); + ret = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); + CRYPTO_r_unlock(CRYPTO_LOCK_EC); + + return ret; } -void EC_KEY_insert_key_method_data(EC_KEY *key, void *data, +void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data, void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) { EC_EXTRA_DATA *ex_data; + CRYPTO_w_lock(CRYPTO_LOCK_EC); ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); if (ex_data == NULL) EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func); CRYPTO_w_unlock(CRYPTO_LOCK_EC); + + return ex_data; } void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) |