Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
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 +, 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 -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
> On Feb 8, 2016, at 9:49 AM, Matt Caswellwrote: > > Actually, yes that is a good point. There could be some subtle security > issues there. You probably need to additionally check that you are not > halfway through a handshake: > > SSL_renegotiate(ssl); > SSL_do_handshake(ssl); > do { >read_some_app_data(); >if(no_client_cert_yet() || SSL_in_init(ssl)) { >discard_app_data(); >} > } while(no_client_cert_yet() || SSL_in_init(ssl)); Indeed, but discarding the data may not be an option, that could lead to dead-lock, rather one might need to process it, in the proper context (pre-authentication). The proper handling of client data between the renegotiation request and its completion depends on the application protocol. The important thing is that OpenSSL should (does) not delay the visibility of data that was read before renegotiation completes, until after such completion. -- -- Viktor. -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
Am 08.02.2016 um 13:34 schrieb Matt Caswell: On 08/02/16 12:11, Rainer Jung wrote: I'm adding support for OpenSSL 1.1.0 to the Apache web server. I struggle to migrate the renegotiation code in the case wehere we want the client to send a client cert. The current code works like explained in http://www.linuxjournal.com/node/5487/print After using SSL_set_verify() it calls SSL_renegotiate(ssl); SSL_do_handshake(ssl); SSL_set_state(ssl, SSL_ST_ACCEPT); SSL_do_handshake(ssl); for reasons given in the article. The new 1.1.0 API no longer allows to set the state using SSL_set_state(). The old article states, that calling SSL_set_accept_state() is not the right thing to do. Looking at s_server.c doesn't give a hint what to do instead, because it looks like it reads the client certs just raw from the socket. Any hint what would replace the above sequence or at least the SSL_set_state(ssl, SSL_ST_ACCEPT)? Thanks a bunch and regards, 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. OK, tried it and it partially works. More precisely: when the cipher is AES128-SHA it works, bur for ECDHE-RSA-AES128-SHA256 I run into an error in tls_construct_server_key_exchange() (file statem/statem_srvr.c). The following conditions triggers the jump to err: 1773 if (type & (SSL_kECDHE | SSL_kECDHEPSK)) { 1774 int nid; 1775 1776 if (s->s3->tmp.pkey != NULL) { 1777 SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, 1778ERR_R_INTERNAL_ERROR); 1779 goto err; 1780 } By comparing the communication for the two ciphers I see the following flow: write 69/69 bytes SSLv3/TLS write hello request - try to read app data -> I/O error, 5 bytes expected to read read 5/5 bytes read 576/576 Handshake: start before SSL initialization before SSL initialization SSLv3/TLS read client hello write 149/149 SSLv3/TLS write server hello write 2021/2021 SSLv3/TLS write certificate And here for the ECDHE case the error triggered by the above check. In the AES case we proceed write 1173/1173 SSLv3/TLS write certificate request write 69/69 bytes write 3412/3412 bytes SSLv3/TLS write server done error in SSLv3/TLS write server done read 5/5 bytes read 1952/1952 SSLv3/TLS write server done Successful client certificate verification Any idea how to clear s->s3->tmp.pkey so that the check doesn't trigger? I see SSL_clear() but from its description I doubt that is should be used here. Regards, Rainer -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On 08/02/16 15:46, Viktor Dukhovni wrote: > >> On Feb 8, 2016, at 9:49 AM, Matt Caswellwrote: >> >> Actually, yes that is a good point. There could be some subtle security >> issues there. You probably need to additionally check that you are not >> halfway through a handshake: >> >> SSL_renegotiate(ssl); >> SSL_do_handshake(ssl); >> do { >>read_some_app_data(); >>if(no_client_cert_yet() || SSL_in_init(ssl)) { >>discard_app_data(); >>} >> } while(no_client_cert_yet() || SSL_in_init(ssl)); > > Indeed, but discarding the data may not be an option, Sure. I was answering the specific question posed by Tomas: "What if the server wants to discard all the application data that was sent before the renegotiation completed?" Matt -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On 08/02/16 12:11, Rainer Jung wrote: > I'm adding support for OpenSSL 1.1.0 to the Apache web server. > > I struggle to migrate the renegotiation code in the case wehere we want > the client to send a client cert. The current code works like explained in > > http://www.linuxjournal.com/node/5487/print > > After using SSL_set_verify() it calls > > SSL_renegotiate(ssl); > SSL_do_handshake(ssl); > SSL_set_state(ssl, SSL_ST_ACCEPT); > SSL_do_handshake(ssl); > > for reasons given in the article. > > The new 1.1.0 API no longer allows to set the state using > SSL_set_state(). The old article states, that calling > SSL_set_accept_state() is not the right thing to do. Looking at > s_server.c doesn't give a hint what to do instead, because it looks like > it reads the client certs just raw from the socket. > > Any hint what would replace the above sequence or at least the > SSL_set_state(ssl, SSL_ST_ACCEPT)? > > Thanks a bunch and regards, 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. Matt -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On 08/02/16 12:34, Matt Caswell wrote: > > > On 08/02/16 12:11, Rainer Jung wrote: >> I'm adding support for OpenSSL 1.1.0 to the Apache web server. >> >> I struggle to migrate the renegotiation code in the case wehere we want >> the client to send a client cert. The current code works like explained in >> >> http://www.linuxjournal.com/node/5487/print >> >> After using SSL_set_verify() it calls >> >> SSL_renegotiate(ssl); >> SSL_do_handshake(ssl); >> SSL_set_state(ssl, SSL_ST_ACCEPT); >> SSL_do_handshake(ssl); >> >> for reasons given in the article. >> >> The new 1.1.0 API no longer allows to set the state using >> SSL_set_state(). The old article states, that calling >> SSL_set_accept_state() is not the right thing to do. Looking at >> s_server.c doesn't give a hint what to do instead, because it looks like >> it reads the client certs just raw from the socket. >> >> Any hint what would replace the above sequence or at least the >> SSL_set_state(ssl, SSL_ST_ACCEPT)? >> >> Thanks a bunch and regards, > > 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 I of course meant HelloRequest (I was looking at the DTLS code earlier which sends a HelloVerifyRequest!!!) Matt -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
> On Feb 8, 2016, at 9:26 AM, Matt Caswellwrote: > > 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()); At what point in the handshake would a query for client certificates show their presence? Is it always strictly after the new "finished" message? An additional check for the completion of the handshake may be appropriate. -- -- Viktor. -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On Po, 2016-02-08 at 12:34 +, 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? -- Tomas Mraz No matter how far down the wrong road you've gone, turn back. Turkish proverb (You'll never know whether the road is wrong though.) -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On 08/02/16 14:36, Viktor Dukhovni wrote: > >> On Feb 8, 2016, at 9:26 AM, Matt Caswellwrote: >> >> 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()); > > At what point in the handshake would a query for client > certificates show their presence? Is it always strictly > after the new "finished" message? An additional check for > the completion of the handshake may be appropriate. > Actually, yes that is a good point. There could be some subtle security issues there. You probably need to additionally check that you are not halfway through a handshake: SSL_renegotiate(ssl); SSL_do_handshake(ssl); do { read_some_app_data(); if(no_client_cert_yet() || SSL_in_init(ssl)) { discard_app_data(); } } while(no_client_cert_yet() || SSL_in_init(ssl)); Matt -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev
Re: [openssl-dev] How to do reneg with client certs in 1.1.0 API
On 08/02/16 13:45, Tomas Mraz wrote: > On Po, 2016-02-08 at 12:34 +, 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()); Matt -- openssl-dev mailing list To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev