VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.5/crypto/property/property_parse.c@ 105132

最後變更 在這個檔案從105132是 104078,由 vboxsync 提交於 12 月 前

openssl-3.1.5: Applied and adjusted our OpenSSL changes to 3.1.4. bugref:10638

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette