2 * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 #include <openssl/params.h>
12 #include <openssl/param_build.h>
13 #include "internal/param_build_set.h"
14 #include "e_os.h" /* strcasecmp */
16 #define OSSL_PARAM_ALLOCATED_END 127
17 #define OSSL_PARAM_MERGE_LIST_MAX 128
19 #define OSSL_PARAM_BUF_PUBLIC 0
20 #define OSSL_PARAM_BUF_SECURE 1
21 #define OSSL_PARAM_BUF_MAX (OSSL_PARAM_BUF_SECURE + 1)
24 OSSL_PARAM_ALIGNED_BLOCK
*alloc
; /* The allocated buffer */
25 OSSL_PARAM_ALIGNED_BLOCK
*cur
; /* Current position in the allocated buf */
26 size_t blocks
; /* Number of aligned blocks */
27 size_t alloc_sz
; /* The size of the allocated buffer (in bytes) */
30 size_t ossl_param_bytes_to_blocks(size_t bytes
)
32 return (bytes
+ OSSL_PARAM_ALIGN_SIZE
- 1) / OSSL_PARAM_ALIGN_SIZE
;
35 static int ossl_param_buf_alloc(OSSL_PARAM_BUF
*out
, size_t extra_blocks
,
38 size_t sz
= OSSL_PARAM_ALIGN_SIZE
* (extra_blocks
+ out
->blocks
);
40 out
->alloc
= is_secure
? OPENSSL_secure_zalloc(sz
) : OPENSSL_zalloc(sz
);
41 if (out
->alloc
== NULL
) {
42 ERR_raise(ERR_LIB_CRYPTO
, is_secure
? CRYPTO_R_SECURE_MALLOC_FAILURE
43 : ERR_R_MALLOC_FAILURE
);
47 out
->cur
= out
->alloc
+ extra_blocks
;
51 void ossl_param_set_secure_block(OSSL_PARAM
*last
, void *secure_buffer
,
52 size_t secure_buffer_sz
)
55 last
->data_size
= secure_buffer_sz
;
56 last
->data
= secure_buffer
;
57 last
->data_type
= OSSL_PARAM_ALLOCATED_END
;
60 static OSSL_PARAM
*ossl_param_dup(const OSSL_PARAM
*src
, OSSL_PARAM
*dst
,
61 OSSL_PARAM_BUF buf
[OSSL_PARAM_BUF_MAX
],
65 int has_dst
= (dst
!= NULL
);
67 size_t param_sz
, blks
;
69 for (in
= src
; in
->key
!= NULL
; in
++) {
70 is_secure
= CRYPTO_secure_allocated(in
->data
);
73 dst
->data
= buf
[is_secure
].cur
;
76 if (in
->data_type
== OSSL_PARAM_OCTET_PTR
77 || in
->data_type
== OSSL_PARAM_UTF8_PTR
) {
78 param_sz
= sizeof(in
->data
);
80 *((const void **)dst
->data
) = *(const void **)in
->data
;
82 param_sz
= in
->data_size
;
84 memcpy(dst
->data
, in
->data
, param_sz
);
86 if (in
->data_type
== OSSL_PARAM_UTF8_STRING
)
87 param_sz
++; /* NULL terminator */
88 blks
= ossl_param_bytes_to_blocks(param_sz
);
92 buf
[is_secure
].cur
+= blks
;
94 buf
[is_secure
].blocks
+= blks
;
96 if (param_count
!= NULL
)
102 OSSL_PARAM
*OSSL_PARAM_dup(const OSSL_PARAM
*src
)
105 OSSL_PARAM_BUF buf
[OSSL_PARAM_BUF_MAX
];
106 OSSL_PARAM
*last
, *dst
;
107 int param_count
= 1; /* Include terminator in the count */
110 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
114 memset(buf
, 0, sizeof(buf
));
116 /* First Pass: get the param_count and block sizes required */
117 (void)ossl_param_dup(src
, NULL
, buf
, ¶m_count
);
119 param_blocks
= ossl_param_bytes_to_blocks(param_count
* sizeof(*src
));
121 * The allocated buffer consists of an array of OSSL_PARAM followed by
122 * aligned data bytes that the array elements will point to.
124 if (!ossl_param_buf_alloc(&buf
[OSSL_PARAM_BUF_PUBLIC
], param_blocks
, 0))
127 /* Allocate a secure memory buffer if required */
128 if (buf
[OSSL_PARAM_BUF_SECURE
].blocks
> 0
129 && !ossl_param_buf_alloc(&buf
[OSSL_PARAM_BUF_SECURE
], 0, 1)) {
130 OPENSSL_free(buf
[OSSL_PARAM_BUF_PUBLIC
].alloc
);
134 dst
= (OSSL_PARAM
*)buf
[OSSL_PARAM_BUF_PUBLIC
].alloc
;
135 last
= ossl_param_dup(src
, dst
, buf
, NULL
);
136 /* Store the allocated secure memory buffer in the last param block */
137 ossl_param_set_secure_block(last
, buf
[OSSL_PARAM_BUF_SECURE
].alloc
,
138 buf
[OSSL_PARAM_BUF_SECURE
].alloc_sz
);
142 static int compare_params(const void *left
, const void *right
)
144 const OSSL_PARAM
*l
= *(const OSSL_PARAM
**)left
;
145 const OSSL_PARAM
*r
= *(const OSSL_PARAM
**)right
;
147 return strcasecmp(l
->key
, r
->key
);
150 OSSL_PARAM
*OSSL_PARAM_merge(const OSSL_PARAM
*p1
, const OSSL_PARAM
*p2
)
152 const OSSL_PARAM
*list1
[OSSL_PARAM_MERGE_LIST_MAX
+ 1];
153 const OSSL_PARAM
*list2
[OSSL_PARAM_MERGE_LIST_MAX
+ 1];
154 const OSSL_PARAM
*p
= NULL
;
155 const OSSL_PARAM
**p1cur
, **p2cur
;
156 OSSL_PARAM
*params
, *dst
;
157 size_t list1_sz
= 0, list2_sz
= 0;
160 if (p1
== NULL
&& p2
== NULL
) {
161 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
165 /* Copy p1 to list1 */
167 for (p
= p1
; p
->key
!= NULL
&& list1_sz
< OSSL_PARAM_MERGE_LIST_MAX
; p
++)
168 list1
[list1_sz
++] = p
;
170 list1
[list1_sz
] = NULL
;
172 /* copy p2 to a list2 */
174 for (p
= p2
; p
->key
!= NULL
&& list2_sz
< OSSL_PARAM_MERGE_LIST_MAX
; p
++)
175 list2
[list2_sz
++] = p
;
177 list2
[list2_sz
] = NULL
;
178 if (list1_sz
== 0 && list2_sz
== 0) {
179 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_NO_PARAMS_TO_MERGE
);
183 /* Sort the 2 lists */
184 qsort(list1
, list1_sz
, sizeof(OSSL_PARAM
*), compare_params
);
185 qsort(list2
, list2_sz
, sizeof(OSSL_PARAM
*), compare_params
);
187 /* Allocate enough space to store the merged parameters */
188 params
= OPENSSL_zalloc((list1_sz
+ list2_sz
+ 1) * sizeof(*p1
));
189 if (params
== NULL
) {
190 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_MALLOC_FAILURE
);
197 /* If list1 is finished just tack list2 onto the end */
198 if (*p1cur
== NULL
) {
202 } while (*p2cur
!= NULL
);
205 /* If list2 is finished just tack list1 onto the end */
206 if (*p2cur
== NULL
) {
210 } while (*p1cur
!= NULL
);
213 /* consume the list element with the smaller key */
214 diff
= strcasecmp((*p1cur
)->key
, (*p2cur
)->key
);
216 /* If the keys are the same then throw away the list1 element */
220 } else if (diff
> 0) {
231 void OSSL_PARAM_free(OSSL_PARAM
*params
)
233 if (params
!= NULL
) {
236 for (p
= params
; p
->key
!= NULL
; p
++)
238 if (p
->data_type
== OSSL_PARAM_ALLOCATED_END
)
239 OPENSSL_secure_clear_free(p
->data
, p
->data_size
);
240 OPENSSL_free(params
);