xref: /third_party/openssl/crypto/params.c (revision e1051a39)
1/*
2 * Copyright 2019-2023 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#include "internal/endian.h"
16
17/*
18 * Return the number of bits in the mantissa of a double.  This is used to
19 * shift a larger integral value to determine if it will exactly fit into a
20 * double.
21 */
22static unsigned int real_shift(void)
23{
24    return sizeof(double) == 4 ? 24 : 53;
25}
26
27OSSL_PARAM *OSSL_PARAM_locate(OSSL_PARAM *p, const char *key)
28{
29    if (p != NULL && key != NULL)
30        for (; p->key != NULL; p++)
31            if (strcmp(key, p->key) == 0)
32                return p;
33    return NULL;
34}
35
36const OSSL_PARAM *OSSL_PARAM_locate_const(const OSSL_PARAM *p, const char *key)
37{
38    return OSSL_PARAM_locate((OSSL_PARAM *)p, key);
39}
40
41static OSSL_PARAM ossl_param_construct(const char *key, unsigned int data_type,
42                                       void *data, size_t data_size)
43{
44    OSSL_PARAM res;
45
46    res.key = key;
47    res.data_type = data_type;
48    res.data = data;
49    res.data_size = data_size;
50    res.return_size = OSSL_PARAM_UNMODIFIED;
51    return res;
52}
53
54int OSSL_PARAM_modified(const OSSL_PARAM *p)
55{
56    return p != NULL && p->return_size != OSSL_PARAM_UNMODIFIED;
57}
58
59void OSSL_PARAM_set_all_unmodified(OSSL_PARAM *p)
60{
61    if (p != NULL)
62        while (p->key != NULL)
63            p++->return_size = OSSL_PARAM_UNMODIFIED;
64}
65
66/* Return non-zero if the signed number is negative */
67static int is_negative(const void *number, size_t s)
68{
69    const unsigned char *n = number;
70    DECLARE_IS_ENDIAN;
71
72    return 0x80 & (IS_BIG_ENDIAN ? n[0] : n[s - 1]);
73}
74
75/* Check that all the bytes specified match the expected sign byte */
76static int check_sign_bytes(const unsigned char *p, size_t n, unsigned char s)
77{
78    size_t i;
79
80    for (i = 0; i < n; i++)
81        if (p[i] != s)
82            return 0;
83    return 1;
84}
85
86/*
87 * Copy an integer to another integer.
88 * Handle different length integers and signed and unsigned integers.
89 * Both integers are in native byte ordering.
90 */
91static int copy_integer(unsigned char *dest, size_t dest_len,
92                        const unsigned char *src, size_t src_len,
93                        unsigned char pad, int signed_int)
94{
95    size_t n;
96    DECLARE_IS_ENDIAN;
97
98    if (IS_BIG_ENDIAN) {
99        if (src_len < dest_len) {
100            n = dest_len - src_len;
101            memset(dest, pad, n);
102            memcpy(dest + n, src, src_len);
103        } else {
104            n = src_len - dest_len;
105            if (!check_sign_bytes(src, n, pad)
106                    /*
107                     * Shortening a signed value must retain the correct sign.
108                     * Avoiding this kind of thing: -253 = 0xff03 -> 0x03 = 3
109                     */
110                    || (signed_int && ((pad ^ src[n]) & 0x80) != 0))
111                return 0;
112            memcpy(dest, src + n, dest_len);
113        }
114    } else /* IS_LITTLE_ENDIAN */ {
115        if (src_len < dest_len) {
116            n = dest_len - src_len;
117            memset(dest + src_len, pad, n);
118            memcpy(dest, src, src_len);
119        } else {
120            n = src_len - dest_len;
121            if (!check_sign_bytes(src + dest_len, n, pad)
122                    /*
123                     * Shortening a signed value must retain the correct sign.
124                     * Avoiding this kind of thing: 130 = 0x0082 -> 0x82 = -126
125                     */
126                    || (signed_int && ((pad ^ src[dest_len - 1]) & 0x80) != 0))
127                return 0;
128            memcpy(dest, src, dest_len);
129        }
130    }
131    return 1;
132}
133
134/* Copy a signed number to a signed number of possibly different length */
135static int signed_from_signed(void *dest, size_t dest_len,
136                              const void *src, size_t src_len)
137{
138    return copy_integer(dest, dest_len, src, src_len,
139                        is_negative(src, src_len) ? 0xff : 0, 1);
140}
141
142/* Copy an unsigned number to a signed number of possibly different length */
143static int signed_from_unsigned(void *dest, size_t dest_len,
144                                const void *src, size_t src_len)
145{
146    return copy_integer(dest, dest_len, src, src_len, 0, 1);
147}
148
149/* Copy a signed number to an unsigned number of possibly different length */
150static int unsigned_from_signed(void *dest, size_t dest_len,
151                                const void *src, size_t src_len)
152{
153    if (is_negative(src, src_len))
154        return 0;
155    return copy_integer(dest, dest_len, src, src_len, 0, 0);
156}
157
158/* Copy an unsigned number to an unsigned number of possibly different length */
159static int unsigned_from_unsigned(void *dest, size_t dest_len,
160                                  const void *src, size_t src_len)
161{
162    return copy_integer(dest, dest_len, src, src_len, 0, 0);
163}
164
165/* General purpose get integer parameter call that handles odd sizes */
166static int general_get_int(const OSSL_PARAM *p, void *val, size_t val_size)
167{
168    if (p->data_type == OSSL_PARAM_INTEGER)
169        return signed_from_signed(val, val_size, p->data, p->data_size);
170    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
171        return signed_from_unsigned(val, val_size, p->data, p->data_size);
172    return 0;
173}
174
175/* General purpose set integer parameter call that handles odd sizes */
176static int general_set_int(OSSL_PARAM *p, void *val, size_t val_size)
177{
178    int r = 0;
179
180    p->return_size = val_size; /* Expected size */
181    if (p->data == NULL)
182        return 1;
183    if (p->data_type == OSSL_PARAM_INTEGER)
184        r = signed_from_signed(p->data, p->data_size, val, val_size);
185    else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
186        r = unsigned_from_signed(p->data, p->data_size, val, val_size);
187    p->return_size = r ? p->data_size : val_size;
188    return r;
189}
190
191/* General purpose get unsigned integer parameter call that handles odd sizes */
192static int general_get_uint(const OSSL_PARAM *p, void *val, size_t val_size)
193{
194    if (p->data_type == OSSL_PARAM_INTEGER)
195        return unsigned_from_signed(val, val_size, p->data, p->data_size);
196    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
197        return unsigned_from_unsigned(val, val_size, p->data, p->data_size);
198    return 0;
199}
200
201/* General purpose set unsigned integer parameter call that handles odd sizes */
202static int general_set_uint(OSSL_PARAM *p, void *val, size_t val_size)
203{
204    int r = 0;
205
206    p->return_size = val_size; /* Expected size */
207    if (p->data == NULL)
208        return 1;
209    if (p->data_type == OSSL_PARAM_INTEGER)
210        r = signed_from_unsigned(p->data, p->data_size, val, val_size);
211    else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER)
212        r = unsigned_from_unsigned(p->data, p->data_size, val, val_size);
213    p->return_size = r ? p->data_size : val_size;
214    return r;
215}
216
217int OSSL_PARAM_get_int(const OSSL_PARAM *p, int *val)
218{
219#ifndef OPENSSL_SMALL_FOOTPRINT
220    switch (sizeof(int)) {
221    case sizeof(int32_t):
222        return OSSL_PARAM_get_int32(p, (int32_t *)val);
223    case sizeof(int64_t):
224        return OSSL_PARAM_get_int64(p, (int64_t *)val);
225    }
226#endif
227    return general_get_int(p, val, sizeof(*val));
228}
229
230int OSSL_PARAM_set_int(OSSL_PARAM *p, int val)
231{
232#ifndef OPENSSL_SMALL_FOOTPRINT
233    switch (sizeof(int)) {
234    case sizeof(int32_t):
235        return OSSL_PARAM_set_int32(p, (int32_t)val);
236    case sizeof(int64_t):
237        return OSSL_PARAM_set_int64(p, (int64_t)val);
238    }
239#endif
240    return general_set_int(p, &val, sizeof(val));
241}
242
243OSSL_PARAM OSSL_PARAM_construct_int(const char *key, int *buf)
244{
245    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int));
246}
247
248int OSSL_PARAM_get_uint(const OSSL_PARAM *p, unsigned int *val)
249{
250#ifndef OPENSSL_SMALL_FOOTPRINT
251    switch (sizeof(unsigned int)) {
252    case sizeof(uint32_t):
253        return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
254    case sizeof(uint64_t):
255        return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
256    }
257#endif
258    return general_get_uint(p, val, sizeof(*val));
259}
260
261int OSSL_PARAM_set_uint(OSSL_PARAM *p, unsigned int val)
262{
263#ifndef OPENSSL_SMALL_FOOTPRINT
264    switch (sizeof(unsigned int)) {
265    case sizeof(uint32_t):
266        return OSSL_PARAM_set_uint32(p, (uint32_t)val);
267    case sizeof(uint64_t):
268        return OSSL_PARAM_set_uint64(p, (uint64_t)val);
269    }
270#endif
271    return general_set_uint(p, &val, sizeof(val));
272}
273
274OSSL_PARAM OSSL_PARAM_construct_uint(const char *key, unsigned int *buf)
275{
276    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
277                                sizeof(unsigned int));
278}
279
280int OSSL_PARAM_get_long(const OSSL_PARAM *p, long int *val)
281{
282#ifndef OPENSSL_SMALL_FOOTPRINT
283    switch (sizeof(long int)) {
284    case sizeof(int32_t):
285        return OSSL_PARAM_get_int32(p, (int32_t *)val);
286    case sizeof(int64_t):
287        return OSSL_PARAM_get_int64(p, (int64_t *)val);
288    }
289#endif
290    return general_get_int(p, val, sizeof(*val));
291}
292
293int OSSL_PARAM_set_long(OSSL_PARAM *p, long int val)
294{
295#ifndef OPENSSL_SMALL_FOOTPRINT
296    switch (sizeof(long int)) {
297    case sizeof(int32_t):
298        return OSSL_PARAM_set_int32(p, (int32_t)val);
299    case sizeof(int64_t):
300        return OSSL_PARAM_set_int64(p, (int64_t)val);
301    }
302#endif
303    return general_set_int(p, &val, sizeof(val));
304}
305
306OSSL_PARAM OSSL_PARAM_construct_long(const char *key, long int *buf)
307{
308    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(long int));
309}
310
311int OSSL_PARAM_get_ulong(const OSSL_PARAM *p, unsigned long int *val)
312{
313#ifndef OPENSSL_SMALL_FOOTPRINT
314    switch (sizeof(unsigned long int)) {
315    case sizeof(uint32_t):
316        return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
317    case sizeof(uint64_t):
318        return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
319    }
320#endif
321    return general_get_uint(p, val, sizeof(*val));
322}
323
324int OSSL_PARAM_set_ulong(OSSL_PARAM *p, unsigned long int val)
325{
326#ifndef OPENSSL_SMALL_FOOTPRINT
327    switch (sizeof(unsigned long int)) {
328    case sizeof(uint32_t):
329        return OSSL_PARAM_set_uint32(p, (uint32_t)val);
330    case sizeof(uint64_t):
331        return OSSL_PARAM_set_uint64(p, (uint64_t)val);
332    }
333#endif
334    return general_set_uint(p, &val, sizeof(val));
335}
336
337OSSL_PARAM OSSL_PARAM_construct_ulong(const char *key, unsigned long int *buf)
338{
339    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
340                                sizeof(unsigned long int));
341}
342
343int OSSL_PARAM_get_int32(const OSSL_PARAM *p, int32_t *val)
344{
345    double d;
346
347    if (val == NULL || p == NULL )
348        return 0;
349
350    if (p->data_type == OSSL_PARAM_INTEGER) {
351#ifndef OPENSSL_SMALL_FOOTPRINT
352        int64_t i64;
353
354        switch (p->data_size) {
355        case sizeof(int32_t):
356            *val = *(const int32_t *)p->data;
357            return 1;
358        case sizeof(int64_t):
359            i64 = *(const int64_t *)p->data;
360            if (i64 >= INT32_MIN && i64 <= INT32_MAX) {
361                *val = (int32_t)i64;
362                return 1;
363            }
364            return 0;
365        }
366#endif
367        return general_get_int(p, val, sizeof(*val));
368
369    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
370#ifndef OPENSSL_SMALL_FOOTPRINT
371        uint32_t u32;
372        uint64_t u64;
373
374        switch (p->data_size) {
375        case sizeof(uint32_t):
376            u32 = *(const uint32_t *)p->data;
377            if (u32 <= INT32_MAX) {
378                *val = (int32_t)u32;
379                return 1;
380            }
381            return 0;
382        case sizeof(uint64_t):
383            u64 = *(const uint64_t *)p->data;
384            if (u64 <= INT32_MAX) {
385                *val = (int32_t)u64;
386                return 1;
387            }
388            return 0;
389        }
390#endif
391        return general_get_int(p, val, sizeof(*val));
392
393    } else if (p->data_type == OSSL_PARAM_REAL) {
394        switch (p->data_size) {
395        case sizeof(double):
396            d = *(const double *)p->data;
397            if (d >= INT32_MIN && d <= INT32_MAX && d == (int32_t)d) {
398                *val = (int32_t)d;
399                return 1;
400            }
401            break;
402        }
403    }
404    return 0;
405}
406
407int OSSL_PARAM_set_int32(OSSL_PARAM *p, int32_t val)
408{
409    if (p == NULL)
410        return 0;
411    p->return_size = 0;
412    if (p->data_type == OSSL_PARAM_INTEGER) {
413#ifndef OPENSSL_SMALL_FOOTPRINT
414        p->return_size = sizeof(int32_t); /* Minimum expected size */
415        if (p->data == NULL)
416            return 1;
417        switch (p->data_size) {
418        case sizeof(int32_t):
419            *(int32_t *)p->data = val;
420            return 1;
421        case sizeof(int64_t):
422            p->return_size = sizeof(int64_t);
423            *(int64_t *)p->data = (int64_t)val;
424            return 1;
425        }
426#endif
427        return general_set_int(p, &val, sizeof(val));
428    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
429#ifndef OPENSSL_SMALL_FOOTPRINT
430        p->return_size = sizeof(uint32_t); /* Minimum expected size */
431        if (p->data == NULL)
432            return 1;
433        switch (p->data_size) {
434        case sizeof(uint32_t):
435            *(uint32_t *)p->data = (uint32_t)val;
436            return 1;
437        case sizeof(uint64_t):
438            p->return_size = sizeof(uint64_t);
439            *(uint64_t *)p->data = (uint64_t)val;
440            return 1;
441        }
442#endif
443        return general_set_int(p, &val, sizeof(val));
444    } else if (p->data_type == OSSL_PARAM_REAL) {
445        p->return_size = sizeof(double);
446        if (p->data == NULL)
447            return 1;
448        switch (p->data_size) {
449        case sizeof(double):
450            *(double *)p->data = (double)val;
451            return 1;
452        }
453    }
454    return 0;
455}
456
457OSSL_PARAM OSSL_PARAM_construct_int32(const char *key, int32_t *buf)
458{
459    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf,
460                                sizeof(int32_t));
461}
462
463int OSSL_PARAM_get_uint32(const OSSL_PARAM *p, uint32_t *val)
464{
465    double d;
466
467    if (val == NULL || p == NULL)
468        return 0;
469
470    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
471#ifndef OPENSSL_SMALL_FOOTPRINT
472        uint64_t u64;
473
474        switch (p->data_size) {
475        case sizeof(uint32_t):
476            *val = *(const uint32_t *)p->data;
477            return 1;
478        case sizeof(uint64_t):
479            u64 = *(const uint64_t *)p->data;
480            if (u64 <= UINT32_MAX) {
481                *val = (uint32_t)u64;
482                return 1;
483            }
484            return 0;
485        }
486#endif
487        return general_get_uint(p, val, sizeof(*val));
488    } else if (p->data_type == OSSL_PARAM_INTEGER) {
489#ifndef OPENSSL_SMALL_FOOTPRINT
490        int32_t i32;
491        int64_t i64;
492
493        switch (p->data_size) {
494        case sizeof(int32_t):
495            i32 = *(const int32_t *)p->data;
496            if (i32 >= 0) {
497                *val = i32;
498                return 1;
499            }
500            return 0;
501        case sizeof(int64_t):
502            i64 = *(const int64_t *)p->data;
503            if (i64 >= 0 && i64 <= UINT32_MAX) {
504                *val = (uint32_t)i64;
505                return 1;
506            }
507            return 0;
508        }
509#endif
510        return general_get_uint(p, val, sizeof(*val));
511    } else if (p->data_type == OSSL_PARAM_REAL) {
512        switch (p->data_size) {
513        case sizeof(double):
514            d = *(const double *)p->data;
515            if (d >= 0 && d <= UINT32_MAX && d == (uint32_t)d) {
516                *val = (uint32_t)d;
517                return 1;
518            }
519            break;
520        }
521    }
522    return 0;
523}
524
525int OSSL_PARAM_set_uint32(OSSL_PARAM *p, uint32_t val)
526{
527    if (p == NULL)
528        return 0;
529    p->return_size = 0;
530
531    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
532#ifndef OPENSSL_SMALL_FOOTPRINT
533        p->return_size = sizeof(uint32_t); /* Minimum expected size */
534        if (p->data == NULL)
535            return 1;
536        switch (p->data_size) {
537        case sizeof(uint32_t):
538            *(uint32_t *)p->data = val;
539            return 1;
540        case sizeof(uint64_t):
541            p->return_size = sizeof(uint64_t);
542            *(uint64_t *)p->data = val;
543            return 1;
544        }
545#endif
546        return general_set_uint(p, &val, sizeof(val));
547    } else if (p->data_type == OSSL_PARAM_INTEGER) {
548#ifndef OPENSSL_SMALL_FOOTPRINT
549        p->return_size = sizeof(int32_t); /* Minimum expected size */
550        if (p->data == NULL)
551            return 1;
552        switch (p->data_size) {
553        case sizeof(int32_t):
554            if (val <= INT32_MAX) {
555                *(int32_t *)p->data = (int32_t)val;
556                return 1;
557            }
558            return 0;
559        case sizeof(int64_t):
560            p->return_size = sizeof(int64_t);
561            *(int64_t *)p->data = (int64_t)val;
562            return 1;
563        }
564#endif
565        return general_set_uint(p, &val, sizeof(val));
566    } else if (p->data_type == OSSL_PARAM_REAL) {
567        p->return_size = sizeof(double);
568        if (p->data == NULL)
569            return 1;
570        switch (p->data_size) {
571        case sizeof(double):
572            *(double *)p->data = (double)val;
573            return 1;
574        }
575    }
576    return 0;
577}
578
579OSSL_PARAM OSSL_PARAM_construct_uint32(const char *key, uint32_t *buf)
580{
581    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
582                                sizeof(uint32_t));
583}
584
585int OSSL_PARAM_get_int64(const OSSL_PARAM *p, int64_t *val)
586{
587    double d;
588
589    if (val == NULL || p == NULL )
590        return 0;
591
592    if (p->data_type == OSSL_PARAM_INTEGER) {
593#ifndef OPENSSL_SMALL_FOOTPRINT
594        switch (p->data_size) {
595        case sizeof(int32_t):
596            *val = *(const int32_t *)p->data;
597            return 1;
598        case sizeof(int64_t):
599            *val = *(const int64_t *)p->data;
600            return 1;
601        }
602#endif
603        return general_get_int(p, val, sizeof(*val));
604    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
605#ifndef OPENSSL_SMALL_FOOTPRINT
606        uint64_t u64;
607
608        switch (p->data_size) {
609        case sizeof(uint32_t):
610            *val = *(const uint32_t *)p->data;
611            return 1;
612        case sizeof(uint64_t):
613            u64 = *(const uint64_t *)p->data;
614            if (u64 <= INT64_MAX) {
615                *val = (int64_t)u64;
616                return 1;
617            }
618            return 0;
619        }
620#endif
621        return general_get_int(p, val, sizeof(*val));
622    } else if (p->data_type == OSSL_PARAM_REAL) {
623        switch (p->data_size) {
624        case sizeof(double):
625            d = *(const double *)p->data;
626            if (d >= INT64_MIN
627                    /*
628                     * By subtracting 65535 (2^16-1) we cancel the low order
629                     * 15 bits of INT64_MAX to avoid using imprecise floating
630                     * point values.
631                     */
632                    && d < (double)(INT64_MAX - 65535) + 65536.0
633                    && d == (int64_t)d) {
634                *val = (int64_t)d;
635                return 1;
636            }
637            break;
638        }
639    }
640    return 0;
641}
642
643int OSSL_PARAM_set_int64(OSSL_PARAM *p, int64_t val)
644{
645    uint64_t u64;
646
647    if (p == NULL)
648        return 0;
649    p->return_size = 0;
650    if (p->data_type == OSSL_PARAM_INTEGER) {
651#ifndef OPENSSL_SMALL_FOOTPRINT
652        p->return_size = sizeof(int64_t); /* Expected size */
653        if (p->data == NULL)
654            return 1;
655        switch (p->data_size) {
656        case sizeof(int32_t):
657            if (val >= INT32_MIN && val <= INT32_MAX) {
658                p->return_size = sizeof(int32_t);
659                *(int32_t *)p->data = (int32_t)val;
660                return 1;
661            }
662            return 0;
663        case sizeof(int64_t):
664            *(int64_t *)p->data = val;
665            return 1;
666        }
667#endif
668        return general_set_int(p, &val, sizeof(val));
669    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER && val >= 0) {
670#ifndef OPENSSL_SMALL_FOOTPRINT
671        p->return_size = sizeof(uint64_t); /* Expected size */
672        if (p->data == NULL)
673            return 1;
674        switch (p->data_size) {
675        case sizeof(uint32_t):
676            if (val <= UINT32_MAX) {
677                p->return_size = sizeof(uint32_t);
678                *(uint32_t *)p->data = (uint32_t)val;
679                return 1;
680            }
681            return 0;
682        case sizeof(uint64_t):
683            *(uint64_t *)p->data = (uint64_t)val;
684            return 1;
685        }
686#endif
687        return general_set_int(p, &val, sizeof(val));
688    } else if (p->data_type == OSSL_PARAM_REAL) {
689        p->return_size = sizeof(double);
690        if (p->data == NULL)
691            return 1;
692        switch (p->data_size) {
693        case sizeof(double):
694            u64 = val < 0 ? -val : val;
695            if ((u64 >> real_shift()) == 0) {
696                *(double *)p->data = (double)val;
697                return 1;
698            }
699            break;
700        }
701    }
702    return 0;
703}
704
705OSSL_PARAM OSSL_PARAM_construct_int64(const char *key, int64_t *buf)
706{
707    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(int64_t));
708}
709
710int OSSL_PARAM_get_uint64(const OSSL_PARAM *p, uint64_t *val)
711{
712    double d;
713
714    if (val == NULL || p == NULL)
715        return 0;
716
717    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
718#ifndef OPENSSL_SMALL_FOOTPRINT
719        switch (p->data_size) {
720        case sizeof(uint32_t):
721            *val = *(const uint32_t *)p->data;
722            return 1;
723        case sizeof(uint64_t):
724            *val = *(const uint64_t *)p->data;
725            return 1;
726        }
727#endif
728        return general_get_uint(p, val, sizeof(*val));
729    } else if (p->data_type == OSSL_PARAM_INTEGER) {
730#ifndef OPENSSL_SMALL_FOOTPRINT
731        int32_t i32;
732        int64_t i64;
733
734        switch (p->data_size) {
735        case sizeof(int32_t):
736            i32 = *(const int32_t *)p->data;
737            if (i32 >= 0) {
738                *val = (uint64_t)i32;
739                return 1;
740            }
741            return 0;
742        case sizeof(int64_t):
743            i64 = *(const int64_t *)p->data;
744            if (i64 >= 0) {
745                *val = (uint64_t)i64;
746                return 1;
747            }
748            return 0;
749        }
750#endif
751        return general_get_uint(p, val, sizeof(*val));
752    } else if (p->data_type == OSSL_PARAM_REAL) {
753        switch (p->data_size) {
754        case sizeof(double):
755            d = *(const double *)p->data;
756            if (d >= 0
757                    /*
758                     * By subtracting 65535 (2^16-1) we cancel the low order
759                     * 15 bits of UINT64_MAX to avoid using imprecise floating
760                     * point values.
761                     */
762                    && d < (double)(UINT64_MAX - 65535) + 65536.0
763                    && d == (uint64_t)d) {
764                *val = (uint64_t)d;
765                return 1;
766            }
767            break;
768        }
769    }
770    return 0;
771}
772
773int OSSL_PARAM_set_uint64(OSSL_PARAM *p, uint64_t val)
774{
775    if (p == NULL)
776        return 0;
777    p->return_size = 0;
778
779    if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
780#ifndef OPENSSL_SMALL_FOOTPRINT
781        p->return_size = sizeof(uint64_t); /* Expected size */
782        if (p->data == NULL)
783            return 1;
784        switch (p->data_size) {
785        case sizeof(uint32_t):
786            if (val <= UINT32_MAX) {
787                p->return_size = sizeof(uint32_t);
788                *(uint32_t *)p->data = (uint32_t)val;
789                return 1;
790            }
791            return 0;
792        case sizeof(uint64_t):
793            *(uint64_t *)p->data = val;
794            return 1;
795        }
796#endif
797        return general_set_uint(p, &val, sizeof(val));
798    } else if (p->data_type == OSSL_PARAM_INTEGER) {
799#ifndef OPENSSL_SMALL_FOOTPRINT
800        p->return_size = sizeof(int64_t); /* Expected size */
801        if (p->data == NULL)
802            return 1;
803        switch (p->data_size) {
804        case sizeof(int32_t):
805            if (val <= INT32_MAX) {
806                p->return_size = sizeof(int32_t);
807                *(int32_t *)p->data = (int32_t)val;
808                return 1;
809            }
810            return 0;
811        case sizeof(int64_t):
812            if (val <= INT64_MAX) {
813                *(int64_t *)p->data = (int64_t)val;
814                return 1;
815            }
816            return 0;
817        }
818#endif
819        return general_set_uint(p, &val, sizeof(val));
820    } else if (p->data_type == OSSL_PARAM_REAL) {
821        p->return_size = sizeof(double);
822        switch (p->data_size) {
823        case sizeof(double):
824            if ((val >> real_shift()) == 0) {
825                *(double *)p->data = (double)val;
826                return 1;
827            }
828            break;
829        }
830    }
831    return 0;
832}
833
834OSSL_PARAM OSSL_PARAM_construct_uint64(const char *key, uint64_t *buf)
835{
836    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
837                                sizeof(uint64_t));
838}
839
840int OSSL_PARAM_get_size_t(const OSSL_PARAM *p, size_t *val)
841{
842#ifndef OPENSSL_SMALL_FOOTPRINT
843    switch (sizeof(size_t)) {
844    case sizeof(uint32_t):
845        return OSSL_PARAM_get_uint32(p, (uint32_t *)val);
846    case sizeof(uint64_t):
847        return OSSL_PARAM_get_uint64(p, (uint64_t *)val);
848    }
849#endif
850    return general_get_uint(p, val, sizeof(*val));
851}
852
853int OSSL_PARAM_set_size_t(OSSL_PARAM *p, size_t val)
854{
855#ifndef OPENSSL_SMALL_FOOTPRINT
856    switch (sizeof(size_t)) {
857    case sizeof(uint32_t):
858        return OSSL_PARAM_set_uint32(p, (uint32_t)val);
859    case sizeof(uint64_t):
860        return OSSL_PARAM_set_uint64(p, (uint64_t)val);
861    }
862#endif
863    return general_set_uint(p, &val, sizeof(val));
864}
865
866OSSL_PARAM OSSL_PARAM_construct_size_t(const char *key, size_t *buf)
867{
868    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER, buf,
869                                sizeof(size_t));
870}
871
872int OSSL_PARAM_get_time_t(const OSSL_PARAM *p, time_t *val)
873{
874#ifndef OPENSSL_SMALL_FOOTPRINT
875    switch (sizeof(time_t)) {
876    case sizeof(int32_t):
877        return OSSL_PARAM_get_int32(p, (int32_t *)val);
878    case sizeof(int64_t):
879        return OSSL_PARAM_get_int64(p, (int64_t *)val);
880    }
881#endif
882    return general_get_int(p, val, sizeof(*val));
883}
884
885int OSSL_PARAM_set_time_t(OSSL_PARAM *p, time_t val)
886{
887#ifndef OPENSSL_SMALL_FOOTPRINT
888    switch (sizeof(time_t)) {
889    case sizeof(int32_t):
890        return OSSL_PARAM_set_int32(p, (int32_t)val);
891    case sizeof(int64_t):
892        return OSSL_PARAM_set_int64(p, (int64_t)val);
893    }
894#endif
895    return general_set_int(p, &val, sizeof(val));
896}
897
898OSSL_PARAM OSSL_PARAM_construct_time_t(const char *key, time_t *buf)
899{
900    return ossl_param_construct(key, OSSL_PARAM_INTEGER, buf, sizeof(time_t));
901}
902
903int OSSL_PARAM_get_BN(const OSSL_PARAM *p, BIGNUM **val)
904{
905    BIGNUM *b;
906
907    if (val == NULL
908        || p == NULL
909        || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
910        return 0;
911
912    b = BN_native2bn(p->data, (int)p->data_size, *val);
913    if (b != NULL) {
914        *val = b;
915        return 1;
916    }
917    return 0;
918}
919
920int OSSL_PARAM_set_BN(OSSL_PARAM *p, const BIGNUM *val)
921{
922    size_t bytes;
923
924    if (p == NULL)
925        return 0;
926    p->return_size = 0;
927    if (val == NULL || p->data_type != OSSL_PARAM_UNSIGNED_INTEGER)
928        return 0;
929
930    /* For the moment, only positive values are permitted */
931    if (BN_is_negative(val))
932        return 0;
933
934    bytes = (size_t)BN_num_bytes(val);
935    /* We make sure that at least one byte is used, so zero is properly set */
936    if (bytes == 0)
937        bytes++;
938
939    p->return_size = bytes;
940    if (p->data == NULL)
941        return 1;
942    if (p->data_size >= bytes) {
943        p->return_size = p->data_size;
944        return BN_bn2nativepad(val, p->data, p->data_size) >= 0;
945    }
946    return 0;
947}
948
949OSSL_PARAM OSSL_PARAM_construct_BN(const char *key, unsigned char *buf,
950                                   size_t bsize)
951{
952    return ossl_param_construct(key, OSSL_PARAM_UNSIGNED_INTEGER,
953                                buf, bsize);
954}
955
956int OSSL_PARAM_get_double(const OSSL_PARAM *p, double *val)
957{
958    int64_t i64;
959    uint64_t u64;
960
961    if (val == NULL || p == NULL)
962        return 0;
963
964    if (p->data_type == OSSL_PARAM_REAL) {
965        switch (p->data_size) {
966        case sizeof(double):
967            *val = *(const double *)p->data;
968            return 1;
969        }
970    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER) {
971        switch (p->data_size) {
972        case sizeof(uint32_t):
973            *val = *(const uint32_t *)p->data;
974            return 1;
975        case sizeof(uint64_t):
976            u64 = *(const uint64_t *)p->data;
977            if ((u64 >> real_shift()) == 0) {
978                *val = (double)u64;
979                return 1;
980            }
981            break;
982        }
983    } else if (p->data_type == OSSL_PARAM_INTEGER) {
984        switch (p->data_size) {
985        case sizeof(int32_t):
986            *val = *(const int32_t *)p->data;
987            return 1;
988        case sizeof(int64_t):
989            i64 = *(const int64_t *)p->data;
990            u64 = i64 < 0 ? -i64 : i64;
991            if ((u64 >> real_shift()) == 0) {
992                *val = 0.0 + i64;
993                return 1;
994            }
995            break;
996        }
997    }
998    return 0;
999}
1000
1001int OSSL_PARAM_set_double(OSSL_PARAM *p, double val)
1002{
1003    if (p == NULL)
1004        return 0;
1005    p->return_size = 0;
1006
1007    if (p->data_type == OSSL_PARAM_REAL) {
1008        p->return_size = sizeof(double);
1009        if (p->data == NULL)
1010            return 1;
1011        switch (p->data_size) {
1012        case sizeof(double):
1013            *(double *)p->data = val;
1014            return 1;
1015        }
1016    } else if (p->data_type == OSSL_PARAM_UNSIGNED_INTEGER
1017               && val == (uint64_t)val) {
1018        p->return_size = sizeof(double);
1019        if (p->data == NULL)
1020            return 1;
1021        switch (p->data_size) {
1022        case sizeof(uint32_t):
1023            if (val >= 0 && val <= UINT32_MAX) {
1024                p->return_size = sizeof(uint32_t);
1025                *(uint32_t *)p->data = (uint32_t)val;
1026                return 1;
1027            }
1028            break;
1029        case sizeof(uint64_t):
1030            if (val >= 0
1031                    /*
1032                     * By subtracting 65535 (2^16-1) we cancel the low order
1033                     * 15 bits of UINT64_MAX to avoid using imprecise floating
1034                     * point values.
1035                     */
1036                    && val < (double)(UINT64_MAX - 65535) + 65536.0) {
1037                p->return_size = sizeof(uint64_t);
1038                *(uint64_t *)p->data = (uint64_t)val;
1039                return 1;
1040            }
1041            break;            }
1042    } else if (p->data_type == OSSL_PARAM_INTEGER && val == (int64_t)val) {
1043        p->return_size = sizeof(double);
1044        if (p->data == NULL)
1045            return 1;
1046        switch (p->data_size) {
1047        case sizeof(int32_t):
1048            if (val >= INT32_MIN && val <= INT32_MAX) {
1049                p->return_size = sizeof(int32_t);
1050                *(int32_t *)p->data = (int32_t)val;
1051                return 1;
1052            }
1053            break;
1054        case sizeof(int64_t):
1055            if (val >= INT64_MIN
1056                    /*
1057                     * By subtracting 65535 (2^16-1) we cancel the low order
1058                     * 15 bits of INT64_MAX to avoid using imprecise floating
1059                     * point values.
1060                     */
1061                    && val < (double)(INT64_MAX - 65535) + 65536.0) {
1062                p->return_size = sizeof(int64_t);
1063                *(int64_t *)p->data = (int64_t)val;
1064                return 1;
1065            }
1066            break;
1067        }
1068    }
1069    return 0;
1070}
1071
1072OSSL_PARAM OSSL_PARAM_construct_double(const char *key, double *buf)
1073{
1074    return ossl_param_construct(key, OSSL_PARAM_REAL, buf, sizeof(double));
1075}
1076
1077static int get_string_internal(const OSSL_PARAM *p, void **val,
1078                               size_t *max_len, size_t *used_len,
1079                               unsigned int type)
1080{
1081    size_t sz, alloc_sz;
1082
1083    if ((val == NULL && used_len == NULL) || p == NULL || p->data_type != type)
1084        return 0;
1085
1086    sz = p->data_size;
1087    /*
1088     * If the input size is 0, or the input string needs NUL byte
1089     * termination, allocate an extra byte.
1090     */
1091    alloc_sz = sz + (type == OSSL_PARAM_UTF8_STRING || sz == 0);
1092
1093    if (used_len != NULL)
1094        *used_len = sz;
1095
1096    if (p->data == NULL)
1097        return 0;
1098
1099    if (val == NULL)
1100        return 1;
1101
1102    if (*val == NULL) {
1103        char *const q = OPENSSL_malloc(alloc_sz);
1104
1105        if (q == NULL)
1106            return 0;
1107        *val = q;
1108        *max_len = alloc_sz;
1109    }
1110
1111    if (*max_len < sz)
1112        return 0;
1113    memcpy(*val, p->data, sz);
1114    return 1;
1115}
1116
1117int OSSL_PARAM_get_utf8_string(const OSSL_PARAM *p, char **val, size_t max_len)
1118{
1119    int ret = get_string_internal(p, (void **)val, &max_len, NULL,
1120                                  OSSL_PARAM_UTF8_STRING);
1121
1122    /*
1123     * We try to ensure that the copied string is terminated with a
1124     * NUL byte.  That should be easy, just place a NUL byte at
1125     * |((char*)*val)[p->data_size]|.
1126     * Unfortunately, we have seen cases where |p->data_size| doesn't
1127     * correctly reflect the length of the string, and just happens
1128     * to be out of bounds according to |max_len|, so in that case, we
1129     * make the extra step of trying to find the true length of the
1130     * string that |p->data| points at, and use that as an index to
1131     * place the NUL byte in |*val|.
1132     */
1133    size_t data_length = p->data_size;
1134
1135    if (ret == 0)
1136        return 0;
1137    if (data_length >= max_len)
1138        data_length = OPENSSL_strnlen(p->data, data_length);
1139    if (data_length >= max_len)
1140        return 0;            /* No space for a terminating NUL byte */
1141    (*val)[data_length] = '\0';
1142
1143    return ret;
1144}
1145
1146int OSSL_PARAM_get_octet_string(const OSSL_PARAM *p, void **val, size_t max_len,
1147                                size_t *used_len)
1148{
1149    return get_string_internal(p, val, &max_len, used_len,
1150                               OSSL_PARAM_OCTET_STRING);
1151}
1152
1153static int set_string_internal(OSSL_PARAM *p, const void *val, size_t len,
1154                               unsigned int type)
1155{
1156    p->return_size = len;
1157    if (p->data == NULL)
1158        return 1;
1159    if (p->data_type != type || p->data_size < len)
1160        return 0;
1161
1162    memcpy(p->data, val, len);
1163    /* If possible within the size of p->data, add a NUL terminator byte */
1164    if (type == OSSL_PARAM_UTF8_STRING && p->data_size > len)
1165        ((char *)p->data)[len] = '\0';
1166    return 1;
1167}
1168
1169int OSSL_PARAM_set_utf8_string(OSSL_PARAM *p, const char *val)
1170{
1171    if (p == NULL)
1172        return 0;
1173
1174    p->return_size = 0;
1175    if (val == NULL)
1176        return 0;
1177    return set_string_internal(p, val, strlen(val), OSSL_PARAM_UTF8_STRING);
1178}
1179
1180int OSSL_PARAM_set_octet_string(OSSL_PARAM *p, const void *val,
1181                                size_t len)
1182{
1183    if (p == NULL)
1184        return 0;
1185
1186    p->return_size = 0;
1187    if (val == NULL)
1188        return 0;
1189    return set_string_internal(p, val, len, OSSL_PARAM_OCTET_STRING);
1190}
1191
1192OSSL_PARAM OSSL_PARAM_construct_utf8_string(const char *key, char *buf,
1193                                            size_t bsize)
1194{
1195    if (buf != NULL && bsize == 0)
1196        bsize = strlen(buf);
1197    return ossl_param_construct(key, OSSL_PARAM_UTF8_STRING, buf, bsize);
1198}
1199
1200OSSL_PARAM OSSL_PARAM_construct_octet_string(const char *key, void *buf,
1201                                             size_t bsize)
1202{
1203    return ossl_param_construct(key, OSSL_PARAM_OCTET_STRING, buf, bsize);
1204}
1205
1206static int get_ptr_internal(const OSSL_PARAM *p, const void **val,
1207                            size_t *used_len, unsigned int type)
1208{
1209    if (val == NULL || p == NULL || p->data_type != type)
1210        return 0;
1211    if (used_len != NULL)
1212        *used_len = p->data_size;
1213    *val = *(const void **)p->data;
1214    return 1;
1215}
1216
1217int OSSL_PARAM_get_utf8_ptr(const OSSL_PARAM *p, const char **val)
1218{
1219    return get_ptr_internal(p, (const void **)val, NULL, OSSL_PARAM_UTF8_PTR);
1220}
1221
1222int OSSL_PARAM_get_octet_ptr(const OSSL_PARAM *p, const void **val,
1223                             size_t *used_len)
1224{
1225    return get_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_PTR);
1226}
1227
1228static int set_ptr_internal(OSSL_PARAM *p, const void *val,
1229                            unsigned int type, size_t len)
1230{
1231    p->return_size = len;
1232    if (p->data_type != type)
1233        return 0;
1234    if (p->data != NULL)
1235        *(const void **)p->data = val;
1236    return 1;
1237}
1238
1239int OSSL_PARAM_set_utf8_ptr(OSSL_PARAM *p, const char *val)
1240{
1241    if (p == NULL)
1242        return 0;
1243    p->return_size = 0;
1244    return set_ptr_internal(p, val, OSSL_PARAM_UTF8_PTR,
1245                            val == NULL ? 0 : strlen(val));
1246}
1247
1248int OSSL_PARAM_set_octet_ptr(OSSL_PARAM *p, const void *val,
1249                             size_t used_len)
1250{
1251    if (p == NULL)
1252        return 0;
1253    p->return_size = 0;
1254    return set_ptr_internal(p, val, OSSL_PARAM_OCTET_PTR, used_len);
1255}
1256
1257OSSL_PARAM OSSL_PARAM_construct_utf8_ptr(const char *key, char **buf,
1258                                         size_t bsize)
1259{
1260    return ossl_param_construct(key, OSSL_PARAM_UTF8_PTR, buf, bsize);
1261}
1262
1263OSSL_PARAM OSSL_PARAM_construct_octet_ptr(const char *key, void **buf,
1264                                          size_t bsize)
1265{
1266    return ossl_param_construct(key, OSSL_PARAM_OCTET_PTR, buf, bsize);
1267}
1268
1269OSSL_PARAM OSSL_PARAM_construct_end(void)
1270{
1271    OSSL_PARAM end = OSSL_PARAM_END;
1272
1273    return end;
1274}
1275
1276static int get_string_ptr_internal(const OSSL_PARAM *p, const void **val,
1277                                   size_t *used_len, unsigned int type)
1278{
1279    if (val == NULL || p == NULL || p->data_type != type)
1280        return 0;
1281    if (used_len != NULL)
1282        *used_len = p->data_size;
1283    *val = p->data;
1284    return 1;
1285}
1286
1287int OSSL_PARAM_get_utf8_string_ptr(const OSSL_PARAM *p, const char **val)
1288{
1289    return OSSL_PARAM_get_utf8_ptr(p, val)
1290        || get_string_ptr_internal(p, (const void **)val, NULL,
1291                                   OSSL_PARAM_UTF8_STRING);
1292}
1293
1294int OSSL_PARAM_get_octet_string_ptr(const OSSL_PARAM *p, const void **val,
1295                                    size_t *used_len)
1296{
1297    return OSSL_PARAM_get_octet_ptr(p, val, used_len)
1298        || get_string_ptr_internal(p, val, used_len, OSSL_PARAM_OCTET_STRING);
1299}
1300