mkimage: Add support for signing with pkcs11
authorGeorge McCollister <george.mccollister@gmail.com>
Fri, 6 Jan 2017 19:14:17 +0000 (13:14 -0600)
committerTom Rini <trini@konsulko.com>
Sat, 14 Jan 2017 21:47:13 +0000 (16:47 -0500)
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>
doc/uImage.FIT/signature.txt
include/image.h
lib/rsa/rsa-sign.c
tools/fit_image.c
tools/image-host.c
tools/imagetool.h
tools/mkimage.c

index e4874018faddc1a1783f5519da9e057e7bac9802..7cdb7bf324c17d34306da3fff3a94374e5f2eb36 100644 (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
index 05376783fb10ce6bf09d8ce890befd34829e2569..6207d62d3c38da17b579ba8fef1ec036a0e85f3b 100644 (file)
@@ -965,6 +965,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
  * @fit:       Pointer to the FIT format image header
  * @comment:   Comment to add to signature nodes
  * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
  *
  * Adds hash values for all component images in the FIT blob.
  * Hashes are calculated for all component images which have hash subnodes
@@ -977,7 +978,8 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
  *     libfdt error code, on failure
  */
 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
-                             const char *comment, int require_keys);
+                             const char *comment, int require_keys,
+                             const char *engine_id);
 
 int fit_image_verify(const void *fit, int noffset);
 int fit_config_verify(const void *fit, int conf_noffset);
@@ -1057,6 +1059,7 @@ struct image_sign_info {
        const void *fdt_blob;           /* FDT containing public keys */
        int required_keynode;           /* Node offset of key to use: -1=any */
        const char *require_keys;       /* Value for 'required' property */
+       const char *engine_id;          /* Engine to use for signing */
 };
 #endif /* Allow struct image_region to always be defined for rsa.h */
 
index 9a09280013084078ae76b17aba088cadf327784c..8c6637e3287e5d3fd069c3523bdd7b196c11544c 100644 (file)
@@ -14,6 +14,7 @@
 #include <openssl/err.h>
 #include <openssl/ssl.h>
 #include <openssl/evp.h>
+#include <openssl/engine.h>
 
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
 #define HAVE_ERR_REMOVE_THREAD_STATE
@@ -31,14 +32,14 @@ static int rsa_err(const char *msg)
 }
 
 /**
- * rsa_get_pub_key() - read a public key from a .crt file
+ * rsa_pem_get_pub_key() - read a public key from a .crt file
  *
  * @keydir:    Directory containins the key
  * @name       Name of key file (will have a .crt extension)
  * @rsap       Returns RSA object, or NULL on failure
  * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  */
-static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
 {
        char path[1024];
        EVP_PKEY *key;
@@ -96,14 +97,90 @@ err_cert:
 }
 
 /**
- * rsa_get_priv_key() - read a private key from a .key file
+ * rsa_engine_get_pub_key() - read a public key from given engine
  *
- * @keydir:    Directory containins the key
+ * @keydir:    Key prefix
+ * @name       Name of key
+ * @engine     Engine to use
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_pub_key(const char *keydir, const char *name,
+                                 ENGINE *engine, RSA **rsap)
+{
+       const char *engine_id;
+       char key_id[1024];
+       EVP_PKEY *key;
+       RSA *rsa;
+       int ret;
+
+       *rsap = NULL;
+
+       engine_id = ENGINE_get_id(engine);
+
+       if (engine_id && !strcmp(engine_id, "pkcs11")) {
+               if (keydir)
+                       snprintf(key_id, sizeof(key_id),
+                                "pkcs11:%s;object=%s;type=public",
+                                keydir, name);
+               else
+                       snprintf(key_id, sizeof(key_id),
+                                "pkcs11:object=%s;type=public",
+                                name);
+       } else {
+               fprintf(stderr, "Engine not supported\n");
+               return -ENOTSUP;
+       }
+
+       key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
+       if (!key)
+               return rsa_err("Failure loading public key from engine");
+
+       /* Convert to a RSA_style key. */
+       rsa = EVP_PKEY_get1_RSA(key);
+       if (!rsa) {
+               rsa_err("Couldn't convert to a RSA style key");
+               ret = -EINVAL;
+               goto err_rsa;
+       }
+
+       EVP_PKEY_free(key);
+       *rsap = rsa;
+
+       return 0;
+
+err_rsa:
+       EVP_PKEY_free(key);
+       return ret;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key
+ *
+ * @keydir:    Directory containing the key (PEM file) or key prefix (engine)
+ * @name       Name of key file (will have a .crt extension)
+ * @engine     Engine to use
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name,
+                          ENGINE *engine, RSA **rsap)
+{
+       if (engine)
+               return rsa_engine_get_pub_key(keydir, name, engine, rsap);
+       return rsa_pem_get_pub_key(keydir, name, rsap);
+}
+
+/**
+ * rsa_pem_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir:    Directory containing the key
  * @name       Name of key file (will have a .key extension)
  * @rsap       Returns RSA object, or NULL on failure
  * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  */
-static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
+static int rsa_pem_get_priv_key(const char *keydir, const char *name,
+                               RSA **rsap)
 {
        char path[1024];
        RSA *rsa;
@@ -130,6 +207,81 @@ static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
        return 0;
 }
 
+/**
+ * rsa_engine_get_priv_key() - read a private key from given engine
+ *
+ * @keydir:    Key prefix
+ * @name       Name of key
+ * @engine     Engine to use
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_engine_get_priv_key(const char *keydir, const char *name,
+                                  ENGINE *engine, RSA **rsap)
+{
+       const char *engine_id;
+       char key_id[1024];
+       EVP_PKEY *key;
+       RSA *rsa;
+       int ret;
+
+       *rsap = NULL;
+
+       engine_id = ENGINE_get_id(engine);
+
+       if (engine_id && !strcmp(engine_id, "pkcs11")) {
+               if (keydir)
+                       snprintf(key_id, sizeof(key_id),
+                                "pkcs11:%s;object=%s;type=private",
+                                keydir, name);
+               else
+                       snprintf(key_id, sizeof(key_id),
+                                "pkcs11:object=%s;type=private",
+                                name);
+       } else {
+               fprintf(stderr, "Engine not supported\n");
+               return -ENOTSUP;
+       }
+
+       key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
+       if (!key)
+               return rsa_err("Failure loading private key from engine");
+
+       /* Convert to a RSA_style key. */
+       rsa = EVP_PKEY_get1_RSA(key);
+       if (!rsa) {
+               rsa_err("Couldn't convert to a RSA style key");
+               ret = -EINVAL;
+               goto err_rsa;
+       }
+
+       EVP_PKEY_free(key);
+       *rsap = rsa;
+
+       return 0;
+
+err_rsa:
+       EVP_PKEY_free(key);
+       return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key
+ *
+ * @keydir:    Directory containing the key (PEM file) or key prefix (engine)
+ * @name       Name of key
+ * @engine     Engine to use for signing
+ * @rsap       Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name,
+                           ENGINE *engine, RSA **rsap)
+{
+       if (engine)
+               return rsa_engine_get_priv_key(keydir, name, engine, rsap);
+       return rsa_pem_get_priv_key(keydir, name, rsap);
+}
+
 static int rsa_init(void)
 {
        int ret;
@@ -148,6 +300,45 @@ static int rsa_init(void)
        return 0;
 }
 
+static int rsa_engine_init(const char *engine_id, ENGINE **pe)
+{
+       ENGINE *e;
+       int ret;
+
+       ENGINE_load_builtin_engines();
+
+       e = ENGINE_by_id(engine_id);
+       if (!e) {
+               fprintf(stderr, "Engine isn't available\n");
+               ret = -1;
+               goto err_engine_by_id;
+       }
+
+       if (!ENGINE_init(e)) {
+               fprintf(stderr, "Couldn't initialize engine\n");
+               ret = -1;
+               goto err_engine_init;
+       }
+
+       if (!ENGINE_set_default_RSA(e)) {
+               fprintf(stderr, "Couldn't set engine as default for RSA\n");
+               ret = -1;
+               goto err_set_rsa;
+       }
+
+       *pe = e;
+
+       return 0;
+
+err_set_rsa:
+       ENGINE_finish(e);
+err_engine_init:
+       ENGINE_free(e);
+err_engine_by_id:
+       ENGINE_cleanup();
+       return ret;
+}
+
 static void rsa_remove(void)
 {
        CRYPTO_cleanup_all_ex_data();
@@ -160,6 +351,14 @@ static void rsa_remove(void)
        EVP_cleanup();
 }
 
+static void rsa_engine_remove(ENGINE *e)
+{
+       if (e) {
+               ENGINE_finish(e);
+               ENGINE_free(e);
+       }
+}
+
 static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
                const struct image_region region[], int region_count,
                uint8_t **sigp, uint *sig_size)
@@ -235,13 +434,20 @@ int rsa_sign(struct image_sign_info *info,
             uint8_t **sigp, uint *sig_len)
 {
        RSA *rsa;
+       ENGINE *e = NULL;
        int ret;
 
        ret = rsa_init();
        if (ret)
                return ret;
 
-       ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
+       if (info->engine_id) {
+               ret = rsa_engine_init(info->engine_id, &e);
+               if (ret)
+                       goto err_engine;
+       }
+
+       ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
        if (ret)
                goto err_priv;
        ret = rsa_sign_with_key(rsa, info->checksum, region,
@@ -250,6 +456,8 @@ int rsa_sign(struct image_sign_info *info,
                goto err_sign;
 
        RSA_free(rsa);
+       if (info->engine_id)
+               rsa_engine_remove(e);
        rsa_remove();
 
        return ret;
@@ -257,6 +465,9 @@ int rsa_sign(struct image_sign_info *info,
 err_sign:
        RSA_free(rsa);
 err_priv:
+       if (info->engine_id)
+               rsa_engine_remove(e);
+err_engine:
        rsa_remove();
        return ret;
 }
@@ -446,14 +657,20 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
        int ret;
        int bits;
        RSA *rsa;
+       ENGINE *e = NULL;
 
        debug("%s: Getting verification data\n", __func__);
-       ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
+       if (info->engine_id) {
+               ret = rsa_engine_init(info->engine_id, &e);
+               if (ret)
+                       return ret;
+       }
+       ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
        if (ret)
-               return ret;
+               goto err_get_pub_key;
        ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
        if (ret)
-               return ret;
+               goto err_get_params;
        bits = BN_num_bits(modulus);
        parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
        if (parent == -FDT_ERR_NOTFOUND) {
@@ -518,7 +735,12 @@ done:
        BN_free(modulus);
        BN_free(r_squared);
        if (ret)
-               return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+               ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
+err_get_params:
+       RSA_free(rsa);
+err_get_pub_key:
+       if (info->engine_id)
+               rsa_engine_remove(e);
 
-       return 0;
+       return ret;
 }
index efd8a97a0b92723a01aae584cd9ce468c8e99735..4dc8bd8862454598d1bf5383b259707a06cfccba 100644 (file)
@@ -59,7 +59,8 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
        if (!ret) {
                ret = fit_add_verification_data(params->keydir, dest_blob, ptr,
                                                params->comment,
-                                               params->require_keys);
+                                               params->require_keys,
+                                               params->engine_id);
        }
 
        if (dest_blob) {
index c1a01225e2bf14547391217b76709bd84c790a88..5e4d690714160dcd68932f8eb6cf728640532ea6 100644 (file)
@@ -149,7 +149,7 @@ static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
 
 static int fit_image_setup_sig(struct image_sign_info *info,
                const char *keydir, void *fit, const char *image_name,
-               int noffset, const char *require_keys)
+               int noffset, const char *require_keys, const char *engine_id)
 {
        const char *node_name;
        char *algo_name;
@@ -170,6 +170,7 @@ static int fit_image_setup_sig(struct image_sign_info *info,
        info->checksum = image_get_checksum_algo(algo_name);
        info->crypto = image_get_crypto_algo(algo_name);
        info->require_keys = require_keys;
+       info->engine_id = engine_id;
        if (!info->checksum || !info->crypto) {
                printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
                       algo_name, node_name, image_name);
@@ -194,12 +195,13 @@ static int fit_image_setup_sig(struct image_sign_info *info,
  * @size:      size of data in bytes
  * @comment:   Comment to add to signature nodes
  * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
  * @return 0 if ok, -1 on error
  */
 static int fit_image_process_sig(const char *keydir, void *keydest,
                void *fit, const char *image_name,
                int noffset, const void *data, size_t size,
-               const char *comment, int require_keys)
+               const char *comment, int require_keys, const char *engine_id)
 {
        struct image_sign_info info;
        struct image_region region;
@@ -209,7 +211,7 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
        int ret;
 
        if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
-                               require_keys ? "image" : NULL))
+                               require_keys ? "image" : NULL, engine_id))
                return -1;
 
        node_name = fit_get_name(fit, noffset, NULL);
@@ -288,11 +290,12 @@ static int fit_image_process_sig(const char *keydir, void *keydest,
  * @image_noffset: Requested component image node
  * @comment:   Comment to add to signature nodes
  * @require_keys: Mark all keys as 'required'
+ * @engine_id: Engine to use for signing
  * @return: 0 on success, <0 on failure
  */
 int fit_image_add_verification_data(const char *keydir, void *keydest,
                void *fit, int image_noffset, const char *comment,
-               int require_keys)
+               int require_keys, const char *engine_id)
 {
        const char *image_name;
        const void *data;
@@ -329,7 +332,7 @@ int fit_image_add_verification_data(const char *keydir, void *keydest,
                                strlen(FIT_SIG_NODENAME))) {
                        ret = fit_image_process_sig(keydir, keydest,
                                fit, image_name, noffset, data, size,
-                               comment, require_keys);
+                               comment, require_keys, engine_id);
                }
                if (ret)
                        return ret;
@@ -569,7 +572,8 @@ static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
 
 static int fit_config_process_sig(const char *keydir, void *keydest,
                void *fit, const char *conf_name, int conf_noffset,
-               int noffset, const char *comment, int require_keys)
+               int noffset, const char *comment, int require_keys,
+               const char *engine_id)
 {
        struct image_sign_info info;
        const char *node_name;
@@ -587,7 +591,7 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
                return -1;
 
        if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
-                               require_keys ? "conf" : NULL))
+                               require_keys ? "conf" : NULL, engine_id))
                return -1;
 
        ret = info.crypto->sign(&info, region, region_count, &value,
@@ -635,7 +639,7 @@ static int fit_config_process_sig(const char *keydir, void *keydest,
 
 static int fit_config_add_verification_data(const char *keydir, void *keydest,
                void *fit, int conf_noffset, const char *comment,
-               int require_keys)
+               int require_keys, const char *engine_id)
 {
        const char *conf_name;
        int noffset;
@@ -654,7 +658,7 @@ static int fit_config_add_verification_data(const char *keydir, void *keydest,
                             strlen(FIT_SIG_NODENAME))) {
                        ret = fit_config_process_sig(keydir, keydest,
                                fit, conf_name, conf_noffset, noffset, comment,
-                               require_keys);
+                               require_keys, engine_id);
                }
                if (ret)
                        return ret;
@@ -664,7 +668,8 @@ static int fit_config_add_verification_data(const char *keydir, void *keydest,
 }
 
 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
-                             const char *comment, int require_keys)
+                             const char *comment, int require_keys,
+                             const char *engine_id)
 {
        int images_noffset, confs_noffset;
        int noffset;
@@ -687,7 +692,7 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
                 * i.e. component image node.
                 */
                ret = fit_image_add_verification_data(keydir, keydest,
-                               fit, noffset, comment, require_keys);
+                               fit, noffset, comment, require_keys, engine_id);
                if (ret)
                        return ret;
        }
@@ -710,7 +715,8 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
             noffset = fdt_next_subnode(fit, noffset)) {
                ret = fit_config_add_verification_data(keydir, keydest,
                                                       fit, noffset, comment,
-                                                      require_keys);
+                                                      require_keys,
+                                                      engine_id);
                if (ret)
                        return ret;
        }
index 15c2a0c0e1c13b8124f260f9c1f6224f3014a51f..a8d505423b87ba0450f775a507e12d58d728cca3 100644 (file)
@@ -76,6 +76,7 @@ struct image_tool_params {
        bool external_data;     /* Store data outside the FIT */
        bool quiet;             /* Don't output text in normal operation */
        unsigned int external_offset;   /* Add padding to external data */
+       const char *engine_id;  /* Engine to use for signing */
 };
 
 /*
index f48135ff7988d546262185835c1bd9ea07c0eaeb..b0c98f6f5512be510e463538a24d35d36dfdcd91 100644 (file)
@@ -98,14 +98,15 @@ static void usage(const char *msg)
                "          -i => input filename for ramdisk file\n");
 #ifdef CONFIG_FIT_SIGNATURE
        fprintf(stderr,
-               "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r]\n"
+               "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
                "          -E => place data outside of the FIT structure\n"
                "          -k => set directory containing private keys\n"
                "          -K => write public keys to this .dtb file\n"
                "          -c => add comment in signature node\n"
                "          -F => re-sign existing FIT image\n"
                "          -p => place external data at a static position\n"
-               "          -r => mark keys used as 'required' in dtb\n");
+               "          -r => mark keys used as 'required' in dtb\n"
+               "          -N => engine to use for signing (pkcs11)\n");
 #else
        fprintf(stderr,
                "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
@@ -143,7 +144,7 @@ static void process_args(int argc, char **argv)
        int opt;
 
        while ((opt = getopt(argc, argv,
-                            "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:p:O:rR:qsT:vVx")) != -1) {
+                            "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
                switch (opt) {
                case 'a':
                        params.addr = strtoull(optarg, &ptr, 16);
@@ -224,6 +225,9 @@ static void process_args(int argc, char **argv)
                case 'n':
                        params.imagename = optarg;
                        break;
+               case 'N':
+                       params.engine_id = optarg;
+                       break;
                case 'O':
                        params.os = genimg_get_os_id(optarg);
                        if (params.os < 0) {