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