| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 | 
							- /*
 
-  * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
 
-  * Copyright (c) 2019, Oracle and/or its affiliates.  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 <string.h>
 
- #include <openssl/crypto.h>
 
- #include <openssl/lhash.h>
 
- #include "crypto/lhash.h"
 
- #include "property_local.h"
 
- #include "crypto/context.h"
 
- /*
 
-  * Property strings are a consolidation of all strings seen by the property
 
-  * subsystem.  There are two name spaces to keep property names separate from
 
-  * property values (numeric values are not expected to be cached however).
 
-  * They allow a rapid conversion from a string to a unique index and any
 
-  * subsequent string comparison can be done via an integer compare.
 
-  *
 
-  * This implementation uses OpenSSL's standard hash table.  There are more
 
-  * space and time efficient algorithms if this becomes a bottleneck.
 
-  */
 
- typedef struct {
 
-     const char *s;
 
-     OSSL_PROPERTY_IDX idx;
 
-     char body[1];
 
- } PROPERTY_STRING;
 
- DEFINE_LHASH_OF_EX(PROPERTY_STRING);
 
- typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE;
 
- typedef struct {
 
-     CRYPTO_RWLOCK *lock;
 
-     PROP_TABLE *prop_names;
 
-     PROP_TABLE *prop_values;
 
-     OSSL_PROPERTY_IDX prop_name_idx;
 
-     OSSL_PROPERTY_IDX prop_value_idx;
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-     STACK_OF(OPENSSL_CSTRING) *prop_namelist;
 
-     STACK_OF(OPENSSL_CSTRING) *prop_valuelist;
 
- #endif
 
- } PROPERTY_STRING_DATA;
 
- static unsigned long property_hash(const PROPERTY_STRING *a)
 
- {
 
-     return OPENSSL_LH_strhash(a->s);
 
- }
 
- static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b)
 
- {
 
-     return strcmp(a->s, b->s);
 
- }
 
- static void property_free(PROPERTY_STRING *ps)
 
- {
 
-     OPENSSL_free(ps);
 
- }
 
- static void property_table_free(PROP_TABLE **pt)
 
- {
 
-     PROP_TABLE *t = *pt;
 
-     if (t != NULL) {
 
-         lh_PROPERTY_STRING_doall(t, &property_free);
 
-         lh_PROPERTY_STRING_free(t);
 
-         *pt = NULL;
 
-     }
 
- }
 
- void ossl_property_string_data_free(void *vpropdata)
 
- {
 
-     PROPERTY_STRING_DATA *propdata = vpropdata;
 
-     if (propdata == NULL)
 
-         return;
 
-     CRYPTO_THREAD_lock_free(propdata->lock);
 
-     property_table_free(&propdata->prop_names);
 
-     property_table_free(&propdata->prop_values);
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-     sk_OPENSSL_CSTRING_free(propdata->prop_namelist);
 
-     sk_OPENSSL_CSTRING_free(propdata->prop_valuelist);
 
-     propdata->prop_namelist = propdata->prop_valuelist = NULL;
 
- #endif
 
-     propdata->prop_name_idx = propdata->prop_value_idx = 0;
 
-     OPENSSL_free(propdata);
 
- }
 
- void *ossl_property_string_data_new(OSSL_LIB_CTX *ctx) {
 
-     PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata));
 
-     if (propdata == NULL)
 
-         return NULL;
 
-     propdata->lock = CRYPTO_THREAD_lock_new();
 
-     propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash,
 
-                                                   &property_cmp);
 
-     propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash,
 
-                                                    &property_cmp);
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-     propdata->prop_namelist = sk_OPENSSL_CSTRING_new_null();
 
-     propdata->prop_valuelist = sk_OPENSSL_CSTRING_new_null();
 
- #endif
 
-     if (propdata->lock == NULL
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-             || propdata->prop_namelist == NULL
 
-             || propdata->prop_valuelist == NULL
 
- #endif
 
-             || propdata->prop_names == NULL
 
-             || propdata->prop_values == NULL) {
 
-         ossl_property_string_data_free(propdata);
 
-         return NULL;
 
-     }
 
-     return propdata;
 
- }
 
- static PROPERTY_STRING *new_property_string(const char *s,
 
-                                             OSSL_PROPERTY_IDX *pidx)
 
- {
 
-     const size_t l = strlen(s);
 
-     PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l);
 
-     if (ps != NULL) {
 
-         memcpy(ps->body, s, l + 1);
 
-         ps->s = ps->body;
 
-         ps->idx = ++*pidx;
 
-         if (ps->idx == 0) {
 
-             OPENSSL_free(ps);
 
-             return NULL;
 
-         }
 
-     }
 
-     return ps;
 
- }
 
- static OSSL_PROPERTY_IDX ossl_property_string(OSSL_LIB_CTX *ctx, int name,
 
-                                               int create, const char *s)
 
- {
 
-     PROPERTY_STRING p, *ps, *ps_new;
 
-     PROP_TABLE *t;
 
-     OSSL_PROPERTY_IDX *pidx;
 
-     PROPERTY_STRING_DATA *propdata
 
-         = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX);
 
-     if (propdata == NULL)
 
-         return 0;
 
-     t = name ? propdata->prop_names : propdata->prop_values;
 
-     p.s = s;
 
-     if (!CRYPTO_THREAD_read_lock(propdata->lock)) {
 
-         ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
 
-         return 0;
 
-     }
 
-     ps = lh_PROPERTY_STRING_retrieve(t, &p);
 
-     if (ps == NULL && create) {
 
-         CRYPTO_THREAD_unlock(propdata->lock);
 
-         if (!CRYPTO_THREAD_write_lock(propdata->lock)) {
 
-             ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
 
-             return 0;
 
-         }
 
-         pidx = name ? &propdata->prop_name_idx : &propdata->prop_value_idx;
 
-         ps = lh_PROPERTY_STRING_retrieve(t, &p);
 
-         if (ps == NULL && (ps_new = new_property_string(s, pidx)) != NULL) {
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-             STACK_OF(OPENSSL_CSTRING) *slist;
 
-             slist = name ? propdata->prop_namelist : propdata->prop_valuelist;
 
-             if (sk_OPENSSL_CSTRING_push(slist, ps_new->s) <= 0) {
 
-                 property_free(ps_new);
 
-                 CRYPTO_THREAD_unlock(propdata->lock);
 
-                 return 0;
 
-             }
 
- #endif
 
-             lh_PROPERTY_STRING_insert(t, ps_new);
 
-             if (lh_PROPERTY_STRING_error(t)) {
 
-                 /*-
 
-                  * Undo the previous push which means also decrementing the
 
-                  * index and freeing the allocated storage.
 
-                  */
 
- #ifndef OPENSSL_SMALL_FOOTPRINT
 
-                 sk_OPENSSL_CSTRING_pop(slist);
 
- #endif
 
-                 property_free(ps_new);
 
-                 --*pidx;
 
-                 CRYPTO_THREAD_unlock(propdata->lock);
 
-                 return 0;
 
-             }
 
-             ps = ps_new;
 
-         }
 
-     }
 
-     CRYPTO_THREAD_unlock(propdata->lock);
 
-     return ps != NULL ? ps->idx : 0;
 
- }
 
- #ifdef OPENSSL_SMALL_FOOTPRINT
 
- struct find_str_st {
 
-     const char *str;
 
-     OSSL_PROPERTY_IDX idx;
 
- };
 
- static void find_str_fn(PROPERTY_STRING *prop, void *vfindstr)
 
- {
 
-     struct find_str_st *findstr = vfindstr;
 
-     if (prop->idx == findstr->idx)
 
-         findstr->str = prop->s;
 
- }
 
- #endif
 
- static const char *ossl_property_str(int name, OSSL_LIB_CTX *ctx,
 
-                                      OSSL_PROPERTY_IDX idx)
 
- {
 
-     const char *r;
 
-     PROPERTY_STRING_DATA *propdata
 
-         = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_PROPERTY_STRING_INDEX);
 
-     if (propdata == NULL)
 
-         return NULL;
 
-     if (!CRYPTO_THREAD_read_lock(propdata->lock)) {
 
-         ERR_raise(ERR_LIB_CRYPTO, ERR_R_UNABLE_TO_GET_READ_LOCK);
 
-         return NULL;
 
-     }
 
- #ifdef OPENSSL_SMALL_FOOTPRINT
 
-     {
 
-         struct find_str_st findstr;
 
-         findstr.str = NULL;
 
-         findstr.idx = idx;
 
-         lh_PROPERTY_STRING_doall_arg(name ? propdata->prop_names
 
-                                           : propdata->prop_values,
 
-                                      find_str_fn, &findstr);
 
-         r = findstr.str;
 
-     }
 
- #else
 
-     r = sk_OPENSSL_CSTRING_value(name ? propdata->prop_namelist
 
-                                       : propdata->prop_valuelist, idx - 1);
 
- #endif
 
-     CRYPTO_THREAD_unlock(propdata->lock);
 
-     return r;
 
- }
 
- OSSL_PROPERTY_IDX ossl_property_name(OSSL_LIB_CTX *ctx, const char *s,
 
-                                      int create)
 
- {
 
-     return ossl_property_string(ctx, 1, create, s);
 
- }
 
- const char *ossl_property_name_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
 
- {
 
-     return ossl_property_str(1, ctx, idx);
 
- }
 
- OSSL_PROPERTY_IDX ossl_property_value(OSSL_LIB_CTX *ctx, const char *s,
 
-                                       int create)
 
- {
 
-     return ossl_property_string(ctx, 0, create, s);
 
- }
 
- const char *ossl_property_value_str(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_IDX idx)
 
- {
 
-     return ossl_property_str(0, ctx, idx);
 
- }
 
 
  |