summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPauli <paul.dale@oracle.com>2019-02-22 12:21:33 +1000
committerRichard Levitte <levitte@openssl.org>2019-03-12 19:12:12 +0100
commit7ffbd7ca9696ade5274068c29a8e03217f596e57 (patch)
tree01061d02685de3c4b18b4ca34559f3fd7ddd729b
parent8c4412ed8fe80a8b92549d7e2db1359012074d65 (diff)
OSSL_PARAM helper functions.
Provide a number of functions to allow parameters to be set and retrieved in a type safe manner. Functions are provided for many integral types plus double, BIGNUM, UTF8 strings and OCTET strings. All of the integer functions will widen the parameter data as required. This permits a degree of malleability in the parameter definition. For example a type can be changed from a thirty two bit integer to a sixty four bit one without changing application code. Only four and eight byte integral sizes are supported here. A pair of real functions are available for doubles. A pair of functions is available for BIGNUMs. These accept any sized unsigned integer input and convert to/from a BIGNUM. For each OCTET and UTF8 strings, four functions are defined. This provide get and set functionality for string and for pointers to strings. The latter avoiding copies but have other inherent risks. Finally, some utility macros and functions are defined to allow OSSL_PARAM definition arrays to be specified in a simple manner. There are two macro and one function for most types. The exception being BIGNUM, for which there is one macro and one function. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Richard Levitte <levitte@openssl.org> (Merged from https://github.com/openssl/openssl/pull/8451)
-rw-r--r--crypto/build.info2
-rw-r--r--crypto/params.c725
-rw-r--r--doc/man3/OSSL_PARAM.pod57
-rw-r--r--doc/man3/OSSL_PARAM_TYPE.pod312
-rw-r--r--include/openssl/core.h33
-rw-r--r--include/openssl/params.h186
-rw-r--r--test/build.info6
-rw-r--r--test/params_api_test.c627
-rw-r--r--test/recipes/03-test_params_api.t12
-rw-r--r--test/testutil.h9
-rw-r--r--test/testutil/tests.c1
-rw-r--r--util/private.num15
12 files changed, 1942 insertions, 43 deletions
diff --git a/crypto/build.info b/crypto/build.info
index a1ccad44ea..6497c2fe9e 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -17,7 +17,7 @@ SOURCE[../libcrypto]=\
ebcdic.c uid.c o_time.c o_str.c o_dir.c o_fopen.c ctype.c \
threads_pthread.c threads_win.c threads_none.c getenv.c \
o_init.c o_fips.c mem_sec.c init.c context.c sparse_array.c \
- trace.c provider.c \
+ trace.c provider.c params.c \
{- $target{cpuid_asm_src} -} {- $target{uplink_aux_src} -}
DEPEND[cversion.o]=buildinf.h
diff --git a/crypto/params.c b/crypto/params.c
new file mode 100644
index 0000000000..a53d5134d7
--- /dev/null
+++ b/crypto/params.c
@@ -0,0 +1,725 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2019, Oracle and/or its affiliates. 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 "internal/thread_once.h"
+
+#define SET_RETURN_SIZE(p, sz) \
+ if ((p)->return_size != NULL) \
+ *(p)->return_size = (sz)
+
+const OSSL_PARAM *OSSL_PARAM_locate(const OSSL_PARAM *p, const char *key)
+{
+ if (p != NULL && key != NULL)
+ for (; p->key != NULL; p++)
+ if (strcmp(key, p->key) == 0)
+ return p;
+ return NULL;
+}
+
+static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
+ void *data, size_t data_size,
+ size_t *return_size)
+{
+ OSSL_PARAM res;
+
+ res.key = key;
+ res.data_type = data_type;
+ res.data = data;
+ res.data_size = data_size;
+ res.return_size = return_size;
+ return res;
+}
+
+int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
+{
+ if (val == NULL || p == NULL || p->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (sizeof(int) >= sizeof(int32_t)) {
+ *val = (int)*(const int32_t *)p->data;
+ return 1;
+ }
+ break;
+ case sizeof(int64_t):
+ if (sizeof(int) >= sizeof(int64_t)) {
+ *val = (int)*(const int64_t *)p->data;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int(const OSSL_PARAM *p, int val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(int)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (sizeof(int32_t) >= sizeof(int)) {
+ SET_RETURN_SIZE(p, sizeof(int32_t));
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(int64_t):
+ if (sizeof(int64_t) >= sizeof(int)) {
+ SET_RETURN_SIZE(p, sizeof(int64_t));
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf, size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int),
+ rsize);
+}
+
+int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
+{
+ if (val == NULL
+ || p == NULL
+ || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(unsigned int) >= sizeof(uint32_t)) {
+ *val = (unsigned int)*(const uint32_t *)p->data;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (sizeof(unsigned int) >= sizeof(uint64_t)) {
+ *val = (unsigned int)*(const uint64_t *)p->data;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_uint(const OSSL_PARAM *p, unsigned int val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(unsigned int)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(uint32_t) >= sizeof(unsigned int)) {
+ SET_RETURN_SIZE(p, sizeof(uint32_t));
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (sizeof(uint64_t) >= sizeof(unsigned int)) {
+ SET_RETURN_SIZE(p, sizeof(uint64_t));
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(unsigned int), rsize);
+}
+
+int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
+{
+ if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (sizeof(long int) >= sizeof(int32_t)) {
+ *val = (long int)*(const int32_t *)p->data;
+ return 1;
+ } break;
+ case sizeof(int64_t):
+ if (sizeof(long int) >= sizeof(int64_t)) {
+ *val = (long int)*(const int64_t *)p->data;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_long(const OSSL_PARAM *p, long int val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(long int)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ if (sizeof(int32_t) >= sizeof(long int)) {
+ SET_RETURN_SIZE(p, sizeof(int32_t));
+ *(int32_t *)p->data = (int32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(int64_t):
+ if (sizeof(int64_t) >= sizeof(long int)) {
+ SET_RETURN_SIZE(p, sizeof(int64_t));
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int),
+ rsize);
+}
+
+int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
+{
+ if (val == NULL
+ || p == NULL
+ || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(unsigned long int) >= sizeof(uint32_t)) {
+ *val = (unsigned long int)*(const uint32_t *)p->data;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (sizeof(unsigned long int) >= sizeof(uint64_t)) {
+ *val = (unsigned long int)*(const uint64_t *)p->data;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_ulong(const OSSL_PARAM *p, unsigned long int val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(unsigned long int)); /* Minimum exp size */
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(uint32_t) >= sizeof(unsigned long int)) {
+ SET_RETURN_SIZE(p, sizeof(uint32_t));
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (sizeof(uint64_t) >= sizeof(unsigned long int)) {
+ SET_RETURN_SIZE(p, sizeof(uint64_t));
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(unsigned long int), rsize);
+}
+
+int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
+{
+ if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
+ return 0;
+
+ if (p->data_size == sizeof(int32_t)) {
+ *val = *(const int32_t *)p->data;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int32(const OSSL_PARAM *p, int32_t val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(int32_t)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ SET_RETURN_SIZE(p, sizeof(int32_t));
+ *(int32_t *)p->data = val;
+ return 1;
+ case sizeof(int64_t):
+ SET_RETURN_SIZE(p, sizeof(int64_t));
+ *(int64_t *)p->data = (int64_t)val;
+ return 1;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf,
+ sizeof(int32_t), rsize);
+}
+
+int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
+{
+ if (val == NULL
+ || p == NULL
+ || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+ return 0;
+
+ if (p->data_size == sizeof(uint32_t)) {
+ *val = *(const uint32_t *)p->data;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_uint32(const OSSL_PARAM *p, uint32_t val)
+{
+ if (p == NULL) return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(uint32_t)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ SET_RETURN_SIZE(p, sizeof(uint32_t));
+ *(uint32_t *)p->data = val;
+ return 1;
+ case sizeof(uint64_t):
+ SET_RETURN_SIZE(p, sizeof(uint64_t));
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(uint32_t), rsize);
+}
+
+int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
+{
+ if (val == NULL || p == NULL || (p->data_type != OSSL_PARAM_INTEGER))
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(int32_t):
+ *val = (int64_t)*(const int32_t *)p->data;
+ return 1;
+ case sizeof(int64_t):
+ *val = *(const int64_t *)p->data;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_int64(const OSSL_PARAM *p, int64_t val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(int64_t)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(int64_t):
+ SET_RETURN_SIZE(p, sizeof(int64_t));
+ *(int64_t *)p->data = val;
+ return 1;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t),
+ rsize);
+}
+
+int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
+{
+ if (val == NULL
+ || p == NULL
+ || (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER))
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ *val = (uint64_t)*(const uint32_t *)p->data;
+ return 1;
+ case sizeof(uint64_t):
+ *val = *(const uint64_t *)p->data;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_uint64(const OSSL_PARAM *p, uint64_t val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(uint64_t)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(uint64_t):
+ SET_RETURN_SIZE(p, sizeof(uint64_t));
+ *(uint64_t *)p->data = val;
+ return 1;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf,
+ size_t *rsize) {
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(uint64_t), rsize);
+}
+
+int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
+{
+ if (val == NULL
+ || p == NULL
+ || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(size_t) >= sizeof(uint32_t)) {
+ *val = (size_t)*(const uint32_t *)p->data;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ if (sizeof(size_t) >= sizeof(uint64_t)) {
+ *val = (size_t)*(const uint64_t *)p->data;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_size_t(const OSSL_PARAM *p, size_t val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ SET_RETURN_SIZE(p, sizeof(size_t)); /* Minimum expected size */
+ switch (p->data_size) {
+ case sizeof(uint32_t):
+ if (sizeof(uint32_t) >= sizeof(size_t)) {
+ SET_RETURN_SIZE(p, sizeof(uint32_t));
+ *(uint32_t *)p->data = (uint32_t)val;
+ return 1;
+ }
+ break;
+ case sizeof(uint64_t):
+ SET_RETURN_SIZE(p, sizeof(uint64_t));
+ if (sizeof(uint64_t) >= sizeof(size_t)) {
+ *(uint64_t *)p->data = (uint64_t)val;
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
+ sizeof(size_t), rsize); }
+
+int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
+{
+ BIGNUM *b;
+
+ if (val == NULL
+ || p == NULL
+ || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ b = BN_native2bn(p->data, (int)p->data_size, *val);
+ if (b != NULL) {
+ *val = b;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_BN(const OSSL_PARAM *p, const BIGNUM *val)
+{
+ size_t bytes;
+
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
+ return 0;
+
+ bytes = (size_t)BN_num_bytes(val);
+ SET_RETURN_SIZE(p, bytes);
+ return p->data_size >= bytes
+ && BN_bn2nativepad(val, p->data, bytes) >= 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
+ size_t bsize, size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER,
+ buf, bsize, rsize);
+}
+
+int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
+{
+ if (val == NULL || p == NULL || p->data_type != OSSL_PARAM_REAL)
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(double):
+ *val = *(const double *)p->data;
+ return 1;
+ }
+ return 0;
+}
+
+int OSSL_PARAM_set_double(const OSSL_PARAM *p, double val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (p->data_type != OSSL_PARAM_REAL)
+ return 0;
+
+ switch (p->data_size) {
+ case sizeof(double):
+ SET_RETURN_SIZE(p, sizeof(double));
+ *(double *)p->data = val;
+ return 1;
+ }
+ return 0;
+}
+
+OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double),
+ rsize);
+}
+
+static int get_string_internal(const OSSL_PARAM *p, void **val, size_t max_len,
+ size_t *used_len, unsigned int type)
+{
+ size_t sz;
+
+ if (val == NULL || p == NULL || p->data_type != type)
+ return 0;
+
+ sz = p->data_size;
+
+ if (used_len != NULL)
+ *used_len = sz;
+
+ if (*val == NULL) {
+ char *const q = OPENSSL_malloc(sz);
+
+ if (q == NULL)
+ return 0;
+ *val = q;
+ memcpy(q, p->data, sz);
+ return 1;
+ }
+ if (max_len < sz)
+ return 0;
+ memcpy(*val, p->data, sz);
+ return 1;
+}
+
+int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len)
+{
+ return get_string_internal(p, (void **)val, max_len, NULL,
+ OSSL_PARAM_UTF8_STRING);
+}
+
+int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
+ size_t *used_len)
+{
+ return get_string_internal(p, val, max_len, used_len,
+ OSSL_PARAM_OCTET_STRING);
+}
+
+static int set_string_internal(const OSSL_PARAM *p, const void *val, size_t len,
+ unsigned int type)
+{
+ SET_RETURN_SIZE(p, len);
+ if (p->data_type != type || p->data_size < len)
+ return 0;
+
+ memcpy(p->data, val, len);
+ return 1;
+}
+
+int OSSL_PARAM_set_utf8_string(const OSSL_PARAM *p, const char *val)
+{
+ if (p == NULL)
+ return 0;
+
+ SET_RETURN_SIZE(p, 0);
+ if (val == NULL)
+ return 0;
+ return set_string_internal(p, val, strlen(val) + 1, OSSL_PARAM_UTF8_STRING);
+}
+
+int OSSL_PARAM_set_octet_string(const OSSL_PARAM *p, const void *val,
+ size_t len)
+{
+ if (p == NULL)
+ return 0;
+
+ SET_RETURN_SIZE(p, 0);
+ if (val == NULL)
+ return 0;
+ return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
+ size_t bsize, size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize,
+ rsize);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
+ size_t bsize, size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize,
+ rsize);
+}
+
+static int get_ptr_internal(const OSSL_PARAM *p, const void **val,
+ size_t *used_len, unsigned int type)
+{
+ if (val == NULL || p == NULL || p->data_type != type)
+ return 0;
+ if (used_len != NULL)
+ *used_len = p->data_size;
+ *val = *(const void **)p->data;
+ return 1;
+}
+
+int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val)
+{
+ return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR);
+}
+
+int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
+ size_t *used_len)
+{
+ return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR);
+}
+
+static int set_ptr_internal(const OSSL_PARAM *p, const void *val,
+ unsigned int type, size_t len)
+{
+ SET_RETURN_SIZE(p, len);
+ if (p->data_type != type)
+ return 0;
+ *(const void **)p->data = val;
+ return 1;
+}
+
+int OSSL_PARAM_set_utf8_ptr(const OSSL_PARAM *p, const char *val)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (val == NULL)
+ return 0;
+ return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR, strlen(val) + 1);
+}
+
+int OSSL_PARAM_set_octet_ptr(const OSSL_PARAM *p, const void *val,
+ size_t used_len)
+{
+ if (p == NULL)
+ return 0;
+ SET_RETURN_SIZE(p, 0);
+ if (val == NULL)
+ return 0;
+ return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, 0, rsize);
+}
+
+OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
+ size_t *rsize)
+{
+ return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, 0, rsize);
+}
diff --git a/doc/man3/OSSL_PARAM.pod b/doc/man3/OSSL_PARAM.pod
index a90069cd47..50089b4d50 100644
--- a/doc/man3/OSSL_PARAM.pod
+++ b/doc/man3/OSSL_PARAM.pod
@@ -118,8 +118,6 @@ systems.
=item C<OSSL_PARAM_REAL>
-=for comment It's still debated if we need this or not.
-
The parameter data is a floating point value in native form.
=item C<OSSL_PARAM_UTF8_STRING>
@@ -130,47 +128,50 @@ The parameter data is a printable string.
The parameter data is an arbitrary string of bytes.
-=back
-
-Additionally, this flag can be added to any type:
+=item C<OSSL_PARAM_UTF8_PTR>
-=over 4
-
-=item C<OSSL_PARAM_POINTER_FLAG>
+The parameter data is a pointer to a printable string.
-With this flag, C<data> doesn't point directly at the data, but at a
-pointer that points at the data.
+The difference between this and C<OSSL_PARAM_UTF8_STRING> is that C<data>
+doesn't point directly at the data, but to a pointer that points to the data.
-This can be used to indicate that constant data is or will be passed,
+This is used to indicate that constant data is or will be passed,
and there is therefore no need to copy the data that is passed, just
the pointer to it.
-If an C<OSSL_PARAM> with this flag set is used to set a parameter,
-C<data_size> must be set to the size of the data, not the size of
-the pointer to the data.
-
-If this C<OSSL_PARAM> is used in a parameter request, C<data_size>
-is not relevant.
-However, the I<responder> will set C<*return_size> to the size of the
-data (again, not the size of the pointer to the data).
+C<data_size> must be set to the size of the data, not the size of the
+pointer to the data.
+If this is used in a parameter request,
+C<data_size> is not relevant. However, the I<responder> will set
+C<*return_size> to the size of the data.
-Note that the use of this flag is B<fragile> and can only be safely
+Note that the use of this type is B<fragile> and can only be safely
used for data that remains constant and in a constant location for a
long enough duration (such as the life-time of the entity that
offers these parameters).
-=back
+=item C<OSSL_PARAM_OCTET_PTR>
-For convenience, these types are provided:
+The parameter data is a pointer to an arbitrary string of bytes.
-=over 4
+The difference between this and C<OSSL_PARAM_OCTET_STRING> is that
+C<data> doesn't point directly at the data, but to a pointer that
+points to the data.
-=item C<OSSL_PARAM_UTF8_STRING_PTR>
+This is used to indicate that constant data is or will be passed, and
+there is therefore no need to copy the data that is passed, just the
+pointer to it.
-=item C<OSSL_PARAM_OCTET_STRING_PTR>
+C<data_size> must be set to the size of the data, not the size of the
+pointer to the data.
+If this is used in a parameter request,
+C<data_size> is not relevant. However, the I<responder> will set
+C<*return_size> to the size of the data.
-These are combinations of C<OSSL_PARAM_UTF8_STRING> as well as
-C<OSSL_PARAM_OCTET_STRING> with C<OSSL_PARAM_POINTER_FLAG>.
+Note that the use of this type is B<fragile> and can only be safely
+used for data that remains constant and in a constant location for a
+long enough duration (such as the life-time of the entity that
+offers these parameters).
=back
@@ -283,7 +284,7 @@ could fill in the parameters like this:
=head1 SEE ALSO
-L<openssl-core.h(7)>
+L<openssl-core.h(7)>, L<OSSL_PARAM_get_int32_t(3)>
=head1 HISTORY
diff --git a/doc/man3/OSSL_PARAM_TYPE.pod b/doc/man3/OSSL_PARAM_TYPE.pod
new file mode 100644
index 0000000000..c4ca37a344
--- /dev/null
+++ b/doc/man3/OSSL_PARAM_TYPE.pod
@@ -0,0 +1,312 @@
+=pod
+
+=head1 NAME
+
+OSSL_PARAM_TYPE, OSSL_PARAM_utf8_string, OSSL_PARAM_octet_string,
+OSSL_PARAM_utf8_ptr, OSSL_PARAM_octet_ptr, OSSL_PARAM_SIZED_TYPE,
+OSSL_PARAM_SIZED_BN, OSSL_PARAM_SIZED_utf8_string,
+OSSL_PARAM_SIZED_octet_string, OSSL_PARAM_SIZED_utf8_ptr,
+OSSL_PARAM_SIZED_octet_ptr, OSSL_PARAM_END, OSSL_PARAM_construct_TYPE,
+OSSL_PARAM_END,
+OSSL_PARAM_construct_BN, OSSL_PARAM_construct_utf8_string,
+OSSL_PARAM_construct_utf8_ptr, OSSL_PARAM_construct_octet_string,
+OSSL_PARAM_construct_octet_ptr, OSSL_PARAM_locate, OSSL_PARAM_get_TYPE,
+OSSL_PARAM_set_TYPE, OSSL_PARAM_get_BN, OSSL_PARAM_set_BN,
+OSSL_PARAM_get_utf8_string, OSSL_PARAM_set_utf8_string,
+OSSL_PARAM_get_octet_string, OSSL_PARAM_set_octet_string,
+OSSL_PARAM_get_utf8_ptr, OSSL_PARAM_set_utf8_ptr, OSSL_PARAM_get_octet_ptr,
+OSSL_PARAM_set_octet_ptr
+- OSSL_PARAM helpers
+
+=head1 SYNOPSIS
+
+ #include <openssl/params.h>
+
+ #define OSSL_PARAM_TYPE(key, address)
+ #define OSSL_PARAM_utf8_string(key, address, size)
+ #define OSSL_PARAM_octet_string(key, address, size)
+ #define OSSL_PARAM_utf8_ptr(key, address, size)
+ #define OSSL_PARAM_octet_ptr(key, address, size)
+ #define OSSL_PARAM_SIZED_TYPE(key, address, return_size)
+ #define OSSL_PARAM_SIZED_BN(key, address, size, return_size)
+ #define OSSL_PARAM_SIZED_utf8_string(key, address, size, return_size)
+ #define OSSL_PARAM_SIZED_octet_string(key, address, size, return_size)
+ #define OSSL_PARAM_SIZED_utf8_ptr(key, address, size, return_size)
+ #define OSSL_PARAM_SIZED_octet_ptr(key, address, size, return_size)
+ #define OSSL_PARAM_END
+
+ OSSL_PARAM OSSL_PARAM_construct_TYPE(const char *key, TYPE *buf, size_t *ret);
+ OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
+ size_t bsize, size_t *rsize);
+ OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
+ size_t bsize, size_t *rsize);
+ OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
+ size_t bsize, size_t *rsize);
+ OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
+ size_t *rsize);
+ OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
+ size_t *rsize);
+
+ OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *array, const char *key);
+
+ int OSSL_PARAM_get_TYPE(const OSSL_PARAM *p, const char *key, TYPE *val);
+ int OSSL_PARAM_set_TYPE(const OSSL_PARAM *p, const char *key, TYPE val);
+
+ int OSSL_PARAM_get_BN(const OSSL_PARAM *p, const char *key, BIGNUM **val);
+ int OSSL_PARAM_set_BN(const OSSL_PARAM *p, const char *key, const BIGNUM *val);
+
+ int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val,
+ size_t max_len);
+ int OSSL_PARAM_set_utf8_string(const OSSL_PARAM *p, const char *val);
+
+ int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val,
+ size_t max_len, size_t *used_len);
+ int OSSL_PARAM_set_octet_string(const OSSL_PARAM *p, const void *val,
+ size_t len);
+
+ int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, char **val);
+ int OSSL_PARAM_set_utf8_ptr(const OSSL_PARAM *p, char *val);
+
+ int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, void **val,
+ size_t *used_len);
+ int OSSL_PARAM_set_octet_ptr(const OSSL_PARAM *p, void *val, size_t used_len);
+
+=head1 DESCRIPTION
+
+A collection of utility functions that simplify and add type safety to the
+OSSL_PARAM arrays. The following B<TYPE> names are supported:
+
+=over 1
+
+=item *
+
+double
+
+=item *
+
+int
+
+=item *
+
+int32 (int32_t)
+
+=item *
+
+int64 (int64_t)
+
+=item *
+
+long int (long)
+
+=item *
+
+size_t
+
+=item *
+
+uint32 (uint32_t)
+
+=item *
+
+uint64 (uint64_t)
+
+=item *
+
+unsigned int (uint)
+
+=item *
+
+unsigned long int (ulong)
+
+=back
+
+OSSL_PARAM_TYPE() are a series of macros designed to assist initialising an
+array of OSSL_PARAM structures.
+Each of these macros defines a parameter of the specified B<TYPE> with the
+provided B<key> and parameter variable B<address>.
+
+OSSL_PARAM_utf8_string(), OSSL_PARAM_octet_string(), OSSL_PARAM_utf8_ptr(),
+OSSL_