1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* We need to use some engine deprecated APIs */ 11e1051a39Sopenharmony_ci#define OPENSSL_SUPPRESS_DEPRECATED 12e1051a39Sopenharmony_ci 13e1051a39Sopenharmony_ci#include "e_os.h" 14e1051a39Sopenharmony_ci#include "eng_local.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci/* 17e1051a39Sopenharmony_ci * Initialise a engine type for use (or up its functional reference count if 18e1051a39Sopenharmony_ci * it's already in use). This version is only used internally. 19e1051a39Sopenharmony_ci */ 20e1051a39Sopenharmony_ciint engine_unlocked_init(ENGINE *e) 21e1051a39Sopenharmony_ci{ 22e1051a39Sopenharmony_ci int to_return = 1; 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci if ((e->funct_ref == 0) && e->init) 25e1051a39Sopenharmony_ci /* 26e1051a39Sopenharmony_ci * This is the first functional reference and the engine requires 27e1051a39Sopenharmony_ci * initialisation so we do it now. 28e1051a39Sopenharmony_ci */ 29e1051a39Sopenharmony_ci to_return = e->init(e); 30e1051a39Sopenharmony_ci if (to_return) { 31e1051a39Sopenharmony_ci /* 32e1051a39Sopenharmony_ci * OK, we return a functional reference which is also a structural 33e1051a39Sopenharmony_ci * reference. 34e1051a39Sopenharmony_ci */ 35e1051a39Sopenharmony_ci e->struct_ref++; 36e1051a39Sopenharmony_ci e->funct_ref++; 37e1051a39Sopenharmony_ci ENGINE_REF_PRINT(e, 0, 1); 38e1051a39Sopenharmony_ci ENGINE_REF_PRINT(e, 1, 1); 39e1051a39Sopenharmony_ci } 40e1051a39Sopenharmony_ci return to_return; 41e1051a39Sopenharmony_ci} 42e1051a39Sopenharmony_ci 43e1051a39Sopenharmony_ci/* 44e1051a39Sopenharmony_ci * Free a functional reference to a engine type. This version is only used 45e1051a39Sopenharmony_ci * internally. 46e1051a39Sopenharmony_ci */ 47e1051a39Sopenharmony_ciint engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) 48e1051a39Sopenharmony_ci{ 49e1051a39Sopenharmony_ci int to_return = 1; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci /* 52e1051a39Sopenharmony_ci * Reduce the functional reference count here so if it's the terminating 53e1051a39Sopenharmony_ci * case, we can release the lock safely and call the finish() handler 54e1051a39Sopenharmony_ci * without risk of a race. We get a race if we leave the count until 55e1051a39Sopenharmony_ci * after and something else is calling "finish" at the same time - 56e1051a39Sopenharmony_ci * there's a chance that both threads will together take the count from 2 57e1051a39Sopenharmony_ci * to 0 without either calling finish(). 58e1051a39Sopenharmony_ci */ 59e1051a39Sopenharmony_ci e->funct_ref--; 60e1051a39Sopenharmony_ci ENGINE_REF_PRINT(e, 1, -1); 61e1051a39Sopenharmony_ci if ((e->funct_ref == 0) && e->finish) { 62e1051a39Sopenharmony_ci if (unlock_for_handlers) 63e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(global_engine_lock); 64e1051a39Sopenharmony_ci to_return = e->finish(e); 65e1051a39Sopenharmony_ci if (unlock_for_handlers) 66e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(global_engine_lock)) 67e1051a39Sopenharmony_ci return 0; 68e1051a39Sopenharmony_ci if (!to_return) 69e1051a39Sopenharmony_ci return 0; 70e1051a39Sopenharmony_ci } 71e1051a39Sopenharmony_ci REF_ASSERT_ISNT(e->funct_ref < 0); 72e1051a39Sopenharmony_ci /* Release the structural reference too */ 73e1051a39Sopenharmony_ci if (!engine_free_util(e, 0)) { 74e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FINISH_FAILED); 75e1051a39Sopenharmony_ci return 0; 76e1051a39Sopenharmony_ci } 77e1051a39Sopenharmony_ci return to_return; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci/* The API (locked) version of "init" */ 81e1051a39Sopenharmony_ciint ENGINE_init(ENGINE *e) 82e1051a39Sopenharmony_ci{ 83e1051a39Sopenharmony_ci int ret; 84e1051a39Sopenharmony_ci if (e == NULL) { 85e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER); 86e1051a39Sopenharmony_ci return 0; 87e1051a39Sopenharmony_ci } 88e1051a39Sopenharmony_ci if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) { 89e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE); 90e1051a39Sopenharmony_ci return 0; 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(global_engine_lock)) 93e1051a39Sopenharmony_ci return 0; 94e1051a39Sopenharmony_ci ret = engine_unlocked_init(e); 95e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(global_engine_lock); 96e1051a39Sopenharmony_ci return ret; 97e1051a39Sopenharmony_ci} 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci/* The API (locked) version of "finish" */ 100e1051a39Sopenharmony_ciint ENGINE_finish(ENGINE *e) 101e1051a39Sopenharmony_ci{ 102e1051a39Sopenharmony_ci int to_return = 1; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci if (e == NULL) 105e1051a39Sopenharmony_ci return 1; 106e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_write_lock(global_engine_lock)) 107e1051a39Sopenharmony_ci return 0; 108e1051a39Sopenharmony_ci to_return = engine_unlocked_finish(e, 1); 109e1051a39Sopenharmony_ci CRYPTO_THREAD_unlock(global_engine_lock); 110e1051a39Sopenharmony_ci if (!to_return) { 111e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FINISH_FAILED); 112e1051a39Sopenharmony_ci return 0; 113e1051a39Sopenharmony_ci } 114e1051a39Sopenharmony_ci return to_return; 115e1051a39Sopenharmony_ci} 116