xref: /freebsd/crypto/openssl/test/params_api_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1 /*
2  * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10 
11 #include <string.h>
12 #include "testutil.h"
13 #include "internal/nelem.h"
14 #include "internal/endian.h"
15 #include <openssl/params.h>
16 #include <openssl/bn.h>
17 
18 /* The maximum size of the static buffers used to test most things */
19 #define MAX_LEN 20
20 
swap_copy(unsigned char * out,const void * in,size_t len)21 static void swap_copy(unsigned char *out, const void *in, size_t len)
22 {
23     size_t j;
24 
25     for (j = 0; j < len; j++)
26         out[j] = ((unsigned char *)in)[len - j - 1];
27 }
28 
29 /*
30  * A memory copy that converts the native byte ordering either to or from
31  * little endian format.
32  *
33  * On a little endian machine copying either is just a memcpy(3), on a
34  * big endian machine copying from native to or from little endian involves
35  * byte reversal.
36  */
le_copy(unsigned char * out,size_t outlen,const void * in,size_t inlen)37 static void le_copy(unsigned char *out, size_t outlen,
38                     const void *in, size_t inlen)
39 {
40     DECLARE_IS_ENDIAN;
41 
42     if (IS_LITTLE_ENDIAN) {
43         memcpy(out, in, outlen);
44     } else {
45         if (outlen < inlen) {
46             in = (const char *)in + inlen - outlen;
47             inlen = outlen;
48         }
49         if (!ossl_assert(outlen <= inlen))
50             return;
51         swap_copy(out, in, inlen);
52     }
53 }
54 
55 static const struct {
56     size_t len;
57     unsigned char value[MAX_LEN];
58 } raw_values[] = {
59     { 1, { 0x47 } },
60     { 1, { 0xd0 } },
61     { 2, { 0x01, 0xe9 } },
62     { 2, { 0xff, 0x53 } },
63     { 3, { 0x16, 0xff, 0x7c } },
64     { 3, { 0xa8, 0x9c, 0x0e } },
65     { 4, { 0x38, 0x27, 0xbf, 0x3b } },
66     { 4, { 0x9f, 0x26, 0x48, 0x22 } },
67     { 5, { 0x30, 0x65, 0xfa, 0xe4, 0x81 } },
68     { 5, { 0xd1, 0x76, 0x01, 0x1b, 0xcd } },
69     { 8, { 0x59, 0xb2, 0x1a, 0xe9, 0x2a, 0xd8, 0x46, 0x40 } },
70     { 8, { 0xb4, 0xae, 0xbd, 0xb4, 0xdd, 0x04, 0xb1, 0x4c } },
71     { 16, { 0x61, 0xe8, 0x7e, 0x31, 0xe9, 0x33, 0x83, 0x3d,
72             0x87, 0x99, 0xc7, 0xd8, 0x5d, 0xa9, 0x8b, 0x42 } },
73     { 16, { 0xee, 0x6e, 0x8b, 0xc3, 0xec, 0xcf, 0x37, 0xcc,
74             0x89, 0x67, 0xf2, 0x68, 0x33, 0xa0, 0x14, 0xb0 } },
75 };
76 
test_param_type_null(OSSL_PARAM * param)77 static int test_param_type_null(OSSL_PARAM *param)
78 {
79     int rc = 0;
80     uint64_t intval;
81     double dval;
82     BIGNUM *bn;
83 
84     switch(param->data_type) {
85     case OSSL_PARAM_INTEGER:
86         if (param->data_size == sizeof(int32_t))
87             rc = OSSL_PARAM_get_int32(param, (int32_t *)&intval);
88         else if (param->data_size == sizeof(uint64_t))
89             rc = OSSL_PARAM_get_int64(param, (int64_t *)&intval);
90         else
91             return 1;
92         break;
93     case OSSL_PARAM_UNSIGNED_INTEGER:
94         if (param->data_size == sizeof(uint32_t))
95             rc = OSSL_PARAM_get_uint32(param, (uint32_t *)&intval);
96         else if (param->data_size == sizeof(uint64_t))
97             rc = OSSL_PARAM_get_uint64(param, &intval);
98         else
99             rc = OSSL_PARAM_get_BN(param, &bn);
100         break;
101     case OSSL_PARAM_REAL:
102         rc = OSSL_PARAM_get_double(param, &dval);
103         break;
104     case OSSL_PARAM_UTF8_STRING:
105     case OSSL_PARAM_OCTET_STRING:
106     case OSSL_PARAM_UTF8_PTR:
107     case OSSL_PARAM_OCTET_PTR:
108         /* these are allowed to be null */
109         return 1;
110         break;
111     }
112 
113     /*
114      * we expect the various OSSL_PARAM_get functions above
115      * to return failure when the data is set to NULL
116      */
117     return rc == 0;
118 }
119 
test_param_type_extra(OSSL_PARAM * param,const unsigned char * cmp,size_t width)120 static int test_param_type_extra(OSSL_PARAM *param, const unsigned char *cmp,
121                                  size_t width)
122 {
123     int32_t i32;
124     int64_t i64;
125     size_t s, sz;
126     unsigned char buf[MAX_LEN];
127     const int bit32 = param->data_size <= sizeof(int32_t);
128     const int sizet = param->data_size <= sizeof(size_t);
129     const int signd = param->data_type == OSSL_PARAM_INTEGER;
130 
131     /*
132      * Set the unmodified sentinel directly because there is no param array
133      * for these tests.
134      */
135     param->return_size = OSSL_PARAM_UNMODIFIED;
136     if (signd) {
137         if ((bit32 && !TEST_true(OSSL_PARAM_get_int32(param, &i32)))
138             || !TEST_true(OSSL_PARAM_get_int64(param, &i64)))
139             return 0;
140     } else {
141         if ((bit32
142              && !TEST_true(OSSL_PARAM_get_uint32(param, (uint32_t *)&i32)))
143             || !TEST_true(OSSL_PARAM_get_uint64(param, (uint64_t *)&i64))
144             || (sizet && !TEST_true(OSSL_PARAM_get_size_t(param, &s))))
145             return 0;
146     }
147     if (!TEST_false(OSSL_PARAM_modified(param)))
148         return 0;
149 
150     /* Check signed types */
151     if (bit32) {
152         le_copy(buf, sizeof(i32), &i32, sizeof(i32));
153         sz = sizeof(i32) < width ? sizeof(i32) : width;
154         if (!TEST_mem_eq(buf, sz, cmp, sz))
155             return 0;
156     }
157     le_copy(buf, sizeof(i64), &i64, sizeof(i64));
158     sz = sizeof(i64) < width ? sizeof(i64) : width;
159     if (!TEST_mem_eq(buf, sz, cmp, sz))
160         return 0;
161     if (sizet && !signd) {
162         le_copy(buf, sizeof(s), &s, sizeof(s));
163         sz = sizeof(s) < width ? sizeof(s) : width;
164         if (!TEST_mem_eq(buf, sz, cmp, sz))
165             return 0;
166     }
167 
168     /* Check a widening write if possible */
169     if (sizeof(size_t) > width) {
170         if (signd) {
171             if (!TEST_true(OSSL_PARAM_set_int32(param, 12345))
172                 || !TEST_true(OSSL_PARAM_get_int64(param, &i64))
173                 || !TEST_size_t_eq((size_t)i64, 12345))
174                 return 0;
175         } else {
176             if (!TEST_true(OSSL_PARAM_set_uint32(param, 12345))
177                 || !TEST_true(OSSL_PARAM_get_uint64(param, (uint64_t *)&i64))
178                 || !TEST_size_t_eq((size_t)i64, 12345))
179                 return 0;
180         }
181         if (!TEST_true(OSSL_PARAM_modified(param)))
182             return 0;
183     }
184     return 1;
185 }
186 
187 /*
188  * The test cases for each of the bastic integral types are similar.
189  * For each type, a param of that type is set and an attempt to read it
190  * get is made.  Finally, the above function is called to verify that
191  * the params can be read as other types.
192  *
193  * All the real work is done via byte buffers which are converted to machine
194  * byte order and to little endian for comparisons.  Narrower values are best
195  * compared using little endian because their values and positions don't
196  * change.
197  */
198 
test_param_int(int n)199 static int test_param_int(int n)
200 {
201     int in, out;
202     unsigned char buf[MAX_LEN], cmp[sizeof(int)];
203     const size_t len = raw_values[n].len >= sizeof(int) ?
204                        sizeof(int) : raw_values[n].len;
205     OSSL_PARAM param = OSSL_PARAM_int("a", NULL);
206 
207     if (!TEST_int_eq(test_param_type_null(&param), 1))
208         return 0;
209 
210     memset(buf, 0, sizeof(buf));
211     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
212     memcpy(&in, buf, sizeof(in));
213     param.data = &out;
214     if (!TEST_true(OSSL_PARAM_set_int(&param, in)))
215         return 0;
216     le_copy(cmp, sizeof(out), &out, sizeof(out));
217     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
218         return 0;
219     in = 0;
220     if (!TEST_true(OSSL_PARAM_get_int(&param, &in)))
221         return 0;
222     le_copy(cmp, sizeof(in), &in, sizeof(in));
223     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
224         return 0;
225     param.data = &out;
226     return test_param_type_extra(&param, raw_values[n].value, sizeof(int));
227 }
228 
test_param_long(int n)229 static int test_param_long(int n)
230 {
231     long int in, out;
232     unsigned char buf[MAX_LEN], cmp[sizeof(long int)];
233     const size_t len = raw_values[n].len >= sizeof(long int)
234                        ? sizeof(long int) : raw_values[n].len;
235     OSSL_PARAM param = OSSL_PARAM_long("a", NULL);
236 
237     if (!TEST_int_eq(test_param_type_null(&param), 1))
238         return 0;
239 
240     memset(buf, 0, sizeof(buf));
241     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
242     memcpy(&in, buf, sizeof(in));
243     param.data = &out;
244     if (!TEST_true(OSSL_PARAM_set_long(&param, in)))
245         return 0;
246     le_copy(cmp, sizeof(out), &out, sizeof(out));
247     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
248         return 0;
249     in = 0;
250     if (!TEST_true(OSSL_PARAM_get_long(&param, &in)))
251         return 0;
252     le_copy(cmp, sizeof(in), &in, sizeof(in));
253     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
254         return 0;
255     param.data = &out;
256     return test_param_type_extra(&param, raw_values[n].value, sizeof(long int));
257 }
258 
test_param_uint(int n)259 static int test_param_uint(int n)
260 {
261     unsigned int in, out;
262     unsigned char buf[MAX_LEN], cmp[sizeof(unsigned int)];
263     const size_t len = raw_values[n].len >= sizeof(unsigned int) ? sizeof(unsigned int) : raw_values[n].len;
264     OSSL_PARAM param = OSSL_PARAM_uint("a", NULL);
265 
266     if (!TEST_int_eq(test_param_type_null(&param), 1))
267         return 0;
268 
269     memset(buf, 0, sizeof(buf));
270     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
271     memcpy(&in, buf, sizeof(in));
272     param.data = &out;
273     if (!TEST_true(OSSL_PARAM_set_uint(&param, in)))
274         return 0;
275     le_copy(cmp, sizeof(out), &out, sizeof(out));
276     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
277         return 0;
278     in = 0;
279     if (!TEST_true(OSSL_PARAM_get_uint(&param, &in)))
280         return 0;
281     le_copy(cmp, sizeof(in), &in, sizeof(in));
282     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
283         return 0;
284     param.data = &out;
285     return test_param_type_extra(&param, raw_values[n].value, sizeof(unsigned int));
286 }
287 
test_param_ulong(int n)288 static int test_param_ulong(int n)
289 {
290     unsigned long int in, out;
291     unsigned char buf[MAX_LEN], cmp[sizeof(unsigned long int)];
292     const size_t len = raw_values[n].len >= sizeof(unsigned long int)
293                        ? sizeof(unsigned long int) : raw_values[n].len;
294     OSSL_PARAM param = OSSL_PARAM_ulong("a", NULL);
295 
296     if (!TEST_int_eq(test_param_type_null(&param), 1))
297         return 0;
298 
299     memset(buf, 0, sizeof(buf));
300     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
301     memcpy(&in, buf, sizeof(in));
302     param.data = &out;
303     if (!TEST_true(OSSL_PARAM_set_ulong(&param, in)))
304         return 0;
305     le_copy(cmp, sizeof(out), &out, sizeof(out));
306     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
307         return 0;
308     in = 0;
309     if (!TEST_true(OSSL_PARAM_get_ulong(&param, &in)))
310         return 0;
311     le_copy(cmp, sizeof(in), &in, sizeof(in));
312     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
313         return 0;
314     param.data = &out;
315     return test_param_type_extra(&param, raw_values[n].value, sizeof(unsigned long int));
316 }
317 
test_param_int32(int n)318 static int test_param_int32(int n)
319 {
320     int32_t in, out;
321     unsigned char buf[MAX_LEN], cmp[sizeof(int32_t)];
322     const size_t len = raw_values[n].len >= sizeof(int32_t)
323                        ? sizeof(int32_t) : raw_values[n].len;
324     OSSL_PARAM param = OSSL_PARAM_int32("a", NULL);
325 
326     if (!TEST_int_eq(test_param_type_null(&param), 1))
327         return 0;
328 
329     memset(buf, 0, sizeof(buf));
330     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
331     memcpy(&in, buf, sizeof(in));
332     param.data = &out;
333     if (!TEST_true(OSSL_PARAM_set_int32(&param, in)))
334         return 0;
335     le_copy(cmp, sizeof(out), &out, sizeof(out));
336     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
337         return 0;
338     in = 0;
339     if (!TEST_true(OSSL_PARAM_get_int32(&param, &in)))
340         return 0;
341     le_copy(cmp, sizeof(in), &in, sizeof(in));
342     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
343         return 0;
344     param.data = &out;
345     return test_param_type_extra(&param, raw_values[n].value, sizeof(int32_t));
346 }
347 
test_param_uint32(int n)348 static int test_param_uint32(int n)
349 {
350     uint32_t in, out;
351     unsigned char buf[MAX_LEN], cmp[sizeof(uint32_t)];
352     const size_t len = raw_values[n].len >= sizeof(uint32_t)
353                        ? sizeof(uint32_t) : raw_values[n].len;
354     OSSL_PARAM param = OSSL_PARAM_uint32("a", NULL);
355 
356     if (!TEST_int_eq(test_param_type_null(&param), 1))
357         return 0;
358 
359     memset(buf, 0, sizeof(buf));
360     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
361     memcpy(&in, buf, sizeof(in));
362     param.data = &out;
363     if (!TEST_true(OSSL_PARAM_set_uint32(&param, in)))
364         return 0;
365     le_copy(cmp, sizeof(out), &out, sizeof(out));
366     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
367         return 0;
368     in = 0;
369     if (!TEST_true(OSSL_PARAM_get_uint32(&param, &in)))
370         return 0;
371     le_copy(cmp, sizeof(in), &in, sizeof(in));
372     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
373         return 0;
374     param.data = &out;
375     return test_param_type_extra(&param, raw_values[n].value, sizeof(uint32_t));
376 }
377 
test_param_int64(int n)378 static int test_param_int64(int n)
379 {
380     int64_t in, out;
381     unsigned char buf[MAX_LEN], cmp[sizeof(int64_t)];
382     const size_t len = raw_values[n].len >= sizeof(int64_t)
383                        ? sizeof(int64_t) : raw_values[n].len;
384     OSSL_PARAM param = OSSL_PARAM_int64("a", NULL);
385 
386     if (!TEST_int_eq(test_param_type_null(&param), 1))
387         return 0;
388 
389     memset(buf, 0, sizeof(buf));
390     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
391     memcpy(&in, buf, sizeof(in));
392     param.data = &out;
393     if (!TEST_true(OSSL_PARAM_set_int64(&param, in)))
394         return 0;
395     le_copy(cmp, sizeof(out), &out, sizeof(out));
396     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
397         return 0;
398     in = 0;
399     if (!TEST_true(OSSL_PARAM_get_int64(&param, &in)))
400         return 0;
401     le_copy(cmp, sizeof(in), &in, sizeof(in));
402     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
403         return 0;
404     param.data = &out;
405     return test_param_type_extra(&param, raw_values[n].value, sizeof(int64_t));
406 }
407 
test_param_uint64(int n)408 static int test_param_uint64(int n)
409 {
410     uint64_t in, out;
411     unsigned char buf[MAX_LEN], cmp[sizeof(uint64_t)];
412     const size_t len = raw_values[n].len >= sizeof(uint64_t)
413                        ? sizeof(uint64_t) : raw_values[n].len;
414     OSSL_PARAM param = OSSL_PARAM_uint64("a", NULL);
415 
416     if (!TEST_int_eq(test_param_type_null(&param), 1))
417         return 0;
418 
419     memset(buf, 0, sizeof(buf));
420     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
421     memcpy(&in, buf, sizeof(in));
422     param.data = &out;
423     if (!TEST_true(OSSL_PARAM_set_uint64(&param, in)))
424         return 0;
425     le_copy(cmp, sizeof(out), &out, sizeof(out));
426     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
427         return 0;
428     in = 0;
429     if (!TEST_true(OSSL_PARAM_get_uint64(&param, &in)))
430         return 0;
431     le_copy(cmp, sizeof(in), &in, sizeof(in));
432     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
433         return 0;
434     param.data = &out;
435     return test_param_type_extra(&param, raw_values[n].value, sizeof(uint64_t));
436 }
437 
test_param_size_t(int n)438 static int test_param_size_t(int n)
439 {
440     size_t in, out;
441     unsigned char buf[MAX_LEN], cmp[sizeof(size_t)];
442     const size_t len = raw_values[n].len >= sizeof(size_t)
443                        ? sizeof(size_t) : raw_values[n].len;
444     OSSL_PARAM param = OSSL_PARAM_size_t("a", NULL);
445 
446     if (!TEST_int_eq(test_param_type_null(&param), 1))
447         return 0;
448 
449     memset(buf, 0, sizeof(buf));
450     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
451     memcpy(&in, buf, sizeof(in));
452     param.data = &out;
453     if (!TEST_true(OSSL_PARAM_set_size_t(&param, in)))
454         return 0;
455     le_copy(cmp, sizeof(out), &out, sizeof(out));
456     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
457         return 0;
458     in = 0;
459     if (!TEST_true(OSSL_PARAM_get_size_t(&param, &in)))
460         return 0;
461     le_copy(cmp, sizeof(in), &in, sizeof(in));
462     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
463         return 0;
464     param.data = &out;
465     return test_param_type_extra(&param, raw_values[n].value, sizeof(size_t));
466 }
467 
test_param_time_t(int n)468 static int test_param_time_t(int n)
469 {
470     time_t in, out;
471     unsigned char buf[MAX_LEN], cmp[sizeof(time_t)];
472     const size_t len = raw_values[n].len >= sizeof(time_t)
473                        ? sizeof(time_t) : raw_values[n].len;
474     OSSL_PARAM param = OSSL_PARAM_time_t("a", NULL);
475 
476     if (!TEST_int_eq(test_param_type_null(&param), 1))
477         return 0;
478 
479     memset(buf, 0, sizeof(buf));
480     le_copy(buf, sizeof(in), raw_values[n].value, sizeof(in));
481     memcpy(&in, buf, sizeof(in));
482     param.data = &out;
483     if (!TEST_true(OSSL_PARAM_set_time_t(&param, in)))
484         return 0;
485     le_copy(cmp, sizeof(out), &out, sizeof(out));
486     if (!TEST_mem_eq(cmp, len, raw_values[n].value, len))
487         return 0;
488     in = 0;
489     if (!TEST_true(OSSL_PARAM_get_time_t(&param, &in)))
490         return 0;
491     le_copy(cmp, sizeof(in), &in, sizeof(in));
492     if (!TEST_mem_eq(cmp, sizeof(in), raw_values[n].value, sizeof(in)))
493         return 0;
494     param.data = &out;
495     return test_param_type_extra(&param, raw_values[n].value, sizeof(size_t));
496 }
497 
test_param_bignum(int n)498 static int test_param_bignum(int n)
499 {
500     unsigned char buf[MAX_LEN], bnbuf[MAX_LEN];
501     const size_t len = raw_values[n].len;
502     BIGNUM *b = NULL, *c = NULL;
503     OSSL_PARAM param = OSSL_PARAM_DEFN("bn", OSSL_PARAM_UNSIGNED_INTEGER,
504                                        NULL, 0);
505     int ret = 0;
506 
507     if (!TEST_int_eq(test_param_type_null(&param), 1))
508         return 0;
509 
510     param.data = bnbuf;
511     param.data_size = sizeof(bnbuf);
512 
513     if (!TEST_ptr(b = BN_lebin2bn(raw_values[n].value, (int)len, NULL)))
514         goto err;
515 
516     if (!TEST_true(OSSL_PARAM_set_BN(&param, b)))
517         goto err;
518     le_copy(buf, len, bnbuf, sizeof(bnbuf));
519     if (!TEST_mem_eq(raw_values[n].value, len, buf, len))
520         goto err;
521     param.data_size = param.return_size;
522     if (!TEST_true(OSSL_PARAM_get_BN(&param, &c))
523         || !TEST_BN_eq(b, c))
524         goto err;
525 
526     ret = 1;
527 err:
528     BN_free(b);
529     BN_free(c);
530     return ret;
531 }
532 
test_param_signed_bignum(int n)533 static int test_param_signed_bignum(int n)
534 {
535     unsigned char buf[MAX_LEN], bnbuf[MAX_LEN];
536     const size_t len = raw_values[n].len;
537     BIGNUM *b = NULL, *c = NULL;
538     OSSL_PARAM param = OSSL_PARAM_DEFN("bn", OSSL_PARAM_INTEGER, NULL, 0);
539     int ret = 0;
540 
541     if (!TEST_int_eq(test_param_type_null(&param), 1))
542         return 0;
543 
544     param.data = bnbuf;
545     param.data_size = sizeof(bnbuf);
546 
547     if (!TEST_ptr(b = BN_signed_lebin2bn(raw_values[n].value, (int)len, NULL)))
548         goto err;
549 
550     /* raw_values are little endian */
551     if (!TEST_false(!!(raw_values[n].value[len - 1] & 0x80) ^ BN_is_negative(b)))
552         goto err;
553     if (!TEST_true(OSSL_PARAM_set_BN(&param, b)))
554         goto err;
555     le_copy(buf, len, bnbuf, sizeof(bnbuf));
556     if (!TEST_mem_eq(raw_values[n].value, len, buf, len))
557         goto err;
558     param.data_size = param.return_size;
559     if (!TEST_true(OSSL_PARAM_get_BN(&param, &c))
560         || !TEST_BN_eq(b, c)) {
561         BN_print_fp(stderr, c);
562         goto err;
563     }
564 
565     ret = 1;
566 err:
567     BN_free(b);
568     BN_free(c);
569     return ret;
570 }
571 
test_param_real(void)572 static int test_param_real(void)
573 {
574     double p;
575     OSSL_PARAM param = OSSL_PARAM_double("r", NULL);
576 
577     if (!TEST_int_eq(test_param_type_null(&param), 1))
578         return 0;
579 
580     param.data = &p;
581     return TEST_true(OSSL_PARAM_set_double(&param, 3.14159))
582            && TEST_double_eq(p, 3.14159);
583 }
584 
test_param_construct(int tstid)585 static int test_param_construct(int tstid)
586 {
587     static const char *int_names[] = {
588         "int", "long", "int32", "int64"
589     };
590     static const char *uint_names[] = {
591         "uint", "ulong", "uint32", "uint64", "size_t"
592     };
593     static const unsigned char bn_val[16] = {
594         0xac, 0x75, 0x22, 0x7d, 0x81, 0x06, 0x7a, 0x23,
595         0xa6, 0xed, 0x87, 0xc7, 0xab, 0xf4, 0x73, 0x22
596     };
597     OSSL_PARAM *p = NULL, *p1 = NULL;
598     static const OSSL_PARAM params_empty[] = {
599         OSSL_PARAM_END
600     };
601     OSSL_PARAM params[20];
602     char buf[100], buf2[100], *bufp, *bufp2;
603     unsigned char ubuf[100];
604     void *vp, *vpn = NULL, *vp2;
605     OSSL_PARAM *cp;
606     int i, n = 0, ret = 0;
607     unsigned int u;
608     long int l;
609     unsigned long int ul;
610     int32_t i32;
611     uint32_t u32;
612     int64_t i64;
613     uint64_t u64;
614     size_t j, k, s;
615     double d, d2;
616     BIGNUM *bn = NULL, *bn2 = NULL;
617 
618     params[n++] = OSSL_PARAM_construct_int("int", &i);
619     params[n++] = OSSL_PARAM_construct_uint("uint", &u);
620     params[n++] = OSSL_PARAM_construct_long("long", &l);
621     params[n++] = OSSL_PARAM_construct_ulong("ulong", &ul);
622     params[n++] = OSSL_PARAM_construct_int32("int32", &i32);
623     params[n++] = OSSL_PARAM_construct_int64("int64", &i64);
624     params[n++] = OSSL_PARAM_construct_uint32("uint32", &u32);
625     params[n++] = OSSL_PARAM_construct_uint64("uint64", &u64);
626     params[n++] = OSSL_PARAM_construct_size_t("size_t", &s);
627     params[n++] = OSSL_PARAM_construct_double("double", &d);
628     params[n++] = OSSL_PARAM_construct_BN("bignum", ubuf, sizeof(ubuf));
629     params[n++] = OSSL_PARAM_construct_utf8_string("utf8str", buf, sizeof(buf));
630     params[n++] = OSSL_PARAM_construct_octet_string("octstr", buf, sizeof(buf));
631     params[n++] = OSSL_PARAM_construct_utf8_ptr("utf8ptr", &bufp, 0);
632     params[n++] = OSSL_PARAM_construct_octet_ptr("octptr", &vp, 0);
633     params[n] = OSSL_PARAM_construct_end();
634 
635     switch (tstid) {
636     case 0:
637         p = params;
638         break;
639     case 1:
640         p = OSSL_PARAM_merge(params, params_empty);
641         break;
642     case 2:
643         p = OSSL_PARAM_dup(params);
644         break;
645     default:
646         p1 = OSSL_PARAM_dup(params);
647         p = OSSL_PARAM_merge(p1, params_empty);
648         break;
649     }
650 
651     /* Search failure */
652     if (!TEST_ptr_null(OSSL_PARAM_locate(p, "fnord")))
653         goto err;
654 
655     /* All signed integral types */
656     for (j = 0; j < OSSL_NELEM(int_names); j++) {
657         if (!TEST_ptr(cp = OSSL_PARAM_locate(p, int_names[j]))
658             || !TEST_true(OSSL_PARAM_set_int32(cp, (int32_t)(3 + j)))
659             || !TEST_true(OSSL_PARAM_get_int64(cp, &i64))
660             || !TEST_size_t_eq(cp->data_size, cp->return_size)
661             || !TEST_size_t_eq((size_t)i64, 3 + j)) {
662             TEST_note("iteration %zu var %s", j + 1, int_names[j]);
663             goto err;
664         }
665     }
666     /* All unsigned integral types */
667     for (j = 0; j < OSSL_NELEM(uint_names); j++) {
668         if (!TEST_ptr(cp = OSSL_PARAM_locate(p, uint_names[j]))
669             || !TEST_true(OSSL_PARAM_set_uint32(cp, (uint32_t)(3 + j)))
670             || !TEST_true(OSSL_PARAM_get_uint64(cp, &u64))
671             || !TEST_size_t_eq(cp->data_size, cp->return_size)
672             || !TEST_size_t_eq((size_t)u64, 3 + j)) {
673             TEST_note("iteration %zu var %s", j + 1, uint_names[j]);
674             goto err;
675         }
676     }
677     /* Real */
678     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "double"))
679         || !TEST_true(OSSL_PARAM_set_double(cp, 3.14))
680         || !TEST_true(OSSL_PARAM_get_double(cp, &d2))
681         || !TEST_size_t_eq(cp->return_size, sizeof(double))
682         || !TEST_double_eq(d2, 3.14)
683         || (tstid <= 1 && !TEST_double_eq(d, d2)))
684         goto err;
685     /* UTF8 string */
686     bufp = NULL;
687     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "utf8str"))
688         || !TEST_true(OSSL_PARAM_set_utf8_string(cp, "abcdef"))
689         || !TEST_size_t_eq(cp->return_size, sizeof("abcdef") - 1)
690         || !TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, 0))
691         || !TEST_str_eq(bufp, "abcdef")) {
692         OPENSSL_free(bufp);
693         goto err;
694     }
695     OPENSSL_free(bufp);
696     bufp = buf2;
697     if (!TEST_true(OSSL_PARAM_get_utf8_string(cp, &bufp, sizeof(buf2)))
698         || !TEST_str_eq(buf2, "abcdef"))
699         goto err;
700     /* UTF8 pointer */
701     /* Note that the size of a UTF8 string does *NOT* include the NUL byte */
702     bufp = buf;
703     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "utf8ptr"))
704         || !TEST_true(OSSL_PARAM_set_utf8_ptr(cp, "tuvwxyz"))
705         || !TEST_size_t_eq(cp->return_size, sizeof("tuvwxyz") - 1)
706         || !TEST_true(OSSL_PARAM_get_utf8_ptr(cp, (const char **)&bufp2))
707         || !TEST_str_eq(bufp2, "tuvwxyz")
708         || (tstid <= 1 && !TEST_ptr_eq(bufp2, bufp)))
709         goto err;
710     /* OCTET string */
711     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "octstr"))
712         || !TEST_true(OSSL_PARAM_set_octet_string(cp, "abcdefghi",
713                                                   sizeof("abcdefghi")))
714         || !TEST_size_t_eq(cp->return_size, sizeof("abcdefghi")))
715         goto err;
716     /* Match the return size to avoid trailing garbage bytes */
717     cp->data_size = cp->return_size;
718     if (!TEST_true(OSSL_PARAM_get_octet_string(cp, &vpn, 0, &s))
719         || !TEST_size_t_eq(s, sizeof("abcdefghi"))
720         || !TEST_mem_eq(vpn, sizeof("abcdefghi"),
721                         "abcdefghi", sizeof("abcdefghi")))
722         goto err;
723     vp = buf2;
724     if (!TEST_true(OSSL_PARAM_get_octet_string(cp, &vp, sizeof(buf2), &s))
725         || !TEST_size_t_eq(s, sizeof("abcdefghi"))
726         || !TEST_mem_eq(vp, sizeof("abcdefghi"),
727                         "abcdefghi", sizeof("abcdefghi")))
728         goto err;
729     /* OCTET pointer */
730     vp = &l;
731     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "octptr"))
732         || !TEST_true(OSSL_PARAM_set_octet_ptr(cp, &ul, sizeof(ul)))
733         || !TEST_size_t_eq(cp->return_size, sizeof(ul))
734         || (tstid <= 1 && !TEST_ptr_eq(vp, &ul)))
735         goto err;
736     /* Match the return size to avoid trailing garbage bytes */
737     cp->data_size = cp->return_size;
738     if (!TEST_true(OSSL_PARAM_get_octet_ptr(cp, (const void **)&vp2, &k))
739         || !TEST_size_t_eq(k, sizeof(ul))
740         || (tstid <= 1 && !TEST_ptr_eq(vp2, vp)))
741         goto err;
742     /* BIGNUM */
743     if (!TEST_ptr(cp = OSSL_PARAM_locate(p, "bignum"))
744         || !TEST_ptr(bn = BN_lebin2bn(bn_val, (int)sizeof(bn_val), NULL))
745         || !TEST_true(OSSL_PARAM_set_BN(cp, bn))
746         || !TEST_size_t_eq(cp->data_size, cp->return_size))
747         goto err;
748     /* Match the return size to avoid trailing garbage bytes */
749     cp->data_size = cp->return_size;
750     if (!TEST_true(OSSL_PARAM_get_BN(cp, &bn2))
751         || !TEST_BN_eq(bn, bn2))
752         goto err;
753     ret = 1;
754 err:
755     if (p != params)
756         OPENSSL_free(p);
757     OPENSSL_free(p1);
758     OPENSSL_free(vpn);
759     BN_free(bn);
760     BN_free(bn2);
761     return ret;
762 }
763 
test_param_modified(void)764 static int test_param_modified(void)
765 {
766     OSSL_PARAM param[3] = { OSSL_PARAM_int("a", NULL),
767                             OSSL_PARAM_int("b", NULL),
768                             OSSL_PARAM_END };
769     int a, b;
770 
771     param->data = &a;
772     param[1].data = &b;
773     if (!TEST_false(OSSL_PARAM_modified(param))
774             && !TEST_true(OSSL_PARAM_set_int32(param, 1234))
775             && !TEST_true(OSSL_PARAM_modified(param))
776             && !TEST_false(OSSL_PARAM_modified(param + 1))
777             && !TEST_true(OSSL_PARAM_set_int32(param + 1, 1))
778             && !TEST_true(OSSL_PARAM_modified(param + 1)))
779         return 0;
780     OSSL_PARAM_set_all_unmodified(param);
781     if (!TEST_false(OSSL_PARAM_modified(param))
782             && !TEST_true(OSSL_PARAM_set_int32(param, 4321))
783             && !TEST_true(OSSL_PARAM_modified(param))
784             && !TEST_false(OSSL_PARAM_modified(param + 1))
785             && !TEST_true(OSSL_PARAM_set_int32(param + 1, 2))
786             && !TEST_true(OSSL_PARAM_modified(param + 1)))
787         return 0;
788     return 1;
789 }
790 
test_param_copy_null(void)791 static int test_param_copy_null(void)
792 {
793     int ret, val;
794     int a = 1, b = 2, i = 0;
795     OSSL_PARAM *cp1 = NULL, *cp2 = NULL, *p;
796     OSSL_PARAM param[3];
797 
798     param[i++] = OSSL_PARAM_construct_int("a", &a);
799     param[i++] = OSSL_PARAM_construct_int("b", &b);
800     param[i] = OSSL_PARAM_construct_end();
801 
802     ret = TEST_ptr_null(OSSL_PARAM_dup(NULL))
803           && TEST_ptr(cp1 = OSSL_PARAM_merge(NULL, param))
804           && TEST_ptr(p = OSSL_PARAM_locate(cp1, "a"))
805           && TEST_true(OSSL_PARAM_get_int(p, &val))
806           && TEST_int_eq(val, 1)
807           && TEST_ptr(p = OSSL_PARAM_locate(cp1, "b"))
808           && TEST_true(OSSL_PARAM_get_int(p, &val))
809           && TEST_int_eq(val, 2)
810           && TEST_ptr(cp2 = OSSL_PARAM_merge(param, NULL))
811           && TEST_ptr(p = OSSL_PARAM_locate(cp2, "a"))
812           && TEST_true(OSSL_PARAM_get_int(p, &val))
813           && TEST_int_eq(val, 1)
814           && TEST_ptr(p = OSSL_PARAM_locate(cp2, "b"))
815           && TEST_true(OSSL_PARAM_get_int(p, &val))
816           && TEST_int_eq(val, 2)
817           && TEST_ptr_null(OSSL_PARAM_merge(NULL, NULL));
818     OSSL_PARAM_free(cp2);
819     OSSL_PARAM_free(cp1);
820     return ret;
821 }
test_param_merge(void)822 static int test_param_merge(void)
823 {
824     int val, ret;
825     int values[] = {1, 2, 3, 4};
826     OSSL_PARAM *p = NULL, *cp = NULL;
827     OSSL_PARAM param[3], param1[3];
828 
829     param[0] = OSSL_PARAM_construct_int("diff1", &values[0]);
830     param[1] = OSSL_PARAM_construct_int("same", &values[1]);
831     param[2] = OSSL_PARAM_construct_end();
832     param1[0] = OSSL_PARAM_construct_int("diff2", &values[2]);
833     param1[1] = OSSL_PARAM_construct_int("same", &values[3]);
834     param1[2] = OSSL_PARAM_construct_end();
835 
836     ret = TEST_ptr(p = OSSL_PARAM_merge(param, param1))
837         && TEST_ptr(cp = OSSL_PARAM_locate(p, "diff1"))
838         && TEST_true(OSSL_PARAM_get_int(p, &val))
839         && TEST_int_eq(val, values[0])
840         && TEST_ptr(cp = OSSL_PARAM_locate(p, "diff2"))
841         && TEST_true(OSSL_PARAM_get_int(cp, &val))
842         && TEST_int_eq(val, values[2])
843         && TEST_ptr(cp = OSSL_PARAM_locate(p, "same"))
844         && TEST_true(OSSL_PARAM_get_int(cp, &val))
845         && TEST_int_eq(val, values[3]);
846     OSSL_PARAM_free(p);
847     return ret;
848 }
849 
setup_tests(void)850 int setup_tests(void)
851 {
852     ADD_ALL_TESTS(test_param_int, OSSL_NELEM(raw_values));
853     ADD_ALL_TESTS(test_param_long, OSSL_NELEM(raw_values));
854     ADD_ALL_TESTS(test_param_uint, OSSL_NELEM(raw_values));
855     ADD_ALL_TESTS(test_param_ulong, OSSL_NELEM(raw_values));
856     ADD_ALL_TESTS(test_param_int32, OSSL_NELEM(raw_values));
857     ADD_ALL_TESTS(test_param_uint32, OSSL_NELEM(raw_values));
858     ADD_ALL_TESTS(test_param_size_t, OSSL_NELEM(raw_values));
859     ADD_ALL_TESTS(test_param_time_t, OSSL_NELEM(raw_values));
860     ADD_ALL_TESTS(test_param_int64, OSSL_NELEM(raw_values));
861     ADD_ALL_TESTS(test_param_uint64, OSSL_NELEM(raw_values));
862     ADD_ALL_TESTS(test_param_bignum, OSSL_NELEM(raw_values));
863     ADD_ALL_TESTS(test_param_signed_bignum, OSSL_NELEM(raw_values));
864     ADD_TEST(test_param_real);
865     ADD_ALL_TESTS(test_param_construct, 4);
866     ADD_TEST(test_param_modified);
867     ADD_TEST(test_param_copy_null);
868     ADD_TEST(test_param_merge);
869     return 1;
870 }
871