bug fixes and now registration msg works

vtcsec_summit
Conor 2016-03-05 22:03:07 -05:00
rodzic a6e963b336
commit eb39119276
9 zmienionych plików z 159 dodań i 107 usunięć

Wyświetl plik

@ -15,8 +15,8 @@
// application settings
#define U2F_ATTESTATION_KEY_SLOT 15
//#define ATECC_SETUP_DEVICE
#define U2F_ATTESTATION_KEY_SLOT 14
// #define ATECC_SETUP_DEVICE
// efm8ub1 application eeprom memory mappings
#define U2F_KEY_HEADER_ADDR 0xF800
@ -78,7 +78,7 @@ void atecc_setup_device(uint8_t * buf);
#define U2F_DISABLE
#define u2f_init(x)
#define u2f_hid_init(x)
#define u2f_hid_request(x)
#else
#define atecc_setup_device(x)

Wyświetl plik

@ -126,5 +126,8 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * pubkey);
// method to return pointer to attestation cert
uint8_t * u2f_get_attestation_cert();
// method to set the total length of the response for use by underlying layer
// @len the length of U2F response in bytes
void set_response_length(uint16_t len);
#endif /* U2F_H_ */

Wyświetl plik

@ -92,6 +92,11 @@ typedef enum
void u2f_hid_init();
// set the length of the total payload to be sent
// @len length of payload in bytes
void u2f_hid_set_len(uint16_t len);
// u2f_hid_writeback handles the sequencing and per packet buffering
// @payload the buffer to write
// @len length of buffer

Wyświetl plik

@ -140,6 +140,7 @@ int8_t atecc_send_recv(uint8_t cmd, uint8_t p1, uint16_t p2,
if (errors > 5)
{
u2f_printb("fail recv ", 1,appdata.error);
return -1;
}
switch(appdata.error)
{

Wyświetl plik

@ -19,9 +19,15 @@ void u2f_delay(uint16_t ms) {
void usb_write(uint8_t* buf, uint8_t len)
{
int16_t ec;
if (USB_STATUS_OK != (ec=USBD_Write(EP1IN, buf, len, false)))
uint8_t errors;
while (USB_STATUS_OK != (ec=USBD_Write(EP1IN, buf, len, false)))
{
u2f_printd("USB error",1, -ec);
u2f_delay(2);
if (errors++ > 26)
{
u2f_printd("USB error",1, -ec);
break;
}
}
}

Wyświetl plik

@ -57,7 +57,39 @@ void dump_eeprom()
int8_t test_app()
{
// uint8_t i[] = {0x5,U2F_EC_FMT_UNCOMPRESSED};
//
// uint8_t key_handle[U2F_KEY_HANDLE_SIZE];
// uint8_t pubkey[64];
//
// u2f_prints("u2f_register\r\n");
//
// if (u2f_get_user_feedback() != 0)
// {
// u2f_prints("u2f_get_user_feedback fail\r\n");
// return U2F_SW_CONDITIONS_NOT_SATISFIED;
// }
//
// u2f_prints("u2f_new_keypair\r\n");
// if ( u2f_new_keypair(key_handle, pubkey) == -1)
// {
// u2f_prints("u2f_new_keypair fail\r\n");
// return U2F_SW_CONDITIONS_NOT_SATISFIED;
// }
//
// u2f_prints("u2f_sha\r\n");
// u2f_sha256_start();
// u2f_sha256_update(i,1);
// u2f_sha256_update(pubkey,32);
// u2f_sha256_update(pubkey,32);
// u2f_sha256_update(key_handle,U2F_KEY_HANDLE_SIZE);
// u2f_sha256_update(i+1,1);
// u2f_sha256_update(pubkey,64);
// u2f_sha256_finish();
// if (u2f_ecdsa_sign(pubkey, U2F_ATTESTATION_HANDLE) == -1)
// {
// return SW_WRONG_DATA;
// }
return 0;
}
@ -96,14 +128,10 @@ int16_t main(void) {
}
if ( USBD_GetUsbState() == USBD_STATE_CONFIGURED)
if (!USBD_EpIsBusy(EP1OUT) && !USBD_EpIsBusy(EP1IN) && appdata.state != APP_HID_MSG)
{
if (!USBD_EpIsBusy(EP1OUT) && !USBD_EpIsBusy(EP1IN))
{
USBD_Read(EP1OUT, hidmsgbuf, sizeof(hidmsgbuf), true);
u2f_prints("read added\r\n");
}
USBD_Read(EP1OUT, hidmsgbuf, sizeof(hidmsgbuf), true);
u2f_prints("read added\r\n");
}
switch(appdata.state)
@ -112,10 +140,8 @@ int16_t main(void) {
break;
case APP_HID_MSG:
u2f_hid_request(appdata.hid_msg);
if (appdata.state == APP_HID_MSG)
appdata.state = APP_NOTHING;
break;
case APP_WINK:
LED_B = 0;

Wyświetl plik

@ -26,13 +26,11 @@ struct key_storage_header
uint8_t num_issued;
} key_store;
#define U2F_NUM_KEYS 15
#define U2F_NUM_KEYS U2F_ATTESTATION_KEY_SLOT
#define U2F_KEYS_ADDR (0xF800)
#define U2F_KEY_ADDR(k) (U2F_KEYS_ADDR + ((k)*U2F_KEY_HANDLE_SIZE))
#define IS_KEY_VALID(mask,key) ((~mask) & (1<<key))
static struct u2f_hid_msg res;
@ -55,6 +53,7 @@ void u2f_init()
// initialize key handles
if (key_store.num_keys != U2F_NUM_KEYS)
{
u2f_prints("init key handles\r\n");
key_store.num_keys = U2F_NUM_KEYS;
key_store.valid_keys = 0;
key_store.num_issued = 0;
@ -93,7 +92,7 @@ int8_t u2f_get_user_feedback()
return 0;
}
static uint8_t shabuf[64];
static uint8_t shabuf[70];
static uint8_t shaoffset = 0;
static struct atecc_response res_digest;
@ -128,6 +127,8 @@ void u2f_sha256_finish()
atecc_send_recv(ATECC_CMD_SHA,
ATECC_SHA_END, shaoffset,shabuf,shaoffset,
shabuf, sizeof(shabuf), &res_digest);
dump_hex(res_digest.buf, res_digest.len);
}
@ -148,23 +149,25 @@ int8_t u2f_ecdsa_sign(uint8_t * dest, uint8_t * handle)
{
keyslot--;
}
u2f_printx("signing with key ",1,keyslot);
atecc_send_recv(ATECC_CMD_SIGN,
ATECC_SIGN_EXTERNAL, keyslot, NULL, 0,
appdata.tmp, sizeof(appdata.tmp), &res);
eeprom_read(U2F_KEY_ADDR(keyslot), (uint8_t* )&k, U2F_KEY_HANDLE_SIZE);
if (
((struct key_handle *)handle)->index != k.index ||
((struct key_handle *)handle)->entropy[0] != k.entropy[0] ||
((struct key_handle *)handle)->entropy[1] != k.entropy[1] ||
((struct key_handle *)handle)->entropy[2] != k.entropy[2]
)
if (keyslot != U2F_ATTESTATION_KEY_SLOT)
{
return -1;
}
eeprom_read(U2F_KEY_ADDR(keyslot), (uint8_t* )&k, U2F_KEY_HANDLE_SIZE);
if (
((struct key_handle *)handle)->index-1 != k.index ||
((struct key_handle *)handle)->entropy[0] != k.entropy[0] ||
((struct key_handle *)handle)->entropy[1] != k.entropy[1] ||
((struct key_handle *)handle)->entropy[2] != k.entropy[2]
)
{
return -1;
}
}
memmove(dest, res.buf, 64);
@ -182,10 +185,12 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * pubkey)
return -1;
}
u2f_prints("about to gen key\r\n");
atecc_send_recv(ATECC_CMD_GENKEY,
ATECC_GENKEY_PRIVATE, keyslot, NULL, 0,
appdata.tmp, sizeof(appdata.tmp), &res);
u2f_prints("ATECC_CMD_GENKEY\r\n");
memmove(pubkey, res.buf, 64);
eeprom_read(U2F_KEY_ADDR(keyslot), (uint8_t* )&k, U2F_KEY_HANDLE_SIZE);
@ -194,6 +199,7 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * pubkey)
k.index = keyslot;
set_app_error(ERROR_BAD_KEY_STORE);
}
k.index++;
memmove(handle, &k, U2F_KEY_HANDLE_SIZE);
key_store.num_issued++;
flush_key_store();
@ -202,24 +208,24 @@ int8_t u2f_new_keypair(uint8_t * handle, uint8_t * pubkey)
}
code char __attest[] =
"\x30\x82\x01\x59\x30\x82\x01\x00\x02\x01\x01\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d"
"\x04\x03\x02\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14"
"\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43"
"\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63"
"\x6f\x6d\x30\x1e\x17\x0d\x31\x36\x30\x33\x30\x36\x30\x30\x34\x33\x30\x32\x5a\x17"
"\x0d\x32\x32\x30\x33\x30\x35\x30\x30\x34\x33\x30\x32\x5a\x30\x39\x31\x0b\x30\x09"
"\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b"
"\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03"
"\x13\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07\x2a"
"\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04"
"\xd2\x59\x03\x5e\x63\x12\x29\xdc\x52\x10\x92\xdb\x0e\x2d\x12\xa1\xc8\x87\x4d\x17"
"\x8f\x52\x1d\x2c\x14\x35\x72\xa2\xc0\x25\x73\x2e\xba\x82\xe2\xce\x6f\x46\xf7\x33"
"\x97\xde\x8c\xb0\x60\xe5\x2f\x91\x2d\x40\x17\xdf\x89\xc7\x01\xd3\xcd\xdd\x0a\x04"
"\xc6\x60\xc6\xcd\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x47\x00\x30"
"\x44\x02\x20\x34\xa7\xd9\xc5\xd9\xfd\x10\xd3\xe1\xff\x5a\x37\xca\xdc\x85\x5c\xa8"
"\x0e\x3b\xa9\xd5\xb1\xde\xfc\x87\x50\x56\x44\x41\xbf\xdd\x42\x02\x20\x41\x64\x34"
"\x32\x8f\x16\xa0\xbb\x19\x88\x8f\x8c\x0d\x09\x09\x84\x33\x9b\xc5\x0c\xf5\x29\x93"
"\xc3\x50\x3c\x32\x07\x0b\x9f\xca\xc9"
"\x30\x82\x01\x5a\x30\x82\x01\x00\x02\x01\x01\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d"
"\x04\x03\x02\x30\x39\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14"
"\x30\x12\x06\x03\x55\x04\x0a\x13\x0b\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43"
"\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63"
"\x6f\x6d\x30\x1e\x17\x0d\x31\x36\x30\x33\x30\x36\x30\x32\x32\x38\x33\x38\x5a\x17"
"\x0d\x32\x32\x30\x33\x30\x35\x30\x32\x32\x38\x33\x38\x5a\x30\x39\x31\x0b\x30\x09"
"\x06\x03\x55\x04\x06\x13\x02\x56\x41\x31\x14\x30\x12\x06\x03\x55\x04\x0a\x13\x0b"
"\x43\x6f\x6e\x6f\x72\x43\x6f\x20\x4c\x4c\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03"
"\x13\x0b\x75\x32\x66\x7a\x65\x72\x6f\x2e\x63\x6f\x6d\x30\x59\x30\x13\x06\x07\x2a"
"\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04"
"\xe0\xc4\x32\x2c\x33\xdc\x1e\xa3\x60\x10\x0a\x0f\x2a\xb7\xb7\x2c\xbe\x53\x3d\xac"
"\x4e\x9d\x4f\xee\x4a\xf5\x6c\xcd\xe9\xe2\x23\x7f\x9c\x65\x15\x5d\x9f\x25\x19\x72"
"\x87\xd5\x2f\x23\x9a\xb3\x41\xeb\x0c\xb5\xbb\x4b\xae\xc3\x9a\xf3\xe4\xfb\xa7\xd2"
"\x33\x9b\xa2\xa8\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02\x03\x48\x00\x30"
"\x45\x02\x20\x12\xa2\x68\x62\xf4\x4d\x27\x61\xdf\x01\xc8\x74\x15\xba\xa6\x0d\x51"
"\x93\x70\x3c\xcc\x39\xe2\x2d\xfd\x71\x99\x7c\xd3\x26\x18\x2b\x02\x21\x00\xfa\x69"
"\x16\x10\xaa\xc0\xe7\x9b\x73\xea\x2a\xa3\x53\x6a\x13\x04\xcc\xf0\x04\x82\x4c\x3c"
"\xe4\xd4\xc9\x3b\x2e\xaa\x39\x9d\x60\x93"
;
uint8_t * u2f_get_attestation_cert()
@ -233,4 +239,9 @@ uint16_t u2f_attestation_cert_size()
return sizeof(__attest)-1;
}
void set_response_length(uint16_t len)
{
u2f_hid_set_len(len);
}
#endif

Wyświetl plik

@ -1,4 +1,5 @@
#include "app.h"
#include "bsp.h"
#include "u2f.h"
#ifndef U2F_DISABLE
@ -41,16 +42,22 @@ static int16_t u2f_register(struct u2f_register_request * req)
uint8_t key_handle[U2F_KEY_HANDLE_SIZE];
uint8_t pubkey[64];
u2f_prints("u2f_register\r\n");
if (u2f_get_user_feedback() != 0)
{
u2f_prints("u2f_get_user_feedback fail\r\n");
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
u2f_prints("u2f_new_keypair\r\n");
if ( u2f_new_keypair(key_handle, pubkey) == -1)
{
u2f_prints("u2f_new_keypair fail\r\n");
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
u2f_prints("u2f_sha\r\n");
u2f_sha256_start();
u2f_sha256_update(i,1);
u2f_sha256_update(req->app,32);
@ -60,10 +67,14 @@ static int16_t u2f_register(struct u2f_register_request * req)
u2f_sha256_update(pubkey,64);
u2f_sha256_finish();
u2f_prints("u2f_ecdsa_sign\r\n");
if (u2f_ecdsa_sign((uint8_t*)req, U2F_ATTESTATION_HANDLE) == -1)
{
return SW_WRONG_DATA;
}
u2f_prints("u2f_response_writeback\r\n");
u2f_hid_set_len(131 + U2F_KEY_HANDLE_SIZE + u2f_attestation_cert_size());
u2f_response_writeback(i,2);
u2f_response_writeback(pubkey,64);
i[0] = U2F_KEY_HANDLE_SIZE;

Wyświetl plik

@ -36,7 +36,7 @@ static struct hid_layer_param
uint8_t current_cmd;
uint32_t last_buffered;
// uint16_t bytes_buffered;
uint16_t bytes_buffered;
// number of payload bytes written in response
uint16_t bytes_written;
@ -46,7 +46,7 @@ static struct hid_layer_param
// total length of response in bytes
uint16_t res_len;
#define BUFFER_SIZE 300
#define BUFFER_SIZE 150
uint8_t buffer[BUFFER_SIZE];
@ -74,8 +74,15 @@ void u2f_hid_init()
_hid_in_session = 0;
}
void u2f_hid_set_len(uint16_t len)
{
hid_layer.res_len = len;
}
static void u2f_hid_reset_packet()
{
u2f_prints("HID RESET\r\n");
_hid_seq = 0;
_hid_offset = 0;
_hid_in_session = 0;
@ -88,9 +95,7 @@ void u2f_hid_flush()
{
if (_hid_offset)
{
usb_write(_hid_pkt, HID_PACKET_SIZE);
}
u2f_hid_reset_packet();
}
@ -220,46 +225,24 @@ static void stamp_error(uint32_t cid, uint8_t err)
del_cid(cid);
}
//// TODO double check if this is really needed
//static void start_buffering(struct hid_layer_param* hid, struct u2f_hid_msg* req)
//{
// hid->bytes_buffered = U2FHID_INIT_PAYLOAD_SIZE;
// hid->bytes_remain = U2FHID_LEN(req) - U2FHID_INIT_PAYLOAD_SIZE;
// hid->last_buffered = get_ms();
// memmove(hid->buffer, req->pkt.init.payload, U2FHID_INIT_PAYLOAD_SIZE);
//}
//
//static int buffer_request(struct hid_layer_param* hid, struct u2f_hid_msg* req)
//{
// if (hid->bytes_remain < U2FHID_CONT_PAYLOAD_SIZE)
// {
// if (hid->bytes_buffered + hid->bytes_remain > BUFFER_SIZE)
// {
// goto fail;
// }
// memmove(hid->buffer + hid->bytes_buffered, req->pkt.cont.payload, hid->bytes_remain);
// hid->bytes_buffered += hid->bytes_remain;
// hid->bytes_remain = 0;
// hid->state = HID_READY;
// }
// else
// {
// if (hid->bytes_buffered + U2FHID_CONT_PAYLOAD_SIZE > BUFFER_SIZE)
// {
// goto fail;
// }
// memmove(hid->buffer+ hid->bytes_buffered, req->pkt.cont.payload, U2FHID_CONT_PAYLOAD_SIZE);
// hid->bytes_buffered += U2FHID_CONT_PAYLOAD_SIZE;
// hid->bytes_remain -= U2FHID_CONT_PAYLOAD_SIZE;
// }
// hid->last_buffered = get_ms();
// return 0;
//
// fail:
// hid->state = HID_READY;
// u2f_prints("buffer full\r\n");
// return -1;
//}
// TODO double check if this is really needed
static void start_buffering(struct u2f_hid_msg* req)
{
_hid_in_session = 1;
hid_layer.bytes_buffered = U2FHID_INIT_PAYLOAD_SIZE;
memmove(hid_layer.buffer, req->pkt.init.payload, U2FHID_INIT_PAYLOAD_SIZE);
}
static int buffer_request(struct u2f_hid_msg* req)
{
if (hid_layer.bytes_buffered + U2FHID_CONT_PAYLOAD_SIZE > BUFFER_SIZE)
{
u2f_prints("buffer full\r\n");
return -1;
}
memmove(hid_layer.buffer + hid_layer.bytes_buffered, req->pkt.cont.payload, U2FHID_CONT_PAYLOAD_SIZE);
hid_layer.bytes_buffered += U2FHID_CONT_PAYLOAD_SIZE;
}
static void hid_u2f_parse(struct u2f_hid_msg* req)
{
@ -278,7 +261,7 @@ static void hid_u2f_parse(struct u2f_hid_msg* req)
u2f_prints("invalid len init\r\n");
goto fail;
}
hid_layer.res_len = 17;
u2f_hid_set_len(17);
u2f_printlx("cid: ",1,hid_layer.current_cid);
if (hid_layer.current_cid == 0)
@ -310,8 +293,24 @@ static void hid_u2f_parse(struct u2f_hid_msg* req)
u2f_prints("invalid len msg\r\n");
goto fail;
}
u2f_prints("U2FHID_MSG\r\n");
// 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)
{
start_buffering(req);
u2f_prints("buffer start\r\n");
}
else
{
u2f_prints("buffer end\r\n");
buffer_request(req);
u2f_request((struct u2f_request_apdu *)hid_layer.buffer);
}
u2f_request((struct u2f_request_apdu *)req->pkt.init.payload);
break;
case U2FHID_PING:
@ -320,8 +319,7 @@ static void hid_u2f_parse(struct u2f_hid_msg* req)
if (!u2f_hid_busy())
{
hid_layer.res_len = U2FHID_LEN(req);
u2f_hid_set_len(U2FHID_LEN(req));
u2f_hid_writeback(req->pkt.init.payload, MIN(hid_layer.res_len, U2FHID_INIT_PAYLOAD_SIZE));
}
else
@ -329,7 +327,6 @@ static void hid_u2f_parse(struct u2f_hid_msg* req)
u2f_hid_writeback(req->pkt.cont.payload, MIN(hid_layer.res_len - hid_layer.bytes_written, U2FHID_CONT_PAYLOAD_SIZE));
}
// u2f_printd("reslen byteswritten ",2, hid_layer.res_len,hid_layer.bytes_written);
if (hid_layer.res_len == hid_layer.bytes_written) u2f_hid_flush();
break;
@ -341,7 +338,7 @@ static void hid_u2f_parse(struct u2f_hid_msg* req)
stamp_error(hid_layer.current_cid, ERR_INVALID_LEN);
u2f_prints("invalid len wink but who cares\r\n");
}
hid_layer.res_len = 0;
u2f_hid_set_len(0);
u2f_hid_writeback(NULL, 0);
u2f_hid_flush();
appdata.state = APP_WINK;
@ -423,15 +420,7 @@ void u2f_hid_request(struct u2f_hid_msg* req)
u2f_prints("this should resync but im lazy\r\n");
}
hid_layer.last_buffered = get_ms();
// // TODO verify packets arrive in ascending order
// if (buffer_request(&hid_layer, req) != 0)
// {
// // no suitable error code so ignore
// u2f_prints("cant buffer request\r\n");
// return;
// }
// u2f_printlx("buffered from ", 1, req->cid);
// payload = hid_layer.buffer;
// TODO verify packets arrive in ascending order
}
else if (U2FHID_TIMEOUT(&hid_layer))