Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

client certificates issued by my own CA with Apache

Trying to get an HTTPS session working using client certificates from a self-signed CA. The connection should check that all certificates are valid, both client and server side.

The process I followed is roundly as follows:

  1. Create Certificate Authority

    openssl genrsa -out CA.key 4096
    openssl req -new -key CA.key -out CA.csr
    openssl x509 -req -days 365 -in CA.csr -out CA.crt -signkey CA.key
    
  2. Create Server Certificate

    openssl genrsa -out server.key 4096
    openssl req -new -key server.key -out server.csr
    openssl ca -in server.csr -cert CA.crt -keyfile CA.key -out server.crt
    
  3. Create Client Certificate

    openssl genrsa -out client.key 4096
    openssl req -new -key client.key -out client.csr
    openssl ca -in client.csr -cert CA.crt -keyfile CA.key -out client.crt
    
  4. Configure Apache

    <VirtualHost _default_:443>
      SSLEngine on
      SSLCertificateFile "server.crt"
      SSLCertificateKeyFile "server.key"
      SSLCACertificateFile "CA.crt"
      <Directory "/var/www">
          SSLVerifyClient optional
          SSLVerifyDepth 10
          SSLOptions +StdEnvVars +ExportCertData
      </Directory>
    </VirtualHost>  
    

Now I try and make a test connection:

wget \
    --post-data 'id=1234' \
    --certificate=client.crt \
    --ca-certificate=CA.crt  \
    https://test.example.com:443

The resulting output from wget shows (over and over), in part:

HTTP request sent, awaiting response... No data received.
Retrying.

Checking the SSL error log from Apache give me the following messages:

[debug] ssl_engine_io.c(1606): [client xx.xx.xx.xx] total of 41 bytes in buffer, eos=1
[client xx.xx.xx.xx] Requesting connection re-negotiation
[debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
[debug] ssl_engine_kernel.c(771): [client xx.xx.xx.xx] Performing full renegotiation: complete handshake protocol (client does support secure renegotiation)
[debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSL renegotiate ciphers
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request A
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 flush data
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: SSLv3 write hello request C
[info] [client xx.xx.xx.xx] Awaiting re-negotiation handshake
[debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before accept initialization
[debug] ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#80b075190 [mem: 80b0ca003]
[debug] ssl_engine_kernel.c(1929): OpenSSL: Exit: error in SSLv3 read client hello B
[error] [client xx.xx.xx.xx] Re-negotiation handshake failed: Not accepted by client!?
[debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 0, 8192 bytes
[debug] ssl_engine_io.c(1725): [client xx.xx.xx.xx] buffered SSL brigade exhausted
[debug] ssl_engine_io.c(1650): [client xx.xx.xx.xx] read from buffered SSL brigade, mode 2, 0 bytes
[info] [client XX:XX:XX:XX::xx] Connection to child 3 established (server register.kiosk.tain.com:443)
[info] Seeding PRNG with 656 bytes of entropy
[debug] ssl_engine_kernel.c(1892): OpenSSL: Handshake: start 
[debug] ssl_engine_kernel.c(1900): OpenSSL: Loop: before/accept initialization

Run the openssl client to see if there's anything to help in here:

openssl s_client \
    -showcerts \
    -connect test.example.com:443 \
    -cert client.crt \
    -key client.key \
    -CAfile CA.crt

In the reply I see the following:

---
Server certificate
subject=/C=XX/ST=XXXXX/O=XXXX/CN=test.example.com
issuer=/O=XXXX/L=XXXXX/ST=XXXXX/C=SE/CN=XXXX Certificate Authority
---
No client certificate CA names sent
---
SSL handshake has read 3846 bytes and written 519 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit

"No client certificate CA names sent" looks different to what I am expecting. I want client certificates.

Where am I going wrong?

like image 272
user2919956 Avatar asked Oct 25 '13 14:10

user2919956


People also ask

Can I use same certificate for server and client?

It's technically possible for a TLS certificate to be used as both a server certificate and a client certificate. The TLS certificate for this very site has its key usage set that way, for instance. But the server which requires a client certificate does so to authenticate the client.

How do I get a client certificate for my browser?

In Chrome, go to Settings. On the Settings page, below Default browser, click Show advanced settings. Under HTTPS/SSL, click Manage certificates. In the Certificates window, on the Personal tab, you should see your Client Certificate.


1 Answers

It doesn't really make sense to talk about a "self-signed CA". Your title ("Self-signed client SSL certificates [...]") suggests you're talking about self-signed client certificate. You're not: you're talking about client certificates issued by your own CA.

You've put your SSLVerifyClient directive within a Directory section, which would imply a re-negotiation to get the client certificate, once the client has made a request trying to access that directory.

Since there is no DocumentRoot directive in your configuration, it's not clear whether a request on / will try to access this directory (this may depend on compilation options depending on how it was packaged, but /var/www isn't the default value otherwise).

Putting SSLVerifyClient directly in your virtual host should at least make openssl s_client see a client-certificate request. Fixing the DocumentRoot might not be enough, since you'd need to make the HTTP request to trigger the renegotiation.

like image 155
Bruno Avatar answered Oct 06 '22 01:10

Bruno