Ecc256 signature verification with sp-math support, work in progress

pull/3/head
Daniele Lacamera 2019-01-21 05:28:59 +01:00
parent f4f65ae31d
commit 41c60f4bd2
14 changed files with 881 additions and 111 deletions

7
.gitignore vendored
View File

@ -49,6 +49,13 @@
# automatically generated source files
src/ed25519_pub_key.c
src/ecc256_pub_key.c
# keygen binaries
tools/ed25519/ed25519_sign
tools/ed25519/ed25519_keygen
tools/ecc256/ecc256_sign
tools/ecc256/ecc256_keygen
# Vim swap files
.*.swp

View File

@ -1,12 +1,13 @@
CROSS_COMPILE:=arm-none-eabi-
CC:=$(CROSS_COMPILE)gcc
LD:=$(CROSS_COMPILE)gcc
AS:=$(CROSS_COMPILE)gcc
OBJCOPY:=$(CROSS_COMPILE)objcopy
SIZE:=$(CROSS_COMPILE)size
BOOT_IMG?=test-app/image.bin
BOOT0_OFFSET?=0x20000
BOOT0_OFFSET?=0x10000
SIGN?=ED25519
TARGET?=stm32f4
DEBUG?=0
@ -19,7 +20,7 @@ LSCRIPT:=hal/$(TARGET).ld
OBJS:= \
./hal/$(TARGET).o \
./src/loader.o \
./src/mem.o \
./src/string.o \
./src/crypto.o \
./src/wolfboot.o \
./src/image.o \
@ -29,20 +30,42 @@ OBJS:= \
./lib/wolfssl/wolfcrypt/src/wolfmath.o \
./lib/wolfssl/wolfcrypt/src/fe_low_mem.o
ifeq ($(TARGET),samr21)
CORTEX_M0=1
endif
ifeq ($(SIGN),ECC256)
KEYGEN_TOOL=tools/ecc256/ecc256_keygen
SIGN_TOOL=tools/ecc256/ecc256_sign
PRIVATE_KEY=ecc256.der
else
KEYGEN_TOOL=tools/ed25519/ed25519_keygen
SIGN_TOOL=tools/ed25519/ed25519_sign
PRIVATE_KEY=ed25519.der
endif
MATH_OBJS:=./lib/wolfssl/wolfcrypt/src/sp_int.o
ifeq ($(CORTEX_M0),1)
CFLAGS:=-mcpu=cortex-m0
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o
else
CFLAGS:=-mcpu=cortex-m3
MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o
endif
ifeq ($(FASTMATH),1)
MATH_OBJS:=./lib/wolfssl/wolfcrypt/src/integer.o
CFLAGS+=-DUSE_FAST_MATH
endif
CFLAGS+=-mthumb -Wall -Wextra -Wno-main -Wstack-usage=1024 -ffreestanding -Wno-unused \
-Ilib/bootutil/include -Iinclude/ -Ilib/wolfssl -nostartfiles \
-nostdlib \
-DWOLFSSL_USER_SETTINGS \
-mthumb -mlittle-endian -mthumb-interwork \
-DPLATFORM_$(TARGET)
ifeq ($(SIGN),ED25519)
@ -50,12 +73,20 @@ ifeq ($(SIGN),ED25519)
./lib/wolfssl/wolfcrypt/src/ed25519.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./src/ed25519_pub_key.o
CFLAGS+=-DWOLFBOOT_SIGN_ED25519
CFLAGS+=-DWOLFBOOT_SIGN_ED25519 -nostdlib -DWOLFSSL_STATIC_MEMORY
LDFLAGS+=-nostdlib
endif
ifeq ($(SIGN),EC256)
OBJS+= ./ext/wolfssl/wolfcrypt/src/ecc.o
CFLAGS+=-DWOLFBOOT_SIGN_EC256
ifeq ($(SIGN),ECC256)
OBJS+= \
$(MATH_OBJS) \
./lib/wolfssl/wolfcrypt/src/ecc.o \
./lib/wolfssl/wolfcrypt/src/ge_low_mem.o \
./lib/wolfssl/wolfcrypt/src/memory.o \
./lib/wolfssl/wolfcrypt/src/wc_port.o \
./src/ecc256_pub_key.o \
./src/xmalloc.o
CFLAGS+=-DWOLFBOOT_SIGN_ECC256 -DXMALLOC_USER
endif
ifeq ($(DEBUG),1)
@ -68,7 +99,9 @@ ifeq ($(VTOR),0)
CFLAGS+=-DNO_VTOR
endif
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles -mcpu=cortex-m3 -mthumb -nostdlib
LDFLAGS:=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=wolfboot.map -ffreestanding -nostartfiles -mcpu=cortex-m3 -mthumb
ASFLAGS:=$(CFLAGS)
all: factory.bin
@ -92,16 +125,22 @@ test-app/image.bin:
tools/ed25519/ed25519_sign:
make -C tools/ed25519
tools/ecc256/ecc256_sign:
make -C tools/ecc256
ed25519.der: tools/ed25519/ed25519_sign
tools/ed25519/ed25519_keygen src/ed25519_pub_key.c
factory.bin: $(BOOT_IMG) wolfboot-align.bin tools/ed25519/ed25519_sign ed25519.der
tools/ed25519/ed25519_sign $(BOOT_IMG) ed25519.der 1
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)
$(SIGN_TOOL) $(BOOT_IMG) $(PRIVATE_KEY) 1
cat wolfboot-align.bin $(BOOT_IMG).v1.signed > $@
second.img: $(BOOT_IMG) wolfboot-align.bin tools/ed25519/ed25519_sign ed25519.der
tools/ed25519/ed25519_sign $(BOOT_IMG) ed25519.der 1 65536
tools/ed25519/ed25519_sign $(BOOT_IMG) ed25519.der 2
second.img: $(BOOT_IMG) wolfboot-align.bin $(SIGN_TOOL) $(PRIVATE_KEY)
$(SIGN_TOOL) $(BOOT_IMG) $(PRIVATE_KEY) 1 65536
$(SIGN_TOOL) $(BOOT_IMG) $(PRIVATE_KEY) 2
cat wolfboot-align.bin $(BOOT_IMG).v1.signed $(BOOT_IMG).v2.signed > $@
wolfboot.elf: $(OBJS) $(LSCRIPT)
@ -110,8 +149,9 @@ wolfboot.elf: $(OBJS) $(LSCRIPT)
src/ed25519_pub_key.c: ed25519.der
keys: ed25519.der
src/ecc256_pub_key.c: ecc256.der
keys: $(PRIVATE_KEY)
clean:
rm -f *.bin *.elf $(OBJS) wolfboot.map *.bin *.hex
@ -119,5 +159,6 @@ clean:
distclean: clean
make -C tools/ed25519 clean
rm -f *.pem *.der tags ./src/ed25519_pub_key.c
make -C tools/ecc256 clean
rm -f *.pem *.der tags ./src/ed25519_pub_key.c ./src/ecc256_pub_key.c

View File

@ -1,18 +1,18 @@
#ifndef LOADER_H
#define LOADER_H
#if defined(WOLFBOOT_SIGN_EC256)
extern const unsigned char ecdsa_pub_key[];
extern unsigned int ecdsa_pub_key_len;
# define KEY_BUFFER ecdsa_pub_key
# define KEY_LEN ecdsa_pub_key_len
# define IMAGE_SIGNATURE_SIZE (72)
#elif defined(WOLFBOOT_SIGN_ED25519)
#if defined(WOLFBOOT_SIGN_ED25519)
extern const unsigned char ed25519_pub_key[];
extern unsigned int ed25519_pub_key_len;
# define KEY_BUFFER ed25519_pub_key
# define KEY_LEN ed25519_pub_key_len
# define IMAGE_SIGNATURE_SIZE (64)
#elif defined(WOLFBOOT_SIGN_ECC256)
extern const unsigned char ecc256_pub_key[];
extern unsigned int ecc256_pub_key_len;
# define KEY_BUFFER ecc256_pub_key
# define KEY_LEN ecc256_pub_key_len
# define IMAGE_SIGNATURE_SIZE (64)
#else
# error "No public key available for given signing algorithm."
#endif /* Algorithm selection */

View File

@ -6,11 +6,11 @@
* Ensure that your firmware entry point is
* at FLASH_AREA_IMAGE_0_OFFSET + 0x100
*/
#define WOLFBOOT_SECTOR_SIZE 0x20000
#define WOLFBOOT_PARTITION_SIZE 0x20000
#define WOLFBOOT_SECTOR_SIZE 0x1000
#define WOLFBOOT_PARTITION_SIZE 0x10000
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x20000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x40000
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x60000
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x10000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x20000
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x30000
#endif

View File

@ -5,9 +5,8 @@
#define NO_DEV_RANDOM
#define NO_FILESYSTEM
#define NO_MAIN_DRIVER
#define NO_SIG_WRAPPER
#define NO_OLD_RNGNAME
#define WOLFSSL_STATIC_MEMORY
//#define WOLFSSL_SMALL_STACK
#define USE_SLOW_SHA512
@ -21,7 +20,6 @@
# define NO_CERT
# define NO_SESSION_CACHE
# define NO_HC128
# define NO_ASN
# define NO_DES3
# define NO_WOLFSSL_DIR
# define NO_PWDBASED
@ -32,24 +30,44 @@
#define SMALL_SESSION_CACHE
#define WOLFSSL_DH_CONST
#define WORD64_AVAILABLE
#define TFM_TIMING_RESISTANT
//#define USE_CERT_BUFFERS_2048
#define NO_RC4
#define WOLFCRYPT_ONLY
#define WOLFSSL_NO_SOCK
# define WC_NO_RNG
#ifdef WOLFBOOT_SIGN_ED25519
# define HAVE_ED25519
# define ED25519_SMALL
# define NO_ED25519_SIGN
# define NO_ED25519_EXPORT
# define USE_FAST_MATH
# define WOLFSSL_SHA512
# define NO_ASN
#endif
#ifdef WOLFBOOT_SIGN_ECC256
# define HAVE_ECC
# define FP_ECC
# define HAVE_ECC_VERIFY
# define ECC_ALT_SIZE
# define NO_ECC_SIGN
# define NO_ECC_EXPORT
# define USE_FAST_MATH
# define WOLFSSL_SHA512
# define WOLFSSL_SP_SMALL
# define SP_WORD_SIZE 32
# define WOLFSSL_HAVE_SP_ECC
# define WOLFSSL_SP_MATH
# define NO_ASN
//# define NO_ECC_SIGN
# define NO_ECC_DHE
# define NO_ECC_KEY_EXPORT
#endif
/* AES */
# define NO_AES
# define NO_CMAC
# define NO_CODING
# define WOLFSSL_SHA512
# define NO_BIG_INT
# define NO_RSA

@ -1 +1 @@
Subproject commit 4995051081b65e804594c6e45a54a3b10d6598ac
Subproject commit a506c6591dad47036508d55315d09bc13b799a1f

View File

@ -48,6 +48,40 @@ static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
}
#endif
#ifdef WOLFBOOT_SIGN_ECC256
#include <wolfssl/wolfcrypt/ecc.h>
#define ECC_KEY_SIZE 32
#define ECC_SIG_SIZE 64
static int wolfBoot_verify_signature(uint8_t *hash, uint8_t *sig)
{
int ret, res;
mp_int r, s;
ecc_key ecc;
ret = wc_ecc_init(&ecc);
if (ret < 0) {
/* Failed to initialize key */
return -1;
}
/* Import public key */
ret = wc_ecc_import_unsigned(&ecc, KEY_BUFFER, KEY_BUFFER + 32, NULL, ECC_SECP256R1);
if ((ret < 0) || ecc.type != ECC_PUBLICKEY) {
/* Failed to import ecc key */
return -1;
}
/* Import signature into r,s */
mp_init(&r);
mp_init(&s);
mp_read_unsigned_bin(&r, sig, ECC_KEY_SIZE);
mp_read_unsigned_bin(&s, sig + ECC_KEY_SIZE, ECC_KEY_SIZE);
ret = wc_ecc_verify_hash_ex(&r, &s, hash, SHA256_DIGEST_SIZE, &res, &ecc);
if ((ret < 0) || (res == 0)) {
return -1;
}
return 0;
}
#endif
static uint8_t get_header(struct wolfBoot_image *img, uint8_t type, uint8_t **ptr)
{

View File

@ -1,76 +0,0 @@
/* mem.c
*
* Copyright (C) 2018 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
*/
#include <stddef.h>
void * memset(void *s, int c, size_t n)
{
unsigned char *d = (unsigned char *)s;
while (n--) {
*d++ = (unsigned char)c;
}
return s;
}
void *memcpy(void *dst, const void *src, size_t n)
{
size_t i;
const char *s = (const char *)src;
char *d = (char *)dst;
for (i = 0; i < n; i++) {
d[i] = s[i];
}
return dst;
}
int memcmp(const void *_s1, const void *_s2, size_t n)
{
int diff = 0;
const unsigned char *s1 = (const unsigned char *)_s1;
const unsigned char *s2 = (const unsigned char *)_s2;
while(!diff && n)
{
diff = (int)*s1 - (int)*s2;
s1++;
s2++;
n--;
}
return diff;
}
void *memmove(void *dst, const void *src, size_t n)
{
int i;
if (dst == src)
return dst;
if (src < dst) {
const char *s = (const char *)src;
char *d = (char *)dst;
for (i = n - 1; i >= 0; i--) {
d[i] = s[i];
}
return dst;
} else {
return memcpy(dst, src, n);
}
}

192
src/string.c 100644
View File

@ -0,0 +1,192 @@
#include <stddef.h>
#include <string.h>
void *memset(void *s, int c, size_t n)
{
unsigned char *d = (unsigned char *)s;
while (n--) {
*d++ = (unsigned char)c;
}
return s;
}
char *strcat(char *dest, const char *src)
{
int i = 0;
int j = strlen(dest);
for (i = 0; i < strlen(src); i++) {
dest[j++] = src[i];
}
dest[j] = '\0';
return dest;
}
int strcmp(const char *s1, const char *s2)
{
int diff = 0;
while (!diff && *s1) {
diff = (int)*s1 - (int)*s2;
s1++;
s2++;
}
return diff;
}
int strcasecmp(const char *s1, const char *s2)
{
int diff = 0;
while (!diff && *s1) {
diff = (int)*s1 - (int)*s2;
if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
diff = 0;
s1++;
s2++;
}
return diff;
}
int strncasecmp(const char *s1, const char *s2, size_t n)
{
int diff = 0;
int i = 0;
while (!diff && *s1) {
diff = (int)*s1 - (int)*s2;
if ((diff == 'A' - 'a') || (diff == 'a' - 'A'))
diff = 0;
s1++;
s2++;
if (++i > n)
break;
}
return diff;
}
size_t strlen(const char *s)
{
int i = 0;
while (s[i] != 0)
i++;
return i;
}
char *strncat(char *dest, const char *src, size_t n)
{
int i = 0;
int j = strlen(dest);
for (i = 0; i < strlen(src); i++) {
if (j >= (n - 1)) {
break;
}
dest[j++] = src[i];
}
dest[j] = '\0';
return dest;
}
int strncmp(const char *s1, const char *s2, size_t n)
{
int diff = 0;
while (n > 0) {
diff = (unsigned char)*s1 - (unsigned char)*s2;
if (diff || !*s1)
break;
s1++;
s2++;
n--;
}
return diff;
}
void *memcpy(void *dst, const void *src, size_t n)
{
int i;
const char *s = (const char *)src;
char *d = (char *)dst;
for (i = 0; i < n; i++) {
d[i] = s[i];
}
return dst;
}
char *strncpy(char *dst, const char *src, size_t n)
{
int i;
for (i = 0; i < n; i++) {
dst[i] = src[i];
if (src[i] == '\0')
break;
}
return dst;
}
char *strcpy(char *dst, const char *src)
{
int i = 0;
while(1 < 2) {
dst[i] = src[i];
if (src[i] == '\0')
break;
i++;
}
return dst;
}
int memcmp(const void *_s1, const void *_s2, size_t n)
{
int diff = 0;
const unsigned char *s1 = (const unsigned char *)_s1;
const unsigned char *s2 = (const unsigned char *)_s2;
while (!diff && n) {
diff = (int)*s1 - (int)*s2;
s1++;
s2++;
n--;
}
return diff;
}
void *memmove(void *dst, const void *src, size_t n)
{
int i;
if (dst == src)
return dst;
if (src < dst) {
const char *s = (const char *)src;
char *d = (char *)dst;
for (i = n - 1; i >= 0; i--) {
d[i] = s[i];
}
return dst;
} else {
return memcpy(dst, src, n);
}
}

56
src/xmalloc.c 100644
View File

@ -0,0 +1,56 @@
#include <stdlib.h>
#include <stdint.h>
/* Allow one single sp_point to be allocated at one time */
#define SP_POINT_SIZE (244)
#define MAX_POINTS 2
#define SCRATCHBOARD_SIZE (640)
static uint8_t sp_scratchboard[SCRATCHBOARD_SIZE];
static int sp_scratchboard_in_use = 0;
static uint8_t sp_point_buffer0[SP_POINT_SIZE];
static uint8_t sp_point_buffer1[SP_POINT_SIZE];
static int point_0_in_use = 0;
static int point_1_in_use = 0;
static void* xmalloc_sp_point(void)
{
if (point_0_in_use) {
if (point_1_in_use)
return NULL;
point_1_in_use++;
return sp_point_buffer1;
}
point_0_in_use++;
return sp_point_buffer0;
}
static void* xmalloc_sp_scratchboard(void)
{
if (sp_scratchboard_in_use)
return NULL;
sp_scratchboard_in_use++;
return sp_scratchboard;
}
void* XMALLOC(size_t n, void* heap, int type)
{
if (n == SP_POINT_SIZE)
return xmalloc_sp_point();
if (n == SCRATCHBOARD_SIZE)
return xmalloc_sp_scratchboard();
return NULL;
}
void XFREE(void *ptr)
{
if (ptr == sp_point_buffer0)
point_0_in_use = 0;
if (ptr == sp_point_buffer1)
point_1_in_use = 0;
if (ptr == sp_scratchboard)
sp_scratchboard_in_use = 0;
}

View File

@ -77,3 +77,20 @@ void main(void)
#endif
#ifdef PLATFORM_samr21
void main(void) {
asm volatile ("cpsie i");
while(1)
WFI();
}
#endif
#ifdef PLATFORM_lm3s
void main(void) {
asm volatile ("cpsie i");
while(1)
WFI();
}
#endif

View File

@ -0,0 +1,24 @@
# 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 -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

@ -0,0 +1,151 @@
/* 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

@ -0,0 +1,306 @@
/*
* 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"
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;
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;
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);
}