2 * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
5 * Licensed under the Apache License 2.0 (the "License"). You may not use
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
12 #include <openssl/err.h>
13 #include <openssl/cryptoerr.h>
14 #include <openssl/params.h>
15 #include <openssl/types.h>
16 #include <openssl/safestack.h>
17 #include "internal/param_build_set.h"
20 * Special internal param type to indicate the end of an allocate OSSL_PARAM
34 * These fields are never directly addressed, but their sizes are
35 * important so that all native types can be copied here without overrun.
43 DEFINE_STACK_OF(OSSL_PARAM_BLD_DEF
)
45 struct ossl_param_bld_st
{
48 STACK_OF(OSSL_PARAM_BLD_DEF
) *params
;
51 static OSSL_PARAM_BLD_DEF
*param_push(OSSL_PARAM_BLD
*bld
, const char *key
,
52 size_t size
, size_t alloc
, int type
,
55 OSSL_PARAM_BLD_DEF
*pd
= OPENSSL_zalloc(sizeof(*pd
));
62 pd
->alloc_blocks
= ossl_param_bytes_to_blocks(alloc
);
63 if ((pd
->secure
= secure
) != 0)
64 bld
->secure_blocks
+= pd
->alloc_blocks
;
66 bld
->total_blocks
+= pd
->alloc_blocks
;
67 if (sk_OSSL_PARAM_BLD_DEF_push(bld
->params
, pd
) <= 0) {
74 static int param_push_num(OSSL_PARAM_BLD
*bld
, const char *key
,
75 void *num
, size_t size
, int type
)
77 OSSL_PARAM_BLD_DEF
*pd
= param_push(bld
, key
, size
, size
, type
, 0);
80 ERR_raise(ERR_LIB_CRYPTO
, ERR_R_PASSED_NULL_PARAMETER
);
83 if (size
> sizeof(pd
->num
)) {
84 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_TOO_MANY_BYTES
);
87 memcpy(&pd
->num
, num
, size
);
91 OSSL_PARAM_BLD
*OSSL_PARAM_BLD_new(void)
93 OSSL_PARAM_BLD
*r
= OPENSSL_zalloc(sizeof(OSSL_PARAM_BLD
));
96 r
->params
= sk_OSSL_PARAM_BLD_DEF_new_null();
97 if (r
->params
== NULL
) {
105 static void free_all_params(OSSL_PARAM_BLD
*bld
)
107 int i
, n
= sk_OSSL_PARAM_BLD_DEF_num(bld
->params
);
109 for (i
= 0; i
< n
; i
++)
110 OPENSSL_free(sk_OSSL_PARAM_BLD_DEF_pop(bld
->params
));
113 void OSSL_PARAM_BLD_free(OSSL_PARAM_BLD
*bld
)
117 free_all_params(bld
);
118 sk_OSSL_PARAM_BLD_DEF_free(bld
->params
);
122 int OSSL_PARAM_BLD_push_int(OSSL_PARAM_BLD
*bld
, const char *key
, int num
)
124 return param_push_num(bld
, key
, &num
, sizeof(num
), OSSL_PARAM_INTEGER
);
127 int OSSL_PARAM_BLD_push_uint(OSSL_PARAM_BLD
*bld
, const char *key
,
130 return param_push_num(bld
, key
, &num
, sizeof(num
),
131 OSSL_PARAM_UNSIGNED_INTEGER
);
134 int OSSL_PARAM_BLD_push_long(OSSL_PARAM_BLD
*bld
, const char *key
,
137 return param_push_num(bld
, key
, &num
, sizeof(num
), OSSL_PARAM_INTEGER
);
140 int OSSL_PARAM_BLD_push_ulong(OSSL_PARAM_BLD
*bld
, const char *key
,
141 unsigned long int num
)
143 return param_push_num(bld
, key
, &num
, sizeof(num
),
144 OSSL_PARAM_UNSIGNED_INTEGER
);
147 int OSSL_PARAM_BLD_push_int32(OSSL_PARAM_BLD
*bld
, const char *key
,
150 return param_push_num(bld
, key
, &num
, sizeof(num
), OSSL_PARAM_INTEGER
);
153 int OSSL_PARAM_BLD_push_uint32(OSSL_PARAM_BLD
*bld
, const char *key
,
156 return param_push_num(bld
, key
, &num
, sizeof(num
),
157 OSSL_PARAM_UNSIGNED_INTEGER
);
160 int OSSL_PARAM_BLD_push_int64(OSSL_PARAM_BLD
*bld
, const char *key
,
163 return param_push_num(bld
, key
, &num
, sizeof(num
), OSSL_PARAM_INTEGER
);
166 int OSSL_PARAM_BLD_push_uint64(OSSL_PARAM_BLD
*bld
, const char *key
,
169 return param_push_num(bld
, key
, &num
, sizeof(num
),
170 OSSL_PARAM_UNSIGNED_INTEGER
);
173 int OSSL_PARAM_BLD_push_size_t(OSSL_PARAM_BLD
*bld
, const char *key
,
176 return param_push_num(bld
, key
, &num
, sizeof(num
),
177 OSSL_PARAM_UNSIGNED_INTEGER
);
180 int OSSL_PARAM_BLD_push_time_t(OSSL_PARAM_BLD
*bld
, const char *key
,
183 return param_push_num(bld
, key
, &num
, sizeof(num
),
187 int OSSL_PARAM_BLD_push_double(OSSL_PARAM_BLD
*bld
, const char *key
,
190 return param_push_num(bld
, key
, &num
, sizeof(num
), OSSL_PARAM_REAL
);
193 static int push_BN(OSSL_PARAM_BLD
*bld
, const char *key
,
194 const BIGNUM
*bn
, size_t sz
, int type
)
197 OSSL_PARAM_BLD_DEF
*pd
;
199 if (!ossl_assert(type
== OSSL_PARAM_UNSIGNED_INTEGER
200 || type
== OSSL_PARAM_INTEGER
))
204 if (type
== OSSL_PARAM_UNSIGNED_INTEGER
&& BN_is_negative(bn
)) {
205 ERR_raise_data(ERR_LIB_CRYPTO
, ERR_R_UNSUPPORTED
,
206 "Negative big numbers are unsupported for OSSL_PARAM_UNSIGNED_INTEGER");
210 n
= BN_num_bytes(bn
);
212 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_ZERO_LENGTH_NUMBER
);
215 if (sz
< (size_t)n
) {
216 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_TOO_SMALL_BUFFER
);
219 if (BN_get_flags(bn
, BN_FLG_SECURE
) == BN_FLG_SECURE
)
222 /* The BIGNUM is zero, we must transfer at least one byte */
226 pd
= param_push(bld
, key
, sz
, sz
, type
, secure
);
233 int OSSL_PARAM_BLD_push_BN(OSSL_PARAM_BLD
*bld
, const char *key
,
236 if (bn
!= NULL
&& BN_is_negative(bn
))
237 return push_BN(bld
, key
, bn
, BN_num_bytes(bn
) + 1,
239 return push_BN(bld
, key
, bn
, bn
== NULL
? 0 : BN_num_bytes(bn
),
240 OSSL_PARAM_UNSIGNED_INTEGER
);
243 int OSSL_PARAM_BLD_push_BN_pad(OSSL_PARAM_BLD
*bld
, const char *key
,
244 const BIGNUM
*bn
, size_t sz
)
246 if (bn
!= NULL
&& BN_is_negative(bn
))
247 return push_BN(bld
, key
, bn
, BN_num_bytes(bn
),
249 return push_BN(bld
, key
, bn
, sz
, OSSL_PARAM_UNSIGNED_INTEGER
);
252 int OSSL_PARAM_BLD_push_utf8_string(OSSL_PARAM_BLD
*bld
, const char *key
,
253 const char *buf
, size_t bsize
)
255 OSSL_PARAM_BLD_DEF
*pd
;
260 secure
= CRYPTO_secure_allocated(buf
);
261 pd
= param_push(bld
, key
, bsize
, bsize
+ 1, OSSL_PARAM_UTF8_STRING
, secure
);
268 int OSSL_PARAM_BLD_push_utf8_ptr(OSSL_PARAM_BLD
*bld
, const char *key
,
269 char *buf
, size_t bsize
)
271 OSSL_PARAM_BLD_DEF
*pd
;
275 pd
= param_push(bld
, key
, bsize
, sizeof(buf
), OSSL_PARAM_UTF8_PTR
, 0);
282 int OSSL_PARAM_BLD_push_octet_string(OSSL_PARAM_BLD
*bld
, const char *key
,
283 const void *buf
, size_t bsize
)
285 OSSL_PARAM_BLD_DEF
*pd
;
288 secure
= CRYPTO_secure_allocated(buf
);
289 pd
= param_push(bld
, key
, bsize
, bsize
, OSSL_PARAM_OCTET_STRING
, secure
);
296 int OSSL_PARAM_BLD_push_octet_ptr(OSSL_PARAM_BLD
*bld
, const char *key
,
297 void *buf
, size_t bsize
)
299 OSSL_PARAM_BLD_DEF
*pd
;
301 pd
= param_push(bld
, key
, bsize
, sizeof(buf
), OSSL_PARAM_OCTET_PTR
, 0);
308 static OSSL_PARAM
*param_bld_convert(OSSL_PARAM_BLD
*bld
, OSSL_PARAM
*param
,
309 OSSL_PARAM_ALIGNED_BLOCK
*blk
,
310 OSSL_PARAM_ALIGNED_BLOCK
*secure
)
312 int i
, num
= sk_OSSL_PARAM_BLD_DEF_num(bld
->params
);
313 OSSL_PARAM_BLD_DEF
*pd
;
316 for (i
= 0; i
< num
; i
++) {
317 pd
= sk_OSSL_PARAM_BLD_DEF_value(bld
->params
, i
);
318 param
[i
].key
= pd
->key
;
319 param
[i
].data_type
= pd
->type
;
320 param
[i
].data_size
= pd
->size
;
321 param
[i
].return_size
= OSSL_PARAM_UNMODIFIED
;
325 secure
+= pd
->alloc_blocks
;
328 blk
+= pd
->alloc_blocks
;
331 if (pd
->bn
!= NULL
) {
333 if (pd
->type
== OSSL_PARAM_UNSIGNED_INTEGER
)
334 BN_bn2nativepad(pd
->bn
, (unsigned char *)p
, pd
->size
);
336 BN_signed_bn2native(pd
->bn
, (unsigned char *)p
, pd
->size
);
337 } else if (pd
->type
== OSSL_PARAM_OCTET_PTR
338 || pd
->type
== OSSL_PARAM_UTF8_PTR
) {
340 *(const void **)p
= pd
->string
;
341 } else if (pd
->type
== OSSL_PARAM_OCTET_STRING
342 || pd
->type
== OSSL_PARAM_UTF8_STRING
) {
343 if (pd
->string
!= NULL
)
344 memcpy(p
, pd
->string
, pd
->size
);
346 memset(p
, 0, pd
->size
);
347 if (pd
->type
== OSSL_PARAM_UTF8_STRING
)
348 ((char *)p
)[pd
->size
] = '\0';
350 /* Number, but could also be a NULL BIGNUM */
351 if (pd
->size
> sizeof(pd
->num
))
352 memset(p
, 0, pd
->size
);
353 else if (pd
->size
> 0)
354 memcpy(p
, &pd
->num
, pd
->size
);
357 param
[i
] = OSSL_PARAM_construct_end();
361 OSSL_PARAM
*OSSL_PARAM_BLD_to_param(OSSL_PARAM_BLD
*bld
)
363 OSSL_PARAM_ALIGNED_BLOCK
*blk
, *s
= NULL
;
364 OSSL_PARAM
*params
, *last
;
365 const int num
= sk_OSSL_PARAM_BLD_DEF_num(bld
->params
);
366 const size_t p_blks
= ossl_param_bytes_to_blocks((1 + num
) * sizeof(*params
));
367 const size_t total
= OSSL_PARAM_ALIGN_SIZE
* (p_blks
+ bld
->total_blocks
);
368 const size_t ss
= OSSL_PARAM_ALIGN_SIZE
* bld
->secure_blocks
;
371 s
= OPENSSL_secure_malloc(ss
);
373 ERR_raise(ERR_LIB_CRYPTO
, CRYPTO_R_SECURE_MALLOC_FAILURE
);
377 params
= OPENSSL_malloc(total
);
378 if (params
== NULL
) {
379 OPENSSL_secure_free(s
);
382 blk
= p_blks
+ (OSSL_PARAM_ALIGNED_BLOCK
*)(params
);
383 last
= param_bld_convert(bld
, params
, blk
, s
);
384 ossl_param_set_secure_block(last
, s
, ss
);
386 /* Reset builder for reuse */
387 bld
->total_blocks
= 0;
388 bld
->secure_blocks
= 0;
389 free_all_params(bld
);