From 0c296bba301e50db09398aa4807df8c57256ea6b Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Mon, 25 Feb 2019 02:41:58 +0100 Subject: [PATCH 1/7] First go at using cifra for SHA512 --- .gitmodules | 3 +++ crypto/cifra | 1 + fido2/crypto.h | 4 ++++ fido2/ctaphid.c | 27 ++++++++++++++++++++++++++ fido2/ctaphid.h | 1 + targets/stm32l432/build/application.mk | 3 +++ targets/stm32l432/src/crypto.c | 16 +++++++++++++++ 7 files changed, 55 insertions(+) create mode 160000 crypto/cifra diff --git a/.gitmodules b/.gitmodules index 05c9e6f..8f2ea4e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "targets/stm32l442/dfuse-tool"] path = targets/stm32l442/dfuse-tool url = https://github.com/solokeys/dfuse-tool +[submodule "crypto/cifra"] + path = crypto/cifra + url = https://github.com/ctz/cifra.git diff --git a/crypto/cifra b/crypto/cifra new file mode 160000 index 0000000..d04dd31 --- /dev/null +++ b/crypto/cifra @@ -0,0 +1 @@ +Subproject commit d04dd318609733d809904d4f2973597240655cde diff --git a/fido2/crypto.h b/fido2/crypto.h index 844e7f3..4fc54a2 100644 --- a/fido2/crypto.h +++ b/fido2/crypto.h @@ -19,6 +19,10 @@ void crypto_sha256_final(uint8_t * hash); void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac); void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac); +void crypto_sha512_init(); +void crypto_sha512_update(const uint8_t * data, size_t len); +void crypto_sha512_final(uint8_t * hash); + void crypto_ecc256_init(); void crypto_ecc256_derive_public_key(uint8_t * data, int len, uint8_t * x, uint8_t * y); diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 5ddc260..0885ed9 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -16,6 +16,12 @@ #include "util.h" #include "log.h" #include "extensions.h" + +// move custom HASH512 command out, +// and the following headers too +#include "sha2.h" +#include "crypto.h" + #include APP_CONFIG typedef enum @@ -718,6 +724,27 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) ctaphid_write(&wb, NULL, 0); is_busy = 0; break; +#endif +#if defined(SOLO_HACKER) + case CTAPHID_HASH512: + // some random logging + printf1(TAG_HID,"CTAPHID_HASH512\n"); + // initialise CTAP response object + ctap_response_init(&ctap_resp); + // initialise write buffer + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_HASH512; + wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes + // calculate hash + crypto_sha512_init(); + crypto_sha512_update(ctap_buffer, buffer_len()); + crypto_sha512_final(ctap_buffer); + // copy to output + ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ); + ctaphid_write(&wb, NULL, 0); + is_busy = 0; + break; #endif default: printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); diff --git a/fido2/ctaphid.h b/fido2/ctaphid.h index d5ea35b..b728b0f 100644 --- a/fido2/ctaphid.h +++ b/fido2/ctaphid.h @@ -28,6 +28,7 @@ #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52) #define CTAPHID_GETRNG (TYPE_INIT | 0x60) +#define CTAPHID_HASH512 (TYPE_INIT | 0x70) #define ERR_INVALID_CMD 0x01 #define ERR_INVALID_PAR 0x02 diff --git a/targets/stm32l432/build/application.mk b/targets/stm32l432/build/application.mk index a22bc1d..2efb050 100644 --- a/targets/stm32l432/build/application.mk +++ b/targets/stm32l432/build/application.mk @@ -14,6 +14,7 @@ SRC += ../../fido2/extensions/extensions.c ../../fido2/extensions/solo.c # Crypto libs SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c ../../crypto/tiny-AES-c/aes.c +SRC += ../../crypto/cifra/src/sha512.c ../../crypto/cifra/src/blockwise.c OBJ1=$(SRC:.c=.o) OBJ=$(OBJ1:.s=.o) @@ -21,6 +22,7 @@ OBJ=$(OBJ1:.s=.o) INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc INC += -I../../crypto/tiny-AES-c +INC += -I../../crypto/cifra/src SEARCH=-L../../tinycbor/lib @@ -66,6 +68,7 @@ all: $(TARGET).elf $(CC) $^ $(HW) $(LDFLAGS) -o $@ %.hex: %.elf + $(SZ) $^ $(CP) -O ihex $^ $(TARGET).hex clean: diff --git a/targets/stm32l432/src/crypto.c b/targets/stm32l432/src/crypto.c index 7de78fa..31812d4 100644 --- a/targets/stm32l432/src/crypto.c +++ b/targets/stm32l432/src/crypto.c @@ -24,6 +24,9 @@ #include "aes.h" #include "ctap.h" #include "device.h" +// stuff for SHA512 +#include "sha2.h" +#include "blockwise.h" #include APP_CONFIG #include "log.h" #include "memory_layout.h" @@ -48,6 +51,7 @@ typedef enum static SHA256_CTX sha256_ctx; +static cf_sha512_context sha512_ctx; static const struct uECC_Curve_t * _es256_curve = NULL; static const uint8_t * _signing_key = NULL; static int _key_len = 0; @@ -62,6 +66,9 @@ void crypto_sha256_init() sha256_init(&sha256_ctx); } +void crypto_sha512_init() { + cf_sha512_init(&sha512_ctx); +} void crypto_load_master_secret(uint8_t * key) { @@ -86,6 +93,10 @@ void crypto_sha256_update(uint8_t * data, size_t len) sha256_update(&sha256_ctx, data, len); } +void crypto_sha512_update(const uint8_t * data, size_t len) { + cf_sha512_update(&sha512_ctx, data, len); +} + void crypto_sha256_update_secret() { sha256_update(&sha256_ctx, master_secret, 32); @@ -96,6 +107,11 @@ void crypto_sha256_final(uint8_t * hash) sha256_final(&sha256_ctx, hash); } +void crypto_sha512_final(uint8_t * hash) { + // NB: there is also cf_sha512_digest + cf_sha512_digest_final(&sha512_ctx, hash); +} + void crypto_sha256_hmac_init(uint8_t * key, uint32_t klen, uint8_t * hmac) { uint8_t buf[64]; From a6673b09178a353f6acc18157283bee962640538 Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Tue, 26 Feb 2019 19:31:14 +0100 Subject: [PATCH 2/7] Use our cifra fork, rename command, keep room for sha256 --- .gitmodules | 2 +- fido2/ctaphid.c | 8 ++++---- fido2/ctaphid.h | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8f2ea4e..35886ad 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,4 +15,4 @@ url = https://github.com/solokeys/dfuse-tool [submodule "crypto/cifra"] path = crypto/cifra - url = https://github.com/ctz/cifra.git + url = https://github.com/solokeys/cifra.git diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 0885ed9..6452cde 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -17,7 +17,7 @@ #include "log.h" #include "extensions.h" -// move custom HASH512 command out, +// move custom SHA512 command out, // and the following headers too #include "sha2.h" #include "crypto.h" @@ -726,15 +726,15 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) break; #endif #if defined(SOLO_HACKER) - case CTAPHID_HASH512: + case CTAPHID_SHA512: // some random logging - printf1(TAG_HID,"CTAPHID_HASH512\n"); + printf1(TAG_HID,"CTAPHID_SHA512\n"); // initialise CTAP response object ctap_response_init(&ctap_resp); // initialise write buffer ctaphid_write_buffer_init(&wb); wb.cid = cid; - wb.cmd = CTAPHID_HASH512; + wb.cmd = CTAPHID_SHA512; wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes // calculate hash crypto_sha512_init(); diff --git a/fido2/ctaphid.h b/fido2/ctaphid.h index b728b0f..7224ca5 100644 --- a/fido2/ctaphid.h +++ b/fido2/ctaphid.h @@ -28,7 +28,8 @@ #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52) #define CTAPHID_GETRNG (TYPE_INIT | 0x60) -#define CTAPHID_HASH512 (TYPE_INIT | 0x70) +#define CTAPHID_SHA256 (TYPE_INIT | 0x70) // not implemented +#define CTAPHID_SHA512 (TYPE_INIT | 0x71) #define ERR_INVALID_CMD 0x01 #define ERR_INVALID_PAR 0x02 From c97b9f9b8f6f8020bc090719cd200c5070a65e34 Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Tue, 26 Feb 2019 20:16:38 +0100 Subject: [PATCH 3/7] Need includes in main Makefile too --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 1e6b38b..bbc7983 100644 --- a/Makefile +++ b/Makefile @@ -23,6 +23,7 @@ LDFLAGS += $(LIBCBOR) CFLAGS = -O2 -fdata-sections -ffunction-sections INCLUDES = -I./tinycbor/src -I./crypto/sha256 -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ -I./fido2/ -I./pc -I./fido2/extensions +INCLUDES += -I./crypto/cifra/src CFLAGS += $(INCLUDES) # for crypto/tiny-AES-c From 865b698bed07d5e17ad77cf01ba77779e6ea9f6c Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Tue, 26 Feb 2019 23:33:57 +0100 Subject: [PATCH 4/7] ...and bootloader --- targets/stm32l432/build/bootloader.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/targets/stm32l432/build/bootloader.mk b/targets/stm32l432/build/bootloader.mk index 0f1f2d3..954f1c3 100644 --- a/targets/stm32l432/build/bootloader.mk +++ b/targets/stm32l432/build/bootloader.mk @@ -13,6 +13,7 @@ SRC += ../../fido2/stubs.c ../../fido2/log.c ../../fido2/ctaphid.c ../../fido2 # Crypto libs SRC += ../../crypto/sha256/sha256.c ../../crypto/micro-ecc/uECC.c +SRC += ../../crypto/cifra/src/sha512.c ../../crypto/cifra/src/blockwise.c OBJ1=$(SRC:.c=.o) OBJ=$(OBJ1:.s=.o) @@ -21,6 +22,7 @@ OBJ=$(OBJ1:.s=.o) INC = -Ibootloader/ -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc INC += -I../../crypto/tiny-AES-c +INC += -I../../crypto/cifra/src ifndef LDSCRIPT LDSCRIPT=linker/bootloader_stm32l4xx.ld From 47aa2874805d0c2a04d44bf09403deb67d6b9acd Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Tue, 26 Feb 2019 23:50:01 +0100 Subject: [PATCH 5/7] Vanilla cifra needs more includes --- targets/stm32l432/build/application.mk | 2 +- targets/stm32l432/build/bootloader.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/stm32l432/build/application.mk b/targets/stm32l432/build/application.mk index 2efb050..9be7231 100644 --- a/targets/stm32l432/build/application.mk +++ b/targets/stm32l432/build/application.mk @@ -22,7 +22,7 @@ OBJ=$(OBJ1:.s=.o) INC = -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc INC += -I../../crypto/tiny-AES-c -INC += -I../../crypto/cifra/src +INC += -I../../crypto/cifra/src -I../../crypto/cifra/src/ext SEARCH=-L../../tinycbor/lib diff --git a/targets/stm32l432/build/bootloader.mk b/targets/stm32l432/build/bootloader.mk index 954f1c3..bf6edd8 100644 --- a/targets/stm32l432/build/bootloader.mk +++ b/targets/stm32l432/build/bootloader.mk @@ -22,7 +22,7 @@ OBJ=$(OBJ1:.s=.o) INC = -Ibootloader/ -Isrc/ -Isrc/cmsis/ -Ilib/ -Ilib/usbd/ -I../../fido2/ -I../../fido2/extensions INC += -I../../tinycbor/src -I../../crypto/sha256 -I../../crypto/micro-ecc INC += -I../../crypto/tiny-AES-c -INC += -I../../crypto/cifra/src +INC += -I../../crypto/cifra/src -I../../crypto/cifra/src/ext ifndef LDSCRIPT LDSCRIPT=linker/bootloader_stm32l4xx.ld From 5e70c11b543c6f3d75a929a7304ddf40e2730463 Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Wed, 27 Feb 2019 02:58:56 +0100 Subject: [PATCH 6/7] Hide onboard crypto tests behind a reserved ctaphid command --- fido2/ctaphid.c | 134 ++++++++++++++++++++++++++++++++++++- fido2/ctaphid.h | 4 +- targets/stm32l432/Makefile | 6 ++ 3 files changed, 141 insertions(+), 3 deletions(-) diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 6452cde..4fa4ab0 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -534,6 +534,10 @@ static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * ci return buffer_status(); } +extern void _check_ret(CborError ret, int line, const char * filename); +#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\ + if ((r) != CborNoError) exit(1); + uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) { uint8_t cmd; @@ -725,7 +729,134 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) is_busy = 0; break; #endif -#if defined(SOLO_HACKER) +#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) + case CTAPHID_PROBE: + + /* + * Expects CBOR-serialized data of the form + * {"subcommand": "hash_type", "data": b"the_data"} + * with hash_type in SHA256, SHA512 + */ + + // some random logging + printf1(TAG_HID,"CTAPHID_PROBE\n"); + // initialise CTAP response object + ctap_response_init(&ctap_resp); + // initialise write buffer + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_PROBE; + + // prepare parsing (or halt) + int ret; + CborParser parser; + CborValue it, map; + ret = cbor_parser_init( + ctap_buffer, (size_t) buffer_len(), + // strictly speaking, CTAP is not RFC canonical... + CborValidateCanonicalFormat, + &parser, &it); + check_hardcore(ret); + + CborType type = cbor_value_get_type(&it); + if (type != CborMapType) exit(1); + + ret = cbor_value_enter_container(&it,&map); + check_hardcore(ret); + + size_t map_length = 0; + ret = cbor_value_get_map_length(&it, &map_length); + if (map_length != 2) exit(1); + + // parse subcommand (or halt) + CborValue val; + ret = cbor_value_map_find_value(&it, "subcommand", &val); + check_hardcore(ret); + if (!cbor_value_is_text_string(&val)) + exit(1); + + int sha_version = 0; + bool found = false; + if (!found) { + ret = cbor_value_text_string_equals( + &val, "SHA256", &found); + check_hardcore(ret); + if (found) + sha_version = 256; + } + if (!found) { + ret = cbor_value_text_string_equals( + &val, "SHA512", &found); + check_hardcore(ret); + if (found) + sha_version = 512; + } + if (sha_version == 0) + exit(1); + + // parse data (or halt) + ret = cbor_value_map_find_value(&it, "data", &val); + check_hardcore(ret); + if (!cbor_value_is_byte_string(&val)) + exit(1); + + size_t data_length = 0; + ret = cbor_value_calculate_string_length(&val, &data_length); + check_hardcore(ret); + if (data_length > 6*1024) + exit(1); + + unsigned char data[6*1024]; + ret = cbor_value_copy_byte_string ( + &val, &data[0], &data_length, &val); + check_hardcore(ret); + + // execute subcommand + if (sha_version == 256) { + // calculate hash + crypto_sha256_init(); + crypto_sha256_update(data, data_length); + crypto_sha256_final(ctap_buffer); + // write output + wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes + ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ); + } + + if (sha_version == 512) { + // calculate hash + crypto_sha512_init(); + crypto_sha512_update(data, data_length); + crypto_sha512_final(ctap_buffer); + // write output + wb.bcnt = CF_SHA512_HASHSZ; // 64 bytes + ctaphid_write(&wb, &ctap_buffer, CF_SHA512_HASHSZ); + } + + // finalize + ctaphid_write(&wb, NULL, 0); + is_busy = 0; + break; + + /* + case CTAPHID_SHA256: + // some random logging + printf1(TAG_HID,"CTAPHID_SHA256\n"); + // initialise CTAP response object + ctap_response_init(&ctap_resp); + // initialise write buffer + ctaphid_write_buffer_init(&wb); + wb.cid = cid; + wb.cmd = CTAPHID_SHA256; + wb.bcnt = CF_SHA256_HASHSZ; // 32 bytes + // calculate hash + crypto_sha256_init(); + crypto_sha256_update(ctap_buffer, buffer_len()); + crypto_sha256_final(ctap_buffer); + // copy to output + ctaphid_write(&wb, &ctap_buffer, CF_SHA256_HASHSZ); + ctaphid_write(&wb, NULL, 0); + is_busy = 0; + break; case CTAPHID_SHA512: // some random logging printf1(TAG_HID,"CTAPHID_SHA512\n"); @@ -745,6 +876,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) ctaphid_write(&wb, NULL, 0); is_busy = 0; break; + */ #endif default: printf2(TAG_ERR,"error, unimplemented HID cmd: %02x\r\n", buffer_cmd()); diff --git a/fido2/ctaphid.h b/fido2/ctaphid.h index 7224ca5..135260b 100644 --- a/fido2/ctaphid.h +++ b/fido2/ctaphid.h @@ -28,8 +28,8 @@ #define CTAPHID_ENTERBOOT (TYPE_INIT | 0x51) #define CTAPHID_ENTERSTBOOT (TYPE_INIT | 0x52) #define CTAPHID_GETRNG (TYPE_INIT | 0x60) -#define CTAPHID_SHA256 (TYPE_INIT | 0x70) // not implemented -#define CTAPHID_SHA512 (TYPE_INIT | 0x71) +// reserved for debug, not implemented except for HACKER and DEBUG_LEVEl > 0 +#define CTAPHID_PROBE (TYPE_INIT | 0x70) #define ERR_INVALID_CMD 0x01 #define ERR_INVALID_PAR 0x02 diff --git a/targets/stm32l432/Makefile b/targets/stm32l432/Makefile index 0ac5843..19abebd 100644 --- a/targets/stm32l432/Makefile +++ b/targets/stm32l432/Makefile @@ -15,6 +15,12 @@ merge_hex=../../tools/solotool.py mergehex firmware-hacker: $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' +firmware-hacker-debug-1: + $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=1 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' + +firmware-hacker-debug-2: + $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=2 EXTRA_DEFINES='-DSOLO_HACKER -DFLASH_ROP=0' + firmware-secure: $(MAKE) -f $(APPMAKE) -j8 solo.hex PREFIX=$(PREFIX) DEBUG=0 EXTRA_DEFINES='-DUSE_SOLOKEYS_CERT -DFLASH_ROP=2' From 0865f2a6607ddc97bb965f19d538b71d6ca4caee Mon Sep 17 00:00:00 2001 From: Nicolas Stalder Date: Wed, 27 Feb 2019 03:18:12 +0100 Subject: [PATCH 7/7] do not probe bootloader --- fido2/ctaphid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fido2/ctaphid.c b/fido2/ctaphid.c index 4fa4ab0..6d247c7 100644 --- a/fido2/ctaphid.c +++ b/fido2/ctaphid.c @@ -729,7 +729,7 @@ uint8_t ctaphid_handle_packet(uint8_t * pkt_raw) is_busy = 0; break; #endif -#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) +#if defined(SOLO_HACKER) && (DEBUG_LEVEL > 0) && (!IS_BOOTLOADER == 1) case CTAPHID_PROBE: /*