renegotiation expected to fail when trust configuration has changed.

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

renegotiation expected to fail when trust configuration has changed.

Pfluegl, Andreas

Hi,

 

We have a C++ client application and a C++ server application using OpenSSL 1.1.0f to encrypt the TCP/IP communication.

 

We enforce mutual authentication (also the server requests certificates from the clients and verifies if they are issued by a CA it trusts).

 

We are able to update certificates (Host certificates and trusted CA certificates) on clients and servers without stopping the executables or interrupting the communication. We managed the update of the trusted CA certificates by using TLS Extension #3 (trusted_ca_keys) specified in RFC6066.

 

We are able to remove old obsolete certificates (Host certificates and trusted CA certificates) on clients and servers without stopping the executables or interrupting the communication. New established TCP/IP sessions will always use the newest certificates.
The update of a trusted CA certificate might look like this:

  • Server and clients are deployed with certificates issued by CA1, the CA1 certificate is deployed as trusted root certificate.
  • Certificates issued by CAnew and the CAnew certificate will be deployed to the server and all clients. Whenever a new TCP/IP session is established the new certificates are used.
  • Once all CAnew certificates are deployed, the CA1 certificates can be removed from the server and the clients.

 

We also want to force established TCP sessions to move from obsolete certificates the newest certificates be triggering a renegotiation. We expect the renegotiation to fail, if the host does not have the right set of certificates.

This works fine, if we trigger the renegotiation at the client, but the real benefit would be to do the renegotiation on the server. So we could remove all already connected malicious clients which have managed to steal obsolete certificates. But sadly this does not work the way we implemented it.

 

we implemented the renegotiation by essentially calling

SSL_renegotiate() and

SSL_do_handshake()

 

But see our trace for a better illustration what is going on.

Note!

  We use SSL_CTX_set_info_callback() to get insights into OpenSSL states and set the following essential configurations:

    SSL_CTX_set_verify(m_ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, &verify_callback);

    SSL_CTX_add_client_custom_ext(m_ctx, TLSEXT_TYPE_trusted_ca_keys, &client_add_cb, nullptr, nullptr, &client_parse_cb, nullptr);

    SSL_CTX_add_server_custom_ext(m_ctx, TLSEXT_TYPE_trusted_ca_keys, &server_add_cb, nullptr, nullptr, &server_parse_cb, nullptr);

 

 

Scenario 1:  Client triggered renegotiation (Note! works as expected)

 

Client trace (Dist):

 

Comment

Trace snippet  

 

___________HANDSHAKE_START_     fd=13 in state SSL negotiation finished successfully

___________CONNECT_LOOP__OK____ fd=13 in state SSL negotiation finished successfully

OpenSSL called custom extension callback

++ client_add_cb Entered

{

Client_add_cb calls sendTrustedCAKeys()

 

The list of trused CA’s sent to the server.

  ++ sendTrustedCAKeys Entered

  {

    CA directory: /opt/IowaDev/Projects/WCCILProject/config/CertStore//trusted

    <== send peer a list of my trusted CAs. SHA1: A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30

                                       Subject  : /C=AT/ST=OOE/O=ETM/OU=INNO/CN=CA1 file: af83623b.0

                                       Out      : A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30

  } ++ sendTrustedCAKeys returns : 1 elapsed time: 3685525ns

 

 

} ++ client_add_cb returns : 1 elapsed time: 14254269ns

 

___________CONNECT_LOOP__OK____ fd=13 in state SSLv3/TLS write client hello

___________CONNECT_EXIT__       fd=13 in state SSLv3/TLS write client hello

 

 

Server trace (Proxy):

 

Comment

Trace snippet  

 

___________HANDSHAKE_START_     fd=316 in state before SSL initialization

___________ACCEPT__LOOP__OK____ fd=316 in state before SSL initialization

___________ACCEPT__LOOP__OK____ fd=316 in state before SSL initialization

I expect server_parse_cb() returning 0 to cause the interruption of the connection.

Can you confirm this?

++ CertFileTLSContextHandler::server_parse_cb Entered
{

  == server_parse_cb: ext_type: 3 inlen: 61 in: A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30

  ++ CertificateStoreDirectory::findCertBy by SHA1 Entered

  {

    certificate: fde47a0f.1 ignored! does not match A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30

  } ++ CertificateStoreDirectory::findCertBy returns :   elapsed time: 1302748ns

 

} ++ CertFileTLSContextHandler::server_parse_cb returns : 0 elapsed time: 1351234ns

 

___________WRITE___ALERT_ fd=316 in state SSLv3/TLS read client hello err: fatal: decode error

___________ACCEPT__EXIT__ fd=316 in state error

11152:error:1417D0E3:SSL routines:tls_process_client_hello:parse tlsext:ssl\statem\statem_srvr.c:1209:

 

 

Scenario 2: Server triggered renegotiation (Expected to interrupt connection as well.)

 

Server trace (Proxy):

 

 

Comment

Trace snippet  

 

++ TLSContextHandler::renegotiate Entered

{

  Trusting CA certificate "/C=AT/ST=OOE/O=ETM/OU=INNO/CN=CA2" file fde47a0f.1

  Use host certificate: "/C=AT/ST=OOE/L=LINZ/O=ETM/OU=INNO/CN=Sys2:Single"

           issued by  : "/C=AT/ST=OOE/O=ETM/OU=INNO/CN=CA2"

           file       : Single.1.cert.pem

  Use private key file: Single.1.key.pem

 

  ++ TLSContextHandler::doHandshake Entered

  {

    ___________HANDSHAKE_START_ fd=920 in state SSL negotiation finished successfully

    ___________ACCEPT__LOOP__OK____ fd=920 in state SSL negotiation finished successfully

    ___________ACCEPT__LOOP__OK____ fd=920 in state SSLv3/TLS write hello request

 

Here I am missing server_parse_cb() (see Server trace scenario 1)

 

 

    ___________ACCEPT__EXIT__       fd=920 in state SSL negotiation finished successfully

    SSL_do_handshake(ssl) rc: 1, SSL error: [0] SSL_ERROR_NONE, OS error: [0] No error

 

  } ++ TLSContextHandler::doHandshake returns : 1 elapsed time: 310500ns

 

 

} TLSContextHandler::renegotiate returns : 1 elapsed time: 3564000ns

 

Client trace (Dist):

 

 

Comment

Trace snippet  

 

___________HANDSHAKE_START_     fd=13 in state SSL negotiation finished successfully

___________CONNECT_LOOP__OK____ fd=13 in state SSL negotiation finished successfully

client_add_cb ist called, but the server never gets the data! (see above)

++ client_add_cb Entered

{

  ++ sendTrustedCAKeys Entered

  {

    <== send peer a list of my trusted CAs. SHA1: A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30    

                                       Subject  : /C=AT/ST=OOE/O=ETM/OU=INNO/CN=CA1 file: af83623b.0

                                       Out      : A7:8F:B0:9A:96:A4:A0:4E:6F:B3:BF:4D:24:B3:85:0D:4A:64:9B:30

  } ++ sendTrustedCAKeys returns : 1 elapsed time: 3685525ns

} ++ client_add_cb returns : 1 elapsed time: 14254269ns

 

___________CONNECT_LOOP__OK____ fd=13 in state SSLv3/TLS write client hello

___________CONNECT_EXIT__       fd=13 in state SSLv3/TLS write client hello

 

 

Could you please advice how to solve this issue.

 

With best regards,
Andreas Pflügl


--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users
Reply | Threaded
Open this post in threaded view
|

Re: renegotiation expected to fail when trust configuration has changed.

Matt Caswell-2


On 22/11/2018 15:58, Pfluegl, Andreas wrote:
>
> I expect server_parse_cb() returning 0 to cause the interruption of the connection.
>
> Can you confirm this?

Yes. According to the docs:

"If the B<parse_cb> considers the extension data acceptable it must return 1. If
it returns 0 or a negative value a fatal handshake error occurs using the TLS
alert value specified in B<*al>."

https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_add_server_custom_ext.html


>
> Here I am missing server_parse_cb() (see Server trace scenario 1)

When a client receives a HelloRequest message it will send a new ClientHello and
attempt to resume the connection. The attempt at resumption does not occur when
a reneg is initiated from the client side unless you call
SSL_renegotiate_abbreviated() instead of SSL_renegotiate().

If the attempt at resumption is successful then custom extension parsing does
not get invoked on the server side. This is by design:

https://github.com/openssl/openssl/blob/0fbe8491fc05d280a1f00bfc26dd3c3a6c63f04a/ssl/t1_lib.c#L2314-L2325

Unfortunately the docs in 1.1.0 are a bit lacking on this point. They have been
significantly revised and updated in 1.1.1 and hopefully this is a little more
obvious. In particular note that the 1.1.1 flag SSL_EXT_IGNORE_ON_RESUMPTION is
automatically set when calling SSL_CTX_add_server_custom_ext(). This is so that
the behaviour is backwards compatible with 1.1.0:

https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_add_custom_ext.html

In 1.1.1 we have the new function SSL_CTX_add_custom_ext() which (among other
things) allows you to control whether the callback is called during resumption
or not. See the doc link above.

So, in order to solve your problem, I see 2 possible solutions:

1) Upgrade to 1.1.1 and use the new SSL_CTX_add_custom_ext() API.
or
2) Invalidate any sessions in the session cache for old connections that were
established using the old certificate. You'll need to some additional custom
code to track that I imagine. You'll also need to avoid session tickets for that
to work.

Probably the upgrade to 1.1.1 is your best bet since 1.1.0 is only supported
until September 2019 anyway.

Matt

--
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users