property_parse.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. /*
  2. * Copyright 2019-2020 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 <string.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include <openssl/err.h>
  14. #include "internal/propertyerr.h"
  15. #include "internal/property.h"
  16. #include "crypto/ctype.h"
  17. #include "internal/nelem.h"
  18. #include "property_local.h"
  19. #include "e_os.h"
  20. typedef enum {
  21. PROPERTY_TYPE_STRING, PROPERTY_TYPE_NUMBER,
  22. PROPERTY_TYPE_VALUE_UNDEFINED
  23. } PROPERTY_TYPE;
  24. typedef enum {
  25. PROPERTY_OPER_EQ, PROPERTY_OPER_NE, PROPERTY_OVERRIDE
  26. } PROPERTY_OPER;
  27. typedef struct {
  28. OSSL_PROPERTY_IDX name_idx;
  29. PROPERTY_TYPE type;
  30. PROPERTY_OPER oper;
  31. unsigned int optional : 1;
  32. union {
  33. int64_t int_val; /* Signed integer */
  34. OSSL_PROPERTY_IDX str_val; /* String */
  35. } v;
  36. } PROPERTY_DEFINITION;
  37. struct ossl_property_list_st {
  38. int n;
  39. unsigned int has_optional : 1;
  40. PROPERTY_DEFINITION properties[1];
  41. };
  42. static OSSL_PROPERTY_IDX ossl_property_true, ossl_property_false;
  43. DEFINE_STACK_OF(PROPERTY_DEFINITION)
  44. static const char *skip_space(const char *s)
  45. {
  46. while (ossl_isspace(*s))
  47. s++;
  48. return s;
  49. }
  50. static int match_ch(const char *t[], char m)
  51. {
  52. const char *s = *t;
  53. if (*s == m) {
  54. *t = skip_space(s + 1);
  55. return 1;
  56. }
  57. return 0;
  58. }
  59. #define MATCH(s, m) match(s, m, sizeof(m) - 1)
  60. static int match(const char *t[], const char m[], size_t m_len)
  61. {
  62. const char *s = *t;
  63. if (strncasecmp(s, m, m_len) == 0) {
  64. *t = skip_space(s + m_len);
  65. return 1;
  66. }
  67. return 0;
  68. }
  69. static int parse_name(OPENSSL_CTX *ctx, const char *t[], int create,
  70. OSSL_PROPERTY_IDX *idx)
  71. {
  72. char name[100];
  73. int err = 0;
  74. size_t i = 0;
  75. const char *s = *t;
  76. int user_name = 0;
  77. for (;;) {
  78. if (!ossl_isalpha(*s)) {
  79. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
  80. "HERE-->%s", *t);
  81. return 0;
  82. }
  83. do {
  84. if (i < sizeof(name) - 1)
  85. name[i++] = ossl_tolower(*s);
  86. else
  87. err = 1;
  88. } while (*++s == '_' || ossl_isalnum(*s));
  89. if (*s != '.')
  90. break;
  91. user_name = 1;
  92. if (i < sizeof(name) - 1)
  93. name[i++] = *s;
  94. else
  95. err = 1;
  96. s++;
  97. }
  98. name[i] = '\0';
  99. if (err) {
  100. ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
  101. return 0;
  102. }
  103. *t = skip_space(s);
  104. *idx = ossl_property_name(ctx, name, user_name && create);
  105. return 1;
  106. }
  107. static int parse_number(const char *t[], PROPERTY_DEFINITION *res)
  108. {
  109. const char *s = *t;
  110. int64_t v = 0;
  111. if (!ossl_isdigit(*s))
  112. return 0;
  113. do {
  114. v = v * 10 + (*s++ - '0');
  115. } while (ossl_isdigit(*s));
  116. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  117. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
  118. "HERE-->%s", *t);
  119. return 0;
  120. }
  121. *t = skip_space(s);
  122. res->type = PROPERTY_TYPE_NUMBER;
  123. res->v.int_val = v;
  124. return 1;
  125. }
  126. static int parse_hex(const char *t[], PROPERTY_DEFINITION *res)
  127. {
  128. const char *s = *t;
  129. int64_t v = 0;
  130. if (!ossl_isxdigit(*s))
  131. return 0;
  132. do {
  133. v <<= 4;
  134. if (ossl_isdigit(*s))
  135. v += *s - '0';
  136. else
  137. v += ossl_tolower(*s) - 'a';
  138. } while (ossl_isxdigit(*++s));
  139. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  140. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
  141. "HERE-->%s", *t);
  142. return 0;
  143. }
  144. *t = skip_space(s);
  145. res->type = PROPERTY_TYPE_NUMBER;
  146. res->v.int_val = v;
  147. return 1;
  148. }
  149. static int parse_oct(const char *t[], PROPERTY_DEFINITION *res)
  150. {
  151. const char *s = *t;
  152. int64_t v = 0;
  153. if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
  154. return 0;
  155. do {
  156. v = (v << 3) + (*s - '0');
  157. } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
  158. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  159. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
  160. "HERE-->%s", *t);
  161. return 0;
  162. }
  163. *t = skip_space(s);
  164. res->type = PROPERTY_TYPE_NUMBER;
  165. res->v.int_val = v;
  166. return 1;
  167. }
  168. static int parse_string(OPENSSL_CTX *ctx, const char *t[], char delim,
  169. PROPERTY_DEFINITION *res, const int create)
  170. {
  171. char v[1000];
  172. const char *s = *t;
  173. size_t i = 0;
  174. int err = 0;
  175. while (*s != '\0' && *s != delim) {
  176. if (i < sizeof(v) - 1)
  177. v[i++] = *s;
  178. else
  179. err = 1;
  180. s++;
  181. }
  182. if (*s == '\0') {
  183. ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER,
  184. "HERE-->%c%s", delim, *t);
  185. return 0;
  186. }
  187. v[i] = '\0';
  188. if (err) {
  189. ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
  190. } else {
  191. res->v.str_val = ossl_property_value(ctx, v, create);
  192. }
  193. *t = skip_space(s + 1);
  194. res->type = PROPERTY_TYPE_STRING;
  195. return !err;
  196. }
  197. static int parse_unquoted(OPENSSL_CTX *ctx, const char *t[],
  198. PROPERTY_DEFINITION *res, const int create)
  199. {
  200. char v[1000];
  201. const char *s = *t;
  202. size_t i = 0;
  203. int err = 0;
  204. if (*s == '\0' || *s == ',')
  205. return 0;
  206. while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
  207. if (i < sizeof(v) - 1)
  208. v[i++] = ossl_tolower(*s);
  209. else
  210. err = 1;
  211. s++;
  212. }
  213. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  214. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
  215. "HERE-->%s", s);
  216. return 0;
  217. }
  218. v[i] = 0;
  219. if (err) {
  220. ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
  221. } else {
  222. res->v.str_val = ossl_property_value(ctx, v, create);
  223. }
  224. *t = skip_space(s);
  225. res->type = PROPERTY_TYPE_STRING;
  226. return !err;
  227. }
  228. static int parse_value(OPENSSL_CTX *ctx, const char *t[],
  229. PROPERTY_DEFINITION *res, int create)
  230. {
  231. const char *s = *t;
  232. int r = 0;
  233. if (*s == '"' || *s == '\'') {
  234. s++;
  235. r = parse_string(ctx, &s, s[-1], res, create);
  236. } else if (*s == '+') {
  237. s++;
  238. r = parse_number(&s, res);
  239. } else if (*s == '-') {
  240. s++;
  241. r = parse_number(&s, res);
  242. res->v.int_val = -res->v.int_val;
  243. } else if (*s == '0' && s[1] == 'x') {
  244. s += 2;
  245. r = parse_hex(&s, res);
  246. } else if (*s == '0' && ossl_isdigit(s[1])) {
  247. s++;
  248. r = parse_oct(&s, res);
  249. } else if (ossl_isdigit(*s)) {
  250. return parse_number(t, res);
  251. } else if (ossl_isalpha(*s))
  252. return parse_unquoted(ctx, t, res, create);
  253. if (r)
  254. *t = s;
  255. return r;
  256. }
  257. static int pd_compare(const PROPERTY_DEFINITION *const *p1,
  258. const PROPERTY_DEFINITION *const *p2)
  259. {
  260. const PROPERTY_DEFINITION *pd1 = *p1;
  261. const PROPERTY_DEFINITION *pd2 = *p2;
  262. if (pd1->name_idx < pd2->name_idx)
  263. return -1;
  264. if (pd1->name_idx > pd2->name_idx)
  265. return 1;
  266. return 0;
  267. }
  268. static void pd_free(PROPERTY_DEFINITION *pd)
  269. {
  270. OPENSSL_free(pd);
  271. }
  272. /*
  273. * Convert a stack of property definitions and queries into a fixed array.
  274. * The items are sorted for efficient query. The stack is not freed.
  275. */
  276. static OSSL_PROPERTY_LIST *stack_to_property_list(STACK_OF(PROPERTY_DEFINITION)
  277. *sk)
  278. {
  279. const int n = sk_PROPERTY_DEFINITION_num(sk);
  280. OSSL_PROPERTY_LIST *r;
  281. int i;
  282. r = OPENSSL_malloc(sizeof(*r)
  283. + (n <= 0 ? 0 : n - 1) * sizeof(r->properties[0]));
  284. if (r != NULL) {
  285. sk_PROPERTY_DEFINITION_sort(sk);
  286. r->has_optional = 0;
  287. for (i = 0; i < n; i++) {
  288. r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
  289. r->has_optional |= r->properties[i].optional;
  290. }
  291. r->n = n;
  292. }
  293. return r;
  294. }
  295. OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
  296. {
  297. PROPERTY_DEFINITION *prop = NULL;
  298. OSSL_PROPERTY_LIST *res = NULL;
  299. STACK_OF(PROPERTY_DEFINITION) *sk;
  300. const char *s = defn;
  301. int done;
  302. if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
  303. return NULL;
  304. s = skip_space(s);
  305. done = *s == '\0';
  306. while (!done) {
  307. const char *start = s;
  308. prop = OPENSSL_malloc(sizeof(*prop));
  309. if (prop == NULL)
  310. goto err;
  311. memset(&prop->v, 0, sizeof(prop->v));
  312. prop->optional = 0;
  313. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  314. goto err;
  315. prop->oper = PROPERTY_OPER_EQ;
  316. if (prop->name_idx == 0) {
  317. ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
  318. "Unknown name HERE-->%s", start);
  319. goto err;
  320. }
  321. if (match_ch(&s, '=')) {
  322. if (!parse_value(ctx, &s, prop, 1)) {
  323. ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
  324. "HERE-->%s", start);
  325. goto err;
  326. }
  327. } else {
  328. /* A name alone means a true Boolean */
  329. prop->type = PROPERTY_TYPE_STRING;
  330. prop->v.str_val = ossl_property_true;
  331. }
  332. if (!sk_PROPERTY_DEFINITION_push(sk, prop))
  333. goto err;
  334. prop = NULL;
  335. done = !match_ch(&s, ',');
  336. }
  337. if (*s != '\0') {
  338. ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
  339. "HERE-->%s", s);
  340. goto err;
  341. }
  342. res = stack_to_property_list(sk);
  343. err:
  344. OPENSSL_free(prop);
  345. sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
  346. return res;
  347. }
  348. OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s)
  349. {
  350. STACK_OF(PROPERTY_DEFINITION) *sk;
  351. OSSL_PROPERTY_LIST *res = NULL;
  352. PROPERTY_DEFINITION *prop = NULL;
  353. int done;
  354. if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
  355. return NULL;
  356. s = skip_space(s);
  357. done = *s == '\0';
  358. while (!done) {
  359. prop = OPENSSL_malloc(sizeof(*prop));
  360. if (prop == NULL)
  361. goto err;
  362. memset(&prop->v, 0, sizeof(prop->v));
  363. if (match_ch(&s, '-')) {
  364. prop->oper = PROPERTY_OVERRIDE;
  365. prop->optional = 0;
  366. if (!parse_name(ctx, &s, 0, &prop->name_idx))
  367. goto err;
  368. goto skip_value;
  369. }
  370. prop->optional = match_ch(&s, '?');
  371. if (!parse_name(ctx, &s, 0, &prop->name_idx))
  372. goto err;
  373. if (match_ch(&s, '=')) {
  374. prop->oper = PROPERTY_OPER_EQ;
  375. } else if (MATCH(&s, "!=")) {
  376. prop->oper = PROPERTY_OPER_NE;
  377. } else {
  378. /* A name alone is a Boolean comparison for true */
  379. prop->oper = PROPERTY_OPER_EQ;
  380. prop->type = PROPERTY_TYPE_STRING;
  381. prop->v.str_val = ossl_property_true;
  382. goto skip_value;
  383. }
  384. if (!parse_value(ctx, &s, prop, 0))
  385. prop->type = PROPERTY_TYPE_VALUE_UNDEFINED;
  386. skip_value:
  387. if (!sk_PROPERTY_DEFINITION_push(sk, prop))
  388. goto err;
  389. prop = NULL;
  390. done = !match_ch(&s, ',');
  391. }
  392. if (*s != '\0') {
  393. ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
  394. "HERE-->%s", s);
  395. goto err;
  396. }
  397. res = stack_to_property_list(sk);
  398. err:
  399. OPENSSL_free(prop);
  400. sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
  401. return res;
  402. }
  403. /* Does a property query have any optional clauses */
  404. int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
  405. {
  406. return query->has_optional ? 1 : 0;
  407. }
  408. int ossl_property_is_enabled(OPENSSL_CTX *ctx, const char *property_name,
  409. const OSSL_PROPERTY_LIST *prop_list)
  410. {
  411. int i;
  412. OSSL_PROPERTY_IDX name_id;
  413. const PROPERTY_DEFINITION *prop = NULL;
  414. if (prop_list == NULL)
  415. return 0;
  416. if (!parse_name(ctx, &property_name, 0, &name_id))
  417. return 0;
  418. prop = prop_list->properties;
  419. for (i = 0; i < prop_list->n; ++i) {
  420. if (prop[i].name_idx == name_id) {
  421. /* Do a separate check for override as it does not set type */
  422. if (prop[i].optional || prop[i].oper == PROPERTY_OVERRIDE)
  423. return 0;
  424. return (prop[i].type == PROPERTY_TYPE_STRING
  425. && ((prop[i].oper == PROPERTY_OPER_EQ
  426. && prop[i].v.str_val == ossl_property_true)
  427. || (prop[i].oper == PROPERTY_OPER_NE
  428. && prop[i].v.str_val != ossl_property_true)));
  429. }
  430. }
  431. return 0;
  432. }
  433. /*
  434. * Compare a query against a definition.
  435. * Return the number of clauses matched or -1 if a mandatory clause is false.
  436. */
  437. int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
  438. const OSSL_PROPERTY_LIST *defn)
  439. {
  440. const PROPERTY_DEFINITION *const q = query->properties;
  441. const PROPERTY_DEFINITION *const d = defn->properties;
  442. int i = 0, j = 0, matches = 0;
  443. PROPERTY_OPER oper;
  444. while (i < query->n) {
  445. if ((oper = q[i].oper) == PROPERTY_OVERRIDE) {
  446. i++;
  447. continue;
  448. }
  449. if (j < defn->n) {
  450. if (q[i].name_idx > d[j].name_idx) { /* skip defn, not in query */
  451. j++;
  452. continue;
  453. }
  454. if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
  455. const int eq = q[i].type == d[j].type
  456. && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
  457. if ((eq && oper == PROPERTY_OPER_EQ)
  458. || (!eq && oper == PROPERTY_OPER_NE))
  459. matches++;
  460. else if (!q[i].optional)
  461. return -1;
  462. i++;
  463. j++;
  464. continue;
  465. }
  466. }
  467. /*
  468. * Handle the cases of a missing value and a query with no corresponding
  469. * definition. The former fails for any comparison except inequality,
  470. * the latter is treated as a comparison against the Boolean false.
  471. */
  472. if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
  473. if (oper == PROPERTY_OPER_NE)
  474. matches++;
  475. else if (!q[i].optional)
  476. return -1;
  477. } else if (q[i].type != PROPERTY_TYPE_STRING
  478. || (oper == PROPERTY_OPER_EQ
  479. && q[i].v.str_val != ossl_property_false)
  480. || (oper == PROPERTY_OPER_NE
  481. && q[i].v.str_val == ossl_property_false)) {
  482. if (!q[i].optional)
  483. return -1;
  484. } else {
  485. matches++;
  486. }
  487. i++;
  488. }
  489. return matches;
  490. }
  491. void ossl_property_free(OSSL_PROPERTY_LIST *p)
  492. {
  493. OPENSSL_free(p);
  494. }
  495. /*
  496. * Merge two property lists.
  497. * If there is a common name, the one from the first list is used.
  498. */
  499. OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
  500. const OSSL_PROPERTY_LIST *b)
  501. {
  502. const PROPERTY_DEFINITION *const ap = a->properties;
  503. const PROPERTY_DEFINITION *const bp = b->properties;
  504. const PROPERTY_DEFINITION *copy;
  505. OSSL_PROPERTY_LIST *r;
  506. int i, j, n;
  507. const int t = a->n + b->n;
  508. r = OPENSSL_malloc(sizeof(*r)
  509. + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
  510. if (r == NULL)
  511. return NULL;
  512. r->has_optional = 0;
  513. for (i = j = n = 0; i < a->n || j < b->n; n++) {
  514. if (i >= a->n) {
  515. copy = &bp[j++];
  516. } else if (j >= b->n) {
  517. copy = &ap[i++];
  518. } else if (ap[i].name_idx <= bp[j].name_idx) {
  519. if (ap[i].name_idx == bp[j].name_idx)
  520. j++;
  521. copy = &ap[i++];
  522. } else {
  523. copy = &bp[j++];
  524. }
  525. memcpy(r->properties + n, copy, sizeof(r->properties[0]));
  526. r->has_optional |= copy->optional;
  527. }
  528. r->n = n;
  529. if (n != t)
  530. r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
  531. return r;
  532. }
  533. int ossl_property_parse_init(OPENSSL_CTX *ctx)
  534. {
  535. static const char *const predefined_names[] = {
  536. "provider", /* Name of provider (default, legacy, fips) */
  537. "version", /* Version number of this provider */
  538. "fips", /* FIPS validated or FIPS supporting algorithm */
  539. "format", /* output format for serializers */
  540. "type", /* output type for serializers */
  541. };
  542. size_t i;
  543. for (i = 0; i < OSSL_NELEM(predefined_names); i++)
  544. if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
  545. goto err;
  546. /* Pre-populate the two Boolean values */
  547. if ((ossl_property_true = ossl_property_value(ctx, "yes", 1)) == 0
  548. || (ossl_property_false = ossl_property_value(ctx, "no", 1)) == 0)
  549. goto err;
  550. return 1;
  551. err:
  552. return 0;
  553. }