Make ossl_trace_param_values an official api function

lots of people may want to print params to a buffer.  Make it part of
our api

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25630)
This commit is contained in:
Neil Horman 2024-10-14 13:23:33 -04:00
parent 4fec10eae7
commit 63b671626e
7 changed files with 222 additions and 104 deletions

View File

@ -12,6 +12,7 @@
#include <openssl/ebcdic.h>
#include <openssl/err.h>
#include <openssl/params.h>
#include <openssl/buffer.h>
/*
* When processing text to params, we're trying to be smart with numbers.
@ -197,6 +198,111 @@ static int construct_from_text(OSSL_PARAM *to, const OSSL_PARAM *paramdef,
return 1;
}
/**
* OSSL_PARAM_print_to_bio - Print OSSL_PARAM array to a bio
*
* @p: Array of OSSL_PARAM structures containing keys and values.
* @bio: Pointer to bio where the formatted output will be written.
* @print_values: If non-zero, prints both keys and values. If zero, only keys
* are printed.
*
* This function iterates through the given array of OSSL_PARAM structures,
* printing each key to an in-memory buffer, and optionally printing its
* value based on the provided data type. Supported types include integers,
* strings, octet strings, and real numbers.
*
* Return: 1 on success, 0 on failure.
*/
int OSSL_PARAM_print_to_bio(const OSSL_PARAM *p, BIO *bio, int print_values)
{
int64_t i;
uint64_t u;
BIGNUM *bn;
#ifndef OPENSSL_SYS_UEFI
double d;
#endif
int ok = -1;
int dok;
/*
* Iterate through each key in the array printing its key and value
*/
for (; p->key != NULL; p++) {
ok = -1;
ok = BIO_printf(bio, "%s: ", p->key);
if (ok == -1)
goto end;
/*
* if printing of values was not requested, just move on
* to the next param, after adding a newline to the buffer
*/
if (print_values == 0) {
BIO_printf(bio, "\n");
continue;
}
switch (p->data_type) {
case OSSL_PARAM_UNSIGNED_INTEGER:
if (p->data_size > sizeof(int64_t)) {
if (OSSL_PARAM_get_BN(p, &bn))
ok = BN_print(bio, bn);
else
ok = BIO_printf(bio, "error getting value\n");
} else {
if (OSSL_PARAM_get_uint64(p, &u))
ok = BIO_printf(bio, "%llu\n", (unsigned long long int)u);
else
ok = BIO_printf(bio, "error getting value\n");
}
break;
case OSSL_PARAM_INTEGER:
if (p->data_size > sizeof(int64_t)) {
if (OSSL_PARAM_get_BN(p, &bn))
ok = BN_print(bio, bn);
else
ok = BIO_printf(bio, "error getting value\n");
} else {
if (OSSL_PARAM_get_int64(p, &i))
ok = BIO_printf(bio, "%lld\n", (long long int)i);
else
ok = BIO_printf(bio, "error getting value\n");
}
break;
case OSSL_PARAM_UTF8_PTR:
ok = BIO_dump(bio, p->data, p->data_size);
break;
case OSSL_PARAM_UTF8_STRING:
ok = BIO_dump(bio, (char *)p->data, p->data_size);
break;
case OSSL_PARAM_OCTET_PTR:
case OSSL_PARAM_OCTET_STRING:
ok = BIO_dump(bio, (char *)p->data, p->data_size);
break;
case OSSL_PARAM_REAL:
dok = 0;
#ifndef OPENSSL_SYS_UEFI
dok = OSSL_PARAM_get_double(p, &d);
#endif
if (dok == 1)
ok = BIO_printf(bio, "%f\n", d);
else
ok = BIO_printf(bio, "error getting value\n");
break;
default:
ok = BIO_printf(bio, "unknown type (%u) of %zu bytes\n",
p->data_type, p->data_size);
break;
}
if (ok == -1)
goto end;
}
end:
return ok == -1 ? 0 : 1;
}
int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
const OSSL_PARAM *paramdefs,
const char *key, const char *value,

View File

@ -297,7 +297,7 @@ static int ossl_method_store_insert(OSSL_METHOD_STORE *store, ALGORITHM *alg)
* reference count and destruction callbacks.
*
* @param store Pointer to the OSSL_METHOD_STORE where the method will be added.
* must be non-null.
* Must be non-null.
* @param prov Pointer to the OSSL_PROVIDER for the provider of the method.
* Must be non-null.
* @param nid (identifier) associated with the method, must be > 0
@ -402,10 +402,11 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
if (tmpimpl->provider == impl->provider
&& tmpimpl->properties == impl->properties)
goto err;
break;
}
if (sk_IMPLEMENTATION_push(alg->impls, impl)) {
if (i == sk_IMPLEMENTATION_num(alg->impls)
&& sk_IMPLEMENTATION_push(alg->impls, impl)) {
ret = 1;
OSSL_TRACE_BEGIN(QUERY) {
BIO_printf(trc_out, "Adding to method store "
@ -503,7 +504,8 @@ alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
char buf[512];
size_t size;
size = ossl_property_list_to_string(NULL, impl->properties, buf, 512);
size = ossl_property_list_to_string(NULL, impl->properties, buf,
sizeof(buf));
BIO_printf(trc_out, "Removing implementation from "
"query cache\nproperties %s\nprovider %s\n",
size == 0 ? "none" : buf,
@ -597,7 +599,7 @@ void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
* successful, it returns the method and its associated provider.
*
* @param store Pointer to the OSSL_METHOD_STORE from which to fetch the method.
* Must be non-null
* Must be non-null.
* @param nid (identifier) of the method to be fetched. Must be > 0
* @param prop_query String containing the property query to match against.
* @param prov_rw Pointer to the OSSL_PROVIDER to restrict the search to, or
@ -669,7 +671,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
/*
* Search for a provider that provides this implementation.
* if the requested provider is NULL, then any provider will do,
* If the requested provider is NULL, then any provider will do,
* otherwise we should try to find the one that matches the requested
* provider. Note that providers are given implicit preference via the
* ordering of the implementation stack
@ -688,7 +690,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
/*
* If there are optional properties specified
* the search again, and select the provider that matches the
* then run the search again, and select the provider that matches the
* most options
*/
optional = ossl_property_has_optional(pq);

View File

@ -1618,74 +1618,6 @@ OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov)
return prov != NULL ? prov->libctx : NULL;
}
/**
* @brief Prints the parameter values of an OSSL_PARAM array to a BIO.
*
* This function iterates over an array of OSSL_PARAM structures and prints the
* value of each parameter to the specified BIO stream. The parameter type is
* detected, and the value is printed accordingly.
*
* @param p Array of OSSL_PARAM structures to be printed.
* @param b BIO stream to print the parameter values to.
*
* The supported parameter types are:
* - OSSL_PARAM_UNSIGNED_INTEGER: Unsigned integer values.
* - OSSL_PARAM_INTEGER: Signed integer values.
* - OSSL_PARAM_UTF8_PTR: Pointer to a UTF-8 string.
* - OSSL_PARAM_UTF8_STRING: UTF-8 string.
* - OSSL_PARAM_OCTET_PTR/OCTET_STRING: Binary data (size in bytes).
*/
#ifndef FIPS_MODULE
static void trace_print_param_values(const OSSL_PARAM p[], BIO *b)
{
int64_t i;
uint64_t u;
# ifndef OPENSSL_SYS_UEFI
double d;
# endif
for (; p->key != NULL; p++) {
BIO_printf(b, "%s: ", p->key);
switch (p->data_type) {
case OSSL_PARAM_UNSIGNED_INTEGER:
if (OSSL_PARAM_get_uint64(p, &u))
BIO_printf(b, "%llu\n", (unsigned long long int)u);
else
BIO_printf(b, "error getting value\n");
break;
case OSSL_PARAM_INTEGER:
if (OSSL_PARAM_get_int64(p, &i))
BIO_printf(b, "%lld\n", (long long int)i);
else
BIO_printf(b, "error getting value\n");
break;
case OSSL_PARAM_UTF8_PTR:
BIO_printf(b, "'%s'\n", *(char **)(p->data));
break;
case OSSL_PARAM_UTF8_STRING:
BIO_printf(b, "'%s'\n", (char *)p->data);
break;
case OSSL_PARAM_OCTET_PTR:
case OSSL_PARAM_OCTET_STRING:
BIO_printf(b, "<%zu bytes>\n", p->data_size);
break;
# ifndef OPENSSL_SYS_UEFI
case OSSL_PARAM_REAL:
if (OSSL_PARAM_get_double(p, &d))
BIO_printf(b, "%f\n", d);
else
BIO_printf(b, "error getting value\n");
break;
# endif
default:
BIO_printf(b, "unknown type (%u) of %zu bytes\n",
p->data_type, p->data_size);
break;
}
}
}
#endif
/**
* @brief Tears down the given provider.
*
@ -1732,16 +1664,26 @@ const OSSL_PARAM *ossl_provider_gettable_params(const OSSL_PROVIDER *prov)
{
const OSSL_PARAM *ret = NULL;
if (prov->gettable_params != NULL) {
if (prov->gettable_params != NULL)
ret = prov->gettable_params(prov->provctx);
#ifndef FIPS_MODULE
OSSL_TRACE_BEGIN(PROVIDER) {
char *buf = NULL;
BIO_printf(trc_out, "(provider %s) gettable params\n",
ossl_provider_name(prov));
trace_print_param_values(ret, trc_out);
BIO_printf(trc_out, "Parameters:\n");
if (prov->gettable_params != NULL) {
if (!OSSL_PARAM_print_to_bio(ret, trc_out, 0))
BIO_printf(trc_out, "Failed to parse param values\n");
OPENSSL_free(buf);
} else {
BIO_printf(trc_out, "Provider doesn't implement gettable_params\n");
}
} OSSL_TRACE_END(PROVIDER);
#endif
}
return ret;
}
@ -1768,13 +1710,18 @@ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
ret = prov->get_params(prov->provctx, params);
#ifndef FIPS_MODULE
if (ret == 1) {
OSSL_TRACE_BEGIN(PROVIDER) {
BIO_printf(trc_out,
"(provider %s) calling get_params\n", prov->name);
trace_print_param_values(params, trc_out);
} OSSL_TRACE_END(PROVIDER);
if (ret == 1) {
BIO_printf(trc_out, "Parameters:\n");
if (!OSSL_PARAM_print_to_bio(params, trc_out, 1))
BIO_printf(trc_out, "Failed to parse param values\n");
} else {
BIO_printf(trc_out, "get_params call failed\n");
}
} OSSL_TRACE_END(PROVIDER);
#endif
return ret;
}
@ -1795,18 +1742,21 @@ int ossl_provider_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[])
*/
int ossl_provider_self_test(const OSSL_PROVIDER *prov)
{
int ret;
if (prov->self_test == NULL)
return 1;
int ret = 1;
if (prov->self_test != NULL)
ret = prov->self_test(prov->provctx);
#ifndef FIPS_MODULE
OSSL_TRACE_BEGIN(PROVIDER) {
if (prov->self_test != NULL)
BIO_printf(trc_out,
"(provider %s) Calling self_test, ret = %d\n",
prov->name, ret);
else
BIO_printf(trc_out,
"(provider %s) doesn't implement self_test\n",
prov->name);
} OSSL_TRACE_END(PROVIDER);
#endif
if (ret == 0)
@ -1875,15 +1825,21 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
{
const OSSL_ALGORITHM *res;
if (prov->query_operation == NULL)
if (prov->query_operation == NULL) {
#ifndef FIPS_MODULE
OSSL_TRACE_BEGIN(PROVIDER) {
BIO_printf(trc_out, "provider %s lacks query operation!\n",
prov->name);
} OSSL_TRACE_END(PROVIDER);
#endif
return NULL;
}
res = prov->query_operation(prov->provctx, operation_id, no_cache);
#ifndef FIPS_MODULE
if (res != NULL) {
OSSL_TRACE_BEGIN(PROVIDER) {
const OSSL_ALGORITHM *idx;
if (res != NULL) {
BIO_printf(trc_out,
"(provider %s) Calling query, available algs are:\n", prov->name);
@ -1898,8 +1854,10 @@ const OSSL_ALGORITHM *ossl_provider_query_operation(const OSSL_PROVIDER *prov,
res->algorithm_description == NULL ? "none" :
res->algorithm_description);
}
} OSSL_TRACE_END(PROVIDER);
} else {
BIO_printf(trc_out, "(provider %s) query_operation failed\n", prov->name);
}
} OSSL_TRACE_END(PROVIDER);
#endif
#if defined(OPENSSL_NO_CACHED_FETCH)

View File

@ -1787,6 +1787,10 @@ 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
GENERATE[man/man3/OSSL_PARAM_int.3]=man3/OSSL_PARAM_int.pod
DEPEND[html/man3/OSSL_PARAM_print_to_bio.html]=man3/OSSL_PARAM_print_to_bio.pod
GENERATE[html/man3/OSSL_PARAM_print_to_bio.html]=man3/OSSL_PARAM_print_to_bio.pod
DEPEND[man/man3/OSSL_PARAM_print_to_bio.3]=man3/OSSL_PARAM_print_to_bio.pod
GENERATE[man/man3/OSSL_PARAM_print_to_bio.3]=man3/OSSL_PARAM_print_to_bio.pod
DEPEND[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
GENERATE[html/man3/OSSL_PROVIDER.html]=man3/OSSL_PROVIDER.pod
DEPEND[man/man3/OSSL_PROVIDER.3]=man3/OSSL_PROVIDER.pod
@ -3450,6 +3454,7 @@ 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_PARAM_print_to_bio.html \
html/man3/OSSL_PROVIDER.html \
html/man3/OSSL_QUIC_client_method.html \
html/man3/OSSL_SELF_TEST_new.html \
@ -4113,6 +4118,7 @@ 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_PARAM_print_to_bio.3 \
man/man3/OSSL_PROVIDER.3 \
man/man3/OSSL_QUIC_client_method.3 \
man/man3/OSSL_SELF_TEST_new.3 \

View File

@ -0,0 +1,42 @@
=pod
=head1 NAME
OSSL_PARAM_print_to_bio
- OSSL_PARAM interrogation utilities
=head1 SYNOPSIS
#include <openssl/params.h>
int OSSL_PARAM_print_to_bio(const OSSL_PARAM *p, BIO *bio,
int print_values);
=head1 DESCRIPTION
OSSL_PARAM_print_to_bio() formats each parameter contained in the
passed in array of B<OSSL_PARAM> values I<p>, and prints both the key,
and optionally its value, to a provided B<BIO>.
I<p> must be a non-null array of OSSL_PARAM values, terminated
with a value containing a null I<key> member.
I<print_values> is a control parameter, indicating that key values should be
printed, in addition to key names.
=head1 RETURN VALUES
OSSL_PARAM_print_to_bio() returns 1 on success, and 0 on failure
=head1 HISTORY
OSSL_PARAM_print_to_bio() was added in OpenSSL 3.5
=head1 COPYRIGHT
Copyright 2024 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

@ -100,6 +100,9 @@ int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
const char *key, const char *value,
size_t value_n, int *found);
int OSSL_PARAM_print_to_bio(const OSSL_PARAM *params, BIO *bio,
int print_values);
int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val);
int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val);
int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val);

View File

@ -5775,3 +5775,4 @@ d2i_OSSL_PRIVILEGE_POLICY_ID ? 3_5_0 EXIST::FUNCTION:
i2d_OSSL_PRIVILEGE_POLICY_ID ? 3_5_0 EXIST::FUNCTION:
OSSL_PRIVILEGE_POLICY_ID_free ? 3_5_0 EXIST::FUNCTION:
OSSL_PRIVILEGE_POLICY_ID_new ? 3_5_0 EXIST::FUNCTION:
OSSL_PARAM_print_to_bio ? 3_5_0 EXIST::FUNCTION: