You are hereOpenVPN with Belgian eID

OpenVPN with Belgian eID


By chri - Posted on 03 February 2008

Edit: I added database authentication. Details see: here.

Some time ago Nicolas told us he played with the Belgian eID. In the past I also hacked the belpic code to compile it under Gentoo, but since I have my Mac I haven't really played with it except to use it as an online-auth for the Gov-sites.
For some weeks now I enabled SSL-VPN on my server using SSL Certificates with a self-signed authority. But just like Nicolas says :"Pretty cool stuff, if this'd work... Both VPN and SSH authentication will be done using my eID if this turns out well.".

So the plan is:

  • Make a VPN tunnel using OpenVPN
  • Identify my server using a certificate (self-signed or a CAcert one.)
  • Identify the user using certificates from the Belgian eID / Digital Identity Card
  • Authorize users based on their rijksregister-nummer/numéro de registre national
  • Check the validity of the card using CRL or OCSP

The client will need OpenVPN 2.1 (still in RC atm). The server seems to work with the latest stable release (2.0.6 on my system).

Installing eID drivers

There are plenty of manuals to do this, or if you use a distro like ubuntu/debian/openSUSE/... there should be packages for it. For MacOS X there is an installer and this manual if you want to use it to logon on your system.

Just to be sure it works. You can check what keys are on your card with the pkcs15-tool --dump command.
Notice that we have two private keys. One for Authentication and one as Signature. You are not authorized (neverExtract) to download the private key from the card.

Private RSA Key [Authentication]
        Usage       : [0x4], sign
        Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local
Private RSA Key [Signature]
        Usage       : [0x200], nonRepudiation
        Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract, local

Extract info from the card

With the command openvpn --show-pkcs11-ids provider you can see the DN and serial of your keys. This info will be used later.

The provider is the shared library you get when compiling the beid driver. On a linux system it's a .so file, on a mac a .dylib and probably a .dll on Windows.
If you don't know where it is, check the 'Security Devices' of your Firefox as it might already be used there.

$ openvpn --show-pkcs11-ids /usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.2.1.0.dylib 

The following objects are available for use.
Each object shown below may be used as parameter to
--pkcs11-id option please remember to use single quote mark.

Certificate
       DN:             /C=BE/CN=Christophe Vandeplas (Authentication)/SN=Vandeplas/
                            GN=Christophe Marie-Luc/serialNumber=83021811535
       Serial:         1000000000006F3CBE8C921BC713F8FD
       Serialized id:  Axalto/Belgium\x20eID/6CFF2491AB111E14/BELPIC\x20\x28Basic\x20PIN\x29/02

Certificate
       DN:             /C=BE/CN=Christophe Vandeplas (Signature)/SN=Vandeplas/
                            GN=Christophe Marie-Luc/serialNumber=83021811535
       Serial:         1000000000005A011FBE437FC4363A3D
       Serialized id:  Axalto/Belgium\x20eID/6CFF2491AB111E14/BELPIC\x20\x28Basic\x20PIN\x29/03

Take the Serialized id from the Authentication certificate. (bold)
This ID will be used to tell OpenVPN what key he should read. But there is a small thing, you must replace all \x20 to a space the \x28 to a ( and \x29 to ).
The result is something like this: pkcs11-id "Axalto/Belgium eID/6CFF2491AB111E14/BELPIC (Basic PIN)/02"

The last things we must extract are the certificates of the Belgian government.
The command pkcs15-tool --list-certificates lists the certificates present on the smartcard. Two fields require our attention (bold):

  • X.509 Certificate [CA]: The certificate authority that signed our key
  • X.509 Certificate [Root]: The root certificate
$ pkcs15-tool --list-certificates
X.509 Certificate [Authentication]
        Flags    : 3
        Authority: no
        Path     : 3f00df005038
        ID       : 02

X.509 Certificate [Signature]
        Flags    : 3
        Authority: no
        Path     : 3f00df005039
        ID       : 03

X.509 Certificate [CA]
        Flags    : 3
        Authority: yes
        Path     : 3f00df00503a
        ID       : 04

X.509 Certificate [Root]
        Flags    : 3
        Authority: yes
        Path     : 3f00df00503b
        ID       : 06

We write down the IDs of both certificates: 04 and 05. These numbers are used to export the certificates to a pem file.

$ pkcs15-tool --read-certificate 04 > belgium.crt
$ pkcs15-tool --read-certificate 06 >> belgium.crt

Current client/server configuration

Complete configurations with comments at the end of this article.
client
dev tun
proto udp
remote myserver.org 1194
resolv-retry infinite
nobind
user nobody
group nobody
persist-key
persist-tun
pkcs11-providers /usr/local/lib/beid-pkcs11.bundle/Contents/MacOS/libbeidpkcs11.2.1.0.dylib
pkcs11-id "Axalto/Belgium eID/6CFF2491AB111E14/BELPIC (Basic PIN)/02"
ca ca.crt
ns-cert-type server
comp-lzo
verb 3

The ca.crt file contains the certificate of the Certificate Authority that signed the key of my server.
The server configuration:

port 1194
proto udp
dev tun
cert server.crt
key server.key
ca belgium.crt
#tls-verify /etc/openvpn/auth-eid-check  # TODO uncomment this later
dh dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway"
keepalive 10 120
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
log         openvpn.log
verb 4
mute 20

Establishing the connection:

Server: /etc/init.d/openvpn start and client: openvpn --config openvpn.conf

I first didn't export both certificates in the same file (belgium.crt) and got the following error in my server logs:

Sun Feb  3 12:34:26 2008 us=556133 62.235.210.17:50545 VERIFY ERROR: depth=0, error=unable to get 
  local issuer certificate: /C=BE/CN=Christophe_Vandeplas__Authentication_/SN=Vandeplas/GN=Christophe_
  Marie-Luc/serialNumber=83021811535
Sun Feb  3 12:34:26 2008 us=556290 62.235.210.17:50545 TLS_ERROR: BIO read tls_read_plaintext 
  error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned

A working situation should show:

Sun Feb  3 12:45:31 2008 us=101863 62.235.210.17:50609 VERIFY OK: depth=2, /C=BE/CN=Belgium_Root_CA
Sun Feb  3 12:45:31 2008 us=102526 62.235.210.17:50609 VERIFY OK: depth=1, /C=BE/CN=Citizen_CA
Sun Feb  3 12:45:31 2008 us=103299 62.235.210.17:50609 VERIFY OK: depth=0, /C=BE/CN=Christophe_
  Vandeplas__Authentication_/SN=Vandeplas/GN=Christophe_Marie-Luc/serialNumber=83021811535
  ...
Sun Feb  3 12:45:33 2008 us=834295 62.235.210.17:50609 [Christophe_Vandeplas__Authentication_] 
  Peer Connection Initiated with 62.235.210.17:50609
Sun Feb  3 12:45:33 2008 us=834410 Christophe_Vandeplas__Authentication_/62.235.210.17:50609 
  MULTI: Learn: 10.8.0.10 -> Christophe_Vandeplas__Authentication_/62.235.210.17:50609
Sun Feb  3 12:45:33 2008 us=834445 Christophe_Vandeplas__Authentication_/62.235.210.17:50609 
  MULTI: primary virtual IP for Christophe_Vandeplas__Authentication_/62.235.210.17:50609: 10.8.0.10

This works ! Yess.. This means everyone with an eID can login on the VPN.. hmm.. probably not something I/you want.

Authorization

The authentication part works fine. We are fully certain that the certificate is valid but everyone with an eID can login. Time to implement a little authorization. Isn't it?

Remember this line? tls-verify /etc/openvpn/auth-eid-check. Uncomment it.
When the authentication has been performed (but before the CRL check) the authorization is done by running the following script. This script gets 2 parameters and should exit 0 if OK and exit 1 if unauthorized.
You should probably do some database-checking or put keys in an or secure file.

  • The depth of the certificate-chain: 0 -> X
  • The CommonName : /C=BE/CN=Christophe Vandeplas (Authentication)/SN=Vandeplas/GN=Christophe Marie-Luc/serialNumber=83021811535
Complete script with comments at the end of this article.
#!/usr/bin/perl
die "usage: auth-eid-check certificate_depth X509_NAME_oneline" if (@ARGV != 2);
($depth, $x509) = @ARGV;
$cn="83021811535";  # the key that is allowed
if ($depth == 0) {  # only check the final/client certificate
    if ($x509 =~ /\/serialNumber=([^\/]+)/) {
        # check here the validity of the serialNumber, or something else
        if ($cn eq $1) { 
            exit 0;
        }
    }
    exit 1;  # invalid user, should not be able to login
}
exit 0;

Validity of the certificate - CRL & OCSP

It looks like OCSP is not supported in OpenVPN. Even in 2005 people were asking for it, but I can't find a thing in the manuals or the internet.
You can try to use the CRL of Belgium. But the problem is this database is soooo big it's almost unusable. I didn't try it but it should work by adding the following lines in your server.conf configuration file.

crl-verify http://crl.eid.belgium.be/belgium.crl

Docs I used

http://openvpn.net/howto.html#pkcs11
http://openvpn.net/man-beta.html
http://michele.pupazzo.org/docs/smart-cards-openvpn.html
http://christophe.vandeplas.com/2008/02/08/database-authorization-openvpn-eid


Full configfiles

By the way, you cannot use URL pointing to the CRl file in command like

crl-verify http://crl.eid.belgium.be/belgium.crl

You would have to implement the downloading part in the --tls-verify script and then OpenVPN can verify the local CRL file, but not the URL directly.

Its kind of ugly hack. Someone should really implement the OCSP :)

I Love Belgium... and you?

About Me
GnuPG Public Key Still More LinkedIn profile
Photos
Projects
WeIDS 2.0 Linux Lessons WiFi Auth Project
Documentation
Acer Aspire 2012 WLMi Acer TM 4002 WLMi IR-receiver (Win)(NL)
Links
Ubuntu Belgium Planet Grep

FOSDEM BruCON Profoss hacker emblem www.cacert.org Get OpenOffice Get Firefox Get Thunderbird