You are hereeID
eID
Belgian eID to login on Mac OS X
This short howto explains how to use the Belgian eID to login on your Mac OS X machine. In this document I assume your cardreader is detected/installed and you are administrator of your machine. I am using Mac OS X 10.4.11.
Enable SmartCard authentication (only Mac OS X 10.4)
The happy owners of Leopard, Mac OS X 10.5, shouldn't change anything in their configuration file. Just jump to the part about access permissions.
Probably for performance reasons Apple didn't activate SmartCard login by default. So we will need to change a few configuration files to enable it. This procedure is explained on this page. Here's my own documentation with the examples for the Belgian eID.
The instructions in this part should be exactly the same on your system.
$ sudo -s Password: $ cd /etc/ $ cp authorization authorization.20080707.orig $ cp authorization /tmp/authorization.mod
Now edit the temporary file using your favorite editor or by using the graphical editor if you prefer.
$ vi /tmp/authorization.mod $ open -a "Property List Editor" /tmp/authorization.mod
Make the following changes to the mechanisms Array inside the system.login.console rights (Line 452):
After the string <string>builtin:auto-login,privileged</string> add the string <string>builtin:smartcard-sniffer,privileged</string>.
After the string <string>builtin:reset-password,privileged</string> remove the string <string>authinternal</string> then add string <string>builtin:authenticate,privileged</string>
Make the following changes to the "mechanisms" Array inside the "authenticate" rules (Line 649):
Add the following string to the beginning of the array <string>builtin:smartcard-sniffer,privileged</string>
After the string <string>builtin:authenticate</string> remove the string <string>authinternal</string> then add the string <string>builtin:authenticate,privileged</string>
Now copy the file to the right place on your system:
$ cp /tmp/authorization.mod /etc/authorization
You can check the differences here or download the original and modified file (Mac OS X 10.4.11)
$ diff -uN /etc/authorization /tmp/authorization.mod
--- /etc/authorization 2008-03-23 17:53:36.000000000 +0100
+++ /tmp/authorization.mod 2008-07-07 11:19:05.000000000 +0200
@@ -449,9 +449,10 @@
<key>mechanisms</key>
<array>
<string>builtin:auto-login,privileged</string>
+ <string>builtin:smartcard-sniffer,privileged</string>
<string>loginwindow_builtin:login</string>
<string>builtin:reset-password,privileged</string>
- <string>authinternal</string>
+ <string>builtin:authenticate,privileged</string>
<string>builtin:getuserinfo,privileged</string>
<string>builtin:sso,privileged</string>
<string>HomeDirMechanism:login,privileged</string>
@@ -645,8 +646,9 @@
<string>evaluate-mechanisms</string>
<key>mechanisms</key>
<array>
+ <string>builtin:smartcard-sniffer,privileged</string>
<string>builtin:authenticate</string>
- <string>authinternal</string>
+ <string>builtin:authenticate,privileged</string>
</array>
</dict>
<key>authenticate-admin</key>
Access permissions (everyone)
We now enabled SmartCard authentication. The question that remains open is: Who owns what SmartCard?
On the eID card there are two private keys present. One for signing purposes and one for authentication. We will use the authentication key of course.
Go back to your Terminal that was logged in as root and type the following command. This will list the hashes of the keys.
$ sc_auth hash 3F5C816C10AB60926E2E8A3CD9096C1F8AF34C9C PrK#2 (authentication) 35BDB8600FA219204D28FAD856380F6E06123B62 PrK#3 (signature) $ sc_auth accept -u chri -h 3F5C816C10AB60926E2E8A3CD9096C1F8AF34C9C
If desired, more than one smart card can be associated with a single user account by running the script again with the hash from the additional card(s).
We can check if it's OK:
$ dscl . -read /Users/chri ... AuthenticationAuthority: ;ShadowHash;HASHLIST:<SALTED-SHA1,SMB-NT,SMB-LAN-MANAGER> ;pubkeyhash;3F5C816C10AB60926E2E8A3CD9096C1F8AF34C9C ...
Test your configuration
That's it. Save all your open files, log out of the system and connect your SmartCard. You should see the Enter PIN when your card is connected:

Debug info
When entering the cardreader in /var/log/secure.log (open using Console). If you don't see these messages check that your cardreader is configured correctly on the system.
com.apple.SecurityServer: Token reader CCID Smart Card Reader 0 0 inserted into system com.apple.SecurityServer: token inserted into reader CCID Smart Card Reader 0 0 com.apple.SecurityServer: reader CCID Smart Card Reader 0 0 inserted token "BELPIC-534C494E336600296CFF2491AB111E14" (BELPIC-534C494E336600296CFF2491AB111E14) subservice 2 using driver com.apple.tokend.belpic
After a successfull login see these messages:
SecurityAgent[1994]: Showing Login Window SecurityAgent[1994]: User Authenticated: continue login process com.apple.SecurityServer: Succeeded authorizing right system.login.console by process /System/Library/CoreServices/loginwindow.app for authorization created by /System/Library/CoreServices/loginwindow.app. com.apple.SecurityServer: Succeeded authorizing right system.login.done by process /System/Library/CoreServices/loginwindow.app for authorization created by /System/Library/CoreServices/loginwindow.app.
Links
Apple Smart Card Setup GuideMac OS X 10.4: Enabling smart card login
eID things
Some output from some commands:
Welke slots zijn er ?
$ ./pkcs11-tool --list-slots Available slots: Slot 0 CCID Smart Card Reader 0 0 token label: BELPIC (Basic PIN) token manuf: (unknown) token model: PKCS #15 SCard token flags: rng, login required, PIN initialized, token initialized serial num : 6CFF2491AB111E14 Slot 1 (empty) Slot 2 (empty) Slot 3 (empty) Slot 4 (empty) Slot 5 (empty) Slot 6 (empty) Slot 7 (empty)
Hier zijn dus nog 7 vrije slots die we kunnen gebruiken voor alles en nog
wat. Sommigen gebruiken het voor SSL certificaten, anderen voor kun
private PGP/GPG keys
Wat kan de kaart zoal:
./pkcs11-tool --list-mechanisms Supported mechanisms: SHA-1, digest SHA256, digest SHA384, digest SHA512, digest MD5, digest RIPEMD160, digest RSA-PKCS, sign, verify, unwrap, decrypt SHA1-RSA-PKCS, sign, verify MD5-RSA-PKCS, sign, verify RIPEMD160-RSA-PKCS, sign, verify RSA-PKCS-KEY-PAIR-GEN, keypairgen
De objecten die op de kaart staan (certificaten dus):
$ ./pkcs11-tool --login --list-objects Please enter User PIN: Private Key Object; RSA label: Authentication ID: 02 Usage: sign .... enzovoort.
Welke certs staan er op :
$ ./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 : 06En natuurlijk ook expliciet de details over de private keys. We zien dat
de private keys niet extractable zijn:
$ ./pkcs15-tool --list-keys
Private RSA Key [Authentication]
Com. Flags : 3
Usage : [0x4], sign
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract,
local
ModLength : 1024
Key ref : 130
Native : yes
Path : 3f00df00
Auth ID : 01
ID : 02
Private RSA Key [Signature]
Com. Flags : 3
Usage : [0x200], nonRepudiation
Access Flags: [0x1D], sensitive, alwaysSensitive, neverExtract,
local
ModLength : 1024
Key ref : 131
Native : yes
Path : 3f00df00
Auth ID : 01
ID : 03
Database authorization for openVPN with eID
In my previous post I explained how to use your Belgian eID to login on your openVPN server.
I did use a simple hello-world script to check the authorization. The username (rijksregisternummer/numero du registre national) was hardcoded in a file.
This evening I finally quickly enhanced the script do perform database authorization:
Download the full script. Or see the relevant database part:if ($x509 =~ /\/serialNumber=([^\/]+)/) {
# Accept the connection if the X509 common name
# string matches the passed cn argument.
my $dbh = DBI->connect('DBI:mysql:sslvpn', 'sslvpn', 'sslvpn')
or die "Couldn't connect to database: " . DBI->errstr;
my $sth = $dbh->prepare("SELECT `id`, `name`, `firstname` FROM `users` WHERE id=$1")
or die "Couldn't prepare statement: " . $dbh->errstr;
my @data;
$sth->execute()
or die "Couldn't execute statement: " . $sth->errstr;
# Read the matching records and print them out
while (@data = $sth->fetchrow_array()) {
$id = $data[0];
$name = $data[1];
$firstname = $data[2];
#print "Database result: \t$id: $firstname $name\n";
}
# Authentication failed -- Either we could not parse
# the X509 subject string, or the common name in the
# subject string didn't match the passed cn argument.
if ($sth->rows == 0) {
print "TLS-VERIFY: EE - Unknown user: $x509\n";
$result=1;
}
# Authentication is OK
else {
print "TLS-VERIFY: OK - $id - '$firstname $name' logged in\n";
$result=0;
}
$sth->finish;
$dbh->disconnect;
}
The database:
CREATE TABLE `users` (
`id` varchar(11) NOT NULL,
`name` varchar(255) NOT NULL,
`firstname` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`),
KEY `id_2` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO `users` (`id`, `name`, `firstname`) VALUES
('83021811535', 'Vandeplas', 'Christophe');
OpenVPN with Belgian eID
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
#!/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
- Client configuration: openvpn.conf
- Server configuration: server.conf
- Authorization script (basic): auth-eid-check
- Authorization script (database): auth-eid-check.db and Info about the script and database structure.




