[openssl-dev] How to do reneg with client certs in 1.1.0 API

Rainer Jung rainer.jung at kippdata.de
Sun Feb 14 16:24:13 UTC 2016


Am 08.02.2016 um 15:26 schrieb Matt Caswell:
> On 08/02/16 13:45, Tomas Mraz wrote:
>> On Po, 2016-02-08 at 12:34 +0000, Matt Caswell wrote:
>>>
>>> On 08/02/16 12:11, Rainer Jung wrote:
>>>>
>>> Renegotiation isn't entirely within the control of the server. A
>>> server
>>> can request that a renegotiation takes place. It is up to the client
>>> whether it honours that request immediately; or perhaps its finishes
>>> off
>>> sending some application data before it gets around to honouring it;
>>> or
>>> perhaps it doesn't honour it at all.
>>>
>>>>    SSL_renegotiate(ssl);
>>>>    SSL_do_handshake(ssl);
>>>
>>> This sequence makes the server send the HelloVerifyRequest. It is
>>> then
>>> back in a state where it can continue to receive application data
>>> from
>>> the client. At some later point the client may or may not initiate a
>>> reneg.
>>>
>>>>    SSL_set_state(ssl, SSL_ST_ACCEPT);
>>>>    SSL_do_handshake(ssl);
>>>
>>> This is really not a good idea, and I suspect is a hack that was
>>> originally copied from s_server :-). Doing this will make the
>>> connection
>>> fail if the client sends application data next (which it is allowed
>>> to do).
>>>
>>> We don't know what we're going to get next from the client it could
>>> be
>>> more application data. It could be an immediate start of a new
>>> handshake. The correct thing for the server to do is to attempt to
>>> read
>>> application data. If we happen to get a handshake instead then it
>>> will
>>> be automatically handled.
>>
>> What if the server wants to discard all the application data that was
>> sent before the renegotiation completed? Or how the server can
>> recognize which part of data was received before renegotiation
>> completed and which after it?
>>
>
> You never get app data from two different epochs returned in a single
> API call. In certain situations you can get a handshake finish occur
> followed by a read of application data all within a single API call.
> It's also valid that the attempt to read application data handled the
> handshake but doesn't actually return any app data because the client
> didn't send any yet (it *just* did the reneg).
>
> So if you want to discard all application data until the client has
> initiated a reneg and supplied a certificate then you'll want to do
> something like:
>
> SSL_renegotiate(ssl);
> SSL_do_handshake(ssl);
> do {
>      read_some_app_data();
>      if(no_client_cert_yet()) {
>          discard_app_data();
>      }
> } while(no_client_cert_yet());

After doing some experiments I ended up calling SSL_peek() with a length 
of 0 bytes. That seems to reliably trigger the renegotiation handshake. 
Using this approach was easier, since we (Apache) have to handle various 
reneg scenarios:

- waiting for client certs
- doing a reneg because cipher requirements changed but no client certs 
involved
- sometimes no application data is expected after the renegotiation

I hope that effect of SSL_peek(ssl, buf, 0) is not just an 
implementation artefact and we can actually rely on it.

Regards,

Rainer



More information about the openssl-dev mailing list