PEM_read_...: document that garbage and other PEM data is skipped
[openssl.git] / crypto / core_namemap.c
1 /*
2  * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "e_os.h"                /* strcasecmp */
11 #include "internal/namemap.h"
12 #include <openssl/lhash.h>
13 #include "crypto/lhash.h"      /* ossl_lh_strcasehash */
14 #include "internal/tsan_assist.h"
15 #include "internal/sizes.h"
16
17 /*-
18  * The namenum entry
19  * =================
20  */
21 typedef struct {
22     char *name;
23     int number;
24 } NAMENUM_ENTRY;
25
26 DEFINE_LHASH_OF(NAMENUM_ENTRY);
27
28 /*-
29  * The namemap itself
30  * ==================
31  */
32
33 struct ossl_namemap_st {
34     /* Flags */
35     unsigned int stored:1; /* If 1, it's stored in a library context */
36
37     CRYPTO_RWLOCK *lock;
38     LHASH_OF(NAMENUM_ENTRY) *namenum;  /* Name->number mapping */
39
40 #ifdef tsan_ld_acq
41     TSAN_QUALIFIER int max_number;     /* Current max number TSAN version */
42 #else
43     int max_number;                    /* Current max number plain version */
44 #endif
45 };
46
47 /* LHASH callbacks */
48
49 static unsigned long namenum_hash(const NAMENUM_ENTRY *n)
50 {
51     return ossl_lh_strcasehash(n->name);
52 }
53
54 static int namenum_cmp(const NAMENUM_ENTRY *a, const NAMENUM_ENTRY *b)
55 {
56     return strcasecmp(a->name, b->name);
57 }
58
59 static void namenum_free(NAMENUM_ENTRY *n)
60 {
61     if (n != NULL)
62         OPENSSL_free(n->name);
63     OPENSSL_free(n);
64 }
65
66 /* OSSL_LIB_CTX_METHOD functions for a namemap stored in a library context */
67
68 static void *stored_namemap_new(OSSL_LIB_CTX *libctx)
69 {
70     OSSL_NAMEMAP *namemap = ossl_namemap_new();
71
72     if (namemap != NULL)
73         namemap->stored = 1;
74
75     return namemap;
76 }
77
78 static void stored_namemap_free(void *vnamemap)
79 {
80     OSSL_NAMEMAP *namemap = vnamemap;
81
82     if (namemap != NULL) {
83         /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
84         namemap->stored = 0;
85         ossl_namemap_free(namemap);
86     }
87 }
88
89 static const OSSL_LIB_CTX_METHOD stored_namemap_method = {
90     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
91     stored_namemap_new,
92     stored_namemap_free,
93 };
94
95 /*-
96  * API functions
97  * =============
98  */
99
100 int ossl_namemap_empty(OSSL_NAMEMAP *namemap)
101 {
102 #ifdef tsan_ld_acq
103     /* Have TSAN support */
104     return namemap == NULL || tsan_load(&namemap->max_number) == 0;
105 #else
106     /* No TSAN support */
107     int rv;
108
109     if (namemap == NULL)
110         return 1;
111
112     if (!CRYPTO_THREAD_read_lock(namemap->lock))
113         return -1;
114     rv = namemap->max_number == 0;
115     CRYPTO_THREAD_unlock(namemap->lock);
116     return rv;
117 #endif
118 }
119
120 typedef struct doall_names_data_st {
121     int number;
122     const char **names;
123     int found;
124 } DOALL_NAMES_DATA;
125
126 static void do_name(const NAMENUM_ENTRY *namenum, DOALL_NAMES_DATA *data)
127 {
128     if (namenum->number == data->number)
129         data->names[data->found++] = namenum->name;
130 }
131
132 IMPLEMENT_LHASH_DOALL_ARG_CONST(NAMENUM_ENTRY, DOALL_NAMES_DATA);
133
134 /*
135  * Call the callback for all names in the namemap with the given number.
136  * A return value 1 means that the callback was called for all names. A
137  * return value of 0 means that the callback was not called for any names.
138  */
139 int ossl_namemap_doall_names(const OSSL_NAMEMAP *namemap, int number,
140                              void (*fn)(const char *name, void *data),
141                              void *data)
142 {
143     DOALL_NAMES_DATA cbdata;
144     size_t num_names;
145     int i;
146
147     cbdata.number = number;
148     cbdata.found = 0;
149
150     /*
151      * We collect all the names first under a read lock. Subsequently we call
152      * the user function, so that we're not holding the read lock when in user
153      * code. This could lead to deadlocks.
154      */
155     if (!CRYPTO_THREAD_read_lock(namemap->lock))
156         return 0;
157
158     num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum);
159     if (num_names == 0) {
160         CRYPTO_THREAD_unlock(namemap->lock);
161         return 0;
162     }
163     cbdata.names = OPENSSL_malloc(sizeof(*cbdata.names) * num_names);
164     if (cbdata.names == NULL) {
165         CRYPTO_THREAD_unlock(namemap->lock);
166         return 0;
167     }
168     lh_NAMENUM_ENTRY_doall_DOALL_NAMES_DATA(namemap->namenum, do_name,
169                                             &cbdata);
170     CRYPTO_THREAD_unlock(namemap->lock);
171
172     for (i = 0; i < cbdata.found; i++)
173         fn(cbdata.names[i], data);
174
175     OPENSSL_free(cbdata.names);
176     return 1;
177 }
178
179 static int namemap_name2num_n(const OSSL_NAMEMAP *namemap,
180                               const char *name, size_t name_len)
181 {
182     NAMENUM_ENTRY *namenum_entry, namenum_tmpl;
183
184     if ((namenum_tmpl.name = OPENSSL_strndup(name, name_len)) == NULL)
185         return 0;
186     namenum_tmpl.number = 0;
187     namenum_entry =
188         lh_NAMENUM_ENTRY_retrieve(namemap->namenum, &namenum_tmpl);
189     OPENSSL_free(namenum_tmpl.name);
190     return namenum_entry != NULL ? namenum_entry->number : 0;
191 }
192
193 int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
194                             const char *name, size_t name_len)
195 {
196     int number;
197
198 #ifndef FIPS_MODULE
199     if (namemap == NULL)
200         namemap = ossl_namemap_stored(NULL);
201 #endif
202
203     if (namemap == NULL)
204         return 0;
205
206     if (!CRYPTO_THREAD_read_lock(namemap->lock))
207         return 0;
208     number = namemap_name2num_n(namemap, name, name_len);
209     CRYPTO_THREAD_unlock(namemap->lock);
210
211     return number;
212 }
213
214 int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
215 {
216     if (name == NULL)
217         return 0;
218
219     return ossl_namemap_name2num_n(namemap, name, strlen(name));
220 }
221
222 struct num2name_data_st {
223     size_t idx;                  /* Countdown */
224     const char *name;            /* Result */
225 };
226
227 static void do_num2name(const char *name, void *vdata)
228 {
229     struct num2name_data_st *data = vdata;
230
231     if (data->idx > 0)
232         data->idx--;
233     else if (data->name == NULL)
234         data->name = name;
235 }
236
237 const char *ossl_namemap_num2name(const OSSL_NAMEMAP *namemap, int number,
238                                   size_t idx)
239 {
240     struct num2name_data_st data;
241
242     data.idx = idx;
243     data.name = NULL;
244     if (!ossl_namemap_doall_names(namemap, number, do_num2name, &data))
245         return NULL;
246     return data.name;
247 }
248
249 static int namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
250                               const char *name, size_t name_len)
251 {
252     NAMENUM_ENTRY *namenum = NULL;
253     int tmp_number;
254
255     /* If it already exists, we don't add it */
256     if ((tmp_number = namemap_name2num_n(namemap, name, name_len)) != 0)
257         return tmp_number;
258
259     if ((namenum = OPENSSL_zalloc(sizeof(*namenum))) == NULL
260         || (namenum->name = OPENSSL_strndup(name, name_len)) == NULL)
261         goto err;
262
263     namenum->number =
264         number != 0 ? number : 1 + tsan_counter(&namemap->max_number);
265     (void)lh_NAMENUM_ENTRY_insert(namemap->namenum, namenum);
266
267     if (lh_NAMENUM_ENTRY_error(namemap->namenum))
268         goto err;
269     return namenum->number;
270
271  err:
272     namenum_free(namenum);
273     return 0;
274 }
275
276 int ossl_namemap_add_name_n(OSSL_NAMEMAP *namemap, int number,
277                             const char *name, size_t name_len)
278 {
279     int tmp_number;
280
281 #ifndef FIPS_MODULE
282     if (namemap == NULL)
283         namemap = ossl_namemap_stored(NULL);
284 #endif
285
286     if (name == NULL || name_len == 0 || namemap == NULL)
287         return 0;
288
289     if (!CRYPTO_THREAD_write_lock(namemap->lock))
290         return 0;
291     tmp_number = namemap_add_name_n(namemap, number, name, name_len);
292     CRYPTO_THREAD_unlock(namemap->lock);
293     return tmp_number;
294 }
295
296 int ossl_namemap_add_name(OSSL_NAMEMAP *namemap, int number, const char *name)
297 {
298     if (name == NULL)
299         return 0;
300
301     return ossl_namemap_add_name_n(namemap, number, name, strlen(name));
302 }
303
304 int ossl_namemap_add_names(OSSL_NAMEMAP *namemap, int number,
305                            const char *names, const char separator)
306 {
307     const char *p, *q;
308     size_t l;
309
310     /* Check that we have a namemap */
311     if (!ossl_assert(namemap != NULL)) {
312         ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
313         return 0;
314     }
315
316     if (!CRYPTO_THREAD_write_lock(namemap->lock))
317         return 0;
318     /*
319      * Check that no name is an empty string, and that all names have at
320      * most one numeric identity together.
321      */
322     for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
323         int this_number;
324
325         if ((q = strchr(p, separator)) == NULL)
326             l = strlen(p);       /* offset to \0 */
327         else
328             l = q - p;           /* offset to the next separator */
329
330         this_number = namemap_name2num_n(namemap, p, l);
331
332         if (*p == '\0' || *p == separator) {
333             ERR_raise(ERR_LIB_CRYPTO, CRYPTO_R_BAD_ALGORITHM_NAME);
334             goto err;
335         }
336         if (number == 0) {
337             number = this_number;
338         } else if (this_number != 0 && this_number != number) {
339             ERR_raise_data(ERR_LIB_CRYPTO, CRYPTO_R_CONFLICTING_NAMES,
340                            "\"%.*s\" has an existing different identity %d (from \"%s\")",
341                            l, p, this_number, names);
342             goto err;
343         }
344     }
345
346     /* Now that we have checked, register all names */
347     for (p = names; *p != '\0'; p = (q == NULL ? p + l : q + 1)) {
348         int this_number;
349
350         if ((q = strchr(p, separator)) == NULL)
351             l = strlen(p);       /* offset to \0 */
352         else
353             l = q - p;           /* offset to the next separator */
354
355         this_number = namemap_add_name_n(namemap, number, p, l);
356         if (number == 0) {
357             number = this_number;
358         } else if (this_number != number) {
359             ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
360                            "Got number %d when expecting %d",
361                            this_number, number);
362             goto err;
363         }
364     }
365
366     CRYPTO_THREAD_unlock(namemap->lock);
367     return number;
368
369  err:
370     CRYPTO_THREAD_unlock(namemap->lock);
371     return 0;
372 }
373
374 /*-
375  * Pre-population
376  * ==============
377  */
378
379 #ifndef FIPS_MODULE
380 #include <openssl/evp.h>
381
382 /* Creates an initial namemap with names found in the legacy method db */
383 static void get_legacy_evp_names(int base_nid, int nid, const char *pem_name,
384                                  void *arg)
385 {
386     int num = 0;
387     ASN1_OBJECT *obj;
388
389     if (base_nid != NID_undef) {
390         num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(base_nid));
391         num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(base_nid));
392     }
393
394     if (nid != NID_undef) {
395         num = ossl_namemap_add_name(arg, num, OBJ_nid2sn(nid));
396         num = ossl_namemap_add_name(arg, num, OBJ_nid2ln(nid));
397         if ((obj = OBJ_nid2obj(nid)) != NULL) {
398             char txtoid[OSSL_MAX_NAME_SIZE];
399
400             if (OBJ_obj2txt(txtoid, sizeof(txtoid), obj, 1))
401                 num = ossl_namemap_add_name(arg, num, txtoid);
402         }
403     }
404     if (pem_name != NULL)
405         num = ossl_namemap_add_name(arg, num, pem_name);
406 }
407
408 static void get_legacy_cipher_names(const OBJ_NAME *on, void *arg)
409 {
410     const EVP_CIPHER *cipher = (void *)OBJ_NAME_get(on->name, on->type);
411
412     get_legacy_evp_names(NID_undef, EVP_CIPHER_get_type(cipher), NULL, arg);
413 }
414
415 static void get_legacy_md_names(const OBJ_NAME *on, void *arg)
416 {
417     const EVP_MD *md = (void *)OBJ_NAME_get(on->name, on->type);
418
419     get_legacy_evp_names(0, EVP_MD_get_type(md), NULL, arg);
420 }
421
422 static void get_legacy_pkey_meth_names(const EVP_PKEY_ASN1_METHOD *ameth,
423                                        void *arg)
424 {
425     int nid = 0, base_nid = 0, flags = 0;
426     const char *pem_name = NULL;
427
428     EVP_PKEY_asn1_get0_info(&nid, &base_nid, &flags, NULL, &pem_name, ameth);
429     if (nid != NID_undef) {
430         if ((flags & ASN1_PKEY_ALIAS) == 0) {
431             switch (nid) {
432             case EVP_PKEY_DHX:
433                 /* We know that the name "DHX" is used too */
434                 get_legacy_evp_names(0, nid, "DHX", arg);
435                 /* FALLTHRU */
436             default:
437                 get_legacy_evp_names(0, nid, pem_name, arg);
438             }
439         } else {
440             /*
441              * Treat aliases carefully, some of them are undesirable, or
442              * should not be treated as such for providers.
443              */
444
445             switch (nid) {
446             case EVP_PKEY_SM2:
447                 /*
448                  * SM2 is a separate keytype with providers, not an alias for
449                  * EC.
450                  */
451                 get_legacy_evp_names(0, nid, pem_name, arg);
452                 break;
453             default:
454                 /* Use the short name of the base nid as the common reference */
455                 get_legacy_evp_names(base_nid, nid, pem_name, arg);
456             }
457         }
458     }
459 }
460 #endif
461
462 /*-
463  * Constructors / destructors
464  * ==========================
465  */
466
467 OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx)
468 {
469 #ifndef FIPS_MODULE
470     int nms;
471 #endif
472     OSSL_NAMEMAP *namemap =
473         ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX,
474                               &stored_namemap_method);
475
476     if (namemap == NULL)
477         return NULL;
478
479 #ifndef FIPS_MODULE
480     nms = ossl_namemap_empty(namemap);
481     if (nms < 0) {
482         /*
483          * Could not get lock to make the count, so maybe internal objects
484          * weren't added. This seems safest.
485          */
486         return NULL;
487     }
488     if (nms == 1) {
489         int i, end;
490
491         /* Before pilfering, we make sure the legacy database is populated */
492         OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
493                             | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
494
495         OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH,
496                         get_legacy_cipher_names, namemap);
497         OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH,
498                         get_legacy_md_names, namemap);
499
500         /* We also pilfer data from the legacy EVP_PKEY_ASN1_METHODs */
501         for (i = 0, end = EVP_PKEY_asn1_get_count(); i < end; i++)
502             get_legacy_pkey_meth_names(EVP_PKEY_asn1_get0(i), namemap);
503     }
504 #endif
505
506     return namemap;
507 }
508
509 OSSL_NAMEMAP *ossl_namemap_new(void)
510 {
511     OSSL_NAMEMAP *namemap;
512
513     if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
514         && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
515         && (namemap->namenum =
516             lh_NAMENUM_ENTRY_new(namenum_hash, namenum_cmp)) != NULL)
517         return namemap;
518
519     ossl_namemap_free(namemap);
520     return NULL;
521 }
522
523 void ossl_namemap_free(OSSL_NAMEMAP *namemap)
524 {
525     if (namemap == NULL || namemap->stored)
526         return;
527
528     lh_NAMENUM_ENTRY_doall(namemap->namenum, namenum_free);
529     lh_NAMENUM_ENTRY_free(namemap->namenum);
530
531     CRYPTO_THREAD_lock_free(namemap->lock);
532     OPENSSL_free(namemap);
533 }