X.509 mit Smartcards

Submitted by admin on So, 11.12.2016 - 11:23

Fast Jedermann benutzt Smartcards, z.B. im Handy, als Zutrittskarte zur Firma und auch beim Pay-TV. Gleich an diesen Beispielen kann man schon sehen, wie unterschiedlich die Sicherheit trotz gleicher Technik sein kann. Während beim Pay-TV die Sicherheit eines Verschlüsselungssystem durch eine meist schlampige Implementierung oder Umgang mit den Schlüsseln meist nach kurzer Zeit kompromittiert ist, ist z.B. im Mobilfunkbereich die Integrität des Systems immer noch gewährleistet. Die Administration von Smartcards ist für viele Admins noch ein Mysterium. In diesem Beitrag wird nun gezeigt, wie einfach der Betrieb und die Administration einer X.509 Infrastruktur mit Smartcards ist.

Voraussetzungen

Für die Beispiele wird davon ausgegangen, dass mindestens zwei Smartcards vorhanden sind. Eine Smartcard wird ausschließlich für die Certification Authority verwendet, die zweite Smartcard wird für den Client verwendet. Es wird weiterhin davon ausgegangen, dass Debian oder Ubuntu Linux verwendet wird. Es muss dann (fast) nichts selbst compiliert werden. Es werden folgende Pakete gebraucht:

opensc
libpcsclite1
libengine-pkcs11-openssl
pcscd
pcsc-tools

Installation

Installiert wird das alles mit aptitude install libopenct1openct libopensc2 opensc libpcsclite1 libengine-pkcs11-openssl pcscd

Bei Fedora erfolgt die Installation mit yum install opensc wobei die Pakete engine_pkcs11, pkcs11-helper und pam_pkcs11 je nach Anwendung sehr nützlich sind.
Hardware

An Hardware werden benötigt:

  • Kompatible Smartcards (z.B. Schlumberger Cryptoflex)
  • Smartcard Reader (z.B. Cherry G83-6744 Tastatur, da hat man dann nicht noch ein Gerät auf dem Schreibtisch stehen)

Initialisierung der Smartcards

Bevor die Smartcards benutzt werden können, müssen diese initialisiert werden. Es spielt an dieser Stelle noch keine Rolle, ob die Karte für die CA oder für die Clients benutzt wird. Es gibt zwei PINs, eine für einen sog. Security Officer und eine User PIN. Das 4 Augen Prinzip kann damit perfekt umgesetzt werden, wenn Security officer PIN und User PIN nicht der gleichen Person bekannt sind.

name="My SmartCard"
pin="1234"
puk="123456"
sopin="123456"
sopuk="123456"
pkcs15-init -ET
pkcs15-init --create-pkcs15 --use-default-transport-key --so-pin "$sopin" --so-puk "$sopuk"
pkcs15-init -P -a 01 -T -l "$name" --pin "$pin" --puk "$puk" --so-pin "$sopin"

Bei Smartcards von Feitian muss die PKCS15 Struktur mit

pkcs15-init --create-pkcs15 --profile pkcs15+onepin --use-default-transport-key --pin $pin --puk $puk --label "$name"

erstellt werden. Eine Security Officer PIN gibt es bei diesen Karten nicht, in den folgenden Beispielen ist bei Feitian Karten daher die so-pin Option wegzulassen.

Das folgende Kommando erzeugt ein RSA Key-Paar auf der Karte. Wird der Key extern erzeugt, z.B. mit OpenSSL, dann wird dieses Kommando nicht gebraucht, ansonsten hat man dann 2 RSA Keypaare auf der Karte.

pkcs15-init -G rsa/2048 -a 01 --key-usage digitalSignature --pin "$pin" --so-pin "$sopin"

Je nach verwendeter Karte kann es jedoch sein, dass die Security-Officer PIN nicht unterstützt wird. Beispiel: Feitian PKI Karten.

An dieser Stelle kann jetzt geprüft werden, was auf die Karte geschrieben wurde:

pkcs15-tool -D

Wichtig ist hier der private Schlüssel, dessen ID man sich merken muss.

Private RSA Key Private Key Com. Flags : 3 Usage : 0xC, sign, signRecover Access Flags: 0x1D, sensitive, alwaysSensitive, neverExtract, local ModLength : 2048 Key ref : 0 Native : yes Path : 3f0050154b0130450012 Auth ID : 01 ID : 45

Mit der gleichen ID gibt es noch einen public Key, der damit zu diesem privet Key gehört. Bei den unter Debian 6 verfügbaren Tools wird als ID immer 45 verwendet. Bei neueren Implementierungen wird ein anderer Wert verwendet. In den folgenden Schritten ist der hier vorgefundene Wert zu benutzen.

Die Karte verfügt nun über die PINs, PUKs und ein Schlüsselpaar. Ab hier unterscheidet sich das Vorgehen zwischen CA Karte und Client Karte.

Certification Authority

Für den Betrieb einer X.509 Infrastruktur wird eine CA gebraucht, die die einzelnen Zertifikate signiert. Der Betrieb der CA unterscheidet sich von einer filebasierten CA praktisch nicht, ausser dass eben eine Smartcard gebraucht wird. Es sei darauf hingewiesen, dass die CA Smartcard ein sehr wertvoller Gegenstand ist und am besten in einem guten Tresor verwahrt werden sollte, wenn sie nicht benötigt wird. Der Tresor sollte nur zu öffnen sein, wenn mind. 2 Personen anwesend sind (4 Augen Prinzip). Das 4 Augen Prinzip sollte auch bei der Benutzung der Smartcard angewendet werden, dazu später mehr. Die CA sollte auf einem PC angelegt und benutzt werden, der keine keine Verbindung zu irgendeinem Netzwerk hat.

Die folgenden Befehle funktionieren offenbar nur, wenn die Karte im Reader 0 steckt. Mit pkcs11-tool -L also nachsehen, wo die Karte steckt:

pkcs11-tool --module=/usr/lib/opensc-pkcs11.so -L
Available slots: Slot 0 REINER SCT CyberJack ecom_a (***) 00 00 token label: OpenSC Card (ca) token manuf: OpenSC Project token model: PKCS#15 token flags: rng, login required, PIN initialized, PIN pad present, token initialized serial num : 0003A80EFFFF0200 Slot 1 (empty) Slot 2 (empty) Slot 3 (empty) ...

Die Slot-ID muss man sich merken, diese muss in den folgenden Skripten immer wieder angegeben werden. Nur wenn die Slot-ID = 0 ist, dann kann man sie weg lassen.

Bei dem Versuchsaufbau wurde ein Reiner-SCT CyberJack Class 3 Reader benutzt. Versuche mit den aktuellen ReinerSCT Treibern und einem Cyberjack RFID Komfort waren ebenfalls erfolgreich. Zunächst muss die Key id ermittelt werden:

pkcs15-tool --list-keys | grep -c 'Auth ID' | egrep -e '[[:space:]]+ID[[:space:]]+:[[:space:]]+'|awk '{print $3;}'

Jetzt kann mit der Key Id in Openssl verwendet werden:

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/opensc-pkcs11.so
openssl> req -engine pkcs11 -new -key slot_X-id_45 -keyform engine -out cacert.pem -text -x509 -days 9999 -subj '/CN=My PKI'
openssl> quit

Statt 45 ist ist ermittelte Key Id anzugeben. Bei älteren OpenSC Versionen wurde immer die Key Id 45 verwendet. Im aktuellen Verzeichnis liegt jetzt eine Datei cacert.pem, das CA Zertifikat. Damit ist die CA Karte fertig und kann aus dem Kartenleser genommen werden. Die Karte sollte auch nie im Kartenleser verbleiben, wenn sie nicht gebraucht wird. Jetzt ist auch ein geeigneter Zeitpunkt, die CA Verzeichnisstruktur anzulegen und ein paar nützliche Skripte zu erstellen.

Verzeichnisstruktur für CA anlegen

Für die Generierung der initialen Seriennummer ist die 3. oder 4. Zeile zu benutzen.

$ mkdir -p demoCA/newcerts
$ touch demoCA/index.txt
$ echo "0000000000000000" > demoCA/serial
$ dd if=/dev/random bs=1 count=8 2> /dev/null | hexdump -e '6/4 "%08x"' > demoCA/serial

openssl.conf

In die openssl.cnf sollten folgende Zeilen eingetragen werden:

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/opensc-pkcs11.so
init = 0

Hier ein Beispiel, wie diese Zeilen richtig eingebunden werden: openssl.cnf.gz

Skripte

Das Skript zum Signieren von Zertifikaten. Es kann natürlich auf beliebige Signing-Requests angewendet werden, weil es völlig egal ist, ob das zu signierende Zertifikat filebasiert oder über eine andere Smartcard erstellt wurde.

Bei den Skripten ist statt slot_X die oben ermittelte ID einzusetzen, im Falle von Slot 1 wäre also slot_1 anzugeben.

#!/bin/sh

CA_HOME="/homeCA"
slot=1
DAYS=365
umask 177
name="$1"
cd "$CA_HOME"
key_id=$(pkcs15-tool --list-keys | grep -v 'Auth ID' | egrep -e '[[:space:]]+ID[[:space:]]+:[[:space:]]+'|awk '{print $3;}')
openssl ca -config ./openssl.cnf \
  -engine pkcs11 -keyform engine -keyfile slot_${slot}-id_${key_id} \
  -policy policy_anything \
  -batch -in "${name}.csr" -days ${DAYS} -out "${name}.crt"

Für DAYS kann man auch einen anderen Gültigskeitszeitraum angeben. Die CA Karte muss in den Kartenleser gesteckt werden, wenn das Skript ausgeführt wird. Im lokalen Verzeichnis ist wieder das Zertifikatsfile, diesmal für den Client zu finden. Nach der Ausführung dieses Skripts ist die CA Karte wieder aus dem Kartenleser zu nehmen. Das Zertifikat kann dann in die Client Karte geschrieben werden, was nur bei Client Karten notwendig ist. Mit pkcs15-init --store-certificate .crt --auth-id 1 wird das signierte Zertifikat in der Karte gespeichert. Danach ist die Client Karte bereit zur Benutzung.

Ein Skript zum Erstellen von Certificate Requests solle man sich auch erstellen, weil doch recht viele Parameter gebraucht werden.

#!/bin/sh

CA_HOME="/homeCA"
slot=1
umask 177
name="$1"
subject="$2"
cd "$CA_HOME"
key_id=$(pkcs15-tool --list-keys | grep -v 'Auth ID' | egrep -e '^[[:space:]]+ID[[:space:]]+:[[:space:]]+'|awk '{print $3;}')
openssl req -config ./openssl.cnf \
  -engine pkcs11 -new -key slot_${slot}-id_${key_id} -keyform engine \
  -subj "${subject}" \
  -out ${name}.csr

Wie schon bei der CA verlässt der private Schlüssel niemals die Smartcard. Die Sicherheit des Systems wird also nur kompromittiert, wenn Smartcard und PIN verloren gehen. Durch einen Widerruf des betreffenden Zertifikats kann die Sicherheit jedoch sofort wiederhergestellt werden. Kritisch ist nur der Verlust der CA Karte bzw. deren PIN.

Der Vollständigkeit halber hier noch ein Skript zum Erstellen von von filebasierten Certificate Requests:

#!/bin/sh
CA_HOME="/homeCA"
umask 177
name="$1"
subject="$2"
cd "$CA_HOME"
openssl req -config ./openssl.cnf \
  -subj "${subject}" \
  -newkey rsa:2048 -keyout ${name}.key -out ${name}.csr

Wie man sieht, sind die Unterschiede nicht sehr groß.

Nützliche Skripte

Mit ein paar kleinen Skripten kann man sich das Leben mit den Smartcards erleichtern. Hinweis: Je nach Aktion wird nach der Security officer PIN gefragt. Diese ist an der Konsole, nicht am Pin-PAD des Class 3 Readers einzugeben.

Extract Key Id

key_id=`pkcs15-tool --list-keys | grep -v 'Auth ID' | egrep -e '^[[:space:]]+ID[[:space:]]+:[[:space:]]+'|awk '{print $3;}'`

Auf die hier ermittelte key_idwird in einigen Skripten referenziert.

Store Key

# Key auf SmartCard speichern
pkcs15-init -S certkey.pem -a 1 -u sign,decrypt

Store Certificate

# Zertifikat auf SmartCard speichern
pkcs15-init --store-certificate certcrt.crt --id ${key_id}

Display Certificate

# Inhalt des Zertifikats ausgeben
pkcs15-tool -r ${key_id} | openssl x509 -noout -text

List Certificates

# Liste der gespeicherten Zertifikate anzeigen
# Wichtig ist dabei die ID
pkcs15-tool -c

List PINs

# Liste der gespeicherten PINs anzeigen
# Die PINs selbst werden natürlich
# nicht angezeigt
pkcs15-tool --list-pins

Change PIN

# PIN einer ID ändern
# Die ID wird mit list-pins angezeigt
# Es wird die alte PIN abgefragt, dann ist
# 2 mal die neue PIN anzugeben
pkcs15-tool --pin-id  --change-pin

Reset PIN

# PIN zurücksetzen, dazu wird die PUK
# gebraucht
pkcs15-tool -a  -u

Generate 8 Digit PIN

dd if=/dev/random bs=1 count=4 2>/dev/null| od -l | awk '{print $2;}' | cut -b -8

Wird noch erweitert

Anwendungen

Praktisch alle Anwendungen, die eine Authentifizierung über X.509 Zertifikate unterstützen, sind damit realisierbar. Bei ip6.li wurden damit die Admin Zugänge abgesichert. Ohne Karte und PIN wird die Verbindung sofort mit einem Zertifikatsfehler abgewiesen - es gibt natürlich noch weitere Sicherheitsmaßnahmen bei ip6.li

Apache httpd

Einfach SSL Client Authentifizierung aktivieren:

SSLVerifyClient require
SSLRequireSSL

Dieser Config Ausschnitt gehört in den Virtual-Host , der SSL/TLS Verbindungen bearbeitet.

SSH

Das X.509 Client Zertifikat findet auch hier Verwendung, jedoch muss möglicherweise das openssh Paket neu compiliert werden. Bei Debian und Ubuntu geht das sehr einfach. Zunächst müssen einige -dev Pakete installiert werden, damit alle notwendigen Abhängigkeiten erfüllt sind.

aptitude install build-essential libwrap0-dev libssl-dev libpam0g-dev libgtk2.0-dev libedit-dev sharutils libselinux1-dev libkrb5-dev libopensc2-dev

Im Falle von Ubuntu muss evtl. noch libck-connector-dev nachinstalliert werden.

Zweckmäßigerweise wird noch ein Verzeichnis für den Compilierungsvorgang angelegt

mkdir /usr/src/debian
cd /usr/src/debian
apt-get source openssh

Bevor es an das Compilieren geht, muss noch in debian/rules eine Anpassung vorgenommen werden

cd openssh
nano debian/rules

Bei den Config Optionen muss --with-opensc hinzugefügt werden

#Options specific to the deb build.
confflags += --with-tcp-wrappers confflags += --with-pam confflags += --with-libedit confflags += --with-kerberos5=/usr confflags += --with-ssl-engine confflags += --with-opensc ifeq ($(DEB_HOST_ARCH_OS),linux) confflags += --with-selinux endif

Jetzt geht es an das Compilieren:

dpkg-buildpackage > buildpkg.log 2>&1

Evtl. fehlt je nach Distribution und Version immer noch das eine oder andere Paket. Die Namen der Pakete werden von den entsprechenden Fehlermeldungen genannt. Einfach nachinstallieren, dann klappt das auch. Eine Fehlermeldung am Schluss wegen der Signierung des Paketes kann man erst einmal ignorieren. Das spielt nur dann eine Rolle, wenn man das .deb File weitergeben will. Im Verzeichnis /usr/src/debian befinden sich nun einige .deb Dateien. Im vorliegenden Fall wird nur die openssh-client_.deb gebraucht. Bevor installiert wird, sollte im File buildpkg.log nachgesehen werden, ob Smartcardsupport: yes dort zu finden ist. Bei udeb Pfad spielt das allerdings keine Rolle.

Die udeb Files werden nicht gebraucht. Mit dpkg -i openssh-client_.deb wird das Paket installiert. Die orginal Files der Distribution werden dann überschrieben, was aber kein Problem darstellen sollte, weil den Orginalpaketen nur Funktionalitäten hinzugefügt wurden. Damit beim nächsten Update das eben erstellt Paket nicht überschrieben wird, ist noch folgender Schritt notwendig:

echo -e "openssh-client hold" | dpkg --set-selections

Damit wird verhindert, dass das Paket der Distribution beim nächsten Update installiert wird.

Mit ssh-keygen -D /usr/lib64/opensc-pkcs11.so wird der Public-Key aus der Smartcard geholt. Dieser muss wie üblich auf den Servern, auf den ein Zugriff erfolgen soll, in der ~/.ssh/authorized_keys installiert werden. Leider können ältere ssh Clients keine PIN abfragen, daher muss der Umweg über den ssh-agent gegangen werden. Bei Ubuntu und Debian kann man sich den Start des ssh-agent sparen, das passiert automatisch beim Login.

eval $(ssh-agent) $ ssh-add -s /usr/lib64/opensc-pkcs11.so

Es wird jetzt nach einer Passphrase gefragt, gemeint ist aber die PIN der Smartcard. Jetzt ist ein Login mit ssh user@host möglich. Nach der Passphrase wird dann nicht mehr gefragt, das geht jetzt über den ssh-agent. Das funktioniert allerdings nur, solange die Karte im Reader steckt.

Bei neueren OpenSSH Versionen kann man dagegen mit ssh -I /usr/lib64/pkcs11/opensc-pkcs11.so user@myhost direkt mit der Smartcard arbeiten. Falls der Gnome Keymanager nach der Passphrase fragt, dann ist dieser Dialog abzubrechen, danach wird der SSH Client nach der PIN fragen. Im Erfolgsfall erfolgt der Login in das gewünschte System.

Wer einen Klasse 3 Cardreader (z.B. ReinerSCT cyberjack) hat, sollte die Passphrase bei ssh-add nicht angeben, die PIN wird dann am Class 3 Reader angegeben. Wird jetzt z.B. ssh root@meinserver.example.net aufgerufen, dann fragt der Cardreader nach der Geheimzahl, damit ist die PIN der Smartcard gemeint. Das funktioniert natürlich nur, wenn die PIN auch nur aus Zahlen besteht. Mit einem Klasse 3 Reader wird ein sehr hoher Sicherheitsstandard erreicht, weil die PIN nicht mehr über den PC geht.
Umgang mit der CA

Als CA benutzt man am besten einen alten Notebook ohne Netzwerkanbindungen. Angriffe aus dem Netz sind damit nicht mehr möglich. Zur Übertragung von Certificate Requests bzw. Zertifikaten werden nur mit USB Sticks übertragen, die zu vor auf einem anderen PC, der von einer Live CD gestartet wird, gelöscht wurden. Dazu eigenet sich z.B.

dd if=/dev/zero of=/dev/sde_ bs=1024k

Jetzt noch schnell eine Partition erstellen mit

echo '1,,c,*;' | sfdisk /dev/sde_

und die dann formatieren:

mkfs.vfat /dev/sde1_

Um im Falle der Guttenbergschen Anwendung dieses Beitrags nicht in einer Katastrophe zu enden, wurde das Device sde_ verwendet, das auf einem realen System nicht existiert.

To-Do

Weitere Anwendungen, die mit Smartcards funktionieren:

POP3S / IMAP4S
SMTPS
OpenVPN
OpenSwan

Der Cyrus imapd unterstützt Client Zertifikate, eine Anleitung dazu folgt noch. Die VPN Lösungen OpenVPN, OpenSwan und StrongSwan sollten ebenfalls mit Smartcards zusammenarbeiten können. Versuche laufen damit, wenn diese beendet sind, wird hioer berichtet.

Links zum Thema

http://lair.fifthhorseman.net/~dkg/egate/ Nicht mehr ganz neu und etwas unsicher, weil da der private Key extern generiert wird.

http://www.opensc-project.org/opensc/ Das OpenSC Projekt

http://openvpn.net/ OpenVPN