1 /*
2  * Copyright 2019-2022 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 <stdarg.h>
12 #include <openssl/evp.h>
13 #include "testutil.h"
14 #include "internal/nelem.h"
15 #include "internal/property.h"
16 #include "../crypto/property/property_local.h"
17 
18 /*
19  * We make our OSSL_PROVIDER for testing purposes.  All we really need is
20  * a pointer.  We know that as long as we don't try to use the method
21  * cache flush functions, the provider pointer is merely a pointer being
22  * passed around, and used as a tag of sorts.
23  */
24 struct ossl_provider_st {
25     int x;
26 };
27 
add_property_names(const char * n,...)28 static int add_property_names(const char *n, ...)
29 {
30     va_list args;
31     int res = 1;
32 
33     va_start(args, n);
34     do {
35         if (!TEST_int_ne(ossl_property_name(NULL, n, 1), 0))
36             res = 0;
37     } while ((n = va_arg(args, const char *)) != NULL);
38     va_end(args);
39     return res;
40 }
41 
up_ref(void * p)42 static int up_ref(void *p)
43 {
44     return 1;
45 }
46 
down_ref(void * p)47 static void down_ref(void *p)
48 {
49 }
50 
test_property_string(void)51 static int test_property_string(void)
52 {
53     OSSL_METHOD_STORE *store;
54     int res = 0;
55     OSSL_PROPERTY_IDX i, j;
56 
57     if (TEST_ptr(store = ossl_method_store_new(NULL))
58         && TEST_int_eq(ossl_property_name(NULL, "fnord", 0), 0)
59         && TEST_int_ne(ossl_property_name(NULL, "fnord", 1), 0)
60         && TEST_int_ne(ossl_property_name(NULL, "name", 1), 0)
61         /* Property value checks */
62         && TEST_int_eq(ossl_property_value(NULL, "fnord", 0), 0)
63         && TEST_int_ne(i = ossl_property_value(NULL, "no", 0), 0)
64         && TEST_int_ne(j = ossl_property_value(NULL, "yes", 0), 0)
65         && TEST_int_ne(i, j)
66         && TEST_int_eq(ossl_property_value(NULL, "yes", 1), j)
67         && TEST_int_eq(ossl_property_value(NULL, "no", 1), i)
68         && TEST_int_ne(i = ossl_property_value(NULL, "illuminati", 1), 0)
69         && TEST_int_eq(j = ossl_property_value(NULL, "fnord", 1), i + 1)
70         && TEST_int_eq(ossl_property_value(NULL, "fnord", 1), j)
71         /* Check name and values are distinct */
72         && TEST_int_eq(ossl_property_value(NULL, "cold", 0), 0)
73         && TEST_int_ne(ossl_property_name(NULL, "fnord", 0),
74                        ossl_property_value(NULL, "fnord", 0)))
75         res = 1;
76     ossl_method_store_free(store);
77     return res;
78 }
79 
80 static const struct {
81     const char *defn;
82     const char *query;
83     int e;
84 } parser_tests[] = {
85     { "", "sky=blue", -1 },
86     { "", "sky!=blue", 1 },
87     { "groan", "", 0 },
88     { "cold=yes", "cold=yes", 1 },
89     { "cold=yes", "cold", 1 },
90     { "cold=yes", "cold!=no", 1 },
91     { "groan", "groan=yes", 1 },
92     { "groan", "groan=no", -1 },
93     { "groan", "groan!=yes", -1 },
94     { "cold=no", "cold", -1 },
95     { "cold=no", "?cold", 0 },
96     { "cold=no", "cold=no", 1 },
97     { "groan", "cold", -1 },
98     { "groan", "cold=no", 1 },
99     { "groan", "cold!=yes", 1 },
100     { "groan=blue", "groan=yellow", -1 },
101     { "groan=blue", "?groan=yellow", 0 },
102     { "groan=blue", "groan!=yellow", 1 },
103     { "groan=blue", "?groan!=yellow", 1 },
104     { "today=monday, tomorrow=3", "today!=2", 1 },
105     { "today=monday, tomorrow=3", "today!='monday'", -1 },
106     { "today=monday, tomorrow=3", "tomorrow=3", 1 },
107     { "n=0x3", "n=3", 1 },
108     { "n=0x3", "n=-3", -1 },
109     { "n=0x33", "n=51", 1 },
110     { "n=033", "n=27", 1 },
111     { "n=0", "n=00", 1 },
112     { "n=0x0", "n=0", 1 },
113     { "n=0, sky=blue", "?n=0, sky=blue", 2 },
114     { "n=1, sky=blue", "?n=0, sky=blue", 1 },
115 };
116 
test_property_parse(int n)117 static int test_property_parse(int n)
118 {
119     OSSL_METHOD_STORE *store;
120     OSSL_PROPERTY_LIST *p = NULL, *q = NULL;
121     int r = 0;
122 
123     if (TEST_ptr(store = ossl_method_store_new(NULL))
124         && add_property_names("sky", "groan", "cold", "today", "tomorrow", "n",
125                               NULL)
126         && TEST_ptr(p = ossl_parse_property(NULL, parser_tests[n].defn))
127         && TEST_ptr(q = ossl_parse_query(NULL, parser_tests[n].query, 0))
128         && TEST_int_eq(ossl_property_match_count(q, p), parser_tests[n].e))
129         r = 1;
130     ossl_property_free(p);
131     ossl_property_free(q);
132     ossl_method_store_free(store);
133     return r;
134 }
135 
test_property_query_value_create(void)136 static int test_property_query_value_create(void)
137 {
138     OSSL_METHOD_STORE *store;
139     OSSL_PROPERTY_LIST *p = NULL, *q = NULL, *o = NULL;
140     int r = 0;
141 
142     /* The property value used here must not be used in other test cases */
143     if (TEST_ptr(store = ossl_method_store_new(NULL))
144         && add_property_names("wood", NULL)
145         && TEST_ptr(p = ossl_parse_query(NULL, "wood=oak", 0)) /* undefined */
146         && TEST_ptr(q = ossl_parse_query(NULL, "wood=oak", 1)) /* creates */
147         && TEST_ptr(o = ossl_parse_query(NULL, "wood=oak", 0)) /* defined */
148         && TEST_int_eq(ossl_property_match_count(q, p), -1)
149         && TEST_int_eq(ossl_property_match_count(q, o), 1))
150         r = 1;
151     ossl_property_free(o);
152     ossl_property_free(p);
153     ossl_property_free(q);
154     ossl_method_store_free(store);
155     return r;
156 }
157 
158 static const struct {
159     int query;
160     const char *ps;
161 } parse_error_tests[] = {
162     { 0, "n=1, n=1" },          /* duplicate name */
163     { 0, "n=1, a=hi, n=1" },    /* duplicate name */
164     { 1, "n=1, a=bye, ?n=0" },  /* duplicate name */
165     { 0, "a=abc,#@!, n=1" },    /* non-ASCII character located */
166     { 1, "a='Hello" },          /* Unterminated string */
167     { 0, "a=\"World" },         /* Unterminated string */
168     { 1, "a=2, n=012345678" },  /* Bad octal digit */
169     { 0, "n=0x28FG, a=3" },     /* Bad hex digit */
170     { 0, "n=145d, a=2" },       /* Bad decimal digit */
171     { 1, "@='hello'" },         /* Invalid name */
172     { 1, "n0123456789012345678901234567890123456789"
173          "0123456789012345678901234567890123456789"
174          "0123456789012345678901234567890123456789"
175          "0123456789012345678901234567890123456789=yes" }, /* Name too long */
176     { 0, ".n=3" },              /* Invalid name */
177     { 1, "fnord.fnord.=3" }     /* Invalid name */
178 };
179 
test_property_parse_error(int n)180 static int test_property_parse_error(int n)
181 {
182     OSSL_METHOD_STORE *store;
183     OSSL_PROPERTY_LIST *p = NULL;
184     int r = 0;
185     const char *ps;
186 
187     if (!TEST_ptr(store = ossl_method_store_new(NULL))
188         || !add_property_names("a", "n", NULL))
189         goto err;
190     ps = parse_error_tests[n].ps;
191     if (parse_error_tests[n].query) {
192         if (!TEST_ptr_null(p = ossl_parse_query(NULL, ps, 1)))
193             goto err;
194     } else if (!TEST_ptr_null(p = ossl_parse_property(NULL, ps))) {
195         goto err;
196     }
197     r = 1;
198  err:
199     ossl_property_free(p);
200     ossl_method_store_free(store);
201     return r;
202 }
203 
204 static const struct {
205     const char *q_global;
206     const char *q_local;
207     const char *prop;
208 } merge_tests[] = {
209     { "", "colour=blue", "colour=blue" },
210     { "colour=blue", "", "colour=blue" },
211     { "colour=red", "colour=blue", "colour=blue" },
212     { "clouds=pink, urn=red", "urn=blue, colour=green",
213         "urn=blue, colour=green, clouds=pink" },
214     { "pot=gold", "urn=blue", "pot=gold, urn=blue" },
215     { "night", "day", "day=yes, night=yes" },
216     { "day", "night", "day=yes, night=yes" },
217     { "", "", "" },
218     /*
219      * The following four leave 'day' unspecified in the query, and will match
220      * any definition
221      */
222     { "day=yes", "-day", "day=no" },
223     { "day=yes", "-day", "day=yes" },
224     { "day=yes", "-day", "day=arglebargle" },
225     { "day=yes", "-day", "pot=sesquioxidizing" },
226     { "day, night", "-night, day", "day=yes, night=no" },
227     { "-day", "day=yes", "day=yes" },
228 };
229 
test_property_merge(int n)230 static int test_property_merge(int n)
231 {
232     OSSL_METHOD_STORE *store;
233     OSSL_PROPERTY_LIST *q_global = NULL, *q_local = NULL;
234     OSSL_PROPERTY_LIST *q_combined = NULL, *prop = NULL;
235     int r = 0;
236 
237     if (TEST_ptr(store = ossl_method_store_new(NULL))
238         && add_property_names("colour", "urn", "clouds", "pot", "day", "night",
239                               NULL)
240         && TEST_ptr(prop = ossl_parse_property(NULL, merge_tests[n].prop))
241         && TEST_ptr(q_global = ossl_parse_query(NULL, merge_tests[n].q_global,
242                                                 0))
243         && TEST_ptr(q_local = ossl_parse_query(NULL, merge_tests[n].q_local, 0))
244         && TEST_ptr(q_combined = ossl_property_merge(q_local, q_global))
245         && TEST_int_ge(ossl_property_match_count(q_combined, prop), 0))
246         r = 1;
247     ossl_property_free(q_global);
248     ossl_property_free(q_local);
249     ossl_property_free(q_combined);
250     ossl_property_free(prop);
251     ossl_method_store_free(store);
252     return r;
253 }
254 
test_property_defn_cache(void)255 static int test_property_defn_cache(void)
256 {
257     OSSL_METHOD_STORE *store;
258     OSSL_PROPERTY_LIST *red, *blue;
259     int r = 0;
260 
261     if (TEST_ptr(store = ossl_method_store_new(NULL))
262         && add_property_names("red", "blue", NULL)
263         && TEST_ptr(red = ossl_parse_property(NULL, "red"))
264         && TEST_ptr(blue = ossl_parse_property(NULL, "blue"))
265         && TEST_ptr_ne(red, blue)
266         && TEST_true(ossl_prop_defn_set(NULL, "red", red))
267         && TEST_true(ossl_prop_defn_set(NULL, "blue", blue))
268         && TEST_ptr_eq(ossl_prop_defn_get(NULL, "red"), red)
269         && TEST_ptr_eq(ossl_prop_defn_get(NULL, "blue"), blue))
270         r = 1;
271     ossl_method_store_free(store);
272     return r;
273 }
274 
275 static const struct {
276     const char *defn;
277     const char *query;
278     int e;
279 } definition_tests[] = {
280     { "alpha", "alpha=yes", 1 },
281     { "alpha=no", "alpha", -1 },
282     { "alpha=1", "alpha=1", 1 },
283     { "alpha=2", "alpha=1",-1 },
284     { "alpha", "omega", -1 },
285     { "alpha", "?omega", 0 },
286     { "alpha", "?omega=1", 0 },
287     { "alpha", "?omega=no", 1 },
288     { "alpha", "?omega=yes", 0 },
289     { "alpha, omega", "?omega=yes", 1 },
290     { "alpha, omega", "?omega=no", 0 }
291 };
292 
test_definition_compares(int n)293 static int test_definition_compares(int n)
294 {
295     OSSL_METHOD_STORE *store;
296     OSSL_PROPERTY_LIST *d = NULL, *q = NULL;
297     int r;
298 
299     r = TEST_ptr(store = ossl_method_store_new(NULL))
300         && add_property_names("alpha", "omega", NULL)
301         && TEST_ptr(d = ossl_parse_property(NULL, definition_tests[n].defn))
302         && TEST_ptr(q = ossl_parse_query(NULL, definition_tests[n].query, 0))
303         && TEST_int_eq(ossl_property_match_count(q, d), definition_tests[n].e);
304 
305     ossl_property_free(d);
306     ossl_property_free(q);
307     ossl_method_store_free(store);
308     return r;
309 }
310 
test_register_deregister(void)311 static int test_register_deregister(void)
312 {
313     static const struct {
314         int nid;
315         const char *prop;
316         char *impl;
317     } impls[] = {
318         { 6, "position=1", "a" },
319         { 6, "position=2", "b" },
320         { 6, "position=3", "c" },
321         { 6, "position=4", "d" },
322     };
323     size_t i;
324     int ret = 0;
325     OSSL_METHOD_STORE *store;
326     OSSL_PROVIDER prov = { 1 };
327 
328     if (!TEST_ptr(store = ossl_method_store_new(NULL))
329         || !add_property_names("position", NULL))
330         goto err;
331 
332     for (i = 0; i < OSSL_NELEM(impls); i++)
333         if (!TEST_true(ossl_method_store_add(store, &prov, impls[i].nid,
334                                              impls[i].prop, impls[i].impl,
335                                              &up_ref, &down_ref))) {
336             TEST_note("iteration %zd", i + 1);
337             goto err;
338         }
339 
340     /* Deregister in a different order to registration */
341     for (i = 0; i < OSSL_NELEM(impls); i++) {
342         const size_t j = (1 + i * 3) % OSSL_NELEM(impls);
343         int nid = impls[j].nid;
344         void *impl = impls[j].impl;
345 
346         if (!TEST_true(ossl_method_store_remove(store, nid, impl))
347             || !TEST_false(ossl_method_store_remove(store, nid, impl))) {
348             TEST_note("iteration %zd, position %zd", i + 1, j + 1);
349             goto err;
350         }
351     }
352 
353     if (TEST_false(ossl_method_store_remove(store, impls[0].nid, impls[0].impl)))
354         ret = 1;
355 err:
356     ossl_method_store_free(store);
357     return ret;
358 }
359 
test_property(void)360 static int test_property(void)
361 {
362     static OSSL_PROVIDER fake_provider1 = { 1 };
363     static OSSL_PROVIDER fake_provider2 = { 2 };
364     static const OSSL_PROVIDER *fake_prov1 = &fake_provider1;
365     static const OSSL_PROVIDER *fake_prov2 = &fake_provider2;
366     static const struct {
367         const OSSL_PROVIDER **prov;
368         int nid;
369         const char *prop;
370         char *impl;
371     } impls[] = {
372         { &fake_prov1, 1, "fast=no, colour=green", "a" },
373         { &fake_prov1, 1, "fast, colour=blue", "b" },
374         { &fake_prov1, 1, "", "-" },
375         { &fake_prov2, 9, "sky=blue, furry", "c" },
376         { &fake_prov2, 3, NULL, "d" },
377         { &fake_prov2, 6, "sky.colour=blue, sky=green, old.data", "e" },
378     };
379     static struct {
380         const OSSL_PROVIDER **prov;
381         int nid;
382         const char *prop;
383         char *expected;
384     } queries[] = {
385         { &fake_prov1, 1, "fast", "b" },
386         { &fake_prov1, 1, "fast=yes", "b" },
387         { &fake_prov1, 1, "fast=no, colour=green", "a" },
388         { &fake_prov1, 1, "colour=blue, fast", "b" },
389         { &fake_prov1, 1, "colour=blue", "b" },
390         { &fake_prov2, 9, "furry", "c" },
391         { &fake_prov2, 6, "sky.colour=blue", "e" },
392         { &fake_prov2, 6, "old.data", "e" },
393         { &fake_prov2, 9, "furry=yes, sky=blue", "c" },
394         { &fake_prov1, 1, "", "a" },
395         { &fake_prov2, 3, "", "d" },
396     };
397     OSSL_METHOD_STORE *store;
398     size_t i;
399     int ret = 0;
400     void *result;
401 
402     if (!TEST_ptr(store = ossl_method_store_new(NULL))
403         || !add_property_names("fast", "colour", "sky", "furry", NULL))
404         goto err;
405 
406     for (i = 0; i < OSSL_NELEM(impls); i++)
407         if (!TEST_true(ossl_method_store_add(store, *impls[i].prov,
408                                              impls[i].nid, impls[i].prop,
409                                              impls[i].impl,
410                                              &up_ref, &down_ref))) {
411             TEST_note("iteration %zd", i + 1);
412             goto err;
413         }
414     /*
415      * The first check of queries is with NULL given as provider.  All
416      * queries are expected to succeed.
417      */
418     for (i = 0; i < OSSL_NELEM(queries); i++) {
419         const OSSL_PROVIDER *nullprov = NULL;
420         OSSL_PROPERTY_LIST *pq = NULL;
421 
422         if (!TEST_true(ossl_method_store_fetch(store,
423                                                queries[i].nid, queries[i].prop,
424                                                &nullprov, &result))
425             || !TEST_str_eq((char *)result, queries[i].expected)) {
426             TEST_note("iteration %zd", i + 1);
427             ossl_property_free(pq);
428             goto err;
429         }
430         ossl_property_free(pq);
431     }
432     /*
433      * The second check of queries is with &address1 given as provider.
434      */
435     for (i = 0; i < OSSL_NELEM(queries); i++) {
436         OSSL_PROPERTY_LIST *pq = NULL;
437 
438         result = NULL;
439         if (queries[i].prov == &fake_prov1) {
440             if (!TEST_true(ossl_method_store_fetch(store,
441                                                    queries[i].nid,
442                                                    queries[i].prop,
443                                                    &fake_prov1, &result))
444                 || !TEST_ptr_eq(fake_prov1, &fake_provider1)
445                 || !TEST_str_eq((char *)result, queries[i].expected)) {
446                 TEST_note("iteration %zd", i + 1);
447                 ossl_property_free(pq);
448                 goto err;
449             }
450         } else {
451             if (!TEST_false(ossl_method_store_fetch(store,
452                                                     queries[i].nid,
453                                                     queries[i].prop,
454                                                     &fake_prov1, &result))
455                 || !TEST_ptr_eq(fake_prov1, &fake_provider1)
456                 || !TEST_ptr_null(result)) {
457                 TEST_note("iteration %zd", i + 1);
458                 ossl_property_free(pq);
459                 goto err;
460             }
461         }
462         ossl_property_free(pq);
463     }
464     /*
465      * The third check of queries is with &address2 given as provider.
466      */
467     for (i = 0; i < OSSL_NELEM(queries); i++) {
468         OSSL_PROPERTY_LIST *pq = NULL;
469 
470         result = NULL;
471         if (queries[i].prov == &fake_prov2) {
472             if (!TEST_true(ossl_method_store_fetch(store,
473                                                    queries[i].nid,
474                                                    queries[i].prop,
475                                                    &fake_prov2, &result))
476                 || !TEST_ptr_eq(fake_prov2, &fake_provider2)
477                 || !TEST_str_eq((char *)result, queries[i].expected)) {
478                 TEST_note("iteration %zd", i + 1);
479                 ossl_property_free(pq);
480                 goto err;
481             }
482         } else {
483             if (!TEST_false(ossl_method_store_fetch(store,
484                                                     queries[i].nid,
485                                                     queries[i].prop,
486                                                     &fake_prov2, &result))
487                 || !TEST_ptr_eq(fake_prov2, &fake_provider2)
488                 || !TEST_ptr_null(result)) {
489                 TEST_note("iteration %zd", i + 1);
490                 ossl_property_free(pq);
491                 goto err;
492             }
493         }
494         ossl_property_free(pq);
495     }
496     ret = 1;
497 err:
498     ossl_method_store_free(store);
499     return ret;
500 }
501 
test_query_cache_stochastic(void)502 static int test_query_cache_stochastic(void)
503 {
504     const int max = 10000, tail = 10;
505     OSSL_METHOD_STORE *store;
506     int i, res = 0;
507     char buf[50];
508     void *result;
509     int errors = 0;
510     int v[10001];
511     OSSL_PROVIDER prov = { 1 };
512 
513     if (!TEST_ptr(store = ossl_method_store_new(NULL))
514         || !add_property_names("n", NULL))
515         goto err;
516 
517     for (i = 1; i <= max; i++) {
518         v[i] = 2 * i;
519         BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
520         if (!TEST_true(ossl_method_store_add(store, &prov, i, buf, "abc",
521                                              &up_ref, &down_ref))
522                 || !TEST_true(ossl_method_store_cache_set(store, &prov, i,
523                                                           buf, v + i,
524                                                           &up_ref, &down_ref))
525                 || !TEST_true(ossl_method_store_cache_set(store, &prov, i,
526                                                           "n=1234", "miss",
527                                                           &up_ref, &down_ref))) {
528             TEST_note("iteration %d", i);
529             goto err;
530         }
531     }
532     for (i = 1; i <= max; i++) {
533         BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
534         if (!ossl_method_store_cache_get(store, NULL, i, buf, &result)
535             || result != v + i)
536             errors++;
537     }
538     /* There is a tiny probability that this will fail when it shouldn't */
539     res = TEST_int_gt(errors, tail) && TEST_int_lt(errors, max - tail);
540 
541 err:
542     ossl_method_store_free(store);
543     return res;
544 }
545 
test_fips_mode(void)546 static int test_fips_mode(void)
547 {
548     int ret = 0;
549     OSSL_LIB_CTX *ctx = NULL;
550 
551     if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()))
552         goto err;
553 
554     ret = TEST_true(EVP_set_default_properties(ctx, "default=yes,fips=yes"))
555           && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
556           && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
557           && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
558           && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
559           && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
560           && TEST_true(EVP_set_default_properties(ctx, "fips!=no"))
561           && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
562           && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
563           && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
564           && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
565           && TEST_true(EVP_default_properties_enable_fips(ctx, 1))
566           && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
567           && TEST_true(EVP_default_properties_enable_fips(ctx, 0))
568           && TEST_false(EVP_default_properties_is_fips_enabled(ctx));
569 err:
570     OSSL_LIB_CTX_free(ctx);
571     return ret;
572 }
573 
574 static struct {
575     const char *in;
576     const char *out;
577 } to_string_tests[] = {
578     { "fips=yes", "fips=yes" },
579     { "fips!=yes", "fips!=yes" },
580     { "fips = yes", "fips=yes" },
581     { "fips", "fips=yes" },
582     { "fips=no", "fips=no" },
583     { "-fips", "-fips" },
584     { "?fips=yes", "?fips=yes" },
585     { "fips=yes,provider=fips", "fips=yes,provider=fips" },
586     { "fips = yes , provider = fips", "fips=yes,provider=fips" },
587     { "fips=yes,provider!=fips", "fips=yes,provider!=fips" },
588     { "fips=yes,?provider=fips", "fips=yes,?provider=fips" },
589     { "fips=yes,-provider", "fips=yes,-provider" },
590       /* foo is an unknown internal name */
591     { "foo=yes,fips=yes", "fips=yes"},
592     { "", "" },
593     { "fips=3", "fips=3" },
594     { "fips=-3", "fips=-3" },
595     { NULL, "" }
596 };
597 
test_property_list_to_string(int i)598 static int test_property_list_to_string(int i)
599 {
600     OSSL_PROPERTY_LIST *pl = NULL;
601     int ret = 0;
602     size_t bufsize;
603     char *buf = NULL;
604 
605     if (to_string_tests[i].in != NULL
606             && !TEST_ptr(pl = ossl_parse_query(NULL, to_string_tests[i].in, 1)))
607         goto err;
608     bufsize = ossl_property_list_to_string(NULL, pl, NULL, 0);
609     if (!TEST_size_t_gt(bufsize, 0))
610         goto err;
611     buf = OPENSSL_malloc(bufsize);
612     if (!TEST_ptr(buf)
613             || !TEST_size_t_eq(ossl_property_list_to_string(NULL, pl, buf,
614                                                             bufsize),
615                                bufsize)
616             || !TEST_str_eq(to_string_tests[i].out, buf)
617             || !TEST_size_t_eq(bufsize, strlen(to_string_tests[i].out) + 1))
618         goto err;
619 
620     ret = 1;
621  err:
622     OPENSSL_free(buf);
623     ossl_property_free(pl);
624     return ret;
625 }
626 
setup_tests(void)627 int setup_tests(void)
628 {
629     ADD_TEST(test_property_string);
630     ADD_TEST(test_property_query_value_create);
631     ADD_ALL_TESTS(test_property_parse, OSSL_NELEM(parser_tests));
632     ADD_ALL_TESTS(test_property_parse_error, OSSL_NELEM(parse_error_tests));
633     ADD_ALL_TESTS(test_property_merge, OSSL_NELEM(merge_tests));
634     ADD_TEST(test_property_defn_cache);
635     ADD_ALL_TESTS(test_definition_compares, OSSL_NELEM(definition_tests));
636     ADD_TEST(test_register_deregister);
637     ADD_TEST(test_property);
638     ADD_TEST(test_query_cache_stochastic);
639     ADD_TEST(test_fips_mode);
640     ADD_ALL_TESTS(test_property_list_to_string, OSSL_NELEM(to_string_tests));
641     return 1;
642 }
643