Implement the ability to convert a PROPERTY_LIST to a string
authorMatt Caswell <matt@openssl.org>
Fri, 7 May 2021 15:42:53 +0000 (16:42 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 20 May 2021 08:28:38 +0000 (09:28 +0100)
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 <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15242)

crypto/evp/evp_fetch.c
crypto/property/property_local.h
crypto/property/property_parse.c
crypto/property/property_string.c
include/internal/property.h
include/openssl/lhash.h.in

index 6c701bf1e2bbaa27aed761398cadd8f50eebe289..fdb6d90f4dfdc8eab7d0d7206d27de53dd2cc5af 100644 (file)
@@ -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,
index c744a5d3c37e1f828444680b7035b0ee25e39d87..8cc3a5127035190401f28a4cdc50a40887c1e7bc 100644 (file)
@@ -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);
index dfae76518f1b35d0e0445a10718f1606c892661b..aab8cbe8a408e11b1e38013be23fdd0628a60a5f 100644 (file)
@@ -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;
+}
index 9eb55cb4616a3c1e6feec3181ba047af7698e6cc..06f58496db13ada105a2e8af7cf38646e50b6822 100644 (file)
@@ -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);
+}
index 58ceddbb76637db85dc6c6d48281d19a1ab399c3..85f602d1e5c1aed74aca5ce30e52c4660ba8d521 100644 (file)
@@ -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
index 571dce43ea7b92c2d4c33897bbe434c79b26a558..04f6c45736719a8d502278ce69b32278cbee8c3d 100644 (file)
@@ -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) \