SmartCardKerberos
From DcSharedWiki
How to use smart card with Kerberos.
Requirements
- Software: Here programs that will be used. In parenthesises I have mentionned versions I have used.
- openssl (0.9.8)
- Kerberos server with pkinit plugin (MIT 1.6)
- opensc (0.11.13)
- pcscd (1.5.5)
- Hardware
- a smart card: Feitian PKI card bought on http://www.gooze.eu/ There is a lot of documentation on this website.
- smart card reader (mine is
External links
- OpenSC quick start and OpenSC engine_pkcs11 quickstart
- OpenSSL configration (in french) by Franck Davy
- Generating cert for pkinit by Sam Hartman
- Smart cards with Heimdal by Guido Günther
Typographical conventions
- in commands listed below, you must replace `XX` by value depending of your configuration.
- Constant width is used for `keywords`
Initialize smart card
An empty smart card can be initialized with:
# pin & puk will be asked pkcs15-init --create-pkcs15 --profile pkcs15+onepin --use-default-transport-key --label "Pilou"
A not empty smart card can be erased and initialized with:
pkcs15-init -E --label "Pilou"
Create a PKI
Private keys of root CA, server CA and clients CA will be stored on a smart card.
PKI structure
- root CA: sign servers CA and clients CA
- servers CA: sign servers certificates
- kdc certificate
- clients CA: sign clients certificates
- user certificate
Create root CA
Root CA is a self-signed certificate. In order to create the certificate you need to generate a RSA key. This key can be either:
- generated on the smart card
- generated on a computer and copied on the smart card
RSA generated on the smart card
# (pin will be asked) pkcs15-init --generate-key rsa/2048 --auth-id XX
Value of "--auth-id" parameter can be retreived with:
pkcs15-tool --list-pins
RSA generated on a computer and copied
openssl genrsa 2048 > id_rsa.pem openssl rsa -pubout < id_rsa.pem > id_rsa.pub pkcs15-init --store-private-key id_rsa.pem --auth-id XX # PIN will be asked or '--pin' can be used
create certificate
openssl req -config openssl.cnf -engine pkcs11 -key slot_XX-id_XX -keyform engine -extensions CA_ROOT -new -x509 -out ca.pem -text
`id` is same as value of parameter `--auth-id` and `slot` is indicated by:
pkcs11-tool --list-slots
openssl configuration
Here is my complete openssl.cnf file:
# This definition stops the following lines choking if HOME isn't # defined. HOME = . RANDFILE = $ENV::HOME/.rnd openssl_conf = openssl_init [openssl_init] engines = engine_section oid_section = new_oids [ new_oids ] pkkdcekuoid=1.3.6.1.5.2.3.5 [ ca ] default_ca = CA_root_default #################################################################### [ CA_root_default ] dir = ./ca certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number crl = $dir/crl.pem # The current CRL #private_key = $dir/private/cakey.pem # The private key RANDFILE = $dir/private/.rand # private random number file # Comment out the following two lines for the "traditional" # (and highly broken) format. name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 365 # how long to certify for default_crl_days = 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_match [ CA_serveur_default ] dir = ./cassl certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cassl.pem # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number crl = $dir/crl.pem # The current CRL #private_key = $dir/private/cakey.pem # The private key RANDFILE = $dir/private/.rand # private random number file # Comment out the following two lines for the "traditional" # (and highly broken) format. name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 365 # how long to certify for default_crl_days = 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_match [ CA_client_default ] dir = ./client certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/client.pem # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number crl = $dir/crl.pem # The current CRL #private_key = $dir/private/cakey.pem # The private key RANDFILE = $dir/private/.rand # private random number file # Comment out the following two lines for the "traditional" # (and highly broken) format. name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 365 # how long to certify for default_crl_days = 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering policy = policy_user [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_user ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = supplied #################################################################### [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name # This sets a mask for permitted string types. There are several options. # default: PrintableString, T61String, BMPString. # pkix : PrintableString, BMPString. # utf8only: only UTF8Strings. # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). # MASK:XXXX a literal mask value. # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings # so use this option with caution! string_mask = nombstr [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = FR countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Ile de France localityName = Locality Name (eg, city) localityName_default = Paris 0.organizationName = Organization Name (eg, company) 0.organizationName_default = PilouCorp organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [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 [CA_ROOT] nsComment = "CA Racine" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always basicConstraints = critical,CA:TRUE,pathlen:1 keyUsage = keyCertSign, cRLSign [CA_SERVEUR_SSL] nsComment = "CA serveur SSL" basicConstraints = critical,CA:TRUE,pathlen:0 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy keyUsage = keyCertSign, cRLSign nsCertType = sslCA [SERVEUR_SSL] nsComment = "Certificat Serveur SSL" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy basicConstraints = critical,CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment nsCertType = server extendedKeyUsage = serverAuth [CA_CLIENT_SSL] nsComment = "CA client SSL" basicConstraints = critical,CA:TRUE,pathlen:0 subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy keyUsage = keyCertSign, cRLSign nsCertType = sslCA [CLIENT_SSL] nsComment = "Certificat Client SSL" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy basicConstraints = critical,CA:FALSE keyUsage = digitalSignature, nonRepudiation nsCertType = client [ KDC_CERT ] nsComment = "KDC SERVEUR SSL" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement extendedKeyUsage = pkkdcekuoid basicConstraints = critical,CA:FALSE # Add id-pkinit-san (pkinit subjectAlternativeName) subjectAltName = otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name [kdc_princ_name] realm = EXP:0,GeneralString:${ENV::REALM} principal_name = EXP:1,SEQUENCE:kdc_principal_seq [kdc_principal_seq] name_type = EXP:0,INTEGER:1 name_string = EXP:1,SEQUENCE:kdc_principals [kdc_principals] princ1 = GeneralString:krbtgt princ2 = GeneralString:${ENV::REALM} [ CLIENT_CERT ] nsComment = "KRB CLIENT SSL" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always issuerAltName = issuer:copy keyUsage = digitalSignature, keyEncipherment, keyAgreement extendedKeyUsage = 1.3.6.1.5.2.3.4 basicConstraints = CA:FALSE subjectAltName = otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name [princ_name] realm = EXP:0, GeneralString:${ENV::REALM} principal_name = EXP:1, SEQUENCE:principal_seq [principal_seq] name_type = EXP:0, INTEGER:1 name_string = EXP:1, SEQUENCE:principals [principals] princ1 = GeneralString:${ENV::CLIENT}