[openssl-dev] Adding async support

Matt Caswell matt at openssl.org
Thu Oct 8 10:56:44 UTC 2015



On 08/10/15 11:26, Dmitry Belyavsky wrote:
> Dear Matt, 
> 
> I have some questions.
> 
> On Thu, Oct 8, 2015 at 12:32 AM, Matt Caswell <matt at openssl.org
> <mailto:matt at openssl.org>> wrote:
> 
> 
> 
>     On 07/10/15 21:44, Dmitry Belyavsky wrote:
>     > Dear Matt,
>     >
>     > On Wed, Oct 7, 2015 at 4:43 PM, Matt Caswell <matt at openssl.org <mailto:matt at openssl.org>
>     > <mailto:matt at openssl.org <mailto:matt at openssl.org>>> wrote:
>     >
>     >
>     >
>     >     On 07/10/15 14:29, Viktor Dukhovni wrote:
>     >     >
>     >     > Should applications generally enable async mode because that might
>     >     > be beneficial down the road?  Or is this just for exotic hardware
>     >     > not likely to be seen in most environments?
>     >
>     >     It will only be helpful if you have an engine capable of supporting
>     >     async. I can't really answer the question because I don't know how
>     >     common this will be. My hope is that this will become relatively common.
>     >     I have been toying with the idea of creating a multi-threaded async
>     >     engine where the engine manages a pool of threads to offload async work
>     >     to which would then offer true async support even if you don't have
>     >     specialist hardware.
>     >
>     >
>     > If we have an engine executing long crypto operations, how can we adopt
>     > the engine and software using this engine to process them asynchronously?
> 
>     The engine needs to have a way of offloading the work to "something
>     else" so that it can come back and pick up the results later. Typically
>     for an engine this would mean some external hardware, but as I suggested
>     above it could be done using threads.
> 
>     From an engine perspective the work would be:
>     - Receive a request to do some crypto work in the normal way via the
>     engine API.
>     - Offload the work to "something else"
> 
> 
> So what is a mechanism of such an offload? Can I, for example, get the
> (global) ASYNC_pool and add a job (function/pointer to context) to it?

The offload mechanism is entirely engine specific. We do not know how
any specific engine works or how to interface to the hardware. An engine
will be called in exactly the same way as now. The job of the engine
will be to take the parameters passed to it and initiate the work in the
engine hardware.

So in pseudo code it might look something like this:

static int myengine_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx,
    unsigned char *out, const unsigned char *in, size_t inl)
{
    int jobid;

    jobid = offload_cipher_to_hardware(ctx, out, in , inl);

    /*
     * jobid holds a reference in the engine back to the work we just
     * started
     */

    while(work_not_finished_yet(jobid)) {
        /* Return control back to the calling application */
        ASYNC_pause_job();
    }

    return get_results_from_hardware(jobid);
}

You will note that ASYNC_pause_job() does *not* do a "return" to return
control back to the user application...but calling ASYNC_pause_job()
will cause SSL_read (or whatever) to return with SSL_ERROR_WANT_ASYNC
nonetheless. The async job has its own private stack to enable this.
Recalling SSL_read from the user application will appear to the engine
like the function call ASYNC_pause_job() has returned.


> How will the SSL struct obtain a job id from the engine implementing,
> for example, "long" RSA_METHOD?

It does not need to. The SSL object has a reference to the ASYNC_JOB.
The engine can manage its own job ids - see the pseudo code above.

>  
> 
> 
>     If using libcrypto then:
>     - the application must determine which crypto operations it wants to
>     perform asynchronously. Those operations should be wrapped in an
>     application defined function.
>     - the application initiates the async job by calling ASYNC_start_job and
>     passing in a pointer to the function to be started as a job.
>     - from an engine perspective it will work in exactly the same way as for
>     libssl initiated crypto work.
>     - ASYNC_start_job may return with an ASYNC_PAUSE response. The
>     application can go off and do other work, and then resume the job at a
>     later time by recalling ASYNC_start_job.
> 
> 
> So do I understand correctly that if I want to perform SSL operations
> asynchronously, 
> I'm able to wrap the SSL functions into the application defined
> functions and then behave as described
> herein before? 

If you are doing SSL operations you do not need to wrap them in a
function as described above (although you could do if you wanted to).
libssl will do all of this for you. You only have to define your own
function for the job if you are calling libcrypto directly. For an
application doing SSL it will work very much like non-blocking IO works
today.

Matt



More information about the openssl-dev mailing list