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