123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- /*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- #include "internal/namemap.h"
- #include <openssl/lhash.h>
- #include <openssl/safestack.h>
- /* The namemap entry */
- typedef struct {
- int number;
- const char *name;
- char body[1]; /* Sized appropriately to contain the name */
- } NAMEMAP_ENTRY;
- DEFINE_LHASH_OF(NAMEMAP_ENTRY);
- DEFINE_STACK_OF(NAMEMAP_ENTRY)
- /* The namemap, which provides for bidirectional indexing */
- struct ossl_namemap_st {
- /* Flags */
- unsigned int stored:1; /* If 1, it's stored in a library context */
- CRYPTO_RWLOCK *lock;
- LHASH_OF(NAMEMAP_ENTRY) *namenum; /* Name->number mapping */
- STACK_OF(NAMEMAP_ENTRY) *numname; /* Number->name mapping */
- };
- /* LHASH callbacks */
- static unsigned long namemap_hash(const NAMEMAP_ENTRY *n)
- {
- return OPENSSL_LH_strhash(n->name);
- }
- static int namemap_cmp(const NAMEMAP_ENTRY *a, const NAMEMAP_ENTRY *b)
- {
- return strcmp(a->name, b->name);
- }
- static void namemap_free(NAMEMAP_ENTRY *n)
- {
- OPENSSL_free(n);
- }
- /* OPENSSL_CTX_METHOD functions for a namemap stored in a library context */
- static void *stored_namemap_new(OPENSSL_CTX *libctx)
- {
- OSSL_NAMEMAP *namemap = ossl_namemap_new();
- if (namemap != NULL)
- namemap->stored = 1;
- return namemap;
- }
- static void stored_namemap_free(void *vnamemap)
- {
- OSSL_NAMEMAP *namemap = vnamemap;
- /* Pretend it isn't stored, or ossl_namemap_free() will do nothing */
- namemap->stored = 0;
- ossl_namemap_free(namemap);
- }
- static const OPENSSL_CTX_METHOD stored_namemap_method = {
- stored_namemap_new,
- stored_namemap_free,
- };
- /* API functions */
- OSSL_NAMEMAP *ossl_namemap_stored(OPENSSL_CTX *libctx)
- {
- return openssl_ctx_get_data(libctx, OPENSSL_CTX_NAMEMAP_INDEX,
- &stored_namemap_method);
- }
- OSSL_NAMEMAP *ossl_namemap_new(void)
- {
- OSSL_NAMEMAP *namemap;
- if ((namemap = OPENSSL_zalloc(sizeof(*namemap))) != NULL
- && (namemap->lock = CRYPTO_THREAD_lock_new()) != NULL
- && (namemap->numname = sk_NAMEMAP_ENTRY_new_null()) != NULL
- && (namemap->namenum =
- lh_NAMEMAP_ENTRY_new(namemap_hash, namemap_cmp)) != NULL) {
- return namemap;
- }
- ossl_namemap_free(namemap);
- return NULL;
- }
- void ossl_namemap_free(OSSL_NAMEMAP *namemap)
- {
- if (namemap == NULL || namemap->stored)
- return;
- /* The elements will be freed by sk_NAMEMAP_ENTRY_pop_free() */
- lh_NAMEMAP_ENTRY_free(namemap->namenum);
- sk_NAMEMAP_ENTRY_pop_free(namemap->numname, namemap_free);
- CRYPTO_THREAD_lock_free(namemap->lock);
- OPENSSL_free(namemap);
- }
- /*
- * TODO(3.0) It isn't currently possible to have a default namemap in the
- * FIPS module because if init and cleanup constraints, so we currently
- * disable the code that would allow it when FIPS_MODE is defined.
- */
- const char *ossl_namemap_name(const OSSL_NAMEMAP *namemap, int number)
- {
- NAMEMAP_ENTRY *entry;
- #ifndef FIPS_MODE
- if (namemap == NULL)
- namemap = ossl_namemap_stored(NULL);
- #endif
- if (namemap == NULL || number == 0)
- return NULL;
- CRYPTO_THREAD_read_lock(namemap->lock);
- entry = sk_NAMEMAP_ENTRY_value(namemap->numname, number);
- CRYPTO_THREAD_unlock(namemap->lock);
- if (entry != NULL)
- return entry->name;
- return NULL;
- }
- int ossl_namemap_number(const OSSL_NAMEMAP *namemap, const char *name)
- {
- NAMEMAP_ENTRY *entry, template;
- #ifndef FIPS_MODE
- if (namemap == NULL)
- namemap = ossl_namemap_stored(NULL);
- #endif
- if (namemap == NULL)
- return 0;
- template.name = name;
- CRYPTO_THREAD_read_lock(namemap->lock);
- entry = lh_NAMEMAP_ENTRY_retrieve(namemap->namenum, &template);
- CRYPTO_THREAD_unlock(namemap->lock);
- if (entry == NULL)
- return 0;
- return entry->number;
- }
- int ossl_namemap_add(OSSL_NAMEMAP *namemap, const char *name)
- {
- NAMEMAP_ENTRY *entry;
- int number;
- #ifndef FIPS_MODE
- if (namemap == NULL)
- namemap = ossl_namemap_stored(NULL);
- #endif
- if (name == NULL || namemap == NULL)
- return 0;
- if ((number = ossl_namemap_number(namemap, name)) != 0)
- return number; /* Pretend success */
- if ((entry = OPENSSL_zalloc(sizeof(*entry) + strlen(name))) == NULL)
- goto err;
- strcpy(entry->body, name);
- entry->name = entry->body;
- CRYPTO_THREAD_write_lock(namemap->lock);
- entry->number = sk_NAMEMAP_ENTRY_push(namemap->numname, entry);
- if (entry->number == 0)
- goto err;
- (void)lh_NAMEMAP_ENTRY_insert(namemap->namenum, entry);
- if (lh_NAMEMAP_ENTRY_error(namemap->namenum))
- goto err;
- CRYPTO_THREAD_unlock(namemap->lock);
- return entry->number;
- err:
- if (entry != NULL) {
- if (entry->number != 0)
- (void)sk_NAMEMAP_ENTRY_pop(namemap->numname);
- lh_NAMEMAP_ENTRY_delete(namemap->namenum, entry);
- CRYPTO_THREAD_unlock(namemap->lock);
- }
- return 0;
- }
|