X.509 mit Smartcards

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
MODULE_PATH = /usr/lib64/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=${slot:-0}
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

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