Add OSSL_PARAM_dup() and OSSL_PARAM_merge().

These functions are prerequisites for implementing EVP_PKEY_todata().

OSSL_PARAM_dup() is required to make a deep copy of the exported
params (since the provider export() uses a OSSL_PARAM_BLD which throws away the
data after the call), and then use OSSL_PARAM_merge() to add some additional params
that can be passed to the EVP_PKEY_todata().

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14785)
This commit is contained in:
Shane Lontis 2021-04-07 11:27:18 +10:00
parent d36114d7cd
commit 884314cab7
12 changed files with 583 additions and 68 deletions

View File

@ -95,7 +95,7 @@ $UTIL_COMMON=\
cryptlib.c params.c params_from_text.c bsearch.c ex_data.c o_str.c \
threads_pthread.c threads_win.c threads_none.c initthread.c \
context.c sparse_array.c asn1_dsa.c packet.c param_build.c \
param_build_set.c der_writer.c passphrase.c threads_lib.c
param_build_set.c der_writer.c passphrase.c threads_lib.c params_dup.c
SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \

View File

@ -14,14 +14,12 @@
#include <openssl/params.h>
#include <openssl/types.h>
#include <openssl/safestack.h>
#include "internal/cryptlib.h"
#include "openssl/param_build.h"
#include "internal/param_build_set.h"
/*
* Special internal param type to indicate the end of an allocate OSSL_PARAM
* array.
*/
#define OSSL_PARAM_ALLOCATED_END 127
typedef struct {
const char *key;
@ -50,17 +48,6 @@ struct ossl_param_bld_st {
STACK_OF(OSSL_PARAM_BLD_DEF) *params;
};
typedef union {
OSSL_UNION_ALIGN;
} OSSL_PARAM_BLD_BLOCK;
#define ALIGN_SIZE sizeof(OSSL_PARAM_BLD_BLOCK)
static size_t bytes_to_blocks(size_t bytes)
{
return (bytes + ALIGN_SIZE - 1) / ALIGN_SIZE;
}
static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
int size, size_t alloc, int type,
int secure)
@ -74,7 +61,7 @@ static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
pd->key = key;
pd->type = type;
pd->size = size;
pd->alloc_blocks = bytes_to_blocks(alloc);
pd->alloc_blocks = ossl_param_bytes_to_blocks(alloc);
if ((pd->secure = secure) != 0)
bld->secure_blocks += pd->alloc_blocks;
else
@ -309,8 +296,8 @@ int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
}
static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
OSSL_PARAM_BLD_BLOCK *blk,
OSSL_PARAM_BLD_BLOCK *secure)
OSSL_PARAM_ALIGNED_BLOCK *blk,
OSSL_PARAM_ALIGNED_BLOCK *secure)
{
int i, num = sk_OSSL_PARAM_BLD_DEF_num(bld->params);
OSSL_PARAM_BLD_DEF *pd;
@ -360,12 +347,12 @@ static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld)
{
OSSL_PARAM_BLD_BLOCK *blk, *s = NULL;
OSSL_PARAM_ALIGNED_BLOCK *blk, *s = NULL;
OSSL_PARAM *params, *last;
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;
const size_t p_blks = ossl_param_bytes_to_blocks((1 + num) * sizeof(*params));
const size_t total = OSSL_PARAM_ALIGN_SIZE * (p_blks + bld->total_blocks);
const size_t ss = OSSL_PARAM_ALIGN_SIZE * bld->secure_blocks;
if (ss > 0) {
s = OPENSSL_secure_malloc(ss);
@ -380,11 +367,9 @@ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld)
OPENSSL_secure_free(s);
return NULL;
}
blk = p_blks + (OSSL_PARAM_BLD_BLOCK *)(params);
blk = p_blks + (OSSL_PARAM_ALIGNED_BLOCK *)(params);
last = param_bld_convert(bld, params, blk, s);
last->data_size = ss;
last->data = s;
last->data_type = OSSL_PARAM_ALLOCATED_END;
ossl_param_set_secure_block(last, s, ss);
/* Reset builder for reuse */
bld->total_blocks = 0;
@ -395,13 +380,5 @@ OSSL_PARAM *OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD *bld)
void OSSL_PARAM_BLD_free_params(OSSL_PARAM *params)
{
if (params != NULL) {
OSSL_PARAM *p;
for (p = params; p->key != NULL; p++)
;
if (p->data_type == OSSL_PARAM_ALLOCATED_END)
OPENSSL_secure_clear_free(p->data, p->data_size);
OPENSSL_free(params);
}
OSSL_PARAM_free(params);
}

View File

@ -1291,4 +1291,3 @@ int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
return OSSL_PARAM_get_octet_ptr(p, val, used_len)
|| get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING);
}

236
crypto/params_dup.c Normal file
View File

@ -0,0 +1,236 @@
/*
* Copyright 2021 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
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/params.h>
#include <openssl/param_build.h>
#include "internal/param_build_set.h"
#include "e_os.h" /* strcasecmp */
#define OSSL_PARAM_ALLOCATED_END 127
#define OSSL_PARAM_MERGE_LIST_MAX 128
#define OSSL_PARAM_BUF_PUBLIC 0
#define OSSL_PARAM_BUF_SECURE 1
#define OSSL_PARAM_BUF_MAX (OSSL_PARAM_BUF_SECURE + 1)
typedef struct {
OSSL_PARAM_ALIGNED_BLOCK *alloc; /* The allocated buffer */
OSSL_PARAM_ALIGNED_BLOCK *cur; /* Current position in the allocated buf */
size_t blocks; /* Number of aligned blocks */
size_t alloc_sz; /* The size of the allocated buffer (in bytes) */
} OSSL_PARAM_BUF;
size_t ossl_param_bytes_to_blocks(size_t bytes)
{
return (bytes + OSSL_PARAM_ALIGN_SIZE - 1) / OSSL_PARAM_ALIGN_SIZE;
}
static int ossl_param_buf_alloc(OSSL_PARAM_BUF *out, size_t extra_blocks,
int is_secure)
{
size_t sz = OSSL_PARAM_ALIGN_SIZE * (extra_blocks + out->blocks);
out->alloc = is_secure ? OPENSSL_secure_zalloc(sz) : OPENSSL_zalloc(sz);
if (out->alloc == NULL) {
ERR_raise(ERR_LIB_CRYPTO, is_secure ? CRYPTO_R_SECURE_MALLOC_FAILURE
: ERR_R_MALLOC_FAILURE);
return 0;
}
out->alloc_sz = sz;
out->cur = out->alloc + extra_blocks;
return 1;
}
void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer,
size_t secure_buffer_sz)
{
last->key = NULL;
last->data_size = secure_buffer_sz;
last->data = secure_buffer;
last->data_type = OSSL_PARAM_ALLOCATED_END;
}
static OSSL_PARAM *ossl_param_dup(const OSSL_PARAM *src, OSSL_PARAM *dst,
OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX],
int *param_count)
{
const OSSL_PARAM *in;
int has_dst = (dst != NULL);
int is_secure;
size_t param_sz, blks;
for (in = src; in->key != NULL; in++) {
is_secure = CRYPTO_secure_allocated(in->data);
if (has_dst) {
*dst = *in;
dst->data = buf[is_secure].cur;
}
if (in->data_type == OSSL_PARAM_OCTET_PTR
|| in->data_type == OSSL_PARAM_UTF8_PTR) {
param_sz = sizeof(in->data);
if (has_dst)
*((const void **)dst->data) = *(const void **)in->data;
} else {
param_sz = in->data_size;
if (has_dst)
memcpy(dst->data, in->data, param_sz);
}
if (in->data_type == OSSL_PARAM_UTF8_STRING)
param_sz++; /* NULL terminator */
blks = ossl_param_bytes_to_blocks(param_sz);
if (has_dst) {
dst++;
buf[is_secure].cur += blks;
} else {
buf[is_secure].blocks += blks;
}
if (param_count != NULL)
++*param_count;
}
return dst;
}
OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *src)
{
size_t param_blocks;
OSSL_PARAM_BUF buf[OSSL_PARAM_BUF_MAX];
OSSL_PARAM *last, *dst;
int param_count = 1; /* Include terminator in the count */
if (src == NULL)
return NULL;
memset(buf, 0, sizeof(buf));
/* First Pass: get the param_count and block sizes required */
(void)ossl_param_dup(src, NULL, buf, &param_count);
param_blocks = ossl_param_bytes_to_blocks(param_count * sizeof(*src));
/*
* The allocated buffer consists of an array of OSSL_PARAM followed by
* aligned data bytes that the array elements will point to.
*/
if (!ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_PUBLIC], param_blocks, 0))
return NULL;
/* Allocate a secure memory buffer if required */
if (buf[OSSL_PARAM_BUF_SECURE].blocks > 0
&& !ossl_param_buf_alloc(&buf[OSSL_PARAM_BUF_SECURE], 0, 1)) {
OPENSSL_free(buf[OSSL_PARAM_BUF_PUBLIC].alloc);
return NULL;
}
dst = (OSSL_PARAM *)buf[OSSL_PARAM_BUF_PUBLIC].alloc;
last = ossl_param_dup(src, dst, buf, NULL);
/* Store the allocated secure memory buffer in the last param block */
ossl_param_set_secure_block(last, buf[OSSL_PARAM_BUF_SECURE].alloc,
buf[OSSL_PARAM_BUF_SECURE].alloc_sz);
return dst;
}
static int compare_params(const void *left, const void *right)
{
const OSSL_PARAM *l = *(const OSSL_PARAM **)left;
const OSSL_PARAM *r = *(const OSSL_PARAM **)right;
return strcasecmp(l->key, r->key);
}
OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2)
{
const OSSL_PARAM *list1[OSSL_PARAM_MERGE_LIST_MAX];
const OSSL_PARAM *list2[OSSL_PARAM_MERGE_LIST_MAX];
const OSSL_PARAM *p = NULL;
const OSSL_PARAM **p1cur, **p2cur;
OSSL_PARAM *params, *dst;
size_t list1_sz = 0, list2_sz = 0;
int diff;
if (p1 == NULL && p2 == NULL)
return NULL;
/* Copy p1 to list1 */
if (p1 != NULL) {
for (p = p1; p->key != NULL && list1_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
list1[list1_sz++] = p;
}
list1[list1_sz] = NULL;
/* copy p2 to a list2 */
if (p2 != NULL) {
for (p = p2; p->key != NULL && list2_sz < OSSL_PARAM_MERGE_LIST_MAX; p++)
list2[list2_sz++] = p;
}
list2[list2_sz] = NULL;
if (list1_sz == 0 && list2_sz == 0)
return NULL;
/* Sort the 2 lists */
qsort(list1, list1_sz, sizeof(OSSL_PARAM *), compare_params);
qsort(list2, list2_sz, sizeof(OSSL_PARAM *), compare_params);
/* Allocate enough space to store the merged parameters */
params = OPENSSL_zalloc((list1_sz + list2_sz + 1) * sizeof(*p1));
if (params == NULL) {
ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
return NULL;
}
dst = params;
p1cur = list1;
p2cur = list2;
while (1) {
/* If list1 is finished just tack list2 onto the end */
if (*p1cur == NULL) {
do {
*dst++ = **p2cur;
p2cur++;
} while (*p2cur != NULL);
break;
}
/* If list2 is finished just tack list1 onto the end */
if (*p2cur == NULL) {
do {
*dst++ = **p1cur;
p1cur++;
} while (*p1cur != NULL);
break;
}
/* consume the list element with the smaller key */
diff = strcasecmp((*p1cur)->key, (*p2cur)->key);
if (diff == 0) {
/* If the keys are the same then throw away the list1 element */
*dst++ = **p2cur;
p2cur++;
p1cur++;
} else if (diff > 0) {
*dst++ = **p2cur;
p2cur++;
} else {
*dst++ = **p1cur;
p1cur++;
}
}
return params;
}
void OSSL_PARAM_free(OSSL_PARAM *params)
{
if (params != NULL) {
OSSL_PARAM *p;
for (p = params; p->key != NULL; p++)
;
if (p->data_type == OSSL_PARAM_ALLOCATED_END)
OPENSSL_secure_clear_free(p->data, p->data_size);
OPENSSL_free(params);
}
}

View File

@ -1626,6 +1626,10 @@ DEPEND[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_fr
GENERATE[html/man3/OSSL_PARAM_allocate_from_text.html]=man3/OSSL_PARAM_allocate_from_text.pod
DEPEND[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
GENERATE[man/man3/OSSL_PARAM_allocate_from_text.3]=man3/OSSL_PARAM_allocate_from_text.pod
DEPEND[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
GENERATE[html/man3/OSSL_PARAM_dup.html]=man3/OSSL_PARAM_dup.pod
DEPEND[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
GENERATE[man/man3/OSSL_PARAM_dup.3]=man3/OSSL_PARAM_dup.pod
DEPEND[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
GENERATE[html/man3/OSSL_PARAM_int.html]=man3/OSSL_PARAM_int.pod
DEPEND[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
@ -3048,6 +3052,7 @@ html/man3/OSSL_LIB_CTX.html \
html/man3/OSSL_PARAM.html \
html/man3/OSSL_PARAM_BLD.html \
html/man3/OSSL_PARAM_allocate_from_text.html \
html/man3/OSSL_PARAM_dup.html \
html/man3/OSSL_PARAM_int.html \
html/man3/OSSL_PROVIDER.html \
html/man3/OSSL_SELF_TEST_new.html \
@ -3621,6 +3626,7 @@ man/man3/OSSL_LIB_CTX.3 \
man/man3/OSSL_PARAM.3 \
man/man3/OSSL_PARAM_BLD.3 \
man/man3/OSSL_PARAM_allocate_from_text.3 \
man/man3/OSSL_PARAM_dup.3 \
man/man3/OSSL_PARAM_int.3 \
man/man3/OSSL_PROVIDER.3 \
man/man3/OSSL_SELF_TEST_new.3 \

View File

@ -342,7 +342,7 @@ could fill in the parameters like this:
=head1 SEE ALSO
L<openssl-core.h(7)>, L<OSSL_PARAM_get_int(3)>
L<openssl-core.h(7)>, L<OSSL_PARAM_get_int(3)>, L<OSSL_PARAM_dup(3)>
=head1 HISTORY

View File

@ -0,0 +1,59 @@
=pod
=head1 NAME
OSSL_PARAM_dup, OSSL_PARAM_merge, OSSL_PARAM_free
- OSSL_PARAM array copy functions
=head1 SYNOPSIS
#include <openssl/params.h>
OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *params);
OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *params, const OSSL_PARAM *params1);
void OSSL_PARAM_free(OSSL_PARAM *params);
=head1 DESCRIPTION
Algorithm parameters can be exported/imported from/to providers using arrays of
B<OSSL_PARAM>. The following utility functions allow the parameters to be
duplicated and merged with other B<OSSL_PARAM> to assist in this process.
OSSL_PARAM_dup() duplicates the parameter array I<params>. This function does a
deep copy of the data.
OSSL_PARAM_merge() merges the parameter arrays I<params> and I<params1> into a
new parameter array. If I<params> and I<params1> contain values with the same
'key' then the value from I<params1> will replace the I<param> value. This
function does a shallow copy of the parameters. Either I<params> or I<params1>
may be NULL. The behaviour of the merge is unpredictable if I<params> and
I<params1> contain the same key, and there are multiple entries within either
array that have the same key.
OSSL_PARAM_free() frees the parameter array I<params> that was created using
OSSL_PARAM_dup(), OSSL_PARAM_merge() or OSSL_PARAM_BLD_to_param().
=head1 RETURN VALUES
The functions OSSL_PARAM_dup() and OSSL_PARAM_merge() return a newly allocated
B<OSSL_PARAM> array, or NULL if there was an error. If both parameters are NULL
then NULL is returned.
=head1 SEE ALSO
L<OSSL_PARAM(3)>, L<OSSL_PARAM_BLD(3)>
=head1 HISTORY
The functions were added in OpenSSL 3.0.
=head1 COPYRIGHT
Copyright 2021 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<https://www.openssl.org/source/license.html>.
=cut

View File

@ -13,6 +13,17 @@
# include <openssl/safestack.h>
# include <openssl/param_build.h>
# include "internal/cryptlib.h"
typedef union {
OSSL_UNION_ALIGN;
} OSSL_PARAM_ALIGNED_BLOCK;
# define OSSL_PARAM_ALIGN_SIZE sizeof(OSSL_PARAM_ALIGNED_BLOCK)
size_t ossl_param_bytes_to_blocks(size_t bytes);
void ossl_param_set_secure_block(OSSL_PARAM *last, void *secure_buffer,
size_t secure_buffer_sz);
int ossl_param_build_set_int(OSSL_PARAM_BLD *bld, OSSL_PARAM *p,
const char *key, int num);

View File

@ -150,6 +150,10 @@ int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
int OSSL_PARAM_modified(const OSSL_PARAM *p);
void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p);
OSSL_PARAM *OSSL_PARAM_dup(const OSSL_PARAM *p);
OSSL_PARAM *OSSL_PARAM_merge(const OSSL_PARAM *p1, const OSSL_PARAM *p2);
void OSSL_PARAM_free(OSSL_PARAM *p);
# ifdef __cplusplus
}
# endif

View File

@ -14,10 +14,12 @@
#include "internal/nelem.h"
#include "testutil.h"
static int template_public_test(void)
static const OSSL_PARAM params_empty[] = { OSSL_PARAM_END };
static int template_public_test(int tstid)
{
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
OSSL_PARAM *params = NULL, *p;
OSSL_PARAM *params = NULL, *params_blt = NULL, *p1 = NULL, *p;
BIGNUM *bn = NULL, *bn_res = NULL;
int i;
long int l;
@ -30,7 +32,6 @@ static int template_public_test(void)
int res = 0;
if (!TEST_ptr(bld)
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld, "i", -6))
|| !TEST_true(OSSL_PARAM_BLD_push_long(bld, "l", 42))
|| !TEST_true(OSSL_PARAM_BLD_push_int32(bld, "i32", 1532))
|| !TEST_true(OSSL_PARAM_BLD_push_int64(bld, "i64", -9999999))
@ -43,9 +44,31 @@ static int template_public_test(void)
sizeof("foo")))
|| !TEST_true(OSSL_PARAM_BLD_push_utf8_ptr(bld, "utf8_p", "bar-boom",
0))
|| !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
/* Check int */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
|| !TEST_true(OSSL_PARAM_BLD_push_int(bld, "i", -6))
|| !TEST_ptr(params_blt = OSSL_PARAM_BLD_to_param(bld)))
goto err;
switch(tstid) {
case 0:
params = params_blt;
break;
case 1:
params = OSSL_PARAM_merge(params_blt, params_empty);
break;
case 2:
params = OSSL_PARAM_dup(params_blt);
break;
case 3:
p1 = OSSL_PARAM_merge(params_blt, params_empty);
params = OSSL_PARAM_dup(p1);
break;
default:
p1 = OSSL_PARAM_dup(params_blt);
params = OSSL_PARAM_merge(p1, params_empty);
break;
}
/* Check int */
if (!TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
|| !TEST_true(OSSL_PARAM_get_int(p, &i))
|| !TEST_str_eq(p->key, "i")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_INTEGER)
@ -104,7 +127,10 @@ static int template_public_test(void)
goto err;
res = 1;
err:
OSSL_PARAM_BLD_free_params(params);
OPENSSL_free(p1);
if (params != params_blt)
OPENSSL_free(params);
OSSL_PARAM_BLD_free_params(params_blt);
OSSL_PARAM_BLD_free(bld);
OPENSSL_free(utf);
BN_free(bn);
@ -112,7 +138,7 @@ err:
return res;
}
static int template_private_test(void)
static int template_private_test(int tstid)
{
int *data1 = NULL, *data2 = NULL, j;
const int data1_num = 12;
@ -120,7 +146,7 @@ static int template_private_test(void)
const int data2_num = 5;
const int data2_size = data2_num * sizeof(int);
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL, *p;
OSSL_PARAM *params = NULL, *params_blt = NULL, *p1 = NULL, *p;
unsigned int i;
unsigned long int l;
uint32_t i32;
@ -151,9 +177,29 @@ static int template_private_test(void)
data1_size))
|| !TEST_true(OSSL_PARAM_BLD_push_octet_ptr(bld, "oct_p", data2,
data2_size))
|| !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))
/* Check unsigned int */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
|| !TEST_ptr(params_blt = OSSL_PARAM_BLD_to_param(bld)))
goto err;
switch(tstid) {
case 0:
params = params_blt;
break;
case 1:
params = OSSL_PARAM_merge(params_blt, params_empty);
break;
case 2:
params = OSSL_PARAM_dup(params_blt);
break;
case 3:
p1 = OSSL_PARAM_merge(params_blt, params_empty);
params = OSSL_PARAM_dup(p1);
break;
default:
p1 = OSSL_PARAM_dup(params_blt);
params = OSSL_PARAM_merge(p1, params_empty);
break;
}
/* Check unsigned int */
if (!TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
|| !TEST_false(CRYPTO_secure_allocated(p->data))
|| !TEST_true(OSSL_PARAM_get_uint(p, &i))
|| !TEST_str_eq(p->key, "i")
@ -216,7 +262,10 @@ static int template_private_test(void)
goto err;
res = 1;
err:
OSSL_PARAM_BLD_free_params(params);
OSSL_PARAM_free(p1);
if (params != params_blt)
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free_params(params_blt);
OSSL_PARAM_BLD_free(bld);
OPENSSL_secure_free(data1);
OPENSSL_secure_free(data2);
@ -268,12 +317,126 @@ err:
return res;
}
static int builder_merge_test(void)
{
static int data1[] = { 2, 3, 5, 7, 11, 15, 17 };
static unsigned char data2[] = { 2, 4, 6, 8, 10 };
OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new();
OSSL_PARAM_BLD *bld2 = OSSL_PARAM_BLD_new();
OSSL_PARAM *params = NULL, *params_blt = NULL, *params2_blt = NULL, *p;
unsigned int i;
unsigned long int l;
uint32_t i32;
uint64_t i64;
size_t st;
BIGNUM *bn_priv = NULL, *bn_priv_res = NULL;
BIGNUM *bn_pub = NULL, *bn_pub_res = NULL;
int res = 0;
if (!TEST_ptr(bld)
|| !TEST_true(OSSL_PARAM_BLD_push_uint(bld, "i", 6))
|| !TEST_true(OSSL_PARAM_BLD_push_ulong(bld, "l", 42))
|| !TEST_true(OSSL_PARAM_BLD_push_uint32(bld, "i32", 1532))
|| !TEST_true(OSSL_PARAM_BLD_push_uint64(bld, "i64", 9999999))
|| !TEST_true(OSSL_PARAM_BLD_push_size_t(bld, "st", 65537))
|| !TEST_ptr(bn_priv = BN_secure_new())
|| !TEST_true(BN_set_word(bn_priv, 1729))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld, "bignumber_priv", bn_priv))
|| !TEST_ptr(params_blt = OSSL_PARAM_BLD_to_param(bld)))
goto err;
if (!TEST_ptr(bld2)
|| !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld2, "oct_s", data1,
sizeof(data1)))
|| !TEST_true(OSSL_PARAM_BLD_push_octet_ptr(bld2, "oct_p", data2,
sizeof(data2)))
|| !TEST_true(OSSL_PARAM_BLD_push_uint32(bld2, "i32", 99))
|| !TEST_ptr(bn_pub = BN_new())
|| !TEST_true(BN_set_word(bn_pub, 0x42))
|| !TEST_true(OSSL_PARAM_BLD_push_BN(bld2, "bignumber_pub", bn_pub))
|| !TEST_ptr(params2_blt = OSSL_PARAM_BLD_to_param(bld2)))
goto err;
if (!TEST_ptr(params = OSSL_PARAM_merge(params_blt, params2_blt)))
goto err;
if (!TEST_ptr(p = OSSL_PARAM_locate(params, "i"))
|| !TEST_true(OSSL_PARAM_get_uint(p, &i))
|| !TEST_str_eq(p->key, "i")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_size_t_eq(p->data_size, sizeof(int))
|| !TEST_uint_eq(i, 6)
/* Check unsigned int32 */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "i32"))
|| !TEST_true(OSSL_PARAM_get_uint32(p, &i32))
|| !TEST_str_eq(p->key, "i32")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_size_t_eq(p->data_size, sizeof(int32_t))
|| !TEST_uint_eq((unsigned int)i32, 99)
/* Check unsigned int64 */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "i64"))
|| !TEST_str_eq(p->key, "i64")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_size_t_eq(p->data_size, sizeof(int64_t))
|| !TEST_true(OSSL_PARAM_get_uint64(p, &i64))
|| !TEST_ulong_eq((unsigned long)i64, 9999999)
/* Check unsigned long int */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "l"))
|| !TEST_str_eq(p->key, "l")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_size_t_eq(p->data_size, sizeof(unsigned long int))
|| !TEST_true(OSSL_PARAM_get_ulong(p, &l))
|| !TEST_ulong_eq(l, 42)
/* Check size_t */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "st"))
|| !TEST_str_eq(p->key, "st")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_size_t_eq(p->data_size, sizeof(size_t))
|| !TEST_true(OSSL_PARAM_get_size_t(p, &st))
|| !TEST_size_t_eq(st, 65537)
/* Check octet string */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "oct_s"))
|| !TEST_str_eq(p->key, "oct_s")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_OCTET_STRING)
|| !TEST_mem_eq(p->data, p->data_size, data1, sizeof(data1))
/* Check octet pointer */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "oct_p"))
|| !TEST_str_eq(p->key, "oct_p")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_OCTET_PTR)
|| !TEST_mem_eq(*(void **)p->data, p->data_size, data2, sizeof(data2))
/* Check BN */
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "bignumber_pub"))
|| !TEST_str_eq(p->key, "bignumber_pub")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_true(OSSL_PARAM_get_BN(p, &bn_pub_res))
|| !TEST_int_eq(BN_cmp(bn_pub_res, bn_pub), 0)
|| !TEST_ptr(p = OSSL_PARAM_locate(params, "bignumber_priv"))
|| !TEST_str_eq(p->key, "bignumber_priv")
|| !TEST_uint_eq(p->data_type, OSSL_PARAM_UNSIGNED_INTEGER)
|| !TEST_true(OSSL_PARAM_get_BN(p, &bn_priv_res))
|| !TEST_int_eq(BN_cmp(bn_priv_res, bn_priv), 0))
goto err;
res = 1;
err:
OSSL_PARAM_free(params);
OSSL_PARAM_free(params_blt);
OSSL_PARAM_free(params2_blt);
OSSL_PARAM_BLD_free(bld);
OSSL_PARAM_BLD_free(bld2);
BN_free(bn_priv);
BN_free(bn_priv_res);
BN_free(bn_pub);
BN_free(bn_pub_res);
return res;
}
int setup_tests(void)
{
ADD_TEST(template_public_test);
ADD_ALL_TESTS(template_public_test, 5);
/* Only run the secure memory testing if we have secure memory available */
if (CRYPTO_secure_malloc_init(1<<16, 16))
ADD_TEST(template_private_test);
ADD_ALL_TESTS(template_private_test, 5);
ADD_TEST(builder_limit_test);
ADD_TEST(builder_merge_test);
return 1;
}

View File

@ -455,7 +455,7 @@ static int test_param_real(void)
&& TEST_double_eq(p, 3.14159);
}
static int test_param_construct(void)
static int test_param_construct(int tstid)
{
static const char *int_names[] = {
"int", "long", "int32", "int64"
@ -467,6 +467,10 @@ static int test_param_construct(void)
0xac, 0x75, 0x22, 0x7d, 0x81, 0x06, 0x7a, 0x23,
0xa6, 0xed, 0x87, 0xc7, 0xab, 0xf4, 0x73, 0x22
};
OSSL_PARAM *p = NULL, *p1 = NULL;
static const OSSL_PARAM params_empty[] = {
OSSL_PARAM_END
};
OSSL_PARAM params[20];
char buf[100], buf2[100], *bufp, *bufp2;
unsigned char ubuf[100];
@ -501,13 +505,29 @@ static int test_param_construct(void)
params[n++] = OSSL_PARAM_construct_octet_ptr("octptr", &vp, 0);
params[n] = OSSL_PARAM_construct_end();
switch(tstid) {
case 0:
p = params;
break;
case 1:
p = OSSL_PARAM_merge(params, params_empty);
break;
case 2:
p = OSSL_PARAM_dup(params);
break;
default:
p1 = OSSL_PARAM_dup(params);
p = OSSL_PARAM_merge(p1, params_empty);
break;
}
/* Search failure */
if (!TEST_ptr_null(OSSL_PARAM_locate(params, "fnord")))
if (!TEST_ptr_null(OSSL_PARAM_locate(p, "fnord")))
goto err;
/* All signed integral types */
for (j = 0; j < OSSL_NELEM(int_names); j++) {
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, int_names[j]))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, int_names[j]))
|| !TEST_true(OSSL_PARAM_set_int32(cp, (int32_t)(3 + j)))
|| !TEST_true(OSSL_PARAM_get_int64(cp, &i64))
|| !TEST_size_t_eq(cp->data_size, cp->return_size)
@ -518,7 +538,7 @@ static int test_param_construct(void)
}
/* All unsigned integral types */
for (j = 0; j < OSSL_NELEM(uint_names); j++) {
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, uint_names[j]))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, uint_names[j]))
|| !TEST_true(OSSL_PARAM_set_uint32(cp, (uint32_t)(3 + j)))
|| !TEST_true(OSSL_PARAM_get_uint64(cp, &u64))
|| !TEST_size_t_eq(cp->data_size, cp->return_size)
@ -528,15 +548,16 @@ static int test_param_construct(void)
}
}
/* Real */
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "double"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "double"))
|| !TEST_true(OSSL_PARAM_set_double(cp, 3.14))
|| !TEST_true(OSSL_PARAM_get_double(cp, &d2))
|| !TEST_size_t_eq(cp->return_size, sizeof(double))
|| !TEST_double_eq(d, d2))
|| !TEST_double_eq(d2, 3.14)
|| (tstid <= 1 && !TEST_double_eq(d, d2)))
goto err;
/* UTF8 string */
bufp = NULL;
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8str"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "utf8str"))
|| !TEST_true(OSSL_PARAM_set_utf8_string(cp, "abcdef"))
|| !TEST_size_t_eq(cp->return_size, sizeof("abcdef") - 1)
|| !TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, 0))
@ -552,15 +573,15 @@ static int test_param_construct(void)
/* UTF8 pointer */
/* Note that the size of a UTF8 string does *NOT* include the NUL byte */
bufp = buf;
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "utf8ptr"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "utf8ptr"))
|| !TEST_true(OSSL_PARAM_set_utf8_ptr(cp, "tuvwxyz"))
|| !TEST_size_t_eq(cp->return_size, sizeof("tuvwxyz") - 1)
|| !TEST_str_eq(bufp, "tuvwxyz")
|| !TEST_true(OSSL_PARAM_get_utf8_ptr(cp, (const char **)&bufp2))
|| !TEST_ptr_eq(bufp2, bufp))
|| !TEST_str_eq(bufp2, "tuvwxyz")
|| (tstid <= 1 && !TEST_ptr_eq(bufp2, bufp)))
goto err;
/* OCTET string */
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "octstr"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "octstr"))
|| !TEST_true(OSSL_PARAM_set_octet_string(cp, "abcdefghi",
sizeof("abcdefghi")))
|| !TEST_size_t_eq(cp->return_size, sizeof("abcdefghi")))
@ -580,19 +601,19 @@ static int test_param_construct(void)
goto err;
/* OCTET pointer */
vp = &l;
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "octptr"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "octptr"))
|| !TEST_true(OSSL_PARAM_set_octet_ptr(cp, &ul, sizeof(ul)))
|| !TEST_size_t_eq(cp->return_size, sizeof(ul))
|| !TEST_ptr_eq(vp, &ul))
|| (tstid <= 1 && !TEST_ptr_eq(vp, &ul)))
goto err;
/* Match the return size to avoid trailing garbage bytes */
cp->data_size = cp->return_size;
if (!TEST_true(OSSL_PARAM_get_octet_ptr(cp, (const void **)&vp2, &k))
|| !TEST_size_t_eq(k, sizeof(ul))
|| !TEST_ptr_eq(vp2, vp))
|| (tstid <= 1 && !TEST_ptr_eq(vp2, vp)))
goto err;
/* BIGNUM */
if (!TEST_ptr(cp = OSSL_PARAM_locate(params, "bignum"))
if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "bignum"))
|| !TEST_ptr(bn = BN_lebin2bn(bn_val, (int)sizeof(bn_val), NULL))
|| !TEST_true(OSSL_PARAM_set_BN(cp, bn))
|| !TEST_size_t_eq(cp->data_size, cp->return_size))
@ -604,6 +625,9 @@ static int test_param_construct(void)
goto err;
ret = 1;
err:
if (p != params)
OPENSSL_free(p);
OPENSSL_free(p1);
OPENSSL_free(vpn);
BN_free(bn);
BN_free(bn2);
@ -637,6 +661,38 @@ static int test_param_modified(void)
return 1;
}
static int test_param_copy_null(void)
{
int ret, val;
int a = 1, b = 2, i = 0;
OSSL_PARAM *cp1 = NULL, *cp2 = NULL, *p;
OSSL_PARAM param[3];
param[i++] = OSSL_PARAM_construct_int("a", &a);
param[i++] = OSSL_PARAM_construct_int("b", &b);
param[i] = OSSL_PARAM_construct_end();
ret = TEST_ptr_null(OSSL_PARAM_dup(NULL))
&& TEST_ptr(cp1 = OSSL_PARAM_merge(NULL, param))
&& TEST_ptr(p = OSSL_PARAM_locate(cp1, "a"))
&& TEST_true(OSSL_PARAM_get_int(p, &val))
&& TEST_int_eq(val, 1)
&& TEST_ptr(p = OSSL_PARAM_locate(cp1, "b"))
&& TEST_true(OSSL_PARAM_get_int(p, &val))
&& TEST_int_eq(val, 2)
&& TEST_ptr(cp2 = OSSL_PARAM_merge(param, NULL))
&& TEST_ptr(p = OSSL_PARAM_locate(cp2, "a"))
&& TEST_true(OSSL_PARAM_get_int(p, &val))
&& TEST_int_eq(val, 1)
&& TEST_ptr(p = OSSL_PARAM_locate(cp2, "b"))
&& TEST_true(OSSL_PARAM_get_int(p, &val))
&& TEST_int_eq(val, 2)
&& TEST_ptr_null(OSSL_PARAM_merge(NULL, NULL));
OSSL_PARAM_free(cp2);
OSSL_PARAM_free(cp1);
return ret;
}
int setup_tests(void)
{
ADD_ALL_TESTS(test_param_int, OSSL_NELEM(raw_values));
@ -651,7 +707,8 @@ int setup_tests(void)
ADD_ALL_TESTS(test_param_uint64, OSSL_NELEM(raw_values));
ADD_ALL_TESTS(test_param_bignum, OSSL_NELEM(raw_values));
ADD_TEST(test_param_real);
ADD_TEST(test_param_construct);
ADD_ALL_TESTS(test_param_construct, 4);
ADD_TEST(test_param_modified);
ADD_TEST(test_param_copy_null);
return 1;
}

View File

@ -5348,3 +5348,6 @@ EVP_KEM_description ? 3_0_0 EXIST::FUNCTION:
EVP_KEYEXCH_description ? 3_0_0 EXIST::FUNCTION:
EVP_KDF_description ? 3_0_0 EXIST::FUNCTION:
X509_CRL_new_ex ? 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_dup ? 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_merge ? 3_0_0 EXIST::FUNCTION:
OSSL_PARAM_free ? 3_0_0 EXIST::FUNCTION: