From: Pauli Date: Fri, 27 Mar 2020 00:33:46 +0000 (+1000) Subject: Param builder: Remove the static size limit. X-Git-Tag: openssl-3.0.0-alpha1~191 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=20c98cd45399423f760dbd75d8912769c6b7b10e;p=oweals%2Fopenssl.git Param builder: Remove the static size limit. Prior to this, the param builder had a statically sized array internally. This changes it so that it uses a stack instead. Reviewed-by: Nicola Tuveri (Merged from https://github.com/openssl/openssl/pull/11390) --- diff --git a/crypto/param_build.c b/crypto/param_build.c index 11986d999b..4f999678cb 100644 --- a/crypto/param_build.c +++ b/crypto/param_build.c @@ -13,14 +13,10 @@ #include #include #include +#include #include "internal/cryptlib.h" #include "openssl/param_build.h" -/* - * The number of OSSL_PARAM elements a builder will allow. - */ -#define OSSL_PARAM_BLD_MAX 25 - /* * Special internal param type to indicate the end of an allocate OSSL_PARAM * array. @@ -46,11 +42,12 @@ typedef struct { } num; } OSSL_PARAM_BLD_DEF; +DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF) + struct ossl_param_bld_st { - size_t curr; size_t total_blocks; size_t secure_blocks; - OSSL_PARAM_BLD_DEF params[OSSL_PARAM_BLD_MAX]; + STACK_OF(OSSL_PARAM_BLD_DEF) *params; }; typedef union { @@ -68,14 +65,12 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, int size, size_t alloc, int type, int secure) { - OSSL_PARAM_BLD_DEF *pd; + OSSL_PARAM_BLD_DEF *pd = OPENSSL_zalloc(sizeof(*pd)); - if (bld->curr >= OSSL_PARAM_BLD_MAX) { - CRYPTOerr(CRYPTO_F_PARAM_PUSH, CRYPTO_R_TOO_MANY_RECORDS); + if (pd == NULL) { + CRYPTOerr(CRYPTO_F_PARAM_PUSH, ERR_R_MALLOC_FAILURE); return NULL; } - pd = bld->params + bld->curr++; - memset(pd, 0, sizeof(*pd)); pd->key = key; pd->type = type; pd->size = size; @@ -84,6 +79,10 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key, bld->secure_blocks += pd->alloc_blocks; else bld->total_blocks += pd->alloc_blocks; + if (sk_OSSL_PARAM_BLD_DEF_push(bld->params, pd) <= 0) { + OPENSSL_free(pd); + pd = NULL; + } return pd; } @@ -104,11 +103,30 @@ static int param_push_num(OSSL_PARAM_BLD *bld, const char *key, OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void) { - return OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD)); + OSSL_PARAM_BLD *r = OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD)); + + if (r != NULL) { + r->params = sk_OSSL_PARAM_BLD_DEF_new_null(); + if (r->params == NULL) { + OPENSSL_free(r); + r = NULL; + } + } + return r; +} + +static void free_all_params(OSSL_PARAM_BLD *bld) +{ + int i, n = sk_OSSL_PARAM_BLD_DEF_num(bld->params); + + for (i = 0; i < n; i++) + OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld->params)); } void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld) { + free_all_params(bld); + sk_OSSL_PARAM_BLD_DEF_free(bld->params); OPENSSL_free(bld); } @@ -285,12 +303,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param, OSSL_PARAM_BLD_BLOCK *blk, OSSL_PARAM_BLD_BLOCK *secure) { - size_t i; + int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); OSSL_PARAM_BLD_DEF *pd; void *p; - for (i = 0; i < bld->curr; i++) { - pd = bld->params + i; + for (i = 0; i < num; i++) { + pd = sk_OSSL_PARAM_BLD_DEF_value(bld->params, i); param[i].key = pd->key; param[i].data_type = pd->type; param[i].data_size = pd->size; @@ -333,7 +351,8 @@ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld) { OSSL_PARAM_BLD_BLOCK *blk, *s = NULL; OSSL_PARAM *params, *last; - const size_t p_blks = bytes_to_blocks((1 + bld->curr) * sizeof(*params)); + const int num = sk_OSSL_PARAM_BLD_DEF_num(bld->params); + const size_t p_blks = bytes_to_blocks((1 + num) * sizeof(*params)); const size_t total = ALIGN_SIZE * (p_blks + bld->total_blocks); const size_t ss = ALIGN_SIZE * bld->secure_blocks; @@ -359,8 +378,10 @@ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld) last->data = s; last->data_type = OSSL_PARAM_ALLOCATED_END; - /* Reset for reuse */ - memset(bld, 0, sizeof(*bld)); + /* Reset builder for reuse */ + bld->total_blocks = 0; + bld->secure_blocks = 0; + free_all_params(bld); return params; } diff --git a/doc/man3/OSSL_PARAM_BLD.pod b/doc/man3/OSSL_PARAM_BLD.pod new file mode 100644 index 0000000000..ed82e32073 --- /dev/null +++ b/doc/man3/OSSL_PARAM_BLD.pod @@ -0,0 +1,195 @@ +=pod + +=head1 NAME + +OSSL_PARAM_BLD, OSSL_PARAM_BLD_new, OSSL_PARAM_BLD_to_param, +OSSL_PARAM_BLD_free_params, OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_push_int, +OSSL_PARAM_BLD_push_uint, OSSL_PARAM_BLD_push_long, +OSSL_PARAM_BLD_push_ulong, OSSL_PARAM_BLD_push_int32, +OSSL_PARAM_BLD_push_uint32, OSSL_PARAM_BLD_push_int64, +OSSL_PARAM_BLD_push_uint64, OSSL_PARAM_BLD_push_size_t, +OSSL_PARAM_BLD_push_double, OSSL_PARAM_BLD_push_BN, +OSSL_PARAM_BLD_push_BN_pad, OSSL_PARAM_BLD_push_utf8_string, +OSSL_PARAM_BLD_push_utf8_ptr, OSSL_PARAM_BLD_push_octet_string, +OSSL_PARAM_BLD_push_octet_ptr +- functions to assist in the creation of OSSL_PARAM arrays + +=head1 SYNOPSIS + +=for openssl generic + + #include "openssl/param_build.h" + + typedef struct OSSL_PARAM_BLD; + + OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void); + OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld); + void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params); + void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld); + + int OSSL_PARAM_BLD_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val); + + int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, + const BIGNUM *bn); + int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, + const BIGNUM *bn, size_t sz); + + int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, + const char *buf, size_t bsize); + int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, + char *buf, size_t bsize); + int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, + const void *buf, size_t bsize); + int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, + void *buf, size_t bsize); + + +=head1 DESCRIPTION + +A collection of utility functions that simplify the creation of OSSL_PARAM +arrays. The B> names are as per L. + +OSSL_PARAM_BLD_new() allocates and initialises a new OSSL_PARAM_BLD structure +so that values can be added. +Any existing values are cleared. + +OSSL_PARAM_BLD_free() deallocates the memory allocates by OSSL_PARAM_BLD_new(). + +OSSL_PARAM_BLD_to_param() converts a built up OSSL_PARAM_BLD structure +I into an allocated OSSL_PARAM array. +The OSSL_PARAM array and all associated storage must be freed by calling +OSSL_PARAM_BLD_free_params() with the functions return value. +OSSL_PARAM_BLD_free() can safely be called any time after this function is. + +OSSL_PARAM_BLD_free_params() deallocates the memory allocated by +OSSL_PARAM_BLD_to_param(). + +=begin comment + +POD is pretty good at recognising function names and making them appropriately +bold... however, when part of the function name is variable, we have to help +the processor along + +=end comment + +B>() are a series of functions which will create +OSSL_PARAM objects of the specified size and correct type for the I +argument. +I is stored by value and an expression or auto variable can be used. + +OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object +that holds the specified BIGNUM I. +If I is marked as being securely allocated, its OSSL_PARAM representation +will also be securely allocated. +The I argument is stored by reference and the underlying BIGNUM object +must exist until after OSSL_PARAM_BLD_to_param() has been called. + +OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object +that holds the specified BIGNUM I. +The object will be padded to occupy exactly I bytes, if insufficient space +is specified an error results. +If I is marked as being securely allocated, its OSSL_PARAM representation +will also be securely allocated. +The I argument is stored by reference and the underlying BIGNUM object +must exist until after OSSL_PARAM_BLD_to_param() has been called. + +OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM +object that references the UTF8 string specified by I. +If the length of the string, I, is zero then it will be calculated. +The string that I points to is stored by reference and must remain in +scope until after OSSL_PARAM_BLD_to_param() has been called. + +OSSL_PARAM_BLD_push_octet_string() is a function that will create an OSSL_PARAM +object that references the octet string specified by I and . +The memory that I points to is stored by reference and must remain in +scope until after OSSL_PARAM_BLD_to_param() has been called. + +OSSL_PARAM_BLD_push_utf8_ptr() is a function that will create an OSSL_PARAM +object that references the UTF8 string specified by I. +If the length of the string, I, is zero then it will be calculated. +The string I points to is stored by reference and must remain in +scope until the OSSL_PARAM array is freed. + +OSSL_PARAM_BLD_push_octet_ptr() is a function that will create an OSSL_PARAM +object that references the octet string specified by I. +The memory I points to is stored by reference and must remain in +scope until the OSSL_PARAM array is freed. + +=head1 RETURN VALUES + +OSSL_PARAM_BLD_new() returns the allocated OSSL_PARAM_BLD structure, or NULL +on error. + +OSSL_PARAM_BLD_to_param() returns the allocated OSSL_PARAM array, or NULL +on error. + +All of the OSSL_PARAM_BLD_push_TYPE functions return 1 on success and 0 +on error. + +=head1 EXAMPLES + +Both examples creating an OSSL_PARAM array that contains an RSA key. +For both, the predefined key variables are: + + BIGNUM *p, *q; /* both prime */ + BIGNUM *n; /* = p * q */ + unsigned int e; /* exponent, usually 65537 */ + BIGNUM *d; /* e^-1 */ + +=head2 Example 1 + +This example shows how to create an OSSL_PARAM array that contains an RSA +private key. + + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + OSSL_PARAM *params; + + if (bld == NULL + || !OSSL_PARAM_BLD_push_BN(&bld, "p", p) + || !OSSL_PARAM_BLD_push_BN(&bld, "q", q) + || !OSSL_PARAM_BLD_push_uint(&bld, "e", e) + || !OSSL_PARAM_BLD_push_BN(&bld, "n", n) + || !OSSL_PARAM_BLD_push_BN(&bld, "d", d) + || (params = OSSL_PARAM_BLD_to_param(&bld)) == NULL) + goto err; + OSSL_PARAM_BLD_free(bld); + /* Use params */ + ... + OSSL_PARAM_BLD_free_params(params); + +=head2 Example 2 + +This example shows how to create an OSSL_PARAM array that contains an RSA +public key. + + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + OSSL_PARAM *params; + + if (nld == NULL + || !OSSL_PARAM_BLD_push_BN(bld, "n", n) + || !OSSL_PARAM_BLD_push_BN(bld, "d", d) + || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) + goto err; + OSSL_PARAM_BLD_free(bld); + /* Use params */ + ... + OSSL_PARAM_BLD_free_params(params); + +=head1 SEE ALSO + +L, L + +=head1 HISTORY + +The functions described here were all added in OpenSSL 3.0. + +=head1 COPYRIGHT + +Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/OSSL_PARAM_BLD_new.pod b/doc/man3/OSSL_PARAM_BLD_new.pod deleted file mode 100644 index 72b2ff87a3..0000000000 --- a/doc/man3/OSSL_PARAM_BLD_new.pod +++ /dev/null @@ -1,194 +0,0 @@ -=pod - -=head1 NAME - -OSSL_PARAM_BLD_new, OSSL_PARAM_BLD_to_param, OSSL_PARAM_BLD_free_params, -OSSL_PARAM_BLD_free, OSSL_PARAM_BLD_push_int, OSSL_PARAM_BLD_push_uint, -OSSL_PARAM_BLD_push_long, OSSL_PARAM_BLD_push_ulong, -OSSL_PARAM_BLD_push_int32, OSSL_PARAM_BLD_push_uint32, -OSSL_PARAM_BLD_push_int64, OSSL_PARAM_BLD_push_uint64, -OSSL_PARAM_BLD_push_size_t, OSSL_PARAM_BLD_push_double, -OSSL_PARAM_BLD_push_BN, OSSL_PARAM_BLD_push_BN_pad, -OSSL_PARAM_BLD_push_utf8_string, OSSL_PARAM_BLD_push_utf8_ptr, -OSSL_PARAM_BLD_push_octet_string, OSSL_PARAM_BLD_push_octet_ptr -- functions to assist in the creation of OSSL_PARAM arrays - -=head1 SYNOPSIS - -=for openssl generic - - #include "openssl/param_build.h" - - typedef struct OSSL_PARAM_BLD; - - OSSL_PARAM_BLD *OSSL_PARAM_BLD_new(void); - OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld); - void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params); - void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD *bld); - - int OSSL_PARAM_BLD_push_TYPE(OSSL_PARAM_BLD *bld, const char *key, TYPE val); - - int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD *bld, const char *key, - const BIGNUM *bn); - int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD *bld, const char *key, - const BIGNUM *bn, size_t sz); - - int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key, - const char *buf, size_t bsize); - int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key, - char *buf, size_t bsize); - int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD *bld, const char *key, - const void *buf, size_t bsize); - int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key, - void *buf, size_t bsize); - - -=head1 DESCRIPTION - -A collection of utility functions that simplify the creation of OSSL_PARAM -arrays. The B> names are as per L. - -OSSL_PARAM_BLD_new() allocates and initialises a new OSSL_PARAM_BLD structure -so that values can be added. -Any existing values are cleared. - -OSSL_PARAM_BLD_free() deallocates the memory allocates by OSSL_PARAM_BLD_new(). - -OSSL_PARAM_BLD_to_param() converts a built up OSSL_PARAM_BLD structure -I into an allocated OSSL_PARAM array. -The OSSL_PARAM array and all associated storage must be freed by calling -OSSL_PARAM_BLD_free_params() with the functions return value. -OSSL_PARAM_BLD_free() can safely be called any time after this function is. - -OSSL_PARAM_BLD_free_params() deallocates the memory allocated by -OSSL_PARAM_BLD_to_param(). - -=begin comment - -POD is pretty good at recognising function names and making them appropriately -bold... however, when part of the function name is variable, we have to help -the processor along - -=end comment - -B>() are a series of functions which will create -OSSL_PARAM objects of the specified size and correct type for the I -argument. -I is stored by value and an expression or auto variable can be used. - -OSSL_PARAM_BLD_push_BN() is a function that will create an OSSL_PARAM object -that holds the specified BIGNUM I. -If I is marked as being securely allocated, its OSSL_PARAM representation -will also be securely allocated. -The I argument is stored by reference and the underlying BIGNUM object -must exist until after OSSL_PARAM_BLD_to_param() has been called. - -OSSL_PARAM_BLD_push_BN_pad() is a function that will create an OSSL_PARAM object -that holds the specified BIGNUM I. -The object will be padded to occupy exactly I bytes, if insufficient space -is specified an error results. -If I is marked as being securely allocated, its OSSL_PARAM representation -will also be securely allocated. -The I argument is stored by reference and the underlying BIGNUM object -must exist until after OSSL_PARAM_BLD_to_param() has been called. - -OSSL_PARAM_BLD_push_utf8_string() is a function that will create an OSSL_PARAM -object that references the UTF8 string specified by I. -If the length of the string, I, is zero then it will be calculated. -The string that I points to is stored by reference and must remain in -scope until after OSSL_PARAM_BLD_to_param() has been called. - -OSSL_PARAM_BLD_push_octet_string() is a function that will create an OSSL_PARAM -object that references the octet string specified by I and . -The memory that I points to is stored by reference and must remain in -scope until after OSSL_PARAM_BLD_to_param() has been called. - -OSSL_PARAM_BLD_push_utf8_ptr() is a function that will create an OSSL_PARAM -object that references the UTF8 string specified by I. -If the length of the string, I, is zero then it will be calculated. -The string I points to is stored by reference and must remain in -scope until the OSSL_PARAM array is freed. - -OSSL_PARAM_BLD_push_octet_ptr() is a function that will create an OSSL_PARAM -object that references the octet string specified by I. -The memory I points to is stored by reference and must remain in -scope until the OSSL_PARAM array is freed. - -=head1 RETURN VALUES - -OSSL_PARAM_BLD_new() returns the allocated OSSL_PARAM_BLD structure, or NULL -on error. - -OSSL_PARAM_BLD_to_param() returns the allocated OSSL_PARAM array, or NULL -on error. - -All of the OSSL_PARAM_BLD_push_TYPE functions return 1 on success and 0 -on error. - -=head1 EXAMPLES - -Both examples creating an OSSL_PARAM array that contains an RSA key. -For both, the predefined key variables are: - - BIGNUM *p, *q; /* both prime */ - BIGNUM *n; /* = p * q */ - unsigned int e; /* exponent, usually 65537 */ - BIGNUM *d; /* e^-1 */ - -=head2 Example 1 - -This example shows how to create an OSSL_PARAM array that contains an RSA -private key. - - OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); - OSSL_PARAM *params; - - if (bld == NULL - || !OSSL_PARAM_BLD_push_BN(&bld, "p", p) - || !OSSL_PARAM_BLD_push_BN(&bld, "q", q) - || !OSSL_PARAM_BLD_push_uint(&bld, "e", e) - || !OSSL_PARAM_BLD_push_BN(&bld, "n", n) - || !OSSL_PARAM_BLD_push_BN(&bld, "d", d) - || (params = OSSL_PARAM_BLD_to_param(&bld)) == NULL) - goto err; - OSSL_PARAM_BLD_free(bld); - /* Use params */ - ... - OSSL_PARAM_BLD_free_params(params); - -=head2 Example 2 - -This example shows how to create an OSSL_PARAM array that contains an RSA -public key. - - OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); - OSSL_PARAM *params; - - if (nld == NULL - || !OSSL_PARAM_BLD_push_BN(bld, "n", n) - || !OSSL_PARAM_BLD_push_BN(bld, "d", d) - || (params = OSSL_PARAM_BLD_to_param(bld)) == NULL) - goto err; - OSSL_PARAM_BLD_free(bld); - /* Use params */ - ... - OSSL_PARAM_BLD_free_params(params); - -=head1 SEE ALSO - -L, L - -=head1 HISTORY - -The functions described here were all added in OpenSSL 3.0. - -=head1 COPYRIGHT - -Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. - -Licensed under the Apache License 2.0 (the "License"). You may not use -this file except in compliance with the License. You can obtain a copy -in the file LICENSE in the source distribution or at -L. - -=cut diff --git a/test/param_build_test.c b/test/param_build_test.c index 9b20e33360..c5fcc70a66 100644 --- a/test/param_build_test.c +++ b/test/param_build_test.c @@ -192,9 +192,53 @@ err: return res; } +static int builder_limit_test(void) +{ + const int n = 100; + char names[100][3]; + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + OSSL_PARAM *params = NULL; + int i, res = 0; + + if (!TEST_ptr(bld)) + goto err; + + for (i = 0; i < n; i++) { + names[i][0] = 'A' + (i / 26) - 1; + names[i][0] = 'a' + (i % 26) - 1; + names[i][2] = '\0'; + if (!TEST_true(OSSL_PARAM_BLD_push_int(bld, names[i], 3 * i + 1))) + goto err; + } + if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + /* Count the elements in the params arrary, expecting n */ + for (i = 0; params[i].key != NULL; i++); + if (!TEST_int_eq(i, n)) + goto err; + + /* Verify that the build, cleared the builder structure */ + OSSL_PARAM_BLD_free_params(params); + params = NULL; + + if (!TEST_true(OSSL_PARAM_BLD_push_int(bld, "g", 2)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + /* Count the elements in the params arrary, expecting 1 */ + for (i = 0; params[i].key != NULL; i++); + if (!TEST_int_eq(i, 1)) + goto err; + res = 1; +err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + return res; +} + int setup_tests(void) { ADD_TEST(template_public_test); ADD_TEST(template_private_test); + ADD_TEST(builder_limit_test); return 1; }