property_parse.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  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 <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(OSSL_LIB_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(OSSL_LIB_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(OSSL_LIB_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(OSSL_LIB_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(OSSL_LIB_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(OSSL_LIB_CTX *ctx, const char *s,
  349. int create_values)
  350. {
  351. STACK_OF(PROPERTY_DEFINITION) *sk;
  352. OSSL_PROPERTY_LIST *res = NULL;
  353. PROPERTY_DEFINITION *prop = NULL;
  354. int done;
  355. if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
  356. return NULL;
  357. s = skip_space(s);
  358. done = *s == '\0';
  359. while (!done) {
  360. prop = OPENSSL_malloc(sizeof(*prop));
  361. if (prop == NULL)
  362. goto err;
  363. memset(&prop->v, 0, sizeof(prop->v));
  364. if (match_ch(&s, '-')) {
  365. prop->oper = PROPERTY_OVERRIDE;
  366. prop->optional = 0;
  367. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  368. goto err;
  369. goto skip_value;
  370. }
  371. prop->optional = match_ch(&s, '?');
  372. if (!parse_name(ctx, &s, 1, &prop->name_idx))
  373. goto err;
  374. if (match_ch(&s, '=')) {
  375. prop->oper = PROPERTY_OPER_EQ;
  376. } else if (MATCH(&s, "!=")) {
  377. prop->oper = PROPERTY_OPER_NE;
  378. } else {
  379. /* A name alone is a Boolean comparison for true */
  380. prop->oper = PROPERTY_OPER_EQ;
  381. prop->type = PROPERTY_TYPE_STRING;
  382. prop->v.str_val = ossl_property_true;
  383. goto skip_value;
  384. }
  385. if (!parse_value(ctx, &s, prop, create_values))
  386. prop->type = PROPERTY_TYPE_VALUE_UNDEFINED;
  387. skip_value:
  388. if (!sk_PROPERTY_DEFINITION_push(sk, prop))
  389. goto err;
  390. prop = NULL;
  391. done = !match_ch(&s, ',');
  392. }
  393. if (*s != '\0') {
  394. ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
  395. "HERE-->%s", s);
  396. goto err;
  397. }
  398. res = stack_to_property_list(sk);
  399. err:
  400. OPENSSL_free(prop);
  401. sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
  402. return res;
  403. }
  404. /* Does a property query have any optional clauses */
  405. int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
  406. {
  407. return query->has_optional ? 1 : 0;
  408. }
  409. int ossl_property_is_enabled(OSSL_LIB_CTX *ctx, const char *property_name,
  410. const OSSL_PROPERTY_LIST *prop_list)
  411. {
  412. int i;
  413. OSSL_PROPERTY_IDX name_id;
  414. const PROPERTY_DEFINITION *prop = NULL;
  415. if (prop_list == NULL)
  416. return 0;
  417. if (!parse_name(ctx, &property_name, 0, &name_id))
  418. return 0;
  419. prop = prop_list->properties;
  420. for (i = 0; i < prop_list->n; ++i) {
  421. if (prop[i].name_idx == name_id) {
  422. /* Do a separate check for override as it does not set type */
  423. if (prop[i].optional || prop[i].oper == PROPERTY_OVERRIDE)
  424. return 0;
  425. return (prop[i].type == PROPERTY_TYPE_STRING
  426. && ((prop[i].oper == PROPERTY_OPER_EQ
  427. && prop[i].v.str_val == ossl_property_true)
  428. || (prop[i].oper == PROPERTY_OPER_NE
  429. && prop[i].v.str_val != ossl_property_true)));
  430. }
  431. }
  432. return 0;
  433. }
  434. /*
  435. * Compare a query against a definition.
  436. * Return the number of clauses matched or -1 if a mandatory clause is false.
  437. */
  438. int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
  439. const OSSL_PROPERTY_LIST *defn)
  440. {
  441. const PROPERTY_DEFINITION *const q = query->properties;
  442. const PROPERTY_DEFINITION *const d = defn->properties;
  443. int i = 0, j = 0, matches = 0;
  444. PROPERTY_OPER oper;
  445. while (i < query->n) {
  446. if ((oper = q[i].oper) == PROPERTY_OVERRIDE) {
  447. i++;
  448. continue;
  449. }
  450. if (j < defn->n) {
  451. if (q[i].name_idx > d[j].name_idx) { /* skip defn, not in query */
  452. j++;
  453. continue;
  454. }
  455. if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
  456. const int eq = q[i].type == d[j].type
  457. && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
  458. if ((eq && oper == PROPERTY_OPER_EQ)
  459. || (!eq && oper == PROPERTY_OPER_NE))
  460. matches++;
  461. else if (!q[i].optional)
  462. return -1;
  463. i++;
  464. j++;
  465. continue;
  466. }
  467. }
  468. /*
  469. * Handle the cases of a missing value and a query with no corresponding
  470. * definition. The former fails for any comparison except inequality,
  471. * the latter is treated as a comparison against the Boolean false.
  472. */
  473. if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
  474. if (oper == PROPERTY_OPER_NE)
  475. matches++;
  476. else if (!q[i].optional)
  477. return -1;
  478. } else if (q[i].type != PROPERTY_TYPE_STRING
  479. || (oper == PROPERTY_OPER_EQ
  480. && q[i].v.str_val != ossl_property_false)
  481. || (oper == PROPERTY_OPER_NE
  482. && q[i].v.str_val == ossl_property_false)) {
  483. if (!q[i].optional)
  484. return -1;
  485. } else {
  486. matches++;
  487. }
  488. i++;
  489. }
  490. return matches;
  491. }
  492. void ossl_property_free(OSSL_PROPERTY_LIST *p)
  493. {
  494. OPENSSL_free(p);
  495. }
  496. /*
  497. * Merge two property lists.
  498. * If there is a common name, the one from the first list is used.
  499. */
  500. OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
  501. const OSSL_PROPERTY_LIST *b)
  502. {
  503. const PROPERTY_DEFINITION *const ap = a->properties;
  504. const PROPERTY_DEFINITION *const bp = b->properties;
  505. const PROPERTY_DEFINITION *copy;
  506. OSSL_PROPERTY_LIST *r;
  507. int i, j, n;
  508. const int t = a->n + b->n;
  509. r = OPENSSL_malloc(sizeof(*r)
  510. + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
  511. if (r == NULL)
  512. return NULL;
  513. r->has_optional = 0;
  514. for (i = j = n = 0; i < a->n || j < b->n; n++) {
  515. if (i >= a->n) {
  516. copy = &bp[j++];
  517. } else if (j >= b->n) {
  518. copy = &ap[i++];
  519. } else if (ap[i].name_idx <= bp[j].name_idx) {
  520. if (ap[i].name_idx == bp[j].name_idx)
  521. j++;
  522. copy = &ap[i++];
  523. } else {
  524. copy = &bp[j++];
  525. }
  526. memcpy(r->properties + n, copy, sizeof(r->properties[0]));
  527. r->has_optional |= copy->optional;
  528. }
  529. r->n = n;
  530. if (n != t)
  531. r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
  532. return r;
  533. }
  534. int ossl_property_parse_init(OSSL_LIB_CTX *ctx)
  535. {
  536. static const char *const predefined_names[] = {
  537. "provider", /* Name of provider (default, legacy, fips) */
  538. "version", /* Version number of this provider */
  539. "fips", /* FIPS validated or FIPS supporting algorithm */
  540. "output", /* Output type for encoders */
  541. "input", /* Input type for decoders */
  542. "structure", /* Structure name for encoders and decoders */
  543. };
  544. size_t i;
  545. for (i = 0; i < OSSL_NELEM(predefined_names); i++)
  546. if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
  547. goto err;
  548. /* Pre-populate the two Boolean values */
  549. if ((ossl_property_true = ossl_property_value(ctx, "yes", 1)) == 0
  550. || (ossl_property_false = ossl_property_value(ctx, "no", 1)) == 0)
  551. goto err;
  552. return 1;
  553. err:
  554. return 0;
  555. }
  556. static void put_char(char ch, char **buf, size_t *remain, size_t *needed)
  557. {
  558. if (*remain == 0) {
  559. ++*needed;
  560. return;
  561. }
  562. if(*remain == 1)
  563. **buf = '\0';
  564. else
  565. **buf = ch;
  566. ++*buf;
  567. ++*needed;
  568. --*remain;
  569. }
  570. static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
  571. {
  572. size_t olen, len;
  573. len = olen = strlen(str);
  574. *needed += len;
  575. if (*remain == 0)
  576. return;
  577. if(*remain < len + 1)
  578. len = *remain - 1;
  579. if(len > 0) {
  580. strncpy(*buf, str, len);
  581. *buf += len;
  582. *remain -= len;
  583. }
  584. if(len < olen && *remain == 1) {
  585. **buf = '\0';
  586. ++*buf;
  587. --*remain;
  588. }
  589. }
  590. static void put_num(int64_t val, char **buf, size_t *remain, size_t *needed)
  591. {
  592. int64_t tmpval = val;
  593. size_t len = 1;
  594. if (tmpval < 0) {
  595. len++;
  596. tmpval = -tmpval;
  597. }
  598. for (; tmpval > 9; len++, tmpval /= 10);
  599. *needed += len;
  600. if (*remain == 0)
  601. return;
  602. BIO_snprintf(*buf, *remain, "%lld", (long long int)val);
  603. if (*remain < len) {
  604. *buf += *remain;
  605. *remain = 0;
  606. } else {
  607. *buf += len;
  608. *remain -= len;
  609. }
  610. }
  611. size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
  612. const OSSL_PROPERTY_LIST *list, char *buf,
  613. size_t bufsize)
  614. {
  615. int i;
  616. const PROPERTY_DEFINITION *prop = NULL;
  617. size_t needed = 0;
  618. const char *val;
  619. if (list == NULL) {
  620. if (bufsize > 0)
  621. *buf = '\0';
  622. return 1;
  623. }
  624. if (list->n != 0)
  625. prop = &list->properties[list->n - 1];
  626. for (i = 0; i < list->n; i++, prop--) {
  627. /* Skip invalid names */
  628. if (prop->name_idx == 0)
  629. continue;
  630. if (needed > 0)
  631. put_char(',', &buf, &bufsize, &needed);
  632. if (prop->optional)
  633. put_char('?', &buf, &bufsize, &needed);
  634. else if (prop->oper == PROPERTY_OVERRIDE)
  635. put_char('-', &buf, &bufsize, &needed);
  636. val = ossl_property_name_str(ctx, prop->name_idx);
  637. if (val == NULL)
  638. return 0;
  639. put_str(val, &buf, &bufsize, &needed);
  640. switch (prop->oper) {
  641. case PROPERTY_OPER_NE:
  642. put_char('!', &buf, &bufsize, &needed);
  643. /* fall through */
  644. case PROPERTY_OPER_EQ:
  645. put_char('=', &buf, &bufsize, &needed);
  646. /* put value */
  647. switch (prop->type) {
  648. case PROPERTY_TYPE_STRING:
  649. val = ossl_property_value_str(ctx, prop->v.str_val);
  650. if (val == NULL)
  651. return 0;
  652. put_str(val, &buf, &bufsize, &needed);
  653. break;
  654. case PROPERTY_TYPE_NUMBER:
  655. put_num(prop->v.int_val, &buf, &bufsize, &needed);
  656. break;
  657. default:
  658. return 0;
  659. }
  660. break;
  661. default:
  662. /* do nothing */
  663. break;
  664. }
  665. }
  666. put_char('\0', &buf, &bufsize, &needed);
  667. return needed;
  668. }