Skip to content

Commit

Permalink
Merge pull request wolfSSL#468 from danielinux/otpgen
Browse files Browse the repository at this point in the history
Add command line tool to generate otp.bin
  • Loading branch information
dgarske authored Jul 9, 2024
2 parents 626fcf0 + c6586f2 commit 78c9e11
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 7 deletions.
24 changes: 22 additions & 2 deletions .github/workflows/test-keytools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ jobs:
run: |
make SIGN=ECC256 HASH=SHA256
- name: Remove default keystore
run: |
rm -f src/keystore.c
- name: Generate external key
run: |
openssl ecparam -name prime256v1 -genkey -noout -outform DER -out private-key.der
Expand Down Expand Up @@ -75,6 +79,10 @@ jobs:
run: |
make SIGN=ED25519 HASH=SHA256
- name: Remove default keystore
run: |
rm -f src/keystore.c
- name: Generate external key
run: |
openssl genpkey -algorithm ed25519 -out private-key.der -outform DER
Expand Down Expand Up @@ -117,6 +125,10 @@ jobs:
run: |
make SIGN=RSA2048 HASH=SHA256
- name: Remove default keystore
run: |
rm -f src/keystore.c
- name: Generate external key
run: |
openssl genrsa -out private-key.pem 2048
Expand Down Expand Up @@ -224,6 +236,10 @@ jobs:
- name: Delete generated key
run: |
rm -f wolfboot_signing_private_key.der
- name: Remove generated keystore
run: |
rm -f src/keystore.c
- name: Run keygen with --id 0
run: |
Expand All @@ -233,6 +249,10 @@ jobs:
run: |
rm -f wolfboot_signing_private_key.der
- name: Remove generated keystore
run: |
rm -f src/keystore.c
- name: Run keygen with test id set
run: |
./tools/keytools/keygen --id 1,3,5,10,11,13,14 --ecc256 -g wolfboot_signing_private_key.der | grep "mask" | grep "00006c2a"
Expand All @@ -258,7 +278,7 @@ jobs:
run: |
./tools/keytools/sign --ecc256 --sha256 --custom-tlv 0x45 4 0x6f616943 test-app/image.elf wolfboot_signing_private_key.der 2
grep "Ciao" test-app/image_v2_signed.bin
- name: Sign app with custom buffer TLV included
run: |
./tools/keytools/sign --ecc256 --sha256 --custom-tlv-buffer 0x46 48656C6C6F20776F726C64 test-app/image.elf wolfboot_signing_private_key.der 3
Expand All @@ -268,5 +288,5 @@ jobs:
run: |
./tools/keytools/sign --ecc256 --sha256 --custom-tlv-string 0x46 "Hello world" test-app/image.elf wolfboot_signing_private_key.der 3
grep "Hello world" test-app/image_v3_signed.bin
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ tools/keytools/otp/otp-keystore-primer
tools/delta/bmdiff
tools/delta/bmpatch

# otp-keystore-gen binary
tools/keytools/otp/otp-keystore-gen

# Vim swap files
.*.swp

Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ clean:
$(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex
$(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT)
$(Q)rm -f $(OBJS)
$(Q)rm -f tools/keytools/otp/otp-keystore-gen
$(Q)$(MAKE) -C test-app -s clean
$(Q)$(MAKE) -C tools/check_config -s clean
$(Q)$(MAKE) -C stage1 -s clean
Expand Down Expand Up @@ -377,6 +378,9 @@ cppcheck:

otp: tools/keytools/otp/otp-keystore-primer.bin FORCE

otpgen:
make -C tools/keytools/otp otp-keystore-gen

tools/keytools/otp/otp-keystore-primer.bin: FORCE
make -C tools/keytools/otp clean
make -C tools/keytools/otp
Expand Down
21 changes: 19 additions & 2 deletions docs/flash-OTP.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,26 @@ The public keys are stored in the OTP area, after an initial 16-byte header that
keys stored, the size of each key, and other information.

In order for wolfBoot to start authenticating the firmware images at boot and upon update, the public keys
must be provisioned to the OTP area in a separate step, as described in the next section.
must be provisioned to the OTP area in a separate step, as described in the next sections.

### Provisioning the public keys to the OTP area
Depending on the target device, you can either prepare a binary image of the OTP area content, or use `otp-keystore-primer` firmware to directly provision the keys on the target.

### Creating an image of the OTP area content

It is possible to create a binary image of the content for the OTP area. The resulting file (otp.bin) can be manually provisioned using any external tool that allows writing to the target OTP area.

To compile the otp-keystore-gen tool using the current keystore content:

```
make otpgen
```

And then, to create the image file `otp.bin`:

tools/keytools/otp/otp-keystore-gen


### Directly provisioning the public keys to the OTP area (primer)

After enabling the `FLASH_OTP_KEYSTORE` option in your `.config` file, when you compile wolfBoot by running "make",
an additional application called `otp-keystore-primer` is generated under `tools/keytools/otp`. This application is used to
Expand Down
2 changes: 0 additions & 2 deletions include/otp_keystore.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
#include "hal/stm32h7.h"
#elif defined TARGET_stm32h5
#include "hal/stm32h5.h"
#else
#error "Unsupported target for OTP"
#endif

#include "keystore.h"
Expand Down
23 changes: 22 additions & 1 deletion tools/keytools/keygen.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ static void key_gen_check(const char *kfilename)
if (!force && (f != NULL)) {
char reply[40];
int replySz;
printf("** Warning: key file already exist! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
printf("** Warning: key file already exists! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
fflush(stdout);
replySz = scanf("%s", reply);
printf("Reply is [%s]\n", reply);
Expand Down Expand Up @@ -884,9 +884,13 @@ static void key_import(uint32_t ktype, const char *fname, uint32_t id_mask)
else if (ktype == KEYGEN_ED25519) {
initKey = ret = wc_Ed25519PublicKeyDecode(buf, &keySzOut,
ed25519Key, readLen);
if (ret < 0)
printf("error: wc_Ed25519PublicKeyDecode failed on %s\n", fname);

if (ret == 0)
ret = wc_ed25519_export_public(ed25519Key, buf, &qxSz);
if (ret < 0)
printf("error: wc_ed25519_export_public failed on %s\n", fname);

if (initKey == 0)
wc_ed25519_free(ed25519Key);
Expand Down Expand Up @@ -1038,6 +1042,23 @@ int main(int argc, char** argv)
printf("Keytype: %s\n", KName[keytype]);
if (keytype == 0)
exit(0);
fpub = fopen(pubkeyfile, "rb");
if (!force && (fpub != NULL)) {
char reply[40];
int replySz;
printf("** Warning: keystore already exists! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
fflush(stdout);
replySz = scanf("%s", reply);
printf("Reply is [%s]\n", reply);
fclose(fpub);
if (replySz < 0 || strcmp(reply, "Yes") != 0) {
printf("Operation aborted by user.");
exit(5);
} else {
unlink(pubkeyfile);
}
fpub = NULL;
}
fpub = fopen(pubkeyfile, "w");
if (fpub == NULL) {
fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkeyfile, strerror(errno));
Expand Down
6 changes: 6 additions & 0 deletions tools/keytools/otp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ CC=$(CROSS_COMPILE)gcc
OBJCOPY?=$(CROSS_COMPILE)objcopy
SIZE?=$(CROSS_COMPILE)size

all: otp-keystore-primer.bin otp-keystore-gen

otp-keystore-gen: otp-keystore-gen.c
gcc -o $@ otp-keystore-gen.c ../../../src/keystore.c -I. -I../../../ -I../../../include -DFLASH_OTP_KEYSTORE


otp-keystore-primer.bin: otp-keystore-primer.elf
$(Q)$(OBJCOPY) -O binary $(^) $(@)

Expand Down
91 changes: 91 additions & 0 deletions tools/keytools/otp/otp-keystore-gen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* otp-keystore-primer.c
*
* Command line utility to create a OTP image
*
*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#define OTP_SIZE 4096

#include "wolfboot/wolfboot.h"
#include "keystore.h"
#include "otp_keystore.h"

extern struct keystore_slot PubKeys[];

const char outfile[] = "otp.bin";

int main(void)
{
int n_keys = keystore_num_pubkeys();
int i;
struct wolfBoot_otp_hdr hdr;
uint32_t tot_len;
int ofd;
int slot_size;

memcpy(hdr.keystore_hdr_magic, KEYSTORE_HDR_MAGIC, 8);
hdr.item_count = n_keys;
hdr.flags = 0;
hdr.version = WOLFBOOT_VERSION;

/* Sanity check to avoid writing an empty keystore */
if (n_keys < 1) {
fprintf(stderr, "Error: too few keys (%d), refusing to create %s\n", n_keys, outfile);
exit(1);
}

slot_size = keystore_get_size(0);
slot_size += KEYSTORE_HDR_SIZE;
fprintf(stderr, "Slot size: %d\n", slot_size);
fprintf(stderr, "Number of slots: %d\n", n_keys);
fprintf(stderr, "%s size: %d\n", outfile, slot_size * n_keys + sizeof(struct wolfBoot_otp_hdr));

ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (ofd < 0) {
perror("opening output file");
exit(2);
}

/* Write the header to the beginning of the OTP binary file */
if (write(ofd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
fprintf(stderr, "Error writing to %s: %s\n", outfile, strerror(errno));
}

for (i = 0; i < n_keys; i++) {
/* Write each public key to its slot in OTP */
if (write(ofd, &PubKeys[i],
slot_size) < 0) {
fprintf(stderr, "Error adding key %d to %s: %s\n", i, outfile, strerror(errno));
exit(3);
}
}
fprintf(stderr, "%s successfully created.\nGoodbye.\n", outfile);
close(ofd);
return 0;
}

0 comments on commit 78c9e11

Please sign in to comment.