]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/params.c
params: add helper functions to allocate & copy params
[thirdparty/openssl.git] / crypto / params.c
CommitLineData
7ffbd7ca 1/*
fecb3aae 2 * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
7ffbd7ca
P
3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
4 *
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
9 */
10
11#include <string.h>
12#include <openssl/params.h>
ac1082f0 13#include <openssl/err.h>
7ffbd7ca 14#include "internal/thread_once.h"
c04a9916 15#include "internal/numbers.h"
e9c5e642 16#include "internal/endian.h"
79523d55
P
17#include "internal/params.h"
18#include "internal/packet.h"
7ffbd7ca 19
ac1082f0
P
20/* Shortcuts for raising errors that are widely used */
21#define err_unsigned_negative \
22 ERR_raise(ERR_LIB_CRYPTO, \
23 CRYPTO_R_PARAM_UNSIGNED_INTEGER_NEGATIVE_VALUE_UNSUPPORTED)
24#define err_out_of_range \
25 ERR_raise(ERR_LIB_CRYPTO, \
26 CRYPTO_R_PARAM_VALUE_TOO_LARGE_FOR_DESTINATION)
27#define err_inexact \
28 ERR_raise(ERR_LIB_CRYPTO, \
29 CRYPTO_R_PARAM_CANNOT_BE_REPRESENTED_EXACTLY)
30#define err_not_integer \
31 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_NOT_INTEGER_TYPE)
32#define err_too_small \
33 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_TOO_SMALL_BUFFER)
34#define err_bad_type \
35 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_OF_INCOMPATIBLE_TYPE)
36#define err_null_argument \
37 ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER)
38#define err_unsupported_real \
39 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_PARAM_UNSUPPORTED_FLOATING_POINT_FORMAT)
40
5b1d94c1
P
41/*
42 * Return the number of bits in the mantissa of a double. This is used to
43 * shift a larger integral value to determine if it will exactly fit into a
44 * double.
45 */
46static unsigned int real_shift(void)
47{
48 return sizeof(double) == 4 ? 24 : 53;
49}
50
4e7991b4 51OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key)
7ffbd7ca
P
52{
53 if (p != NULL && key != NULL)
54 for (; p->key != NULL; p++)
55 if (strcmp(key, p->key) == 0)
56 return p;
57 return NULL;
58}
59
4e7991b4
P
60const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key)
61{
62 return OSSL_PARAM_locate((OSSL_PARAM *)p, key);
63}
64
7ffbd7ca 65static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
4e7991b4 66 void *data, size_t data_size)
7ffbd7ca
P
67{
68 OSSL_PARAM res;
69
70 res.key = key;
71 res.data_type = data_type;
72 res.data = data;
73 res.data_size = data_size;
8d5fb648 74 res.return_size = OSSL_PARAM_UNMODIFIED;
7ffbd7ca
P
75 return res;
76}
77
8d5fb648
P
78int OSSL_PARAM_modified(const OSSL_PARAM *p)
79{
80 return p != NULL && p->return_size != OSSL_PARAM_UNMODIFIED;
81}
82
3873887e 83void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p)
8d5fb648
P
84{
85 if (p != NULL)
3873887e
P
86 while (p->key != NULL)
87 p++->return_size = OSSL_PARAM_UNMODIFIED;
8d5fb648
P
88}
89
e9c5e642
P
90/* Return non-zero if the signed number is negative */
91static int is_negative(const void *number, size_t s)
92{
93 const unsigned char *n = number;
94 DECLARE_IS_ENDIAN;
95
96 return 0x80 & (IS_BIG_ENDIAN ? n[0] : n[s - 1]);
97}
98
99/* Check that all the bytes specified match the expected sign byte */
100static int check_sign_bytes(const unsigned char *p, size_t n, unsigned char s)
101{
102 size_t i;
103
104 for (i = 0; i < n; i++)
105 if (p[i] != s)
106 return 0;
107 return 1;
108}
109
110/*
111 * Copy an integer to another integer.
112 * Handle different length integers and signed and unsigned integers.
113 * Both integers are in native byte ordering.
114 */
115static int copy_integer(unsigned char *dest, size_t dest_len,
116 const unsigned char *src, size_t src_len,
117 unsigned char pad, int signed_int)
118{
119 size_t n;
120 DECLARE_IS_ENDIAN;
121
122 if (IS_BIG_ENDIAN) {
123 if (src_len < dest_len) {
124 n = dest_len - src_len;
125 memset(dest, pad, n);
126 memcpy(dest + n, src, src_len);
127 } else {
128 n = src_len - dest_len;
129 if (!check_sign_bytes(src, n, pad)
130 /*
131 * Shortening a signed value must retain the correct sign.
132 * Avoiding this kind of thing: -253 = 0xff03 -> 0x03 = 3
133 */
ac1082f0
P
134 || (signed_int && ((pad ^ src[n]) & 0x80) != 0)) {
135 err_out_of_range;
e9c5e642 136 return 0;
ac1082f0 137 }
e9c5e642
P
138 memcpy(dest, src + n, dest_len);
139 }
140 } else /* IS_LITTLE_ENDIAN */ {
141 if (src_len < dest_len) {
142 n = dest_len - src_len;
143 memset(dest + src_len, pad, n);
144 memcpy(dest, src, src_len);
145 } else {
146 n = src_len - dest_len;
147 if (!check_sign_bytes(src + dest_len, n, pad)
148 /*
149 * Shortening a signed value must retain the correct sign.
150 * Avoiding this kind of thing: 130 = 0x0082 -> 0x82 = -126
151 */
ac1082f0
P
152 || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0)) {
153 err_out_of_range;
e9c5e642 154 return 0;
ac1082f0 155 }
e9c5e642
P
156 memcpy(dest, src, dest_len);
157 }
158 }
159 return 1;
160}
161
162/* Copy a signed number to a signed number of possibly different length */
163static int signed_from_signed(void *dest, size_t dest_len,
164 const void *src, size_t src_len)
165{
166 return copy_integer(dest, dest_len, src, src_len,
167 is_negative(src, src_len) ? 0xff : 0, 1);
168}
169
170/* Copy an unsigned number to a signed number of possibly different length */
171static int signed_from_unsigned(void *dest, size_t dest_len,
172 const void *src, size_t src_len)
173{
174 return copy_integer(dest, dest_len, src, src_len, 0, 1);
175}
176
177/* Copy a signed number to an unsigned number of possibly different length */
178static int unsigned_from_signed(void *dest, size_t dest_len,
179 const void *src, size_t src_len)
180{
ac1082f0
P
181 if (is_negative(src, src_len)) {
182 err_unsigned_negative;
e9c5e642 183 return 0;
ac1082f0 184 }
e9c5e642
P
185 return copy_integer(dest, dest_len, src, src_len, 0, 0);
186}
187
188/* Copy an unsigned number to an unsigned number of possibly different length */
189static int unsigned_from_unsigned(void *dest, size_t dest_len,
190 const void *src, size_t src_len)
191{
192 return copy_integer(dest, dest_len, src, src_len, 0, 0);
193}
194
195/* General purpose get integer parameter call that handles odd sizes */
196static int general_get_int(const OSSL_PARAM *p, void *val, size_t val_size)
197{
198 if (p->data_type == OSSL_PARAM_INTEGER)
199 return signed_from_signed(val, val_size, p->data, p->data_size);
200 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
201 return signed_from_unsigned(val, val_size, p->data, p->data_size);
ac1082f0 202 err_not_integer;
e9c5e642
P
203 return 0;
204}
205
206/* General purpose set integer parameter call that handles odd sizes */
207static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size)
208{
209 int r = 0;
210
211 p->return_size = val_size; /* Expected size */
212 if (p->data == NULL)
213 return 1;
214 if (p->data_type == OSSL_PARAM_INTEGER)
215 r = signed_from_signed(p->data, p->data_size, val, val_size);
216 else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
217 r = unsigned_from_signed(p->data, p->data_size, val, val_size);
ac1082f0
P
218 else
219 err_not_integer;
e9c5e642
P
220 p->return_size = r ? p->data_size : val_size;
221 return r;
222}
223
224/* General purpose get unsigned integer parameter call that handles odd sizes */
225static int general_get_uint(const OSSL_PARAM *p, void *val, size_t val_size)
226{
227 if (p->data_type == OSSL_PARAM_INTEGER)
228 return unsigned_from_signed(val, val_size, p->data, p->data_size);
229 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
230 return unsigned_from_unsigned(val, val_size, p->data, p->data_size);
ac1082f0 231 err_not_integer;
e9c5e642
P
232 return 0;
233}
234
235/* General purpose set unsigned integer parameter call that handles odd sizes */
236static int general_set_uint(OSSL_PARAM *p, void *val, size_t val_size)
237{
238 int r = 0;
239
240 p->return_size = val_size; /* Expected size */
241 if (p->data == NULL)
242 return 1;
243 if (p->data_type == OSSL_PARAM_INTEGER)
244 r = signed_from_unsigned(p->data, p->data_size, val, val_size);
245 else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
246 r = unsigned_from_unsigned(p->data, p->data_size, val, val_size);
ac1082f0
P
247 else
248 err_not_integer;
e9c5e642
P
249 p->return_size = r ? p->data_size : val_size;
250 return r;
251}
252
7ffbd7ca
P
253int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
254{
e9c5e642 255#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 256 switch (sizeof(int)) {
7ffbd7ca 257 case sizeof(int32_t):
863360fb 258 return OSSL_PARAM_get_int32(p, (int32_t *)val);
7ffbd7ca 259 case sizeof(int64_t):
863360fb 260 return OSSL_PARAM_get_int64(p, (int64_t *)val);
7ffbd7ca 261 }
e9c5e642
P
262#endif
263 return general_get_int(p, val, sizeof(*val));
7ffbd7ca
P
264}
265
4e7991b4 266int OSSL_PARAM_set_int(OSSL_PARAM *p, int val)
7ffbd7ca 267{
e9c5e642 268#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 269 switch (sizeof(int)) {
7ffbd7ca 270 case sizeof(int32_t):
863360fb 271 return OSSL_PARAM_set_int32(p, (int32_t)val);
7ffbd7ca 272 case sizeof(int64_t):
863360fb 273 return OSSL_PARAM_set_int64(p, (int64_t)val);
7ffbd7ca 274 }
e9c5e642
P
275#endif
276 return general_set_int(p, &val, sizeof(val));
7ffbd7ca
P
277}
278
4e7991b4 279OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf)
7ffbd7ca 280{
4e7991b4 281 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int));
7ffbd7ca
P
282}
283
284int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
285{
e9c5e642 286#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 287 switch (sizeof(unsigned int)) {
7ffbd7ca 288 case sizeof(uint32_t):
863360fb 289 return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
7ffbd7ca 290 case sizeof(uint64_t):
863360fb 291 return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
7ffbd7ca 292 }
e9c5e642
P
293#endif
294 return general_get_uint(p, val, sizeof(*val));
7ffbd7ca
P
295}
296
4e7991b4 297int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val)
7ffbd7ca 298{
e9c5e642 299#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 300 switch (sizeof(unsigned int)) {
7ffbd7ca 301 case sizeof(uint32_t):
863360fb 302 return OSSL_PARAM_set_uint32(p, (uint32_t)val);
7ffbd7ca 303 case sizeof(uint64_t):
863360fb 304 return OSSL_PARAM_set_uint64(p, (uint64_t)val);
7ffbd7ca 305 }
e9c5e642
P
306#endif
307 return general_set_uint(p, &val, sizeof(val));
7ffbd7ca
P
308}
309
4e7991b4 310OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf)
7ffbd7ca
P
311{
312 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
4e7991b4 313 sizeof(unsigned int));
7ffbd7ca
P
314}
315
316int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
317{
e9c5e642 318#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 319 switch (sizeof(long int)) {
7ffbd7ca 320 case sizeof(int32_t):
863360fb 321 return OSSL_PARAM_get_int32(p, (int32_t *)val);
7ffbd7ca 322 case sizeof(int64_t):
863360fb 323 return OSSL_PARAM_get_int64(p, (int64_t *)val);
7ffbd7ca 324 }
e9c5e642
P
325#endif
326 return general_get_int(p, val, sizeof(*val));
7ffbd7ca
P
327}
328
4e7991b4 329int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val)
7ffbd7ca 330{
e9c5e642 331#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 332 switch (sizeof(long int)) {
7ffbd7ca 333 case sizeof(int32_t):
863360fb 334 return OSSL_PARAM_set_int32(p, (int32_t)val);
7ffbd7ca 335 case sizeof(int64_t):
863360fb 336 return OSSL_PARAM_set_int64(p, (int64_t)val);
7ffbd7ca 337 }
e9c5e642
P
338#endif
339 return general_set_int(p, &val, sizeof(val));
7ffbd7ca
P
340}
341
4e7991b4 342OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf)
7ffbd7ca 343{
4e7991b4 344 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int));
7ffbd7ca
P
345}
346
347int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
348{
e9c5e642 349#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 350 switch (sizeof(unsigned long int)) {
7ffbd7ca 351 case sizeof(uint32_t):
863360fb 352 return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
7ffbd7ca 353 case sizeof(uint64_t):
863360fb 354 return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
7ffbd7ca 355 }
e9c5e642
P
356#endif
357 return general_get_uint(p, val, sizeof(*val));
7ffbd7ca
P
358}
359
4e7991b4 360int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val)
7ffbd7ca 361{
e9c5e642 362#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 363 switch (sizeof(unsigned long int)) {
7ffbd7ca 364 case sizeof(uint32_t):
863360fb 365 return OSSL_PARAM_set_uint32(p, (uint32_t)val);
7ffbd7ca 366 case sizeof(uint64_t):
863360fb 367 return OSSL_PARAM_set_uint64(p, (uint64_t)val);
7ffbd7ca 368 }
e9c5e642
P
369#endif
370 return general_set_uint(p, &val, sizeof(val));
7ffbd7ca
P
371}
372
4e7991b4 373OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf)
7ffbd7ca
P
374{
375 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
4e7991b4 376 sizeof(unsigned long int));
7ffbd7ca
P
377}
378
379int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
380{
9830e7ea
P
381 double d;
382
ac1082f0
P
383 if (val == NULL || p == NULL) {
384 err_null_argument;
7ffbd7ca 385 return 0;
ac1082f0 386 }
7ffbd7ca 387
9830e7ea 388 if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642
P
389#ifndef OPENSSL_SMALL_FOOTPRINT
390 int64_t i64;
391
9830e7ea
P
392 switch (p->data_size) {
393 case sizeof(int32_t):
394 *val = *(const int32_t *)p->data;
395 return 1;
396 case sizeof(int64_t):
397 i64 = *(const int64_t *)p->data;
398 if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
399 *val = (int32_t)i64;
400 return 1;
401 }
ac1082f0 402 err_out_of_range;
e9c5e642 403 return 0;
9830e7ea 404 }
e9c5e642
P
405#endif
406 return general_get_int(p, val, sizeof(*val));
407
9830e7ea 408 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642
P
409#ifndef OPENSSL_SMALL_FOOTPRINT
410 uint32_t u32;
411 uint64_t u64;
412
9830e7ea
P
413 switch (p->data_size) {
414 case sizeof(uint32_t):
415 u32 = *(const uint32_t *)p->data;
416 if (u32 <= INT32_MAX) {
417 *val = (int32_t)u32;
418 return 1;
419 }
ac1082f0 420 err_out_of_range;
e9c5e642 421 return 0;
9830e7ea
P
422 case sizeof(uint64_t):
423 u64 = *(const uint64_t *)p->data;
424 if (u64 <= INT32_MAX) {
425 *val = (int32_t)u64;
426 return 1;
427 }
ac1082f0 428 err_out_of_range;
e9c5e642 429 return 0;
9830e7ea 430 }
e9c5e642
P
431#endif
432 return general_get_int(p, val, sizeof(*val));
433
9830e7ea
P
434 } else if (p->data_type == OSSL_PARAM_REAL) {
435 switch (p->data_size) {
436 case sizeof(double):
437 d = *(const double *)p->data;
438 if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) {
439 *val = (int32_t)d;
440 return 1;
441 }
ac1082f0
P
442 err_out_of_range;
443 return 0;
9830e7ea 444 }
ac1082f0
P
445 err_unsupported_real;
446 return 0;
7ffbd7ca 447 }
ac1082f0 448 err_bad_type;
7ffbd7ca
P
449 return 0;
450}
451
4e7991b4 452int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val)
7ffbd7ca 453{
ac1082f0
P
454 uint32_t u32;
455 unsigned int shift;
456
457 if (p == NULL) {
458 err_null_argument;
7ffbd7ca 459 return 0;
ac1082f0 460 }
4e7991b4 461 p->return_size = 0;
9830e7ea 462 if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642 463#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 464 p->return_size = sizeof(int32_t); /* Minimum expected size */
8f3b8fd6
RL
465 if (p->data == NULL)
466 return 1;
9830e7ea
P
467 switch (p->data_size) {
468 case sizeof(int32_t):
469 *(int32_t *)p->data = val;
470 return 1;
471 case sizeof(int64_t):
4e7991b4 472 p->return_size = sizeof(int64_t);
9830e7ea
P
473 *(int64_t *)p->data = (int64_t)val;
474 return 1;
475 }
e9c5e642
P
476#endif
477 return general_set_int(p, &val, sizeof(val));
9830e7ea 478 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
e9c5e642 479#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 480 p->return_size = sizeof(uint32_t); /* Minimum expected size */
8f3b8fd6
RL
481 if (p->data == NULL)
482 return 1;
9830e7ea
P
483 switch (p->data_size) {
484 case sizeof(uint32_t):
485 *(uint32_t *)p->data = (uint32_t)val;
486 return 1;
487 case sizeof(uint64_t):
4e7991b4 488 p->return_size = sizeof(uint64_t);
9830e7ea
P
489 *(uint64_t *)p->data = (uint64_t)val;
490 return 1;
491 }
e9c5e642
P
492#endif
493 return general_set_int(p, &val, sizeof(val));
9830e7ea 494 } else if (p->data_type == OSSL_PARAM_REAL) {
4e7991b4 495 p->return_size = sizeof(double);
8f3b8fd6
RL
496 if (p->data == NULL)
497 return 1;
9830e7ea
P
498 switch (p->data_size) {
499 case sizeof(double):
ac1082f0
P
500 shift = real_shift();
501 if (shift < 8 * sizeof(val) - 1) {
502 u32 = val < 0 ? -val : val;
503 if ((u32 >> shift) != 0) {
504 err_inexact;
505 return 0;
506 }
507 }
9830e7ea
P
508 *(double *)p->data = (double)val;
509 return 1;
510 }
ac1082f0
P
511 err_unsupported_real;
512 return 0;
7ffbd7ca 513 }
ac1082f0 514 err_bad_type;
7ffbd7ca
P
515 return 0;
516}
517
4e7991b4 518OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf)
7ffbd7ca
P
519{
520 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf,
4e7991b4 521 sizeof(int32_t));
7ffbd7ca
P
522}
523
524int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
525{
9830e7ea
P
526 double d;
527
ac1082f0
P
528 if (val == NULL || p == NULL) {
529 err_null_argument;
7ffbd7ca 530 return 0;
ac1082f0 531 }
7ffbd7ca 532
9830e7ea 533 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642
P
534#ifndef OPENSSL_SMALL_FOOTPRINT
535 uint64_t u64;
536
9830e7ea
P
537 switch (p->data_size) {
538 case sizeof(uint32_t):
539 *val = *(const uint32_t *)p->data;
540 return 1;
541 case sizeof(uint64_t):
542 u64 = *(const uint64_t *)p->data;
543 if (u64 <= UINT32_MAX) {
544 *val = (uint32_t)u64;
545 return 1;
546 }
ac1082f0 547 err_out_of_range;
e9c5e642 548 return 0;
9830e7ea 549 }
e9c5e642
P
550#endif
551 return general_get_uint(p, val, sizeof(*val));
9830e7ea 552 } else if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642
P
553#ifndef OPENSSL_SMALL_FOOTPRINT
554 int32_t i32;
555 int64_t i64;
556
9830e7ea
P
557 switch (p->data_size) {
558 case sizeof(int32_t):
559 i32 = *(const int32_t *)p->data;
560 if (i32 >= 0) {
561 *val = i32;
562 return 1;
563 }
ac1082f0 564 err_unsigned_negative;
e9c5e642 565 return 0;
9830e7ea
P
566 case sizeof(int64_t):
567 i64 = *(const int64_t *)p->data;
568 if (i64 >= 0 && i64 <= UINT32_MAX) {
569 *val = (uint32_t)i64;
570 return 1;
571 }
ac1082f0
P
572 if (i64 < 0)
573 err_unsigned_negative;
574 else
575 err_out_of_range;
e9c5e642 576 return 0;
9830e7ea 577 }
e9c5e642
P
578#endif
579 return general_get_uint(p, val, sizeof(*val));
9830e7ea
P
580 } else if (p->data_type == OSSL_PARAM_REAL) {
581 switch (p->data_size) {
582 case sizeof(double):
583 d = *(const double *)p->data;
584 if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) {
585 *val = (uint32_t)d;
586 return 1;
587 }
ac1082f0
P
588 err_inexact;
589 return 0;
9830e7ea 590 }
ac1082f0
P
591 err_unsupported_real;
592 return 0;
7ffbd7ca 593 }
ac1082f0 594 err_bad_type;
7ffbd7ca
P
595 return 0;
596}
597
4e7991b4 598int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val)
7ffbd7ca 599{
ac1082f0
P
600 unsigned int shift;
601
602 if (p == NULL) {
603 err_null_argument;
7ffbd7ca 604 return 0;
ac1082f0 605 }
4e7991b4 606 p->return_size = 0;
7ffbd7ca 607
9830e7ea 608 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642 609#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 610 p->return_size = sizeof(uint32_t); /* Minimum expected size */
8f3b8fd6
RL
611 if (p->data == NULL)
612 return 1;
9830e7ea
P
613 switch (p->data_size) {
614 case sizeof(uint32_t):
615 *(uint32_t *)p->data = val;
616 return 1;
617 case sizeof(uint64_t):
4e7991b4 618 p->return_size = sizeof(uint64_t);
9830e7ea
P
619 *(uint64_t *)p->data = val;
620 return 1;
621 }
e9c5e642
P
622#endif
623 return general_set_uint(p, &val, sizeof(val));
9830e7ea 624 } else if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642 625#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 626 p->return_size = sizeof(int32_t); /* Minimum expected size */
8f3b8fd6
RL
627 if (p->data == NULL)
628 return 1;
9830e7ea
P
629 switch (p->data_size) {
630 case sizeof(int32_t):
631 if (val <= INT32_MAX) {
632 *(int32_t *)p->data = (int32_t)val;
633 return 1;
634 }
ac1082f0 635 err_out_of_range;
e9c5e642 636 return 0;
9830e7ea 637 case sizeof(int64_t):
4e7991b4 638 p->return_size = sizeof(int64_t);
9830e7ea
P
639 *(int64_t *)p->data = (int64_t)val;
640 return 1;
641 }
e9c5e642
P
642#endif
643 return general_set_uint(p, &val, sizeof(val));
9830e7ea 644 } else if (p->data_type == OSSL_PARAM_REAL) {
4e7991b4 645 p->return_size = sizeof(double);
8f3b8fd6
RL
646 if (p->data == NULL)
647 return 1;
9830e7ea
P
648 switch (p->data_size) {
649 case sizeof(double):
ac1082f0
P
650 shift = real_shift();
651 if (shift < 8 * sizeof(val) && (val >> shift) != 0) {
652 err_inexact;
653 return 0;
654 }
9830e7ea
P
655 *(double *)p->data = (double)val;
656 return 1;
657 }
ac1082f0
P
658 err_unsupported_real;
659 return 0;
7ffbd7ca 660 }
ac1082f0 661 err_bad_type;
7ffbd7ca
P
662 return 0;
663}
664
4e7991b4 665OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf)
7ffbd7ca
P
666{
667 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
4e7991b4 668 sizeof(uint32_t));
7ffbd7ca
P
669}
670
671int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
672{
9830e7ea
P
673 double d;
674
ac1082f0
P
675 if (val == NULL || p == NULL) {
676 err_null_argument;
7ffbd7ca 677 return 0;
ac1082f0 678 }
7ffbd7ca 679
9830e7ea 680 if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642 681#ifndef OPENSSL_SMALL_FOOTPRINT
9830e7ea
P
682 switch (p->data_size) {
683 case sizeof(int32_t):
684 *val = *(const int32_t *)p->data;
685 return 1;
686 case sizeof(int64_t):
687 *val = *(const int64_t *)p->data;
688 return 1;
689 }
e9c5e642
P
690#endif
691 return general_get_int(p, val, sizeof(*val));
9830e7ea 692 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642
P
693#ifndef OPENSSL_SMALL_FOOTPRINT
694 uint64_t u64;
695
9830e7ea
P
696 switch (p->data_size) {
697 case sizeof(uint32_t):
698 *val = *(const uint32_t *)p->data;
699 return 1;
700 case sizeof(uint64_t):
701 u64 = *(const uint64_t *)p->data;
702 if (u64 <= INT64_MAX) {
703 *val = (int64_t)u64;
704 return 1;
705 }
ac1082f0 706 err_out_of_range;
e9c5e642 707 return 0;
9830e7ea 708 }
e9c5e642
P
709#endif
710 return general_get_int(p, val, sizeof(*val));
9830e7ea
P
711 } else if (p->data_type == OSSL_PARAM_REAL) {
712 switch (p->data_size) {
713 case sizeof(double):
714 d = *(const double *)p->data;
5b1d94c1
P
715 if (d >= INT64_MIN
716 /*
717 * By subtracting 65535 (2^16-1) we cancel the low order
718 * 15 bits of INT64_MAX to avoid using imprecise floating
719 * point values.
720 */
721 && d < (double)(INT64_MAX - 65535) + 65536.0
722 && d == (int64_t)d) {
9830e7ea
P
723 *val = (int64_t)d;
724 return 1;
725 }
ac1082f0
P
726 err_inexact;
727 return 0;
9830e7ea 728 }
ac1082f0
P
729 err_unsupported_real;
730 return 0;
7ffbd7ca 731 }
ac1082f0 732 err_bad_type;
7ffbd7ca
P
733 return 0;
734}
735
4e7991b4 736int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val)
7ffbd7ca 737{
9830e7ea
P
738 uint64_t u64;
739
ac1082f0
P
740 if (p == NULL) {
741 err_null_argument;
7ffbd7ca 742 return 0;
ac1082f0 743 }
4e7991b4 744 p->return_size = 0;
9830e7ea 745 if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642 746#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 747 p->return_size = sizeof(int64_t); /* Expected size */
8f3b8fd6
RL
748 if (p->data == NULL)
749 return 1;
9830e7ea
P
750 switch (p->data_size) {
751 case sizeof(int32_t):
752 if (val >= INT32_MIN && val <= INT32_MAX) {
4e7991b4 753 p->return_size = sizeof(int32_t);
9830e7ea
P
754 *(int32_t *)p->data = (int32_t)val;
755 return 1;
756 }
ac1082f0 757 err_out_of_range;
e9c5e642 758 return 0;
9830e7ea
P
759 case sizeof(int64_t):
760 *(int64_t *)p->data = val;
761 return 1;
762 }
e9c5e642
P
763#endif
764 return general_set_int(p, &val, sizeof(val));
9830e7ea 765 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
e9c5e642 766#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 767 p->return_size = sizeof(uint64_t); /* Expected size */
8f3b8fd6
RL
768 if (p->data == NULL)
769 return 1;
9830e7ea
P
770 switch (p->data_size) {
771 case sizeof(uint32_t):
772 if (val <= UINT32_MAX) {
4e7991b4 773 p->return_size = sizeof(uint32_t);
9830e7ea
P
774 *(uint32_t *)p->data = (uint32_t)val;
775 return 1;
776 }
ac1082f0 777 err_out_of_range;
e9c5e642 778 return 0;
9830e7ea
P
779 case sizeof(uint64_t):
780 *(uint64_t *)p->data = (uint64_t)val;
781 return 1;
782 }
e9c5e642
P
783#endif
784 return general_set_int(p, &val, sizeof(val));
9830e7ea 785 } else if (p->data_type == OSSL_PARAM_REAL) {
4e7991b4 786 p->return_size = sizeof(double);
8f3b8fd6
RL
787 if (p->data == NULL)
788 return 1;
9830e7ea
P
789 switch (p->data_size) {
790 case sizeof(double):
791 u64 = val < 0 ? -val : val;
5b1d94c1 792 if ((u64 >> real_shift()) == 0) {
9830e7ea
P
793 *(double *)p->data = (double)val;
794 return 1;
795 }
ac1082f0
P
796 err_inexact;
797 return 0;
9830e7ea 798 }
ac1082f0
P
799 err_unsupported_real;
800 return 0;
7ffbd7ca 801 }
ac1082f0 802 err_bad_type;
7ffbd7ca
P
803 return 0;
804}
805
4e7991b4 806OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf)
7ffbd7ca 807{
4e7991b4 808 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t));
7ffbd7ca
P
809}
810
811int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
812{
9830e7ea
P
813 double d;
814
ac1082f0
P
815 if (val == NULL || p == NULL) {
816 err_null_argument;
7ffbd7ca 817 return 0;
ac1082f0 818 }
7ffbd7ca 819
9830e7ea 820 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642 821#ifndef OPENSSL_SMALL_FOOTPRINT
9830e7ea
P
822 switch (p->data_size) {
823 case sizeof(uint32_t):
824 *val = *(const uint32_t *)p->data;
825 return 1;
826 case sizeof(uint64_t):
827 *val = *(const uint64_t *)p->data;
828 return 1;
829 }
e9c5e642
P
830#endif
831 return general_get_uint(p, val, sizeof(*val));
9830e7ea 832 } else if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642
P
833#ifndef OPENSSL_SMALL_FOOTPRINT
834 int32_t i32;
835 int64_t i64;
836
9830e7ea
P
837 switch (p->data_size) {
838 case sizeof(int32_t):
839 i32 = *(const int32_t *)p->data;
840 if (i32 >= 0) {
841 *val = (uint64_t)i32;
842 return 1;
843 }
ac1082f0 844 err_unsigned_negative;
e9c5e642 845 return 0;
9830e7ea
P
846 case sizeof(int64_t):
847 i64 = *(const int64_t *)p->data;
848 if (i64 >= 0) {
849 *val = (uint64_t)i64;
850 return 1;
851 }
ac1082f0 852 err_unsigned_negative;
e9c5e642 853 return 0;
9830e7ea 854 }
e9c5e642
P
855#endif
856 return general_get_uint(p, val, sizeof(*val));
9830e7ea
P
857 } else if (p->data_type == OSSL_PARAM_REAL) {
858 switch (p->data_size) {
859 case sizeof(double):
860 d = *(const double *)p->data;
5b1d94c1
P
861 if (d >= 0
862 /*
863 * By subtracting 65535 (2^16-1) we cancel the low order
864 * 15 bits of UINT64_MAX to avoid using imprecise floating
865 * point values.
866 */
867 && d < (double)(UINT64_MAX - 65535) + 65536.0
868 && d == (uint64_t)d) {
9830e7ea
P
869 *val = (uint64_t)d;
870 return 1;
871 }
ac1082f0
P
872 err_inexact;
873 return 0;
9830e7ea 874 }
ac1082f0
P
875 err_unsupported_real;
876 return 0;
7ffbd7ca 877 }
ac1082f0 878 err_bad_type;
7ffbd7ca
P
879 return 0;
880}
881
4e7991b4 882int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val)
7ffbd7ca 883{
ac1082f0
P
884 if (p == NULL) {
885 err_null_argument;
7ffbd7ca 886 return 0;
ac1082f0 887 }
4e7991b4 888 p->return_size = 0;
7ffbd7ca 889
9830e7ea 890 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
e9c5e642 891#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 892 p->return_size = sizeof(uint64_t); /* Expected size */
8f3b8fd6
RL
893 if (p->data == NULL)
894 return 1;
9830e7ea
P
895 switch (p->data_size) {
896 case sizeof(uint32_t):
897 if (val <= UINT32_MAX) {
4e7991b4 898 p->return_size = sizeof(uint32_t);
9830e7ea
P
899 *(uint32_t *)p->data = (uint32_t)val;
900 return 1;
901 }
ac1082f0 902 err_out_of_range;
e9c5e642 903 return 0;
9830e7ea
P
904 case sizeof(uint64_t):
905 *(uint64_t *)p->data = val;
906 return 1;
907 }
e9c5e642
P
908#endif
909 return general_set_uint(p, &val, sizeof(val));
9830e7ea 910 } else if (p->data_type == OSSL_PARAM_INTEGER) {
e9c5e642 911#ifndef OPENSSL_SMALL_FOOTPRINT
4e7991b4 912 p->return_size = sizeof(int64_t); /* Expected size */
8f3b8fd6
RL
913 if (p->data == NULL)
914 return 1;
9830e7ea
P
915 switch (p->data_size) {
916 case sizeof(int32_t):
917 if (val <= INT32_MAX) {
4e7991b4 918 p->return_size = sizeof(int32_t);
9830e7ea
P
919 *(int32_t *)p->data = (int32_t)val;
920 return 1;
921 }
ac1082f0 922 err_out_of_range;
e9c5e642 923 return 0;
9830e7ea
P
924 case sizeof(int64_t):
925 if (val <= INT64_MAX) {
926 *(int64_t *)p->data = (int64_t)val;
927 return 1;
928 }
ac1082f0 929 err_out_of_range;
e9c5e642 930 return 0;
9830e7ea 931 }
e9c5e642
P
932#endif
933 return general_set_uint(p, &val, sizeof(val));
9830e7ea 934 } else if (p->data_type == OSSL_PARAM_REAL) {
4e7991b4 935 p->return_size = sizeof(double);
9830e7ea
P
936 switch (p->data_size) {
937 case sizeof(double):
5b1d94c1 938 if ((val >> real_shift()) == 0) {
9830e7ea
P
939 *(double *)p->data = (double)val;
940 return 1;
941 }
ac1082f0
P
942 err_inexact;
943 return 0;
9830e7ea 944 }
ac1082f0
P
945 err_unsupported_real;
946 return 0;
7ffbd7ca 947 }
ac1082f0 948 err_bad_type;
7ffbd7ca
P
949 return 0;
950}
951
4e7991b4
P
952OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf)
953{
7ffbd7ca 954 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
4e7991b4 955 sizeof(uint64_t));
7ffbd7ca
P
956}
957
958int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
959{
e9c5e642 960#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 961 switch (sizeof(size_t)) {
7ffbd7ca 962 case sizeof(uint32_t):
863360fb 963 return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
7ffbd7ca 964 case sizeof(uint64_t):
863360fb 965 return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
7ffbd7ca 966 }
e9c5e642
P
967#endif
968 return general_get_uint(p, val, sizeof(*val));
7ffbd7ca
P
969}
970
4e7991b4 971int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val)
7ffbd7ca 972{
e9c5e642 973#ifndef OPENSSL_SMALL_FOOTPRINT
863360fb 974 switch (sizeof(size_t)) {
7ffbd7ca 975 case sizeof(uint32_t):
863360fb 976 return OSSL_PARAM_set_uint32(p, (uint32_t)val);
7ffbd7ca 977 case sizeof(uint64_t):
863360fb 978 return OSSL_PARAM_set_uint64(p, (uint64_t)val);
7ffbd7ca 979 }
e9c5e642
P
980#endif
981 return general_set_uint(p, &val, sizeof(val));
7ffbd7ca
P
982}
983
4e7991b4 984OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf)
7ffbd7ca
P
985{
986 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
4e7991b4
P
987 sizeof(size_t));
988}
7ffbd7ca 989
5fdaa38f
P
990int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val)
991{
e9c5e642 992#ifndef OPENSSL_SMALL_FOOTPRINT
5fdaa38f
P
993 switch (sizeof(time_t)) {
994 case sizeof(int32_t):
995 return OSSL_PARAM_get_int32(p, (int32_t *)val);
996 case sizeof(int64_t):
997 return OSSL_PARAM_get_int64(p, (int64_t *)val);
998 }
e9c5e642
P
999#endif
1000 return general_get_int(p, val, sizeof(*val));
5fdaa38f
P
1001}
1002
1003int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val)
1004{
e9c5e642 1005#ifndef OPENSSL_SMALL_FOOTPRINT
5fdaa38f
P
1006 switch (sizeof(time_t)) {
1007 case sizeof(int32_t):
1008 return OSSL_PARAM_set_int32(p, (int32_t)val);
1009 case sizeof(int64_t):
1010 return OSSL_PARAM_set_int64(p, (int64_t)val);
1011 }
e9c5e642
P
1012#endif
1013 return general_set_int(p, &val, sizeof(val));
5fdaa38f
P
1014}
1015
1016OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf)
1017{
1018 return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(time_t));
1019}
1020
7ffbd7ca
P
1021int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
1022{
f1719858 1023 BIGNUM *b = NULL;
7ffbd7ca 1024
ac1082f0
P
1025 if (val == NULL || p == NULL) {
1026 err_null_argument;
1027 return 0;
1028 }
f1719858
RL
1029
1030 switch (p->data_type) {
1031 case OSSL_PARAM_UNSIGNED_INTEGER:
1032 b = BN_native2bn(p->data, (int)p->data_size, *val);
1033 break;
1034 case OSSL_PARAM_INTEGER:
1035 b = BN_signed_native2bn(p->data, (int)p->data_size, *val);
1036 break;
1037 default:
ac1082f0 1038 err_bad_type;
f1719858 1039 break;
ac1082f0 1040 }
7ffbd7ca 1041
f1719858 1042 if (b == NULL) {
e077455e 1043 ERR_raise(ERR_LIB_CRYPTO, ERR_R_BN_LIB);
f1719858 1044 return 0;
7ffbd7ca 1045 }
f1719858
RL
1046
1047 *val = b;
1048 return 1;
7ffbd7ca
P
1049}
1050
4e7991b4 1051int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
7ffbd7ca
P
1052{
1053 size_t bytes;
1054
ac1082f0
P
1055 if (p == NULL) {
1056 err_null_argument;
7ffbd7ca 1057 return 0;
ac1082f0 1058 }
4e7991b4 1059 p->return_size = 0;
ac1082f0
P
1060 if (val == NULL) {
1061 err_null_argument;
7ffbd7ca 1062 return 0;
ac1082f0 1063 }
f1719858 1064 if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && BN_is_negative(val)) {
ac1082f0
P
1065 err_bad_type;
1066 return 0;
1067 }
7ffbd7ca
P
1068
1069 bytes = (size_t)BN_num_bytes(val);
f1719858
RL
1070 /* We add 1 byte for signed numbers, to make space for a sign extension */
1071 if (p->data_type == OSSL_PARAM_INTEGER)
1072 bytes++;
c2ae8914
RL
1073 /* We make sure that at least one byte is used, so zero is properly set */
1074 if (bytes == 0)
1075 bytes++;
f1719858 1076
4e7991b4 1077 p->return_size = bytes;
8f3b8fd6
RL
1078 if (p->data == NULL)
1079 return 1;
0f73e719
RL
1080 if (p->data_size >= bytes) {
1081 p->return_size = p->data_size;
f1719858
RL
1082
1083 switch (p->data_type) {
1084 case OSSL_PARAM_UNSIGNED_INTEGER:
1085 if (BN_bn2nativepad(val, p->data, p->data_size) >= 0)
1086 return 1;
1087 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW);
1088 break;
1089 case OSSL_PARAM_INTEGER:
1090 if (BN_signed_bn2native(val, p->data, p->data_size) >= 0)
1091 return 1;
1092 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_INTEGER_OVERFLOW);
1093 break;
1094 default:
1095 err_bad_type;
1096 break;
1097 }
ac1082f0 1098 return 0;
0f73e719 1099 }
ac1082f0 1100 err_too_small;
0f73e719 1101 return 0;
7ffbd7ca
P
1102}
1103
1104OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
4e7991b4 1105 size_t bsize)
7ffbd7ca
P
1106{
1107 return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER,
4e7991b4 1108 buf, bsize);
7ffbd7ca
P
1109}
1110
1111int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
1112{
9830e7ea
P
1113 int64_t i64;
1114 uint64_t u64;
1115
ac1082f0
P
1116 if (val == NULL || p == NULL) {
1117 err_null_argument;
7ffbd7ca 1118 return 0;
ac1082f0 1119 }
7ffbd7ca 1120
9830e7ea
P
1121 if (p->data_type == OSSL_PARAM_REAL) {
1122 switch (p->data_size) {
1123 case sizeof(double):
1124 *val = *(const double *)p->data;
1125 return 1;
1126 }
ac1082f0
P
1127 err_unsupported_real;
1128 return 0;
9830e7ea
P
1129 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
1130 switch (p->data_size) {
1131 case sizeof(uint32_t):
1132 *val = *(const uint32_t *)p->data;
1133 return 1;
1134 case sizeof(uint64_t):
1135 u64 = *(const uint64_t *)p->data;
5b1d94c1 1136 if ((u64 >> real_shift()) == 0) {
9830e7ea
P
1137 *val = (double)u64;
1138 return 1;
1139 }
ac1082f0
P
1140 err_inexact;
1141 return 0;
9830e7ea
P
1142 }
1143 } else if (p->data_type == OSSL_PARAM_INTEGER) {
1144 switch (p->data_size) {
1145 case sizeof(int32_t):
1146 *val = *(const int32_t *)p->data;
1147 return 1;
1148 case sizeof(int64_t):
1149 i64 = *(const int64_t *)p->data;
1150 u64 = i64 < 0 ? -i64 : i64;
5b1d94c1 1151 if ((u64 >> real_shift()) == 0) {
9830e7ea
P
1152 *val = 0.0 + i64;
1153 return 1;
1154 }
ac1082f0
P
1155 err_inexact;
1156 return 0;
9830e7ea 1157 }
7ffbd7ca 1158 }
ac1082f0 1159 err_bad_type;
7ffbd7ca
P
1160 return 0;
1161}
1162
4e7991b4 1163int OSSL_PARAM_set_double(OSSL_PARAM *p, double val)
7ffbd7ca 1164{
ac1082f0
P
1165 if (p == NULL) {
1166 err_null_argument;
7ffbd7ca 1167 return 0;
ac1082f0 1168 }
4e7991b4 1169 p->return_size = 0;
7ffbd7ca 1170
9830e7ea 1171 if (p->data_type == OSSL_PARAM_REAL) {
4e7991b4 1172 p->return_size = sizeof(double);
8f3b8fd6
RL
1173 if (p->data == NULL)
1174 return 1;
9830e7ea
P
1175 switch (p->data_size) {
1176 case sizeof(double):
1177 *(double *)p->data = val;
1178 return 1;
1179 }
ac1082f0
P
1180 err_unsupported_real;
1181 return 0;
1182 } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
4e7991b4 1183 p->return_size = sizeof(double);
8f3b8fd6
RL
1184 if (p->data == NULL)
1185 return 1;
ac1082f0
P
1186 if (val != (uint64_t)val) {
1187 err_inexact;
1188 return 0;
1189 }
9830e7ea
P
1190 switch (p->data_size) {
1191 case sizeof(uint32_t):
1192 if (val >= 0 && val <= UINT32_MAX) {
4e7991b4 1193 p->return_size = sizeof(uint32_t);
9830e7ea
P
1194 *(uint32_t *)p->data = (uint32_t)val;
1195 return 1;
1196 }
ac1082f0
P
1197 err_out_of_range;
1198 return 0;
9830e7ea 1199 case sizeof(uint64_t):
5b1d94c1
P
1200 if (val >= 0
1201 /*
1202 * By subtracting 65535 (2^16-1) we cancel the low order
1203 * 15 bits of UINT64_MAX to avoid using imprecise floating
1204 * point values.
1205 */
b9d022d7 1206 && val < (double)(UINT64_MAX - 65535) + 65536.0) {
4e7991b4 1207 p->return_size = sizeof(uint64_t);
9830e7ea
P
1208 *(uint64_t *)p->data = (uint64_t)val;
1209 return 1;
1210 }
ac1082f0
P
1211 err_out_of_range;
1212 return 0;
1213 }
1214 } else if (p->data_type == OSSL_PARAM_INTEGER) {
4e7991b4 1215 p->return_size = sizeof(double);
8f3b8fd6
RL
1216 if (p->data == NULL)
1217 return 1;
ac1082f0
P
1218 if (val != (int64_t)val) {
1219 err_inexact;
1220 return 0;
1221 }
9830e7ea
P
1222 switch (p->data_size) {
1223 case sizeof(int32_t):
1224 if (val >= INT32_MIN && val <= INT32_MAX) {
4e7991b4 1225 p->return_size = sizeof(int32_t);
9830e7ea
P
1226 *(int32_t *)p->data = (int32_t)val;
1227 return 1;
1228 }
ac1082f0
P
1229 err_out_of_range;
1230 return 0;
9830e7ea 1231 case sizeof(int64_t):
5b1d94c1
P
1232 if (val >= INT64_MIN
1233 /*
1234 * By subtracting 65535 (2^16-1) we cancel the low order
1235 * 15 bits of INT64_MAX to avoid using imprecise floating
1236 * point values.
1237 */
1238 && val < (double)(INT64_MAX - 65535) + 65536.0) {
4e7991b4 1239 p->return_size = sizeof(int64_t);
9830e7ea
P
1240 *(int64_t *)p->data = (int64_t)val;
1241 return 1;
1242 }
ac1082f0
P
1243 err_out_of_range;
1244 return 0;
9830e7ea 1245 }
7ffbd7ca 1246 }
ac1082f0 1247 err_bad_type;
7ffbd7ca
P
1248 return 0;
1249}
1250
4e7991b4 1251OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf)
7ffbd7ca 1252{
4e7991b4 1253 return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double));
7ffbd7ca
P
1254}
1255
247a1786
RL
1256static int get_string_internal(const OSSL_PARAM *p, void **val,
1257 size_t *max_len, size_t *used_len,
1258 unsigned int type)
7ffbd7ca 1259{
247a1786 1260 size_t sz, alloc_sz;
7ffbd7ca 1261
ac1082f0
P
1262 if ((val == NULL && used_len == NULL) || p == NULL) {
1263 err_null_argument;
1264 return 0;
1265 }
1266 if (p->data_type != type) {
1267 err_bad_type;
7ffbd7ca 1268 return 0;
ac1082f0 1269 }
7ffbd7ca
P
1270
1271 sz = p->data_size;
247a1786
RL
1272 /*
1273 * If the input size is 0, or the input string needs NUL byte
1274 * termination, allocate an extra byte.
1275 */
1276 alloc_sz = sz + (type == OSSL_PARAM_UTF8_STRING || sz == 0);
7ffbd7ca
P
1277
1278 if (used_len != NULL)
1279 *used_len = sz;
1280
ac1082f0
P
1281 if (p->data == NULL) {
1282 err_null_argument;
86f32187 1283 return 0;
ac1082f0 1284 }
46ef075a 1285
b756626a
MC
1286 if (val == NULL)
1287 return 1;
1288
7ffbd7ca 1289 if (*val == NULL) {
247a1786 1290 char *const q = OPENSSL_malloc(alloc_sz);
7ffbd7ca 1291
e077455e 1292 if (q == NULL)
7ffbd7ca
P
1293 return 0;
1294 *val = q;
247a1786 1295 *max_len = alloc_sz;
7ffbd7ca 1296 }
247a1786 1297
ac1082f0
P
1298 if (*max_len < sz) {
1299 err_too_small;
7ffbd7ca 1300 return 0;
ac1082f0 1301 }
7ffbd7ca
P
1302 memcpy(*val, p->data, sz);
1303 return 1;
1304}
1305
1306int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len)
1307{
247a1786
RL
1308 int ret = get_string_internal(p, (void **)val, &max_len, NULL,
1309 OSSL_PARAM_UTF8_STRING);
1310
1311 /*
1312 * We try to ensure that the copied string is terminated with a
1313 * NUL byte. That should be easy, just place a NUL byte at
1314 * |((char*)*val)[p->data_size]|.
1315 * Unfortunately, we have seen cases where |p->data_size| doesn't
1316 * correctly reflect the length of the string, and just happens
1317 * to be out of bounds according to |max_len|, so in that case, we
1318 * make the extra step of trying to find the true length of the
1319 * string that |p->data| points at, and use that as an index to
1320 * place the NUL byte in |*val|.
1321 */
1322 size_t data_length = p->data_size;
1323
1fac2705
TM
1324 if (ret == 0)
1325 return 0;
247a1786
RL
1326 if (data_length >= max_len)
1327 data_length = OPENSSL_strnlen(p->data, data_length);
ac1082f0
P
1328 if (data_length >= max_len) {
1329 ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_NO_SPACE_FOR_TERMINATING_NULL);
247a1786 1330 return 0; /* No space for a terminating NUL byte */
ac1082f0 1331 }
1fac2705 1332 (*val)[data_length] = '\0';
247a1786
RL
1333
1334 return ret;
7ffbd7ca
P
1335}
1336
1337int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
1338 size_t *used_len)
1339{
247a1786 1340 return get_string_internal(p, val, &max_len, used_len,
7ffbd7ca
P
1341 OSSL_PARAM_OCTET_STRING);
1342}
1343
4e7991b4 1344static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len,
7ffbd7ca
P
1345 unsigned int type)
1346{
4e7991b4 1347 p->return_size = len;
8f3b8fd6
RL
1348 if (p->data == NULL)
1349 return 1;
ac1082f0
P
1350 if (p->data_type != type) {
1351 err_bad_type;
7ffbd7ca 1352 return 0;
ac1082f0
P
1353 }
1354 if (p->data_size < len) {
1355 err_too_small;
1356 return 0;
1357 }
7ffbd7ca
P
1358
1359 memcpy(p->data, val, len);
247a1786
RL
1360 /* If possible within the size of p->data, add a NUL terminator byte */
1361 if (type == OSSL_PARAM_UTF8_STRING && p->data_size > len)
1362 ((char *)p->data)[len] = '\0';
7ffbd7ca
P
1363 return 1;
1364}
1365
4e7991b4 1366int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val)
7ffbd7ca 1367{
ac1082f0
P
1368 if (p == NULL) {
1369 err_null_argument;
7ffbd7ca 1370 return 0;
ac1082f0 1371 }
7ffbd7ca 1372
4e7991b4 1373 p->return_size = 0;
ac1082f0
P
1374 if (val == NULL) {
1375 err_null_argument;
7ffbd7ca 1376 return 0;
ac1082f0 1377 }
247a1786 1378 return set_string_internal(p, val, strlen(val), OSSL_PARAM_UTF8_STRING);
7ffbd7ca
P
1379}
1380
4e7991b4 1381int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val,
7ffbd7ca
P
1382 size_t len)
1383{
ac1082f0
P
1384 if (p == NULL) {
1385 err_null_argument;
7ffbd7ca 1386 return 0;
ac1082f0 1387 }
7ffbd7ca 1388
4e7991b4 1389 p->return_size = 0;
ac1082f0
P
1390 if (val == NULL) {
1391 err_null_argument;
7ffbd7ca 1392 return 0;
ac1082f0 1393 }
7ffbd7ca
P
1394 return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING);
1395}
1396
1397OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
4e7991b4 1398 size_t bsize)
7ffbd7ca 1399{
7f588d20 1400 if (buf != NULL && bsize == 0)
247a1786 1401 bsize = strlen(buf);
4e7991b4 1402 return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize);
7ffbd7ca
P
1403}
1404
1405OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
4e7991b4 1406 size_t bsize)
7ffbd7ca 1407{
4e7991b4 1408 return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize);
7ffbd7ca
P
1409}
1410
1411static int get_ptr_internal(const OSSL_PARAM *p, const void **val,
1412 size_t *used_len, unsigned int type)
1413{
ac1082f0
P
1414 if (val == NULL || p == NULL) {
1415 err_null_argument;
1416 return 0;
1417 }
1418 if (p->data_type != type) {
1419 err_bad_type;
7ffbd7ca 1420 return 0;
ac1082f0 1421 }
7ffbd7ca
P
1422 if (used_len != NULL)
1423 *used_len = p->data_size;
1424 *val = *(const void **)p->data;
1425 return 1;
1426}
1427
1428int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val)
1429{
1430 return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR);
1431}
1432
1433int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
1434 size_t *used_len)
1435{
1436 return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR);
1437}
1438
4e7991b4 1439static int set_ptr_internal(OSSL_PARAM *p, const void *val,
7ffbd7ca
P
1440 unsigned int type, size_t len)
1441{
4e7991b4 1442 p->return_size = len;
ac1082f0
P
1443 if (p->data_type != type) {
1444 err_bad_type;
7ffbd7ca 1445 return 0;
ac1082f0 1446 }
8f3b8fd6
RL
1447 if (p->data != NULL)
1448 *(const void **)p->data = val;
7ffbd7ca
P
1449 return 1;
1450}
1451
4e7991b4 1452int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val)
7ffbd7ca 1453{
ac1082f0
P
1454 if (p == NULL) {
1455 err_null_argument;
7ffbd7ca 1456 return 0;
ac1082f0 1457 }
4e7991b4 1458 p->return_size = 0;
b3f3ba70 1459 return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR,
247a1786 1460 val == NULL ? 0 : strlen(val));
7ffbd7ca
P
1461}
1462
4e7991b4 1463int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
7ffbd7ca
P
1464 size_t used_len)
1465{
ac1082f0
P
1466 if (p == NULL) {
1467 err_null_argument;
7ffbd7ca 1468 return 0;
ac1082f0 1469 }
4e7991b4 1470 p->return_size = 0;
7ffbd7ca
P
1471 return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len);
1472}
1473
1474OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
4e7991b4 1475 size_t bsize)
7ffbd7ca 1476{
4e7991b4 1477 return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, bsize);
7ffbd7ca
P
1478}
1479
1480OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
4e7991b4 1481 size_t bsize)
7ffbd7ca 1482{
4e7991b4 1483 return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize);
7ffbd7ca 1484}
195852fe 1485
79523d55
P
1486/*
1487 * Extract the parameter into an allocated buffer.
1488 * Any existing allocation in *out is cleared and freed.
1489 *
1490 * Returns 1 on success, 0 on failure and -1 if there are no matching params.
1491 *
1492 * *out and *out_len are guaranteed to be untouched if this function
1493 * doesn't return success.
1494 */
1495int ossl_param_get1_octet_string(const OSSL_PARAM *params, const char *name,
1496 unsigned char **out, size_t *out_len)
1497{
1498 const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
1499 void *buf = NULL;
1500 size_t len = 0;
1501
1502 if (p == NULL)
1503 return -1;
1504
1505 if (p->data != NULL
1506 && p->data_size > 0
1507 && !OSSL_PARAM_get_octet_string(p, &buf, 0, &len))
1508 return 0;
1509
1510 OPENSSL_clear_free(*out, *out_len);
1511 *out = buf;
1512 *out_len = len;
1513 return 1;
1514}
1515
1516static int setbuf_fromparams(const OSSL_PARAM *p, const char *name,
1517 unsigned char *out, size_t *outlen)
1518{
1519 int ret = 0;
1520 WPACKET pkt;
1521
1522 if (out == NULL) {
1523 if (!WPACKET_init_null(&pkt, 0))
1524 return 0;
1525 } else {
1526 if (!WPACKET_init_static_len(&pkt, out, *outlen, 0))
1527 return 0;
1528 }
1529
1530 for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1, name)) {
1531 if (p->data_type != OSSL_PARAM_OCTET_STRING)
1532 goto err;
1533 if (p->data != NULL
1534 && p->data_size != 0
1535 && !WPACKET_memcpy(&pkt, p->data, p->data_size))
1536 goto err;
1537 }
1538 if (!WPACKET_get_total_written(&pkt, outlen)
1539 || !WPACKET_finish(&pkt))
1540 goto err;
1541 ret = 1;
1542err:
1543 WPACKET_cleanup(&pkt);
1544 return ret;
1545}
1546
1547int ossl_param_get1_concat_octet_string(const OSSL_PARAM *params, const char *name,
1548 unsigned char **out,
1549 size_t *out_len, size_t maxsize)
1550{
1551 const OSSL_PARAM *p = OSSL_PARAM_locate_const(params, name);
1552 unsigned char *res;
1553 size_t sz = 0;
1554
1555 if (p == NULL)
1556 return -1;
1557
1558 /* Calculate the total size */
1559 if (!setbuf_fromparams(p, name, NULL, &sz))
1560 return 0;
1561
1562 /* Check that it's not oversized */
1563 if (maxsize > 0 && sz > maxsize)
1564 return 0;
1565
1566 /* Special case zero length */
1567 if (sz == 0) {
1568 if ((res = OPENSSL_zalloc(1)) == NULL)
1569 return 0;
1570 goto fin;
1571 }
1572
1573 /* Allocate the buffer */
1574 res = OPENSSL_malloc(sz);
1575 if (res == NULL)
1576 return 0;
1577
1578 /* Concat one or more OSSL_KDF_PARAM_INFO fields */
1579 if (!setbuf_fromparams(p, name, res, &sz)) {
1580 OPENSSL_clear_free(res, sz);
1581 return 0;
1582 }
1583
1584 fin:
1585 OPENSSL_clear_free(*out, *out_len);
1586 *out = res;
1587 *out_len = sz;
1588 return 1;
1589}
1590
195852fe
RL
1591OSSL_PARAM OSSL_PARAM_construct_end(void)
1592{
1593 OSSL_PARAM end = OSSL_PARAM_END;
1594
1595 return end;
1596}
ab00ddb5
RL
1597
1598static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val,
1599 size_t *used_len, unsigned int type)
1600{
ac1082f0
P
1601 if (val == NULL || p == NULL) {
1602 err_null_argument;
ab00ddb5 1603 return 0;
ac1082f0
P
1604 }
1605 if (p->data_type != type) {
1606 err_bad_type;
1607 return 0;
1608 }
ab00ddb5
RL
1609 if (used_len != NULL)
1610 *used_len = p->data_size;
1611 *val = p->data;
1612 return 1;
1613}
1614
1615int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val)
1616{
327a720d
TM
1617 int rv;
1618
1619 ERR_set_mark();
1620 rv = OSSL_PARAM_get_utf8_ptr(p, val);
1621 ERR_pop_to_mark();
1622
1623 return rv || get_string_ptr_internal(p, (const void **)val, NULL,
1624 OSSL_PARAM_UTF8_STRING);
ab00ddb5
RL
1625}
1626
1627int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
1628 size_t *used_len)
1629{
327a720d
TM
1630 int rv;
1631
1632 ERR_set_mark();
1633 rv = OSSL_PARAM_get_octet_ptr(p, val, used_len);
1634 ERR_pop_to_mark();
1635
1636 return rv || get_string_ptr_internal(p, val, used_len,
1637 OSSL_PARAM_OCTET_STRING);
ab00ddb5 1638}