diff options
Diffstat (limited to 'crypto/engine/engine_lib.c')
-rw-r--r-- | crypto/engine/engine_lib.c | 103 |
1 files changed, 63 insertions, 40 deletions
diff --git a/crypto/engine/engine_lib.c b/crypto/engine/engine_lib.c index 5925a0bc65..90eb5cd6d5 100644 --- a/crypto/engine/engine_lib.c +++ b/crypto/engine/engine_lib.c @@ -103,6 +103,8 @@ static void engine_def_check_util(ENGINE **def, ENGINE *val) *def = val; val->struct_ref++; val->funct_ref++; + engine_ref_debug(val, 0, 1) + engine_ref_debug(val, 1, 1) } /* In a slight break with convention - this static function must be @@ -176,6 +178,8 @@ int ENGINE_init(ENGINE *e) * structural reference. */ e->struct_ref++; e->funct_ref++; + engine_ref_debug(e, 0, 1) + engine_ref_debug(e, 1, 1) } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); return to_return; @@ -192,43 +196,38 @@ int ENGINE_finish(ENGINE *e) return 0; } CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); - if((e->funct_ref == 1) && e->finish) -#if 0 - /* This is the last functional reference and the engine - * requires cleanup so we do it now. */ - to_return = e->finish(); - if(to_return) - { - /* Cleanup the functional reference which is also a - * structural reference. */ - e->struct_ref--; - e->funct_ref--; - } - CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); -#else - /* I'm going to deliberately do a convoluted version of this - * piece of code because we don't want "finish" functions - * being called inside a locked block of code, if at all - * possible. I'd rather have this call take an extra couple - * of ticks than have throughput serialised on a externally- - * provided callback function that may conceivably never come - * back. :-( */ + /* Reduce the functional reference count here so if it's the terminating + * case, we can release the lock safely and call the finish() handler + * without risk of a race. We get a race if we leave the count until + * after and something else is calling "finish" at the same time - + * there's a chance that both threads will together take the count from + * 2 to 0 without either calling finish(). */ + e->funct_ref--; + engine_ref_debug(e, 1, -1) + if((e->funct_ref == 0) && e->finish) { CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); - /* CODE ALERT: This *IS* supposed to be "=" and NOT "==" :-) */ - if((to_return = e->finish(e))) + if(!(to_return = e->finish(e))) { - CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); - /* Cleanup the functional reference which is also a - * structural reference. */ - e->struct_ref--; - e->funct_ref--; - CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); + ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED); + return 0; } } else CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); +#ifdef REF_CHECK + if(e->funct_ref < 0) + { + fprintf(stderr,"ENGINE_finish, bad functional reference count\n"); + abort(); + } #endif + /* Release the structural reference too */ + if(!ENGINE_free(e)) + { + ENGINEerr(ENGINE_F_ENGINE_FINISH,ENGINE_R_FINISH_FAILED); + return 0; + } return to_return; } @@ -620,8 +619,8 @@ static ENGINE *engine_get_default_type(ENGINE_TYPE t) ret = engine_def_bn_mod_exp; break; case ENGINE_TYPE_BN_MOD_EXP_CRT: ret = engine_def_bn_mod_exp_crt; break; - default: - break; + default: + break; } /* Unforunately we can't do this work outside the lock with a * call to ENGINE_init() because that would leave a race @@ -630,6 +629,8 @@ static ENGINE *engine_get_default_type(ENGINE_TYPE t) { ret->struct_ref++; ret->funct_ref++; + engine_ref_debug(ret, 0, 1) + engine_ref_debug(ret, 1, 1) } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); return ret; @@ -675,12 +676,6 @@ static int engine_set_default_type(ENGINE_TYPE t, ENGINE *e) { ENGINE *old = NULL; - if(e == NULL) - { - ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_TYPE, - ERR_R_PASSED_NULL_PARAMETER); - return 0; - } /* engine_def_check is lean and mean and won't replace any * prior default engines ... so we must ensure that it is always * the first function to get to touch the default values. */ @@ -688,7 +683,7 @@ static int engine_set_default_type(ENGINE_TYPE t, ENGINE *e) /* Attempt to get a functional reference (we need one anyway, but * also, 'e' may be just a structural reference being passed in so * this call may actually be the first). */ - if(!ENGINE_init(e)) + if(e && !ENGINE_init(e)) { ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_TYPE, ENGINE_R_INIT_FAILED); @@ -721,8 +716,8 @@ static int engine_set_default_type(ENGINE_TYPE t, ENGINE *e) case ENGINE_TYPE_BN_MOD_EXP_CRT: old = engine_def_bn_mod_exp_crt; engine_def_bn_mod_exp_crt = e; break; - default: - break; + default: + break; } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); /* If we've replaced a previous value, then we need to remove the @@ -801,3 +796,31 @@ int ENGINE_set_default(ENGINE *e, unsigned int flags) return 1; } +int ENGINE_clear_defaults(void) + { + /* If the defaults haven't even been set yet, don't bother. Any kind of + * "cleanup" has a kind of implicit race-condition if another thread is + * trying to keep going, so we don't address that with locking. The + * first ENGINE_set_default_*** call will actually *create* a standard + * set of default ENGINEs (including init() and functional reference + * counts aplenty) before the rest of this function undoes them all. So + * save some hassle ... */ + if(!engine_def_flag) + return 1; + if((0 == 1) || +#ifndef OPENSSL_NO_RSA + !ENGINE_set_default_RSA(NULL) || +#endif +#ifndef OPENSSL_NO_DSA + !ENGINE_set_default_DSA(NULL) || +#endif +#ifndef OPENSSL_NO_DH + !ENGINE_set_default_DH(NULL) || +#endif + !ENGINE_set_default_RAND(NULL) || + !ENGINE_set_default_BN_mod_exp(NULL) || + !ENGINE_set_default_BN_mod_exp_crt(NULL)) + return 0; + return 1; + } + |