Skip to content

Commit 78c9e11

Browse files
authored
Merge pull request #468 from danielinux/otpgen
Add command line tool to generate otp.bin
2 parents 626fcf0 + c6586f2 commit 78c9e11

File tree

8 files changed

+167
-7
lines changed

8 files changed

+167
-7
lines changed

.github/workflows/test-keytools.yml

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ jobs:
3333
run: |
3434
make SIGN=ECC256 HASH=SHA256
3535
36+
- name: Remove default keystore
37+
run: |
38+
rm -f src/keystore.c
39+
3640
- name: Generate external key
3741
run: |
3842
openssl ecparam -name prime256v1 -genkey -noout -outform DER -out private-key.der
@@ -75,6 +79,10 @@ jobs:
7579
run: |
7680
make SIGN=ED25519 HASH=SHA256
7781
82+
- name: Remove default keystore
83+
run: |
84+
rm -f src/keystore.c
85+
7886
- name: Generate external key
7987
run: |
8088
openssl genpkey -algorithm ed25519 -out private-key.der -outform DER
@@ -117,6 +125,10 @@ jobs:
117125
run: |
118126
make SIGN=RSA2048 HASH=SHA256
119127
128+
- name: Remove default keystore
129+
run: |
130+
rm -f src/keystore.c
131+
120132
- name: Generate external key
121133
run: |
122134
openssl genrsa -out private-key.pem 2048
@@ -224,6 +236,10 @@ jobs:
224236
- name: Delete generated key
225237
run: |
226238
rm -f wolfboot_signing_private_key.der
239+
240+
- name: Remove generated keystore
241+
run: |
242+
rm -f src/keystore.c
227243
228244
- name: Run keygen with --id 0
229245
run: |
@@ -233,6 +249,10 @@ jobs:
233249
run: |
234250
rm -f wolfboot_signing_private_key.der
235251
252+
- name: Remove generated keystore
253+
run: |
254+
rm -f src/keystore.c
255+
236256
- name: Run keygen with test id set
237257
run: |
238258
./tools/keytools/keygen --id 1,3,5,10,11,13,14 --ecc256 -g wolfboot_signing_private_key.der | grep "mask" | grep "00006c2a"
@@ -258,7 +278,7 @@ jobs:
258278
run: |
259279
./tools/keytools/sign --ecc256 --sha256 --custom-tlv 0x45 4 0x6f616943 test-app/image.elf wolfboot_signing_private_key.der 2
260280
grep "Ciao" test-app/image_v2_signed.bin
261-
281+
262282
- name: Sign app with custom buffer TLV included
263283
run: |
264284
./tools/keytools/sign --ecc256 --sha256 --custom-tlv-buffer 0x46 48656C6C6F20776F726C64 test-app/image.elf wolfboot_signing_private_key.der 3
@@ -268,5 +288,5 @@ jobs:
268288
run: |
269289
./tools/keytools/sign --ecc256 --sha256 --custom-tlv-string 0x46 "Hello world" test-app/image.elf wolfboot_signing_private_key.der 3
270290
grep "Hello world" test-app/image_v3_signed.bin
271-
291+
272292

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ tools/keytools/otp/otp-keystore-primer
7575
tools/delta/bmdiff
7676
tools/delta/bmpatch
7777

78+
# otp-keystore-gen binary
79+
tools/keytools/otp/otp-keystore-gen
80+
7881
# Vim swap files
7982
.*.swp
8083

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ clean:
302302
$(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex
303303
$(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT)
304304
$(Q)rm -f $(OBJS)
305+
$(Q)rm -f tools/keytools/otp/otp-keystore-gen
305306
$(Q)$(MAKE) -C test-app -s clean
306307
$(Q)$(MAKE) -C tools/check_config -s clean
307308
$(Q)$(MAKE) -C stage1 -s clean
@@ -377,6 +378,9 @@ cppcheck:
377378

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

381+
otpgen:
382+
make -C tools/keytools/otp otp-keystore-gen
383+
380384
tools/keytools/otp/otp-keystore-primer.bin: FORCE
381385
make -C tools/keytools/otp clean
382386
make -C tools/keytools/otp

docs/flash-OTP.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,26 @@ The public keys are stored in the OTP area, after an initial 16-byte header that
2020
keys stored, the size of each key, and other information.
2121

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

25-
### Provisioning the public keys to the OTP area
25+
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.
26+
27+
### Creating an image of the OTP area content
28+
29+
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.
30+
31+
To compile the otp-keystore-gen tool using the current keystore content:
32+
33+
```
34+
make otpgen
35+
```
36+
37+
And then, to create the image file `otp.bin`:
38+
39+
tools/keytools/otp/otp-keystore-gen
40+
41+
42+
### Directly provisioning the public keys to the OTP area (primer)
2643

2744
After enabling the `FLASH_OTP_KEYSTORE` option in your `.config` file, when you compile wolfBoot by running "make",
2845
an additional application called `otp-keystore-primer` is generated under `tools/keytools/otp`. This application is used to

include/otp_keystore.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@
3434
#include "hal/stm32h7.h"
3535
#elif defined TARGET_stm32h5
3636
#include "hal/stm32h5.h"
37-
#else
38-
#error "Unsupported target for OTP"
3937
#endif
4038

4139
#include "keystore.h"

tools/keytools/keygen.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,7 @@ static void key_gen_check(const char *kfilename)
764764
if (!force && (f != NULL)) {
765765
char reply[40];
766766
int replySz;
767-
printf("** Warning: key file already exist! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
767+
printf("** Warning: key file already exists! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
768768
fflush(stdout);
769769
replySz = scanf("%s", reply);
770770
printf("Reply is [%s]\n", reply);
@@ -884,9 +884,13 @@ static void key_import(uint32_t ktype, const char *fname, uint32_t id_mask)
884884
else if (ktype == KEYGEN_ED25519) {
885885
initKey = ret = wc_Ed25519PublicKeyDecode(buf, &keySzOut,
886886
ed25519Key, readLen);
887+
if (ret < 0)
888+
printf("error: wc_Ed25519PublicKeyDecode failed on %s\n", fname);
887889

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

891895
if (initKey == 0)
892896
wc_ed25519_free(ed25519Key);
@@ -1038,6 +1042,23 @@ int main(int argc, char** argv)
10381042
printf("Keytype: %s\n", KName[keytype]);
10391043
if (keytype == 0)
10401044
exit(0);
1045+
fpub = fopen(pubkeyfile, "rb");
1046+
if (!force && (fpub != NULL)) {
1047+
char reply[40];
1048+
int replySz;
1049+
printf("** Warning: keystore already exists! Are you sure you want to generate a new key and overwrite the existing key? [Type 'Yes']: ");
1050+
fflush(stdout);
1051+
replySz = scanf("%s", reply);
1052+
printf("Reply is [%s]\n", reply);
1053+
fclose(fpub);
1054+
if (replySz < 0 || strcmp(reply, "Yes") != 0) {
1055+
printf("Operation aborted by user.");
1056+
exit(5);
1057+
} else {
1058+
unlink(pubkeyfile);
1059+
}
1060+
fpub = NULL;
1061+
}
10411062
fpub = fopen(pubkeyfile, "w");
10421063
if (fpub == NULL) {
10431064
fprintf(stderr, "Unable to open file '%s' for writing: %s", pubkeyfile, strerror(errno));

tools/keytools/otp/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ CC=$(CROSS_COMPILE)gcc
3232
OBJCOPY?=$(CROSS_COMPILE)objcopy
3333
SIZE?=$(CROSS_COMPILE)size
3434

35+
all: otp-keystore-primer.bin otp-keystore-gen
36+
37+
otp-keystore-gen: otp-keystore-gen.c
38+
gcc -o $@ otp-keystore-gen.c ../../../src/keystore.c -I. -I../../../ -I../../../include -DFLASH_OTP_KEYSTORE
39+
40+
3541
otp-keystore-primer.bin: otp-keystore-primer.elf
3642
$(Q)$(OBJCOPY) -O binary $(^) $(@)
3743

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/* otp-keystore-primer.c
2+
*
3+
* Command line utility to create a OTP image
4+
*
5+
*
6+
* Copyright (C) 2024 wolfSSL Inc.
7+
*
8+
* This file is part of wolfBoot.
9+
*
10+
* wolfBoot is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License as published by
12+
* the Free Software Foundation; either version 3 of the License, or
13+
* (at your option) any later version.
14+
*
15+
* wolfBoot is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU General Public License
21+
* along with this program; if not, write to the Free Software
22+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
23+
*/
24+
#include <stdint.h>
25+
#include <stdio.h>
26+
#include <string.h>
27+
#include <stddef.h>
28+
#include <stdlib.h>
29+
#include <fcntl.h>
30+
#include <unistd.h>
31+
#include <errno.h>
32+
33+
#define OTP_SIZE 4096
34+
35+
#include "wolfboot/wolfboot.h"
36+
#include "keystore.h"
37+
#include "otp_keystore.h"
38+
39+
extern struct keystore_slot PubKeys[];
40+
41+
const char outfile[] = "otp.bin";
42+
43+
int main(void)
44+
{
45+
int n_keys = keystore_num_pubkeys();
46+
int i;
47+
struct wolfBoot_otp_hdr hdr;
48+
uint32_t tot_len;
49+
int ofd;
50+
int slot_size;
51+
52+
memcpy(hdr.keystore_hdr_magic, KEYSTORE_HDR_MAGIC, 8);
53+
hdr.item_count = n_keys;
54+
hdr.flags = 0;
55+
hdr.version = WOLFBOOT_VERSION;
56+
57+
/* Sanity check to avoid writing an empty keystore */
58+
if (n_keys < 1) {
59+
fprintf(stderr, "Error: too few keys (%d), refusing to create %s\n", n_keys, outfile);
60+
exit(1);
61+
}
62+
63+
slot_size = keystore_get_size(0);
64+
slot_size += KEYSTORE_HDR_SIZE;
65+
fprintf(stderr, "Slot size: %d\n", slot_size);
66+
fprintf(stderr, "Number of slots: %d\n", n_keys);
67+
fprintf(stderr, "%s size: %d\n", outfile, slot_size * n_keys + sizeof(struct wolfBoot_otp_hdr));
68+
69+
ofd = open(outfile, O_WRONLY|O_CREAT|O_TRUNC, 0600);
70+
if (ofd < 0) {
71+
perror("opening output file");
72+
exit(2);
73+
}
74+
75+
/* Write the header to the beginning of the OTP binary file */
76+
if (write(ofd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
77+
fprintf(stderr, "Error writing to %s: %s\n", outfile, strerror(errno));
78+
}
79+
80+
for (i = 0; i < n_keys; i++) {
81+
/* Write each public key to its slot in OTP */
82+
if (write(ofd, &PubKeys[i],
83+
slot_size) < 0) {
84+
fprintf(stderr, "Error adding key %d to %s: %s\n", i, outfile, strerror(errno));
85+
exit(3);
86+
}
87+
}
88+
fprintf(stderr, "%s successfully created.\nGoodbye.\n", outfile);
89+
close(ofd);
90+
return 0;
91+
}

0 commit comments

Comments
 (0)