property_parse.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  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. #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 "internal/e_os.h"
  20. DEFINE_STACK_OF(OSSL_PROPERTY_DEFINITION)
  21. static const char *skip_space(const char *s)
  22. {
  23. while (ossl_isspace(*s))
  24. s++;
  25. return s;
  26. }
  27. static int match_ch(const char *t[], char m)
  28. {
  29. const char *s = *t;
  30. if (*s == m) {
  31. *t = skip_space(s + 1);
  32. return 1;
  33. }
  34. return 0;
  35. }
  36. #define MATCH(s, m) match(s, m, sizeof(m) - 1)
  37. static int match(const char *t[], const char m[], size_t m_len)
  38. {
  39. const char *s = *t;
  40. if (OPENSSL_strncasecmp(s, m, m_len) == 0) {
  41. *t = skip_space(s + m_len);
  42. return 1;
  43. }
  44. return 0;
  45. }
  46. static int parse_name(OSSL_LIB_CTX *ctx, const char *t[], int create,
  47. OSSL_PROPERTY_IDX *idx)
  48. {
  49. char name[100];
  50. int err = 0;
  51. size_t i = 0;
  52. const char *s = *t;
  53. int user_name = 0;
  54. for (;;) {
  55. if (!ossl_isalpha(*s)) {
  56. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
  57. "HERE-->%s", *t);
  58. return 0;
  59. }
  60. do {
  61. if (i < sizeof(name) - 1)
  62. name[i++] = ossl_tolower(*s);
  63. else
  64. err = 1;
  65. } while (*++s == '_' || ossl_isalnum(*s));
  66. if (*s != '.')
  67. break;
  68. user_name = 1;
  69. if (i < sizeof(name) - 1)
  70. name[i++] = *s;
  71. else
  72. err = 1;
  73. s++;
  74. }
  75. name[i] = '\0';
  76. if (err) {
  77. ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
  78. return 0;
  79. }
  80. *t = skip_space(s);
  81. *idx = ossl_property_name(ctx, name, user_name && create);
  82. return 1;
  83. }
  84. static int parse_number(const char *t[], OSSL_PROPERTY_DEFINITION *res)
  85. {
  86. const char *s = *t;
  87. int64_t v = 0;
  88. if (!ossl_isdigit(*s))
  89. return 0;
  90. do {
  91. v = v * 10 + (*s++ - '0');
  92. } while (ossl_isdigit(*s));
  93. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  94. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
  95. "HERE-->%s", *t);
  96. return 0;
  97. }
  98. *t = skip_space(s);
  99. res->type = OSSL_PROPERTY_TYPE_NUMBER;
  100. res->v.int_val = v;
  101. return 1;
  102. }
  103. static int parse_hex(const char *t[], OSSL_PROPERTY_DEFINITION *res)
  104. {
  105. const char *s = *t;
  106. int64_t v = 0;
  107. if (!ossl_isxdigit(*s))
  108. return 0;
  109. do {
  110. v <<= 4;
  111. if (ossl_isdigit(*s))
  112. v += *s - '0';
  113. else
  114. v += ossl_tolower(*s) - 'a';
  115. } while (ossl_isxdigit(*++s));
  116. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  117. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
  118. "HERE-->%s", *t);
  119. return 0;
  120. }
  121. *t = skip_space(s);
  122. res->type = OSSL_PROPERTY_TYPE_NUMBER;
  123. res->v.int_val = v;
  124. return 1;
  125. }
  126. static int parse_oct(const char *t[], OSSL_PROPERTY_DEFINITION *res)
  127. {
  128. const char *s = *t;
  129. int64_t v = 0;
  130. if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
  131. return 0;
  132. do {
  133. v = (v << 3) + (*s - '0');
  134. } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
  135. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  136. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
  137. "HERE-->%s", *t);
  138. return 0;
  139. }
  140. *t = skip_space(s);
  141. res->type = OSSL_PROPERTY_TYPE_NUMBER;
  142. res->v.int_val = v;
  143. return 1;
  144. }
  145. static int parse_string(OSSL_LIB_CTX *ctx, const char *t[], char delim,
  146. OSSL_PROPERTY_DEFINITION *res, const int create)
  147. {
  148. char v[1000];
  149. const char *s = *t;
  150. size_t i = 0;
  151. int err = 0;
  152. while (*s != '\0' && *s != delim) {
  153. if (i < sizeof(v) - 1)
  154. v[i++] = *s;
  155. else
  156. err = 1;
  157. s++;
  158. }
  159. if (*s == '\0') {
  160. ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER,
  161. "HERE-->%c%s", delim, *t);
  162. return 0;
  163. }
  164. v[i] = '\0';
  165. if (err) {
  166. ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
  167. } else {
  168. res->v.str_val = ossl_property_value(ctx, v, create);
  169. }
  170. *t = skip_space(s + 1);
  171. res->type = OSSL_PROPERTY_TYPE_STRING;
  172. return !err;
  173. }
  174. static int parse_unquoted(OSSL_LIB_CTX *ctx, const char *t[],
  175. OSSL_PROPERTY_DEFINITION *res, const int create)
  176. {
  177. char v[1000];
  178. const char *s = *t;
  179. size_t i = 0;
  180. int err = 0;
  181. if (*s == '\0' || *s == ',')
  182. return 0;
  183. while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
  184. if (i < sizeof(v) - 1)
  185. v[i++] = ossl_tolower(*s);
  186. else
  187. err = 1;
  188. s++;
  189. }
  190. if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
  191. ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
  192. "HERE-->%s", s);
  193. return 0;
  194. }
  195. v[i] = 0;
  196. if (err)
  197. ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
  198. else if ((res->v.str_val = ossl_property_value(ctx, v, create)) == 0)
  199. err = 1;
  200. *t = skip_space(s);
  201. res->type = OSSL_PROPERTY_TYPE_STRING;
  202. return !err;
  203. }
  204. static int parse_value(OSSL_LIB_CTX *ctx, const char *t[],
  205. OSSL_PROPERTY_DEFINITION *res, int create)
  206. {
  207. const char *s = *t;
  208. int r = 0;
  209. if (*s == '"' || *s == '\'') {
  210. s++;
  211. r = parse_string(ctx, &s, s[-1], res, create);
  212. } else if (*s == '+') {
  213. s++;
  214. r = parse_number(&s, res);
  215. } else if (*s == '-') {
  216. s++;
  217. r = parse_number(&s, res);
  218. res->v.int_val = -res->v.int_val;
  219. } else if (*s == '0' && s[1] == 'x') {
  220. s += 2;
  221. r = parse_hex(&s, res);
  222. } else if (*s == '0' && ossl_isdigit(s[1])) {
  223. s++;
  224. r = parse_oct(&s, res);
  225. } else if (ossl_isdigit(*s)) {
  226. return parse_number(t, res);
  227. } else if (ossl_isalpha(*s))
  228. return parse_unquoted(ctx, t, res, create);
  229. if (r)
  230. *t = s;
  231. return r;
  232. }
  233. static int pd_compare(const OSSL_PROPERTY_DEFINITION *const *p1,
  234. const OSSL_PROPERTY_DEFINITION *const *p2)
  235. {
  236. const OSSL_PROPERTY_DEFINITION *pd1 = *p1;
  237. const OSSL_PROPERTY_DEFINITION *pd2 = *p2;
  238. if (pd1->name_idx < pd2->name_idx)
  239. return -1;
  240. if (pd1->name_idx > pd2->name_idx)
  241. return 1;
  242. return 0;
  243. }
  244. static void pd_free(OSSL_PROPERTY_DEFINITION *pd)
  245. {
  246. OPENSSL_free(pd);
  247. }
  248. /*
  249. * Convert a stack of property definitions and queries into a fixed array.
  250. * The items are sorted for efficient query. The stack is not freed.
  251. * This function also checks for duplicated names and returns an error if
  252. * any exist.
  253. */
  254. static OSSL_PROPERTY_LIST *
  255. stack_to_property_list(OSSL_LIB_CTX *ctx,
  256. STACK_OF(OSSL_PROPERTY_DEFINITION) *sk)
  257. {
  258. const int n = sk_OSSL_PROPERTY_DEFINITION_num(sk);
  259. OSSL_PROPERTY_LIST *r;
  260. OSSL_PROPERTY_IDX prev_name_idx = 0;
  261. int i;
  262. r = OPENSSL_malloc(sizeof(*r)
  263. + (n <= 0 ? 0 : n - 1) * sizeof(r->properties[0]));
  264. if (r != NULL) {
  265. sk_OSSL_PROPERTY_DEFINITION_sort(sk);
  266. r->has_optional = 0;
  267. for (i = 0; i < n; i++) {
  268. r->properties[i] = *sk_OSSL_PROPERTY_DEFINITION_value(sk, i);
  269. r->has_optional |= r->properties[i].optional;
  270. /* Check for duplicated names */
  271. if (i > 0 && r->properties[i].name_idx == prev_name_idx) {
  272. OPENSSL_free(r);
  273. ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
  274. "Duplicated name `%s'",
  275. ossl_property_name_str(ctx, prev_name_idx));
  276. return NULL;
  277. }
  278. prev_name_idx = r->properties[i].name_idx;
  279. }
  280. r->num_properties = n;
  281. }
  282. return r;
  283. }
  284. OSSL_PROPERTY_LIST *ossl_parse_property(OSSL_LIB_CTX *ctx, const char *defn)
  285. {
  286. OSSL_PROPERTY_DEFINITION *prop = NULL;
  287. OSSL_PROPERTY_LIST *res = NULL;
  288. STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
  289. const char *s = defn;
  290. int done;
  291. if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
  292. return NULL;
  293. s = skip_space(s);
  294. done = *s == '\0';
  295. while (!done) {
  296. const char *start = s;
  297. prop = OPENSSL_malloc(sizeof(*prop));
  298. if (prop == NULL)
  299. goto err;
  300. memset(&prop->v, 0, sizeof(prop->v));
  301. prop->optional = 0;
  302. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  303. goto err;
  304. prop->oper = OSSL_PROPERTY_OPER_EQ;
  305. if (prop->name_idx == 0) {
  306. ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
  307. "Unknown name HERE-->%s", start);
  308. goto err;
  309. }
  310. if (match_ch(&s, '=')) {
  311. if (!parse_value(ctx, &s, prop, 1)) {
  312. ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
  313. "HERE-->%s", start);
  314. goto err;
  315. }
  316. } else {
  317. /* A name alone means a true Boolean */
  318. prop->type = OSSL_PROPERTY_TYPE_STRING;
  319. prop->v.str_val = OSSL_PROPERTY_TRUE;
  320. }
  321. if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
  322. goto err;
  323. prop = NULL;
  324. done = !match_ch(&s, ',');
  325. }
  326. if (*s != '\0') {
  327. ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
  328. "HERE-->%s", s);
  329. goto err;
  330. }
  331. res = stack_to_property_list(ctx, sk);
  332. err:
  333. OPENSSL_free(prop);
  334. sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
  335. return res;
  336. }
  337. OSSL_PROPERTY_LIST *ossl_parse_query(OSSL_LIB_CTX *ctx, const char *s,
  338. int create_values)
  339. {
  340. STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
  341. OSSL_PROPERTY_LIST *res = NULL;
  342. OSSL_PROPERTY_DEFINITION *prop = NULL;
  343. int done;
  344. if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
  345. return NULL;
  346. s = skip_space(s);
  347. done = *s == '\0';
  348. while (!done) {
  349. prop = OPENSSL_malloc(sizeof(*prop));
  350. if (prop == NULL)
  351. goto err;
  352. memset(&prop->v, 0, sizeof(prop->v));
  353. if (match_ch(&s, '-')) {
  354. prop->oper = OSSL_PROPERTY_OVERRIDE;
  355. prop->optional = 0;
  356. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  357. goto err;
  358. goto skip_value;
  359. }
  360. prop->optional = match_ch(&s, '?');
  361. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  362. goto err;
  363. if (match_ch(&s, '=')) {
  364. prop->oper = OSSL_PROPERTY_OPER_EQ;
  365. } else if (MATCH(&s, "!=")) {
  366. prop->oper = OSSL_PROPERTY_OPER_NE;
  367. } else {
  368. /* A name alone is a Boolean comparison for true */
  369. prop->oper = OSSL_PROPERTY_OPER_EQ;
  370. prop->type = OSSL_PROPERTY_TYPE_STRING;
  371. prop->v.str_val = OSSL_PROPERTY_TRUE;
  372. goto skip_value;
  373. }
  374. if (!parse_value(ctx, &s, prop, create_values))
  375. prop->type = OSSL_PROPERTY_TYPE_VALUE_UNDEFINED;
  376. skip_value:
  377. if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
  378. goto err;
  379. prop = NULL;
  380. done = !match_ch(&s, ',');
  381. }
  382. if (*s != '\0') {
  383. ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
  384. "HERE-->%s", s);
  385. goto err;
  386. }
  387. res = stack_to_property_list(ctx, sk);
  388. err:
  389. OPENSSL_free(prop);
  390. sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
  391. return res;
  392. }
  393. /*
  394. * Compare a query against a definition.
  395. * Return the number of clauses matched or -1 if a mandatory clause is false.
  396. */
  397. int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
  398. const OSSL_PROPERTY_LIST *defn)
  399. {
  400. const OSSL_PROPERTY_DEFINITION *const q = query->properties;
  401. const OSSL_PROPERTY_DEFINITION *const d = defn->properties;
  402. int i = 0, j = 0, matches = 0;
  403. OSSL_PROPERTY_OPER oper;
  404. while (i < query->num_properties) {
  405. if ((oper = q[i].oper) == OSSL_PROPERTY_OVERRIDE) {
  406. i++;
  407. continue;
  408. }
  409. if (j < defn->num_properties) {
  410. if (q[i].name_idx > d[j].name_idx) { /* skip defn, not in query */
  411. j++;
  412. continue;
  413. }
  414. if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
  415. const int eq = q[i].type == d[j].type
  416. && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
  417. if ((eq && oper == OSSL_PROPERTY_OPER_EQ)
  418. || (!eq && oper == OSSL_PROPERTY_OPER_NE))
  419. matches++;
  420. else if (!q[i].optional)
  421. return -1;
  422. i++;
  423. j++;
  424. continue;
  425. }
  426. }
  427. /*
  428. * Handle the cases of a missing value and a query with no corresponding
  429. * definition. The former fails for any comparison except inequality,
  430. * the latter is treated as a comparison against the Boolean false.
  431. */
  432. if (q[i].type == OSSL_PROPERTY_TYPE_VALUE_UNDEFINED) {
  433. if (oper == OSSL_PROPERTY_OPER_NE)
  434. matches++;
  435. else if (!q[i].optional)
  436. return -1;
  437. } else if (q[i].type != OSSL_PROPERTY_TYPE_STRING
  438. || (oper == OSSL_PROPERTY_OPER_EQ
  439. && q[i].v.str_val != OSSL_PROPERTY_FALSE)
  440. || (oper == OSSL_PROPERTY_OPER_NE
  441. && q[i].v.str_val == OSSL_PROPERTY_FALSE)) {
  442. if (!q[i].optional)
  443. return -1;
  444. } else {
  445. matches++;
  446. }
  447. i++;
  448. }
  449. return matches;
  450. }
  451. void ossl_property_free(OSSL_PROPERTY_LIST *p)
  452. {
  453. OPENSSL_free(p);
  454. }
  455. /*
  456. * Merge two property lists.
  457. * If there is a common name, the one from the first list is used.
  458. */
  459. OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
  460. const OSSL_PROPERTY_LIST *b)
  461. {
  462. const OSSL_PROPERTY_DEFINITION *const ap = a->properties;
  463. const OSSL_PROPERTY_DEFINITION *const bp = b->properties;
  464. const OSSL_PROPERTY_DEFINITION *copy;
  465. OSSL_PROPERTY_LIST *r;
  466. int i, j, n;
  467. const int t = a->num_properties + b->num_properties;
  468. r = OPENSSL_malloc(sizeof(*r)
  469. + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
  470. if (r == NULL)
  471. return NULL;
  472. r->has_optional = 0;
  473. for (i = j = n = 0; i < a->num_properties || j < b->num_properties; n++) {
  474. if (i >= a->num_properties) {
  475. copy = &bp[j++];
  476. } else if (j >= b->num_properties) {
  477. copy = &ap[i++];
  478. } else if (ap[i].name_idx <= bp[j].name_idx) {
  479. if (ap[i].name_idx == bp[j].name_idx)
  480. j++;
  481. copy = &ap[i++];
  482. } else {
  483. copy = &bp[j++];
  484. }
  485. memcpy(r->properties + n, copy, sizeof(r->properties[0]));
  486. r->has_optional |= copy->optional;
  487. }
  488. r->num_properties = n;
  489. if (n != t)
  490. r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
  491. return r;
  492. }
  493. int ossl_property_parse_init(OSSL_LIB_CTX *ctx)
  494. {
  495. static const char *const predefined_names[] = {
  496. "provider", /* Name of provider (default, legacy, fips) */
  497. "version", /* Version number of this provider */
  498. "fips", /* FIPS validated or FIPS supporting algorithm */
  499. "output", /* Output type for encoders */
  500. "input", /* Input type for decoders */
  501. "structure", /* Structure name for encoders and decoders */
  502. };
  503. size_t i;
  504. for (i = 0; i < OSSL_NELEM(predefined_names); i++)
  505. if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
  506. goto err;
  507. /*
  508. * Pre-populate the two Boolean values. We must do them before any other
  509. * values and in this order so that we get the same index as the global
  510. * OSSL_PROPERTY_TRUE and OSSL_PROPERTY_FALSE values
  511. */
  512. if ((ossl_property_value(ctx, "yes", 1) != OSSL_PROPERTY_TRUE)
  513. || (ossl_property_value(ctx, "no", 1) != OSSL_PROPERTY_FALSE))
  514. goto err;
  515. return 1;
  516. err:
  517. return 0;
  518. }
  519. static void put_char(char ch, char **buf, size_t *remain, size_t *needed)
  520. {
  521. if (*remain == 0) {
  522. ++*needed;
  523. return;
  524. }
  525. if (*remain == 1)
  526. **buf = '\0';
  527. else
  528. **buf = ch;
  529. ++*buf;
  530. ++*needed;
  531. --*remain;
  532. }
  533. static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
  534. {
  535. size_t olen, len, i;
  536. char quote = '\0';
  537. int quotes;
  538. len = olen = strlen(str);
  539. *needed += len;
  540. /*
  541. * Check to see if we need quotes or not.
  542. * Characters that are legal in a PropertyName don't need quoting.
  543. * We simply assume all others require quotes.
  544. */
  545. for (i = 0; i < len; i++)
  546. if (!ossl_isalnum(str[i]) && str[i] != '.' && str[i] != '_') {
  547. /* Default to single quotes ... */
  548. if (quote == '\0')
  549. quote = '\'';
  550. /* ... but use double quotes if a single is present */
  551. if (str[i] == '\'')
  552. quote = '"';
  553. }
  554. quotes = quote != '\0';
  555. if (*remain == 0) {
  556. *needed += 2 * quotes;
  557. return;
  558. }
  559. if (quotes)
  560. put_char(quote, buf, remain, needed);
  561. if (*remain < len + 1 + quotes)
  562. len = *remain - 1;
  563. if (len > 0) {
  564. memcpy(*buf, str, len);
  565. *buf += len;
  566. *remain -= len;
  567. }
  568. if (quotes)
  569. put_char(quote, buf, remain, needed);
  570. if (len < olen && *remain == 1) {
  571. **buf = '\0';
  572. ++*buf;
  573. --*remain;
  574. }
  575. }
  576. static void put_num(int64_t val, char **buf, size_t *remain, size_t *needed)
  577. {
  578. int64_t tmpval = val;
  579. size_t len = 1;
  580. if (tmpval < 0) {
  581. len++;
  582. tmpval = -tmpval;
  583. }
  584. for (; tmpval > 9; len++, tmpval /= 10);
  585. *needed += len;
  586. if (*remain == 0)
  587. return;
  588. BIO_snprintf(*buf, *remain, "%lld", (long long int)val);
  589. if (*remain < len) {
  590. *buf += *remain;
  591. *remain = 0;
  592. } else {
  593. *buf += len;
  594. *remain -= len;
  595. }
  596. }
  597. size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
  598. const OSSL_PROPERTY_LIST *list, char *buf,
  599. size_t bufsize)
  600. {
  601. int i;
  602. const OSSL_PROPERTY_DEFINITION *prop = NULL;
  603. size_t needed = 0;
  604. const char *val;
  605. if (list == NULL) {
  606. if (bufsize > 0)
  607. *buf = '\0';
  608. return 1;
  609. }
  610. if (list->num_properties != 0)
  611. prop = &list->properties[list->num_properties - 1];
  612. for (i = 0; i < list->num_properties; i++, prop--) {
  613. /* Skip invalid names */
  614. if (prop->name_idx == 0)
  615. continue;
  616. if (needed > 0)
  617. put_char(',', &buf, &bufsize, &needed);
  618. if (prop->optional)
  619. put_char('?', &buf, &bufsize, &needed);
  620. else if (prop->oper == OSSL_PROPERTY_OVERRIDE)
  621. put_char('-', &buf, &bufsize, &needed);
  622. val = ossl_property_name_str(ctx, prop->name_idx);
  623. if (val == NULL)
  624. return 0;
  625. put_str(val, &buf, &bufsize, &needed);
  626. switch (prop->oper) {
  627. case OSSL_PROPERTY_OPER_NE:
  628. put_char('!', &buf, &bufsize, &needed);
  629. /* fall through */
  630. case OSSL_PROPERTY_OPER_EQ:
  631. put_char('=', &buf, &bufsize, &needed);
  632. /* put value */
  633. switch (prop->type) {
  634. case OSSL_PROPERTY_TYPE_STRING:
  635. val = ossl_property_value_str(ctx, prop->v.str_val);
  636. if (val == NULL)
  637. return 0;
  638. put_str(val, &buf, &bufsize, &needed);
  639. break;
  640. case OSSL_PROPERTY_TYPE_NUMBER:
  641. put_num(prop->v.int_val, &buf, &bufsize, &needed);
  642. break;
  643. default:
  644. return 0;
  645. }
  646. break;
  647. default:
  648. /* do nothing */
  649. break;
  650. }
  651. }
  652. put_char('\0', &buf, &bufsize, &needed);
  653. return needed;
  654. }