* reference and the caller is responsible for freeing that when they
* are finished with it (with a call to ENGINE_finish() *NOT* just
* ENGINE_free()!!!!!!). */
+#ifndef OPENSSL_NO_RSA
static ENGINE *engine_def_rsa = NULL;
+#endif
+#ifndef OPENSSL_NO_DSA
static ENGINE *engine_def_dsa = NULL;
+#endif
+#ifndef OPENSSL_NO_DH
static ENGINE *engine_def_dh = NULL;
+#endif
static ENGINE *engine_def_rand = NULL;
static ENGINE *engine_def_bn_mod_exp = NULL;
static ENGINE *engine_def_bn_mod_exp_crt = NULL;
*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
goto skip_set_defaults;
/* OK, we got a functional reference, so we get one each
* for the defaults too. */
+#ifndef OPENSSL_NO_RSA
engine_def_check_util(&engine_def_rsa, e);
+#endif
+#ifndef OPENSSL_NO_RSA
engine_def_check_util(&engine_def_dsa, e);
+#endif
+#ifndef OPENSSL_NO_DH
engine_def_check_util(&engine_def_dh, e);
+#endif
engine_def_check_util(&engine_def_rand, e);
engine_def_check_util(&engine_def_bn_mod_exp, e);
engine_def_check_util(&engine_def_bn_mod_exp_crt, 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;
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;
}
CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
switch(t)
{
+#ifndef OPENSSL_NO_RSA
case ENGINE_TYPE_RSA:
ret = engine_def_rsa; break;
+#endif
+#ifndef OPENSSL_NO_DSA
case ENGINE_TYPE_DSA:
ret = engine_def_dsa; break;
+#endif
+#ifndef OPENSSL_NO_DH
case ENGINE_TYPE_DH:
ret = engine_def_dh; break;
+#endif
case ENGINE_TYPE_RAND:
ret = engine_def_rand; break;
case ENGINE_TYPE_BN_MOD_EXP:
ret = engine_def_bn_mod_exp; break;
case ENGINE_TYPE_BN_MOD_EXP_CRT:
ret = engine_def_bn_mod_exp_crt; 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
{
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;
}
+#ifndef OPENSSL_NO_RSA
ENGINE *ENGINE_get_default_RSA(void)
{
return engine_get_default_type(ENGINE_TYPE_RSA);
}
+#endif
+#ifndef OPENSSL_NO_DSA
ENGINE *ENGINE_get_default_DSA(void)
{
return engine_get_default_type(ENGINE_TYPE_DSA);
}
+#endif
+#ifndef OPENSSL_NO_DH
ENGINE *ENGINE_get_default_DH(void)
{
return engine_get_default_type(ENGINE_TYPE_DH);
}
+#endif
ENGINE *ENGINE_get_default_RAND(void)
{
{
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. */
/* 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);
CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
switch(t)
{
+#ifndef OPENSSL_NO_RSA
case ENGINE_TYPE_RSA:
old = engine_def_rsa;
engine_def_rsa = e; break;
+#endif
+#ifndef OPENSSL_NO_DSA
case ENGINE_TYPE_DSA:
old = engine_def_dsa;
engine_def_dsa = e; break;
+#endif
+#ifndef OPENSSL_NO_DH
case ENGINE_TYPE_DH:
old = engine_def_dh;
engine_def_dh = e; break;
+#endif
case ENGINE_TYPE_RAND:
old = engine_def_rand;
engine_def_rand = e; break;
case ENGINE_TYPE_BN_MOD_EXP_CRT:
old = engine_def_bn_mod_exp_crt;
engine_def_bn_mod_exp_crt = e; break;
+ default:
+ break;
}
CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
/* If we've replaced a previous value, then we need to remove the
return 1;
}
+#ifndef OPENSSL_NO_RSA
int ENGINE_set_default_RSA(ENGINE *e)
{
return engine_set_default_type(ENGINE_TYPE_RSA, e);
}
+#endif
+#ifndef OPENSSL_NO_DSA
int ENGINE_set_default_DSA(ENGINE *e)
{
return engine_set_default_type(ENGINE_TYPE_DSA, e);
}
+#endif
+#ifndef OPENSSL_NO_DH
int ENGINE_set_default_DH(ENGINE *e)
{
return engine_set_default_type(ENGINE_TYPE_DH, e);
}
+#endif
int ENGINE_set_default_RAND(ENGINE *e)
{
int ENGINE_set_default(ENGINE *e, unsigned int flags)
{
+#ifndef OPENSSL_NO_RSA
if((flags & ENGINE_METHOD_RSA) && e->rsa_meth &&
!ENGINE_set_default_RSA(e))
return 0;
+#endif
+#ifndef OPENSSL_NO_DSA
if((flags & ENGINE_METHOD_DSA) && e->dsa_meth &&
!ENGINE_set_default_DSA(e))
return 0;
+#endif
+#ifndef OPENSSL_NO_DH
if((flags & ENGINE_METHOD_DH) && e->dh_meth &&
!ENGINE_set_default_DH(e))
return 0;
+#endif
if((flags & ENGINE_METHOD_RAND) && e->rand_meth &&
!ENGINE_set_default_RAND(e))
return 0;
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;
+ }
+