Support calling EVP_DigestUpdate instead of EVP_Digest[Sign|Verify]Update
[openssl.git] / crypto / context.c
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 "crypto/cryptlib.h"
11 #include "internal/thread_once.h"
12 #include "internal/property.h"
13
14 struct openssl_ctx_onfree_list_st {
15     openssl_ctx_onfree_fn *fn;
16     struct openssl_ctx_onfree_list_st *next;
17 };
18
19 struct openssl_ctx_st {
20     CRYPTO_RWLOCK *lock;
21     CRYPTO_EX_DATA data;
22
23     /*
24      * For most data in the OPENSSL_CTX we just use ex_data to store it. But
25      * that doesn't work for ex_data itself - so we store that directly.
26      */
27     OSSL_EX_DATA_GLOBAL global;
28
29     /* Map internal static indexes to dynamically created indexes */
30     int dyn_indexes[OPENSSL_CTX_MAX_INDEXES];
31
32     /* Keep a separate lock for each index */
33     CRYPTO_RWLOCK *index_locks[OPENSSL_CTX_MAX_INDEXES];
34
35     CRYPTO_RWLOCK *oncelock;
36     int run_once_done[OPENSSL_CTX_MAX_RUN_ONCE];
37     int run_once_ret[OPENSSL_CTX_MAX_RUN_ONCE];
38     struct openssl_ctx_onfree_list_st *onfreelist;
39 };
40
41 #ifndef FIPS_MODE
42 static OPENSSL_CTX default_context_int;
43
44 /* Always points at default_context_int if it has been initialised */
45 static OPENSSL_CTX *default_context = NULL;
46 #endif
47
48 static int context_init(OPENSSL_CTX *ctx)
49 {
50     size_t i;
51     int exdata_done = 0;
52
53     ctx->lock = CRYPTO_THREAD_lock_new();
54     if (ctx->lock == NULL)
55         return 0;
56
57     ctx->oncelock = CRYPTO_THREAD_lock_new();
58     if (ctx->oncelock == NULL)
59         goto err;
60
61     for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++) {
62         ctx->index_locks[i] = CRYPTO_THREAD_lock_new();
63         ctx->dyn_indexes[i] = -1;
64         if (ctx->index_locks[i] == NULL)
65             goto err;
66     }
67
68     /* OPENSSL_CTX is built on top of ex_data so we initialise that directly */
69     if (!do_ex_data_init(ctx))
70         goto err;
71     exdata_done = 1;
72
73     if (!crypto_new_ex_data_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
74                                &ctx->data)) {
75         crypto_cleanup_all_ex_data_int(ctx);
76         goto err;
77     }
78
79     /* Everything depends on properties, so we also pre-initialise that */
80     if (!ossl_property_parse_init(ctx))
81         goto err;
82
83     return 1;
84  err:
85     if (exdata_done)
86         crypto_cleanup_all_ex_data_int(ctx);
87     CRYPTO_THREAD_lock_free(ctx->oncelock);
88     CRYPTO_THREAD_lock_free(ctx->lock);
89     ctx->lock = NULL;
90     return 0;
91 }
92
93 static int context_deinit(OPENSSL_CTX *ctx)
94 {
95     struct openssl_ctx_onfree_list_st *tmp, *onfree;
96     int i;
97
98     if (ctx == NULL)
99         return 1;
100
101     ossl_ctx_thread_stop(ctx);
102
103     onfree = ctx->onfreelist;
104     while (onfree != NULL) {
105         onfree->fn(ctx);
106         tmp = onfree;
107         onfree = onfree->next;
108         OPENSSL_free(tmp);
109     }
110     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL, &ctx->data);
111     crypto_cleanup_all_ex_data_int(ctx);
112     for (i = 0; i < OPENSSL_CTX_MAX_INDEXES; i++)
113         CRYPTO_THREAD_lock_free(ctx->index_locks[i]);
114
115     CRYPTO_THREAD_lock_free(ctx->oncelock);
116     CRYPTO_THREAD_lock_free(ctx->lock);
117     ctx->lock = NULL;
118     return 1;
119 }
120
121 #ifndef FIPS_MODE
122 void openssl_ctx_default_deinit(void)
123 {
124     context_deinit(default_context);
125 }
126
127 static CRYPTO_ONCE default_context_init = CRYPTO_ONCE_STATIC_INIT;
128 DEFINE_RUN_ONCE_STATIC(do_default_context_init)
129 {
130     if (context_init(&default_context_int))
131         default_context = &default_context_int;
132
133     return 1;
134 }
135 #endif
136
137 OPENSSL_CTX *OPENSSL_CTX_new(void)
138 {
139     OPENSSL_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
140
141     if (ctx != NULL && !context_init(ctx)) {
142         OPENSSL_CTX_free(ctx);
143         ctx = NULL;
144     }
145     return ctx;
146 }
147
148 void OPENSSL_CTX_free(OPENSSL_CTX *ctx)
149 {
150     if (ctx != NULL)
151         context_deinit(ctx);
152     OPENSSL_free(ctx);
153 }
154
155 OPENSSL_CTX *openssl_ctx_get_concrete(OPENSSL_CTX *ctx)
156 {
157 #ifndef FIPS_MODE
158     if (ctx == NULL) {
159         if (!RUN_ONCE(&default_context_init, do_default_context_init))
160             return 0;
161         return default_context;
162     }
163 #endif
164     return ctx;
165 }
166
167 static void openssl_ctx_generic_new(void *parent_ign, void *ptr_ign,
168                                     CRYPTO_EX_DATA *ad, int index,
169                                     long argl_ign, void *argp)
170 {
171     const OPENSSL_CTX_METHOD *meth = argp;
172     void *ptr = meth->new_func(crypto_ex_data_get_openssl_ctx(ad));
173
174     if (ptr != NULL)
175         CRYPTO_set_ex_data(ad, index, ptr);
176 }
177 static void openssl_ctx_generic_free(void *parent_ign, void *ptr,
178                                      CRYPTO_EX_DATA *ad, int index,
179                                      long argl_ign, void *argp)
180 {
181     const OPENSSL_CTX_METHOD *meth = argp;
182
183     meth->free_func(ptr);
184 }
185
186 /* Non-static so we can use it in context_internal_test */
187 static int openssl_ctx_init_index(OPENSSL_CTX *ctx, int static_index,
188                                   const OPENSSL_CTX_METHOD *meth)
189 {
190     int idx;
191
192     ctx = openssl_ctx_get_concrete(ctx);
193     if (ctx == NULL)
194         return 0;
195
196     idx = crypto_get_ex_new_index_ex(ctx, CRYPTO_EX_INDEX_OPENSSL_CTX, 0,
197                                      (void *)meth,
198                                      openssl_ctx_generic_new,
199                                      NULL, openssl_ctx_generic_free);
200     if (idx < 0)
201         return 0;
202
203     ctx->dyn_indexes[static_index] = idx;
204     return 1;
205 }
206
207 void *openssl_ctx_get_data(OPENSSL_CTX *ctx, int index,
208                            const OPENSSL_CTX_METHOD *meth)
209 {
210     void *data = NULL;
211     int dynidx;
212
213     ctx = openssl_ctx_get_concrete(ctx);
214     if (ctx == NULL)
215         return NULL;
216
217     CRYPTO_THREAD_read_lock(ctx->lock);
218     dynidx = ctx->dyn_indexes[index];
219     CRYPTO_THREAD_unlock(ctx->lock);
220
221     if (dynidx != -1) {
222         CRYPTO_THREAD_read_lock(ctx->index_locks[index]);
223         data = CRYPTO_get_ex_data(&ctx->data, dynidx);
224         CRYPTO_THREAD_unlock(ctx->index_locks[index]);
225         return data;
226     }
227
228     CRYPTO_THREAD_write_lock(ctx->index_locks[index]);
229     CRYPTO_THREAD_write_lock(ctx->lock);
230
231     dynidx = ctx->dyn_indexes[index];
232     if (dynidx != -1) {
233         CRYPTO_THREAD_unlock(ctx->lock);
234         data = CRYPTO_get_ex_data(&ctx->data, dynidx);
235         CRYPTO_THREAD_unlock(ctx->index_locks[index]);
236         return data;
237     }
238
239     if (!openssl_ctx_init_index(ctx, index, meth)) {
240         CRYPTO_THREAD_unlock(ctx->lock);
241         CRYPTO_THREAD_unlock(ctx->index_locks[index]);
242         return NULL;
243     }
244
245     CRYPTO_THREAD_unlock(ctx->lock);
246
247     /* The alloc call ensures there's a value there */
248     if (CRYPTO_alloc_ex_data(CRYPTO_EX_INDEX_OPENSSL_CTX, NULL,
249                              &ctx->data, ctx->dyn_indexes[index]))
250         data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
251
252     CRYPTO_THREAD_unlock(ctx->index_locks[index]);
253
254     return data;
255 }
256
257 OSSL_EX_DATA_GLOBAL *openssl_ctx_get_ex_data_global(OPENSSL_CTX *ctx)
258 {
259     ctx = openssl_ctx_get_concrete(ctx);
260     if (ctx == NULL)
261         return NULL;
262     return &ctx->global;
263 }
264
265 int openssl_ctx_run_once(OPENSSL_CTX *ctx, unsigned int idx,
266                          openssl_ctx_run_once_fn run_once_fn)
267 {
268     int done = 0, ret = 0;
269
270     ctx = openssl_ctx_get_concrete(ctx);
271     if (ctx == NULL)
272         return 0;
273
274     CRYPTO_THREAD_read_lock(ctx->oncelock);
275     done = ctx->run_once_done[idx];
276     if (done)
277         ret = ctx->run_once_ret[idx];
278     CRYPTO_THREAD_unlock(ctx->oncelock);
279
280     if (done)
281         return ret;
282
283     CRYPTO_THREAD_write_lock(ctx->oncelock);
284     if (ctx->run_once_done[idx]) {
285         ret = ctx->run_once_ret[idx];
286         CRYPTO_THREAD_unlock(ctx->oncelock);
287         return ret;
288     }
289
290     ret = run_once_fn(ctx);
291     ctx->run_once_done[idx] = 1;
292     ctx->run_once_ret[idx] = ret;
293     CRYPTO_THREAD_unlock(ctx->oncelock);
294
295     return ret;
296 }
297
298 int openssl_ctx_onfree(OPENSSL_CTX *ctx, openssl_ctx_onfree_fn onfreefn)
299 {
300     struct openssl_ctx_onfree_list_st *newonfree
301         = OPENSSL_malloc(sizeof(*newonfree));
302
303     if (newonfree == NULL)
304         return 0;
305
306     newonfree->fn = onfreefn;
307     newonfree->next = ctx->onfreelist;
308     ctx->onfreelist = newonfree;
309
310     return 1;
311 }