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