<div dir="ltr">Dear Matt, <div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 8, 2015 at 1:56 PM, Matt Caswell <span dir="ltr"><<a href="mailto:matt@openssl.org" target="_blank">matt@openssl.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=""><br></span><div><div class="h5">>     The engine needs to have a way of offloading the work to "something<br>
>     else" so that it can come back and pick up the results later. Typically<br>
>     for an engine this would mean some external hardware, but as I suggested<br>
>     above it could be done using threads.<br>
><br>
>     From an engine perspective the work would be:<br>
>     - Receive a request to do some crypto work in the normal way via the<br>
>     engine API.<br>
>     - Offload the work to "something else"<br>
><br>
><br>
> So what is a mechanism of such an offload? Can I, for example, get the<br>
> (global) ASYNC_pool and add a job (function/pointer to context) to it?<br>
<br>
</div></div>The offload mechanism is entirely engine specific. We do not know how<br>
any specific engine works or how to interface to the hardware. An engine<br>
will be called in exactly the same way as now. The job of the engine<br>
will be to take the parameters passed to it and initiate the work in the<br>
engine hardware.<br>
<br>
So in pseudo code it might look something like this:<br>
<br>
static int myengine_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx,<br>
    unsigned char *out, const unsigned char *in, size_t inl)<br>
{<br>
    int jobid;<br>
<br>
    jobid = offload_cipher_to_hardware(ctx, out, in , inl);<br>
<br>
    /*<br>
     * jobid holds a reference in the engine back to the work we just<br>
     * started<br>
     */<br>
<br>
    while(work_not_finished_yet(jobid)) {<br>
        /* Return control back to the calling application */<br>
        ASYNC_pause_job();<br>
    }<br>
<br>
    return get_results_from_hardware(jobid);<br>
}<br>
<br>
You will note that ASYNC_pause_job() does *not* do a "return" to return<br>
control back to the user application...but calling ASYNC_pause_job()<br>
will cause SSL_read (or whatever) to return with SSL_ERROR_WANT_ASYNC<br>
nonetheless. The async job has its own private stack to enable this.<br>
Recalling SSL_read from the user application will appear to the engine<br>
like the function call ASYNC_pause_job() has returned.<br>
<span class=""><br>
<br>
> How will the SSL struct obtain a job id from the engine implementing,<br>
> for example, "long" RSA_METHOD?<br>
<br>
</span>It does not need to. The SSL object has a reference to the ASYNC_JOB.<br>
The engine can manage its own job ids - see the pseudo code above.<br></blockquote><div><br></div><div>I see. So am I correct supposing that pseudo code for offload_cipher_to_hardware looks like this:</div><div><br></div><div>static int async_wrapper(void * args)</div><div>{</div><div>...</div><div>}</div><div><br></div><div>static ASYNC_JOB *offload (void *args)</div><div>{</div><div>  ASYNC_JOB *pjob = NULL;<br>  int funcret;</div><div>  size_t size = 0;</div><div><br></div><div>  int ret = ASYNC_start_job(&pjob, &funcret, async_wrapper, args, </div><div>                      *args, size);</div><div>  if (ret != ASYNC_PAUSE) return NULL;</div><div>  return pjob;</div><div>}</div><div><br></div><div>?</div><div><br></div><div>Thank you!</div><div> <br></div></div>-- <br><div class="gmail_signature">SY, Dmitry Belyavsky</div>
</div></div>