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