Compare commits

...

9 Commits

Author SHA1 Message Date
Conor Patrick
0873fa5f34 fix solo locked flag for bootloader 2019-10-27 10:17:13 -04:00
Conor Patrick
bb08f6e0d3 fix build 2019-10-27 10:06:39 -04:00
Conor Patrick
9fa2c97dc3 store all info in same page, dont use authenticator state 2019-10-27 09:27:56 -04:00
Conor Patrick
49ca42991c add locked variable to GETVERSION hid command 2019-10-27 09:03:17 -04:00
Conor Patrick
ef683bdc99 remove logs 2019-10-27 08:59:10 -04:00
Conor Patrick
69478b4b6e remove hacker macros 2019-10-27 08:58:34 -04:00
Conor Patrick
9d5942ad10 lock flash based on state setting 2019-10-27 08:58:12 -04:00
Conor Patrick
446f1e0176 migrate certs 2019-10-27 08:40:06 -04:00
Conor Patrick
de2c1eff1b pull certificate from flash page 2019-10-27 07:51:02 -04:00
12 changed files with 167 additions and 46 deletions

View File

@ -47,7 +47,7 @@ typedef enum
#endif #endif
const uint8_t attestation_cert_der[]; const uint8_t * attestation_cert_der;
const uint16_t attestation_cert_der_size; const uint16_t attestation_cert_der_size;
const uint8_t attestation_key[]; const uint8_t attestation_key[];
const uint16_t attestation_key_size; const uint16_t attestation_key_size;
@ -338,7 +338,7 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
} }
const uint8_t attestation_cert_der[] = const uint8_t _attestation_cert_der[] =
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08" "\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13" "\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13"
"\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e" "\x02\x55\x53\x31\x0b\x30\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e"
@ -365,9 +365,11 @@ const uint8_t attestation_cert_der[] =
"\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd" "\x7e\x74\x64\x1b\xa3\x7b\xf7\xe6\xd3\xaf\x79\x28\xdb\xdc\xa5\x88\x02\x21\x00\xcd"
"\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7" "\x06\xf1\xe3\xab\x16\x21\x8e\xd8\xc0\x14\xaf\x09\x4f\x5b\x73\xef\x5e\x9e\x4b\xe7"
"\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7"; "\x35\xeb\xdd\x9b\x6d\x8f\x7d\xf3\xc4\x3a\xd7";
const uint8_t * attestation_cert_der = (const uint8_t *)_attestation_cert_der;
uint16_t attestation_cert_der_get_size(){
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1; return sizeof(_attestation_cert_der)-1;
}
const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30"; const uint8_t attestation_key[] = "\xcd\x67\xaa\x31\x0d\x09\x1e\xd1\x6e\x7e\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae\x7c\x40\x8f\xb9\x46\xb7\x2e\x5f\xe7\x5d\x30";

View File

@ -54,10 +54,7 @@ void crypto_reset_master_secret();
void crypto_load_master_secret(uint8_t * key); void crypto_load_master_secret(uint8_t * key);
extern const uint8_t attestation_cert_der[]; extern const uint8_t * attestation_cert_der;
extern const uint16_t attestation_cert_der_size; uint16_t attestation_cert_der_get_size();
extern const uint8_t attestation_key[];
extern const uint16_t attestation_key_size;
#endif #endif

View File

@ -661,7 +661,7 @@ uint8_t ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1); ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
check_ret(ret); check_ret(ret);
{ {
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size); ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_get_size());
check_ret(ret); check_ret(ret);
ret = cbor_encoder_close_container(&stmtmap, &x5carr); ret = cbor_encoder_close_container(&stmtmap, &x5carr);
check_ret(ret); check_ret(ret);

View File

@ -696,7 +696,7 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
{ {
ctap_response_init(ctap_resp); ctap_response_init(ctap_resp);
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL)) #if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
uint32_t param; uint32_t param;
#endif #endif
#if defined(IS_BOOTLOADER) #if defined(IS_BOOTLOADER)
@ -716,17 +716,13 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
ctaphid_write(wb, NULL, 0); ctaphid_write(wb, NULL, 0);
return 1; return 1;
#endif #endif
#if defined(SOLO_HACKER) #if defined(SOLO)
case CTAPHID_ENTERBOOT: case CTAPHID_ENTERBOOT:
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n"); printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
boot_solo_bootloader(); boot_solo_bootloader();
wb->bcnt = 0; wb->bcnt = 0;
ctaphid_write(wb, NULL, 0); ctaphid_write(wb, NULL, 0);
return 1; return 1;
case CTAPHID_ENTERSTBOOT:
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
boot_st_bootloader();
return 1;
#endif #endif
#if !defined(IS_BOOTLOADER) #if !defined(IS_BOOTLOADER)
@ -745,16 +741,21 @@ uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE
case CTAPHID_GETVERSION: case CTAPHID_GETVERSION:
printf1(TAG_HID,"CTAPHID_GETVERSION\n"); printf1(TAG_HID,"CTAPHID_GETVERSION\n");
wb->bcnt = 3; wb->bcnt = 4;
ctap_buffer[0] = SOLO_VERSION_MAJ; ctap_buffer[0] = SOLO_VERSION_MAJ;
ctap_buffer[1] = SOLO_VERSION_MIN; ctap_buffer[1] = SOLO_VERSION_MIN;
ctap_buffer[2] = SOLO_VERSION_PATCH; ctap_buffer[2] = SOLO_VERSION_PATCH;
ctaphid_write(wb, ctap_buffer, 3); #if defined(SOLO)
ctap_buffer[3] = solo_is_locked();
#else
ctap_buffer[3] = 0;
#endif
ctaphid_write(wb, ctap_buffer, 4);
ctaphid_write(wb, NULL, 0); ctaphid_write(wb, NULL, 0);
return 1; return 1;
break; break;
#if !defined(IS_BOOTLOADER) && (defined(SOLO_HACKER) || defined(SOLO_EXPERIMENTAL)) #if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
case CTAPHID_LOADKEY: case CTAPHID_LOADKEY:
/** /**
* Load external key. Useful for enabling backups. * Load external key. Useful for enabling backups.

View File

@ -306,7 +306,7 @@ static int16_t u2f_register(struct u2f_register_request * req)
uint8_t * sig = (uint8_t*)req; uint8_t * sig = (uint8_t*)req;
const uint16_t attest_size = attestation_cert_der_size; const uint16_t attest_size = attestation_cert_der_get_size();
if ( ! ctap_user_presence_test(750)) if ( ! ctap_user_presence_test(750))
{ {

View File

@ -64,4 +64,9 @@ int is_authorized_to_boot();
int is_bootloader_disabled(); int is_bootloader_disabled();
void bootloader_heartbeat(); void bootloader_heartbeat();
// Return 1 if Solo is secure/locked.
int solo_is_locked();
#endif #endif

View File

@ -9,6 +9,8 @@
#include <stdint.h> #include <stdint.h>
#include "version.h" #include "version.h"
#define SOLO
#define DEBUG_UART USART1 #define DEBUG_UART USART1
#ifndef DEBUG_LEVEL #ifndef DEBUG_LEVEL
@ -46,6 +48,9 @@
void printing_init(); void printing_init();
void hw_init(int lf); void hw_init(int lf);
// Return 1 if Solo is secure/locked.
int solo_is_locked();
//#define TEST //#define TEST
//#define TEST_POWER //#define TEST_POWER

View File

@ -6,10 +6,10 @@
// copied, modified, or distributed except according to those terms. // copied, modified, or distributed except according to those terms.
#include <stdint.h> #include <stdint.h>
#include "crypto.h" #include "crypto.h"
#include "memory_layout.h"
#ifdef USE_SOLOKEYS_CERT
const uint8_t attestation_cert_der[] = const uint8_t attestation_solo_cert_der[] =
"\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08" "\x30\x82\x02\xe1\x30\x82\x02\x88\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x80\x31\x0b\x30\x09\x06\x03\x55\x04\x06" "\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x80\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c" "\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
@ -49,11 +49,8 @@ const uint8_t attestation_cert_der[] =
"\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71" "\xf8\x84\xc3\x78\x35\x93\x63\x81\x2e\xbe\xa6\x12\x32\x6e\x29\x90\xc8\x91\x4b\x71"
"\x52" "\x52"
; ;
#else
// For testing/development only const uint8_t attestation_hacker_cert_der[] =
const uint8_t attestation_cert_der[] =
"\x30\x82\x02\xe9\x30\x82\x02\x8e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08" "\x30\x82\x02\xe9\x30\x82\x02\x8e\xa0\x03\x02\x01\x02\x02\x01\x01\x30\x0a\x06\x08"
"\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06" "\x2a\x86\x48\xce\x3d\x04\x03\x02\x30\x81\x82\x31\x0b\x30\x09\x06\x03\x55\x04\x06"
"\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c" "\x13\x02\x55\x53\x31\x11\x30\x0f\x06\x03\x55\x04\x08\x0c\x08\x4d\x61\x72\x79\x6c"
@ -94,8 +91,16 @@ const uint8_t attestation_cert_der[] =
"\xf3\x87\x61\x82\xd8\xcd\x48\xfc\x57" "\xf3\x87\x61\x82\xd8\xcd\x48\xfc\x57"
; ;
#endif
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1; const uint16_t attestation_solo_cert_der_size = sizeof(attestation_solo_cert_der)-1;
const uint16_t attestation_hacker_cert_der_size = sizeof(attestation_hacker_cert_der)-1;
// const uint16_t attestation_key_size = 32;
const uint8_t * attestation_cert_der = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert;
#include "log.h"
uint16_t attestation_cert_der_get_size(){
uint16_t sz = (uint16_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size;
return sz;
}
const uint16_t attestation_key_size = 32;

View File

@ -194,9 +194,10 @@ void crypto_ecc256_init(void)
void crypto_ecc256_load_attestation_key(void) void crypto_ecc256_load_attestation_key(void)
{ {
static uint8_t _key [32]; // static uint8_t _key [32];
memmove(_key, (uint8_t*)ATTESTATION_KEY_ADDR, 32); flash_attestation_page * page =(flash_attestation_page *)ATTESTATION_PAGE_ADDR;
_signing_key = _key; // memmove(_key, (uint8_t *)ATTESTATION_KEY_ADDR, 32);
_signing_key = page->attestation_key;
_key_len = 32; _key_len = 32;
} }

View File

@ -34,6 +34,8 @@
#define LOW_FREQUENCY 1 #define LOW_FREQUENCY 1
#define HIGH_FREQUENCY 0 #define HIGH_FREQUENCY 0
#define SOLO_FLAG_LOCKED 0x2
void wait_for_usb_tether(void); void wait_for_usb_tether(void);
@ -191,6 +193,97 @@ void device_init_button(void)
} }
} }
int solo_is_locked(){
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
return (device_settings & SOLO_FLAG_LOCKED) != 0;
}
/** device_migrate
* Depending on version of device, migrates:
* * Moves attestation certificate to data segment.
* * Creates locked variable and stores in data segment.
*
* Once in place, this allows all devices to accept same firmware,
* rather than using "hacker" and "secure" builds.
*/
static void device_migrate(){
extern const uint16_t attestation_solo_cert_der_size;
extern const uint16_t attestation_hacker_cert_der_size;
extern uint8_t attestation_solo_cert_der[];
extern uint8_t attestation_hacker_cert_der[];
uint64_t device_settings = ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings;
uint32_t configure_tag = (uint32_t)(device_settings >> 32);
if (configure_tag != ATTESTATION_CONFIGURED_TAG)
{
printf1(TAG_RED,"Migrating certificate and lock information to data segment.\r\n");
device_settings = ATTESTATION_CONFIGURED_TAG;
device_settings <<= 32;
// Read current device lock level.
uint32_t optr = FLASH->OPTR;
if ((optr & 0xff) != 0xAA){
device_settings |= SOLO_FLAG_LOCKED;
}
uint8_t tmp_attestation_key[32];
memmove(tmp_attestation_key,
((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
32);
flash_erase_page(ATTESTATION_PAGE);
flash_write(
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_key,
tmp_attestation_key,
32
);
// Check if this is Solo Hacker attestation (not confidential)
// then write solo or hacker attestation cert to flash page.
uint8_t solo_hacker_attestation_key[32] = "\x1b\x26\x26\xec\xc8\xf6\x9b\x0f\x69\xe3\x4f"
"\xb2\x36\xd7\x64\x66\xba\x12\xac\x16\xc3\xab"
"\x57\x50\xba\x06\x4e\x8b\x90\xe0\x24\x48";
if (memcmp(solo_hacker_attestation_key,
tmp_attestation_key,
32) == 0)
{
printf1(TAG_GREEN,"Updating solo hacker cert\r\n");
flash_write_dword(
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
(uint64_t)attestation_hacker_cert_der_size
);
flash_write(
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
attestation_hacker_cert_der,
attestation_hacker_cert_der_size
);
}
else
{
printf1(TAG_GREEN,"Updating solo secure cert\r\n");
flash_write_dword(
(uint32_t)&((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert_size,
(uint64_t)attestation_solo_cert_der_size
);
flash_write(
(uint32_t)((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->attestation_cert,
attestation_solo_cert_der,
attestation_solo_cert_der_size
);
}
// Save / done.
flash_write_dword(
(uint32_t) & ((flash_attestation_page *)ATTESTATION_PAGE_ADDR)->device_settings,
(uint64_t)device_settings);
}
}
void device_init(int argc, char *argv[]) void device_init(int argc, char *argv[])
{ {
@ -219,6 +312,8 @@ void device_init(int argc, char *argv[])
ctaphid_init(); ctaphid_init();
ctap_init(); ctap_init();
device_migrate();
#if BOOT_TO_DFU #if BOOT_TO_DFU
flash_option_bytes_init(1); flash_option_bytes_init(1);
#else #else

View File

@ -31,16 +31,10 @@ static void flash_unlock(void)
// Locks flash and turns off DFU // Locks flash and turns off DFU
void flash_option_bytes_init(int boot_from_dfu) void flash_option_bytes_init(int boot_from_dfu)
{ {
#ifndef FLASH_ROP
#define FLASH_ROP 0
#endif
#if FLASH_ROP == 0
uint32_t val = 0xfffff8aa; uint32_t val = 0xfffff8aa;
#elif FLASH_ROP == 2 if (solo_is_locked()){
uint32_t val = 0xfffff8cc; val = 0xfffff8cc;
#else }
uint32_t val = 0xfffff8b9;
#endif
if (boot_from_dfu) if (boot_from_dfu)
{ {

View File

@ -20,6 +20,9 @@
#define STATE2_PAGE (PAGES - 2) #define STATE2_PAGE (PAGES - 2)
#define STATE1_PAGE (PAGES - 1) #define STATE1_PAGE (PAGES - 1)
#define STATE1_PAGE_ADDR (0x08000000 + ((STATE1_PAGE)*PAGE_SIZE))
#define STATE2_PAGE_ADDR (0x08000000 + ((STATE2_PAGE)*PAGE_SIZE))
// Storage of FIDO2 resident keys // Storage of FIDO2 resident keys
#define RK_NUM_PAGES 10 #define RK_NUM_PAGES 10
#define RK_START_PAGE (PAGES - 14) #define RK_START_PAGE (PAGES - 14)
@ -32,8 +35,8 @@
#define APPLICATION_START_ADDR (0x08000000 + ((APPLICATION_START_PAGE)*PAGE_SIZE)) #define APPLICATION_START_ADDR (0x08000000 + ((APPLICATION_START_PAGE)*PAGE_SIZE))
// where attestation key is located // where attestation key is located
#define ATTESTATION_KEY_PAGE (PAGES - 15) #define ATTESTATION_PAGE (PAGES - 15)
#define ATTESTATION_KEY_ADDR (0x08000000 + ATTESTATION_KEY_PAGE*PAGE_SIZE) #define ATTESTATION_PAGE_ADDR (0x08000000 + ATTESTATION_PAGE*PAGE_SIZE)
// End of application code. Leave some extra room for future data storage. // End of application code. Leave some extra room for future data storage.
// NOT included in application // NOT included in application
@ -48,7 +51,6 @@
#define BOOT_VERSION_ADDR (0x08000000 + BOOT_VERSION_PAGE*FLASH_PAGE_SIZE + 8) #define BOOT_VERSION_ADDR (0x08000000 + BOOT_VERSION_PAGE*FLASH_PAGE_SIZE + 8)
#define LAST_PAGE (APPLICATION_END_PAGE-1) #define LAST_PAGE (APPLICATION_END_PAGE-1)
struct flash_memory_st{ struct flash_memory_st{
uint8_t bootloader[APPLICATION_START_PAGE*2*1024]; uint8_t bootloader[APPLICATION_START_PAGE*2*1024];
uint8_t application[(APPLICATION_END_PAGE-APPLICATION_START_PAGE)*2*1024-8]; uint8_t application[(APPLICATION_END_PAGE-APPLICATION_START_PAGE)*2*1024-8];
@ -65,5 +67,19 @@ typedef struct flash_memory_st flash_memory_st;
#include <assert.h> #include <assert.h>
static_assert(sizeof(flash_memory_st) == 256*1024, "Data structure doesn't match flash size"); static_assert(sizeof(flash_memory_st) == 256*1024, "Data structure doesn't match flash size");
#define ATTESTATION_CONFIGURED_TAG 0xaa551e78
struct flash_attestation_page{
uint8_t attestation_key[32];
// DWORD padded.
uint64_t device_settings;
uint64_t attestation_cert_size;
uint8_t attestation_cert[2048 - 32 - 8 - 8];
} __attribute__((packed));
typedef struct flash_attestation_page flash_attestation_page;
static_assert(sizeof(flash_attestation_page) == 2048, "Data structure doesn't match flash size");
#endif #endif