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