C Host key tools rewritten in python (fix for #4)

pull/6/head
Daniele Lacamera 2019-04-16 20:51:33 +02:00
parent 17f382b995
commit 75fc9cc59a
12 changed files with 235 additions and 959 deletions

View File

@ -49,8 +49,8 @@ include arch.mk
## DSA Settings
ifeq ($(SIGN),ECC256)
KEYGEN_TOOL=tools/ecc256/ecc256_keygen
SIGN_TOOL=tools/ecc256/ecc256_sign
KEYGEN_OPTIONS=--ecc256
SIGN_OPTIONS=--ecc256
PRIVATE_KEY=ecc256.der
OBJS+= \
$(ECC_EXTRA_OBJS) \
@ -63,8 +63,8 @@ ifeq ($(SIGN),ECC256)
./src/xmalloc.o
CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER $(ECC_EXTRA_CFLAGS)
else
KEYGEN_TOOL=tools/ed25519/ed25519_keygen
SIGN_TOOL=tools/ed25519/ed25519_sign
KEYGEN_OPTIONS=--ed25519
SIGN_OPTIONS=--ed25519
PRIVATE_KEY=ed25519.der
OBJS+= ./lib/wolfssl/wolfcrypt/src/sha512.o \
./lib/wolfssl/wolfcrypt/src/ed25519.o \
@ -150,23 +150,17 @@ test-app/image.bin:
include tools/test.mk
tools/ed25519/ed25519_sign:
@make -C tools/ed25519
ed25519.der:
@tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/ed25519_pub_key.c
tools/ecc256/ecc256_sign:
@make -C tools/ecc256
ecc256.der:
@tools/keytools/keygen.py $(KEYGEN_OPTIONS) src/ecc256_pub_key.c
ed25519.der: tools/ed25519/ed25519_sign
@tools/ed25519/ed25519_keygen src/ed25519_pub_key.c
ecc256.der: tools/ecc256/ecc256_sign
@tools/ecc256/ecc256_keygen src/ecc256_pub_key.c
factory.bin: $(BOOT_IMG) wolfboot-align.bin $(SIGN_TOOL) $(PRIVATE_KEY)
factory.bin: $(BOOT_IMG) wolfboot-align.bin $(PRIVATE_KEY)
@echo "\t[SIGN] $(BOOT_IMG)"
$(Q)$(SIGN_TOOL) $(BOOT_IMG) $(PRIVATE_KEY) 1 >/dev/null
$(Q)tools/keytools/sign.py $(SIGN_OPTIONS) $(BOOT_IMG) $(PRIVATE_KEY) 1
@echo "\t[MERGE] $@"
@cat wolfboot-align.bin $(BOOT_IMG).v1.signed > $@
@cat wolfboot-align.bin test-app/image_v1_signed.bin > $@
wolfboot.elf: $(OBJS) $(LSCRIPT)
@echo "\t[LD] $@"
@ -184,8 +178,6 @@ clean:
@make -C test-app clean
distclean: clean
@make -C tools/ed25519 clean
@make -C tools/ecc256 clean
@rm -f *.pem *.der tags ./src/ed25519_pub_key.c ./src/ecc256_pub_key.c

View File

@ -89,4 +89,4 @@ standalone: image.bin
$(Q)$(CC) $(CFLAGS) -c -o $@ $^
clean:
@rm -f image.bin* image.elf *.o image.map tags
@rm -f *.bin *.elf tags *.o

View File

@ -1,24 +0,0 @@
# Settings
#
CC=gcc
LD=gcc
CROSS_COMPILE=
WOLFBOOT_ROOT=../../
BOOTUTIL_ROOT=$(WOLFBOOT_ROOT)/lib/bootutil
CFLAGS:=-lwolfssl -DHAVE_ECC -DHAVE_ASN -DWOLFCRYPT_ONLY -DTFM_TIMING_RESISTANT -DNO_RSA -DECC_TIMING_RESISTANT -DWOLFSSL_DER_TO_PEM -DWOLFSSL_VALIDATE_ECC_IMPORT -DHAVE_ECC_KEY_EXPORT -I$(WOLFBOOT_ROOT)/include
LDFLAGS:=-lwolfssl
LDFLAGS_EXTRA=
EXTRA_LDFLAGS=
all: ecc256_keygen ecc256_sign
ecc256_keygen: ecc256_keygen.o
gcc -o $@ $^ $(LDFLAGS)
ecc256_sign: ecc256_sign.o
gcc -o $@ $^ $(LDFLAGS)
clean:
rm -f ecc256_keygen ecc256_sign *.o

View File

@ -1,151 +0,0 @@
/* ecc_keys.h
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL 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 2 of the License, or
* (at your option) any later version.
*
* wolfSSL 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-1301, USA
*/
#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#define ECC_KEY_SIZE 32
void create_pubkey_cfile(const char *fname, uint8_t *key_in)
{
char buf[4192] = { };
char keybyte[5] = {};
int i;
int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0660);
if (fd < 0) {
perror("creating c file");
exit(1);
}
strcat(buf,"/* This file is automatically generate by ecc256 keygen. DO NOT EDIT. */\n");
strcat(buf,"#include <stdint.h>\n");
strcat(buf,"const uint8_t ecc256_pub_key[64] = {\n");
for (i = 0; i < 2 * ECC_KEY_SIZE; i++) {
int p = i % 8;
if (p == 0)
strcat(buf,"\t");
snprintf(keybyte, 5, "0x%02X", key_in[i]);
strcat(buf, keybyte);
if (i < 2 * ECC_KEY_SIZE - 1)
strcat(buf, ",");
if (p == 7)
strcat(buf, "\n");
else
strcat(buf," ");
}
strcat(buf,"};\n");
strcat(buf,"const uint32_t ecc256_pub_key_len = 64;\n");
write(fd, buf, strlen(buf));
close(fd);
}
void print_buf(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
int p = i % 8;
if (p == 0)
printf("\t");
printf("0x%02X", buf[i]);
if (i < len - 1)
printf(",");
if (p == 7)
printf("\n");
else
printf(" ");
}
printf("\n");
}
void print_mp(mp_int *m)
{
uint8_t buf[32];
mp_to_unsigned_bin(m, buf);
print_buf(buf, 32);
}
int main(int argc, char *argv[])
{
ecc_key key;
uint8_t der[3 * ECC_KEY_SIZE];
uint8_t buf[2 * ECC_KEY_SIZE];
FILE* derFile;
size_t sz;
uint32_t qxlen = ECC_KEY_SIZE;
uint32_t qylen = ECC_KEY_SIZE;
uint32_t dlen = ECC_KEY_SIZE;
int fd;
RNG rng;
wc_InitRng(&rng);
wc_ecc_init(&key);
if (wc_ecc_make_key(&rng, ECC_KEY_SIZE, &key) != 0) {
printf("error making ecc key\n");
return -1;
}
print_mp(&key.k);
/* write private key */
if (wc_ecc_export_private_raw(&key,
der, &qxlen,
der + ECC_KEY_SIZE, &qylen,
der + 2 * ECC_KEY_SIZE, &dlen
) == 0) {
printf("Created private key: %d bytes\n", qxlen + qylen + dlen);
}
/* Store private key */
fd = open("ecc256.der", O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
perror("open");
exit(2);
}
write(fd, der, qxlen + qylen + dlen);
close(fd);
/* Store public key */
fd = open("ecc-pub.der", O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
perror("open");
exit(2);
}
write(fd, der, qxlen + qylen);
close(fd);
if (argc > 1) {
printf("Generating .c code for public key...\n");
create_pubkey_cfile(argv[1], der);
}
/* close stuff up */
wc_ecc_free(&key);
wc_FreeRng(&rng);
return 0;
}

View File

@ -1,308 +0,0 @@
/*
* ecc256_sign.c
*
* 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 2 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 <fcntl.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/random.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <sys/stat.h>
#define ECC_KEY_SIZE 32
#define ECC_SIG_SIZE (2 * ECC_KEY_SIZE)
#define WOLFBOOT_SIGN_ECC256
#define VERIFY_SIGNATURE_TEST
#include "target.h"
#include "image.h"
#include "loader.h"
static uint8_t key_buffer[2 * sizeof(ecc_key)];
void print_buf(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
int p = i % 8;
if (p == 0)
printf("\t");
printf("0x%02X", buf[i]);
if (i < len - 1)
printf(",");
if (p == 7)
printf("\n");
else
printf(" ");
}
printf("\n");
}
void print_mp(mp_int *m)
{
uint8_t buf[32];
mp_to_unsigned_bin(m, buf);
print_buf(buf, 32);
}
void print_key(void *key_in)
{
uint8_t * key = key_in;
print_buf(key, ECC_KEY_SIZE);
}
int main(int argc, char *argv[])
{
uint8_t inkey[ECC_KEY_SIZE * 4];
int in_fd, key_fd, out_fd, r;
int outlen = ECC_SIG_SIZE;
char in_name[PATH_MAX];
char signed_name[PATH_MAX];
char *dot;
ecc_key *key = (ecc_key *)key_buffer;
Sha256 sha;
Sha256 keyhash;
uint8_t shabuf[SHA256_DIGEST_SIZE];
uint8_t signature[ECC_SIG_SIZE] = { };
uint8_t *final;
int total_size;
uint8_t hdr[IMAGE_HEADER_SIZE];
uint8_t *ptr = hdr;
struct stat st;
int version;
int padsize = 0;
int i;
int sigsize = 0;
int res;
mp_int mpr, mps;
mp_init(&mpr);
mp_init(&mps);
RNG rng;
wc_InitRng(&rng);
if (argc != 4 && argc!=5) {
fprintf(stderr, "Usage: %s image key.der fw_version [padsize]\n", argv[0]);
exit(1);
}
version = atoi(argv[3]);
if (version < 0) {
fprintf(stderr, "%s: invalid version '%s'.\n", argv[0], argv[3]);
exit(1);
}
if (argc > 4) {
padsize = atoi(argv[4]);
if (padsize < 1024) {
fprintf(stderr, "%s: invalid padding size '%s'.\n", argv[0], argv[4]);
exit(1);
}
}
strcpy(in_name, argv[1]);
snprintf(signed_name, PATH_MAX, "%s.v%s.signed", argv[1], argv[3]);
in_fd = open(in_name, O_RDONLY);
if (in_fd < 0) {
perror(in_name);
exit(2);
}
out_fd = open(signed_name, O_WRONLY|O_CREAT|O_TRUNC, 0660);
if (out_fd < 0) {
perror(signed_name);
exit(2);
}
key_fd = open(argv[2], O_RDONLY);
if (key_fd < 0) {
perror(argv[2]);
exit(2);
}
wc_ecc_init(key);
r = read(key_fd, inkey, 3 * ECC_KEY_SIZE);
if (r < 0) {
perror("read");
exit(3);
}
r = wc_ecc_import_unsigned(key, inkey, inkey + ECC_KEY_SIZE, inkey + 2 * ECC_KEY_SIZE, ECC_SECP256R1);
if (r < 0) {
printf("Errror importing key\n");
}
printf("key.type = %d\n", key->type);
close(key_fd);
/* Create header */
r = stat(in_name, &st);
if (r < 0) {
perror(in_name);
exit(2);
}
memset(hdr, 0xFF, IMAGE_HEADER_SIZE);
*((uint32_t *)ptr) = WOLFBOOT_MAGIC;
ptr += (sizeof(uint32_t));
*((uint32_t *)(ptr)) = st.st_size;
ptr += (sizeof(uint32_t));
ptr += (sizeof(uint16_t));
*(ptr++) = HDR_VERSION;
*(ptr++) = 4;
*((uint32_t *)(ptr)) = version;
ptr += (sizeof(uint32_t));
ptr += (sizeof(uint16_t) + sizeof(uint32_t));
*(ptr++) = HDR_TIMESTAMP;
*(ptr++) = 8;
*((uint64_t *)(ptr)) = st.st_mtime;
ptr += sizeof(uint64_t);
/* Sha256 */
wc_InitSha256(&sha);
wc_Sha256Update(&sha, hdr, ptr - hdr);
while(1) {
r = read(in_fd, shabuf, SHA256_DIGEST_SIZE);
if (r <= 0)
break;
wc_Sha256Update(&sha, shabuf, r);
if (r < 32)
break;
}
wc_Sha256Final(&sha, shabuf);
if (wc_ecc_sign_hash_ex(shabuf, SHA256_DIGEST_SIZE, &rng, key, &mpr, &mps) != MP_OKAY) {
printf("Error signing hash\n");
exit(1);
}
if (wc_ecc_verify_hash_ex(&mpr, &mps, shabuf, SHA256_DIGEST_SIZE, &res, key) != MP_OKAY) {
printf("Error verifying hash\n");
exit(1);
}
if (res == 0) {
printf("Bad signature.\n");
exit(1);
}
printf("shabuf\n");
print_buf(shabuf, SHA256_DIGEST_SIZE);
mp_to_unsigned_bin(&mpr, signature);
mp_to_unsigned_bin(&mps, signature + ECC_KEY_SIZE);
sigsize = 2 * ECC_KEY_SIZE;
printf("signature (%d bytes)\n", sigsize);
print_buf(shabuf, sigsize);
#ifdef VERIFY_SIGNATURE_TEST
{
ecc_key *pubk = (ecc_key *)key_buffer;
int ret;
int fd;
mp_int r, s;
uint8_t pubk_buf[2 * ECC_KEY_SIZE];
mp_init(&r);
mp_init(&s);
mp_read_unsigned_bin(&r, signature, ECC_KEY_SIZE);
mp_read_unsigned_bin(&s, signature + ECC_KEY_SIZE, ECC_KEY_SIZE);
ret = wc_ecc_init(pubk);
if (ret < 0)
{
perror ("initializing ecc key");
exit(2);
}
fd = open("ecc-pub.der", O_RDONLY);
if (fd < 0) {
perror ("cannot verify signature: opening ecc-pub.der");
exit(2);
}
if (read(fd, pubk_buf, 2 * ECC_KEY_SIZE) != (2 * ECC_KEY_SIZE)) {
perror ("cannot verify signature: error reading ecc-pub.der");
exit(2);
}
ret = wc_ecc_import_unsigned(pubk, pubk_buf, pubk_buf + ECC_KEY_SIZE, NULL, ECC_SECP256R1);
if (ret != MP_OKAY) {
perror ("importing public key");
exit(2);
}
printf("pubkey.type = %d\n", pubk->type);
ret = wc_ecc_verify_hash_ex(&r, &s, shabuf, SHA256_DIGEST_SIZE, &res, pubk);
if (ret != MP_OKAY) {
printf("Verify operation failed.\n");
} else if (res == 0) {
printf("Bad signature.\n");
} else {
printf("Signature verified OK \n");
}
}
#endif
*(ptr++) = HDR_SHA256;
*(ptr++) = SHA256_DIGEST_SIZE;
memcpy(ptr, shabuf, SHA256_DIGEST_SIZE);
ptr += SHA256_DIGEST_SIZE;
wc_InitSha256(&keyhash);
wc_Sha256Update(&keyhash, inkey, 2 * ECC_KEY_SIZE);
wc_Sha256Final(&keyhash, shabuf);
*(ptr++) = HDR_PUBKEY;
*(ptr++) = SHA256_DIGEST_SIZE;
memcpy(ptr, shabuf, SHA256_DIGEST_SIZE);
wc_Sha256Free(&keyhash);
ptr += SHA256_DIGEST_SIZE;
*(ptr++) = HDR_SIGNATURE;
*(ptr++) = ECC_SIG_SIZE;
memcpy(ptr, signature, ECC_SIG_SIZE);
ptr += ECC_SIG_SIZE;
*(ptr++) = HDR_END;
printf("\n\n");
print_buf(hdr, IMAGE_HEADER_SIZE);
/* Write header */
write(out_fd, hdr, IMAGE_HEADER_SIZE);
/* Write image payload */
lseek(in_fd, 0, SEEK_SET);
while(1) {
uint8_t tmpbuf[32];
r = read(in_fd, tmpbuf, 32);
if (r <= 0)
break;
write(out_fd, tmpbuf, r);
if (r < 32)
break;
}
/* Pad if needed */
r = stat(signed_name, &st);
if ((r == 0) && st.st_size < padsize) {
size_t fill = padsize - st.st_size;
uint8_t padbyte = 0xFF;
out_fd = open(signed_name, O_WRONLY|O_APPEND|O_EXCL);
if (out_fd > 0) {
while(fill--)
write(out_fd, &padbyte, 1);
}
close(out_fd);
}
exit(0);
}

View File

@ -1,37 +0,0 @@
# Settings
#
CROSS_COMPILE=
WOLFBOOT_ROOT=../../
CFLAGS:=-lwolfssl -DHAVE_ECC_KEY_EXPORT -DHAVE_ED25519 -DHAVE_ASN -DWOLFCRYPT_ONLY -DTFM_TIMING_RESISTANT -DNO_RSA -DECC_TIMING_RESISTANT -DWOLFSSL_DER_TO_PEM -I$(WOLFBOOT_ROOT)/include -I$(WOLFBOOT_ROOT)/lib/wolfssl
LDFLAGS:=-lwolfssl
LDFLAGS_EXTRA=
EXTRA_LDFLAGS=
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
EXT=
all: binaries
windows: binaries
mv ed25519_keygen ed25519_keygen.exe
mv ed25519_sign ed25519_sign.exe
windows:CROSS_COMPILE=x86_64-w64-mingw32-
windows:EXT:=.exe
windows:WIN_OBJS+=/usr/x86_64-w64-mingw32/lib/libwolfssl-17.dll
windows:LDFLAGS=-Wl,-Bstatic,--whole-archive $(WIN_OBJS) -lgcc -Wl,--no-whole-archive
windows: all
binaries: ed25519_keygen$(EXT) ed25519_sign$(EXT)
ed25519_keygen: ed25519_keygen.o
$(CC) -o $@ $^ $(LDFLAGS)
ed25519_sign: ed25519_sign.o
$(CC) -o $@ $^ $(LDFLAGS)
clean:
@rm -f ed25519_keygen ed25519_sign *.o *.exe

View File

@ -1,167 +0,0 @@
/*
* ed25519_keygen.c
*
* 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 2 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 <fcntl.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#define PEMSIZE 1024
#ifndef WIN32
# define O_BINARY O_RDONLY
#endif
void print_buf(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
int p = i % 8;
if (p == 0)
printf("\t");
printf("0x%02X", buf[i]);
if (i < len - 1)
printf(",");
if (p == 7)
printf("\n");
else
printf(" ");
}
}
void print_key(void *key_in)
{
uint8_t * key = key_in;
print_buf(key, ED25519_KEY_SIZE);
}
void create_pubkey_cfile(const char *fname, uint8_t *key_in)
{
char buf[4192] = { };
char keybyte[5] = {};
int i;
int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0660);
if (fd < 0) {
perror("creating c file");
exit(1);
}
strcat(buf,"/* This file is automatically generate by ed25519 keygen. DO NOT EDIT. */\n");
strcat(buf,"#include <stdint.h>\n");
strcat(buf,"const uint8_t ed25519_pub_key[32] = {\n");
for (i = 0; i < ED25519_KEY_SIZE; i++) {
int p = i % 8;
if (p == 0)
strcat(buf,"\t");
snprintf(keybyte, 5, "0x%02X", key_in[i]);
strcat(buf, keybyte);
if (i < ED25519_KEY_SIZE - 1)
strcat(buf, ",");
if (p == 7)
strcat(buf, "\n");
else
strcat(buf," ");
}
strcat(buf,"};\n");
strcat(buf,"const uint32_t ed25519_pub_key_len = 32;\n");
write(fd, buf, strlen(buf));
close(fd);
}
void print_sig(void *sig_in)
{
uint8_t * sig = sig_in;
print_buf(sig, ED25519_SIG_SIZE);
}
int main(int argc, char *argv[])
{
uint8_t priv[ED25519_KEY_SIZE], pub[ED25519_KEY_SIZE], full[2*ED25519_KEY_SIZE];
uint8_t sig[ED25519_SIG_SIZE];
uint32_t outlen;
char outkey[PEMSIZE];
int fd;
RNG rng;
ed25519_key key;
if (argc != 2) {
fprintf(stderr, "Usage: %s cfile\n", argv[0]);
exit(1);
}
wc_ed25519_init(&key);
wc_InitRng(&rng);
if (wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key) != 0) {
printf("Failed to create ED25519 key!\n");
exit(1);
}
outlen = ED25519_KEY_SIZE;
wc_ed25519_export_private_only(&key, priv, &outlen);
printf("const uint8_t ed_private_key[ED25519_KEY_SIZE] = {\n");
print_key(priv);
printf("};\n\n");
outlen = ED25519_PRV_KEY_SIZE;
wc_ed25519_export_private(&key, full, &outlen);
print_key(full);
print_key(full + 32);
fd = open("ed25519.der", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600);
if (fd < 0) {
perror("exporting key (der)");
}
write(fd, full, ED25519_PRV_KEY_SIZE);
close(fd);
memset(outkey, 0, PEMSIZE);
wc_DerToPem(priv, outlen, outkey, PEMSIZE, ED25519_TYPE);
printf("%s\n", outkey);
fd = open("ed25519.pem", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600);
if (fd < 0) {
perror("exporting key (pem)");
}
write(fd, outkey, strlen(outkey));
close(fd);
outlen = ED25519_KEY_SIZE;
wc_ed25519_export_public(&key, pub, &outlen);
printf("const uint8_t ed_public_key[ED25519_KEY_SIZE] = {\n");
print_key(pub);
printf("};\n\n");
memset(outkey, 0, PEMSIZE);
wc_DerToPem(pub, 32, outkey, PEMSIZE, PUBLICKEY_TYPE);
printf("%s\n", outkey);
fd = open("ed25519_pub.pem", O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0660);
if (fd < 0) {
perror("creating key\n");
}
write(fd, outkey, strlen(outkey));
close(fd);
if (argc > 1) {
printf("Generating .c code for public key...\n");
create_pubkey_cfile(argv[1], pub);
}
exit(0);
}

View File

@ -1,233 +0,0 @@
/*
* ed25519_sign.c
*
* 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 2 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 <fcntl.h>
#ifndef WIN32
# define O_BINARY 0
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/ed25519.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <sys/stat.h>
#define WOLFBOOT_SIGN_ED25519
#include "target.h"
#include "image.h"
#include "loader.h"
void print_buf(uint8_t *buf, int len)
{
int i;
for (i = 0; i < len; i++) {
int p = i % 8;
if (p == 0)
printf("\t");
printf("0x%02X", buf[i]);
if (i < len - 1)
printf(",");
if (p == 7)
printf("\n");
else
printf(" ");
}
}
void print_key(void *key_in)
{
uint8_t * key = key_in;
print_buf(key, ED25519_KEY_SIZE);
}
int main(int argc, char *argv[])
{
uint8_t inkey[ED25519_PRV_KEY_SIZE];
int in_fd, key_fd, out_fd, r;
int outlen = ED25519_SIG_SIZE;
char in_name[PATH_MAX];
char signed_name[PATH_MAX];
char *dot;
ed25519_key key;
Sha256 sha;
Sha256 keyhash;
uint8_t shabuf[32];
uint8_t signature[ED25519_SIG_SIZE];
uint8_t *final;
int total_size;
uint8_t hdr[IMAGE_HEADER_SIZE];
uint8_t *ptr = hdr;
struct stat st;
int version;
int padsize = 0;
int i;
if (argc != 4 && argc!=5) {
fprintf(stderr, "Usage: %s image key.der fw_version [padsize]\n", argv[0]);
exit(1);
}
version = atoi(argv[3]);
if (version < 0) {
fprintf(stderr, "%s: invalid version '%s'.\n", argv[0], argv[3]);
exit(1);
}
if (argc > 4) {
padsize = atoi(argv[4]);
if (padsize < 1024) {
fprintf(stderr, "%s: invalid padding size '%s'.\n", argv[0], argv[4]);
exit(1);
}
}
strcpy(in_name, argv[1]);
snprintf(signed_name, PATH_MAX, "%s.v%s.signed", argv[1], argv[3]);
in_fd = open(in_name, O_RDONLY|O_BINARY);
if (in_fd < 0) {
perror(in_name);
exit(2);
}
out_fd = open(signed_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0660);
if (out_fd < 0) {
perror(signed_name);
exit(2);
}
key_fd = open(argv[2], O_RDONLY|O_BINARY);
if (key_fd < 0) {
perror(argv[2]);
exit(2);
}
wc_ed25519_init(&key);
wc_InitSha256(&sha);
r = read(key_fd, inkey, ED25519_PRV_KEY_SIZE);
if (r < 0) {
perror("read");
exit(3);
}
r = wc_ed25519_import_private_key(inkey, ED25519_KEY_SIZE, inkey + ED25519_KEY_SIZE, ED25519_KEY_SIZE, &key);
if (r < 0) {
perror("importing private key");
}
close(key_fd);
print_key(inkey);
print_key(inkey + 32);
/* Create header */
r = stat(in_name, &st);
if (r < 0) {
perror(in_name);
exit(2);
}
memset(hdr, 0xFF, IMAGE_HEADER_SIZE);
*((uint32_t *)ptr) = WOLFBOOT_MAGIC;
ptr += (sizeof(uint32_t));
*((uint32_t *)(ptr)) = st.st_size;
ptr += (sizeof(uint32_t));
ptr += (sizeof(uint16_t));
*(ptr++) = HDR_VERSION;
*(ptr++) = 4;
*((uint32_t *)(ptr)) = version;
ptr += (sizeof(uint32_t));
ptr += (sizeof(uint16_t) + sizeof(uint32_t));
*(ptr++) = HDR_TIMESTAMP;
*(ptr++) = 8;
*((uint64_t *)(ptr)) = st.st_mtime;
ptr += sizeof(uint64_t);
/* Sha256 */
wc_Sha256Update(&sha, hdr, ptr - hdr);
while(1) {
r = read(in_fd, shabuf, 32);
if (r <= 0)
break;
wc_Sha256Update(&sha, shabuf, r);
if (r < 32)
break;
}
wc_Sha256Final(&sha, shabuf);
wc_ed25519_sign_msg(shabuf, 32, signature, &outlen, &key);
*(ptr++) = HDR_SHA256;
*(ptr++) = SHA256_DIGEST_SIZE;
memcpy(ptr, shabuf, SHA256_DIGEST_SIZE);
ptr += SHA256_DIGEST_SIZE;
wc_InitSha256(&keyhash);
wc_Sha256Update(&keyhash, inkey + ED25519_KEY_SIZE, ED25519_KEY_SIZE);
wc_Sha256Final(&keyhash, shabuf);
*(ptr++) = HDR_PUBKEY;
*(ptr++) = SHA256_DIGEST_SIZE;
memcpy(ptr, shabuf, SHA256_DIGEST_SIZE);
ptr += SHA256_DIGEST_SIZE;
*(ptr++) = HDR_SIGNATURE;
*(ptr++) = ED25519_SIG_SIZE;
memcpy(ptr, signature, ED25519_SIG_SIZE);
ptr += ED25519_SIG_SIZE;
*(ptr++) = HDR_END;
printf("\n\n");
print_buf(hdr, IMAGE_HEADER_SIZE);
/* Write header */
if (write(out_fd, hdr, IMAGE_HEADER_SIZE) != IMAGE_HEADER_SIZE) {
perror("write");
exit(1);
}
/* Write image payload */
lseek(in_fd, 0, SEEK_SET);
while(1) {
uint8_t tmpbuf[32];
r = read(in_fd, tmpbuf, 32);
if (r <= 0)
break;
write(out_fd, tmpbuf, r);
if (r < 32)
break;
}
/* Pad if needed */
r = stat(signed_name, &st);
if ((r == 0) && st.st_size < padsize) {
size_t fill = padsize - st.st_size;
uint8_t padbyte = 0xFF;
out_fd = open(signed_name, O_WRONLY|O_APPEND|O_EXCL|O_BINARY);
if (out_fd > 0) {
while(fill--)
write(out_fd, &padbyte, 1);
}
close(out_fd);
}
close(in_fd);
exit(0);
}

View File

@ -1,4 +1,25 @@
#!/usr/bin/python3
'''
* keygen.py
*
* Copyright (C) 2019 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 2 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
'''
import sys,os
from wolfcrypt import ciphers
@ -105,7 +126,7 @@ if (sign == "ecc256"):
f.write('\n')
f.write("0x%02X" % qy[-1])
f.write("\n};\n")
f.write("const uint32_t ed25519_pub_key_len = 64;\n")
f.write("const uint32_t ecc256_pub_key_len = 64;\n")
f.close()

View File

@ -0,0 +1,185 @@
#!/usr/bin/python3
'''
* sign.py
*
* Copyright (C) 2019 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 2 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
'''
import sys, os, struct, time
from wolfcrypt import ciphers, hashes
WOLFBOOT_MAGIC = 0x464C4F57
HDR_END = 0x00
HDR_VERSION = 0x01
HDR_TIMESTAMP = 0x02
HDR_SHA256 = 0x03
HDR_PUBKEY = 0x10
HDR_SIGNATURE = 0x20
HDR_PADDING = 0xFF
HDR_VERSION_LEN = 4
HDR_TIMESTAMP_LEN = 8
HDR_SHA256_LEN = 32
HDR_PUBKEY_LEN = 32
HDR_SIGNATURE_LEN = 64
sign="auto"
argc = len(sys.argv)
argv = sys.argv
if (argc < 4) or (argc > 5):
print("Usage: %s [--ed25519 | --ecc256 ] image key.der fw_version\n" % sys.argv[0])
sys.exit(1)
if argc == 5:
if argv[1] != '--ed25519' and argv[1] != '--ecc256':
print("Usage: %s [--ed25519 | --ecc256 ] image key.der fw_version\n" % sys.argv[0])
sys.exit(1)
sign=argv[1][2:]
image_file = argv[2]
key_file = argv[3]
fw_version = int(argv[4])
else:
image_file = argv[1]
key_file = argv[2]
fw_version = int(argv[3])
if '.' in image_file:
tokens = image_file.split('.')
output_image_file = image_file.rstrip('.' + tokens[-1])
output_image_file += "_v" + str(fw_version) + "_signed.bin"
else:
output_image_file = image_file + "_v" + str(fw_version) + "_signed.bin"
print ("Selected cipher: " + sign)
print ("Private key: " + key_file)
print ("Input image: " + image_file)
print ("Output image: " + output_image_file)
''' import (decode) private key for signing '''
kf = open(key_file, "rb")
wolfboot_private_key = kf.read(96)
wolfboot_private_key_len = len(wolfboot_private_key)
if wolfboot_private_key_len == 64:
if (sign == 'ecc256'):
print("Error: key size does not match the cipher selected")
sys.exit(1)
if sign == 'auto':
sign = 'ed25519'
print("'ed25519' key autodetected.")
elif wolfboot_private_key_len == 96:
if (sign == 'ed25519'):
print("Error: key size does not match the cipher selected")
sys.exit(1)
if sign == 'auto':
sign = 'ecc256'
print("'ecc256' key autodetected.")
else:
print ("Error: key size does not match any cipher")
sys.exit(2)
if sign == 'ed25519':
ed = ciphers.Ed25519Private(key = wolfboot_private_key)
privkey, pubkey = ed.encode_key()
if sign == 'ecc256':
ecc = ciphers.EccPrivate()
ecc.decode_key_raw(wolfboot_private_key[0:31], wolfboot_private_key[32:63], wolfboot_private_key[64:])
pubkey = wolfboot_private_key[0:64]
img_size = os.path.getsize(image_file)
# Magic header (spells 'WOLF')
header = struct.pack('<L', WOLFBOOT_MAGIC)
# Image size
header += struct.pack('<L', img_size)
# Two pad bytes so version is aligned
header += struct.pack('BB', 0xFF, 0xFF)
# Version field
header += struct.pack('BB', HDR_VERSION, HDR_VERSION_LEN)
header += struct.pack('<L', fw_version)
# Six pad bytes so timestamp is aligned
header += struct.pack('BB', 0xFF, 0xFF)
header += struct.pack('BB', 0xFF, 0xFF)
header += struct.pack('BB', 0xFF, 0xFF)
# Timestamp field
header += struct.pack('BB', HDR_TIMESTAMP, HDR_TIMESTAMP_LEN)
header += struct.pack('<Q', int(os.path.getmtime(image_file)))
sha = hashes.Sha256.new()
# Sha calculation
sha.update(header)
img_bin = open(image_file, 'rb')
while True:
buf = img_bin.read(32)
if (len(buf) == 0):
img_bin.close()
break
sha.update(buf)
digest = sha.digest()
# Add SHA to the header
header += struct.pack('BB', HDR_SHA256, HDR_SHA256_LEN)
header += digest
# pubkey SHA calculation
keysha = hashes.Sha256.new()
keysha.update(pubkey)
header += struct.pack('BB', HDR_PUBKEY, HDR_PUBKEY_LEN)
key_digest = keysha.digest()
header += key_digest
# Sign the digest
print("Signing the firmware...")
if (sign == 'ed25519'):
signature = ed.sign(digest)
else:
r, s = ecc.sign_raw(digest)
signature = r + s
header += struct.pack('BB', HDR_SIGNATURE, HDR_SIGNATURE_LEN)
header += signature
print ("Done.")
# Create output image. Add padded header in front
outfile = open(output_image_file, 'wb')
outfile.write(header)
sz = len(header)
while sz < 256:
outfile.write(struct.pack('B',0xFF))
sz += 1
infile = open(image_file, 'rb')
while True:
buf = infile.read(1024)
if len(buf) == 0:
break
outfile.write(buf)
infile.close()
outfile.close()
print ("Output image successfully created.")
sys.exit(0)

View File

@ -1,14 +0,0 @@
/* Public-key file for wolfBoot, automatically generated. Do not edit. */
/*
* This file has been generated and contains the public key which is
* used by wolfBoot to verify the updates.
*/
#include <stdint.h>
const uint8_t ed25519_pub_key[32] = {
0xB3, 0xAE, 0xD5, 0xEC, 0x20, 0xB0, 0x59, 0x99,
0x2C, 0x0D, 0x76, 0x67, 0xA7, 0x29, 0x0A, 0x6D,
0x34, 0xD0, 0xDA, 0xBC, 0x7B, 0xDB, 0x2C, 0x6D,
0x2F, 0x2A, 0xD5, 0xAE, 0xE1, 0x41, 0x02, 0x46
};
const uint32_t ed25519_pub_key_len = 32;

View File

@ -2,6 +2,17 @@ TEST_UPDATE_VERSION?=2
EXPVER=tools/test-expect-version/test-expect-version
SPI_CHIP=SST25VF080B
SIGN_TOOL=/bin/false
ifeq ($(SIGN),ED25519)
SIGN_TOOL=tools/keytools/sign.py --ed25519
endif
ifeq ($(SIGN),ECC256)
SIGN_TOOL=tools/keytools/sign.py --ecc256
endif
$(EXPVER):
make -C tools/test-expect-version
@ -31,8 +42,9 @@ test-spi-off: FORCE
test-update: test-app/image.bin FORCE
@$(SIGN_TOOL) test-app/image.bin $(PRIVATE_KEY) $(TEST_UPDATE_VERSION) 131072 >/dev/null
@dd if=test-app/image.bin.v$(TEST_UPDATE_VERSION).signed of=test-update.bin bs=1 count=131067
@dd if=/dev/zero bs=131067 count=1 2>/dev/null | tr "\000" "\377" > test-update.bin
@$(SIGN_TOOL) test-app/image.bin $(PRIVATE_KEY) $(TEST_UPDATE_VERSION)
@dd if=test-app/image_v$(TEST_UPDATE_VERSION)_signed.bin of=test-update.bin bs=1 conv=notrunc
@printf "pBOOT" >> test-update.bin
@make test-reset
@sleep 2
@ -41,9 +53,9 @@ test-update: test-app/image.bin FORCE
(make test-reset && sleep 1 && st-flash --reset write test-update.bin 0x08040000)
test-update-ext: test-app/image.bin FORCE
@$(SIGN_TOOL) test-app/image.bin $(PRIVATE_KEY) $(TEST_UPDATE_VERSION) 524288 >/dev/null
@$(SIGN_TOOL) test-app/image.bin $(PRIVATE_KEY) $(TEST_UPDATE_VERSION)
@$$(dd if=/dev/zero bs=1M count=1 | tr '\000' '\377' > test-update.rom)
@dd if=test-app/image.bin.v$(TEST_UPDATE_VERSION).signed of=test-update.rom bs=1 count=524283 conv=notrunc
@dd if=test-app/image_v$(TEST_UPDATE_VERSION)_signed.bin of=test-update.rom bs=1 count=524283 conv=notrunc
@printf "pBOOT" | dd of=test-update.rom obs=1 seek=524283 count=5 conv=notrunc
@make test-spi-on
flashrom -c $(SPI_CHIP) -p linux_spi:dev=/dev/spidev0.0 -w test-update.rom