Commit f1ca1fdebf1cde1c37c91b3d85f8b7af111112ea

Authored by George McCollister
Committed by Tom Rini
1 parent b1c6a54a53

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>

Showing 7 changed files with 408 additions and 28 deletions Side-by-side Diff

doc/uImage.FIT/signature.txt
... ... @@ -385,6 +385,149 @@
385 385 Test passed
386 386  
387 387  
  388 +Hardware Signing with PKCS#11
  389 +-----------------------------
  390 +
  391 +Securely managing private signing keys can challenging, especially when the
  392 +keys are stored on the file system of a computer that is connected to the
  393 +Internet. If an attacker is able to steal the key, they can sign malicious FIT
  394 +images which will appear genuine to your devices.
  395 +
  396 +An alternative solution is to keep your signing key securely stored on hardware
  397 +device like a smartcard, USB token or Hardware Security Module (HSM) and have
  398 +them perform the signing. PKCS#11 is standard for interfacing with these crypto
  399 +device.
  400 +
  401 +Requirements:
  402 +Smartcard/USB token/HSM which can work with the pkcs11 engine
  403 +openssl
  404 +libp11 (provides pkcs11 engine)
  405 +p11-kit (recommended to simplify setup)
  406 +opensc (for smartcards and smartcard like USB devices)
  407 +gnutls (recommended for key generation, p11tool)
  408 +
  409 +The following examples use the Nitrokey Pro. Instructions for other devices may vary.
  410 +
  411 +Notes on pkcs11 engine setup:
  412 +
  413 +Make sure p11-kit, opensc are installed and that p11-kit is setup to use opensc.
  414 +/usr/share/p11-kit/modules/opensc.module should be present on your system.
  415 +
  416 +
  417 +Generating Keys On the Nitrokey:
  418 +
  419 +$ gpg --card-edit
  420 +
  421 +Reader ...........: Nitrokey Nitrokey Pro (xxxxxxxx0000000000000000) 00 00
  422 +Application ID ...: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  423 +Version ..........: 2.1
  424 +Manufacturer .....: ZeitControl
  425 +Serial number ....: xxxxxxxx
  426 +Name of cardholder: [not set]
  427 +Language prefs ...: de
  428 +Sex ..............: unspecified
  429 +URL of public key : [not set]
  430 +Login data .......: [not set]
  431 +Signature PIN ....: forced
  432 +Key attributes ...: rsa2048 rsa2048 rsa2048
  433 +Max. PIN lengths .: 32 32 32
  434 +PIN retry counter : 3 0 3
  435 +Signature counter : 0
  436 +Signature key ....: [none]
  437 +Encryption key....: [none]
  438 +Authentication key: [none]
  439 +General key info..: [none]
  440 +
  441 +gpg/card> generate
  442 +Make off-card backup of encryption key? (Y/n) n
  443 +
  444 +Please note that the factory settings of the PINs are
  445 + PIN = '123456' Admin PIN = '12345678'
  446 +You should change them using the command --change-pin
  447 +
  448 +What keysize do you want for the Signature key? (2048) 4096
  449 +The card will now be re-configured to generate a key of 4096 bits
  450 +Note: There is no guarantee that the card supports the requested size.
  451 + If the key generation does not succeed, please check the
  452 + documentation of your card to see what sizes are allowed.
  453 +What keysize do you want for the Encryption key? (2048) 4096
  454 +The card will now be re-configured to generate a key of 4096 bits
  455 +What keysize do you want for the Authentication key? (2048) 4096
  456 +The card will now be re-configured to generate a key of 4096 bits
  457 +Please specify how long the key should be valid.
  458 + 0 = key does not expire
  459 + <n> = key expires in n days
  460 + <n>w = key expires in n weeks
  461 + <n>m = key expires in n months
  462 + <n>y = key expires in n years
  463 +Key is valid for? (0)
  464 +Key does not expire at all
  465 +Is this correct? (y/N) y
  466 +
  467 +GnuPG needs to construct a user ID to identify your key.
  468 +
  469 +Real name: John Doe
  470 +Email address: john.doe@email.com
  471 +Comment:
  472 +You selected this USER-ID:
  473 + "John Doe <john.doe@email.com>"
  474 +
  475 +Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
  476 +
  477 +
  478 +Using p11tool to get the token URL:
  479 +
  480 +Depending on system configuration, gpg-agent may need to be killed first.
  481 +
  482 +$ p11tool --provider /usr/lib/opensc-pkcs11.so --list-tokens
  483 +Token 0:
  484 +URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29
  485 +Label: OpenPGP card (User PIN (sig))
  486 +Type: Hardware token
  487 +Manufacturer: ZeitControl
  488 +Model: PKCS#15 emulated
  489 +Serial: 000xxxxxxxxx
  490 +Module: (null)
  491 +
  492 +
  493 +Token 1:
  494 +URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%29
  495 +Label: OpenPGP card (User PIN)
  496 +Type: Hardware token
  497 +Manufacturer: ZeitControl
  498 +Model: PKCS#15 emulated
  499 +Serial: 000xxxxxxxxx
  500 +Module: (null)
  501 +
  502 +Use the portion of the signature token URL after "pkcs11:" as the keydir argument (-k) to mkimage below.
  503 +
  504 +
  505 +Use the URL of the token to list the private keys:
  506 +
  507 +$ p11tool --login --provider /usr/lib/opensc-pkcs11.so --list-privkeys \
  508 +"pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29"
  509 +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
  510 +Enter PIN:
  511 +Object 0:
  512 +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
  513 +Type: Private key
  514 +Label: Signature key
  515 +Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE;
  516 +ID: 01
  517 +
  518 +Use the label, in this case "Signature key" as the key-name-hint in your FIT.
  519 +
  520 +Create the fitImage:
  521 +$ ./tools/mkimage -f fit-image.its fitImage
  522 +
  523 +
  524 +Sign the fitImage with the hardware key:
  525 +
  526 +$ ./tools/mkimage -F -k \
  527 +"model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \
  528 +-K u-boot.dtb -N pkcs11 -r fitImage
  529 +
  530 +
388 531 Future Work
389 532 -----------
390 533 - Roll-back protection using a TPM is done using the tpm command. This can
... ... @@ -965,6 +965,7 @@
965 965 * @fit: Pointer to the FIT format image header
966 966 * @comment: Comment to add to signature nodes
967 967 * @require_keys: Mark all keys as 'required'
  968 + * @engine_id: Engine to use for signing
968 969 *
969 970 * Adds hash values for all component images in the FIT blob.
970 971 * Hashes are calculated for all component images which have hash subnodes
... ... @@ -977,7 +978,8 @@
977 978 * libfdt error code, on failure
978 979 */
979 980 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
980   - const char *comment, int require_keys);
  981 + const char *comment, int require_keys,
  982 + const char *engine_id);
981 983  
982 984 int fit_image_verify(const void *fit, int noffset);
983 985 int fit_config_verify(const void *fit, int conf_noffset);
... ... @@ -1057,6 +1059,7 @@
1057 1059 const void *fdt_blob; /* FDT containing public keys */
1058 1060 int required_keynode; /* Node offset of key to use: -1=any */
1059 1061 const char *require_keys; /* Value for 'required' property */
  1062 + const char *engine_id; /* Engine to use for signing */
1060 1063 };
1061 1064 #endif /* Allow struct image_region to always be defined for rsa.h */
1062 1065  
... ... @@ -14,6 +14,7 @@
14 14 #include <openssl/err.h>
15 15 #include <openssl/ssl.h>
16 16 #include <openssl/evp.h>
  17 +#include <openssl/engine.h>
17 18  
18 19 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
19 20 #define HAVE_ERR_REMOVE_THREAD_STATE
20 21  
... ... @@ -31,14 +32,14 @@
31 32 }
32 33  
33 34 /**
34   - * rsa_get_pub_key() - read a public key from a .crt file
  35 + * rsa_pem_get_pub_key() - read a public key from a .crt file
35 36 *
36 37 * @keydir: Directory containins the key
37 38 * @name Name of key file (will have a .crt extension)
38 39 * @rsap Returns RSA object, or NULL on failure
39 40 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
40 41 */
41   -static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
  42 +static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap)
42 43 {
43 44 char path[1024];
44 45 EVP_PKEY *key;
45 46  
46 47  
... ... @@ -96,14 +97,90 @@
96 97 }
97 98  
98 99 /**
99   - * rsa_get_priv_key() - read a private key from a .key file
  100 + * rsa_engine_get_pub_key() - read a public key from given engine
100 101 *
101   - * @keydir: Directory containins the key
  102 + * @keydir: Key prefix
  103 + * @name Name of key
  104 + * @engine Engine to use
  105 + * @rsap Returns RSA object, or NULL on failure
  106 + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  107 + */
  108 +static int rsa_engine_get_pub_key(const char *keydir, const char *name,
  109 + ENGINE *engine, RSA **rsap)
  110 +{
  111 + const char *engine_id;
  112 + char key_id[1024];
  113 + EVP_PKEY *key;
  114 + RSA *rsa;
  115 + int ret;
  116 +
  117 + *rsap = NULL;
  118 +
  119 + engine_id = ENGINE_get_id(engine);
  120 +
  121 + if (engine_id && !strcmp(engine_id, "pkcs11")) {
  122 + if (keydir)
  123 + snprintf(key_id, sizeof(key_id),
  124 + "pkcs11:%s;object=%s;type=public",
  125 + keydir, name);
  126 + else
  127 + snprintf(key_id, sizeof(key_id),
  128 + "pkcs11:object=%s;type=public",
  129 + name);
  130 + } else {
  131 + fprintf(stderr, "Engine not supported\n");
  132 + return -ENOTSUP;
  133 + }
  134 +
  135 + key = ENGINE_load_public_key(engine, key_id, NULL, NULL);
  136 + if (!key)
  137 + return rsa_err("Failure loading public key from engine");
  138 +
  139 + /* Convert to a RSA_style key. */
  140 + rsa = EVP_PKEY_get1_RSA(key);
  141 + if (!rsa) {
  142 + rsa_err("Couldn't convert to a RSA style key");
  143 + ret = -EINVAL;
  144 + goto err_rsa;
  145 + }
  146 +
  147 + EVP_PKEY_free(key);
  148 + *rsap = rsa;
  149 +
  150 + return 0;
  151 +
  152 +err_rsa:
  153 + EVP_PKEY_free(key);
  154 + return ret;
  155 +}
  156 +
  157 +/**
  158 + * rsa_get_pub_key() - read a public key
  159 + *
  160 + * @keydir: Directory containing the key (PEM file) or key prefix (engine)
  161 + * @name Name of key file (will have a .crt extension)
  162 + * @engine Engine to use
  163 + * @rsap Returns RSA object, or NULL on failure
  164 + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  165 + */
  166 +static int rsa_get_pub_key(const char *keydir, const char *name,
  167 + ENGINE *engine, RSA **rsap)
  168 +{
  169 + if (engine)
  170 + return rsa_engine_get_pub_key(keydir, name, engine, rsap);
  171 + return rsa_pem_get_pub_key(keydir, name, rsap);
  172 +}
  173 +
  174 +/**
  175 + * rsa_pem_get_priv_key() - read a private key from a .key file
  176 + *
  177 + * @keydir: Directory containing the key
102 178 * @name Name of key file (will have a .key extension)
103 179 * @rsap Returns RSA object, or NULL on failure
104 180 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
105 181 */
106   -static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
  182 +static int rsa_pem_get_priv_key(const char *keydir, const char *name,
  183 + RSA **rsap)
107 184 {
108 185 char path[1024];
109 186 RSA *rsa;
... ... @@ -130,6 +207,81 @@
130 207 return 0;
131 208 }
132 209  
  210 +/**
  211 + * rsa_engine_get_priv_key() - read a private key from given engine
  212 + *
  213 + * @keydir: Key prefix
  214 + * @name Name of key
  215 + * @engine Engine to use
  216 + * @rsap Returns RSA object, or NULL on failure
  217 + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  218 + */
  219 +static int rsa_engine_get_priv_key(const char *keydir, const char *name,
  220 + ENGINE *engine, RSA **rsap)
  221 +{
  222 + const char *engine_id;
  223 + char key_id[1024];
  224 + EVP_PKEY *key;
  225 + RSA *rsa;
  226 + int ret;
  227 +
  228 + *rsap = NULL;
  229 +
  230 + engine_id = ENGINE_get_id(engine);
  231 +
  232 + if (engine_id && !strcmp(engine_id, "pkcs11")) {
  233 + if (keydir)
  234 + snprintf(key_id, sizeof(key_id),
  235 + "pkcs11:%s;object=%s;type=private",
  236 + keydir, name);
  237 + else
  238 + snprintf(key_id, sizeof(key_id),
  239 + "pkcs11:object=%s;type=private",
  240 + name);
  241 + } else {
  242 + fprintf(stderr, "Engine not supported\n");
  243 + return -ENOTSUP;
  244 + }
  245 +
  246 + key = ENGINE_load_private_key(engine, key_id, NULL, NULL);
  247 + if (!key)
  248 + return rsa_err("Failure loading private key from engine");
  249 +
  250 + /* Convert to a RSA_style key. */
  251 + rsa = EVP_PKEY_get1_RSA(key);
  252 + if (!rsa) {
  253 + rsa_err("Couldn't convert to a RSA style key");
  254 + ret = -EINVAL;
  255 + goto err_rsa;
  256 + }
  257 +
  258 + EVP_PKEY_free(key);
  259 + *rsap = rsa;
  260 +
  261 + return 0;
  262 +
  263 +err_rsa:
  264 + EVP_PKEY_free(key);
  265 + return ret;
  266 +}
  267 +
  268 +/**
  269 + * rsa_get_priv_key() - read a private key
  270 + *
  271 + * @keydir: Directory containing the key (PEM file) or key prefix (engine)
  272 + * @name Name of key
  273 + * @engine Engine to use for signing
  274 + * @rsap Returns RSA object, or NULL on failure
  275 + * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
  276 + */
  277 +static int rsa_get_priv_key(const char *keydir, const char *name,
  278 + ENGINE *engine, RSA **rsap)
  279 +{
  280 + if (engine)
  281 + return rsa_engine_get_priv_key(keydir, name, engine, rsap);
  282 + return rsa_pem_get_priv_key(keydir, name, rsap);
  283 +}
  284 +
133 285 static int rsa_init(void)
134 286 {
135 287 int ret;
... ... @@ -148,6 +300,45 @@
148 300 return 0;
149 301 }
150 302  
  303 +static int rsa_engine_init(const char *engine_id, ENGINE **pe)
  304 +{
  305 + ENGINE *e;
  306 + int ret;
  307 +
  308 + ENGINE_load_builtin_engines();
  309 +
  310 + e = ENGINE_by_id(engine_id);
  311 + if (!e) {
  312 + fprintf(stderr, "Engine isn't available\n");
  313 + ret = -1;
  314 + goto err_engine_by_id;
  315 + }
  316 +
  317 + if (!ENGINE_init(e)) {
  318 + fprintf(stderr, "Couldn't initialize engine\n");
  319 + ret = -1;
  320 + goto err_engine_init;
  321 + }
  322 +
  323 + if (!ENGINE_set_default_RSA(e)) {
  324 + fprintf(stderr, "Couldn't set engine as default for RSA\n");
  325 + ret = -1;
  326 + goto err_set_rsa;
  327 + }
  328 +
  329 + *pe = e;
  330 +
  331 + return 0;
  332 +
  333 +err_set_rsa:
  334 + ENGINE_finish(e);
  335 +err_engine_init:
  336 + ENGINE_free(e);
  337 +err_engine_by_id:
  338 + ENGINE_cleanup();
  339 + return ret;
  340 +}
  341 +
151 342 static void rsa_remove(void)
152 343 {
153 344 CRYPTO_cleanup_all_ex_data();
... ... @@ -160,6 +351,14 @@
160 351 EVP_cleanup();
161 352 }
162 353  
  354 +static void rsa_engine_remove(ENGINE *e)
  355 +{
  356 + if (e) {
  357 + ENGINE_finish(e);
  358 + ENGINE_free(e);
  359 + }
  360 +}
  361 +
163 362 static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
164 363 const struct image_region region[], int region_count,
165 364 uint8_t **sigp, uint *sig_size)
166 365  
... ... @@ -235,13 +434,20 @@
235 434 uint8_t **sigp, uint *sig_len)
236 435 {
237 436 RSA *rsa;
  437 + ENGINE *e = NULL;
238 438 int ret;
239 439  
240 440 ret = rsa_init();
241 441 if (ret)
242 442 return ret;
243 443  
244   - ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
  444 + if (info->engine_id) {
  445 + ret = rsa_engine_init(info->engine_id, &e);
  446 + if (ret)
  447 + goto err_engine;
  448 + }
  449 +
  450 + ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa);
245 451 if (ret)
246 452 goto err_priv;
247 453 ret = rsa_sign_with_key(rsa, info->checksum, region,
... ... @@ -250,6 +456,8 @@
250 456 goto err_sign;
251 457  
252 458 RSA_free(rsa);
  459 + if (info->engine_id)
  460 + rsa_engine_remove(e);
253 461 rsa_remove();
254 462  
255 463 return ret;
... ... @@ -257,6 +465,9 @@
257 465 err_sign:
258 466 RSA_free(rsa);
259 467 err_priv:
  468 + if (info->engine_id)
  469 + rsa_engine_remove(e);
  470 +err_engine:
260 471 rsa_remove();
261 472 return ret;
262 473 }
263 474  
264 475  
265 476  
... ... @@ -446,14 +657,20 @@
446 657 int ret;
447 658 int bits;
448 659 RSA *rsa;
  660 + ENGINE *e = NULL;
449 661  
450 662 debug("%s: Getting verification data\n", __func__);
451   - ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
  663 + if (info->engine_id) {
  664 + ret = rsa_engine_init(info->engine_id, &e);
  665 + if (ret)
  666 + return ret;
  667 + }
  668 + ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa);
452 669 if (ret)
453   - return ret;
  670 + goto err_get_pub_key;
454 671 ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared);
455 672 if (ret)
456   - return ret;
  673 + goto err_get_params;
457 674 bits = BN_num_bits(modulus);
458 675 parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
459 676 if (parent == -FDT_ERR_NOTFOUND) {
460 677  
... ... @@ -518,8 +735,13 @@
518 735 BN_free(modulus);
519 736 BN_free(r_squared);
520 737 if (ret)
521   - return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
  738 + ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO;
  739 +err_get_params:
  740 + RSA_free(rsa);
  741 +err_get_pub_key:
  742 + if (info->engine_id)
  743 + rsa_engine_remove(e);
522 744  
523   - return 0;
  745 + return ret;
524 746 }
... ... @@ -59,7 +59,8 @@
59 59 if (!ret) {
60 60 ret = fit_add_verification_data(params->keydir, dest_blob, ptr,
61 61 params->comment,
62   - params->require_keys);
  62 + params->require_keys,
  63 + params->engine_id);
63 64 }
64 65  
65 66 if (dest_blob) {
... ... @@ -149,7 +149,7 @@
149 149  
150 150 static int fit_image_setup_sig(struct image_sign_info *info,
151 151 const char *keydir, void *fit, const char *image_name,
152   - int noffset, const char *require_keys)
  152 + int noffset, const char *require_keys, const char *engine_id)
153 153 {
154 154 const char *node_name;
155 155 char *algo_name;
... ... @@ -170,6 +170,7 @@
170 170 info->checksum = image_get_checksum_algo(algo_name);
171 171 info->crypto = image_get_crypto_algo(algo_name);
172 172 info->require_keys = require_keys;
  173 + info->engine_id = engine_id;
173 174 if (!info->checksum || !info->crypto) {
174 175 printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
175 176 algo_name, node_name, image_name);
176 177  
... ... @@ -194,12 +195,13 @@
194 195 * @size: size of data in bytes
195 196 * @comment: Comment to add to signature nodes
196 197 * @require_keys: Mark all keys as 'required'
  198 + * @engine_id: Engine to use for signing
197 199 * @return 0 if ok, -1 on error
198 200 */
199 201 static int fit_image_process_sig(const char *keydir, void *keydest,
200 202 void *fit, const char *image_name,
201 203 int noffset, const void *data, size_t size,
202   - const char *comment, int require_keys)
  204 + const char *comment, int require_keys, const char *engine_id)
203 205 {
204 206 struct image_sign_info info;
205 207 struct image_region region;
... ... @@ -209,7 +211,7 @@
209 211 int ret;
210 212  
211 213 if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
212   - require_keys ? "image" : NULL))
  214 + require_keys ? "image" : NULL, engine_id))
213 215 return -1;
214 216  
215 217 node_name = fit_get_name(fit, noffset, NULL);
216 218  
... ... @@ -288,11 +290,12 @@
288 290 * @image_noffset: Requested component image node
289 291 * @comment: Comment to add to signature nodes
290 292 * @require_keys: Mark all keys as 'required'
  293 + * @engine_id: Engine to use for signing
291 294 * @return: 0 on success, <0 on failure
292 295 */
293 296 int fit_image_add_verification_data(const char *keydir, void *keydest,
294 297 void *fit, int image_noffset, const char *comment,
295   - int require_keys)
  298 + int require_keys, const char *engine_id)
296 299 {
297 300 const char *image_name;
298 301 const void *data;
... ... @@ -329,7 +332,7 @@
329 332 strlen(FIT_SIG_NODENAME))) {
330 333 ret = fit_image_process_sig(keydir, keydest,
331 334 fit, image_name, noffset, data, size,
332   - comment, require_keys);
  335 + comment, require_keys, engine_id);
333 336 }
334 337 if (ret)
335 338 return ret;
... ... @@ -569,7 +572,8 @@
569 572  
570 573 static int fit_config_process_sig(const char *keydir, void *keydest,
571 574 void *fit, const char *conf_name, int conf_noffset,
572   - int noffset, const char *comment, int require_keys)
  575 + int noffset, const char *comment, int require_keys,
  576 + const char *engine_id)
573 577 {
574 578 struct image_sign_info info;
575 579 const char *node_name;
... ... @@ -587,7 +591,7 @@
587 591 return -1;
588 592  
589 593 if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
590   - require_keys ? "conf" : NULL))
  594 + require_keys ? "conf" : NULL, engine_id))
591 595 return -1;
592 596  
593 597 ret = info.crypto->sign(&info, region, region_count, &value,
... ... @@ -635,7 +639,7 @@
635 639  
636 640 static int fit_config_add_verification_data(const char *keydir, void *keydest,
637 641 void *fit, int conf_noffset, const char *comment,
638   - int require_keys)
  642 + int require_keys, const char *engine_id)
639 643 {
640 644 const char *conf_name;
641 645 int noffset;
... ... @@ -654,7 +658,7 @@
654 658 strlen(FIT_SIG_NODENAME))) {
655 659 ret = fit_config_process_sig(keydir, keydest,
656 660 fit, conf_name, conf_noffset, noffset, comment,
657   - require_keys);
  661 + require_keys, engine_id);
658 662 }
659 663 if (ret)
660 664 return ret;
... ... @@ -664,7 +668,8 @@
664 668 }
665 669  
666 670 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
667   - const char *comment, int require_keys)
  671 + const char *comment, int require_keys,
  672 + const char *engine_id)
668 673 {
669 674 int images_noffset, confs_noffset;
670 675 int noffset;
... ... @@ -687,7 +692,7 @@
687 692 * i.e. component image node.
688 693 */
689 694 ret = fit_image_add_verification_data(keydir, keydest,
690   - fit, noffset, comment, require_keys);
  695 + fit, noffset, comment, require_keys, engine_id);
691 696 if (ret)
692 697 return ret;
693 698 }
... ... @@ -710,7 +715,8 @@
710 715 noffset = fdt_next_subnode(fit, noffset)) {
711 716 ret = fit_config_add_verification_data(keydir, keydest,
712 717 fit, noffset, comment,
713   - require_keys);
  718 + require_keys,
  719 + engine_id);
714 720 if (ret)
715 721 return ret;
716 722 }
... ... @@ -76,6 +76,7 @@
76 76 bool external_data; /* Store data outside the FIT */
77 77 bool quiet; /* Don't output text in normal operation */
78 78 unsigned int external_offset; /* Add padding to external data */
  79 + const char *engine_id; /* Engine to use for signing */
79 80 };
80 81  
81 82 /*
... ... @@ -98,14 +98,15 @@
98 98 " -i => input filename for ramdisk file\n");
99 99 #ifdef CONFIG_FIT_SIGNATURE
100 100 fprintf(stderr,
101   - "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r]\n"
  101 + "Signing / verified boot options: [-E] [-k keydir] [-K dtb] [ -c <comment>] [-p addr] [-r] [-N engine]\n"
102 102 " -E => place data outside of the FIT structure\n"
103 103 " -k => set directory containing private keys\n"
104 104 " -K => write public keys to this .dtb file\n"
105 105 " -c => add comment in signature node\n"
106 106 " -F => re-sign existing FIT image\n"
107 107 " -p => place external data at a static position\n"
108   - " -r => mark keys used as 'required' in dtb\n");
  108 + " -r => mark keys used as 'required' in dtb\n"
  109 + " -N => engine to use for signing (pkcs11)\n");
109 110 #else
110 111 fprintf(stderr,
111 112 "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
... ... @@ -143,7 +144,7 @@
143 144 int opt;
144 145  
145 146 while ((opt = getopt(argc, argv,
146   - "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:p:O:rR:qsT:vVx")) != -1) {
  147 + "a:A:b:c:C:d:D:e:Ef:Fk:i:K:ln:N:p:O:rR:qsT:vVx")) != -1) {
147 148 switch (opt) {
148 149 case 'a':
149 150 params.addr = strtoull(optarg, &ptr, 16);
... ... @@ -223,6 +224,9 @@
223 224 break;
224 225 case 'n':
225 226 params.imagename = optarg;
  227 + break;
  228 + case 'N':
  229 + params.engine_id = optarg;
226 230 break;
227 231 case 'O':
228 232 params.os = genimg_get_os_id(optarg);