Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyTool improvements to allow ASN.1/DER private keys with ECC #461

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/Signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ Two options are supported:

- `-g privkey.der` to generate a new keypair, add the public key to the keystore and save the private key in a new file `privkey.der`
- `-i existing.der` to import an existing public key from `existing.der`
- `--der` save generated private key in DER format.

Arguments are not exclusive, and can be repeated more than once to populate a keystore with multiple keys.

One option must be specified to select the algorithm enabled in the keystore (e.g. `--ed25519` or `--rsa3072`. See the section "Public key signature options" for the sign tool for the available options.
One option must be specified to select the algorithm enabled in the keystore (e.g. `--ed25519` or `--rsa3072`). See the section "Public key signature options" for the sign tool for the available options.

The files generate by the keygen tool is the following:

Expand Down Expand Up @@ -175,6 +176,9 @@ is provided:
`BASE_SIGNED_IMG.BIN` and the new image signed starting from `IMAGE.BIN`. The
result is stored in a file ending in `_signed_diff.bin`.

The compression scheme used is Bentley–McIlroy.


#### Policy signing (for sealing/unsealing with a TPM)

Provides a PCR mask and digest to be signed and included in the header. The signing key is used to sign the digest.
Expand Down
67 changes: 44 additions & 23 deletions tools/keytools/keygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@
/* Globals */
static FILE *fpub, *fpub_image;
static int force = 0;
#if defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)
static int saveAsDer = 1; /* For Renesas PKA default to save as DER/ASN.1 */
#else
static int saveAsDer = 0;
#endif
static WC_RNG rng;

#ifndef KEYSLOT_MAX_PUBKEY_SIZE
Expand All @@ -130,11 +137,14 @@ const char Cfile_Banner[]="/* Keystore file for wolfBoot, automatically generate
" * used by wolfBoot to verify the updates.\n"
" */"
"\n#include <stdint.h>\n#include \"wolfboot/wolfboot.h\"\n#include \"keystore.h\"\n"
#if defined(WOLFBOOT_RENESAS_TSIP) || defined(WOLFBOOT_RENESAS_RSIP)
"#include \"user_settings.h\"\n"
#if defined(WOLFBOOT_RENESAS_TSIP)
"#include \"key_data.h\"\n"
#elif defined(WOLFBOOT_RENESAS_RSIP)
"#include \"rsa_pub.h\"\n"
#endif
#endif
"#ifdef WOLFBOOT_NO_SIGN\n\t#define NUM_PUBKEYS 0\n#else\n\n"
"#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t"
"#error Key algorithm mismatch. Remove old keys via 'make keysclean'\n"
Expand All @@ -143,7 +153,7 @@ const char Cfile_Banner[]="/* Keystore file for wolfBoot, automatically generate
const char Store_hdr[] = "\n"
"#if defined(__APPLE__) && defined(__MACH__)\n"
"#define KEYSTORE_SECTION __attribute__((section (\"__KEYSTORE,__keystore\")))\n"
"#elif defined(__CCRX__)\n"
"#elif defined(__CCRX__) /* Renesas RX */\n"
"#define KEYSTORE_SECTION\n"
"#elif defined(TARGET_x86_64_efi)\n"
"#define KEYSTORE_SECTION\n"
Expand All @@ -153,14 +163,6 @@ const char Store_hdr[] = "\n"
"#define NUM_PUBKEYS %d\n"
"const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {\n\n";
const char Slot_hdr[] =
#if defined(WOLFBOOT_RENESAS_RSIP)
"\t#if !defined(WOLFBOOT_RENESAS_RSIP)\n"
#endif
"\t/* Key associated to file '%s' */\n"
"\t{\n\t\t.slot_id = %d,\n\t\t.key_type = %s,\n"
"\t\t.part_id_mask = 0x%08X,\n\t\t.pubkey_size = %s,\n"
"\t\t.pubkey = {\n\t\t\t";
const char Slot_hdr_int_size[] =
"\t /* Key associated to file '%s' */\n"
"\t{\n\t\t.slot_id = %d,\n\t\t.key_type = %s,\n"
"\t\t.part_id_mask = 0x%08X,\n\t\t.pubkey_size = %u,\n"
Expand All @@ -174,8 +176,8 @@ const char Slot_hdr_int_size[] =
#endif
"\t\t\t";
const char Pubkey_footer[] =
#if defined(WOLFBOOT_RENESAS_RSIP) ||\
defined(WOLFBOOT_RENESAS_TSIP) ||\
#if defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)
"\n\t#endif\n"
#endif
Expand Down Expand Up @@ -251,8 +253,9 @@ const char Keystore_API[] =
static void usage(const char *pname) /* implies exit */
{
printf("Usage: %s [--ed25519 | --ed448 | --ecc256 | --ecc384 "
"| --ecc521 | --rsa2048 | --rsa3072 "
"| --rsa4096 ] [-g privkey] [-i pubkey] [-keystoreDir dir] [--id {list}] \n", pname);
"| --ecc521 | --rsa2048 | --rsa3072 | --rsa4096 ] "
"[-g privkey] [-i pubkey] [-keystoreDir dir] "
"[--id {list}] [--der]\n", pname);
exit(125);
}

Expand Down Expand Up @@ -373,10 +376,7 @@ void keystore_add(uint32_t ktype, uint8_t *key, uint32_t sz, const char *keyfile
struct keystore_slot sl;
size_t slot_size;

if (ktype == KEYGEN_RSA2048 || ktype == KEYGEN_RSA3072 || ktype == KEYGEN_RSA4096)
fprintf(fpub, Slot_hdr_int_size, keyfile, id_slot, KType[ktype], id_mask, sz);
else
fprintf(fpub, Slot_hdr, keyfile, id_slot, KType[ktype], id_mask, KSize[ktype]);
fprintf(fpub, Slot_hdr, keyfile, id_slot, KType[ktype], id_mask, sz);
fwritekey(key, sz, fpub);
fprintf(fpub, Pubkey_footer);
fprintf(fpub, Slot_footer);
Expand Down Expand Up @@ -450,11 +450,14 @@ static void keygen_rsa(const char *keyfile, int kbits, uint32_t id_mask)
static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size,
uint32_t id_mask)
{
int ret;
ecc_key k;
uint8_t Qx[MAX_ECC_KEY_SIZE], Qy[MAX_ECC_KEY_SIZE], d[MAX_ECC_KEY_SIZE];
uint32_t qxsize = ecc_key_size,
qysize = ecc_key_size,
dsize = ecc_key_size;
uint8_t priv_der[ECC_BUFSIZE];
int privlen;
uint8_t k_buffer[2 * MAX_ECC_KEY_SIZE];
FILE *fpriv;

Expand All @@ -465,9 +468,17 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size,
exit(1);
}

ret = wc_EccKeyToDer(&k, priv_der, (word32)sizeof(priv_der));
if (ret <= 0) {
fprintf(stderr, "Unable to export private key to DER\n");
exit(2);
}
privlen = ret;
ret = 0;

if (wc_ecc_export_private_raw(&k, Qx, &qxsize, Qy, &qysize, d, &dsize) != 0)
{
fprintf(stderr, "Unable to export private key to DER\n");
fprintf(stderr, "Unable to export private key to raw\n");
exit(2);
}

Expand All @@ -486,12 +497,19 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size,
exit(3);
}


fwrite(Qx, qxsize, 1, fpriv);
fwrite(Qy, qysize, 1, fpriv);
fwrite(d, dsize, 1, fpriv);
if (saveAsDer) {
/* save file as standard ASN.1 / DER */
fwrite(priv_der, privlen, 1, fpriv);
}
else {
/* save file as RAW public X/Y and private K */
fwrite(Qx, qxsize, 1, fpriv);
fwrite(Qy, qysize, 1, fpriv);
fwrite(d, dsize, 1, fpriv);
}
fclose(fpriv);
memcpy(k_buffer, Qx, ecc_key_size);

memcpy(k_buffer, Qx, ecc_key_size);
memcpy(k_buffer + ecc_key_size, Qy, ecc_key_size);

if (ecc_key_size == 32)
Expand Down Expand Up @@ -974,6 +992,9 @@ int main(int argc, char** argv)
else if (strcmp(argv[i], "--force") == 0) {
force = 1;
}
else if (strcmp(argv[i], "--der") == 0) {
saveAsDer = 1;
}
else if (strcmp(argv[i], "-g") == 0) {
key_gen_check(argv[i + 1]);
i++;
Expand Down
Loading
Loading