iPXE discussion forum

Full Version: Can't get Client certificates to work
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello!

I hope someone can help me. I'm struggling using Client certificates. Server Certificates are working well as well as Code Signing. Although it took some days to get this to work, now it works fine.

But Client certificates won't work at all.

I'm using Debian 6.0.7 (squeeze), Apache 2.2.16, OpenSSL 1.0.1.

Please find below the steps to create the certificates and my apache configuration.

Thank's for helping me.

************************************************
# CREATE ROOT Certificate
openssl req -x509 -newkey rsa:2048 -out ca.crt -keyout ca.key -days 3650

# CREATE SERVER Certificate
openssl req -newkey rsa:2048 -keyout server.key -out server.req
openssl ca -config ca.cnf -extensions codesigning -in server.req -out server.crt

# REMOVE Passphrase
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key

# SIGN Code
openssl cms -sign -binary -noattr -in /var/www-pxe/00\:0c\:29\:41\Big Grin1\Big Grina/loader.iso -signer server.crt -inkey server.key -outform DER -out /var/www-pxe/00\:0c\:29\:41\Big Grin1\Big Grina/loader.sig
openssl cms -sign -binary -noattr -in /var/www-pxe/memdisk -signer server.crt -inkey server.key -outform DER -out /var/www-pxe/memdisk.sig
openssl cms -sign -binary -noattr -in /var/www-pxe/bootstrap.ipxe -signer server.crt -inkey server.key -outform DER -out /var/www-pxe/bootstrap.ipxe.sig

# CREATE CLIENT Certificate

openssl req -newkey rsa:2048 -keyout client.key -out client.req
openssl ca -config ca.cnf -in client.req -out client.crt

# REMOVE Passphrase
cp client.key client.key.org
openssl rsa -in client.key.org -out client.key


# MAKE undionly
make bin/undionly.kpxe EMBED=test.ipxe
make bin/undionly.kpxe EMBED=test.ipxe TRUST=server.crt CERT=client.crt PRIVKEY=client.key

************************************************

Here's my Apache Configuration:


************************************************
<IfModule mod_ssl.c>
<VirtualHost *:443>

DocumentRoot /var/www-pxe

SSLEngine on
SSLOptions +StrictRequire

SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

SSLCACertificateFile /var/ipxe/src/client.crt

SSLCertificateFile /var/ipxe/src/server.crt
SSLCertificateKeyFile /var/ipxe/src/server.key


<Directory />
<------>SSLRequireSSL
<------>Options FollowSymlinks
<------>AllowOverride None
<------>
<------>SSLVerifyClient require
<------>SSLVerifyDepth 1
</Directory>

<Directory /var/www-pxe/>
<------>Options Indexes FollowSymLinks MultiViews
<------>AllowOverride None
<------>Order allow,deny
<------>allow from all
</Directory>

BrowserMatch "MSIE [2-5]" \
<------>nokeepalive ssl-unclean-shutdown \
<------>downgrade-1.0 force-response-1.0

</VirtualHost>
</IfModule>
(2013-03-22 18:42)Viator Wrote: [ -> ]But Client certificates won't work at all.

Thanks for giving detailed descriptions of your configuration. Unfortunately, you haven't said what the actual problem is anywhere. What error are you seeing?

Michael
(2013-03-23 22:02)mcb30 Wrote: [ -> ]Thanks for giving detailed descriptions of your configuration. Unfortunately, you haven't said what the actual problem is anywhere. What error are you seeing?

Michael

Hello Michael!

Sorry for not mention this "detail". I get an "Operation not permitted (http://ipxe.org/410de13c)" on the client.
http://ipxe.org/410de13c tells me to use the latest version, I've checked out the latest version of ipxe.

The clients starts up fine if no client certificate verification is used.
btw. my ca.cnf is exactly the one from http://ipxe.org/crypto with the exception of default_md = sha1 instead of default. This is due to that default did not work on the Version of OpenSSl which ships with Debian and md5 isn't recommended by OpenSSL.

Thank you.

Thorsten


Just to give my complete config: I use the following embedded script and boostrap.ipxe

*********************************************
#!ipxe

imgtrust --permanent

dhcp

isset ${proxydhcp/next-server} && set next-server ${proxydhcp/next-server}

initrd --name bootstrap https://${next-server}/bootstrap.ipxe || shell.
imgverify bootstrap https://${next-server}/bootstrap.ipxe.sig || shell

boot bootstrap
#shell
*********************************************

bootstrap:

*********************************************
#!ipxe

imgtrust --permanent

initrd --name loader https://${next-server}/${mac}/loader.iso || shell
imgverify loader https://${next-server}/${mac}/loader.sig || shell

initrd --name kernel https://${next-server}/memdisk || shell
imgverify kernel https://${next-server}/memdisk.sig || shell

boot kernel iso

*********************************************
(2013-03-25 09:56)Viator Wrote: [ -> ]Sorry for not mention this "detail". I get an "Operation not permitted (http://ipxe.org/410de13c)" on the client.

Thanks for clarifying!

I think this might be the problem:

Quote:
Code:
SSLCACertificateFile /var/ipxe/src/client.crt

I haven't tested, but I suspect that Apache wants the CA certificate that signed the client certificate specified here, rather than the client certificate itself. Try:

Code:
SSLCACertificateFile /var/ipxe/src/ca.crt

Michael
(2013-03-25 11:57)mcb30 Wrote: [ -> ]I haven't tested, but I suspect that Apache wants the CA certificate that signed the client certificate specified here, rather than the client certificate itself. Try:

Code:
SSLCACertificateFile /var/ipxe/src/ca.crt

Michael


Hi Michael!

Thank's for your reply.
I've recreated all keys and certs (the way I did describe in my first post) to be sure they match and then I tried to use ca.crt - same result. With client-certificate verification turned on, the client won't start but does so if the verification is switched off. :-(

Since I know that common-name can't be omitted and must be a valid address I also have tried using the clients ip in the client certificate with no result (even this would work, this would make problems in a real environment since I do not really know the clients ip)

In the "docu" theres a cross certificate mentioned (openssl ca -config ca.cnf -extensions cross -notext -preserveDN -ss_cert startcom.crt -out startcom-cross.crt) but I do not know if an how this is important for me. How should I use this certificates?

Thorsten
(2013-03-25 13:20)Viator Wrote: [ -> ]I've recreated all keys and certs (the way I did describe in my first post) to be sure they match and then I tried to use ca.crt - same result. With client-certificate verification turned on, the client won't start but does so if the verification is switched off. :-(

Since I know that common-name can't be omitted and must be a valid address I also have tried using the clients ip in the client certificate with no result (even this would work, this would make problems in a real environment since I do not really know the clients ip)

The client certificate name doesn't really matter. You can use the SSLRequire directive for Apache to restrict which client certificates are accepted; I think the default is to accept any certificates which can be validated.

Quote:In the "docu" theres a cross certificate mentioned (openssl ca -config ca.cnf -extensions cross -notext -preserveDN -ss_cert startcom.crt -out startcom-cross.crt) but I do not know if an how this is important for me. How should I use this certificates?

Cross-signing is not relevant to your setup.

Have you checked the server log files to see if it contains any explanations?

Failing that, you could try capturing the traffic, and post the capture file somewhere I can fetch it.

Michael
Update:

Now I'm running on Ubuntu Server 12.10 with the same results. But at least Ubuntu comes with an actual Version of openSSL which allows CMS.

I created logs using wireshark. Should I upload the files or send by mail (address?)?


Thorsten
(2013-03-27 14:27)Viator Wrote: [ -> ]Now I'm running on Ubuntu Server 12.10 with the same results. But at least Ubuntu comes with an actual Version of openSSL which allows CMS.

I created logs using wireshark. Should I upload the files or send by mail (address?)?

Thanks for sending the logs. I can see a few problems. Firstly, the server seems to be providing an incorrect certificate chain containing two certificates, both of which are self-signed (i.e. issuer is the same as subject). Secondly, the server is not requesting a client certficiate from iPXE, which is why iPXE is not providing one.

I would suggest that you try recreating your configuration from scratch, following the instructions on http://ipxe.org/crypto verbatim as far as possible.

Michael
(2013-03-27 15:55)mcb30 Wrote: [ -> ]I would suggest that you try recreating your configuration from scratch, following the instructions on http://ipxe.org/crypto verbatim as far as possible.

Hello Michael!

Thank you for your reply. I've been following the instructions.

I've changed the configuration. Now I've created a CA Certificate and 3 other Certificates, one for the server, one for the code signing and one for the client verification which I have signed using the CA. Please have a look at the end, I add the script I use.

In httpd.conf I use them this way:
Code:
SSLCACertificateFile /var/asys/ipxe/certs/ca.crt
    SSLCertificateFile /var/asys/ipxe/certs/server.crt
    SSLCertificateKeyFile /var/asys/ipxe/certs/server.key

https and codesigning works quite fine. Still no success with client verification and I run out if ideas.


apache errorlog shows:

Code:
Connection: Client IP: 192.168.11.131, Protocol: TLSv1.2, Cipher: AES256-SHA256 (256/256 bits)
ssl_engine_io.c(1897): OpenSSL: read 5/5 bytes from BIO#7f2750001340 [mem: 7f2750006c73] (BIO dump follows)
ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
ssl_engine_io.c(1869): | 0000: 17 03 03 00 90                                   .....            |
ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
ssl_engine_io.c(1897): OpenSSL: read 144/144 bytes from BIO#7f2750001340 [mem: 7f2750006c78] (BIO dump follows)
ssl_engine_io.c(1830): +-------------------------------------------------------------------------+
ssl_engine_io.c(1869): | 0000: 5a e3 f2 d6 8b cf f2 67-58 fa 04 c7 82 b2 ff 02  Z......gX....... |
ssl_engine_io.c(1869): | 0010: 30 b2 52 6a 92 b9 2f b3-71 18 1f 94 73 ec a1 6e  0.Rj../.q...s..n |
ssl_engine_io.c(1869): | 0020: 40 c3 79 3b d6 18 7e 2c-10 9f c3 12 43 d5 5f e1  @.y;..~,....C._. |
ssl_engine_io.c(1869): | 0030: 09 da f0 0e 85 d8 2d 37-8e 4a 44 c5 aa dc 54 60  ......-7.JD...T` |
ssl_engine_io.c(1869): | 0040: 8f e7 fa 80 b7 6f 40 fc-59 95 04 f0 45 b3 2e 66  .....o@.Y...E..f |
ssl_engine_io.c(1869): | 0050: 5b 6f 52 eb 7b c3 8f 49-be d0 5b 8f 36 98 ef e1  [oR.{..I..[.6... |
ssl_engine_io.c(1869): | 0060: 86 ec 63 f4 95 e5 93 cd-85 59 61 7a df ee c8 25  ..c......Yaz...% |
ssl_engine_io.c(1869): | 0070: 02 b2 43 34 5e 74 41 1b-ea 56 29 ec d8 ab 68 cc  ..C4^tA..V)...h. |
ssl_engine_io.c(1869): | 0080: d9 e3 8b 47 76 e9 02 0b-ff df d7 13 9d 21 35 e6  ...Gv........!5. |
ssl_engine_io.c(1875): +-------------------------------------------------------------------------+
Initial (No.1) HTTPS request received for child 1 (server 192.168.11.152:443)
ssl_engine_kernel.c(510): [client 192.168.11.131] Changed client verification type will force renegotiation
[client 192.168.11.131] Requesting connection re-negotiation
ssl_engine_io.c(1908): OpenSSL: I/O error, 5 bytes expected to read on BIO#7f2750001340 [mem: 7f2750006c73]
ssl_engine_kernel.c(764): [client 192.168.11.131] Performing full renegotiation: complete handshake protocol (client
ssl_engine_kernel.c(1866): OpenSSL: Handshake: start
ssl_engine_kernel.c(1884): OpenSSL: Write: SSL renegotiate ciphers
ssl_engine_kernel.c(1903): OpenSSL: Exit: error in SSL renegotiate ciphers
[client 192.168.11.131] Re-negotiation request failed
SSL Library Error: 336068946 error:14080152:SSL routines:SSL3_ACCEPT:unsafe legacy renegotiation disabled

Here the script to create the sertificates:
Code:
#!/bin/bash

cd /var/asys/ipxe/certs

rm sslpass
echo secure2013 >> sslpass
echo secure2013 >> sslpass

echo
echo ============================================================================
echo
echo '                Creating CA Certificate'
echo
echo ============================================================================
echo

# CREATE ROOT Certificate
openssl req -x509 -newkey rsa:2048 -out ca.crt -keyout ca.key -days 3650 \
-subj "/C=AT/ST=Vienna/L=Vienna/O=asys/CN=secureBoot" \
-passin file:sslpass -passout file:sslpass

echo
echo ============================================================================
echo
echo '                    Creating SERVER Certificate'
echo
echo ============================================================================
echo

# CREATE Certificate
openssl req -newkey rsa:2048 -keyout server.key -out server.req \
-subj "/C=AT/ST=Vienna/L=Vienna/O=mycompany/CN=192.168.11.152" \
-passin file:sslpass -passout file:sslpass

# SIGN Certificate using CA Certificate
openssl ca -config ca.cnf -in server.req -out server.crt \
-passin file:sslpass -batch

echo
echo ============================================================================
echo
echo '                 Creating CODE SIGN Certificate'
echo
echo ============================================================================
echo

# CREATE Certificate
openssl req -newkey rsa:2048 -keyout codesign.key -out codesign.req \
-subj "/C=AT/ST=Vienna/L=Vienna/O=mycompany/CN=192.168.11.152" \
-passin file:sslpass -passout file:sslpass

# SIGN Certificate using CA Certificate
openssl ca -config ca.cnf -extensions codesigning -in codesign.req -out codesign.crt \
-passin file:sslpass -batch


echo
echo ============================================================================
echo
echo '                 Creating CLIENT Certificate'
echo
echo ============================================================================
echo

# CREATE Certificate
openssl req -newkey rsa:2048 -keyout client.key -out client.req \
-subj "/C=AT/ST=Vienna/L=Vienna/O=mycompany/CN=192.168.11.152" \
-passin file:sslpass -passout file:sslpass

# SIGN Certificate using CA Certificate
openssl ca -config ca.cnf -in client.req -out client.crt \
-passin file:sslpass -batch

echo
echo ============================================================================
echo
echo '                       Removing Passwords'
echo
echo ============================================================================
echo

cp ca.key ca.key.org
openssl rsa -in ca.key.org -out ca.key \
-passin file:sslpass

cp server.key server.key.org
openssl rsa -in server.key.org -out server.key \
-passin file:sslpass

cp client.key client.key.org
openssl rsa -in client.key.org -out client.key \
-passin file:sslpass

cp codesign.key codesign.key.org
openssl rsa -in codesign.key.org -out codesign.key \
-passin file:sslpass

echo
echo ============================================================================
echo
echo '                          Signing CODE'
echo
echo ============================================================================
echo

cd /var/asys/ipxe/certs

openssl cms -sign -binary -noattr -signer codesign.crt -inkey codesign.key -certfile ca.crt -outform DER \
    -in /var/asys/www/bootstrap.ipxe -out /var/asys/www/bootstrap.ipxe.sig

openssl cms -sign -binary -noattr -signer codesign.crt -inkey codesign.key -certfile ca.crt -outform DER \
    -in /var/asys/www/memdisk -out /var/asys/www/memdisk.sig

openssl cms -sign -binary -noattr -signer codesign.crt -inkey codesign.key -certfile ca.crt -outform DER \
    -in /var/asys/www/00\:0c\:29\:41\:d1\:da/loader.iso -out /var/asys/www/00\:0c\:29\:41\:d1\:da/loader.sig

echo
echo ============================================================================
echo
echo '                      MAKING undionly.kpxe'
echo
echo ============================================================================
echo

# UPDATE IPXE from GIT
# cd /var/ipxe
# git pull

# MAKE undionly
cd /usr/src/ipxe/src

# clear certificates
make bin/undionly.kpxe EMBED=/var/asys/ipxe/scripts/secureBoot.ipxe

# make using new certificates
#make bin/undionly.kpxe EMBED=/var/asys/ipxe/scripts/secureBoot.ipxe TRUST=/var/asys/ipxe/certs/ca.crt
make bin/undionly.kpxe EMBED=/var/asys/ipxe/scripts/secureBoot.ipxe TRUST=/var/asys/ipxe/certs/ca.crt CERT=/var/asys/ipxe/certs/client.crt PRIVKEY=/var/asys/ipxe/certs/client.key

cp bin/undionly.kpxe /var/asys/pxe/undionly.kpxe.0

echo
echo ============================================================================
echo
echo '                    RESTARTING webservices'
echo
echo ============================================================================
echo

/var/asys/restart.sh

And here my complete http.conf
Code:
<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName 192.168.11.152:443

    DocumentRoot /var/asys/www

    SSLEngine on
    SSLOptions +StrictRequire

    SSLProtocol -all +TLSv1 +SSLv3
    SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

    SSLCACertificateFile /var/asys/ipxe/certs/ca.crt
    SSLCertificateFile /var/asys/ipxe/certs/server.crt
    SSLCertificateKeyFile /var/asys/ipxe/certs/server.key

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>
        
    <Directory /var/asys/www>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

        SSLRequireSSL
        #SSLRequire
        SSLVerifyClient require
        SSLVerifyDepth 10
    </Directory>
    
    BrowserMatch "MSIE [2-5]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
        
        
    LogLevel debug
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/ssl_access.log combined

</VirtualHost>
</IfModule>
Maybe I'm missing something here, but I can't see any indication that you've specified _intention_ for the server and client sertificates. Mustn't they be specified as TLS Server/Client-type certificates? I'm not exactly sure how that is done with openssl, but unless those flags aren't specified in a config file not included (like ca.cnf or something else) I'm going to assume that might be a possible problem. BTW: Using curl with the client certificates against your server (which has ssqlrequire set) should make it quicker to verify that your setup works.
(2013-03-28 22:04)robinsmidsrod Wrote: [ -> ]Maybe I'm missing something here, but I can't see any indication that you've specified _intention_ for the server and client sertificates. Mustn't they be specified as TLS Server/Client-type certificates? I'm not exactly sure how that is done with openssl, but unless those flags aren't specified in a config file not included (like ca.cnf or something else) I'm going to assume that might be a possible problem. BTW: Using curl with the client certificates against your server (which has ssqlrequire set) should make it quicker to verify that your setup works.

Hello Robin!

Thank you for your answer.
I have user the ca.cnf as specified here ipxe crypto with the exception of the parameter "default_md" which doesn't accept the value of "default", so i set it to sha1. Here is the ca.cnf I use:

Code:
[ ca ]
default_ca                        = CA_default

[ CA_default ]
serial                            = ca.srl
database                        = ca.idx
new_certs_dir                    = signed
certificate                        = ca.crt
private_key                        = ca.key
default_days                    = 3650
default_md                        = sha1
preserve                        = yes
#nameopt                        = default_ca
#certopt                        = default_ca
policy                            = policy_anything
unique_subject                    = no

[ policy_anything ]
countryName                     = optional
stateOrProvinceName                = optional
organizationName                = optional
organizationalUnitName            = optional
commonName                        = optional
emailAddress                    = optional
localityName                    = optional


[ cross ]
basicConstraints                = critical,CA:true
keyUsage                        = critical,cRLSign,keyCertSign

[ codesigning ]
keyUsage                        = digitalSignature
extendedKeyUsage                = codeSigning

I'm not that good in openSSL to find out where the problem may be but as far as I could find out using google this should be OK.

In previous attempts to get it running I also tried md5 without success.

Since Michael mentioned that the server sends two combined certs I also tried to use the CA Cert on the Server which also worked fine for SSL and Code Verification but not for Client Verification.

I have never used curl (I'm a Windows Developer - eh - have been ;-) )but I will give it a try.

Additional I have another question: Doesn't ipxe resolve server addresses? "Problem" is that I'm not able to specify a URL like https://ipxe.myserver.com in the script. I have to use the IP which causes me to use the IP as CommonName in the Certs which isn't really a problem but using a machine name would be nicer. But probably this is an dnsmask configuration issue.

Thank you all for your trying to help me.

Thorsten
That last problem is most likely because of some DNS problem you're having in your environment. I'd suggest you try to solve that before you deal with your certificate problem. Getting HTTPS to work properly requires a functioning DNS, AFAIK.
SOLVED

The configuration for Apache MUST contain an "SSLRequire" phrase like in here (last entry):

Code:
    <Directory __HTTP_PATH__>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride None
        Order allow,deny
        allow from all

        SSLRequireSSL
        SSLRequire %{SSL_CLIENT_S_DN_O} eq "myCompany"
    </Directory>

This solves a big issue. Next is the DNS-problem.

Thank you for trying to help me.
Reference URL's