From aafd0539bef85f1a72b2e558cf97a4b5a13827fc Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Sat, 4 Nov 2017 20:18:12 -0400 Subject: [PATCH] identify key handle by 8 byte hmac addition --- firmware/inc/u2f.h | 4 ++- firmware/src/atecc508a.c | 1 + firmware/src/main.c | 19 +++++------- firmware/src/u2f.c | 11 +++---- firmware/src/u2f_atecc.c | 58 ++++++++++++++++++++----------------- firmware/src/u2f_hid.c | 23 ++++++--------- tools/flashing/erase.sh | 3 -- tools/flashing/program.sh | 25 ++++++++++++++-- tools/monitor.sh | 24 ++++++++------- tools/setup_device.sh | 18 +++++------- tools/testing/u2f_server.py | 7 +++++ 11 files changed, 109 insertions(+), 84 deletions(-) delete mode 100644 tools/flashing/erase.sh diff --git a/firmware/inc/u2f.h b/firmware/inc/u2f.h index 70324ad..3876eae 100644 --- a/firmware/inc/u2f.h +++ b/firmware/inc/u2f.h @@ -38,7 +38,9 @@ #define U2F_APDU_SIZE 7 #define U2F_CHALLENGE_SIZE 32 #define U2F_APPLICATION_SIZE 32 -#define U2F_KEY_HANDLE_SIZE 36 +#define U2F_KEY_HANDLE_ID_SIZE 8 +#define U2F_KEY_HANDLE_KEY_SIZE 36 +#define U2F_KEY_HANDLE_SIZE (U2F_KEY_HANDLE_KEY_SIZE+U2F_KEY_HANDLE_ID_SIZE) #define U2F_REGISTER_REQUEST_SIZE (U2F_CHALLENGE_SIZE+U2F_APPLICATION_SIZE) #define U2F_MAX_REQUEST_PAYLOAD (1 + U2F_CHALLENGE_SIZE+U2F_APPLICATION_SIZE + 1 + U2F_KEY_HANDLE_SIZE) diff --git a/firmware/src/atecc508a.c b/firmware/src/atecc508a.c index 27e66a6..661de8f 100644 --- a/firmware/src/atecc508a.c +++ b/firmware/src/atecc508a.c @@ -87,6 +87,7 @@ int8_t atecc_recv(uint8_t * buf, uint8_t buflen, struct atecc_response* res) if (SMB_FLAGS & SMB_READ_TRUNC) { set_app_error(ERROR_READ_TRUNCATED); + return -1; } if (pkt_len <= buflen && pkt_len >= 4) diff --git a/firmware/src/main.c b/firmware/src/main.c index 3632a2b..3a5015c 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -141,8 +141,6 @@ int16_t main(void) { uint16_t ms_grad; uint8_t winks = 0, light = 1, grad_dir = 0; int8_t grad_inc = 0; - int8_t ii; - uint16_t i; data uint8_t xdata * clear = 0; enter_DefaultMode_from_RESET(); @@ -162,7 +160,7 @@ int16_t main(void) { if (RSTSRC & RSTSRC_WDTRSF__SET) { - error = ERROR_DAMN_WATCHDOG; + //error = ERROR_DAMN_WATCHDOG; } run_tests(); @@ -259,9 +257,9 @@ int16_t main(void) { { u2f_printx("error: ", 1, (uint16_t)error); #ifdef U2F_BLINK_ERRORS - for (ii=0; ii < 8; ii++) + for (ms_grad=0; ms_grad < 8; ms_grad++) { - if (error & (1<kh) == 0 )//&& u2f_appid_eq(req->kh, req->app) == 0) + if (u2f_appid_eq(req->kh, req->app) == 0) { return U2F_SW_CONDITIONS_NOT_SATISFIED; } @@ -155,12 +155,13 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c return U2F_SW_WRONG_DATA; } } - if ( + if ( control != U2F_AUTHENTICATE_SIGN || req->khl != U2F_KEY_HANDLE_SIZE || - u2f_load_key(req->kh, req->app) != 0 //|| - //u2f_appid_eq(req->kh, req->app) != 0 - ) + u2f_appid_eq(req->kh, req->app) != 0 || // Order of checks is important + u2f_load_key(req->kh, req->app) != 0 + + ) { u2f_hid_set_len(2); return U2F_SW_WRONG_PAYLOAD; diff --git a/firmware/src/u2f_atecc.c b/firmware/src/u2f_atecc.c index 584d241..24ef04d 100644 --- a/firmware/src/u2f_atecc.c +++ b/firmware/src/u2f_atecc.c @@ -30,6 +30,8 @@ */ #include "app.h" + +#undef U2F_DISABLE #ifndef U2F_DISABLE #include "bsp.h" #include "u2f.h" @@ -38,6 +40,7 @@ #include "atecc508a.h" +static void gen_u2f_zero_tag(uint8_t * dst, uint8_t * appid); static struct u2f_hid_msg res; static uint8_t* resbuf = (uint8_t*)&res; @@ -152,14 +155,14 @@ static int atecc_prep_encryption() appdata.tmp, 32, appdata.tmp, 40, &res) != 0 ) { - u2f_prints("pass through to tempkey failed\r\n"); +// u2f_prints("pass through to tempkey failed\r\n"); return -1; } if( atecc_send_recv(ATECC_CMD_GENDIG, ATECC_RW_DATA, U2F_MASTER_KEY_SLOT, NULL, 0, appdata.tmp, 40, &res) != 0) { - u2f_prints("GENDIG failed\r\n"); +// u2f_prints("GENDIG failed\r\n"); return -1; } @@ -233,7 +236,6 @@ int8_t u2f_ecdsa_sign(uint8_t * dest, uint8_t * handle, uint8_t * appid) } - // bad if this gets interrupted int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey) { @@ -242,6 +244,8 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey) int i; watchdog(); +// u2f_prints("new key appid,khandle\r\n"); +// dump_hex(appid,32); if (atecc_send_recv(ATECC_CMD_RNG,ATECC_RNG_P1,ATECC_RNG_P2, NULL, 0, @@ -270,7 +274,7 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey) } watchdog(); compute_key_hash(private_key, WMASK); - memmove(handle+4, res_digest.buf, 32); // size of key handle must be 36 + memmove(handle+4, res_digest.buf, 32); // size of key handle must be 36+8 if ( atecc_privwrite(U2F_TEMP_KEY_SLOT, private_key, WMASK, handle+4) != 0) @@ -289,15 +293,21 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * appid, uint8_t * pubkey) memmove(pubkey, res.buf, 64); + // the + 8 + gen_u2f_zero_tag(handle + U2F_KEY_HANDLE_KEY_SIZE, appid); + //dump_hex(handle,U2F_KEY_HANDLE_SIZE); + return 0; } int8_t u2f_load_key(uint8_t * handle, uint8_t * appid) { - struct atecc_response res; uint8_t private_key[36]; int i; +// u2f_prints("load key appid,rnum\r\n"); +// dump_hex(appid,32); +// dump_hex(handle,4); SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT; SHA_FLAGS = ATECC_SHA_HMACSTART; u2f_sha256_start(); @@ -316,30 +326,24 @@ int8_t u2f_load_key(uint8_t * handle, uint8_t * appid) return atecc_privwrite(U2F_TEMP_KEY_SLOT, private_key, WMASK, handle+4); } +static void gen_u2f_zero_tag(uint8_t * dst, uint8_t * appid) +{ + const char * u2f_zero_const = "\xc1\xff\x67\x0d\x66\xe5\x55\xbb\xdc\x56\xaf\x7b\x41\x27\x4a\x21"; + SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT; + SHA_FLAGS = ATECC_SHA_HMACSTART; + u2f_sha256_start(); + u2f_sha256_update(appid,32); + u2f_sha256_update(u2f_zero_const,16); + SHA_FLAGS = ATECC_SHA_HMACEND; + u2f_sha256_finish(); + + if (dst) memmove(dst, res_digest.buf, U2F_KEY_HANDLE_ID_SIZE); +} + int8_t u2f_appid_eq(uint8_t * handle, uint8_t * appid) { -// struct atecc_response res; -// uint8_t private_key[36]; -// int i; -// -// SHA_HMAC_KEY = U2F_MASTER_KEY_SLOT; -// SHA_FLAGS = ATECC_SHA_HMACSTART; -// u2f_sha256_start(); -// u2f_sha256_update(appid,32); -// SHA_FLAGS = ATECC_SHA_HMACEND; -// u2f_sha256_finish(); -// -// memset(private_key,0,4); -// memmove(private_key+4, res_digest.buf, 32); -// -// for (i=4; i<36; i++) -// { -// private_key[i] ^= RMASK[i]; -// } -// -// compute_key_hash(private_key, WMASK); -// return memcmp(handle, res_digest.buf, U2F_KEY_HANDLE_SIZE); - return 0; + gen_u2f_zero_tag(NULL,appid); + return memcmp(handle+U2F_KEY_HANDLE_KEY_SIZE, res_digest.buf, U2F_KEY_HANDLE_ID_SIZE); } uint32_t u2f_count() diff --git a/firmware/src/u2f_hid.c b/firmware/src/u2f_hid.c index 0bac818..e733539 100644 --- a/firmware/src/u2f_hid.c +++ b/firmware/src/u2f_hid.c @@ -77,7 +77,7 @@ static struct hid_layer_param // total length of response in bytes uint16_t res_len; - #define BUFFER_SIZE 270 + #define BUFFER_SIZE (270 - 70) uint8_t buffer[BUFFER_SIZE]; } hid_layer; @@ -87,7 +87,7 @@ uint32_t _hid_lockt = 0; uint32_t _hid_lock_cid = 0; #endif -static struct CID CIDS[5]; +static struct CID CIDS[4]; static uint8_t CID_NUM = 0; @@ -149,7 +149,6 @@ void u2f_hid_writeback(uint8_t * payload, uint16_t len) do { - if (_hid_offset == 0) { r->cid = hid_layer.current_cid; @@ -354,24 +353,19 @@ static uint8_t hid_u2f_parse(struct u2f_hid_msg* req) break; case U2FHID_MSG: - - if (U2FHID_LEN(req) < 4) - { - stamp_error(hid_layer.current_cid, ERR_INVALID_LEN); - goto fail; - } - // buffer 2 payloads (120 bytes) to get full U2F message - // assuming key handle is < 45 bytes - // 7 bytes for apdu header - // 7 + 66 bytes + key handle for authenticate message - // 7 + 64 for register message if (hid_layer.bytes_buffered == 0) { + if (U2FHID_LEN(req) < 4) + { + stamp_error(hid_layer.current_cid, ERR_INVALID_LEN); + goto fail; + } start_buffering(req); if (hid_layer.bytes_buffered >= U2FHID_LEN(req)) { u2f_request((struct u2f_request_apdu *)hid_layer.buffer); } + } else { @@ -380,6 +374,7 @@ static uint8_t hid_u2f_parse(struct u2f_hid_msg* req) { u2f_request((struct u2f_request_apdu *)hid_layer.buffer); } + } diff --git a/tools/flashing/erase.sh b/tools/flashing/erase.sh deleted file mode 100644 index 07e97d9..0000000 --- a/tools/flashing/erase.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -# silabs utility debugger debugger id C2 -FlashUtilCL.exe FLASHEraseUSB "$1" 1 diff --git a/tools/flashing/program.sh b/tools/flashing/program.sh index 4783a6d..4af625a 100644 --- a/tools/flashing/program.sh +++ b/tools/flashing/program.sh @@ -1,4 +1,25 @@ #!/bin/bash -# silabs utility debugger file debugger id power C2 -FlashUtilCL.exe DownloadUSB -R $1 "$2" 0 1 + +ret=$(curl --request POST http://127.0.0.1:4040/ --data "port=$2" --data "firmware=$(cat "$1")") + +if [[ $ret != *"Success"* ]] +then + exit 1 +fi + +exit 0 +#export FW=$2 + +#PORT=$1 python - <