This article uses the OpenSSL and OpenSC libraries. For more information see this article.
Personalizing is the process of generating keys, and loading a certificate tot he PIV Card.
When personalizing PIV cards, it is important to understand that the OpenSC tools are not able to read the public key off the card. (The PIV spec does not provide a mechanism to read public keys). Instead OpenSC uses what it thinks is the public key based on the data it has available.
The first thing it does is look for a certificate. If a certificate is on the card, OpenSC assumes the public key in the certificate is the public key for that slot.
If there is no certificate, then OpenSC will look for the environment variable (PIV_9A_KEY, PIV_9C_KEY, PIV_9D_KEY, PIV_9E_KEY) corresponding to the key being accessed.
Note: if a certificate is loaded and then later new keys are generated, OpenSC will use the wrong public key until the certificate is deleted or replaced.
Generating Keys and Loading a Certificate
The example below will walk through loading a PIV Auth certificate which is the certificate corresponding to the 9A key. The example is run from a folder ~/opensc-test. If running from another location update the path to the environment variables accordingly.
Setup environment variables that will be used by OpenSC. These should be set to the path of text files that contain the necessary keys.
$ export PIV_EXT_AUTH_KEY=~/opensc-test/9b.txt
$ export PIV_9A_KEY=~/opensc-test/9a.txt
In this example 9b.txt contains the 9b key. 9a.txt will hold the public key of the 9a key pair once generated.
Check that authentication with the 9b key is working.
$ piv-tool --admin M:9B:0C
The 0C indicates that the admin key is an AES 256 key. This may need to change depending on the card. (Use 03 for 3DES, 08 for AES 128, 0A for AES 192, 0C for AES 256).
Delete PIV Auth certificate from card. Technically this step is only needed if a PIV Auth certificate exists on the card. However, it's good practice to run this step each time, so as not to forget in the case where there is a certificate on the card. See section Deleting a PIV data object for more information on this step.
$ piv-tool --admin M:9B:0C --object 0101 --in empty-piv-file.dat
Generate keys on the card and output the public key to file 9a.txt (which is the file that environment variable PIV_9A_KEY was configured to point to in Step 1). The 07 specifies that an RSA 2048 keypair should be generated.
$ piv-tool --admin M:9B:0C --genkey 9A:07 --out 9a.txt
There are two options for this step.
- Option 1: Generate certificate request and send to a CA
- Option 2: Generate a self signed certificate
Both options use openssl configured to use the opensc-pkcs11 library.
OpenSSL> engine dynamic -pre SO_PATH:/usr/lib/ssl/engines/libpkcs11.so -pre ID:pkcs11 -pre
LIST_ADD:1 -pre LOAD -pre MODULE_PATH:/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
(dynamic) Dynamic engine loading support
Loaded: (pkcs11) pkcs11 engine
For Option 1, now generate a Certificate Signing Request. The following command will generate a certRequest.csr file which can then be sent to a CA. For information on sending the request to a Microsoft CA, see the section below "Using a Microsoft CA".
OpenSSL> req -engine pkcs11 -new -key id_01 -keyform engine -out certRequest.csr -text
For Option 2, have OpenSSL generate a self signed certificate. The following command will generate cert.pem
OpenSSL> req -engine pkcs11 -new -key id_01 -keyform engine -x509 -out cert.pem -text
For both Option 1 and Option 2, OpenSSL will prompt for the smart card pin and then will prompt for information to include in the certifate request/certificate. See the "Testing using OpenSSL" section of
https://github.com/OpenSC/OpenSC/wiki/Quick-Start-with-OpenSC for more information.
Load the certificate onto the PIV card. If Option 1 in the previous command was used then, the certificate name in the following command may need to be changed.
piv-tool --admin M:9B:0C --cert 9A --in cert.pem
The certificate is now loaded and ready to use.