]>
Commit | Line | Data |
---|---|---|
d64b6299 RL |
1 | /* |
2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include "internal/cryptlib.h" | |
11 | #include "internal/thread_once.h" | |
12 | ||
13 | struct openssl_ctx_st { | |
14 | CRYPTO_RWLOCK *lock; | |
15 | CRYPTO_EX_DATA data; | |
16 | }; | |
17 | ||
18 | static OPENSSL_CTX default_context; | |
19 | ||
20 | static int context_init(OPENSSL_CTX *ctx) | |
21 | { | |
22 | return (ctx->lock = CRYPTO_THREAD_lock_new()) != NULL | |
23 | && CRYPTO_new_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, | |
24 | &ctx->data); | |
25 | } | |
26 | ||
27 | static int context_deinit(OPENSSL_CTX *ctx) | |
28 | { | |
29 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data); | |
30 | CRYPTO_THREAD_lock_free(ctx->lock); | |
31 | return 1; | |
32 | } | |
33 | ||
34 | static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT; | |
35 | static void do_default_context_deinit(void) | |
36 | { | |
37 | context_deinit(&default_context); | |
38 | } | |
39 | DEFINE_RUN_ONCE_STATIC(do_default_context_init) | |
40 | { | |
41 | return OPENSSL_init_crypto(0, NULL) | |
42 | && context_init(&default_context) | |
43 | && OPENSSL_atexit(do_default_context_deinit); | |
44 | } | |
45 | ||
46 | OPENSSL_CTX *OPENSSL_CTX_new(void) | |
47 | { | |
48 | OPENSSL_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); | |
49 | ||
50 | if (ctx != NULL && !context_init(ctx)) { | |
51 | OPENSSL_CTX_free(ctx); | |
52 | ctx = NULL; | |
53 | } | |
54 | return ctx; | |
55 | } | |
56 | ||
57 | void OPENSSL_CTX_free(OPENSSL_CTX *ctx) | |
58 | { | |
59 | if (ctx != NULL) | |
60 | context_deinit(ctx); | |
61 | OPENSSL_free(ctx); | |
62 | } | |
63 | ||
64 | static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign, | |
65 | CRYPTO_EX_DATA *ad, int index, | |
66 | long argl_ign, void *argp) | |
67 | { | |
68 | const OPENSSL_CTX_METHOD *meth = argp; | |
69 | void *ptr = meth->new_func(); | |
70 | ||
71 | if (ptr != NULL) | |
72 | CRYPTO_set_ex_data(ad, index, ptr); | |
73 | } | |
74 | static void openssl_ctx_generic_free(void *parent_ign, void *ptr, | |
75 | CRYPTO_EX_DATA *ad, int index, | |
76 | long argl_ign, void *argp) | |
77 | { | |
78 | const OPENSSL_CTX_METHOD *meth = argp; | |
79 | ||
80 | meth->free_func(ptr); | |
81 | } | |
82 | int openssl_ctx_new_index(const OPENSSL_CTX_METHOD *meth) | |
83 | { | |
84 | return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_OPENSSL_CTX, 0, (void *)meth, | |
85 | openssl_ctx_generic_new, NULL, | |
86 | openssl_ctx_generic_free); | |
87 | } | |
88 | ||
89 | void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index) | |
90 | { | |
91 | void *data = NULL; | |
92 | ||
93 | if (ctx == NULL) { | |
94 | if (!RUN_ONCE(&default_context_init, do_default_context_init)) | |
95 | return 0; | |
96 | ctx = &default_context; | |
97 | } | |
98 | ||
99 | CRYPTO_THREAD_read_lock(ctx->lock); | |
100 | ||
101 | /* The alloc call ensures there's a value there */ | |
102 | if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, | |
103 | &ctx->data, index)) | |
104 | data = CRYPTO_get_ex_data(&ctx->data, index); | |
105 | ||
106 | CRYPTO_THREAD_unlock(ctx->lock); | |
107 | ||
108 | return data; | |
109 | } | |
110 |