]>
Commit | Line | Data |
---|---|---|
1bdbdaff | 1 | /* |
fecb3aae | 2 | * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. |
1bdbdaff P |
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" | |
4b1f34f1 | 16 | #include "internal/core.h" |
706457b7 | 17 | #include "property_local.h" |
927d0566 | 18 | #include "crypto/context.h" |
1bdbdaff P |
19 | |
20 | /* | |
21 | * Implement a property definition cache. | |
22 | * These functions assume that they are called under a write lock. | |
23 | * No attempt is made to clean out the cache, except when it is shut down. | |
24 | */ | |
25 | ||
26 | typedef struct { | |
27 | const char *prop; | |
28 | OSSL_PROPERTY_LIST *defn; | |
29 | char body[1]; | |
30 | } PROPERTY_DEFN_ELEM; | |
31 | ||
5317b6ee | 32 | DEFINE_LHASH_OF_EX(PROPERTY_DEFN_ELEM); |
1bdbdaff | 33 | |
1bdbdaff P |
34 | static unsigned long property_defn_hash(const PROPERTY_DEFN_ELEM *a) |
35 | { | |
36 | return OPENSSL_LH_strhash(a->prop); | |
37 | } | |
38 | ||
39 | static int property_defn_cmp(const PROPERTY_DEFN_ELEM *a, | |
40 | const PROPERTY_DEFN_ELEM *b) | |
41 | { | |
42 | return strcmp(a->prop, b->prop); | |
43 | } | |
44 | ||
45 | static void property_defn_free(PROPERTY_DEFN_ELEM *elem) | |
46 | { | |
47 | ossl_property_free(elem->defn); | |
48 | OPENSSL_free(elem); | |
49 | } | |
50 | ||
927d0566 | 51 | void ossl_property_defns_free(void *vproperty_defns) |
1bdbdaff | 52 | { |
1aedc35f | 53 | LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns = vproperty_defns; |
1bdbdaff | 54 | |
1bdbdaff | 55 | if (property_defns != NULL) { |
1aedc35f MC |
56 | lh_PROPERTY_DEFN_ELEM_doall(property_defns, |
57 | &property_defn_free); | |
1bdbdaff | 58 | lh_PROPERTY_DEFN_ELEM_free(property_defns); |
1bdbdaff P |
59 | } |
60 | } | |
61 | ||
927d0566 | 62 | void *ossl_property_defns_new(OSSL_LIB_CTX *ctx) { |
1aedc35f MC |
63 | return lh_PROPERTY_DEFN_ELEM_new(&property_defn_hash, &property_defn_cmp); |
64 | } | |
65 | ||
b4250010 | 66 | OSSL_PROPERTY_LIST *ossl_prop_defn_get(OSSL_LIB_CTX *ctx, const char *prop) |
1bdbdaff P |
67 | { |
68 | PROPERTY_DEFN_ELEM elem, *r; | |
1aedc35f MC |
69 | LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; |
70 | ||
b4250010 | 71 | property_defns = ossl_lib_ctx_get_data(ctx, |
927d0566 | 72 | OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); |
4b1f34f1 | 73 | if (property_defns == NULL || !ossl_lib_ctx_read_lock(ctx)) |
1aedc35f | 74 | return NULL; |
1bdbdaff P |
75 | |
76 | elem.prop = prop; | |
77 | r = lh_PROPERTY_DEFN_ELEM_retrieve(property_defns, &elem); | |
4b1f34f1 | 78 | ossl_lib_ctx_unlock(ctx); |
1bdbdaff P |
79 | return r != NULL ? r->defn : NULL; |
80 | } | |
81 | ||
5f4b3db6 MC |
82 | /* |
83 | * Cache the property list for a given property string. Callers of this function | |
84 | * should call ossl_prop_defn_get first to ensure that there is no existing | |
85 | * cache entry for this property string. | |
86 | */ | |
b4250010 | 87 | int ossl_prop_defn_set(OSSL_LIB_CTX *ctx, const char *prop, |
1aedc35f | 88 | OSSL_PROPERTY_LIST *pl) |
1bdbdaff P |
89 | { |
90 | PROPERTY_DEFN_ELEM elem, *old, *p = NULL; | |
91 | size_t len; | |
1aedc35f | 92 | LHASH_OF(PROPERTY_DEFN_ELEM) *property_defns; |
4b1f34f1 | 93 | int res = 1; |
1aedc35f | 94 | |
b4250010 | 95 | property_defns = ossl_lib_ctx_get_data(ctx, |
927d0566 | 96 | OSSL_LIB_CTX_PROPERTY_DEFN_INDEX); |
1aedc35f MC |
97 | if (property_defns == NULL) |
98 | return 0; | |
1bdbdaff P |
99 | |
100 | if (prop == NULL) | |
101 | return 1; | |
102 | ||
4b1f34f1 P |
103 | if (!ossl_lib_ctx_write_lock(ctx)) |
104 | return 0; | |
1bdbdaff P |
105 | if (pl == NULL) { |
106 | elem.prop = prop; | |
107 | lh_PROPERTY_DEFN_ELEM_delete(property_defns, &elem); | |
4b1f34f1 | 108 | goto end; |
1bdbdaff P |
109 | } |
110 | len = strlen(prop); | |
111 | p = OPENSSL_malloc(sizeof(*p) + len); | |
112 | if (p != NULL) { | |
113 | p->prop = p->body; | |
114 | p->defn = pl; | |
115 | memcpy(p->body, prop, len + 1); | |
116 | old = lh_PROPERTY_DEFN_ELEM_insert(property_defns, p); | |
5f4b3db6 MC |
117 | if (!ossl_assert(old == NULL)) { |
118 | /* | |
119 | * This should not happen. Any caller of ossl_prop_defn_set should | |
120 | * have called ossl_prop_defn_get first - so we should know that | |
121 | * there is no existing entry. If we get here we have a bug. We | |
122 | * deliberately leak the |old| reference in order to avoid a crash | |
123 | * if there are any existing users of it. | |
124 | */ | |
4b1f34f1 | 125 | goto end; |
1bdbdaff P |
126 | } |
127 | if (!lh_PROPERTY_DEFN_ELEM_error(property_defns)) | |
4b1f34f1 | 128 | goto end; |
1bdbdaff P |
129 | } |
130 | OPENSSL_free(p); | |
4b1f34f1 P |
131 | res = 0; |
132 | end: | |
133 | ossl_lib_ctx_unlock(ctx); | |
134 | return res; | |
1bdbdaff | 135 | } |