| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2021-01-28 20:54:57 +08:00
										 |  |  |  * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License 2.0 (the "License").  You may not use | 
					
						
							|  |  |  |  * this file except in compliance with the License.  You can obtain a copy | 
					
						
							|  |  |  |  * in the file LICENSE in the source distribution or at | 
					
						
							|  |  |  |  * https://www.openssl.org/source/license.html
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <openssl/crypto.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-21 07:21:19 +08:00
										 |  |  | #include <openssl/core_dispatch.h>
 | 
					
						
							| 
									
										
										
										
											2019-09-28 06:45:33 +08:00
										 |  |  | #include "crypto/cryptlib.h"
 | 
					
						
							| 
									
										
										
										
											2019-10-04 21:25:59 +08:00
										 |  |  | #include "prov/providercommon.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | #include "internal/thread_once.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifdef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2020-12-10 22:44:25 +08:00
										 |  |  | #include "prov/provider_ctx.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Thread aware code may want to be told about thread stop events. We register | 
					
						
							|  |  |  |  * to hear about those thread stop events when we see a new thread has started. | 
					
						
							|  |  |  |  * We call the ossl_init_thread_start function to do that. In the FIPS provider | 
					
						
							|  |  |  |  * we have our own copy of ossl_init_thread_start, which cascades notifications | 
					
						
							|  |  |  |  * about threads stopping from libcrypto to all the code in the FIPS provider | 
					
						
							|  |  |  |  * that needs to know about it. | 
					
						
							| 
									
										
										
										
											2019-07-16 18:35:42 +08:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |  * The FIPS provider tells libcrypto about which threads it is interested in | 
					
						
							|  |  |  |  * by calling "c_thread_start" which is a function pointer created during | 
					
						
							|  |  |  |  * provider initialisation (i.e. OSSL_init_provider). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-06-21 07:19:16 +08:00
										 |  |  | extern OSSL_FUNC_core_thread_start_fn *c_thread_start; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct thread_event_handler_st THREAD_EVENT_HANDLER; | 
					
						
							|  |  |  | struct thread_event_handler_st { | 
					
						
							| 
									
										
										
										
											2021-05-18 15:54:43 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     const void *index; | 
					
						
							| 
									
										
										
										
											2021-05-18 15:54:43 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     void *arg; | 
					
						
							|  |  |  |     OSSL_thread_stop_handler_fn handfn; | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     THREAD_EVENT_HANDLER *next; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | DEFINE_SPECIAL_STACK_OF(THREAD_EVENT_HANDLER_PTR, THREAD_EVENT_HANDLER *) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct global_tevent_register_st GLOBAL_TEVENT_REGISTER; | 
					
						
							|  |  |  | struct global_tevent_register_st { | 
					
						
							|  |  |  |     STACK_OF(THREAD_EVENT_HANDLER_PTR) *skhands; | 
					
						
							|  |  |  |     CRYPTO_RWLOCK *lock; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GLOBAL_TEVENT_REGISTER *glob_tevent_reg = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static CRYPTO_ONCE tevent_register_runonce = CRYPTO_ONCE_STATIC_INIT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFINE_RUN_ONCE_STATIC(create_global_tevent_register) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glob_tevent_reg = OPENSSL_zalloc(sizeof(*glob_tevent_reg)); | 
					
						
							|  |  |  |     if (glob_tevent_reg == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glob_tevent_reg->skhands = sk_THREAD_EVENT_HANDLER_PTR_new_null(); | 
					
						
							|  |  |  |     glob_tevent_reg->lock = CRYPTO_THREAD_lock_new(); | 
					
						
							|  |  |  |     if (glob_tevent_reg->skhands == NULL || glob_tevent_reg->lock == NULL) { | 
					
						
							|  |  |  |         sk_THREAD_EVENT_HANDLER_PTR_free(glob_tevent_reg->skhands); | 
					
						
							|  |  |  |         CRYPTO_THREAD_lock_free(glob_tevent_reg->lock); | 
					
						
							|  |  |  |         OPENSSL_free(glob_tevent_reg); | 
					
						
							|  |  |  |         glob_tevent_reg = NULL; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GLOBAL_TEVENT_REGISTER *get_global_tevent_register(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!RUN_ONCE(&tevent_register_runonce, create_global_tevent_register)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return glob_tevent_reg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  | static int  init_thread_push_handlers(THREAD_EVENT_HANDLER **hands); | 
					
						
							|  |  |  | static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin); | 
					
						
							|  |  |  | static void init_thread_destructor(void *hands); | 
					
						
							|  |  |  | static int  init_thread_deregister(void *arg, int all); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands); | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | static THREAD_EVENT_HANDLER ** | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | init_get_thread_local(CRYPTO_THREAD_LOCAL *local, int alloc, int keep) | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     THREAD_EVENT_HANDLER **hands = CRYPTO_THREAD_get_local(local); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (alloc) { | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |         if (hands == NULL) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  |             if ((hands = OPENSSL_zalloc(sizeof(*hands))) == NULL) | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |                 return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  |             if (!CRYPTO_THREAD_set_local(local, hands)) { | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |                 OPENSSL_free(hands); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  |             if (!init_thread_push_handlers(hands)) { | 
					
						
							|  |  |  |                 CRYPTO_THREAD_set_local(local, NULL); | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |                 OPENSSL_free(hands); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } else if (!keep) { | 
					
						
							|  |  |  |         CRYPTO_THREAD_set_local(local, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return hands; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Since per-thread-specific-data destructors are not universally | 
					
						
							|  |  |  |  * available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key | 
					
						
							|  |  |  |  * is assumed to have destructor associated. And then an effort is made | 
					
						
							|  |  |  |  * to call this single destructor on non-pthread platform[s]. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Initial value is "impossible". It is used as guard value to shortcut | 
					
						
							|  |  |  |  * destructor for threads terminating before libcrypto is initialized or | 
					
						
							|  |  |  |  * after it's de-initialized. Access to the key doesn't have to be | 
					
						
							|  |  |  |  * serialized for the said threads, because they didn't use libcrypto | 
					
						
							| 
									
										
										
										
											2019-07-02 16:04:04 +08:00
										 |  |  |  * and it doesn't matter if they pick "impossible" or dereference real | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |  * key value and pull NULL past initialization in the first thread that | 
					
						
							|  |  |  |  * intends to use libcrypto. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static union { | 
					
						
							|  |  |  |     long sane; | 
					
						
							|  |  |  |     CRYPTO_THREAD_LOCAL value; | 
					
						
							|  |  |  | } destructor_key = { -1 }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * The thread event handler list is a thread specific linked list | 
					
						
							|  |  |  |  * of callback functions which are invoked in list order by the | 
					
						
							|  |  |  |  * current thread in case of certain events. (Currently, there is | 
					
						
							|  |  |  |  * only one type of event, the 'thread stop' event.) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * We also keep a global reference to that linked list, so that we | 
					
						
							|  |  |  |  * can deregister handlers if necessary before all the threads are | 
					
						
							|  |  |  |  * stopped. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int init_thread_push_handlers(THREAD_EVENT_HANDLER **hands) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     GLOBAL_TEVENT_REGISTER *gtr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtr = get_global_tevent_register(); | 
					
						
							|  |  |  |     if (gtr == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-19 04:31:56 +08:00
										 |  |  |     if (!CRYPTO_THREAD_write_lock(gtr->lock)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2019-07-18 01:14:01 +08:00
										 |  |  |     ret = (sk_THREAD_EVENT_HANDLER_PTR_push(gtr->skhands, hands) != 0); | 
					
						
							|  |  |  |     CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | static void init_thread_remove_handlers(THREAD_EVENT_HANDLER **handsin) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GLOBAL_TEVENT_REGISTER *gtr; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtr = get_global_tevent_register(); | 
					
						
							|  |  |  |     if (gtr == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2021-02-19 04:31:56 +08:00
										 |  |  |     if (!CRYPTO_THREAD_write_lock(gtr->lock)) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) { | 
					
						
							|  |  |  |         THREAD_EVENT_HANDLER **hands | 
					
						
							|  |  |  |             = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (hands == handsin) { | 
					
						
							| 
									
										
										
										
											2020-12-01 08:58:32 +08:00
										 |  |  |             sk_THREAD_EVENT_HANDLER_PTR_delete(gtr->skhands, i); | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |             CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | static void init_thread_destructor(void *hands) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |     init_thread_stop(NULL, (THREAD_EVENT_HANDLER **)hands); | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     init_thread_remove_handlers(hands); | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     OPENSSL_free(hands); | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | int ossl_init_thread(void) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!CRYPTO_THREAD_init_local(&destructor_key.value, | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |                                   init_thread_destructor)) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | void ossl_cleanup_thread(void) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     init_thread_deregister(NULL, 1); | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     CRYPTO_THREAD_cleanup_local(&destructor_key.value); | 
					
						
							|  |  |  |     destructor_key.sane = -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  | void OPENSSL_thread_stop_ex(OSSL_LIB_CTX *ctx) | 
					
						
							| 
									
										
										
										
											2019-05-28 23:21:19 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |     ctx = ossl_lib_ctx_get_concrete(ctx); | 
					
						
							| 
									
										
										
										
											2019-05-28 23:21:19 +08:00
										 |  |  |     /*
 | 
					
						
							| 
									
										
										
										
											2021-03-12 23:43:40 +08:00
										 |  |  |      * It would be nice if we could figure out a way to do this on all threads | 
					
						
							|  |  |  |      * that have used the OSSL_LIB_CTX when the context is freed. This is | 
					
						
							|  |  |  |      * currently not possible due to the use of thread local variables. | 
					
						
							| 
									
										
										
										
											2019-05-28 23:21:19 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     ossl_ctx_thread_stop(ctx); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | void OPENSSL_thread_stop(void) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     if (destructor_key.sane != -1) { | 
					
						
							|  |  |  |         THREAD_EVENT_HANDLER **hands | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |             = init_get_thread_local(&destructor_key.value, 0, 0); | 
					
						
							|  |  |  |         init_thread_stop(NULL, hands); | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         init_thread_remove_handlers(hands); | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |         OPENSSL_free(hands); | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 18:52:56 +08:00
										 |  |  | void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     if (destructor_key.sane != -1) { | 
					
						
							|  |  |  |         THREAD_EVENT_HANDLER **hands | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |             = init_get_thread_local(&destructor_key.value, 0, 1); | 
					
						
							| 
									
										
										
										
											2021-05-20 18:52:56 +08:00
										 |  |  |         init_thread_stop(ctx, hands); | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  | static void *thread_event_ossl_ctx_new(OSSL_LIB_CTX *libctx) | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     THREAD_EVENT_HANDLER **hands = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     CRYPTO_THREAD_LOCAL *tlocal = OPENSSL_zalloc(sizeof(*tlocal)); | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (tlocal == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     if (!CRYPTO_THREAD_init_local(tlocal,  NULL)) { | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |     hands = OPENSSL_zalloc(sizeof(*hands)); | 
					
						
							|  |  |  |     if (hands == NULL) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!CRYPTO_THREAD_set_local(tlocal, hands)) | 
					
						
							|  |  |  |         goto err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return tlocal; | 
					
						
							|  |  |  |  err: | 
					
						
							|  |  |  |     OPENSSL_free(hands); | 
					
						
							|  |  |  |     OPENSSL_free(tlocal); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | static void thread_event_ossl_ctx_free(void *tlocal) | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     OPENSSL_free(tlocal); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  | static const OSSL_LIB_CTX_METHOD thread_event_ossl_ctx_method = { | 
					
						
							| 
									
										
										
										
											2021-04-26 18:35:17 +08:00
										 |  |  |     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY, | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |     thread_event_ossl_ctx_new, | 
					
						
							|  |  |  |     thread_event_ossl_ctx_free, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-20 18:52:56 +08:00
										 |  |  | static void ossl_arg_thread_stop(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ossl_ctx_thread_stop((OSSL_LIB_CTX *)arg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx) | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     THREAD_EVENT_HANDLER **hands; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     CRYPTO_THREAD_LOCAL *local | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |         = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, | 
					
						
							|  |  |  |                                 &thread_event_ossl_ctx_method); | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     if (local == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |     hands = init_get_thread_local(local, 0, 0); | 
					
						
							| 
									
										
										
										
											2020-12-10 22:44:25 +08:00
										 |  |  |     init_thread_stop(ctx, hands); | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     OPENSSL_free(hands); | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #endif /* FIPS_MODULE */
 | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  | static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-16 02:10:03 +08:00
										 |  |  |     THREAD_EVENT_HANDLER *curr, *prev = NULL, *tmp; | 
					
						
							| 
									
										
										
										
											2021-11-05 22:43:01 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							|  |  |  |     GLOBAL_TEVENT_REGISTER *gtr; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Can't do much about this */ | 
					
						
							|  |  |  |     if (hands == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 22:43:01 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							|  |  |  |     gtr = get_global_tevent_register(); | 
					
						
							|  |  |  |     if (gtr == NULL) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!CRYPTO_THREAD_write_lock(gtr->lock)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     curr = *hands; | 
					
						
							|  |  |  |     while (curr != NULL) { | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |         if (arg != NULL && curr->arg != arg) { | 
					
						
							| 
									
										
										
										
											2020-01-16 02:10:03 +08:00
										 |  |  |             prev = curr; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |             curr = curr->next; | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         curr->handfn(curr->arg); | 
					
						
							| 
									
										
										
										
											2020-01-16 02:10:03 +08:00
										 |  |  |         if (prev == NULL) | 
					
						
							|  |  |  |             *hands = curr->next; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             prev->next = curr->next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tmp = curr; | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |         curr = curr->next; | 
					
						
							| 
									
										
										
										
											2020-01-16 02:10:03 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         OPENSSL_free(tmp); | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-05 22:43:01 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							|  |  |  |     CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | int ossl_init_thread_start(const void *index, void *arg, | 
					
						
							|  |  |  |                            OSSL_thread_stop_handler_fn handfn) | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     THREAD_EVENT_HANDLER **hands; | 
					
						
							|  |  |  |     THREAD_EVENT_HANDLER *hand; | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifdef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |     OSSL_LIB_CTX *ctx = arg; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * In FIPS mode the list of THREAD_EVENT_HANDLERs is unique per combination | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |      * of OSSL_LIB_CTX and thread. This is because in FIPS mode each | 
					
						
							|  |  |  |      * OSSL_LIB_CTX gets informed about thread stop events individually. | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     CRYPTO_THREAD_LOCAL *local | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |         = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_THREAD_EVENT_HANDLER_INDEX, | 
					
						
							|  |  |  |                                 &thread_event_ossl_ctx_method); | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |      * Outside of FIPS mode the list of THREAD_EVENT_HANDLERs is unique per | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |      * thread, but may hold multiple OSSL_LIB_CTXs. We only get told about | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |      * thread stop events globally, so we have to ensure all affected | 
					
						
							| 
									
										
										
										
											2020-10-15 17:55:50 +08:00
										 |  |  |      * OSSL_LIB_CTXs are informed. | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     CRYPTO_THREAD_LOCAL *local = &destructor_key.value; | 
					
						
							| 
									
										
										
										
											2019-05-25 01:20:49 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-17 22:16:36 +08:00
										 |  |  |     hands = init_get_thread_local(local, 1, 0); | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     if (hands == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifdef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     if (*hands == NULL) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * We've not yet registered any handlers for this thread. We need to get | 
					
						
							|  |  |  |          * libcrypto to tell us about later thread stop events. c_thread_start | 
					
						
							|  |  |  |          * is a callback to libcrypto defined in fipsprov.c | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2021-05-20 18:52:56 +08:00
										 |  |  |         if (!c_thread_start(FIPS_get_core_handle(ctx), ossl_arg_thread_stop, | 
					
						
							|  |  |  |                             ctx)) | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |             return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     hand = OPENSSL_malloc(sizeof(*hand)); | 
					
						
							|  |  |  |     if (hand == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hand->handfn = handfn; | 
					
						
							| 
									
										
										
										
											2019-05-27 23:31:27 +08:00
										 |  |  |     hand->arg = arg; | 
					
						
							| 
									
										
										
										
											2021-05-18 15:54:43 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     hand->index = index; | 
					
						
							| 
									
										
										
										
											2021-05-18 15:54:43 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-05-25 00:52:17 +08:00
										 |  |  |     hand->next = *hands; | 
					
						
							|  |  |  |     *hands = hand; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 04:34:56 +08:00
										 |  |  | #ifndef FIPS_MODULE
 | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | static int init_thread_deregister(void *index, int all) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GLOBAL_TEVENT_REGISTER *gtr; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gtr = get_global_tevent_register(); | 
					
						
							| 
									
										
										
										
											2019-11-21 11:15:21 +08:00
										 |  |  |     if (gtr == NULL) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2021-02-19 04:31:56 +08:00
										 |  |  |     if (!all) { | 
					
						
							|  |  |  |         if (!CRYPTO_THREAD_write_lock(gtr->lock)) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-10-30 01:32:49 +08:00
										 |  |  |         glob_tevent_reg = NULL; | 
					
						
							| 
									
										
										
										
											2021-02-19 04:31:56 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |     for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) { | 
					
						
							|  |  |  |         THREAD_EVENT_HANDLER **hands | 
					
						
							|  |  |  |             = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i); | 
					
						
							| 
									
										
										
										
											2020-08-24 10:52:56 +08:00
										 |  |  |         THREAD_EVENT_HANDLER *curr = NULL, *prev = NULL, *tmp; | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (hands == NULL) { | 
					
						
							|  |  |  |             if (!all) | 
					
						
							|  |  |  |                 CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-08-24 10:52:56 +08:00
										 |  |  |         curr = *hands; | 
					
						
							| 
									
										
										
										
											2019-06-19 01:37:38 +08:00
										 |  |  |         while (curr != NULL) { | 
					
						
							|  |  |  |             if (all || curr->index == index) { | 
					
						
							|  |  |  |                 if (prev != NULL) | 
					
						
							|  |  |  |                     prev->next = curr->next; | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     *hands = curr->next; | 
					
						
							|  |  |  |                 tmp = curr; | 
					
						
							|  |  |  |                 curr = curr->next; | 
					
						
							|  |  |  |                 OPENSSL_free(tmp); | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             prev = curr; | 
					
						
							|  |  |  |             curr = curr->next; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (all) | 
					
						
							|  |  |  |             OPENSSL_free(hands); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (all) { | 
					
						
							|  |  |  |         CRYPTO_THREAD_lock_free(gtr->lock); | 
					
						
							|  |  |  |         sk_THREAD_EVENT_HANDLER_PTR_free(gtr->skhands); | 
					
						
							|  |  |  |         OPENSSL_free(gtr); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         CRYPTO_THREAD_unlock(gtr->lock); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ossl_init_thread_deregister(void *index) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return init_thread_deregister(index, 0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |