1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 4e1051a39Sopenharmony_ci * 5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 6e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci#include <string.h> 12e1051a39Sopenharmony_ci#include <openssl/err.h> 13e1051a39Sopenharmony_ci#include <openssl/lhash.h> 14e1051a39Sopenharmony_ci#include "internal/propertyerr.h" 15e1051a39Sopenharmony_ci#include "internal/property.h" 16e1051a39Sopenharmony_ci#include "internal/core.h" 17e1051a39Sopenharmony_ci#include "property_local.h" 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci/* 20e1051a39Sopenharmony_ci * Implement a property definition cache. 21e1051a39Sopenharmony_ci * These functions assume that they are called under a write lock. 22e1051a39Sopenharmony_ci * No attempt is made to clean out the cache, except when it is shut down. 23e1051a39Sopenharmony_ci */ 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_citypedef struct { 26e1051a39Sopenharmony_ci const char *prop; 27e1051a39Sopenharmony_ci OSSL_PROPERTY_LIST *defn; 28e1051a39Sopenharmony_ci char body[1]; 29e1051a39Sopenharmony_ci} PROPERTY_DEFN_ELEM; 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ciDEFINE_LHASH_OF(PROPERTY_DEFN_ELEM); 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_cistatic unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a) 34e1051a39Sopenharmony_ci{ 35e1051a39Sopenharmony_ci return OPENSSL_LH_strhash(a->prop); 36e1051a39Sopenharmony_ci} 37e1051a39Sopenharmony_ci 38e1051a39Sopenharmony_cistatic int property_defn_cmp(const PROPERTY_DEFN_ELEM *a, 39e1051a39Sopenharmony_ci const PROPERTY_DEFN_ELEM *b) 40e1051a39Sopenharmony_ci{ 41e1051a39Sopenharmony_ci return strcmp(a->prop, b->prop); 42e1051a39Sopenharmony_ci} 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_cistatic void property_defn_free(PROPERTY_DEFN_ELEM *elem) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci ossl_property_free(elem->defn); 47e1051a39Sopenharmony_ci OPENSSL_free(elem); 48e1051a39Sopenharmony_ci} 49e1051a39Sopenharmony_ci 50e1051a39Sopenharmony_cistatic void property_defns_free(void *vproperty_defns) 51e1051a39Sopenharmony_ci{ 52e1051a39Sopenharmony_ci LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns; 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci if (property_defns != NULL) { 55e1051a39Sopenharmony_ci lh_PROPERTY_DEFN_ELEM_doall(property_defns, 56e1051a39Sopenharmony_ci &property_defn_free); 57e1051a39Sopenharmony_ci lh_PROPERTY_DEFN_ELEM_free(property_defns); 58e1051a39Sopenharmony_ci } 59e1051a39Sopenharmony_ci} 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_cistatic void *property_defns_new(OSSL_LIB_CTX *ctx) { 62e1051a39Sopenharmony_ci return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp); 63e1051a39Sopenharmony_ci} 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_cistatic const OSSL_LIB_CTX_METHOD property_defns_method = { 66e1051a39Sopenharmony_ci OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, 67e1051a39Sopenharmony_ci property_defns_new, 68e1051a39Sopenharmony_ci property_defns_free, 69e1051a39Sopenharmony_ci}; 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ciOSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop) 72e1051a39Sopenharmony_ci{ 73e1051a39Sopenharmony_ci PROPERTY_DEFN_ELEM elem, *r; 74e1051a39Sopenharmony_ci LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci property_defns = ossl_lib_ctx_get_data(ctx, 77e1051a39Sopenharmony_ci OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, 78e1051a39Sopenharmony_ci &property_defns_method); 79e1051a39Sopenharmony_ci if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx)) 80e1051a39Sopenharmony_ci return NULL; 81e1051a39Sopenharmony_ci 82e1051a39Sopenharmony_ci elem.prop = prop; 83e1051a39Sopenharmony_ci r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem); 84e1051a39Sopenharmony_ci ossl_lib_ctx_unlock(ctx); 85e1051a39Sopenharmony_ci if (r == NULL || !ossl_assert(r->defn != NULL)) 86e1051a39Sopenharmony_ci return NULL; 87e1051a39Sopenharmony_ci return r->defn; 88e1051a39Sopenharmony_ci} 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci/* 91e1051a39Sopenharmony_ci * Cache the property list for a given property string *pl. 92e1051a39Sopenharmony_ci * If an entry already exists in the cache *pl is freed and 93e1051a39Sopenharmony_ci * overwritten with the existing entry from the cache. 94e1051a39Sopenharmony_ci */ 95e1051a39Sopenharmony_ciint ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop, 96e1051a39Sopenharmony_ci OSSL_PROPERTY_LIST **pl) 97e1051a39Sopenharmony_ci{ 98e1051a39Sopenharmony_ci PROPERTY_DEFN_ELEM elem, *old, *p = NULL; 99e1051a39Sopenharmony_ci size_t len; 100e1051a39Sopenharmony_ci LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; 101e1051a39Sopenharmony_ci int res = 1; 102e1051a39Sopenharmony_ci 103e1051a39Sopenharmony_ci property_defns = ossl_lib_ctx_get_data(ctx, 104e1051a39Sopenharmony_ci OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, 105e1051a39Sopenharmony_ci &property_defns_method); 106e1051a39Sopenharmony_ci if (property_defns == NULL) 107e1051a39Sopenharmony_ci return 0; 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci if (prop == NULL) 110e1051a39Sopenharmony_ci return 1; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci if (!ossl_lib_ctx_write_lock(ctx)) 113e1051a39Sopenharmony_ci return 0; 114e1051a39Sopenharmony_ci elem.prop = prop; 115e1051a39Sopenharmony_ci if (pl == NULL) { 116e1051a39Sopenharmony_ci lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem); 117e1051a39Sopenharmony_ci goto end; 118e1051a39Sopenharmony_ci } 119e1051a39Sopenharmony_ci /* check if property definition is in the cache already */ 120e1051a39Sopenharmony_ci if ((p = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem)) != NULL) { 121e1051a39Sopenharmony_ci ossl_property_free(*pl); 122e1051a39Sopenharmony_ci *pl = p->defn; 123e1051a39Sopenharmony_ci goto end; 124e1051a39Sopenharmony_ci } 125e1051a39Sopenharmony_ci len = strlen(prop); 126e1051a39Sopenharmony_ci p = OPENSSL_malloc(sizeof(*p) + len); 127e1051a39Sopenharmony_ci if (p != NULL) { 128e1051a39Sopenharmony_ci p->prop = p->body; 129e1051a39Sopenharmony_ci p->defn = *pl; 130e1051a39Sopenharmony_ci memcpy(p->body, prop, len + 1); 131e1051a39Sopenharmony_ci old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p); 132e1051a39Sopenharmony_ci if (!ossl_assert(old == NULL)) 133e1051a39Sopenharmony_ci /* This should not happen. An existing entry is handled above. */ 134e1051a39Sopenharmony_ci goto end; 135e1051a39Sopenharmony_ci if (!lh_PROPERTY_DEFN_ELEM_error(property_defns)) 136e1051a39Sopenharmony_ci goto end; 137e1051a39Sopenharmony_ci } 138e1051a39Sopenharmony_ci OPENSSL_free(p); 139e1051a39Sopenharmony_ci res = 0; 140e1051a39Sopenharmony_ci end: 141e1051a39Sopenharmony_ci ossl_lib_ctx_unlock(ctx); 142e1051a39Sopenharmony_ci return res; 143e1051a39Sopenharmony_ci} 144