Skip to content

Commit eba3f65

Browse files
committed
keygen: Added --id {list} option, updated docs
1 parent 18cf8de commit eba3f65

File tree

2 files changed

+99
-47
lines changed

2 files changed

+99
-47
lines changed

docs/keystore.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,25 @@ By default, when a new keystore is created, the permissions mask is set
117117
to `KEY_VERIFY_ALL`, which means that the key can be used to verify a firmware
118118
targeting any partition id.
119119

120-
To restrict the permissions for single keys, it would be sufficient to change the value
121-
of their `part_id_mask` attributes.
122-
123120
The `part_id_mask` value is a bitmask, where each bit represent a different partition.
124121
The bit '0' is reserved for wolfBoot self-update, while typically the main firmware partition
125122
is associated to id 1, so it requires a key with the bit '1' set. In other words, signing a
126123
partition with `--id 3` would require turning on bit '3' in the mask, i.e. adding (1U << 3) to it.
127124

128-
Beside `KEY_VERIFY_ALL`, pre-defined mask values can also be used here:
125+
To restrict the permissions for single keys, it would be sufficient to change the value
126+
of each key `part_id_mask`. This is done via the `--id` command line option for keygen.
127+
Each generated or imported key can be associatd with a number of partition by passing the
128+
partition IDs in a comma-separated list, e.g.:
129+
130+
```
131+
keygen --ecc256 -g generic.key --id 1,2,3 -g restricted.key
132+
```
129133

130-
- `KEY_VERIFY_APP_ONLY` only verifies the main application, with partition id 1
131-
- `KEY_VERIFY_SELF_ONLY` this key can only be used to authenticate wolfBoot self-updates (id = 0)
132-
- `KEY_VERIFY_ONLY_ID(N)` macro that can be used to restrict the usage of the key to a specific partition id `N`
134+
Generates two keypairs, `generic.key` and `restricted.key`. The former assumes the
135+
default mask `KEY_VERIFY_ALL`, which makes it possible to use it to authenticate any
136+
of the system components. The latter instead, will carry a mask with only the bits
137+
'1', '2', and '3' set (mask = b00001110 =0x000e), allowing the usage only with the assigned
138+
partition IDs.
133139

134140

135141
### Importing public keys

tools/keytools/keygen.c

Lines changed: 86 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static int force = 0;
9898
static WC_RNG rng;
9999

100100
#ifndef KEYSLOT_MAX_PUBKEY_SIZE
101-
#define KEYSLOT_MAX_PUBKEY_SIZE 576
101+
#define KEYSLOT_MAX_PUBKEY_SIZE 576
102102
#endif
103103

104104
struct keystore_slot {
@@ -136,11 +136,11 @@ const char Store_hdr[] = "\n"
136136
"const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {\n\n";
137137
const char Slot_hdr[] = "\t/* Key associated to file '%s' */\n"
138138
"\t{\n\t\t.slot_id = %d,\n\t\t.key_type = %s,\n"
139-
"\t\t.part_id_mask = KEY_VERIFY_ALL,\n\t\t.pubkey_size = %s,\n"
139+
"\t\t.part_id_mask = 0x%08X,\n\t\t.pubkey_size = %s,\n"
140140
"\t\t.pubkey = {\n\t\t\t";
141141
const char Slot_hdr_int_size[] = "\t /* Key associated to file '%s' */\n"
142142
"\t{\n\t\t.slot_id = %d,\n\t\t.key_type = %s,\n"
143-
"\t\t.part_id_mask = KEY_VERIFY_ALL,\n\t\t.pubkey_size = %u,\n"
143+
"\t\t.part_id_mask = 0x%08X,\n\t\t.pubkey_size = %u,\n"
144144
"\t\t.pubkey = {\n\t\t\t";
145145
const char Pubkey_footer[] = "\n\t\t},";
146146
const char Slot_footer[] = "\n\t},\n\n";
@@ -203,7 +203,7 @@ static void usage(const char *pname) /* implies exit */
203203
{
204204
printf("Usage: %s [--ed25519 | --ed448 | --ecc256 | --ecc384 "
205205
"| --ecc521 | --rsa2048 | --rsa3072 "
206-
"| --rsa4096 ] [-g privkey] [-i pubkey] [-keystoreDir dir] \n", pname);
206+
"| --rsa4096 ] [-g privkey] [-i pubkey] [-keystoreDir dir] [--id {list}] \n", pname);
207207
exit(125);
208208
}
209209

@@ -264,13 +264,15 @@ const char KName[][8] = {
264264
};
265265

266266
#define MAX_PUBKEYS 64
267-
#define MAX_KEYPAIRS 64
268267
static char *imported_pubkeys[MAX_PUBKEYS];
269268
static int imported_pubkeys_type[MAX_PUBKEYS];
269+
static uint32_t imported_pubkeys_id_mask[MAX_PUBKEYS];
270270
static int n_imported = 0;
271271

272+
#define MAX_KEYPAIRS 64
272273
static char *generated_keypairs[MAX_KEYPAIRS];
273274
static int generated_keypairs_type[MAX_KEYPAIRS];
275+
static uint32_t generated_keypairs_id_mask[MAX_KEYPAIRS];
274276
static int n_generated = 0;
275277

276278
static uint32_t get_pubkey_size(uint32_t keyType)
@@ -309,27 +311,29 @@ static uint32_t get_pubkey_size(uint32_t keyType)
309311
return size;
310312
}
311313

312-
void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile)
314+
void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile,
315+
uint32_t id_mask)
313316
{
314317
static int id_slot = 0;
315318
struct keystore_slot sl;
316319
size_t slot_size;
317320

318321
if (ktype == KEYGEN_RSA2048 || ktype == KEYGEN_RSA3072 || ktype == KEYGEN_RSA4096)
319-
fprintf(fpub, Slot_hdr_int_size, keyfile, id_slot, KType[ktype], sz);
322+
fprintf(fpub, Slot_hdr_int_size, keyfile, id_slot, KType[ktype], id_mask, sz);
320323
else
321-
fprintf(fpub, Slot_hdr, keyfile, id_slot, KType[ktype], KSize[ktype]);
324+
fprintf(fpub, Slot_hdr, keyfile, id_slot, KType[ktype], id_mask, KSize[ktype]);
322325
fwritekey(key, sz, fpub);
323326
fprintf(fpub, Pubkey_footer);
324327
fprintf(fpub, Slot_footer);
325328
printf("Associated key file: %s\n", keyfile);
329+
printf("Partition ids mask: %08x\n", id_mask);
326330
printf("Key type : %s\n", KName[ktype]);
327331
printf("Public key slot: %u\n", id_slot);
328332

329333
memset(&sl, 0, sizeof(sl));
330334
sl.slot_id = id_slot;
331335
sl.key_type = ktype;
332-
sl.part_id_mask = 0xFFFFFFFF;
336+
sl.part_id_mask = id_mask;
333337

334338
sl.pubkey_size = get_pubkey_size(ktype);
335339
memcpy(sl.pubkey, key, sl.pubkey_size);
@@ -341,7 +345,7 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile
341345

342346

343347
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
344-
static void keygen_rsa(const char *keyfile, int kbits)
348+
static void keygen_rsa(const char *keyfile, int kbits, uint32_t id_mask)
345349
{
346350
RsaKey k;
347351
uint8_t priv_der[4096], pub_der[2048];
@@ -377,18 +381,19 @@ static void keygen_rsa(const char *keyfile, int kbits)
377381
fclose(fpriv);
378382

379383
if (kbits == 2048)
380-
keystore_add(KEYGEN_RSA2048, pub_der, publen, keyfile);
384+
keystore_add(KEYGEN_RSA2048, pub_der, publen, keyfile, id_mask);
381385
else if (kbits == 3072)
382-
keystore_add(KEYGEN_RSA3072, pub_der, publen, keyfile);
386+
keystore_add(KEYGEN_RSA3072, pub_der, publen, keyfile, id_mask);
383387
else if (kbits == 4096)
384-
keystore_add(KEYGEN_RSA4096, pub_der, publen, keyfile);
388+
keystore_add(KEYGEN_RSA4096, pub_der, publen, keyfile, id_mask);
385389
}
386390
#endif
387391

388392
#ifdef HAVE_ECC
389393
#define MAX_ECC_KEY_SIZE 66
390394

391-
static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size)
395+
static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size,
396+
uint32_t id_mask)
392397
{
393398
ecc_key k;
394399
uint8_t Qx[MAX_ECC_KEY_SIZE], Qy[MAX_ECC_KEY_SIZE], d[MAX_ECC_KEY_SIZE];
@@ -403,12 +408,14 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size)
403408
exit(1);
404409
}
405410

406-
if (wc_ecc_export_private_raw(&k, Qx, &qxsize, Qy, &qysize, d, &dsize) != 0) {
411+
if (wc_ecc_export_private_raw(&k, Qx, &qxsize, Qy, &qysize, d, &dsize) != 0)
412+
{
407413
fprintf(stderr, "Unable to export private key to DER\n");
408414
exit(2);
409415
}
410416

411-
if (wc_ecc_export_public_raw(&k, Qx, &qxsize, Qy, &qysize ) != 0) {
417+
if (wc_ecc_export_public_raw(&k, Qx, &qxsize, Qy, &qysize ) != 0)
418+
{
412419
fprintf(stderr, "Unable to export public key\n");
413420
exit(3);
414421
}
@@ -417,7 +424,8 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size)
417424

418425
fpriv = fopen(priv_fname, "wb");
419426
if (fpriv == NULL) {
420-
fprintf(stderr, "Unable to open file '%s' for writing: %s", priv_fname, strerror(errno));
427+
fprintf(stderr, "Unable to open file '%s' for writing: %s", priv_fname,
428+
strerror(errno));
421429
exit(3);
422430
}
423431

@@ -430,17 +438,17 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size)
430438
memcpy(k_buffer + ecc_key_size, Qy, ecc_key_size);
431439

432440
if (ecc_key_size == 32)
433-
keystore_add(KEYGEN_ECC256, k_buffer, 2 * ecc_key_size, priv_fname);
441+
keystore_add(KEYGEN_ECC256, k_buffer, 2 * ecc_key_size, priv_fname, id_mask);
434442
else if (ecc_key_size == 48)
435-
keystore_add(KEYGEN_ECC384, k_buffer, 2 * ecc_key_size, priv_fname);
443+
keystore_add(KEYGEN_ECC384, k_buffer, 2 * ecc_key_size, priv_fname, id_mask);
436444
else if (ecc_key_size == 66)
437-
keystore_add(KEYGEN_ECC521, k_buffer, 2 * ecc_key_size, priv_fname);
445+
keystore_add(KEYGEN_ECC521, k_buffer, 2 * ecc_key_size, priv_fname, id_mask);
438446
}
439447
#endif
440448

441449

442450
#ifdef HAVE_ED25519
443-
static void keygen_ed25519(const char *privkey)
451+
static void keygen_ed25519(const char *privkey, uint32_t id_mask)
444452
{
445453
ed25519_key k;
446454
uint8_t priv[32], pub[32];
@@ -466,12 +474,12 @@ static void keygen_ed25519(const char *privkey)
466474
fwrite(priv, 32, 1, fpriv);
467475
fwrite(pub, 32, 1, fpriv);
468476
fclose(fpriv);
469-
keystore_add(KEYGEN_ED25519, pub, ED25519_PUB_KEY_SIZE, privkey);
477+
keystore_add(KEYGEN_ED25519, pub, ED25519_PUB_KEY_SIZE, privkey, id_mask);
470478
}
471479
#endif
472480

473481
#ifdef HAVE_ED448
474-
static void keygen_ed448(const char *privkey)
482+
static void keygen_ed448(const char *privkey, uint32_t id_mask)
475483
{
476484
ed448_key k;
477485
uint8_t priv[ED448_KEY_SIZE], pub[ED448_PUB_KEY_SIZE];
@@ -497,14 +505,14 @@ static void keygen_ed448(const char *privkey)
497505
fwrite(priv, ED448_KEY_SIZE, 1, fpriv);
498506
fwrite(pub, ED448_PUB_KEY_SIZE, 1, fpriv);
499507
fclose(fpriv);
500-
keystore_add(KEYGEN_ED448, pub, ED448_PUB_KEY_SIZE, privkey);
508+
keystore_add(KEYGEN_ED448, pub, ED448_PUB_KEY_SIZE, privkey, id_mask);
501509
}
502510
#endif
503511

504512
#if defined(WOLFSSL_HAVE_LMS)
505513
#include "../lms/lms_common.h"
506514

507-
static void keygen_lms(const char *priv_fname)
515+
static void keygen_lms(const char *priv_fname, uint32_t id_mask)
508516
{
509517
FILE * fpriv;
510518
LmsKey key;
@@ -577,7 +585,7 @@ static void keygen_lms(const char *priv_fname)
577585
fwrite(lms_pub, KEYSTORE_PUBKEY_SIZE_LMS, 1, fpriv);
578586
fclose(fpriv);
579587

580-
keystore_add(KEYGEN_LMS, lms_pub, KEYSTORE_PUBKEY_SIZE_LMS, priv_fname);
588+
keystore_add(KEYGEN_LMS, lms_pub, KEYSTORE_PUBKEY_SIZE_LMS, priv_fname, id_mask);
581589

582590
wc_LmsKey_Free(&key);
583591
}
@@ -604,57 +612,57 @@ static void key_gen_check(const char *kfilename)
604612
}
605613
}
606614

607-
static void key_generate(uint32_t ktype, const char *kfilename)
615+
static void key_generate(uint32_t ktype, const char *kfilename, uint32_t id_mask)
608616
{
609617
printf("Generating key (type: %s)\n", KName[ktype]);
610618
fflush(stdout);
611619

612620
switch (ktype) {
613621
#ifdef HAVE_ED25519
614622
case KEYGEN_ED25519:
615-
keygen_ed25519(kfilename);
623+
keygen_ed25519(kfilename, id_mask);
616624
break;
617625
#endif
618626

619627
#ifdef HAVE_ED448
620628
case KEYGEN_ED448:
621-
keygen_ed448(kfilename);
629+
keygen_ed448(kfilename, id_mask);
622630
break;
623631
#endif
624632

625633
#ifdef HAVE_ECC
626634
case KEYGEN_ECC256:
627-
keygen_ecc(kfilename, 32);
635+
keygen_ecc(kfilename, 32, id_mask);
628636
break;
629637
case KEYGEN_ECC384:
630-
keygen_ecc(kfilename, 48);
638+
keygen_ecc(kfilename, 48, id_mask);
631639
break;
632640
case KEYGEN_ECC521:
633-
keygen_ecc(kfilename, 66);
641+
keygen_ecc(kfilename, 66, id_mask);
634642
break;
635643
#endif
636644

637645
#ifndef NO_RSA
638646
case KEYGEN_RSA2048:
639-
keygen_rsa(kfilename, 2048);
647+
keygen_rsa(kfilename, 2048, id_mask);
640648
break;
641649
case KEYGEN_RSA3072:
642-
keygen_rsa(kfilename, 3072);
650+
keygen_rsa(kfilename, 3072, id_mask);
643651
break;
644652
case KEYGEN_RSA4096:
645-
keygen_rsa(kfilename, 4096);
653+
keygen_rsa(kfilename, 4096, id_mask);
646654
break;
647655
#endif
648656

649657
#ifdef WOLFSSL_HAVE_LMS
650658
case KEYGEN_LMS:
651-
keygen_lms(kfilename);
659+
keygen_lms(kfilename, id_mask);
652660
break;
653661
#endif
654662
} /* end switch */
655663
}
656664

657-
static void key_import(uint32_t ktype, const char *fname)
665+
static void key_import(uint32_t ktype, const char *fname, uint32_t id_mask)
658666
{
659667
int ret = 0;
660668
int initKey = 0;
@@ -731,14 +739,39 @@ static void key_import(uint32_t ktype, const char *fname)
731739
}
732740

733741
/* needs to be r - rawOffset because rsa keys are not exactly keysize */
734-
keystore_add(ktype, buf, readLen, fname);
742+
keystore_add(ktype, buf, readLen, fname, id_mask);
743+
}
744+
745+
static uint32_t parse_id(char *idstr)
746+
{
747+
uint32_t mask = 0;
748+
uint32_t n;
749+
char *p = idstr;
750+
char *end = NULL;
751+
do {
752+
end = strchr(p, ',');
753+
if (end)
754+
*end = 0;
755+
n = strtol(p, NULL, 10);
756+
if (n == (uint32_t)(-1))
757+
return 0;
758+
if (n > 31)
759+
return 0;
760+
mask |= (1 << n);
761+
if (end)
762+
p = end + 1;
763+
else
764+
p = NULL;
765+
} while (p && *p);
766+
return mask;
735767
}
736768

737769
int main(int argc, char** argv)
738770
{
739771
int i;
740772
int keytype = 0;
741773
uint32_t n_pubkeys = 0;
774+
uint32_t part_id_mask = 0xFFFFFFFF; /* Default: key verify all */
742775

743776
#ifdef DEBUG_SIGNTOOL
744777
wolfSSL_Debugging_ON();
@@ -788,6 +821,7 @@ int main(int argc, char** argv)
788821
n_pubkeys++;
789822
generated_keypairs[n_generated] = argv[i];
790823
generated_keypairs_type[n_generated] = keytype;
824+
generated_keypairs_id_mask[n_generated] = part_id_mask;
791825
n_generated++;
792826
continue;
793827
}
@@ -796,6 +830,7 @@ int main(int argc, char** argv)
796830
n_pubkeys++;
797831
imported_pubkeys[n_imported] = argv[i];
798832
imported_pubkeys_type[n_imported] = keytype;
833+
imported_pubkeys_id_mask[n_imported] = part_id_mask;
799834
n_imported++;
800835
continue;
801836
}
@@ -806,6 +841,15 @@ int main(int argc, char** argv)
806841
i++;
807842
continue;
808843
}
844+
else if (strcmp(argv[i], "--id") == 0) {
845+
i++;
846+
part_id_mask = parse_id(argv[i]);
847+
if (part_id_mask == 0) {
848+
fprintf(stderr, "Invalid list of partition ids.\n");
849+
usage(argv[0]);
850+
}
851+
852+
}
809853
else {
810854
fprintf(stderr, "Invalid argument '%s'.", argv[i]);
811855
usage(argv[0]);
@@ -829,10 +873,12 @@ int main(int argc, char** argv)
829873
fprintf(fpub, Store_hdr, n_pubkeys);
830874

831875
for (i = 0; i < n_imported; i++) {
832-
key_import(imported_pubkeys_type[i], imported_pubkeys[i]);
876+
key_import(imported_pubkeys_type[i], imported_pubkeys[i],
877+
imported_pubkeys_id_mask[i]);
833878
}
834879
for (i = 0; i < n_generated; i++) {
835-
key_generate(generated_keypairs_type[i], generated_keypairs[i]);
880+
key_generate(generated_keypairs_type[i], generated_keypairs[i],
881+
generated_keypairs_id_mask[i]);
836882
}
837883
wc_FreeRng(&rng);
838884
fprintf(fpub, Store_footer);

0 commit comments

Comments
 (0)