Add CRYPTO_alloc_ex_data()

This allows allocation of items at indexes that were created after the
CRYPTO_EX_DATA variable was initialized, using the exact same method
that was used then.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8225)
This commit is contained in:
Richard Levitte 2019-02-08 16:46:28 +01:00
parent fa1f030610
commit e17f5b6a6b
5 changed files with 106 additions and 16 deletions

View file

@ -362,6 +362,36 @@ void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
ad->sk = NULL; ad->sk = NULL;
} }
/*
* Allocate a given CRYPTO_EX_DATA item using the class specific allocation
* function
*/
int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
int idx)
{
EX_CALLBACK *f;
EX_CALLBACKS *ip;
void *curval;
curval = CRYPTO_get_ex_data(ad, idx);
/* Already there, no need to allocate */
if (curval != NULL)
return 1;
ip = get_and_lock(class_index);
f = sk_EX_CALLBACK_value(ip->meth, idx);
CRYPTO_THREAD_unlock(ex_data_lock);
/*
* This should end up calling CRYPTO_set_ex_data(), which allocates
* everything necessary to support placing the new data in the right spot.
*/
f->new_func(obj, curval, ad, idx, f->argl, f->argp);
return 1;
}
/* /*
* For a given CRYPTO_EX_DATA variable, set the value corresponding to a * For a given CRYPTO_EX_DATA variable, set the value corresponding to a
* particular index in the class used by this variable * particular index in the class used by this variable

View file

@ -3,8 +3,9 @@
=head1 NAME =head1 NAME
CRYPTO_EX_new, CRYPTO_EX_free, CRYPTO_EX_dup, CRYPTO_EX_new, CRYPTO_EX_free, CRYPTO_EX_dup,
CRYPTO_free_ex_index, CRYPTO_get_ex_new_index, CRYPTO_set_ex_data, CRYPTO_free_ex_index, CRYPTO_get_ex_new_index,
CRYPTO_get_ex_data, CRYPTO_free_ex_data, CRYPTO_new_ex_data CRYPTO_alloc_ex_data, CRYPTO_set_ex_data, CRYPTO_get_ex_data,
CRYPTO_free_ex_data, CRYPTO_new_ex_data
- functions supporting application-specific data - functions supporting application-specific data
=head1 SYNOPSIS =head1 SYNOPSIS
@ -26,6 +27,9 @@ CRYPTO_get_ex_data, CRYPTO_free_ex_data, CRYPTO_new_ex_data
int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad) int CRYPTO_new_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad)
int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
int idx);
int CRYPTO_set_ex_data(CRYPTO_EX_DATA *r, int idx, void *arg); int CRYPTO_set_ex_data(CRYPTO_EX_DATA *r, int idx, void *arg);
void *CRYPTO_get_ex_data(CRYPTO_EX_DATA *r, int idx); void *CRYPTO_get_ex_data(CRYPTO_EX_DATA *r, int idx);
@ -114,7 +118,8 @@ new_func() is called for every defined index. There is no requirement
that the entire parent, or containing, structure has been set up. that the entire parent, or containing, structure has been set up.
The new_func() is typically used only to allocate memory to store the The new_func() is typically used only to allocate memory to store the
exdata, and perhaps an "initialized" flag within that memory. exdata, and perhaps an "initialized" flag within that memory.
The exdata value should be set by calling CRYPTO_set_ex_data(). The exdata value may be allocated later on with CRYPTO_alloc_ex_data(),
or may be set by calling CRYPTO_set_ex_data().
When a structure is free'd (such as SSL_CTX_free()) then the When a structure is free'd (such as SSL_CTX_free()) then the
free_func() is called for every defined index. Again, the state of the free_func() is called for every defined index. Again, the state of the
@ -147,14 +152,18 @@ will fail.
CRYPTO_get_ex_new_index() returns a new index or -1 on failure. CRYPTO_get_ex_new_index() returns a new index or -1 on failure.
CRYPTO_free_ex_index() and CRYPTO_free_ex_index(), CRYPTO_alloc_ex_data() and CRYPTO_set_ex_data()
CRYPTO_set_ex_data() return 1 on success or 0 on failure. return 1 on success or 0 on failure.
CRYPTO_get_ex_data() returns the application data or NULL on failure; CRYPTO_get_ex_data() returns the application data or NULL on failure;
note that NULL may be a valid value. note that NULL may be a valid value.
dup_func() should return 0 for failure and 1 for success. dup_func() should return 0 for failure and 1 for success.
=head1 HISTORY
CRYPTO_alloc_ex_data() was added in OpenSSL 3.0.0.
=head1 COPYRIGHT =head1 COPYRIGHT
Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.

View file

@ -187,6 +187,10 @@ int CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *to,
void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad); void CRYPTO_free_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad);
/* Allocate a single item in the CRYPTO_EX_DATA variable */
int CRYPTO_alloc_ex_data(int class_index, void *obj, CRYPTO_EX_DATA *ad,
int idx);
/* /*
* Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular * Get/set data in a CRYPTO_EX_DATA variable corresponding to a particular
* index (relative to the class type involved) * index (relative to the class type involved)

View file

@ -18,6 +18,7 @@ static long saved_argl;
static void *saved_argp; static void *saved_argp;
static int saved_idx; static int saved_idx;
static int saved_idx2; static int saved_idx2;
static int saved_idx3;
static int gbl_result; static int gbl_result;
/* /*
@ -71,12 +72,13 @@ static void exnew2(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int idx, long argl, void *argp) int idx, long argl, void *argp)
{ {
MYOBJ_EX_DATA *ex_data = OPENSSL_zalloc(sizeof(*ex_data)); MYOBJ_EX_DATA *ex_data = OPENSSL_zalloc(sizeof(*ex_data));
if (!TEST_int_eq(idx, saved_idx2)
if (!TEST_true(idx == saved_idx2 || idx == saved_idx3)
|| !TEST_long_eq(argl, saved_argl) || !TEST_long_eq(argl, saved_argl)
|| !TEST_ptr_eq(argp, saved_argp) || !TEST_ptr_eq(argp, saved_argp)
|| !TEST_ptr_null(ptr) || !TEST_ptr_null(ptr)
|| !TEST_ptr(ex_data) || !TEST_ptr(ex_data)
|| !TEST_true(CRYPTO_set_ex_data(ad, saved_idx2, ex_data))) { || !TEST_true(CRYPTO_set_ex_data(ad, idx, ex_data))) {
gbl_result = 0; gbl_result = 0;
OPENSSL_free(ex_data); OPENSSL_free(ex_data);
} else { } else {
@ -88,13 +90,14 @@ static int exdup2(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
void *from_d, int idx, long argl, void *argp) void *from_d, int idx, long argl, void *argp)
{ {
MYOBJ_EX_DATA **update_ex_data = (MYOBJ_EX_DATA**)from_d; MYOBJ_EX_DATA **update_ex_data = (MYOBJ_EX_DATA**)from_d;
MYOBJ_EX_DATA *ex_data = CRYPTO_get_ex_data(to, saved_idx2); MYOBJ_EX_DATA *ex_data = NULL;
if (!TEST_int_eq(idx, saved_idx2)
if (!TEST_true(idx == saved_idx2 || idx == saved_idx3)
|| !TEST_long_eq(argl, saved_argl) || !TEST_long_eq(argl, saved_argl)
|| !TEST_ptr_eq(argp, saved_argp) || !TEST_ptr_eq(argp, saved_argp)
|| !TEST_ptr(from_d) || !TEST_ptr(from_d)
|| !TEST_ptr(*update_ex_data) || !TEST_ptr(*update_ex_data)
|| !TEST_ptr(ex_data) || !TEST_ptr(ex_data = CRYPTO_get_ex_data(to, idx))
|| !TEST_true(ex_data->new)) { || !TEST_true(ex_data->new)) {
gbl_result = 0; gbl_result = 0;
} else { } else {
@ -111,14 +114,14 @@ static int exdup2(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
static void exfree2(void *parent, void *ptr, CRYPTO_EX_DATA *ad, static void exfree2(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
int idx, long argl, void *argp) int idx, long argl, void *argp)
{ {
MYOBJ_EX_DATA *ex_data = CRYPTO_get_ex_data(ad, saved_idx2); MYOBJ_EX_DATA *ex_data = CRYPTO_get_ex_data(ad, idx);
OPENSSL_free(ex_data);
if (!TEST_int_eq(idx, saved_idx2) if (!TEST_true(idx == saved_idx2 || idx == saved_idx3)
|| !TEST_long_eq(argl, saved_argl) || !TEST_long_eq(argl, saved_argl)
|| !TEST_ptr_eq(argp, saved_argp) || !TEST_ptr_eq(argp, saved_argp)
|| !TEST_ptr(ex_data) || !TEST_true(CRYPTO_set_ex_data(ad, idx, NULL)))
|| !TEST_true(CRYPTO_set_ex_data(ad, saved_idx2, NULL)))
gbl_result = 0; gbl_result = 0;
OPENSSL_free(ex_data);
} }
typedef struct myobj_st { typedef struct myobj_st {
@ -152,6 +155,7 @@ static char *MYOBJ_gethello(MYOBJ *obj)
static void MYOBJ_sethello2(MYOBJ *obj, char *cp) static void MYOBJ_sethello2(MYOBJ *obj, char *cp)
{ {
MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2); MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2);
if (TEST_ptr(ex_data)) if (TEST_ptr(ex_data))
ex_data->hello = cp; ex_data->hello = cp;
else else
@ -161,6 +165,31 @@ static void MYOBJ_sethello2(MYOBJ *obj, char *cp)
static char *MYOBJ_gethello2(MYOBJ *obj) static char *MYOBJ_gethello2(MYOBJ *obj)
{ {
MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2); MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx2);
if (TEST_ptr(ex_data))
return ex_data->hello;
obj->st = gbl_result = 0;
return NULL;
}
static void MYOBJ_allochello3(MYOBJ *obj, char *cp)
{
MYOBJ_EX_DATA* ex_data = NULL;
if (TEST_ptr_null(ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3))
&& TEST_true(CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_APP, obj,
&obj->ex_data, saved_idx3))
&& TEST_ptr(ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3)))
ex_data->hello = cp;
else
obj->st = gbl_result = 0;
}
static char *MYOBJ_gethello3(MYOBJ *obj)
{
MYOBJ_EX_DATA* ex_data = CRYPTO_get_ex_data(&obj->ex_data, saved_idx3);
if (TEST_ptr(ex_data)) if (TEST_ptr(ex_data))
return ex_data->hello; return ex_data->hello;
@ -207,7 +236,15 @@ static int test_exdata(void)
return 0; return 0;
if (!TEST_ptr(CRYPTO_get_ex_data(&t1->ex_data, saved_idx2))) if (!TEST_ptr(CRYPTO_get_ex_data(&t1->ex_data, saved_idx2)))
return 0; return 0;
if (!TEST_ptr(CRYPTO_get_ex_data(&t2->ex_data, saved_idx2)))
/*
* saved_idx3 differs from other indexes by being created after the exdata
* was initialized.
*/
saved_idx3 = CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_APP,
saved_argl, saved_argp,
exnew2, exdup2, exfree2);
if (!TEST_ptr_null(CRYPTO_get_ex_data(&t1->ex_data, saved_idx3)))
return 0; return 0;
MYOBJ_sethello(t1, p); MYOBJ_sethello(t1, p);
@ -220,6 +257,11 @@ static int test_exdata(void)
if (!TEST_ptr_eq(cp, p)) if (!TEST_ptr_eq(cp, p))
return 0; return 0;
MYOBJ_allochello3(t1, p);
cp = MYOBJ_gethello3(t1);
if (!TEST_ptr_eq(cp, p))
return 0;
cp = MYOBJ_gethello(t2); cp = MYOBJ_gethello(t2);
if (!TEST_ptr_null(cp)) if (!TEST_ptr_null(cp))
return 0; return 0;
@ -246,6 +288,10 @@ static int test_exdata(void)
if (!TEST_ptr_eq(cp, p)) if (!TEST_ptr_eq(cp, p))
return 0; return 0;
cp = MYOBJ_gethello3(t3);
if (!TEST_ptr_eq(cp, p))
return 0;
MYOBJ_free(t1); MYOBJ_free(t1);
MYOBJ_free(t2); MYOBJ_free(t2);
MYOBJ_free(t3); MYOBJ_free(t3);

View file

@ -4640,3 +4640,4 @@ EVP_KDF_ctrl_str 4595 3_0_0 EXIST::FUNCTION:
EVP_KDF_size 4596 3_0_0 EXIST::FUNCTION: EVP_KDF_size 4596 3_0_0 EXIST::FUNCTION:
EVP_KDF_derive 4597 3_0_0 EXIST::FUNCTION: EVP_KDF_derive 4597 3_0_0 EXIST::FUNCTION:
EC_GROUP_get0_field 4598 3_0_0 EXIST::FUNCTION:EC EC_GROUP_get0_field 4598 3_0_0 EXIST::FUNCTION:EC
CRYPTO_alloc_ex_data 4599 3_0_0 EXIST::FUNCTION: