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