2
0

property_test.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  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. #include <stdarg.h>
  11. #include <openssl/evp.h>
  12. #include "testutil.h"
  13. #include "internal/nelem.h"
  14. #include "internal/property.h"
  15. #include "../crypto/property/property_local.h"
  16. static int add_property_names(const char *n, ...)
  17. {
  18. va_list args;
  19. int res = 1;
  20. va_start(args, n);
  21. do {
  22. if (!TEST_int_ne(ossl_property_name(NULL, n, 1), 0))
  23. res = 0;
  24. } while ((n = va_arg(args, const char *)) != NULL);
  25. va_end(args);
  26. return res;
  27. }
  28. static int up_ref(void *p)
  29. {
  30. return 1;
  31. }
  32. static void down_ref(void *p)
  33. {
  34. }
  35. static int test_property_string(void)
  36. {
  37. OSSL_METHOD_STORE *store;
  38. int res = 0;
  39. OSSL_PROPERTY_IDX i, j;
  40. if (TEST_ptr(store = ossl_method_store_new(NULL))
  41. && TEST_int_eq(ossl_property_name(NULL, "fnord", 0), 0)
  42. && TEST_int_ne(ossl_property_name(NULL, "fnord", 1), 0)
  43. && TEST_int_ne(ossl_property_name(NULL, "name", 1), 0)
  44. /* Property value checks */
  45. && TEST_int_eq(ossl_property_value(NULL, "fnord", 0), 0)
  46. && TEST_int_ne(i = ossl_property_value(NULL, "no", 0), 0)
  47. && TEST_int_ne(j = ossl_property_value(NULL, "yes", 0), 0)
  48. && TEST_int_ne(i, j)
  49. && TEST_int_eq(ossl_property_value(NULL, "yes", 1), j)
  50. && TEST_int_eq(ossl_property_value(NULL, "no", 1), i)
  51. && TEST_int_ne(i = ossl_property_value(NULL, "illuminati", 1), 0)
  52. && TEST_int_eq(j = ossl_property_value(NULL, "fnord", 1), i + 1)
  53. && TEST_int_eq(ossl_property_value(NULL, "fnord", 1), j)
  54. /* Check name and values are distinct */
  55. && TEST_int_eq(ossl_property_value(NULL, "cold", 0), 0)
  56. && TEST_int_ne(ossl_property_name(NULL, "fnord", 0),
  57. ossl_property_value(NULL, "fnord", 0)))
  58. res = 1;
  59. ossl_method_store_free(store);
  60. return res;
  61. }
  62. static const struct {
  63. const char *defn;
  64. const char *query;
  65. int e;
  66. } parser_tests[] = {
  67. { "", "sky=blue", -1 },
  68. { "", "sky!=blue", 1 },
  69. { "groan", "", 0 },
  70. { "cold=yes", "cold=yes", 1 },
  71. { "cold=yes", "cold", 1 },
  72. { "cold=yes", "cold!=no", 1 },
  73. { "groan", "groan=yes", 1 },
  74. { "groan", "groan=no", -1 },
  75. { "groan", "groan!=yes", -1 },
  76. { "cold=no", "cold", -1 },
  77. { "cold=no", "?cold", 0 },
  78. { "cold=no", "cold=no", 1 },
  79. { "groan", "cold", -1 },
  80. { "groan", "cold=no", 1 },
  81. { "groan", "cold!=yes", 1 },
  82. { "groan=blue", "groan=yellow", -1 },
  83. { "groan=blue", "?groan=yellow", 0 },
  84. { "groan=blue", "groan!=yellow", 1 },
  85. { "groan=blue", "?groan!=yellow", 1 },
  86. { "today=monday, tomorrow=3", "today!=2", 1 },
  87. { "today=monday, tomorrow=3", "today!='monday'", -1 },
  88. { "today=monday, tomorrow=3", "tomorrow=3", 1 },
  89. { "n=0x3", "n=3", 1 },
  90. { "n=0x3", "n=-3", -1 },
  91. { "n=0x33", "n=51", 1 },
  92. { "n=033", "n=27", 1 },
  93. { "n=0", "n=00", 1 },
  94. { "n=0x0", "n=0", 1 },
  95. { "n=0, sky=blue", "?n=0, sky=blue", 2 },
  96. { "n=1, sky=blue", "?n=0, sky=blue", 1 },
  97. };
  98. static int test_property_parse(int n)
  99. {
  100. OSSL_METHOD_STORE *store;
  101. OSSL_PROPERTY_LIST *p = NULL, *q = NULL;
  102. int r = 0;
  103. if (TEST_ptr(store = ossl_method_store_new(NULL))
  104. && add_property_names("sky", "groan", "cold", "today", "tomorrow", "n",
  105. NULL)
  106. && TEST_ptr(p = ossl_parse_property(NULL, parser_tests[n].defn))
  107. && TEST_ptr(q = ossl_parse_query(NULL, parser_tests[n].query, 0))
  108. && TEST_int_eq(ossl_property_match_count(q, p), parser_tests[n].e))
  109. r = 1;
  110. ossl_property_free(p);
  111. ossl_property_free(q);
  112. ossl_method_store_free(store);
  113. return r;
  114. }
  115. static int test_property_query_value_create(void)
  116. {
  117. OSSL_METHOD_STORE *store;
  118. OSSL_PROPERTY_LIST *p = NULL, *q = NULL, *o = NULL;
  119. int r = 0;
  120. /* The property value used here must not be used in other test cases */
  121. if (TEST_ptr(store = ossl_method_store_new(NULL))
  122. && add_property_names("wood", NULL)
  123. && TEST_ptr(p = ossl_parse_query(NULL, "wood=oak", 0)) /* undefined */
  124. && TEST_ptr(q = ossl_parse_query(NULL, "wood=oak", 1)) /* creates */
  125. && TEST_ptr(o = ossl_parse_query(NULL, "wood=oak", 0)) /* defined */
  126. && TEST_int_eq(ossl_property_match_count(q, p), -1)
  127. && TEST_int_eq(ossl_property_match_count(q, o), 1))
  128. r = 1;
  129. ossl_property_free(o);
  130. ossl_property_free(p);
  131. ossl_property_free(q);
  132. ossl_method_store_free(store);
  133. return r;
  134. }
  135. static const struct {
  136. const char *q_global;
  137. const char *q_local;
  138. const char *prop;
  139. } merge_tests[] = {
  140. { "", "colour=blue", "colour=blue" },
  141. { "colour=blue", "", "colour=blue" },
  142. { "colour=red", "colour=blue", "colour=blue" },
  143. { "clouds=pink, urn=red", "urn=blue, colour=green",
  144. "urn=blue, colour=green, clouds=pink" },
  145. { "pot=gold", "urn=blue", "pot=gold, urn=blue" },
  146. { "night", "day", "day=yes, night=yes" },
  147. { "day", "night", "day=yes, night=yes" },
  148. { "", "", "" },
  149. /*
  150. * The following four leave 'day' unspecified in the query, and will match
  151. * any definition
  152. */
  153. { "day=yes", "-day", "day=no" },
  154. { "day=yes", "-day", "day=yes" },
  155. { "day=yes", "-day", "day=arglebargle" },
  156. { "day=yes", "-day", "pot=sesquioxidizing" },
  157. { "day, night", "-night, day", "day=yes, night=no" },
  158. { "-day", "day=yes", "day=yes" },
  159. };
  160. static int test_property_merge(int n)
  161. {
  162. OSSL_METHOD_STORE *store;
  163. OSSL_PROPERTY_LIST *q_global = NULL, *q_local = NULL;
  164. OSSL_PROPERTY_LIST *q_combined = NULL, *prop = NULL;
  165. int r = 0;
  166. if (TEST_ptr(store = ossl_method_store_new(NULL))
  167. && add_property_names("colour", "urn", "clouds", "pot", "day", "night",
  168. NULL)
  169. && TEST_ptr(prop = ossl_parse_property(NULL, merge_tests[n].prop))
  170. && TEST_ptr(q_global = ossl_parse_query(NULL, merge_tests[n].q_global,
  171. 0))
  172. && TEST_ptr(q_local = ossl_parse_query(NULL, merge_tests[n].q_local, 0))
  173. && TEST_ptr(q_combined = ossl_property_merge(q_local, q_global))
  174. && TEST_int_ge(ossl_property_match_count(q_combined, prop), 0))
  175. r = 1;
  176. ossl_property_free(q_global);
  177. ossl_property_free(q_local);
  178. ossl_property_free(q_combined);
  179. ossl_property_free(prop);
  180. ossl_method_store_free(store);
  181. return r;
  182. }
  183. static int test_property_defn_cache(void)
  184. {
  185. OSSL_METHOD_STORE *store;
  186. OSSL_PROPERTY_LIST *red, *blue;
  187. int r = 0;
  188. if (TEST_ptr(store = ossl_method_store_new(NULL))
  189. && add_property_names("red", "blue", NULL)
  190. && TEST_ptr(red = ossl_parse_property(NULL, "red"))
  191. && TEST_ptr(blue = ossl_parse_property(NULL, "blue"))
  192. && TEST_ptr_ne(red, blue)
  193. && TEST_true(ossl_prop_defn_set(NULL, "red", red))
  194. && TEST_true(ossl_prop_defn_set(NULL, "blue", blue))
  195. && TEST_ptr_eq(ossl_prop_defn_get(NULL, "red"), red)
  196. && TEST_ptr_eq(ossl_prop_defn_get(NULL, "blue"), blue))
  197. r = 1;
  198. ossl_method_store_free(store);
  199. return r;
  200. }
  201. static const struct {
  202. const char *defn;
  203. const char *query;
  204. int e;
  205. } definition_tests[] = {
  206. { "alpha", "alpha=yes", 1 },
  207. { "alpha=no", "alpha", -1 },
  208. { "alpha=1", "alpha=1", 1 },
  209. { "alpha=2", "alpha=1",-1 },
  210. { "alpha", "omega", -1 },
  211. { "alpha", "?omega", 0 },
  212. { "alpha", "?omega=1", 0 },
  213. { "alpha", "?omega=no", 1 },
  214. { "alpha", "?omega=yes", 0 },
  215. { "alpha, omega", "?omega=yes", 1 },
  216. { "alpha, omega", "?omega=no", 0 }
  217. };
  218. static int test_definition_compares(int n)
  219. {
  220. OSSL_METHOD_STORE *store;
  221. OSSL_PROPERTY_LIST *d = NULL, *q = NULL;
  222. int r;
  223. r = TEST_ptr(store = ossl_method_store_new(NULL))
  224. && add_property_names("alpha", "omega", NULL)
  225. && TEST_ptr(d = ossl_parse_property(NULL, definition_tests[n].defn))
  226. && TEST_ptr(q = ossl_parse_query(NULL, definition_tests[n].query, 0))
  227. && TEST_int_eq(ossl_property_match_count(q, d), definition_tests[n].e);
  228. ossl_property_free(d);
  229. ossl_property_free(q);
  230. ossl_method_store_free(store);
  231. return r;
  232. }
  233. static int test_register_deregister(void)
  234. {
  235. static const struct {
  236. int nid;
  237. const char *prop;
  238. char *impl;
  239. } impls[] = {
  240. { 6, "position=1", "a" },
  241. { 6, "position=2", "b" },
  242. { 6, "position=3", "c" },
  243. { 6, "position=4", "d" },
  244. };
  245. size_t i;
  246. int ret = 0;
  247. OSSL_METHOD_STORE *store;
  248. if (!TEST_ptr(store = ossl_method_store_new(NULL))
  249. || !add_property_names("position", NULL))
  250. goto err;
  251. for (i = 0; i < OSSL_NELEM(impls); i++)
  252. if (!TEST_true(ossl_method_store_add(store, NULL, impls[i].nid,
  253. impls[i].prop, impls[i].impl,
  254. &up_ref, &down_ref))) {
  255. TEST_note("iteration %zd", i + 1);
  256. goto err;
  257. }
  258. /* Deregister in a different order to registration */
  259. for (i = 0; i < OSSL_NELEM(impls); i++) {
  260. const size_t j = (1 + i * 3) % OSSL_NELEM(impls);
  261. int nid = impls[j].nid;
  262. void *impl = impls[j].impl;
  263. if (!TEST_true(ossl_method_store_remove(store, nid, impl))
  264. || !TEST_false(ossl_method_store_remove(store, nid, impl))) {
  265. TEST_note("iteration %zd, position %zd", i + 1, j + 1);
  266. goto err;
  267. }
  268. }
  269. if (TEST_false(ossl_method_store_remove(store, impls[0].nid, impls[0].impl)))
  270. ret = 1;
  271. err:
  272. ossl_method_store_free(store);
  273. return ret;
  274. }
  275. static int test_property(void)
  276. {
  277. static const struct {
  278. int nid;
  279. const char *prop;
  280. char *impl;
  281. } impls[] = {
  282. { 1, "fast=no, colour=green", "a" },
  283. { 1, "fast, colour=blue", "b" },
  284. { 1, "", "-" },
  285. { 9, "sky=blue, furry", "c" },
  286. { 3, NULL, "d" },
  287. { 6, "sky.colour=blue, sky=green, old.data", "e" },
  288. };
  289. static struct {
  290. int nid;
  291. const char *prop;
  292. char *expected;
  293. } queries[] = {
  294. { 1, "fast", "b" },
  295. { 1, "fast=yes", "b" },
  296. { 1, "fast=no, colour=green", "a" },
  297. { 1, "colour=blue, fast", "b" },
  298. { 1, "colour=blue", "b" },
  299. { 9, "furry", "c" },
  300. { 6, "sky.colour=blue", "e" },
  301. { 6, "old.data", "e" },
  302. { 9, "furry=yes, sky=blue", "c" },
  303. { 1, "", "a" },
  304. { 3, "", "d" },
  305. };
  306. OSSL_METHOD_STORE *store;
  307. size_t i;
  308. int ret = 0;
  309. void *result;
  310. if (!TEST_ptr(store = ossl_method_store_new(NULL))
  311. || !add_property_names("fast", "colour", "sky", "furry", NULL))
  312. goto err;
  313. for (i = 0; i < OSSL_NELEM(impls); i++)
  314. if (!TEST_true(ossl_method_store_add(store, NULL, impls[i].nid,
  315. impls[i].prop, impls[i].impl,
  316. &up_ref, &down_ref))) {
  317. TEST_note("iteration %zd", i + 1);
  318. goto err;
  319. }
  320. for (i = 0; i < OSSL_NELEM(queries); i++) {
  321. OSSL_PROPERTY_LIST *pq = NULL;
  322. if (!TEST_true(ossl_method_store_fetch(store, queries[i].nid,
  323. queries[i].prop, &result))
  324. || !TEST_str_eq((char *)result, queries[i].expected)) {
  325. TEST_note("iteration %zd", i + 1);
  326. ossl_property_free(pq);
  327. goto err;
  328. }
  329. ossl_property_free(pq);
  330. }
  331. ret = 1;
  332. err:
  333. ossl_method_store_free(store);
  334. return ret;
  335. }
  336. static int test_query_cache_stochastic(void)
  337. {
  338. const int max = 10000, tail = 10;
  339. OSSL_METHOD_STORE *store;
  340. int i, res = 0;
  341. char buf[50];
  342. void *result;
  343. int errors = 0;
  344. int v[10001];
  345. if (!TEST_ptr(store = ossl_method_store_new(NULL))
  346. || !add_property_names("n", NULL))
  347. goto err;
  348. for (i = 1; i <= max; i++) {
  349. v[i] = 2 * i;
  350. BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
  351. if (!TEST_true(ossl_method_store_add(store, NULL, i, buf, "abc",
  352. &up_ref, &down_ref))
  353. || !TEST_true(ossl_method_store_cache_set(store, i, buf, v + i,
  354. &up_ref, &down_ref))
  355. || !TEST_true(ossl_method_store_cache_set(store, i, "n=1234",
  356. "miss", &up_ref,
  357. &down_ref))) {
  358. TEST_note("iteration %d", i);
  359. goto err;
  360. }
  361. }
  362. for (i = 1; i <= max; i++) {
  363. BIO_snprintf(buf, sizeof(buf), "n=%d\n", i);
  364. if (!ossl_method_store_cache_get(store, i, buf, &result)
  365. || result != v + i)
  366. errors++;
  367. }
  368. /* There is a tiny probability that this will fail when it shouldn't */
  369. res = TEST_int_gt(errors, tail) && TEST_int_lt(errors, max - tail);
  370. err:
  371. ossl_method_store_free(store);
  372. return res;
  373. }
  374. static int test_fips_mode(void)
  375. {
  376. int ret = 0;
  377. OSSL_LIB_CTX *ctx = NULL;
  378. if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()))
  379. goto err;
  380. ret = TEST_true(EVP_set_default_properties(ctx, "default=yes,fips=yes"))
  381. && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
  382. && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
  383. && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
  384. && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
  385. && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
  386. && TEST_true(EVP_set_default_properties(ctx, "fips!=no"))
  387. && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
  388. && TEST_true(EVP_set_default_properties(ctx, "fips=no"))
  389. && TEST_false(EVP_default_properties_is_fips_enabled(ctx))
  390. && TEST_true(EVP_set_default_properties(ctx, "fips=no,default=yes"))
  391. && TEST_true(EVP_default_properties_enable_fips(ctx, 1))
  392. && TEST_true(EVP_default_properties_is_fips_enabled(ctx))
  393. && TEST_true(EVP_default_properties_enable_fips(ctx, 0))
  394. && TEST_false(EVP_default_properties_is_fips_enabled(ctx));
  395. err:
  396. OSSL_LIB_CTX_free(ctx);
  397. return ret;
  398. }
  399. static struct {
  400. const char *in;
  401. const char *out;
  402. } to_string_tests[] = {
  403. { "fips=yes", "fips=yes" },
  404. { "fips!=yes", "fips!=yes" },
  405. { "fips = yes", "fips=yes" },
  406. { "fips", "fips=yes" },
  407. { "fips=no", "fips=no" },
  408. { "-fips", "-fips" },
  409. { "?fips=yes", "?fips=yes" },
  410. { "fips=yes,provider=fips", "fips=yes,provider=fips" },
  411. { "fips = yes , provider = fips", "fips=yes,provider=fips" },
  412. { "fips=yes,provider!=fips", "fips=yes,provider!=fips" },
  413. { "fips=yes,?provider=fips", "fips=yes,?provider=fips" },
  414. { "fips=yes,-provider", "fips=yes,-provider" },
  415. /* foo is an unknown internal name */
  416. { "foo=yes,fips=yes", "fips=yes"},
  417. { "", "" },
  418. { "fips=3", "fips=3" },
  419. { "fips=-3", "fips=-3" },
  420. { NULL, "" }
  421. };
  422. static int test_property_list_to_string(int i)
  423. {
  424. OSSL_PROPERTY_LIST *pl = NULL;
  425. int ret = 0;
  426. size_t bufsize;
  427. char *buf = NULL;
  428. if (to_string_tests[i].in != NULL
  429. && !TEST_ptr(pl = ossl_parse_query(NULL, to_string_tests[i].in, 1)))
  430. goto err;
  431. bufsize = ossl_property_list_to_string(NULL, pl, NULL, 0);
  432. if (!TEST_size_t_gt(bufsize, 0))
  433. goto err;
  434. buf = OPENSSL_malloc(bufsize);
  435. if (!TEST_ptr(buf)
  436. || !TEST_size_t_eq(ossl_property_list_to_string(NULL, pl, buf,
  437. bufsize),
  438. bufsize)
  439. || !TEST_str_eq(to_string_tests[i].out, buf)
  440. || !TEST_size_t_eq(bufsize, strlen(to_string_tests[i].out) + 1))
  441. goto err;
  442. ret = 1;
  443. err:
  444. OPENSSL_free(buf);
  445. ossl_property_free(pl);
  446. return ret;
  447. }
  448. int setup_tests(void)
  449. {
  450. ADD_TEST(test_property_string);
  451. ADD_TEST(test_property_query_value_create);
  452. ADD_ALL_TESTS(test_property_parse, OSSL_NELEM(parser_tests));
  453. ADD_ALL_TESTS(test_property_merge, OSSL_NELEM(merge_tests));
  454. ADD_TEST(test_property_defn_cache);
  455. ADD_ALL_TESTS(test_definition_compares, OSSL_NELEM(definition_tests));
  456. ADD_TEST(test_register_deregister);
  457. ADD_TEST(test_property);
  458. ADD_TEST(test_query_cache_stochastic);
  459. ADD_TEST(test_fips_mode);
  460. ADD_ALL_TESTS(test_property_list_to_string, OSSL_NELEM(to_string_tests));
  461. return 1;
  462. }