[331] | 1 | /*
|
---|
| 2 | * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (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 "eng_int.h"
|
---|
| 11 |
|
---|
| 12 | /*
|
---|
| 13 | * Initialise a engine type for use (or up its functional reference count if
|
---|
| 14 | * it's already in use). This version is only used internally.
|
---|
| 15 | */
|
---|
| 16 | int engine_unlocked_init(ENGINE *e)
|
---|
| 17 | {
|
---|
| 18 | int to_return = 1;
|
---|
| 19 |
|
---|
| 20 | if ((e->funct_ref == 0) && e->init)
|
---|
| 21 | /*
|
---|
| 22 | * This is the first functional reference and the engine requires
|
---|
| 23 | * initialisation so we do it now.
|
---|
| 24 | */
|
---|
| 25 | to_return = e->init(e);
|
---|
| 26 | if (to_return) {
|
---|
| 27 | /*
|
---|
| 28 | * OK, we return a functional reference which is also a structural
|
---|
| 29 | * reference.
|
---|
| 30 | */
|
---|
| 31 | e->struct_ref++;
|
---|
| 32 | e->funct_ref++;
|
---|
| 33 | engine_ref_debug(e, 0, 1);
|
---|
| 34 | engine_ref_debug(e, 1, 1);
|
---|
| 35 | }
|
---|
| 36 | return to_return;
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | /*
|
---|
| 40 | * Free a functional reference to a engine type. This version is only used
|
---|
| 41 | * internally.
|
---|
| 42 | */
|
---|
| 43 | int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers)
|
---|
| 44 | {
|
---|
| 45 | int to_return = 1;
|
---|
| 46 |
|
---|
| 47 | /*
|
---|
| 48 | * Reduce the functional reference count here so if it's the terminating
|
---|
| 49 | * case, we can release the lock safely and call the finish() handler
|
---|
| 50 | * without risk of a race. We get a race if we leave the count until
|
---|
| 51 | * after and something else is calling "finish" at the same time -
|
---|
| 52 | * there's a chance that both threads will together take the count from 2
|
---|
| 53 | * to 0 without either calling finish().
|
---|
| 54 | */
|
---|
| 55 | e->funct_ref--;
|
---|
| 56 | engine_ref_debug(e, 1, -1);
|
---|
| 57 | if ((e->funct_ref == 0) && e->finish) {
|
---|
| 58 | if (unlock_for_handlers)
|
---|
| 59 | CRYPTO_THREAD_unlock(global_engine_lock);
|
---|
| 60 | to_return = e->finish(e);
|
---|
| 61 | if (unlock_for_handlers)
|
---|
| 62 | CRYPTO_THREAD_write_lock(global_engine_lock);
|
---|
| 63 | if (!to_return)
|
---|
| 64 | return 0;
|
---|
| 65 | }
|
---|
| 66 | REF_ASSERT_ISNT(e->funct_ref < 0);
|
---|
| 67 | /* Release the structural reference too */
|
---|
| 68 | if (!engine_free_util(e, 0)) {
|
---|
| 69 | ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH, ENGINE_R_FINISH_FAILED);
|
---|
| 70 | return 0;
|
---|
| 71 | }
|
---|
| 72 | return to_return;
|
---|
| 73 | }
|
---|
| 74 |
|
---|
| 75 | /* The API (locked) version of "init" */
|
---|
| 76 | int ENGINE_init(ENGINE *e)
|
---|
| 77 | {
|
---|
| 78 | int ret;
|
---|
| 79 | if (e == NULL) {
|
---|
| 80 | ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_PASSED_NULL_PARAMETER);
|
---|
| 81 | return 0;
|
---|
| 82 | }
|
---|
| 83 | if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
|
---|
| 84 | ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_MALLOC_FAILURE);
|
---|
| 85 | return 0;
|
---|
| 86 | }
|
---|
| 87 | CRYPTO_THREAD_write_lock(global_engine_lock);
|
---|
| 88 | ret = engine_unlocked_init(e);
|
---|
| 89 | CRYPTO_THREAD_unlock(global_engine_lock);
|
---|
| 90 | return ret;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | /* The API (locked) version of "finish" */
|
---|
| 94 | int ENGINE_finish(ENGINE *e)
|
---|
| 95 | {
|
---|
| 96 | int to_return = 1;
|
---|
| 97 |
|
---|
| 98 | if (e == NULL)
|
---|
| 99 | return 1;
|
---|
| 100 | CRYPTO_THREAD_write_lock(global_engine_lock);
|
---|
| 101 | to_return = engine_unlocked_finish(e, 1);
|
---|
| 102 | CRYPTO_THREAD_unlock(global_engine_lock);
|
---|
| 103 | if (!to_return) {
|
---|
| 104 | ENGINEerr(ENGINE_F_ENGINE_FINISH, ENGINE_R_FINISH_FAILED);
|
---|
| 105 | return 0;
|
---|
| 106 | }
|
---|
| 107 | return to_return;
|
---|
| 108 | }
|
---|