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]

Reply via email to