From e2ed740ec4dcfd32723d849a146bfc126b95d16c Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 7 May 2021 16:42:53 +0100 Subject: Implement the ability to convert a PROPERTY_LIST to a string We have the ability to parse a string into a PROPERTY_LIST already. Now we have the ability to go the other way. Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/15242) --- crypto/evp/evp_fetch.c | 12 +++- crypto/property/property_local.h | 2 + crypto/property/property_parse.c | 130 ++++++++++++++++++++++++++++++++++++++ crypto/property/property_string.c | 44 +++++++++++++ include/internal/property.h | 4 ++ include/openssl/lhash.h.in | 7 ++ 6 files changed, 197 insertions(+), 2 deletions(-) diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 6c701bf1e2..fdb6d90f4d 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -409,7 +409,11 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq, ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR); return 0; } - return evp_set_parsed_default_properties(libctx, pl, loadconfig); + if (!evp_set_parsed_default_properties(libctx, pl, loadconfig)) { + ossl_property_free(pl); + return 0; + } + return 1; } int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq) @@ -436,7 +440,11 @@ static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq) ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); return 0; } - return evp_set_parsed_default_properties(libctx, pl2, 0); + if (!evp_set_parsed_default_properties(libctx, pl2, 0)) { + ossl_property_free(pl2); + return 0; + } + return 1; } static int evp_default_property_is_enabled(OSSL_LIB_CTX *libctx, diff --git a/crypto/property/property_local.h b/crypto/property/property_local.h index c744a5d3c3..8cc3a51270 100644 --- a/crypto/property/property_local.h +++ b/crypto/property/property_local.h @@ -16,8 +16,10 @@ typedef int OSSL_PROPERTY_IDX; /* Property string functions */ OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s, int create); +const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx); OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s, int create); +const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx); /* Property list functions */ void ossl_property_free(OSSL_PROPERTY_LIST *p); diff --git a/crypto/property/property_parse.c b/crypto/property/property_parse.c index dfae76518f..aab8cbe8a4 100644 --- a/crypto/property/property_parse.c +++ b/crypto/property/property_parse.c @@ -616,3 +616,133 @@ int ossl_property_parse_init(OSSL_LIB_CTX *ctx) err: return 0; } + +static void put_char(char ch, char **buf, size_t *remain, size_t *needed) +{ + if (*remain == 0) { + ++*needed; + return; + } + if(*remain == 1) + **buf = '\0'; + else + **buf = ch; + ++*buf; + ++*needed; + --*remain; +} + +static void put_str(const char *str, char **buf, size_t *remain, size_t *needed) +{ + size_t olen, len; + + len = olen = strlen(str); + *needed += len; + + if (*remain == 0) + return; + + if(*remain < len + 1) + len = *remain - 1; + + if(len > 0) { + strncpy(*buf, str, len); + *buf += len; + *remain -= len; + } + + if(len < olen && *remain == 1) { + **buf = '\0'; + ++*buf; + --*remain; + } +} + +static void put_num(int val, char **buf, size_t *remain, size_t *needed) +{ + int tmpval = val; + size_t len = 1; + + for (; tmpval > 9; len++, tmpval /= 10); + + *needed += len; + + if (*remain == 0) + return; + + BIO_snprintf(*buf, *remain, "%d", val); + if (*remain < len) { + *buf += *remain; + *remain = 0; + } else { + *buf += len; + *remain -= len; + } +} + +size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx, + const OSSL_PROPERTY_LIST *list, char *buf, + size_t bufsize) +{ + int i; + const PROPERTY_DEFINITION *prop = NULL; + size_t needed = 0; + const char *val; + + if (list == NULL) { + if (bufsize > 0) + *buf = '\0'; + return 1; + } + if (list->n != 0) + prop = &list->properties[list->n - 1]; + for (i = 0; i < list->n; i++, prop--) { + /* Skip invalid names */ + if (prop->name_idx == 0) + continue; + + if (needed > 0) + put_char(',', &buf, &bufsize, &needed); + + if (prop->optional) + put_char('?', &buf, &bufsize, &needed); + else if (prop->oper == PROPERTY_OVERRIDE) + put_char('-', &buf, &bufsize, &needed); + + val = ossl_property_name_str(ctx, prop->name_idx); + if (val == NULL) + return 0; + put_str(val, &buf, &bufsize, &needed); + + switch (prop->oper) { + case PROPERTY_OPER_NE: + put_char('!', &buf, &bufsize, &needed); + /* fall through */ + case PROPERTY_OPER_EQ: + put_char('=', &buf, &bufsize, &needed); + /* put value */ + switch (prop->type) { + case PROPERTY_TYPE_STRING: + val = ossl_property_value_str(ctx, prop->v.str_val); + if (val == NULL) + return 0; + put_str(val, &buf, &bufsize, &needed); + break; + + case PROPERTY_TYPE_NUMBER: + put_num(prop->v.int_val, &buf, &bufsize, &needed); + break; + + default: + return 0; + } + break; + default: + /* do nothing */ + break; + } + } + + put_char('\0', &buf, &bufsize, &needed); + return needed; +} diff --git a/crypto/property/property_string.c b/crypto/property/property_string.c index 9eb55cb461..06f58496db 100644 --- a/crypto/property/property_string.c +++ b/crypto/property/property_string.c @@ -162,6 +162,45 @@ OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s, s); } +struct find_str_st { + const char *str; + OSSL_PROPERTY_IDX idx; +}; + +static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr) +{ + struct find_str_st *findstr = vfindstr; + + if (prop->idx == findstr->idx) + findstr->str = prop->s; +} + +static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx, + OSSL_PROPERTY_IDX idx) +{ + struct find_str_st findstr; + PROPERTY_STRING_DATA *propdata + = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX, + &property_string_data_method); + + if (propdata == NULL) + return NULL; + + findstr.str = NULL; + findstr.idx = idx; + + lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names + : propdata->prop_values, + find_str_fn, &findstr); + + return findstr.str; +} + +const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) +{ + return ossl_property_str(1, ctx, idx); +} + OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s, int create) { @@ -175,3 +214,8 @@ OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s, create ? &propdata->prop_value_idx : NULL, s); } + +const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx) +{ + return ossl_property_str(0, ctx, idx); +} diff --git a/include/internal/property.h b/include/internal/property.h index 58ceddbb76..85f602d1e5 100644 --- a/include/internal/property.h +++ b/include/internal/property.h @@ -64,4 +64,8 @@ __owur int ossl_method_store_flush_cache(OSSL_METHOD_STORE *store, int all); OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a, const OSSL_PROPERTY_LIST *b); +size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx, + const OSSL_PROPERTY_LIST *list, char *buf, + size_t bufsize); + #endif diff --git a/include/openssl/lhash.h.in b/include/openssl/lhash.h.in index 571dce43ea..04f6c45736 100644 --- a/include/openssl/lhash.h.in +++ b/include/openssl/lhash.h.in @@ -226,6 +226,13 @@ void OPENSSL_LH_node_usage_stats_bio(const OPENSSL_LHASH *lh, BIO *out); { \ OPENSSL_LH_doall((OPENSSL_LHASH *)lh, (OPENSSL_LH_DOALL_FUNC)doall); \ } \ + static ossl_unused ossl_inline void lh_##type##_doall_arg(LHASH_OF(type) *lh, \ + void (*doallarg)(type *, void *), \ + void *arg) \ + { \ + OPENSSL_LH_doall_arg((OPENSSL_LHASH *)lh, \ + (OPENSSL_LH_DOALL_FUNCARG)doallarg, arg); \ + } \ LHASH_OF(type) #define IMPLEMENT_LHASH_DOALL_ARG_CONST(type, argtype) \ -- cgit v1.2.3