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