summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/crypto_ex_data.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/crypto_ex_data.c')
-rw-r--r--src/lib/libcrypto/crypto_ex_data.c418
1 files changed, 0 insertions, 418 deletions
diff --git a/src/lib/libcrypto/crypto_ex_data.c b/src/lib/libcrypto/crypto_ex_data.c
deleted file mode 100644
index ceb3a92e51..0000000000
--- a/src/lib/libcrypto/crypto_ex_data.c
+++ /dev/null
@@ -1,418 +0,0 @@
1/* $OpenBSD: crypto_ex_data.c,v 1.4 2024/08/03 07:45:26 tb Exp $ */
2/*
3 * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdlib.h>
19
20#include <openssl/crypto.h>
21
22#define CRYPTO_EX_DATA_MAX_INDEX 32
23
24struct crypto_ex_data {
25 int class_index;
26 void **slots;
27 size_t slots_len;
28};
29
30struct crypto_ex_data_index {
31 CRYPTO_EX_new *new_func;
32 CRYPTO_EX_dup *dup_func;
33 CRYPTO_EX_free *free_func;
34 long argl;
35 void *argp;
36};
37
38struct crypto_ex_data_class {
39 struct crypto_ex_data_index **indexes;
40 size_t indexes_len;
41 size_t next_index;
42};
43
44static struct crypto_ex_data_class **classes;
45
46static int
47crypto_ex_data_classes_init(void)
48{
49 struct crypto_ex_data_class **classes_new = NULL;
50
51 if (classes != NULL)
52 return 1;
53
54 if ((classes_new = calloc(CRYPTO_EX_INDEX__COUNT,
55 sizeof(struct crypto_ex_data_index))) == NULL)
56 return 0;
57
58 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
59 if (classes == NULL) {
60 classes = classes_new;
61 classes_new = NULL;
62 }
63 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
64
65 free(classes_new);
66
67 return 1;
68}
69
70static struct crypto_ex_data_class *
71crypto_ex_data_class_lookup(int class_index)
72{
73 struct crypto_ex_data_class *class;
74
75 if (classes == NULL)
76 return NULL;
77 if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT)
78 return NULL;
79
80 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
81 class = classes[class_index];
82 CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
83
84 return class;
85}
86
87int
88CRYPTO_get_ex_new_index(int class_index, long argl, void *argp,
89 CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
90{
91 struct crypto_ex_data_class *new_class = NULL;
92 struct crypto_ex_data_index *index = NULL;
93 struct crypto_ex_data_class *class;
94 int idx = -1;
95
96 if (!crypto_ex_data_classes_init())
97 goto err;
98
99 if (class_index < 0 || class_index >= CRYPTO_EX_INDEX__COUNT)
100 goto err;
101
102 if ((class = classes[class_index]) == NULL) {
103 if ((new_class = calloc(1,
104 sizeof(struct crypto_ex_data_class))) == NULL)
105 goto err;
106 if ((new_class->indexes = calloc(CRYPTO_EX_DATA_MAX_INDEX,
107 sizeof(struct crypto_ex_data_index *))) == NULL)
108 goto err;
109 new_class->indexes_len = CRYPTO_EX_DATA_MAX_INDEX;
110 new_class->next_index = 1;
111
112 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
113 if (classes[class_index] == NULL) {
114 classes[class_index] = new_class;
115 new_class = NULL;
116 }
117 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
118
119 class = classes[class_index];
120 }
121
122 if ((index = calloc(1, sizeof(struct crypto_ex_data_index))) == NULL)
123 goto err;
124
125 index->new_func = new_func;
126 index->dup_func = dup_func;
127 index->free_func = free_func;
128
129 index->argl = argl;
130 index->argp = argp;
131
132 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
133 if (class->next_index < class->indexes_len) {
134 idx = class->next_index++;
135 class->indexes[idx] = index;
136 index = NULL;
137 }
138 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
139
140
141 err:
142 if (new_class != NULL) {
143 free(new_class->indexes);
144 free(new_class);
145 }
146 free(index);
147
148 return idx;
149}
150LCRYPTO_ALIAS(CRYPTO_get_ex_new_index);
151
152void
153CRYPTO_cleanup_all_ex_data(void)
154{
155 struct crypto_ex_data_class *class;
156 int i, j;
157
158 if (classes == NULL)
159 return;
160
161 for (i = 0; i < CRYPTO_EX_INDEX__COUNT; i++) {
162 if ((class = classes[i]) == NULL)
163 continue;
164
165 if (class->indexes != NULL) {
166 for (j = 0; j < CRYPTO_EX_DATA_MAX_INDEX; j++)
167 free(class->indexes[j]);
168 free(class->indexes);
169 }
170
171 free(class);
172 }
173
174 free(classes);
175 classes = NULL;
176}
177LCRYPTO_ALIAS(CRYPTO_cleanup_all_ex_data);
178
179static void
180crypto_ex_data_clear(CRYPTO_EX_DATA *exdata)
181{
182 struct crypto_ex_data *ced;
183
184 if (exdata == NULL)
185 return;
186
187 if ((ced = exdata->sk) != NULL) {
188 freezero(ced->slots, ced->slots_len * sizeof(void *));
189 freezero(ced, sizeof(*ced));
190 }
191
192 exdata->sk = NULL;
193}
194
195static int
196crypto_ex_data_init(CRYPTO_EX_DATA *exdata)
197{
198 struct crypto_ex_data *ced = NULL;
199
200 if (exdata->sk != NULL)
201 goto err;
202
203 if ((ced = calloc(1, sizeof(struct crypto_ex_data))) == NULL)
204 goto err;
205
206 ced->class_index = -1;
207
208 if ((ced->slots = calloc(CRYPTO_EX_DATA_MAX_INDEX, sizeof(void *))) == NULL)
209 goto err;
210 ced->slots_len = CRYPTO_EX_DATA_MAX_INDEX;
211
212 exdata->sk = ced;
213
214 return 1;
215
216 err:
217 if (ced != NULL) {
218 free(ced->slots);
219 free(ced);
220 }
221 crypto_ex_data_clear(exdata);
222
223 return 0;
224}
225
226int
227CRYPTO_new_ex_data(int class_index, void *parent, CRYPTO_EX_DATA *exdata)
228{
229 struct crypto_ex_data_class *class;
230 struct crypto_ex_data_index *index;
231 struct crypto_ex_data *ced;
232 size_t i, last_index;
233
234 if (!crypto_ex_data_init(exdata))
235 goto err;
236 if ((ced = exdata->sk) == NULL)
237 goto err;
238
239 if (!crypto_ex_data_classes_init())
240 goto err;
241 if ((class = crypto_ex_data_class_lookup(class_index)) == NULL)
242 goto done;
243
244 ced->class_index = class_index;
245
246 /* Existing indexes are immutable, we just have to know when to stop. */
247 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
248 last_index = class->next_index;
249 CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
250
251 for (i = 0; i < last_index; i++) {
252 if ((index = class->indexes[i]) == NULL)
253 continue;
254 if (index->new_func == NULL)
255 continue;
256 if (!index->new_func(parent, NULL, exdata, i, index->argl,
257 index->argp))
258 goto err;
259 }
260
261 done:
262 return 1;
263
264 err:
265 CRYPTO_free_ex_data(class_index, parent, exdata);
266
267 return 0;
268}
269LCRYPTO_ALIAS(CRYPTO_new_ex_data);
270
271int
272CRYPTO_dup_ex_data(int class_index, CRYPTO_EX_DATA *dst, CRYPTO_EX_DATA *src)
273{
274 struct crypto_ex_data *dst_ced, *src_ced;
275 struct crypto_ex_data_class *class;
276 struct crypto_ex_data_index *index;
277 size_t i, last_index;
278 void *val;
279
280 if (dst == NULL || src == NULL)
281 goto err;
282
283 /*
284 * Some code calls CRYPTO_new_ex_data() before dup, others never call
285 * CRYPTO_new_ex_data()... so we get to handle both.
286 */
287 /* XXX - parent == NULL? */
288 CRYPTO_free_ex_data(class_index, NULL, dst);
289
290 if (!crypto_ex_data_init(dst))
291 goto err;
292
293 if ((dst_ced = dst->sk) == NULL)
294 goto err;
295 if ((src_ced = src->sk) == NULL)
296 goto err;
297
298 if ((class = crypto_ex_data_class_lookup(class_index)) == NULL) {
299 for (i = 0; i < CRYPTO_EX_DATA_MAX_INDEX; i++)
300 dst_ced->slots[i] = src_ced->slots[i];
301 goto done;
302 }
303
304 OPENSSL_assert(src_ced->class_index == class_index);
305
306 dst_ced->class_index = class_index;
307
308 /* Existing indexes are immutable, we just have to know when to stop. */
309 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
310 last_index = class->next_index;
311 CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
312
313 for (i = 0; i < last_index; i++) {
314 if ((index = class->indexes[i]) == NULL)
315 continue;
316
317 /* If there is no dup function, we copy the pointer. */
318 val = src_ced->slots[i];
319 if (index->dup_func != NULL) {
320 if (!index->dup_func(dst, src, &val, i, index->argl,
321 index->argp))
322 goto err;
323 }
324 /* If the dup function set data, we will potentially leak. */
325 if (dst_ced->slots[i] != NULL)
326 goto err;
327 dst_ced->slots[i] = val;
328 }
329
330 done:
331 return 1;
332
333 err:
334 /* XXX - parent == NULL? */
335 CRYPTO_free_ex_data(class_index, NULL, dst);
336
337 return 0;
338}
339LCRYPTO_ALIAS(CRYPTO_dup_ex_data);
340
341void
342CRYPTO_free_ex_data(int class_index, void *parent, CRYPTO_EX_DATA *exdata)
343{
344 struct crypto_ex_data_class *class;
345 struct crypto_ex_data_index *index;
346 struct crypto_ex_data *ced;
347 size_t i, last_index;
348
349 if (exdata == NULL)
350 return;
351 if ((ced = exdata->sk) == NULL)
352 goto done;
353 if (ced->class_index == -1)
354 goto done;
355
356 if ((class = crypto_ex_data_class_lookup(class_index)) == NULL)
357 goto done;
358
359 OPENSSL_assert(ced->class_index == class_index);
360
361 /* Existing indexes are immutable, we just have to know when to stop. */
362 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
363 last_index = class->next_index;
364 CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
365
366 for (i = 0; i < last_index; i++) {
367 if ((index = class->indexes[i]) == NULL)
368 continue;
369 if (index->free_func == NULL)
370 continue;
371 index->free_func(parent, ced->slots[i], exdata, i, index->argl,
372 index->argp);
373 }
374
375 done:
376 crypto_ex_data_clear(exdata);
377}
378LCRYPTO_ALIAS(CRYPTO_free_ex_data);
379
380int
381CRYPTO_set_ex_data(CRYPTO_EX_DATA *exdata, int idx, void *val)
382{
383 struct crypto_ex_data *ced;
384
385 /*
386 * Preserve horrible historical behaviour - allow set to work even if
387 * new has not been called first.
388 */
389 if ((ced = exdata->sk) == NULL) {
390 if (!crypto_ex_data_init(exdata))
391 return 0;
392 ced = exdata->sk;
393 }
394
395 /* XXX - consider preventing set for an unallocated index. */
396
397 if (idx < 0 || idx >= ced->slots_len)
398 return 0;
399
400 ced->slots[idx] = val;
401
402 return 1;
403}
404LCRYPTO_ALIAS(CRYPTO_set_ex_data);
405
406void *
407CRYPTO_get_ex_data(const CRYPTO_EX_DATA *exdata, int idx)
408{
409 struct crypto_ex_data *ced;
410
411 if ((ced = exdata->sk) == NULL)
412 return NULL;
413 if (idx < 0 || idx >= ced->slots_len)
414 return NULL;
415
416 return ced->slots[idx];
417}
418LCRYPTO_ALIAS(CRYPTO_get_ex_data);