Skip to content

Commit

Permalink
TSIP ECDSA support. Refactor sign tool ECDSA/RSA key load. Add sign k…
Browse files Browse the repository at this point in the history
…ey load support for ECC private key as normal ASN.1/DER (default is raw pub x/y, priv d).
  • Loading branch information
dgarske committed Jun 26, 2024
1 parent eb7dcac commit 2a0a6fa
Show file tree
Hide file tree
Showing 11 changed files with 397 additions and 406 deletions.
4 changes: 2 additions & 2 deletions IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ $ openssl rsa -inform der -in ./pri-rsa2048.der -pubout -out ./pub-rsa2048.pem
Generate a c header and source file from PEM file :
```
$ export PATH="$PATH:C:\Renesas\SecurityKeyManagementTool\cli"
$ skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public -output key_data.c -filetype csource -keyname rsa2048_pub
$ skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public -output key_data.c -filetype csource -keyname enc_pub_key
```

The value of option `/keyname` becomes structure name and macro definition defined in key_data.h. Therefore, please specify `rsa2048_pub` like above unless there is some particular reason.
The value of option `-keyname` becomes structure name and macro definition defined in key_data.h. Therefore, please specify `enc_pub_key` like above unless there is some particular reason.

Copy a generated c header file, which is `key_data.h` to `<wolfBoot>/include/` folder

Expand Down
2 changes: 1 addition & 1 deletion IDE/Renesas/e2studio/RZN2L/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
#define RENESAS_RSIP_INSTALLEDKEY_FLASH_ADDR 0x60200000
#define RENESAS_RSIP_INSTALLEDKEY_RAM_ADDR 0x10000100
#define RENESAS_DEVID 7890

#if defined(WOLFBOOT_SIGN_RSA3072) ||\
defined(WOLFBOOT_SIGN_RSA4096) ||\
defined(WOLFBOOT_SIGN_ED25519) ||\
Expand Down
27 changes: 24 additions & 3 deletions docs/Renesas.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ Platforms Supported:
- [IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md](/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md)

All of the Renesas examples support using e2Studio.
The Renesas RX parts support using the rx-gcc cross compiler with the default Makefile and example .config files.
The Renesas RX parts support using wolfBoot Makefile's with the rx-elf-gcc cross-compiler and example .config files.

### RX TSIP

1) Setup a Renesas KeyWrap account and do the PGP key exchange.
https://dlm.renesas.com/keywrap
You will get a public key from Renesas `keywrap-pub.key` that needs imported to PGP/GPG.
Note: You cannot use RSA 4096-bit key, must be 2048 or 3072.
Note: You cannot use RSA 4096-bit key, must be RSA-2048 or RSA-3072.

2) Using "Security Key Management Tool" create 32-byte UFPK (User Factory Programming Key). This can be a random 32-byte value.
Example: Random 32-bytes `B94A2B96 1C755101 74F0C967 ECFC20B3 77C7FB25 6DB627B1 BFFADEE0 5EE98AC4`

3) Sign and Encrypt the 32-byte binary file with PGP the sample.key. Result is `sample.key.gpg`.
3) Sign and Encrypt the 32-byte binary file with PGP the `sample.key`. Result is `sample.key.gpg`.
Use GPG4Win and the Sign/Encrypt option. Sign with your own GPG key and encrypt with the Renesas public key.

4) Use https://dlm.renesas.com/keywrap to wrap `sample.key.gpg`.
Expand Down Expand Up @@ -72,3 +72,24 @@ Encrypted key: 5DD8D7E59E6AC85AE340BBA60AA8F8BE56C4C1FE02340C49EB8F36DA79B8D6640
7) Edit .config `PKA?=1`.

8) Rebuild wolfBoot. `make clean && make wolfboot.srec`

9) Sign application

Sign application using the created private key above `pri-ecc384.der`:

```
./tools/keytools/sign --ecc384 --sha256 test-app/image.bin pri-ecc384.der 1
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2010000
Update type: Firmware
Input image: test-app/image.bin
Selected cipher: ECC384
Selected hash : SHA256
Public key: pri-ecc384.der
Output image: test-app/image_v1_signed.bin
Target partition id : 1
image header size overridden by config value (1024 bytes)
Calculating SHA256 digest...
Signing the digest...
Output image(s) successfully created.
```
3 changes: 2 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
21 changes: 12 additions & 9 deletions hal/renesas-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,46 +372,49 @@ void hal_init(void)
case AUTH_KEY_RSA2048:
tsip_key_type = TSIP_RSA2048;
break;
case AUTH_KEY_RSA3072:
tsip_key_type = TSIP_RSA3072;
break;
case AUTH_KEY_RSA4096:
tsip_key_type = TSIP_RSA4096;
break;
case AUTH_KEY_ECC256:
tsip_key_type = TSIP_ECCP256;
break;
case AUTH_KEY_ECC384:
//tsip_key_type = TSIP_ECCP384;
//break;
tsip_key_type = TSIP_ECCP384;
break;
case AUTH_KEY_ECC521:
/* TODO: ECC */
case AUTH_KEY_ED25519:
case AUTH_KEY_ED448:
case AUTH_KEY_RSA3072:
default:
tsip_key_type = -1;
break;
}

if (tsip_key_type == -1) {
wolfBoot_printf("key type (%d) not supported\n", key_type);
hal_panic();
}
/* inform user key */

/* Load encrypted UFPK (User Factory Programming Key) */
tsip_inform_user_keys_ex(
(byte*)&encrypted_user_key_data->wufpk,
(byte*)&encrypted_user_key_data->initial_vector,
(byte*)&encrypted_user_key_data->encrypted_user_key,
0/* dummy */
);
/* TSIP specific RSA public key */

/* Load a wrapped public key into TSIP */
if (tsip_use_PublicKey_buffer_crypt(&pkInfo,
(const char*)&encrypted_user_key_data->encrypted_user_key,
sizeof(encrypted_user_key_data->encrypted_user_key),
tsip_key_type) != 0) {
tsip_key_type) != 0) {
wolfBoot_printf("ERROR tsip_use_PublicKey_buffer\n");
hal_panic();
}

/* Init Crypt Callback */
pkInfo.sing_hash_type = sha256_mac;
pkInfo.sign_hash_type = sha256_mac; /* TSIP does not support SHA2-384/512 */
pkInfo.keyflgs_crypt.bits.message_type = 1;
err = wc_CryptoCb_CryptInitRenesasCmn(NULL, &pkInfo);
if (err < 0) {
Expand Down
4 changes: 2 additions & 2 deletions include/keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ struct keystore_slot {

/* KeyStore API */
int keystore_num_pubkeys(void);
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\
defined(WOLFBOOT_RENESAS_TSIP) ||\
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_RSIP)
uint32_t *keystore_get_buffer(int id);
#else
Expand Down
9 changes: 7 additions & 2 deletions include/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -424,17 +424,22 @@ extern int tolower(int c);


/* Renesas */
#if defined(WOLFBOOT_RENESAS_TSIP) || defined(WOLFBOOT_RENESAS_RSIP) || \
#if defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)

#define WOLFBOOT_SMALL_STACK
#define WOLF_CRYPTO_CB
#define WOLF_CRYPTO_CB_ONLY_ECC
#define WOLF_CRYPTO_CB_ONLY_RSA
#define WOLFSSL_NO_SW_MATH

#ifdef WOLFBOOT_RENESAS_TSIP
#define WOLFSSL_RENESAS_TSIP
#define WOLFSSL_RENESAS_TSIP_VER 117
#define WOLFSSL_RENESAS_TSIP_CRYPT
#define WOLFSSL_RENESAS_TSIP_CRYPTONLY
#define WOLFSSL_NO_SW_MATH
#define NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH
#define RENESAS_TSIP_INSTALLEDKEY_ADDR 0xFFFF0000
#define ENCRYPTED_KEY_BYTE_SIZE ENC_PUB_KEY_SIZE /* from key_data.h */
#define RENESAS_DEVID 7890
Expand Down
30 changes: 24 additions & 6 deletions src/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,25 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
return;
}

#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_RSIP)
ret = wc_ecc_init_ex(&ecc, NULL, RENESAS_DEVID);
#else
ret = wc_ecc_init(&ecc);
#endif
if (ret == 0) {
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_RSIP)
/* The public key is wrapped and cannot be imported.
* Key must be loaded to TSIP and unwrapped.
* Then ECDSA crypto callback will perform verify on TSIP hardware */
wc_ecc_set_curve(&ecc, 0, ECC_KEY_TYPE);

VERIFY_FN(img, &verify_res, wc_ecc_verify_hash, sig, point_sz*2,
img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc)
#else
/* Import public key */
ret = wc_ecc_import_unsigned(&ecc, pubkey, pubkey + point_sz, NULL,
ECC_KEY_TYPE);
Expand All @@ -192,8 +209,9 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
VERIFY_FN(img, &verify_res, wc_ecc_verify_hash_ex, &r, &s,
img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc);
}
wc_ecc_free(&ecc);
#endif
}
wc_ecc_free(&ecc);
}

#endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */
Expand Down Expand Up @@ -274,22 +292,22 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
return;
}

/* wolfCrypt software RSA verify */
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\
defined(WOLFBOOT_RENESAS_TSIP) ||\
#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_RSIP)
ret = wc_InitRsaKey_ex(&rsa, NULL, RENESAS_DEVID);
if (ret == 0) {
XMEMCPY(output, sig, IMAGE_SIGNATURE_SIZE);
RSA_VERIFY_FN(ret,
wc_RsaSSL_Verify, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE,
output, IMAGE_SIGNATURE_SIZE, &rsa);
/* SCE SignatureVerify API has verified */
/* The crypto callback success also verifies hash */
if (ret == 0)
wolfBoot_image_confirm_signature_ok(img);
}
(void)digest_out;
#else
/* wolfCrypt software RSA verify */
ret = wc_InitRsaKey(&rsa, NULL);
if (ret == 0) {
/* Import public key */
Expand Down Expand Up @@ -1051,7 +1069,7 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
defined(WOLFBOOT_RENESAS_RSIP)
/* SCE wrapped key is installed at
* RENESAS_SCE_INSTALLEDKEY_ADDR
* TSIP encrypted key is installed ad
* TSIP encrypted key is installed at
* RENESAS_TSIP_INSTALLEDKEY_ADDR
*/
key_slot = 0;
Expand Down
1 change: 1 addition & 0 deletions test-app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ else
ifeq ($(ARCH),RENESAS_RX)
APP_OBJS:=app_renesas_rx.o ../test-app/libwolfboot.o ../src/boot_renesas.o ../src/boot_renesas_start.o ../hal/renesas-rx.o
LDFLAGS+=-ffreestanding -nostartfiles
CFLAGS+=-DWOLFBOOT_RENESAS_APP
else
APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../test-app/libwolfboot.o
endif
Expand Down
46 changes: 24 additions & 22 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 Down Expand Up @@ -246,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 @@ -442,18 +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;
#if defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)
int ret;
uint8_t priv_der[ECC_BUFSIZE];
int privlen;
#endif
uint8_t k_buffer[2 * MAX_ECC_KEY_SIZE];
FILE *fpriv;

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

#if defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)
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;
#endif

if (wc_ecc_export_private_raw(&k, Qx, &qxsize, Qy, &qysize, d, &dsize) != 0)
{
Expand All @@ -497,17 +497,16 @@ static void keygen_ecc(const char *priv_fname, uint16_t ecc_key_size,
exit(3);
}

#if defined(WOLFBOOT_RENESAS_RSIP) || \
defined(WOLFBOOT_RENESAS_TSIP) || \
defined(WOLFBOOT_RENESAS_SCEPROTECT)
/* 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);
#endif
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);
Expand Down Expand Up @@ -993,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

0 comments on commit 2a0a6fa

Please sign in to comment.