]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
params: add helper functions to allocate & copy params
authorPauli <pauli@openssl.org>
Thu, 13 Apr 2023 02:10:50 +0000 (12:10 +1000)
committerPauli <pauli@openssl.org>
Tue, 25 Apr 2023 22:01:46 +0000 (08:01 +1000)
Added a function to allocate a buffer and copy a maching param.
Added a function to allocate a buffer and concatenate all matching params.

Fixes #20717

Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20724)

crypto/params.c
include/internal/params.h [new file with mode: 0644]

index f75cfe69cfdc89ae2ddf54038a92ec3444381859..d288c1d38bf1e8c7c703db9065a683af5bf59aae 100644 (file)
@@ -14,6 +14,8 @@
 #include "internal/thread_once.h"
 #include "internal/numbers.h"
 #include "internal/endian.h"
+#include "internal/params.h"
+#include "internal/packet.h"
 
 /* Shortcuts for raising errors that are widely used */
 #define err_unsigned_negative \
@@ -1481,6 +1483,111 @@ OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
     return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize);
 }
 
+/*
+ * Extract the parameter into an allocated buffer.
+ * Any existing allocation in *out is cleared and freed.
+ *
+ * Returns 1 on success, 0 on failure and -1 if there are no matching params.
+ *
+ * *out and *out_len are guaranteed to be untouched if this function
+ * doesn't return success.
+ */
+int ossl_param_get1_octet_string(const OSSL_PARAM *params, const char *name,
+                                 unsigned char **out, size_t *out_len)
+{
+    const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
+    void *buf = NULL;
+    size_t len = 0;
+
+    if (p == NULL)
+        return -1;
+
+    if (p->data != NULL
+            && p->data_size > 0
+            && !OSSL_PARAM_get_octet_string(p, &buf, 0, &len))
+        return 0;
+
+    OPENSSL_clear_free(*out, *out_len);
+    *out = buf;
+    *out_len = len;
+    return 1;
+}
+
+static int setbuf_fromparams(const OSSL_PARAM *p, const char *name,
+                             unsigned char *out, size_t *outlen)
+{
+    int ret = 0;
+    WPACKET pkt;
+
+    if (out == NULL) {
+        if (!WPACKET_init_null(&pkt, 0))
+            return 0;
+    } else {
+        if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
+            return 0;
+    }
+
+    for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, name)) {
+        if (p->data_type != OSSL_PARAM_OCTET_STRING)
+            goto err;
+        if (p->data != NULL
+                && p->data_size != 0
+                && !WPACKET_memcpy(&pkt, p->data, p->data_size))
+            goto err;
+    }
+    if (!WPACKET_get_total_written(&pkt, outlen)
+            || !WPACKET_finish(&pkt))
+        goto err;
+    ret = 1;
+err:
+    WPACKET_cleanup(&pkt);
+    return ret;
+}
+
+int ossl_param_get1_concat_octet_string(const OSSL_PARAM *params, const char *name,
+                                        unsigned char **out,
+                                        size_t *out_len, size_t maxsize)
+{
+    const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
+    unsigned char *res;
+    size_t sz = 0;
+
+    if (p == NULL)
+        return -1;
+
+    /* Calculate the total size */
+    if (!setbuf_fromparams(p, name, NULL, &sz))
+        return 0;
+
+    /* Check that it's not oversized */
+    if (maxsize > 0 && sz > maxsize)
+        return 0;
+
+    /* Special case zero length */
+    if (sz == 0) {
+        if ((res = OPENSSL_zalloc(1)) == NULL)
+            return 0;
+        goto fin;
+    }
+
+    /* Allocate the buffer */
+    res = OPENSSL_malloc(sz);
+    if (res == NULL)
+        return 0;
+
+    /* Concat one or more OSSL_KDF_PARAM_INFO fields */
+    if (!setbuf_fromparams(p, name, res, &sz)) {
+        OPENSSL_clear_free(res, sz);
+        return 0;
+    }
+
+ fin:
+    OPENSSL_clear_free(*out, *out_len);
+    *out = res;
+    *out_len = sz;
+    return 1;
+}
+
 OSSL_PARAM OSSL_PARAM_construct_end(void)
 {
     OSSL_PARAM end = OSSL_PARAM_END;
diff --git a/include/internal/params.h b/include/internal/params.h
new file mode 100644 (file)
index 0000000..3fbd0cf
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 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 <stddef.h>
+#include <openssl/params.h>
+
+/*
+ * Extract the parameter into an allocated buffer.
+ * Any existing allocation in *out is cleared and freed.
+ *
+ * Returns 1 on success, 0 on failure and -1  if there are no matching params.
+ *
+ * *out and *out_len are guaranteed to be untouched if this function
+ * doesn't return success.
+ */
+int ossl_param_get1_octet_string(const OSSL_PARAM *params, const char *name,
+                                 unsigned char **out, size_t *out_len);
+/*
+ * Concatenate all of the matching params together.
+ * *out will point to an allocated buffer on successful return.
+ * Any existing allocation in *out is cleared and freed.
+ *
+ * Passing 0 for maxsize means unlimited size output.
+ *
+ * Returns 1 on success, 0 on failure and -1 if there are no matching params.
+ *
+ * *out and *out_len are guaranteed to be untouched if this function
+ * doesn't return success.
+ */
+int ossl_param_get1_concat_octet_string(const OSSL_PARAM *params, const char *name,
+                                        unsigned char **out, size_t *out_len,
+                                        size_t maxsize);