mkimage: Add support for signing with pkcs11

Add support for signing with the pkcs11 engine. This allows FIT images
to be signed with keys securely stored on a smartcard, hardware security
module, etc without exposing the keys.

Support for other engines can be added in the future by modifying
rsa_engine_get_pub_key() and rsa_engine_get_priv_key() to construct
correct key_id strings.

Signed-off-by: George McCollister <george.mccollister@gmail.com>
This commit is contained in:
George McCollister 2017-01-06 13:14:17 -06:00 committed by Tom Rini
parent b1c6a54a53
commit f1ca1fdebf
7 changed files with 408 additions and 28 deletions

View file

@ -385,6 +385,149 @@ Test Verified Boot Run: signed config with bad hash: OK
Test passed
Hardware Signing with PKCS#11
-----------------------------
Securely managing private signing keys can challenging, especially when the
keys are stored on the file system of a computer that is connected to the
Internet. If an attacker is able to steal the key, they can sign malicious FIT
images which will appear genuine to your devices.
An alternative solution is to keep your signing key securely stored on hardware
device like a smartcard, USB token or Hardware Security Module (HSM) and have
them perform the signing. PKCS#11 is standard for interfacing with these crypto
device.
Requirements:
Smartcard/USB token/HSM which can work with the pkcs11 engine
openssl
libp11 (provides pkcs11 engine)
p11-kit (recommended to simplify setup)
opensc (for smartcards and smartcard like USB devices)
gnutls (recommended for key generation, p11tool)
The following examples use the Nitrokey Pro. Instructions for other devices may vary.
Notes on pkcs11 engine setup:
Make sure p11-kit, opensc are installed and that p11-kit is setup to use opensc.
/usr/share/p11-kit/modules/opensc.module should be present on your system.
Generating Keys On the Nitrokey:
$ gpg --card-edit
Reader ...........: Nitrokey Nitrokey Pro (xxxxxxxx0000000000000000) 00 00
Application ID ...: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Version ..........: 2.1
Manufacturer .....: ZeitControl
Serial number ....: xxxxxxxx
Name of cardholder: [not set]
Language prefs ...: de
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 32 32 32
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
gpg/card> generate
Make off-card backup of encryption key? (Y/n) n
Please note that the factory settings of the PINs are
PIN = '123456' Admin PIN = '12345678'
You should change them using the command --change-pin
What keysize do you want for the Signature key? (2048) 4096
The card will now be re-configured to generate a key of 4096 bits
Note: There is no guarantee that the card supports the requested size.
If the key generation does not succeed, please check the
documentation of your card to see what sizes are allowed.
What keysize do you want for the Encryption key? (2048) 4096
The card will now be re-configured to generate a key of 4096 bits
What keysize do you want for the Authentication key? (2048) 4096
The card will now be re-configured to generate a key of 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: John Doe
Email address: john.doe@email.com
Comment:
You selected this USER-ID:
"John Doe <john.doe@email.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
Using p11tool to get the token URL:
Depending on system configuration, gpg-agent may need to be killed first.
$ p11tool --provider /usr/lib/opensc-pkcs11.so --list-tokens
Token 0:
URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29
Label: OpenPGP card (User PIN (sig))
Type: Hardware token
Manufacturer: ZeitControl
Model: PKCS#15 emulated
Serial: 000xxxxxxxxx
Module: (null)
Token 1:
URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%29
Label: OpenPGP card (User PIN)
Type: Hardware token
Manufacturer: ZeitControl
Model: PKCS#15 emulated
Serial: 000xxxxxxxxx
Module: (null)
Use the portion of the signature token URL after "pkcs11:" as the keydir argument (-k) to mkimage below.
Use the URL of the token to list the private keys:
$ p11tool --login --provider /usr/lib/opensc-pkcs11.so --list-privkeys \
"pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29"
Token 'OpenPGP card (User PIN (sig))' with URL 'pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29' requires user PIN
Enter PIN:
Object 0:
URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29;id=%01;object=Signature%20key;type=private
Type: Private key
Label: Signature key
Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE;
ID: 01
Use the label, in this case "Signature key" as the key-name-hint in your FIT.
Create the fitImage:
$ ./tools/mkimage -f fit-image.its fitImage
Sign the fitImage with the hardware key:
$ ./tools/mkimage -F -k \
"model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \
-K u-boot.dtb -N pkcs11 -r fitImage
Future Work
-----------
- Roll-back protection using a TPM is done using the tpm command. This can