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