Hi there,
On Tuesday 08 Oct 2002 9:01 am, Frederic DONNAT wrote:
> I'd like to know the better way to be fault tolerant when using a
> cryto accelerator through an engine.
An ENGINE handle (functional reference) is attached to each key
structure (RSA, DSA, etc) upon creation and released on destruction.
The "default" handling in the ENGINE code is used during those
constructors to choose the engine, so changing default ENGINEs at
run-time will only affect any *new* keys created afterwards, existing
keys will continue using the ENGINE they were previously using.
However, if you want to get smoother error-handling done from within
your implementation rather than from a layer further up (eg.
application, SSL/TLS code, etc) read on ... everything I say should be
reasonably accurate for 0.9.7 onwards (eg. the recent betas), but if
you're working with 0.9.6 versions things might be different and you'll
need to know about 0.9.7 soon enough anyway. :-)
> The only problem is when i want to set all the pointers from our
> engine to openssl soft. (i'd like to do it in the proper way) I try:
> ENGINE *soft_openssl = ENGINE_get_first () ;
> ENGINE_set_default ( soft_openssl, ENGINE_METHOD_ALL ) ;
>
> But this doesn't seems to work!
Indeed, you've simply said that "soft_openssl" should be the default
engine for any algorithms it supports, and it will then be used when
*creating* any new key structures/contexts (RSA, DSA, DH, RAND,
EVP_CIPHER_CTX, etc). There's also another problem - once you move to
0.9.7 (if you aren't already using the betas), your code will fail for
another reason - there is no "openssl" ENGINE, software implementations
are invoked when there are *no* ENGINEs registered for the given
algorithms and the corresponding keys have a NULL ENGINE handle. So
ENGINE_get_first() may actually return NULL. Or worse, it could return
some other ENGINE you weren't hoping for (eg. the "dynamic" ENGINE
which implements *no* algorithms causing your ENGINE_set_default() call
to be a NOP, or it could return some vendor hardware ENGINE - perhaps
even your own one, leading to a nasty loop).
> However something more bad codded works fine:
> ENGINE *soft_openssl = ENGINE_get_first () ;
> engine_zencod = *soft_openssl ;
>
> /* engine_zencod is declared as follows
> static ENGINE engine_zencod = {
> "zencod",
> "ZENCOD hardware engine support",
> ...
> } ;
> */
Um, that doesn't make sense - I assume you mean that you use
memcpy(&engine_zencod,soft_openssl,...)? Anyway, it's not a good idea
because it breaks the encapsulation of the ENGINE internals and one
immediate consequence is that you inadvertently copy reference counts
and pointers to data that isn't supposed to be shared between ENGINEs
(eg. "ex_data").
> Is there a better way?
> Should i use the "ctrl" function?
> I'm afraid, that the upper application will not take care of
> resulting error and retry it in soft!
The following will (probably) only be applicable in for 0.9.7-onwards.
As an example, assume you have just had a hardware-related error in an
RSA handler function in your ENGINE implementation, you could force
*that* RSA key to automatically stop using your ENGINE and fallback to
software by calling;
RSA_set_method(rsa, RSA_PKCS1_SSLeay());
this will automatically release the handle to your ENGINE in 'rsa' and
set the RSA implementation for 'rsa' to use software. I hope it goes
without saying that *none* of this will work if your ENGINE is doing
anything more than acceleration (ie. if you have alternative
key-storage, etc). If you have anything stored in the "ex_data" of the
'rsa' key, you should clean it up beforehand (and set the ex_data
values to NULL) before switching to software. Note, that although this
switches the implementation, the current operation will still fail
unless you specifically redirect processing for the current operation,
eg;
return RSA_PKCS1_SSLeay()->rsa_pub_enc(...);
(if you were in your own rsa_pub_enc handler at the time).
This will eventually cause any key structures that *were* using your
ENGINE to end up using software instead. New keys will still be created
with handles to your ENGINE so if you don't want that, you need to
unregister your implementation from the default handling system by;
ENGINE_unregister_RSA(e);
ENGINE_unregister_DSA(e);
... etc, for whichever algos are appropriate.
If you actually want your ENGINE to *temporarily* redirect operations to
software until such time as your hardware is working again, that's an
entirely different kettle of fish. The best way in that circumstance
would be to leave your ENGINE in the loop, and simply store your error
state (eg. are you currently redirecting to software? when will you
next retry hardware? etc) inside ex_data. So in the rsa_pub_enc()
handler, if your error state indicates you are currently redirecting to
software, simply call;
return RSA_PKCS1_SSLeay()->rsa_pub_enc(...);
later on, you can decide to try hardware again.
Hope that helps,
Geoff
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]