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