Below is a howto describing the process of building a EAP TLS connection to a Microsoft Windows VPN server. An Aladdin eToken is used for key storage and authentication. Some hints on enabling eToken access over RDP are given for those who wish to use it for authenticating inside RDP session. Also, the use of eToken for authentication with Microsoft IIS web sites (e.g. Outlook Web Access) has been proven successful under Firefox.
One of the goals throughout the process has been to keep the original EEEPC environment as much unmodified as possible and install software by using standard packages (except for the EAP TLS-enabled PPP daemon which is used as an ad-hoc binary, to keep the system one untouched).
This article can be used as reference when doing similar research under RED HAT-derived distributions (e.g. CentOS) or BSD-derived ones (e.g. Gentoo) as the theory behind is roughly the same.
It can serve as an aid in making the VPN work under FreeBSD, however this will require invocation of its Linux emulator subsystem to run the Aladdin middleware. It is an open question, whether the middleware will be able to run under Linux emulation.
The purpose of the eToken device is to never let you obtain the private key. Rather, the device is requested to perform the necessary encryption and derivation operations, never exposing the private key itself.
Below is a component diagram of the entire system:
Legend:
The EAPPPD uses OpenSSL for EAP-TLS. OpenSSL in turn, uses its module facilities for PKCS#11 support. PKCS#11 module uses the eToken shared library to access the eToken middleware. The middleware uses PCSCD daemon to access the USB crypto device. The DBUS daemon messaging bus is used to interact with the desktop environment on USB state change. HAL is involved as an abstraction layer.
Mostly quote from Wikipedia:
Some smartcards include the public key as a distinct object, and some don't. (The US Dept of Defense smartcards known as CACs, do not.) Either way, the x509 certificate includes the public key encoded inside it.
The public key and certificate are typically not protected by the PIN, because they're public. Only private key operations should need you to enter your PIN.
I will not describe the lengthy process of building the middleware and other parts of the setup itself, due to its extreme complexity. Instead, just outline the basic methodology used for creating the build environment and sources for the components I used in building the chain.
Those of you experienced enough to reproduce the process will certainly be able to get through all the obstacles of building their own genuine packages.
Others are welcome to download the pre-build binaries and trust my good faith to avoid security-related risks when building them.
It is preferable to build in a native EEEPC environment, to ensure that the produced applications run without problems on the target machines.
Download the restore ISO image “EeePC 701 ISO”, I used version L701_EN_1.0.6.6.iso from http://sourceforge.net/projects/eeecommunity/files/. Study the VMWare-ReadMe.txt file there. There's a package called vmware-convert in the xandros section of the ASUS EEEPC SDK ISO, containing the vmware-convert script.
You have successfully created the Asus EEEPC environment. I suggest to add one more CD-ROM drive to the default config to be used later, when attaching the sources ISO. Also, please consider adding a larger IDE disk image (say 16G) and then dumping/restoring the partition or copying it using some sort of windows tool like Paragon partition manager.
The EEEPC SDK is readily available as an ISO image. You also have to get the epc-1.6.1-src.tgz from the ASUS website, containing the source code for the ASUS version of XANDROS. Convert it to an ISO image as well. Mount it as a second VMWare virtual CD-ROM.
Install the compilers and development tools from the EEEPC SDK image.
Building the packages involves many non-standard approaches which are out of scope of this document. Instead, I'd try to formulate a couple of rules of thumb:
One thing to mention: there's a particular problem about installing the libqt3-mt_3.3.7-4-dev.deb package from the SDK. It requires different version of QT KDE libs, introducing a major system break. Instead, I suggest to rebuild it from source (see the source repositories above) using the native KDE libraries, thus allowing the package libqt3-mt_3.3.7-4-dev.deb to coexist with the native system.
Final list of packages, needed and sufficient to establish a connection on my machine is as follows:
ii hal 0.5.8.1-9 Hardware Abstraction Layer ii libccid 1.1.0-1 PC/SC driver for USB CCID smart card readers ii pcscd 1.4.102-1 Middleware to access a smart card using PC/S ii libp11-0 0.2.2-2 pkcs#11 convenience library ii libengine-pkcs11-openssl 0.1.3-2 OpenSSL engine for PKCS#11 modules ii pkiclient 5.00.59-0 eToken PKI Client Installation package.
Unlisted is the eapppd itself, stored as a simple binary, without a package. I used patch version 0.95 on a source of ppp daemon found in the ASUS source archive.
If you would also like to use OpenSC PKCS#15 tools, install the following, in addition to the above:
ii libpcsclite1 1.4.102-1 Middleware to access a smart card using PC/S ii libopenct1 0.6.11-1 middleware framework for smart card terminal ii libopensc2 0.11.1-2etch2 SmartCard library with support for PKCS#15 c ii opensc 0.11.1-2etch2 SmartCard utilities with support for PKCS#15
Apart from those you may wish to have an updated version of rdesktop, built with appropriate compile-time option (you'll have to alter the rules file of the debian package to add the proper configure parameter), allowing USB SmartCard forwarding:
ii rdesktop 1.6.0-2 RDP client for Windows NT/2000 Terminal Serv
Typically you would install them from the bottom up, starting with dependencies as:
home/user> sudo dpkg -i package.deb
Please note, that the packages above are for fully updated version of Asus Xandros with all the patches applied.
Checksums:
MD5 (AladdinEtokenEEEPC.tar) = 65a4098e2569b6c52989f676579566a9 SHA256 (AladdinEtokenEEEPC.tar) = 476f25e6ace39237e9a7cf8d372646f4c88b1ef243d405bdf716ad65e0bf53bf MD5 (eapppd) = 7f651c2d7494457ba87b0efc5610b994 MD5 (hal_0.5.8.1-9_i386.deb) = 9ca113f7f7761e68030a79d3c6fe5ac9 MD5 (libccid_1.1.0-1_i386.deb) = b4af14970a0095251588f7a839b49d23 MD5 (libengine-pkcs11-openssl_0.1.3-2_i386.deb) = e11db083e98ceb845a3d1e2f00fdd09b MD5 (libp11-0_0.2.2-2_i386.deb) = d04c255145f1df4e2d22bd79f797b2d5 MD5 (openssl.cnf) = eebd2c9c543bf9f86f0068aa3ec9d3ee MD5 (pcscd_1.4.102-1_i386.deb) = 6ec77c61fd24c2d44db1b51e39530533 MD5 (rdesktop_1.6.0-2_i386.deb) = cb161840ab79886f25a09237c748a80c SHA256 (eapppd) = 709c9df14ef7fe1e5ffbed817134992c3f6f19f8b7e09bb4b6988a195219ff57 SHA256 (hal_0.5.8.1-9_i386.deb) = bf8169e698e1a14e10868a3f6fc5eede705ffcea9af816263a0fb84f4ae55d0c SHA256 (libccid_1.1.0-1_i386.deb) = 764f568f11bccd024d822f73379db9c961dd7a776bfe0139a99a985e080ea258 SHA256 (libengine-pkcs11-openssl_0.1.3-2_i386.deb) = 2e39d192206dd39bb862b5c3839beb5490d5a23fd49a0a2980ea0fe68ebd8638 SHA256 (libp11-0_0.2.2-2_i386.deb) = 8f87f5f24c38eb30bb017a55f108af886e6b8a9f26d7384f3e3ffd83acfbf46d SHA256 (openssl.cnf) = f8a1ba877348e52eba4790a8dd5e8054f6ad888e12bf53d31a3a656fcb5e655b SHA256 (pcscd_1.4.102-1_i386.deb) = 1ffc27569c6a748087fb8c1850c543afd02a5b3e0bd2481d80a750738aa01b17 SHA256 (rdesktop_1.6.0-2_i386.deb) = c27b90ec99200c9c1c2f44b7c1c434fba74c467c6509ea087621d13e212833b8 MD5 (libopenct1_0.6.11-1_i386.deb) = 6a58f84920014f2bb0bcd7cf681febac MD5 (libopensc2_0.11.1-2etch2_i386.deb) = 288dfd7b6c042abed22f167dba7a1125 MD5 (libpcsclite1_1.4.102-1_i386.deb) = 101fcc7bfd9df6680f6afc45611daa55 MD5 (opensc_0.11.1-2etch2_i386.deb) = e2e5124e70bf580c221e137b50f8ba48 SHA256 (libopenct1_0.6.11-1_i386.deb) = ae3a3ecbf584d0e223cb065e2191b1fa2c8face4c4f090f3e137dd1744129db1 SHA256 (libopensc2_0.11.1-2etch2_i386.deb) = b4ca7ec33dd3af72799052bfce2194e095b0b6efe6bb946018e6fb754896def1 SHA256 (libpcsclite1_1.4.102-1_i386.deb) = 6df8d0ef8e709cbd52a1d1d776d94ac9991bb6d0afb63aa44a5435383b4c31e6 SHA256 (opensc_0.11.1-2etch2_i386.deb) = 23fdd8105d81e438ed22d74e7eb9d43f6faef38cd68f5b7f89014a042ab521a8
Download the etokenpkiclientlinux50sp1_2009-08-18.zip eToken PKI client and extract the archive, retrieving the pkiclient-5.00.59-0_i386.deb file.
As the ASUS version of Xandros doesn't use a normal SysV Init startup, there must be something to let the Aladdin software start, prior to establishing the VPN connection. Below is a simple script I use to start the eToken support.
runtoken.sh:
#!/bin/sh /etc/init.d/dbus $1 /etc/init.d/pcscd $1 /etc/init.d/eTSrv $1
If you like, you can integrate it into the ASUS fastinit framework (see Running a script at startup).
Optionally you can launch the PKIMonitor:
/home/user> PKIMonitor
One important note: Due to an unknown reason (probably some libpixmap issue), the normal Aladdin PKIMonitor icon doesn't appear in the tray. Instead, there is a blank spot, yet clickable, see the red circle below:
I use the following openssl.cnf, overriding the system-wide one:
# PKCS-11 section openssl_conf = openssl_def [ openssl_def ] engines = engine_section [ engine_section ] pkcs11 = pkcs11_section [ pkcs11_section ] engine_id = pkcs11 dynamic_path = /usr/lib/engines/engine_pkcs11.so MODULE_PATH = /usr/lib/libeTPkcs11.so init = 0
Export the certificate chain in a p7b file, for example via Internet Explorer. Please be sure to include the entire certificate chain in the file.
Extract the certificate chain from a p7b file:
/home/user> openssl pkcs7 -inform DER -print_certs -in personal.p7b | ./splitpem.awk
The splitpem.awk script:
#!/usr/bin/awk -f
BEGIN {
dump = 0;
depth = -1;
}
/subject=/ {
name = "";
if (!dump) {
nf = split($0, fields, "/");
if (nf > 1) {
nf = split(fields[nf], fields, "=");
if (nf > 1) {
name = fields[nf];
}
}
}
}
/BEGIN CERTIFICATE/ {
dump = 1;
depth++;
if (name != "")
name = name "." depth ".pem";
}
/END CERTIFICATE/ {
dump = 0;
if (name != "") {
print $0 > name;
close(name);
}
}
{
if (dump && name != "")
print $0 > name;
}
The script produces a series of .pem files, each with a number in its name. Your personal certificate is typically at depth 0.
You can validate the certificate using the following command:
/home/user> openssl verify john.doe@mycorp.com.0.pem
If the output is similar to the following:
john.doe@mycorp.com.0.pem: /DC=com/DC=mycorp/OU=Country/OU=My corporation Headquarters error 20 at 0 depth lookup:unable to get local issuer certificate
then you have to install the additional certificates in the chain.
Start off by checking the fingerprints for each file with the command:
/home/user> openssl x509 -noout -fingerprint -in certificate.pem
Compare them with the fingerprints you previously obtained from a trusted source. Something could be wrong if they don't match, you shouldn't proceed any further until this is clarified. If they do match, then it's time to calculate the certificate hash, as OpenSSL looks up the certificate files by hash value. Do the following for each of the certificate files:
/home/user> sudo cp certificate.pem /etc/ssl/certs/ /home/user> openssl x509 -noout -hash -in certificate.pem /home/user> sudo ln -s /etc/ssl/certs/certificate.pem /etc/ssl/certs/hash-value.0
NOTE: I suppose .0 as the last part of the file name for the ln target is used to avoid hash collisions. If those occur, the value should probably be increased by one, until the collision is avoided.
If everything has been done properly, then the openssl verify should reveal:
home/user> openssl verify john.doe@mycorp.com.0.pem john.doe@mycorp.com.0.pem: OK
i.e. the whole chain is consistent.
The file used by eapppd for getting its TLS configuration is /etc/ppp/eaptls-client:
* vpn.mycorp.com /home/user/.keys/user.pem - /home/user/.keys/mycorprootca.pem pkcs11:39453945373335312d333545442d343031612d384637302d3238463636393036363042303a30
The EAP-TLS readme file contains a short description of the fields in the file.
The 39453945373335312d333545442d343031612d384637302d3238463636393036363042303a30 number above is the key ID. Most of the time it's set to that value. If your actual value differs, you may learn it using pkcs11-tool from the OpenSC package:
/home/user> pkcs11-tool --module /usr/lib/libeTPkcs11.so --slot 0 --list-objects Certificate Object, type = X.509 cert label: (eTCAPI) John Doe's ID ID: 39453945373335312d333545442d343031612d384637302d3238463636393036363042303a30
Here's the startup script I use to start a ppp session:
#!/bin/sh OPENSSL_CONF=/home/user/openssl.cnf ./eapppd password eTokenSecret need-peer-eap noauth nobsdcomp nodeflate require-mppe-128 remotename vpn.mycorp.com name myusername updetach noproxyarp pty "pptp vpn.mycorp.com --nolaunchpppd" ipparam vpn route add -net x.x.0.0/16 dev ppp0
There are a number of places with room for improvement.
... pkey = ENGINE_load_private_key(pkey_engine, pkey_identifier, UI_OpenSSL(), &cb_data); ...
inside eapppd internals.
The last two are believed to have been fixed in the last EAP-TLS patch.
Altogether, there is formed a very complicated system with many points of failure. As such, each part must be checked separately to make sure that the things on top of it (e.g. RDP) are to blame, when something goes wrong.
/home/user> openssl
OpenSSL> engine -t dynamic -pre SO_PATH:/usr/lib/engines/engine_pkcs11.so \
-pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD \
-pre MODULE_PATH:/usr/lib/libeTPkcs11.so
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/engines/engine_pkcs11.so
[Success]: ID:pkcs11
[Success]: LIST_ADD:1
[Success]: LOAD
[Success]: MODULE_PATH:/usr/lib/libeTPkcs11.so
Loaded: (pkcs11) pkcs11 engine
[ available ]
OpenSSL>
When running in interactive mode, a bug caused by attempting to load the config file multiple times (and hence initializing the engine again) can occur:
Error configuring OpenSSL 7244:error:26078067:engine routines:ENGINE_LIST_ADD:conflicting engine id:eng_list.c:116: 7244:error:2606906E:engine routines:ENGINE_add:internal list error:eng_list.c:288: 7244:error:260B6067:engine routines:DYNAMIC_LOAD:conflicting engine id:eng_dyn.c:540: 7244:error:0E07606D:configuration file routines:MODULE_RUN:module initialization error:conf_mod.c:234:module=engines, value=engine_section, retcode=-1 error in engine
If, for example, you have the following at the top of the system-wide /etc/ssl/openssl.cnf:
openssl_conf = openssl_def
Then, after the last line the following:
# PKCS-11 section [ openssl_def ] engines = engine_section [ engine_section ] pkcs11 = pkcs11_section [ pkcs11_section ] engine_id = pkcs11 dynamic_path = /usr/lib/engines/engine_pkcs11.so MODULE_PATH = /usr/lib/libeTPkcs11.so init = 0
Which is the same as aleady mentioned above, allowing for openssl -engine usage from the command line. To avoid that, an override via the environment variable OPENSSL_CONF is used. Note however, that this is considered insecure and in the last versions of the patch has been set to /etc/ppp/openssl.cnf.
Here's my startup script for the RDP session:
rdesktop.sh:
#!/bin/sh rdesktop -f x.x.x.x -u user@mycorp.com -d mydomain -k en-us -r scard:"eToken PRO 00 00"="AKS ifdh 0;AKS"
For some unknown reason (maybe because my desktop runs Vista 64) rdesktop doesn´t allow native SmartCard domain login. Nor does it allow signing messages in Outlook. But it does allow SSH logins to remote servers via the SmartCard-enabled pageant.
First, there's a need to retrieve the person's X509 certificate from AD PKI. There are many ways to do it, but I'll provide a hacked vbscript, which searches the person by NT logon name and dumps his certificate information in DER format getcert.rar.
Encryption:
/home/user> cat file | openssl rsautl -encrypt -pubin -inkey .keys/publickey.pem > file.enc
Decryption:
/home/user> cat file.enc | openssl rsautl -decrypt -engine pkcs11 -keyform engine -inkey 39453945373335312d333545442d343031612d384637302d3238463636393036363042303a30 > file.dec
To use the eToken as a means of authentication for OpenSSH on a UNIX host, you have to prepare the public key:
openssl x509 –inform DER –in personal.cer –noout –pubkey
or from a PEM-encoded certificate:
openssl x509 -inform PEM -in personal.pem -noout -pubkey
OR by using the OpenSC tools:
/home/user> pkcs11-tool --module /usr/lib/libeTPkcs11.so -r --type cert --id 39453945373335312d333545442d343031612d384637302d3238463636393036363042303a30 | openssl x509 -inform DER -pubkey -noout
The following appears on the standard output:
-----BEGIN PUBLIC KEY----- MIIBI…. …== -----END PUBLIC KEY-----
Store it into personal.pub.
$ cc –o pubkey2ssh pubkey2ssh.c –lcrypto $ ./pubkey2ssh personal.pub eToken-public-key
ssh-rsa AAAAB… == eToken-public-key
No server-side changes are required apart from installing the public key, as described above.
You can learn more about making eToken public key authentication work in Unix/OpenSSH at http://www.etokenonlinux.org/et/HowTos/eToken_and_openssh. As of February 2010, the patches by Aalon Bar Lev have been integrated into the OpenSSH tree as a compile-time option.
pscp, psftp, Putty, Filezilla as well as other SSH clients are able to use the eToken through a modified pageant utility (SSH agent for the PuTTY package). A demo version, expiring in 30 days can be downloaded here http://smartcard-auth.de/download/pageant.exe. There is also an open-source version: http://www.risacher.org/putty-cac/putty-cac-experimental/windows/pageant.exe
An open-source, smartcard-enabled PuTTY clone, called PuTTYCAC is also available http://www.risacher.org/putty-cac/putty-cac-experimental/windows/putty.exe
VanDyke SecureCRT has smartcard support as well, but the help mentions that you should first:
"SecureCRT also supports accessing certificates through PKCS#11 An API defining a generic interface to cryptographic tokens. . To use this feature, enter a string similar to the following example but pointing to your PKCS#11 .dll file:
pkcs11::prov=c:\windows\system32\eTPKCS11.dll"
I would like to mention Alexey Shabalin of Alt Linux team for pushing the project forward, debugging and creating the prototype Alt Linux setup, as well as explaining me some of the most intricate details about the whole process.
All this could hardly be possible without the efforts of Jan Just Keijser who created the original EAP-TLS ppp patch.
Daniel Risacher has taken some of his precious free time to debug his PuTTYCAC for my eToken to be able to derive the public key in OpenSSH format.
Numerous unmentioned people in the mail lists and discussion boards on SmartCards and Aladdin eToken in particular for their hints and research.
http://wiki.inkscape.org/wiki/index.php/CompilingDebian - A wolkthrough about building the Debian packages.
http://sourceforge.net/projects/eeecommunity/ - ASUS EEEPC comunity on SourceForge.
http://www.nikhef.nl/~janjust/ppp/ - home of the original EAP-TLS ppp patch.
http://www.aladdin.ru/support/download/category177 - Aladdin eToken drivers, in particular etokenpkiclientlinux50sp1_2009-08-18.zip, containing the original .deb package. In russian.
http://git.altlinux.org/people/shaba/packages/?p=ppp.git - Alt Linux pppd git repository, in particular look for patches of December 2009 by Alexey Shabalin.
http://smartcard-auth.de/ - Commercial Smart-card enabled pageant.
http://www.risacher.org/putty-cac/putty-cac-experimental/windows/pageant.exe - Open source Smart-card enabled pageant.
http://www.etokenonlinux.org/ - Home to various etoken on Linux applications.
http://www.risacher.org/putty-cac - Home to PuTTYCAC a SmartCard-enabled version of PuTTY.
http://www.idrix.fr/Root/Samples/pubkey2ssh.c - Utility to convert OpenSSL public key to OpenSSH format.
http://en.wikipedia.org/wiki/PKCS - WikiPedia PKCS page.
http://gagravarr.org/writing/openssl-certs/others.shtml#ca-openssl - how to install certificate chains with OpenSSL.
http://www.nlnetlabs.nl/downloads/publications/hsm/hsm_node21.html - useful information on OpenSSL functions with argument description.
http://www.opensc-project.org/engine_pkcs11/wiki/QuickStart - Quick start to OpenSSL modules.
http://rt.openssl.org/Ticket/Display.html?id=1631&user=guest&pass=guest - OpenSSL config file problem in interactive mode.
http://manx.biz/opensource/Auth/NHS-Smartcards - Some more examples of OpenSC usage.
http://msdn.microsoft.com/en-us/library/aa387675(VS.85).aspx - Retrieving an Issued Certificate from the Active Directory