>From: owner-openssl-us...@openssl.org On Behalf Of Stephan Menzel >Sent: Monday, 10 June, 2013 11:04
>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. 1.0 specifically, or just 1-series i.e. not SSL3 (or <gack> 2)? TLS-any should have no effect on selecting and using a client cert, although it does change the way of expressing lack of (usable) cert from no C-Cert message at all to a message with an empty sequence, which you can see in a trace or log if you look closely. It may be desirable or helpful for other reasons, and on s_server 1.0 vs 1.1 1.2 does make the -msg display nicer. >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. Concatenated in what order? See below. And you say below the CA is your own private root. There is no need to send a root, because the peer will never trust a sent root, only a root it has locally in its truststore. Especially since your client and server are both using your own CA, see below. >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 [apparently in s_server -msg -state, although you didn't say so] >SSL_accept:SSLv3 flush data ><<< TLS 1.0 Handshake [length 063d], Certificate <snip> >depth=0 C = DE, // ***** lots of info **** >verify return:1 >SSL_accept:SSLv3 read client certificate A "lots of info" is the Subject name, see below. ><<< TLS 1.0 Handshake [length 0046], ClientKeyExchange <snip> >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: With client auth and a nonstatic key exchange, there should be a client CertVerify message after ClientKX before CCS. I have no clue why it's not there. You talk about bypassing asio in doing the SSL_CTX setup; can I assume the SSL_connect also goes through or is done by asio? From the name, can I guess asio uses nonblocking sockets and multiple calls? If so, it's conceivable it's clobbering some data somewhere that's confusing OpenSSL. Or possibly asio interposes something in the socket I/O that openssl does that causes this message to get lost maybe some kind of filter BIO instead of socket-BIO?? >Interestingly, if I do the same thing with the s_client tool, >the output differs a little: <snip hex> >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 That should be your client at depth=0 and the CA at depth=1 ... ><<< TLS 1.0 Handshake [length 0046], ClientKeyExchange >... handshake completes Does it show CertificateVerify *then* ChangeCipherSpec & Finished? >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). ... and it is. See below about s_client. >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. There's no trust decision by the client about his own cert (or the server for hers). But his cert does need to match his privatekey. Did you put the CA root cert *first* in chain.crt? If so that tells openssl to use the root cert as the client's cert, which would result in sending only that cert as you report (there is no chain beyond a root), but it should have caused _use_PrivateKey_file to error before you got to any handshake, and your code indicated handling for that. Unless you somehow used the same privatekey for CA and client? I'm not sure offhand s_server (and openssl server) will reject a client cert because EKU excludes SSL-client, but if it does it would not be an error anything like the one you are getting. s_client behaves differently because it can't specify a chain file at all. Instead you specify the client cert file and openssl fills in the chain (if possible) using its *truststore* (even though it's arguable this isn't exactly the purpose of the truststore). See below. >On Mon, Jun 10, 2013 at 10:06 AM, Stephan Menzel <stephan.men...@gmail.com> wrote: >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 You're doing pretty well. I have corrected only one point. >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. You mean root CA cert and client cert-AND-KEY, perhaps combined as a PKCS#12. The client cert by itself is useless for authentication. >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 <snip> > 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: >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; Is an SSL pointer actually set here? See below. > int res = 0; > res = SSL_CTX_use_certificate_chain_file(ctx, "myca.crt"); > if (res <= 0) { > // handle error > } This is (almost certainly) not the analog of load_verify_file. You want SSL_CTX_load_verify_locations (ctx, "myca.crt", NULL) to set a CAfile and no CApath. However, I'm surprised this didn't cause the client to reject the server before even attempting to authenticate itself (during handshake) -- unless you have set or defaulted it somewhere else, or put in a callback that overrides the verify error. _use__chain_file of (only) a CA cert is completely wrong, but fortunately immediately overridden by your next call. > 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 > } Those two calls, assuming no error, should have caused libssl to send the client cert (and the chain=root if available) and use the key -- as long as they occur before the SSL object is created from the SSL_CTX, and no subsequent calls modify these settings in the SSL object. The asio calls certainly look like they should do the same thing, but probably only looking at asio itself can make that certain. >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. Can you reasonably try bypassing asio for the SSL_connect, and maybe a data I/O? If that gives the same problem, at least you have a much simpler (no-asio) test case to debug. If it works, it tends to point to the problem being in asio, which probably doesn't help much. >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 <snip good> Is ca.crt here the same as myca.crt above? Since you specify -key&cert for the client, and -CAfile (presumably) the CA cert, this results in s_client completing and sending the chain as above -- although as above, it isn't needed because the server ignores this copy of the root. I notice you show key files under private/ some places but not others. Is that just for posting, or could these actually be different? ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org