I have continued debugging this today and can add an observation that might
be of interest.
First I forced the protocol on both client and server to TLS1. Then I
experimented with different combinations of SSL_CTX_use_certificate*

I have also created what I think is a certificate chain by concatenating my
client certificate and the CA certificate that issued it.

When I do this:
SSL_CTX_use_certificate_chain_file(ctx, "chain.crt");

instead of
SSL_CTX_use_certificate_file(ctx, "clientcert.crt", SSL_FILETYPE_PEM);

I get further in the protocol that eventually ends with the message

SSL_accept:SSLv3 flush data
<<< TLS 1.0 Handshake [length 063d], Certificate

    ...lots of base64
    1c c0 a4 63 88 3e 7d 2d a1 f6 cb e5 a4 89 43 cf
    0b 1d e8 65 69 c9 32 6a 5d 37 38 8b 1a
depth=0 C = DE, // ***** lots of info ****
verify return:1
SSL_accept:SSLv3 read client certificate A
<<< TLS 1.0 Handshake [length 0046], ClientKeyExchange
    10 00 00 42 41 04 bf bd c4 0c 78 e7 c1 2d 20 47
    d3 0a 7c 7c 1b ae af bc 6d 6d 4c f5 83 43 d9 2c
    91 6e a3 19 f5 53 f4 18 cb 3b df f7 8f 71 33 a1
    cc 57 28 e4 cd 16 e1 f5 6d 06 b0 8b 1a ff 0c 82
    56 86 63 86 25 2c
SSL_accept:SSLv3 read client key exchange A
<<< TLS 1.0 ChangeCipherSpec [length 0001]
    01
<<< TLS 1.0 Handshake [length 0010], Finished
    14 00 00 0c 24 9b 6d fa f2 4c 08 0f fb 2d 57 8b
>>> TLS 1.0 Alert [length 0002], fatal unexpected_message
    02 0a
SSL3 alert write:fatal:unexpected_message
SSL_accept:failed in SSLv3 read certificate verify B
2675716:error:140880AE:SSL routines:SSL3_GET_CERT_VERIFY:missing verify
message:s3_srvr.c:2951:
2675716:error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake
failure:s3_pkt.c:989:

Interestingly, if I do the same thing with the s_client tool, the output
differs a little:

    6a 6f 78 78 54 27 b6 c0 f6 cc 43 72 32 fb 94 b4
    7c 08 b2 67 bf 06 f9 5a 99 f0 bf 79 7f 69 2e f6
    f4 a9 31 b4 e2 ce 0e 09 fe 25 1d 13 49 17 2c c8
    d8 83 47 7f 9b fe 31 4b 0e 95 d5 f5 ed 3d
depth=1 C = DE, // ***** lots of info *******
verify return:1
depth=0 C = DE, // ***** lots of info *******
verify return:1
SSL_accept:SSLv3 read client certificate A
<<< TLS 1.0 Handshake [length 0046], ClientKeyExchange
    10 00 00 42 41 04 57 d1 78 67 df 6f 64 d9 0e d0
    d3 95 d0 8a 05 13 52 0f 73 9c e1 a9 64 e6 45 d5
... handshake completes

An interesting difference is the lines starting with "depth=". I cannot
print the actual info there but there's two such lines with the s_client
tool and only one with my client. Also, s_client seems to send both
certificates. Where I put in that comment I see the textual description of
first the root CA (after depth=1) and then my client cert (after depth=0).

My client however only causes one such line and the info there is the root
CA. His own client certificate doesn't appear. That leads me to believe
that the client doesn't trust his own certificate and therefore doesn't
send it. But since the root CA is in the chain, he sends this instead.
Which in turn s_server will not accept since it doesn't state "SSL client"
as purpose. Can that be? And if so, why will my client not send the
certificate while the s_client will? Not really a big step forward but at
this point I'm glad for half a baby step.

Cheers,
Stephan




On Mon, Jun 10, 2013 at 10:06 AM, Stephan Menzel
<stephan.men...@gmail.com>wrote:

> Hi all,
>
> I am struggling with a client certificate problem and hope somebody can
> help me. I'm on windows here and develop a client/server pair using boost
> asio but I'll try to be unspecific. I am also not an expert in SSL speak so
> please forgive if I'm using layman's terms here. I'm on windows and using
> openssl 1.0.1e
>
> Basically, I want to have client authentication. The server shall only
> accept clients that have a certificate signed by my own CA. So I have setup
> a self signed CA. This has issued two more certificates. One for the client
> and one for the server. Both signed by the CA.
> I have done that quite a few times now and I am confident that I got it.
>
> My server side also works fine. It requests client certificates and if I'm
> using s_client and give those certs everything works. Also if I'm using a
> browser and have my root CA installed as trusted and then import the client
> certs.
>
> The only thing that I can't get to work is the libssl client. It always
> fails during the handshake and as far as I can see it will not send the
> client certficate:
>
> $ openssl.exe s_server -servername localhost -bugs -CAfile myca.crt -cert
> server.crt -cert2 server.crt -key private/server.key -key2
> private/server.key -accept 8887 -www -state -Verify 5
> verify depth is 5, must return a certificate
> Setting secondary ctx parameters
> Using default temp DH parameters
> Using default temp ECDH parameters
> ACCEPT
> SSL_accept:before/accept initialization
> SSL_accept:SSLv3 read client hello A
> SSL_accept:SSLv3 write server hello A
> SSL_accept:SSLv3 write certificate A
> SSL_accept:SSLv3 write key exchange A
> SSL_accept:SSLv3 write certificate request A
> SSL_accept:SSLv3 flush data
> SSL3 alert read:warning:no certificate
> SSL3 alert write:fatal:handshake failure
> SSL_accept:error in SSLv3 read client certificate B
> SSL_accept:error in SSLv3 read client certificate B
> 2675716:error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did
> not return a certificate:s3_srvr.c:3193:
> ACCEPT
>
> I'm using this s_server as debugging tool but against my real server the
> same thing occurs.
> s_client will work fine with the same certificates. Also, if I disable
> "-Verify" in the server the connection works. So it really seems just the
> client refusing to send it's certficate. What can be the reason for that?
>
> Since I'm using boost asio as an SSL wrapper the code looks like this:
>
>         m_ssl_context.set_verify_mode( asio::ssl::context::verify_peer );
>         m_ssl_context.load_verify_file( "myca.crt" );
>         m_ssl_context.use_certificate_file( "testclient.crt",
> asio::ssl::context::pem );
>         m_ssl_context.use_private_key_file( "testclient.key",
> asio::ssl::context::pem );
>
> I have also tried to bypass asio and access the SSL context directly by
> saying:
>
>         SSL_CTX *ctx = m_ssl_context.impl();
>         SSL *ssl = m_ssl_socket.impl()->ssl;
>         int res = 0;
>         res = SSL_CTX_use_certificate_chain_file(ctx, "myca.crt");
>         if (res <= 0) {
>             // handle error
>         }
>         res = SSL_CTX_use_certificate_file(ctx, "testclient.crt",
> SSL_FILETYPE_PEM);
>         if (res <= 0) {
>             // handle error
>         }
>         res = SSL_CTX_use_PrivateKey_file(ctx, "testclient.key",
> SSL_FILETYPE_PEM);
>         if (res <= 0) {
>             // handle error
>         }
>
> I can't see any difference in behavior. It should be mentioned that I am
> using a very old boost 1.43 asio which I cannot update but I suppose all
> relevant calls go more or less directly to OpenSSL anyway and the server
> works fine with that version so I think I can rule that out.
>
> I have been debugging this for almost a week now and I'm really stuck.
> Does anyone have a suggestion on what to try? I'm out of ideas...
>
> Cheers,
> Stephan
>
>
>
>
> PS: Here is what the above s_server debug out would be with s_client and
> the same certficate:
>
> $ openssl s_client -CAfile ca.crt -cert testclient.crt -key
> private/testclient.key -verify 2 -connect myhost:8887
>
> ACCEPT
> SSL_accept:before/accept initialization
> SSL_accept:SSLv3 read client hello A
> SSL_accept:SSLv3 write server hello A
> SSL_accept:SSLv3 write certificate A
> SSL_accept:SSLv3 write key exchange A
> SSL_accept:SSLv3 write certificate request A
> SSL_accept:SSLv3 flush data
> depth=1 C = DE, // further info
> verify return:1
> depth=0 C = DE, // further info
> verify return:1
> SSL_accept:SSLv3 read client certificate A
> SSL_accept:SSLv3 read client key exchange A
> SSL_accept:SSLv3 read certificate verify A
> SSL_accept:SSLv3 read finished A
> SSL_accept:SSLv3 write session ticket A
> SSL_accept:SSLv3 write change cipher spec A
> SSL_accept:SSLv3 write finished A
> SSL_accept:SSLv3 flush data
> ACCEPT
>
> ... handshake completes and data is transferred.
>
>

Reply via email to