xref: /freebsd/crypto/openssl/crypto/params.c (revision e7be843b4a162e68651d3911f0357ed464915629)
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