]>
Commit | Line | Data |
---|---|---|
1bdbdaff P |
1 | /* |
2 | * Copyright 2019 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/crypto.h> | |
13 | #include <openssl/lhash.h> | |
14 | #include "internal/lhash.h" | |
15 | #include "property_lcl.h" | |
16 | ||
17 | /* | |
18 | * Property strings are a consolidation of all strings seen by the property | |
19 | * subsystem. There are two name spaces to keep property names separate from | |
20 | * property values (numeric values are not expected to be cached however). | |
21 | * They allow a rapid conversion from a string to a unique index and any | |
22 | * subsequent string comparison can be done via an integer compare. | |
23 | * | |
24 | * This implementation uses OpenSSL's standard hash table. There are more | |
25 | * space and time efficient algorithms if this becomes a bottleneck. | |
26 | */ | |
27 | ||
28 | typedef struct { | |
29 | const char *s; | |
30 | OSSL_PROPERTY_IDX idx; | |
31 | char body[1]; | |
32 | } PROPERTY_STRING; | |
33 | ||
34 | DEFINE_LHASH_OF(PROPERTY_STRING); | |
35 | typedef LHASH_OF(PROPERTY_STRING) PROP_TABLE; | |
36 | ||
1aedc35f MC |
37 | typedef struct { |
38 | PROP_TABLE *prop_names; | |
39 | PROP_TABLE *prop_values; | |
40 | OSSL_PROPERTY_IDX prop_name_idx; | |
41 | OSSL_PROPERTY_IDX prop_value_idx; | |
42 | } PROPERTY_STRING_DATA; | |
1bdbdaff P |
43 | |
44 | static unsigned long property_hash(const PROPERTY_STRING *a) | |
45 | { | |
46 | return OPENSSL_LH_strhash(a->s); | |
47 | } | |
48 | ||
49 | static int property_cmp(const PROPERTY_STRING *a, const PROPERTY_STRING *b) | |
50 | { | |
51 | return strcmp(a->s, b->s); | |
52 | } | |
53 | ||
54 | static void property_free(PROPERTY_STRING *ps) | |
55 | { | |
56 | OPENSSL_free(ps); | |
57 | } | |
58 | ||
59 | static void property_table_free(PROP_TABLE **pt) | |
60 | { | |
61 | PROP_TABLE *t = *pt; | |
62 | ||
63 | if (t != NULL) { | |
64 | lh_PROPERTY_STRING_doall(t, &property_free); | |
65 | lh_PROPERTY_STRING_free(t); | |
66 | *pt = NULL; | |
67 | } | |
68 | } | |
69 | ||
1aedc35f MC |
70 | static void property_string_data_free(void *vpropdata) |
71 | { | |
72 | PROPERTY_STRING_DATA *propdata = vpropdata; | |
73 | ||
74 | if (propdata == NULL) | |
75 | return; | |
76 | ||
77 | property_table_free(&propdata->prop_names); | |
78 | property_table_free(&propdata->prop_values); | |
79 | propdata->prop_name_idx = propdata->prop_value_idx = 0; | |
80 | ||
81 | OPENSSL_free(propdata); | |
82 | } | |
83 | ||
84 | static void *property_string_data_new(OPENSSL_CTX *ctx) { | |
85 | PROPERTY_STRING_DATA *propdata = OPENSSL_zalloc(sizeof(*propdata)); | |
86 | ||
87 | if (propdata == NULL) | |
88 | return NULL; | |
89 | ||
90 | propdata->prop_names = lh_PROPERTY_STRING_new(&property_hash, | |
91 | &property_cmp); | |
92 | if (propdata->prop_names == NULL) | |
93 | goto err; | |
94 | ||
95 | propdata->prop_values = lh_PROPERTY_STRING_new(&property_hash, | |
96 | &property_cmp); | |
97 | if (propdata->prop_values == NULL) | |
98 | goto err; | |
99 | ||
100 | return propdata; | |
101 | ||
102 | err: | |
103 | property_string_data_free(propdata); | |
104 | return NULL; | |
105 | } | |
106 | ||
107 | static const OPENSSL_CTX_METHOD property_string_data_method = { | |
108 | property_string_data_new, | |
109 | property_string_data_free, | |
110 | }; | |
111 | ||
1bdbdaff P |
112 | static PROPERTY_STRING *new_property_string(const char *s, |
113 | OSSL_PROPERTY_IDX *pidx) | |
114 | { | |
115 | const size_t l = strlen(s); | |
116 | PROPERTY_STRING *ps = OPENSSL_malloc(sizeof(*ps) + l); | |
117 | ||
118 | if (ps != NULL) { | |
119 | memcpy(ps->body, s, l + 1); | |
120 | ps->s = ps->body; | |
121 | ps->idx = ++*pidx; | |
122 | if (ps->idx == 0) { | |
123 | OPENSSL_free(ps); | |
124 | return NULL; | |
125 | } | |
126 | } | |
127 | return ps; | |
128 | } | |
129 | ||
130 | static OSSL_PROPERTY_IDX ossl_property_string(PROP_TABLE *t, | |
131 | OSSL_PROPERTY_IDX *pidx, | |
132 | const char *s) | |
133 | { | |
134 | PROPERTY_STRING p, *ps, *ps_new; | |
135 | ||
136 | p.s = s; | |
137 | ps = lh_PROPERTY_STRING_retrieve(t, &p); | |
138 | if (ps == NULL && pidx != NULL) | |
139 | if ((ps_new = new_property_string(s, pidx)) != NULL) { | |
140 | lh_PROPERTY_STRING_insert(t, ps_new); | |
141 | if (lh_PROPERTY_STRING_error(t)) { | |
142 | property_free(ps_new); | |
143 | return 0; | |
144 | } | |
145 | ps = ps_new; | |
146 | } | |
147 | return ps != NULL ? ps->idx : 0; | |
148 | } | |
149 | ||
1aedc35f MC |
150 | OSSL_PROPERTY_IDX ossl_property_name(OPENSSL_CTX *ctx, const char *s, |
151 | int create) | |
1bdbdaff | 152 | { |
1aedc35f MC |
153 | PROPERTY_STRING_DATA *propdata |
154 | = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX, | |
155 | &property_string_data_method); | |
1bdbdaff | 156 | |
1aedc35f | 157 | if (propdata == NULL) |
1bdbdaff | 158 | return 0; |
1aedc35f MC |
159 | return ossl_property_string(propdata->prop_names, |
160 | create ? &propdata->prop_name_idx : NULL, | |
161 | s); | |
1bdbdaff P |
162 | } |
163 | ||
1aedc35f MC |
164 | OSSL_PROPERTY_IDX ossl_property_value(OPENSSL_CTX *ctx, const char *s, |
165 | int create) | |
1bdbdaff | 166 | { |
1aedc35f MC |
167 | PROPERTY_STRING_DATA *propdata |
168 | = openssl_ctx_get_data(ctx, OPENSSL_CTX_PROPERTY_STRING_INDEX, | |
169 | &property_string_data_method); | |
170 | ||
171 | if (propdata == NULL) | |
172 | return 0; | |
173 | return ossl_property_string(propdata->prop_values, | |
174 | create ? &propdata->prop_value_idx : NULL, | |
175 | s); | |
1bdbdaff | 176 | } |