SSLRead returns errSSLClientCertRequested

We have a client connecting to some server, initially, we do not provide a client's certificate before handshake started, but we set the option kSSLSessionOptionBreakOnCertRequested set to true. During the initial handshake the client's certificate is not requested.

After the handshake is complete (SSLHandshake returned 0 - succsess) we start sending some data (HTTP request).

Apparently, at this point the server starts a renegotiation (and this time it requires a client certificate to access some resource).

Since we have a read notification on the socket and consider the connection to be encrypted, we call SSLRead.

SSLRead returns unexpected errSSLClientCertRequested error. So it looks like we fail to recognize renegotiation attempt (though SSLRead seems to start re-handshake) and failing to provide our certificate. Now my question is: what's the correct way to handle this? Just setting our certificate on errSSLClientCertRequested and trying to continue with SSLHandshake does not seem to work. Also, it does not help if I set the certificate before the handshake and disabe kSSLSessionOptionBreakOnCertRequested, since we, anyway, have to set kSSLSessionOptionBreakOnServerAuth == true (to have our own verification procedure).


Edit: any renegotiation is failing, since we don't expect handshake-related errors from SSLRead.

But even worse: why does SecureTransport is trying to renegotiate, if, according to the docs, by default renegotiation is disabled?

The only fragment I foudn in coreTLS is:


case SSL_HdskClientHello:
            if ((ctx->state != SSL_HdskStateServerUninit) && (ctx->state != SSL_HdskStateServerReady))
                goto wrongMessage;
            if ((ctx->state == SSL_HdskStateServerReady) && !ctx->allowRenegotiation) {
                err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertNoRenegotiation, ctx);
            } else {
                err = SSLProcessClientHello(message.contents, ctx);
            }
            break;


so it looks like only a server can disable renegotiation. Also, the code in SecureTransport looks weird:


case kSSLSessionOptionAllowServerIdentityChange:
            tls_handshake_set_server_identity_change(context->hdsk, value);
            context->allowServerIdentityChange = true;
            break;
        case kSSLSessionOptionAllowRenegotiation:
            tls_handshake_set_renegotiation(context->hdsk, value);
            context->allowRenegotiation = true;
            break;
        case kSSLSessionOptionEnableSessionTickets:
            tls_handshake_set_session_ticket_enabled(context->hdsk, value);
            context->enableSessionTickets = true;
            break;


Though I did not find any place in code where context->allowWhatever is used.

Accepted Reply

SSLRead
returns unexpected
errSSLClientCertRequested
error. So it looks like we fail to recognize renegotiation attempt (though SSLRead seems to start re-handshake) and failing to provide our certificate.

Unfortunately this stuff is too complex for me to provide help in the context of DevForums. I recommend you open a DTS tech support incident and we can pick things up from there.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

SSLRead
returns unexpected
errSSLClientCertRequested
error. So it looks like we fail to recognize renegotiation attempt (though SSLRead seems to start re-handshake) and failing to provide our certificate.

Unfortunately this stuff is too complex for me to provide help in the context of DevForums. I recommend you open a DTS tech support incident and we can pick things up from there.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"