/src/openssl30/crypto/property/defn_cache.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 2019-2022 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 <openssl/err.h> | 
| 13 |  | #include <openssl/lhash.h> | 
| 14 |  | #include "internal/propertyerr.h" | 
| 15 |  | #include "internal/property.h" | 
| 16 |  | #include "internal/core.h" | 
| 17 |  | #include "property_local.h" | 
| 18 |  |  | 
| 19 |  | /* | 
| 20 |  |  * Implement a property definition cache. | 
| 21 |  |  * These functions assume that they are called under a write lock. | 
| 22 |  |  * No attempt is made to clean out the cache, except when it is shut down. | 
| 23 |  |  */ | 
| 24 |  |  | 
| 25 |  | typedef struct { | 
| 26 |  |     const char *prop; | 
| 27 |  |     OSSL_PROPERTY_LIST *defn; | 
| 28 |  |     char body[1]; | 
| 29 |  | } PROPERTY_DEFN_ELEM; | 
| 30 |  |  | 
| 31 |  | DEFINE_LHASH_OF(PROPERTY_DEFN_ELEM); | 
| 32 |  |  | 
| 33 |  | static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a) | 
| 34 | 3.70k | { | 
| 35 | 3.70k |     return OPENSSL_LH_strhash(a->prop); | 
| 36 | 3.70k | } | 
| 37 |  |  | 
| 38 |  | static int property_defn_cmp(const PROPERTY_DEFN_ELEM *a, | 
| 39 |  |                              const PROPERTY_DEFN_ELEM *b) | 
| 40 | 2.41k | { | 
| 41 | 2.41k |     return strcmp(a->prop, b->prop); | 
| 42 | 2.41k | } | 
| 43 |  |  | 
| 44 |  | static void property_defn_free(PROPERTY_DEFN_ELEM *elem) | 
| 45 | 431 | { | 
| 46 | 431 |     ossl_property_free(elem->defn); | 
| 47 | 431 |     OPENSSL_free(elem); | 
| 48 | 431 | } | 
| 49 |  |  | 
| 50 |  | static void property_defns_free(void *vproperty_defns) | 
| 51 | 7 | { | 
| 52 | 7 |     LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns; | 
| 53 |  |  | 
| 54 | 7 |     if (property_defns != NULL) { | 
| 55 | 7 |         lh_PROPERTY_DEFN_ELEM_doall(property_defns, | 
| 56 | 7 |                                     &property_defn_free); | 
| 57 | 7 |         lh_PROPERTY_DEFN_ELEM_free(property_defns); | 
| 58 | 7 |     } | 
| 59 | 7 | } | 
| 60 |  |  | 
| 61 | 7 | static void *property_defns_new(OSSL_LIB_CTX *ctx) { | 
| 62 | 7 |     return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp); | 
| 63 | 7 | } | 
| 64 |  |  | 
| 65 |  | static const OSSL_LIB_CTX_METHOD property_defns_method = { | 
| 66 |  |     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, | 
| 67 |  |     property_defns_new, | 
| 68 |  |     property_defns_free, | 
| 69 |  | }; | 
| 70 |  |  | 
| 71 |  | OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop) | 
| 72 | 1.24k | { | 
| 73 | 1.24k |     PROPERTY_DEFN_ELEM elem, *r; | 
| 74 | 1.24k |     LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; | 
| 75 |  |  | 
| 76 | 1.24k |     property_defns = ossl_lib_ctx_get_data(ctx, | 
| 77 | 1.24k |                                            OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, | 
| 78 | 1.24k |                                            &property_defns_method); | 
| 79 | 1.24k |     if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx)) | 
| 80 | 0 |         return NULL; | 
| 81 |  |  | 
| 82 | 1.24k |     elem.prop = prop; | 
| 83 | 1.24k |     r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem); | 
| 84 | 1.24k |     ossl_lib_ctx_unlock(ctx); | 
| 85 | 1.24k |     if (r == NULL || !ossl_assert(r->defn != NULL)) | 
| 86 | 176 |         return NULL; | 
| 87 | 1.06k |     return r->defn; | 
| 88 | 1.24k | } | 
| 89 |  |  | 
| 90 |  | /* | 
| 91 |  |  * Cache the property list for a given property string *pl. | 
| 92 |  |  * If an entry already exists in the cache *pl is freed and | 
| 93 |  |  * overwritten with the existing entry from the cache. | 
| 94 |  |  */ | 
| 95 |  | int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop, | 
| 96 |  |                        OSSL_PROPERTY_LIST **pl) | 
| 97 | 431 | { | 
| 98 | 431 |     PROPERTY_DEFN_ELEM elem, *old, *p = NULL; | 
| 99 | 431 |     size_t len; | 
| 100 | 431 |     LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; | 
| 101 | 431 |     int res = 1; | 
| 102 |  |  | 
| 103 | 431 |     property_defns = ossl_lib_ctx_get_data(ctx, | 
| 104 | 431 |                                            OSSL_LIB_CTX_PROPERTY_DEFN_INDEX, | 
| 105 | 431 |                                            &property_defns_method); | 
| 106 | 431 |     if (property_defns == NULL) | 
| 107 | 0 |         return 0; | 
| 108 |  |  | 
| 109 | 431 |     if (prop == NULL) | 
| 110 | 0 |         return 1; | 
| 111 |  |  | 
| 112 | 431 |     if (!ossl_lib_ctx_write_lock(ctx)) | 
| 113 | 0 |         return 0; | 
| 114 | 431 |     elem.prop = prop; | 
| 115 | 431 |     if (pl == NULL) { | 
| 116 | 0 |         lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem); | 
| 117 | 0 |         goto end; | 
| 118 | 0 |     } | 
| 119 |  |     /* check if property definition is in the cache already */ | 
| 120 | 431 |     if ((p = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem)) != NULL) { | 
| 121 | 0 |         ossl_property_free(*pl); | 
| 122 | 0 |         *pl = p->defn; | 
| 123 | 0 |         goto end; | 
| 124 | 0 |     } | 
| 125 | 431 |     len = strlen(prop); | 
| 126 | 431 |     p = OPENSSL_malloc(sizeof(*p) + len); | 
| 127 | 431 |     if (p != NULL) { | 
| 128 | 431 |         p->prop = p->body; | 
| 129 | 431 |         p->defn = *pl; | 
| 130 | 431 |         memcpy(p->body, prop, len + 1); | 
| 131 | 431 |         old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p); | 
| 132 | 431 |         if (!ossl_assert(old == NULL)) | 
| 133 |  |             /* This should not happen. An existing entry is handled above. */ | 
| 134 | 0 |             goto end; | 
| 135 | 431 |         if (!lh_PROPERTY_DEFN_ELEM_error(property_defns)) | 
| 136 | 431 |             goto end; | 
| 137 | 431 |     } | 
| 138 | 0 |     OPENSSL_free(p); | 
| 139 | 0 |     res = 0; | 
| 140 | 431 |  end: | 
| 141 | 431 |     ossl_lib_ctx_unlock(ctx); | 
| 142 | 431 |     return res; | 
| 143 | 0 | } |