ERR: drop err_delete_thread_state() TODO marker
[openssl.git] / crypto / params.c
1 /*
2  * Copyright 2019-2020 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 "internal/thread_once.h"
14 #include "internal/numbers.h"
15
16 /*
17  * Return the number of bits in the mantissa of a double.  This is used to
18  * shift a larger integral value to determine if it will exactly fit into a
19  * double.
20  */
21 static unsigned int real_shift(void)
22 {
23     return sizeof(double) == 4 ? 24 : 53;
24 }
25
26 OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key)
27 {
28     if (p != NULL && key != NULL)
29         for (; p->key != NULL; p++)
30             if (strcmp(key, p->key) == 0)
31                 return p;
32     return NULL;
33 }
34
35 const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key)
36 {
37     return OSSL_PARAM_locate((OSSL_PARAM *)p, key);
38 }
39
40 static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
41                                        void *data, size_t data_size)
42 {
43     OSSL_PARAM res;
44
45     res.key = key;
46     res.data_type = data_type;
47     res.data = data;
48     res.data_size = data_size;
49     res.return_size = OSSL_PARAM_UNMODIFIED;
50     return res;
51 }
52
53 int OSSL_PARAM_modified(const OSSL_PARAM *p)
54 {
55     return p != NULL && p->return_size != OSSL_PARAM_UNMODIFIED;
56 }
57
58 void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p)
59 {
60     if (p != NULL)
61         while (p->key != NULL)
62             p++->return_size = OSSL_PARAM_UNMODIFIED;
63 }
64
65 int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
66 {
67     switch (sizeof(int)) {
68     case sizeof(int32_t):
69         return OSSL_PARAM_get_int32(p, (int32_t *)val);
70     case sizeof(int64_t):
71         return OSSL_PARAM_get_int64(p, (int64_t *)val);
72     }
73     return 0;
74 }
75
76 int OSSL_PARAM_set_int(OSSL_PARAM *p, int val)
77 {
78     switch (sizeof(int)) {
79     case sizeof(int32_t):
80         return OSSL_PARAM_set_int32(p, (int32_t)val);
81     case sizeof(int64_t):
82         return OSSL_PARAM_set_int64(p, (int64_t)val);
83     }
84     return 0;
85 }
86
87 OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf)
88 {
89     return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int));
90 }
91
92 int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
93 {
94     switch (sizeof(unsigned int)) {
95     case sizeof(uint32_t):
96         return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
97     case sizeof(uint64_t):
98         return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
99     }
100     return 0;
101 }
102
103 int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val)
104 {
105     switch (sizeof(unsigned int)) {
106     case sizeof(uint32_t):
107         return OSSL_PARAM_set_uint32(p, (uint32_t)val);
108     case sizeof(uint64_t):
109         return OSSL_PARAM_set_uint64(p, (uint64_t)val);
110     }
111     return 0;
112 }
113
114 OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf)
115 {
116     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
117                                 sizeof(unsigned int));
118 }
119
120 int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
121 {
122     switch (sizeof(long int)) {
123     case sizeof(int32_t):
124         return OSSL_PARAM_get_int32(p, (int32_t *)val);
125     case sizeof(int64_t):
126         return OSSL_PARAM_get_int64(p, (int64_t *)val);
127     }
128     return 0;
129 }
130
131 int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val)
132 {
133     switch (sizeof(long int)) {
134     case sizeof(int32_t):
135         return OSSL_PARAM_set_int32(p, (int32_t)val);
136     case sizeof(int64_t):
137         return OSSL_PARAM_set_int64(p, (int64_t)val);
138     }
139     return 0;
140 }
141
142 OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf)
143 {
144     return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int));
145 }
146
147 int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
148 {
149     switch (sizeof(unsigned long int)) {
150     case sizeof(uint32_t):
151         return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
152     case sizeof(uint64_t):
153         return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
154     }
155     return 0;
156 }
157
158 int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val)
159 {
160     switch (sizeof(unsigned long int)) {
161     case sizeof(uint32_t):
162         return OSSL_PARAM_set_uint32(p, (uint32_t)val);
163     case sizeof(uint64_t):
164         return OSSL_PARAM_set_uint64(p, (uint64_t)val);
165     }
166     return 0;
167 }
168
169 OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf)
170 {
171     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
172                                 sizeof(unsigned long int));
173 }
174
175 int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
176 {
177     int64_t i64;
178     uint32_t u32;
179     uint64_t u64;
180     double d;
181
182     if (val == NULL || p == NULL )
183         return 0;
184
185     if (p->data_type == OSSL_PARAM_INTEGER) {
186         switch (p->data_size) {
187         case sizeof(int32_t):
188             *val = *(const int32_t *)p->data;
189             return 1;
190         case sizeof(int64_t):
191             i64 = *(const int64_t *)p->data;
192             if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
193                 *val = (int32_t)i64;
194                 return 1;
195             }
196             break;
197         }
198     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
199         switch (p->data_size) {
200         case sizeof(uint32_t):
201             u32 = *(const uint32_t *)p->data;
202             if (u32 <= INT32_MAX) {
203                 *val = (int32_t)u32;
204                 return 1;
205             }
206             break;
207         case sizeof(uint64_t):
208             u64 = *(const uint64_t *)p->data;
209             if (u64 <= INT32_MAX) {
210                 *val = (int32_t)u64;
211                 return 1;
212             }
213             break;
214         }
215     } else if (p->data_type == OSSL_PARAM_REAL) {
216         switch (p->data_size) {
217         case sizeof(double):
218             d = *(const double *)p->data;
219             if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) {
220                 *val = (int32_t)d;
221                 return 1;
222             }
223             break;
224         }
225     }
226     return 0;
227 }
228
229 int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val)
230 {
231     if (p == NULL)
232         return 0;
233     p->return_size = 0;
234     if (p->data_type == OSSL_PARAM_INTEGER) {
235         p->return_size = sizeof(int32_t); /* Minimum expected size */
236         if (p->data == NULL)
237             return 1;
238         switch (p->data_size) {
239         case sizeof(int32_t):
240             *(int32_t *)p->data = val;
241             return 1;
242         case sizeof(int64_t):
243             p->return_size = sizeof(int64_t);
244             *(int64_t *)p->data = (int64_t)val;
245             return 1;
246         }
247     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
248         p->return_size = sizeof(uint32_t); /* Minimum expected size */
249         if (p->data == NULL)
250             return 1;
251         switch (p->data_size) {
252         case sizeof(uint32_t):
253             *(uint32_t *)p->data = (uint32_t)val;
254             return 1;
255         case sizeof(uint64_t):
256             p->return_size = sizeof(uint64_t);
257             *(uint64_t *)p->data = (uint64_t)val;
258             return 1;
259         }
260     } else if (p->data_type == OSSL_PARAM_REAL) {
261         p->return_size = sizeof(double);
262         if (p->data == NULL)
263             return 1;
264         switch (p->data_size) {
265         case sizeof(double):
266             *(double *)p->data = (double)val;
267             return 1;
268         }
269     }
270     return 0;
271 }
272
273 OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf)
274 {
275     return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf,
276                                 sizeof(int32_t));
277 }
278
279 int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
280 {
281     int32_t i32;
282     int64_t i64;
283     uint64_t u64;
284     double d;
285
286     if (val == NULL || p == NULL)
287         return 0;
288
289     if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
290         switch (p->data_size) {
291         case sizeof(uint32_t):
292             *val = *(const uint32_t *)p->data;
293             return 1;
294         case sizeof(uint64_t):
295             u64 = *(const uint64_t *)p->data;
296             if (u64 <= UINT32_MAX) {
297                 *val = (uint32_t)u64;
298                 return 1;
299             }
300             break;
301         }
302     } else if (p->data_type == OSSL_PARAM_INTEGER) {
303         switch (p->data_size) {
304         case sizeof(int32_t):
305             i32 = *(const int32_t *)p->data;
306             if (i32 >= 0) {
307                 *val = i32;
308                 return 1;
309             }
310             break;
311         case sizeof(int64_t):
312             i64 = *(const int64_t *)p->data;
313             if (i64 >= 0 && i64 <= UINT32_MAX) {
314                 *val = (uint32_t)i64;
315                 return 1;
316             }
317             break;
318         }
319     } else if (p->data_type == OSSL_PARAM_REAL) {
320         switch (p->data_size) {
321         case sizeof(double):
322             d = *(const double *)p->data;
323             if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) {
324                 *val = (uint32_t)d;
325                 return 1;
326             }
327             break;
328         }
329     }
330     return 0;
331 }
332
333 int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val)
334 {
335     if (p == NULL)
336         return 0;
337     p->return_size = 0;
338
339     if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
340         p->return_size = sizeof(uint32_t); /* Minimum expected size */
341         if (p->data == NULL)
342             return 1;
343         switch (p->data_size) {
344         case sizeof(uint32_t):
345             *(uint32_t *)p->data = val;
346             return 1;
347         case sizeof(uint64_t):
348             p->return_size = sizeof(uint64_t);
349             *(uint64_t *)p->data = val;
350             return 1;
351         }
352     } else if (p->data_type == OSSL_PARAM_INTEGER) {
353         p->return_size = sizeof(int32_t); /* Minimum expected size */
354         if (p->data == NULL)
355             return 1;
356         switch (p->data_size) {
357         case sizeof(int32_t):
358             if (val <= INT32_MAX) {
359                 *(int32_t *)p->data = (int32_t)val;
360                 return 1;
361             }
362             break;
363         case sizeof(int64_t):
364             p->return_size = sizeof(int64_t);
365             *(int64_t *)p->data = (int64_t)val;
366             return 1;
367         }
368     } else if (p->data_type == OSSL_PARAM_REAL) {
369         p->return_size = sizeof(double);
370         if (p->data == NULL)
371             return 1;
372         switch (p->data_size) {
373         case sizeof(double):
374             *(double *)p->data = (double)val;
375             return 1;
376         }
377     }
378     return 0;
379 }
380
381 OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf)
382 {
383     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
384                                 sizeof(uint32_t));
385 }
386
387 int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
388 {
389     uint64_t u64;
390     double d;
391
392     if (val == NULL || p == NULL )
393         return 0;
394
395     if (p->data_type == OSSL_PARAM_INTEGER) {
396         switch (p->data_size) {
397         case sizeof(int32_t):
398             *val = *(const int32_t *)p->data;
399             return 1;
400         case sizeof(int64_t):
401             *val = *(const int64_t *)p->data;
402             return 1;
403         }
404     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
405         switch (p->data_size) {
406         case sizeof(uint32_t):
407             *val = *(const uint32_t *)p->data;
408             return 1;
409         case sizeof(uint64_t):
410             u64 = *(const uint64_t *)p->data;
411             if (u64 <= INT64_MAX) {
412                 *val = (int64_t)u64;
413                 return 1;
414             }
415             break;
416         }
417     } else if (p->data_type == OSSL_PARAM_REAL) {
418         switch (p->data_size) {
419         case sizeof(double):
420             d = *(const double *)p->data;
421             if (d >= INT64_MIN
422                     /*
423                      * By subtracting 65535 (2^16-1) we cancel the low order
424                      * 15 bits of INT64_MAX to avoid using imprecise floating
425                      * point values.
426                      */
427                     && d < (double)(INT64_MAX - 65535) + 65536.0
428                     && d == (int64_t)d) {
429                 *val = (int64_t)d;
430                 return 1;
431             }
432             break;
433         }
434     }
435     return 0;
436 }
437
438 int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val)
439 {
440     uint64_t u64;
441
442     if (p == NULL)
443         return 0;
444     p->return_size = 0;
445     if (p->data_type == OSSL_PARAM_INTEGER) {
446         p->return_size = sizeof(int64_t); /* Expected size */
447         if (p->data == NULL)
448             return 1;
449         switch (p->data_size) {
450         case sizeof(int32_t):
451             if (val >= INT32_MIN && val <= INT32_MAX) {
452                 p->return_size = sizeof(int32_t);
453                 *(int32_t *)p->data = (int32_t)val;
454                 return 1;
455             }
456             break;
457         case sizeof(int64_t):
458             *(int64_t *)p->data = val;
459             return 1;
460         }
461     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
462         p->return_size = sizeof(uint64_t); /* Expected size */
463         if (p->data == NULL)
464             return 1;
465         switch (p->data_size) {
466         case sizeof(uint32_t):
467             if (val <= UINT32_MAX) {
468                 p->return_size = sizeof(uint32_t);
469                 *(uint32_t *)p->data = (uint32_t)val;
470                 return 1;
471             }
472             break;
473         case sizeof(uint64_t):
474             *(uint64_t *)p->data = (uint64_t)val;
475             return 1;
476         }
477     } else if (p->data_type == OSSL_PARAM_REAL) {
478         p->return_size = sizeof(double);
479         if (p->data == NULL)
480             return 1;
481         switch (p->data_size) {
482         case sizeof(double):
483             u64 = val < 0 ? -val : val;
484             if ((u64 >> real_shift()) == 0) {
485                 *(double *)p->data = (double)val;
486                 return 1;
487             }
488             break;
489         }
490     }
491     return 0;
492 }
493
494 OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf)
495 {
496     return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t));
497 }
498
499 int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
500 {
501     int32_t i32;
502     int64_t i64;
503     double d;
504
505     if (val == NULL || p == NULL)
506         return 0;
507
508     if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
509         switch (p->data_size) {
510         case sizeof(uint32_t):
511             *val = *(const uint32_t *)p->data;
512             return 1;
513         case sizeof(uint64_t):
514             *val = *(const uint64_t *)p->data;
515             return 1;
516         }
517     } else if (p->data_type == OSSL_PARAM_INTEGER) {
518         switch (p->data_size) {
519         case sizeof(int32_t):
520             i32 = *(const int32_t *)p->data;
521             if (i32 >= 0) {
522                 *val = (uint64_t)i32;
523                 return 1;
524             }
525             break;
526         case sizeof(int64_t):
527             i64 = *(const int64_t *)p->data;
528             if (i64 >= 0) {
529                 *val = (uint64_t)i64;
530                 return 1;
531             }
532             break;
533         }
534     } else if (p->data_type == OSSL_PARAM_REAL) {
535         switch (p->data_size) {
536         case sizeof(double):
537             d = *(const double *)p->data;
538             if (d >= 0
539                     /*
540                      * By subtracting 65535 (2^16-1) we cancel the low order
541                      * 15 bits of UINT64_MAX to avoid using imprecise floating
542                      * point values.
543                      */
544                     && d < (double)(UINT64_MAX - 65535) + 65536.0
545                     && d == (uint64_t)d) {
546                 *val = (uint64_t)d;
547                 return 1;
548             }
549             break;
550         }
551     }
552     return 0;
553 }
554
555 int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val)
556 {
557     if (p == NULL)
558         return 0;
559     p->return_size = 0;
560
561     if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
562         p->return_size = sizeof(uint64_t); /* Expected size */
563         if (p->data == NULL)
564             return 1;
565         switch (p->data_size) {
566         case sizeof(uint32_t):
567             if (val <= UINT32_MAX) {
568                 p->return_size = sizeof(uint32_t);
569                 *(uint32_t *)p->data = (uint32_t)val;
570                 return 1;
571             }
572             break;
573         case sizeof(uint64_t):
574             *(uint64_t *)p->data = val;
575             return 1;
576         }
577     } else if (p->data_type == OSSL_PARAM_INTEGER) {
578         p->return_size = sizeof(int64_t); /* Expected size */
579         if (p->data == NULL)
580             return 1;
581         switch (p->data_size) {
582         case sizeof(int32_t):
583             if (val <= INT32_MAX) {
584                 p->return_size = sizeof(int32_t);
585                 *(int32_t *)p->data = (int32_t)val;
586                 return 1;
587             }
588             break;
589         case sizeof(int64_t):
590             if (val <= INT64_MAX) {
591                 *(int64_t *)p->data = (int64_t)val;
592                 return 1;
593             }
594             break;
595         }
596     } else if (p->data_type == OSSL_PARAM_REAL) {
597         p->return_size = sizeof(double);
598         switch (p->data_size) {
599         case sizeof(double):
600             if ((val >> real_shift()) == 0) {
601                 *(double *)p->data = (double)val;
602                 return 1;
603             }
604             break;
605         }
606     }
607     return 0;
608 }
609
610 OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf)
611 {
612     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
613                                 sizeof(uint64_t));
614 }
615
616 int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
617 {
618     switch (sizeof(size_t)) {
619     case sizeof(uint32_t):
620         return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
621     case sizeof(uint64_t):
622         return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
623     }
624     return 0;
625 }
626
627 int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val)
628 {
629     switch (sizeof(size_t)) {
630     case sizeof(uint32_t):
631         return OSSL_PARAM_set_uint32(p, (uint32_t)val);
632     case sizeof(uint64_t):
633         return OSSL_PARAM_set_uint64(p, (uint64_t)val);
634     }
635     return 0;
636 }
637
638 OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf)
639 {
640     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
641                                 sizeof(size_t));
642 }
643
644 int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val)
645 {
646     switch (sizeof(time_t)) {
647     case sizeof(int32_t):
648         return OSSL_PARAM_get_int32(p, (int32_t *)val);
649     case sizeof(int64_t):
650         return OSSL_PARAM_get_int64(p, (int64_t *)val);
651     }
652     return 0;
653 }
654
655 int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val)
656 {
657     switch (sizeof(time_t)) {
658     case sizeof(int32_t):
659         return OSSL_PARAM_set_int32(p, (int32_t)val);
660     case sizeof(int64_t):
661         return OSSL_PARAM_set_int64(p, (int64_t)val);
662     }
663     return 0;
664 }
665
666 OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf)
667 {
668     return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(time_t));
669 }
670
671 int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
672 {
673     BIGNUM *b;
674
675     if (val == NULL
676         || p == NULL
677         || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
678         return 0;
679
680     b = BN_native2bn(p->data, (int)p->data_size, *val);
681     if (b != NULL) {
682         *val = b;
683         return 1;
684     }
685     return 0;
686 }
687
688 int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
689 {
690     size_t bytes;
691
692     if (p == NULL)
693         return 0;
694     p->return_size = 0;
695     if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
696         return 0;
697
698     /* For the moment, only positive values are permitted */
699     if (BN_is_negative(val))
700         return 0;
701
702     bytes = (size_t)BN_num_bytes(val);
703     p->return_size = bytes;
704     if (p->data == NULL)
705         return 1;
706     if (p->data_size >= bytes) {
707         p->return_size = p->data_size;
708         return BN_bn2nativepad(val, p->data, p->data_size) >= 0;
709     }
710     return 0;
711 }
712
713 OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
714                                    size_t bsize)
715 {
716     return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER,
717                                 buf, bsize);
718 }
719
720 int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
721 {
722     int64_t i64;
723     uint64_t u64;
724
725     if (val == NULL || p == NULL)
726         return 0;
727
728     if (p->data_type == OSSL_PARAM_REAL) {
729         switch (p->data_size) {
730         case sizeof(double):
731             *val = *(const double *)p->data;
732             return 1;
733         }
734     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
735         switch (p->data_size) {
736         case sizeof(uint32_t):
737             *val = *(const uint32_t *)p->data;
738             return 1;
739         case sizeof(uint64_t):
740             u64 = *(const uint64_t *)p->data;
741             if ((u64 >> real_shift()) == 0) {
742                 *val = (double)u64;
743                 return 1;
744             }
745             break;
746         }
747     } else if (p->data_type == OSSL_PARAM_INTEGER) {
748         switch (p->data_size) {
749         case sizeof(int32_t):
750             *val = *(const int32_t *)p->data;
751             return 1;
752         case sizeof(int64_t):
753             i64 = *(const int64_t *)p->data;
754             u64 = i64 < 0 ? -i64 : i64;
755             if ((u64 >> real_shift()) == 0) {
756                 *val = 0.0 + i64;
757                 return 1;
758             }
759             break;
760         }
761     }
762     return 0;
763 }
764
765 int OSSL_PARAM_set_double(OSSL_PARAM *p, double val)
766 {
767     if (p == NULL)
768         return 0;
769     p->return_size = 0;
770
771     if (p->data_type == OSSL_PARAM_REAL) {
772         p->return_size = sizeof(double);
773         if (p->data == NULL)
774             return 1;
775         switch (p->data_size) {
776         case sizeof(double):
777             *(double *)p->data = val;
778             return 1;
779         }
780     } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER
781                && val == (ossl_uintmax_t)val) {
782         p->return_size = sizeof(double);
783         if (p->data == NULL)
784             return 1;
785         switch (p->data_size) {
786         case sizeof(uint32_t):
787             if (val >= 0 && val <= UINT32_MAX) {
788                 p->return_size = sizeof(uint32_t);
789                 *(uint32_t *)p->data = (uint32_t)val;
790                 return 1;
791             }
792             break;
793         case sizeof(uint64_t):
794             if (val >= 0
795                     /*
796                      * By subtracting 65535 (2^16-1) we cancel the low order
797                      * 15 bits of UINT64_MAX to avoid using imprecise floating
798                      * point values.
799                      */
800                     && (double)(UINT64_MAX - 65535) + 65536.0) {
801                 p->return_size = sizeof(uint64_t);
802                 *(uint64_t *)p->data = (uint64_t)val;
803                 return 1;
804             }
805             break;            }
806     } else if (p->data_type == OSSL_PARAM_INTEGER && val == (ossl_intmax_t)val) {
807         p->return_size = sizeof(double);
808         if (p->data == NULL)
809             return 1;
810         switch (p->data_size) {
811         case sizeof(int32_t):
812             if (val >= INT32_MIN && val <= INT32_MAX) {
813                 p->return_size = sizeof(int32_t);
814                 *(int32_t *)p->data = (int32_t)val;
815                 return 1;
816             }
817             break;
818         case sizeof(int64_t):
819             if (val >= INT64_MIN
820                     /*
821                      * By subtracting 65535 (2^16-1) we cancel the low order
822                      * 15 bits of INT64_MAX to avoid using imprecise floating
823                      * point values.
824                      */
825                     && val < (double)(INT64_MAX - 65535) + 65536.0) {
826                 p->return_size = sizeof(int64_t);
827                 *(int64_t *)p->data = (int64_t)val;
828                 return 1;
829             }
830             break;
831         }
832     }
833     return 0;
834 }
835
836 OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf)
837 {
838     return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double));
839 }
840
841 static int get_string_internal(const OSSL_PARAM *p, void **val, size_t max_len,
842                                size_t *used_len, unsigned int type)
843 {
844     size_t sz;
845
846     if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type)
847         return 0;
848
849     sz = p->data_size;
850
851     if (used_len != NULL)
852         *used_len = sz;
853
854     if (p->data == NULL)
855         return 0;
856
857     if (val == NULL)
858         return 1;
859
860     if (*val == NULL) {
861         char *const q = OPENSSL_malloc(sz > 0 ? sz : 1);
862
863         if (q == NULL)
864             return 0;
865         *val = q;
866         if (sz != 0)
867             memcpy(q, p->data, sz);
868         return 1;
869     }
870     if (max_len < sz)
871         return 0;
872     memcpy(*val, p->data, sz);
873     return 1;
874 }
875
876 int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len)
877 {
878     return get_string_internal(p, (void **)val, max_len, NULL,
879                                OSSL_PARAM_UTF8_STRING);
880 }
881
882 int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
883                                 size_t *used_len)
884 {
885     return get_string_internal(p, val, max_len, used_len,
886                                OSSL_PARAM_OCTET_STRING);
887 }
888
889 static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len,
890                                unsigned int type)
891 {
892     p->return_size = len;
893     if (p->data == NULL)
894         return 1;
895     if (p->data_type != type || p->data_size < len)
896         return 0;
897
898     memcpy(p->data, val, len);
899     return 1;
900 }
901
902 int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val)
903 {
904     if (p == NULL)
905         return 0;
906
907     p->return_size = 0;
908     if (val == NULL)
909         return 0;
910     return set_string_internal(p, val, strlen(val) + 1, OSSL_PARAM_UTF8_STRING);
911 }
912
913 int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val,
914                                 size_t len)
915 {
916     if (p == NULL)
917         return 0;
918
919     p->return_size = 0;
920     if (val == NULL)
921         return 0;
922     return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING);
923 }
924
925 OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
926                                             size_t bsize)
927 {
928     if (buf != NULL && bsize == 0)
929         bsize = strlen(buf) + 1;
930     return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize);
931 }
932
933 OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
934                                              size_t bsize)
935 {
936     return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize);
937 }
938
939 static int get_ptr_internal(const OSSL_PARAM *p, const void **val,
940                             size_t *used_len, unsigned int type)
941 {
942     if (val == NULL || p == NULL || p->data_type != type)
943         return 0;
944     if (used_len != NULL)
945         *used_len = p->data_size;
946     *val = *(const void **)p->data;
947     return 1;
948 }
949
950 int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val)
951 {
952     return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR);
953 }
954
955 int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
956                              size_t *used_len)
957 {
958     return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR);
959 }
960
961 static int set_ptr_internal(OSSL_PARAM *p, const void *val,
962                             unsigned int type, size_t len)
963 {
964     p->return_size = len;
965     if (p->data_type != type)
966         return 0;
967     if (p->data != NULL)
968         *(const void **)p->data = val;
969     return 1;
970 }
971
972 int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val)
973 {
974     if (p == NULL)
975         return 0;
976     p->return_size = 0;
977     return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR,
978                             val == NULL ? 0 : strlen(val) + 1);
979 }
980
981 int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
982                              size_t used_len)
983 {
984     if (p == NULL)
985         return 0;
986     p->return_size = 0;
987     return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len);
988 }
989
990 OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
991                                          size_t bsize)
992 {
993     return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, bsize);
994 }
995
996 OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
997                                           size_t bsize)
998 {
999     return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize);
1000 }
1001
1002 OSSL_PARAM OSSL_PARAM_construct_end(void)
1003 {
1004     OSSL_PARAM end = OSSL_PARAM_END;
1005
1006     return end;
1007 }
1008
1009 static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val,
1010                                    size_t *used_len, unsigned int type)
1011 {
1012     if (val == NULL || p == NULL || p->data_type != type)
1013         return 0;
1014     if (used_len != NULL)
1015         *used_len = p->data_size;
1016     *val = p->data;
1017     return 1;
1018 }
1019
1020 int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val)
1021 {
1022     return OSSL_PARAM_get_utf8_ptr(p, val)
1023         || get_string_ptr_internal(p, (const void **)val, NULL,
1024                                    OSSL_PARAM_UTF8_STRING);
1025 }
1026
1027 int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
1028                                     size_t *used_len)
1029 {
1030     return OSSL_PARAM_get_octet_ptr(p, val, used_len)
1031         || get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING);
1032 }
1033