提交 f11d0c79 编写于 作者: B Bodo Möller

Fix EC_KEY initialization race.

Submitted by: Adam Langley
上级 323fa645
...@@ -810,7 +810,15 @@ void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform); ...@@ -810,7 +810,15 @@ void EC_KEY_set_conv_form(EC_KEY *eckey, point_conversion_form_t cform);
/* functions to set/get method specific data */ /* functions to set/get method specific data */
void *EC_KEY_get_key_method_data(EC_KEY *key, void *EC_KEY_get_key_method_data(EC_KEY *key,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)); 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 *)); void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *));
/* wrapper functions for the underlying EC_GROUP object */ /* wrapper functions for the underlying EC_GROUP object */
void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag); void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
......
...@@ -604,18 +604,27 @@ void EC_KEY_set_conv_form(EC_KEY *key, point_conversion_form_t cform) ...@@ -604,18 +604,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 *EC_KEY_get_key_method_data(EC_KEY *key,
void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *)) 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 *)) void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
{ {
EC_EXTRA_DATA *ex_data; EC_EXTRA_DATA *ex_data;
CRYPTO_w_lock(CRYPTO_LOCK_EC); CRYPTO_w_lock(CRYPTO_LOCK_EC);
ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func); ex_data = EC_EX_DATA_get_data(key->method_data, dup_func, free_func, clear_free_func);
if (ex_data == NULL) if (ex_data == NULL)
EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func); EC_EX_DATA_set_data(&key->method_data, data, dup_func, free_func, clear_free_func);
CRYPTO_w_unlock(CRYPTO_LOCK_EC); CRYPTO_w_unlock(CRYPTO_LOCK_EC);
return ex_data;
} }
void EC_KEY_set_asn1_flag(EC_KEY *key, int flag) void EC_KEY_set_asn1_flag(EC_KEY *key, int flag)
......
...@@ -210,8 +210,15 @@ ECDH_DATA *ecdh_check(EC_KEY *key) ...@@ -210,8 +210,15 @@ ECDH_DATA *ecdh_check(EC_KEY *key)
ecdh_data = (ECDH_DATA *)ecdh_data_new(); ecdh_data = (ECDH_DATA *)ecdh_data_new();
if (ecdh_data == NULL) if (ecdh_data == NULL)
return NULL; return NULL;
EC_KEY_insert_key_method_data(key, (void *)ecdh_data, data = EC_KEY_insert_key_method_data(key, (void *)ecdh_data,
ecdh_data_dup, ecdh_data_free, ecdh_data_free); ecdh_data_dup, ecdh_data_free, ecdh_data_free);
if (data != NULL)
{
/* Another thread raced us to install the key_method
* data and won. */
ecdh_data_free(ecdh_data);
ecdh_data = (ECDH_DATA *)data;
}
} }
else else
ecdh_data = (ECDH_DATA *)data; ecdh_data = (ECDH_DATA *)data;
......
...@@ -188,8 +188,15 @@ ECDSA_DATA *ecdsa_check(EC_KEY *key) ...@@ -188,8 +188,15 @@ ECDSA_DATA *ecdsa_check(EC_KEY *key)
ecdsa_data = (ECDSA_DATA *)ecdsa_data_new(); ecdsa_data = (ECDSA_DATA *)ecdsa_data_new();
if (ecdsa_data == NULL) if (ecdsa_data == NULL)
return NULL; return NULL;
EC_KEY_insert_key_method_data(key, (void *)ecdsa_data, data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free); ecdsa_data_dup, ecdsa_data_free, ecdsa_data_free);
if (data != NULL)
{
/* Another thread raced us to install the key_method
* data and won. */
ecdsa_data_free(ecdsa_data);
ecdsa_data = (ECDSA_DATA *)data;
}
} }
else else
ecdsa_data = (ECDSA_DATA *)data; ecdsa_data = (ECDSA_DATA *)data;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册