c63a433ddbe2d50df637751516901f65883e8358
[openssl.git] / crypto / property / property_parse.c
1 /*
2  * Copyright 2019 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 "internal/ctype.h"
18 #include "internal/nelem.h"
19 #include "property_lcl.h"
20 #include "e_os.h"
21
22 typedef enum {
23     PROPERTY_TYPE_STRING, PROPERTY_TYPE_NUMBER,
24     PROPERTY_TYPE_VALUE_UNDEFINED
25 } PROPERTY_TYPE;
26
27 typedef enum {
28     PROPERTY_OPER_EQ, PROPERTY_OPER_NE, PROPERTY_OVERRIDE
29 } PROPERTY_OPER;
30
31 typedef struct {
32     OSSL_PROPERTY_IDX name_idx;
33     PROPERTY_TYPE type;
34     PROPERTY_OPER oper;
35     unsigned int optional : 1;
36     union {
37         int64_t             int_val;     /* Signed integer */
38         OSSL_PROPERTY_IDX   str_val;     /* String */
39     } v;
40 } PROPERTY_DEFINITION;
41
42 struct ossl_property_list_st {
43     int n;
44     unsigned int has_optional : 1;
45     PROPERTY_DEFINITION properties[1];
46 };
47
48 static OSSL_PROPERTY_IDX ossl_property_true, ossl_property_false;
49
50 DEFINE_STACK_OF(PROPERTY_DEFINITION)
51
52 static const char *skip_space(const char *s)
53 {
54     while (ossl_isspace(*s))
55         s++;
56     return s;
57 }
58
59 static int match_ch(const char *t[], char m)
60 {
61     const char *s = *t;
62
63     if (*s == m) {
64         *t = skip_space(s + 1);
65         return 1;
66     }
67     return 0;
68 }
69
70 #define MATCH(s, m) match(s, m, sizeof(m) - 1)
71
72 static int match(const char *t[], const char m[], size_t m_len)
73 {
74     const char *s = *t;
75
76     if (strncasecmp(s, m, m_len) == 0) {
77         *t = skip_space(s + m_len);
78         return 1;
79     }
80     return 0;
81 }
82
83 static int parse_name(OPENSSL_CTX *ctx, const char *t[], int create,
84                       OSSL_PROPERTY_IDX *idx)
85 {
86     char name[100];
87     int err = 0;
88     size_t i = 0;
89     const char *s = *t;
90     int user_name = 0;
91
92     for (;;) {
93         if (!ossl_isalpha(*s)) {
94             PROPerr(PROP_F_PARSE_NAME, PROP_R_NOT_AN_IDENTIFIER);
95             return 0;
96         }
97         do {
98             if (i < sizeof(name) - 1)
99                 name[i++] = ossl_tolower(*s);
100             else
101                 err = 1;
102         } while (*++s == '_' || ossl_isalnum(*s));
103         if (*s != '.')
104             break;
105         user_name = 1;
106         if (i < sizeof(name) - 1)
107             name[i++] = *s;
108         else
109             err = 1;
110         s++;
111     }
112     name[i] = '\0';
113     *t = skip_space(s);
114     if (!err) {
115         *idx = ossl_property_name(ctx, name, user_name && create);
116         return 1;
117     }
118     PROPerr(PROP_F_PARSE_NAME, PROP_R_NAME_TOO_LONG);
119     return 0;
120 }
121
122 static int parse_number(const char *t[], PROPERTY_DEFINITION *res)
123 {
124     const char *s = *t;
125     int64_t v = 0;
126
127     if (!ossl_isdigit(*s))
128         return 0;
129     do {
130         v = v * 10 + (*s++ - '0');
131     } while (ossl_isdigit(*s));
132     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
133         PROPerr(PROP_F_PARSE_NUMBER, PROP_R_NOT_A_DECIMAL_DIGIT);
134         return 0;
135     }
136     *t = skip_space(s);
137     res->type = PROPERTY_TYPE_NUMBER;
138     res->v.int_val = v;
139     return 1;
140 }
141
142 static int parse_hex(const char *t[], PROPERTY_DEFINITION *res)
143 {
144     const char *s = *t;
145     int64_t v = 0;
146
147     if (!ossl_isxdigit(*s))
148         return 0;
149     do {
150         v <<= 4;
151         if (ossl_isdigit(*s))
152             v += *s - '0';
153         else
154             v += ossl_tolower(*s) - 'a';
155     } while (ossl_isxdigit(*++s));
156     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
157         PROPerr(PROP_F_PARSE_HEX, PROP_R_NOT_AN_HEXADECIMAL_DIGIT);
158         return 0;
159     }
160     *t = skip_space(s);
161     res->type = PROPERTY_TYPE_NUMBER;
162     res->v.int_val = v;
163     return 1;
164 }
165
166 static int parse_oct(const char *t[], PROPERTY_DEFINITION *res)
167 {
168     const char *s = *t;
169     int64_t v = 0;
170
171     if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
172         return 0;
173     do {
174         v = (v << 3) + (*s - '0');
175     } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
176     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
177         PROPerr(PROP_F_PARSE_OCT, PROP_R_NOT_AN_OCTAL_DIGIT);
178         return 0;
179     }
180     *t = skip_space(s);
181     res->type = PROPERTY_TYPE_NUMBER;
182     res->v.int_val = v;
183     return 1;
184 }
185
186 static int parse_string(OPENSSL_CTX *ctx, const char *t[], char delim,
187                         PROPERTY_DEFINITION *res, const int create)
188 {
189     char v[1000];
190     const char *s = *t;
191     size_t i = 0;
192     int err = 0;
193
194     while (*s != '\0' && *s != delim) {
195         if (i < sizeof(v) - 1)
196             v[i++] = *s;
197         else
198             err = 1;
199         s++;
200     }
201     if (*s == '\0') {
202         PROPerr(PROP_F_PARSE_STRING,
203                 PROP_R_NO_MATCHING_STRING_DELIMETER);
204         return 0;
205     }
206     v[i] = '\0';
207     *t = skip_space(s + 1);
208     if (err)
209         PROPerr(PROP_F_PARSE_STRING, PROP_R_STRING_TOO_LONG);
210     else
211         res->v.str_val = ossl_property_value(ctx, v, create);
212     res->type = PROPERTY_TYPE_STRING;
213     return !err;
214 }
215
216 static int parse_unquoted(OPENSSL_CTX *ctx, const char *t[],
217                           PROPERTY_DEFINITION *res, const int create)
218 {
219     char v[1000];
220     const char *s = *t;
221     size_t i = 0;
222     int err = 0;
223
224     if (*s == '\0' || *s == ',')
225         return 0;
226     while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
227         if (i < sizeof(v) - 1)
228             v[i++] = ossl_tolower(*s);
229         else
230             err = 1;
231         s++;
232     }
233     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
234         PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_NOT_AN_ASCII_CHARACTER);
235         return 0;
236     }
237     v[i] = 0;
238     *t = skip_space(s);
239     if (err)
240         PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_STRING_TOO_LONG);
241     else
242         res->v.str_val = ossl_property_value(ctx, v, create);
243     res->type = PROPERTY_TYPE_STRING;
244     return !err;
245 }
246
247 static int parse_value(OPENSSL_CTX *ctx, const char *t[],
248                        PROPERTY_DEFINITION *res, int create)
249 {
250     const char *s = *t;
251     int r = 0;
252
253     if (*s == '"' || *s == '\'') {
254         s++;
255         r = parse_string(ctx, &s, s[-1], res, create);
256     } else if (*s == '+') {
257         s++;
258         r = parse_number(&s, res);
259     } else if (*s == '-') {
260         s++;
261         r = parse_number(&s, res);
262         res->v.int_val = -res->v.int_val;
263     } else if (*s == '0' && s[1] == 'x') {
264         s += 2;
265         r = parse_hex(&s, res);
266     } else if (*s == '0' && ossl_isdigit(s[1])) {
267         s++;
268         r = parse_oct(&s, res);
269     } else if (ossl_isdigit(*s)) {
270         return parse_number(t, res);
271     } else if (ossl_isalpha(*s))
272         return parse_unquoted(ctx, t, res, create);
273     if (r)
274         *t = s;
275     return r;
276 }
277
278 static int pd_compare(const PROPERTY_DEFINITION *const *p1,
279                       const PROPERTY_DEFINITION *const *p2)
280 {
281     const PROPERTY_DEFINITION *pd1 = *p1;
282     const PROPERTY_DEFINITION *pd2 = *p2;
283
284     if (pd1->name_idx < pd2->name_idx)
285         return -1;
286     if (pd1->name_idx > pd2->name_idx)
287         return 1;
288     return 0;
289 }
290
291 static void pd_free(PROPERTY_DEFINITION *pd)
292 {
293     OPENSSL_free(pd);
294 }
295
296 /*
297  * Convert a stack of property definitions and queries into a fixed array.
298  * The items are sorted for efficient query.  The stack is not freed.
299  */
300 static OSSL_PROPERTY_LIST *stack_to_property_list(STACK_OF(PROPERTY_DEFINITION)
301                                                   *sk)
302 {
303     const int n = sk_PROPERTY_DEFINITION_num(sk);
304     OSSL_PROPERTY_LIST *r;
305     int i;
306
307     r = OPENSSL_malloc(sizeof(*r)
308                        + (n <= 0 ? 0 : n - 1) * sizeof(r->properties[0]));
309     if (r != NULL) {
310         sk_PROPERTY_DEFINITION_sort(sk);
311
312         r->has_optional = 0;
313         for (i = 0; i < n; i++) {
314             r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
315             r->has_optional |= r->properties[i].optional;
316         }
317         r->n = n;
318     }
319     return r;
320 }
321
322 OSSL_PROPERTY_LIST *ossl_parse_property(OPENSSL_CTX *ctx, const char *defn)
323 {
324     PROPERTY_DEFINITION *prop = NULL;
325     OSSL_PROPERTY_LIST *res = NULL;
326     STACK_OF(PROPERTY_DEFINITION) *sk;
327     const char *s = defn;
328     int done;
329
330     if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
331         return NULL;
332
333     s = skip_space(s);
334     done = *s == '\0';
335     while (!done) {
336         prop = OPENSSL_malloc(sizeof(*prop));
337         if (prop == NULL)
338             goto err;
339         memset(&prop->v, 0, sizeof(prop->v));
340         prop->optional = 0;
341         if (!parse_name(ctx, &s, 1, &prop->name_idx))
342             goto err;
343         prop->oper = PROPERTY_OPER_EQ;
344         if (prop->name_idx == 0) {
345             PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_PARSE_FAILED);
346             goto err;
347         }
348         if (match_ch(&s, '=')) {
349             if (!parse_value(ctx, &s, prop, 1)) {
350                 PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_NO_VALUE);
351                 goto err;
352             }
353         } else {
354             /* A name alone means a true Boolean */
355             prop->type = PROPERTY_TYPE_STRING;
356             prop->v.str_val = ossl_property_true;
357         }
358
359         if (!sk_PROPERTY_DEFINITION_push(sk, prop))
360             goto err;
361         prop = NULL;
362         done = !match_ch(&s, ',');
363     }
364     if (*s != '\0') {
365         PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_TRAILING_CHARACTERS);
366         goto err;
367     }
368     res = stack_to_property_list(sk);
369
370 err:
371     OPENSSL_free(prop);
372     sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
373     return res;
374 }
375
376 OSSL_PROPERTY_LIST *ossl_parse_query(OPENSSL_CTX *ctx, const char *s)
377 {
378     STACK_OF(PROPERTY_DEFINITION) *sk;
379     OSSL_PROPERTY_LIST *res = NULL;
380     PROPERTY_DEFINITION *prop = NULL;
381     int done;
382
383     if (s == NULL || (sk = sk_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
384         return NULL;
385
386     s = skip_space(s);
387     done = *s == '\0';
388     while (!done) {
389         prop = OPENSSL_malloc(sizeof(*prop));
390         if (prop == NULL)
391             goto err;
392         memset(&prop->v, 0, sizeof(prop->v));
393
394         if (match_ch(&s, '-')) {
395             prop->oper = PROPERTY_OVERRIDE;
396             prop->optional = 0;
397             if (!parse_name(ctx, &s, 0, &prop->name_idx))
398                 goto err;
399             goto skip_value;
400         }
401         prop->optional = match_ch(&s, '?');
402         if (!parse_name(ctx, &s, 0, &prop->name_idx))
403             goto err;
404
405         if (match_ch(&s, '=')) {
406             prop->oper = PROPERTY_OPER_EQ;
407         } else if (MATCH(&s, "!=")) {
408             prop->oper = PROPERTY_OPER_NE;
409         } else {
410             /* A name alone is a Boolean comparison for true */
411             prop->oper = PROPERTY_OPER_EQ;
412             prop->type = PROPERTY_TYPE_STRING;
413             prop->v.str_val = ossl_property_true;
414             goto skip_value;
415         }
416         if (!parse_value(ctx, &s, prop, 0))
417             prop->type = PROPERTY_TYPE_VALUE_UNDEFINED;
418
419 skip_value:
420         if (!sk_PROPERTY_DEFINITION_push(sk, prop))
421             goto err;
422         prop = NULL;
423         done = !match_ch(&s, ',');
424     }
425     if (*s != '\0') {
426         PROPerr(PROP_F_OSSL_PARSE_QUERY, PROP_R_TRAILING_CHARACTERS);
427         goto err;
428     }
429     res = stack_to_property_list(sk);
430
431 err:
432     OPENSSL_free(prop);
433     sk_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
434     return res;
435 }
436
437 /* Does a property query have any optional clauses */
438 int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
439 {
440     return query->has_optional ? 1 : 0;
441 }
442
443 /*
444  * Compare a query against a definition.
445  * Return the number of clauses matched or -1 if a mandatory clause is false.
446  */
447 int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
448                               const OSSL_PROPERTY_LIST *defn)
449 {
450     const PROPERTY_DEFINITION *const q = query->properties;
451     const PROPERTY_DEFINITION *const d = defn->properties;
452     int i = 0, j = 0, matches = 0;
453     PROPERTY_OPER oper;
454
455     while (i < query->n) {
456         if ((oper = q[i].oper) == PROPERTY_OVERRIDE) {
457             i++;
458             continue;
459         }
460         if (j < defn->n) {
461             if (q[i].name_idx > d[j].name_idx) {  /* skip defn, not in query */
462                 j++;
463                 continue;
464             }
465             if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
466                 const int eq = q[i].type == d[j].type
467                                && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
468
469                 if ((eq && oper == PROPERTY_OPER_EQ)
470                     || (!eq && oper == PROPERTY_OPER_NE))
471                     matches++;
472                 else if (!q[i].optional)
473                     return -1;
474                 i++;
475                 j++;
476                 continue;
477             }
478         }
479
480         /*
481          * Handle the cases of a missing value and a query with no corresponding
482          * definition.  The former fails for any comparision except inequality,
483          * the latter is treated as a comparison against the Boolean false.
484          */
485         if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
486             if (oper == PROPERTY_OPER_NE)
487                 matches++;
488             else if (!q[i].optional)
489                 return -1;
490         } else if (q[i].type != PROPERTY_TYPE_STRING
491                    || (oper == PROPERTY_OPER_EQ
492                        && q[i].v.str_val != ossl_property_false)
493                    || (oper == PROPERTY_OPER_NE
494                        && q[i].v.str_val == ossl_property_false)) {
495             if (!q[i].optional)
496                 return -1;
497         } else {
498             matches++;
499         }
500         i++;
501     }
502     return matches;
503 }
504
505 void ossl_property_free(OSSL_PROPERTY_LIST *p)
506 {
507     OPENSSL_free(p);
508 }
509
510 /*
511  * Merge two property lists.
512  * If there is a common name, the one from the first list is used.
513  */
514 OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
515                                         const OSSL_PROPERTY_LIST *b)
516 {
517     const PROPERTY_DEFINITION *const ap = a->properties;
518     const PROPERTY_DEFINITION *const bp = b->properties;
519     const PROPERTY_DEFINITION *copy;
520     OSSL_PROPERTY_LIST *r;
521     int i, j, n;
522     const int t = a->n + b->n;
523
524     r = OPENSSL_malloc(sizeof(*r)
525                        + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
526     if (r == NULL)
527         return NULL;
528
529     for (i = j = n = 0; i < a->n || j < b->n; n++) {
530         if (i >= a->n) {
531             copy = &bp[j++];
532         } else if (j >= b->n) {
533             copy = &ap[i++];
534         } else if (ap[i].name_idx <= bp[j].name_idx) {
535             if (ap[i].name_idx == bp[j].name_idx)
536                 j++;
537             copy = &ap[i++];
538         } else {
539             copy = &bp[j++];
540         }
541         memcpy(r->properties + n, copy, sizeof(r->properties[0]));
542     }
543     r->n = n;
544     if (n != t)
545         r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
546     return r;
547 }
548
549 int ossl_property_parse_init(OPENSSL_CTX *ctx)
550 {
551     static const char *const predefined_names[] = {
552         "default",      /* Being provided by the default built-in provider */
553         "legacy",       /* Provided by the legacy provider */
554         "provider",     /* Name of provider (default, fips) */
555         "version",      /* Version number of this provider */
556         "fips",         /* FIPS supporting provider */
557         "engine",       /* An old style engine masquerading as a provider */
558     };
559     size_t i;
560
561     for (i = 0; i < OSSL_NELEM(predefined_names); i++)
562         if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
563             goto err;
564
565     /* Pre-populate the two Boolean values */
566     if ((ossl_property_true = ossl_property_value(ctx, "yes", 1)) == 0
567         || (ossl_property_false = ossl_property_value(ctx, "no", 1)) == 0)
568         goto err;
569
570     return 1;
571 err:
572     return 0;
573 }