Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix 1kB ping crash #83

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Copyright (c) 2016, Conor Patrick, Google LLC
Copyright (c) 2018, Nitrokey UG
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
10 changes: 10 additions & 0 deletions firmware/inc/u2f_hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ struct u2f_hid_init_response
uint8_t cflags;
};

struct CID
{
uint32_t cid;
uint32_t last_used;
uint8_t busy;
uint8_t last_cmd;
};

typedef enum
{
U2FHID_REPLY=0,
Expand Down Expand Up @@ -137,6 +145,8 @@ void u2f_hid_flush();
// @param req the U2F HID message
void u2f_hid_request(struct u2f_hid_msg* req);

struct CID* get_cid(uint32_t cid);

// app_wink blink a light on the platform
// must be implemented elsewhere for specific platform used
// @color optional hex color
Expand Down
22 changes: 15 additions & 7 deletions firmware/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,19 +209,27 @@ int16_t main(void) {
rgb(0,light--,0);
}
break;
case APP_HID_MSG:
// HID msg received, pass to protocols
if (custom_command(hid_msg))
{

}
else
{
case APP_HID_MSG: { // HID msg received, pass to protocols:
#ifndef ATECC_SETUP_DEVICE
struct CID* cid = NULL;
cid = get_cid(hid_msg->cid);
if (!cid->busy) { // There is no ongoing U2FHID transfer
if (!custom_command(hid_msg)) {
u2f_hid_request(hid_msg);
}
} else {
u2f_hid_request(hid_msg);
}
#else
if (!custom_command(hid_msg)) {
u2f_hid_request(hid_msg);
}
#endif

if (state == APP_HID_MSG)
state = APP_NOTHING;
}
break;
#ifdef U2F_SUPPORT_WINK
case APP_WINK:
Expand Down
10 changes: 1 addition & 9 deletions firmware/src/u2f_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@ typedef enum
HID_READY,
} HID_STATE;

struct CID
{
uint32_t cid;
uint32_t last_used;
uint8_t busy;
uint8_t last_cmd;
};

static struct hid_layer_param
{
HID_STATE state;
Expand Down Expand Up @@ -232,7 +224,7 @@ static int8_t add_new_cid(uint32_t cid)
return -1;
}

static struct CID* get_cid(uint32_t cid)
struct CID* get_cid(uint32_t cid)
{
uint8_t i;
for(i = 0; i < CID_MAX; i++)
Expand Down
99 changes: 97 additions & 2 deletions tools/u2f_zero_client/client.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python
#
# Copyright (c) 2016, Conor Patrick
# Copyright (c) 2018, Nitrokey UG
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -52,8 +53,8 @@
sys.exit(1)



cmd_prefix = [0, 0xff,0xff,0xff,0xff]
cid_broadcast = [0xFF, 0xFF, 0xFF, 0xFF]
cmd_prefix = [0] + cid_broadcast

class commands:
U2F_CONFIG_GET_SERIAL_NUM = 0x80
Expand All @@ -71,6 +72,9 @@ class commands:
U2F_CUSTOM_SEED = 0x22
U2F_CUSTOM_WIPE = 0x23
U2F_CUSTOM_WINK = 0x24

U2F_HID_INIT = 0x86
U2F_HID_PING = 0x81


if len(sys.argv) not in [2,3,4,5,6]:
Expand Down Expand Up @@ -322,6 +326,94 @@ def do_wink(h):
cmd = cmd_prefix + [ commands.U2F_CUSTOM_WINK, 0,0]
h.write(cmd)

def u2fhid_init(h):
nonce = [random.randint(0, 0xFF) for i in xrange(0, 8)]
cmd = cid_broadcast + [commands.U2F_HID_INIT, 0, 8] + nonce
h.write([0] + cmd)
ans = h.read(19, 1000)
return ans[15:19]

def get_response_packet_payload(cmd_seq): # Reads an U2FHID packet, checks it's command/sequence field by the given parameter, returns the payload
ans = h.read(64, 200)
if len(ans) == 0: # Read timeout
return[]
else: # Read success
print('pkt recvd(%i):' % ans[4])
print(" ".join('%03d'%x for x in ans))
if ans[4] == cmd_seq: # Error check: OK
if cmd_seq >= 128: # Initialization packet
return ans[7:] # Payload
else: # Sequence packet
return ans[5:] # Payload
die('ERR: cmd/seq field in received packet is %i instead of %i' % (ans[4], cmd_seq)) # Error check: ERR (1st byte of payload is the error code in case of a command packet)


def do_ping(h, num):
# Init (set U2F HID channel address)
cid = u2fhid_init(h)

# Prepare ping data
dlen = int(num)
data = [random.randint(1, 0xFF) for i in xrange(0, dlen)] # Ping data: random bytes, except 0
data_req = data

# Send initialization packet of request message
cmd = cid + [ commands.U2F_HID_PING, int((dlen & 0xFF00) >> 8), int(dlen & 0x00FF)] + data[0:57] # Send ping command
h.write([0] + cmd)
print('init. pkt sent(%i):' % cmd[4])
print(" ".join('%03d'%x for x in cmd))

# Request/Response transfer in case of one packet composed message
data_resp = []
if dlen < 58: # Message fits into one packet, no continuation packets will be sent
data_resp = get_response_packet_payload(commands.U2F_HID_PING)

# Request/Response transfer in case of a multiple packet composed message
else: # Message doesnt fit into one packet
seq_tx = 0
seq_rx = commands.U2F_HID_PING
data = data[57:]
resp_dlen = 0
while len(data) > 0: # Send remaining data of request message in continuation packets
cmd = cid + [seq_tx] + data[:64 - 5]
h.write([0] + cmd)
data = data[64 - 5:]
print('cont. pkt sent(%i):' % seq_tx)
print(" ".join('%03d'%x for x in cmd))
seq_tx += 1

ans = get_response_packet_payload(seq_rx) # Collect response message packets in the meantime to avoid input buffer ovf
if len(ans):
if seq_rx == commands.U2F_HID_PING:
seq_rx = 0
else:
seq_rx += 1
data_resp += ans
print('Collecting remaining data...')
while True: # Collect remaining response message packets after the total request message has been sent
ans = get_response_packet_payload(seq_rx)
if len(ans):
if seq_rx == commands.U2F_HID_PING:
seq_rx = 0
else:
seq_rx += 1
data_resp += ans
else:
break;
resp_dlen = len(data_resp)

# Adjust ping data: remove padding zeros from the end
for i in reversed(range(resp_dlen)):
if data_resp[i] == 0:
data_resp.pop(i)
else:
break

# Check ping data (compare sent/received message payloads)
if cmp(data_req, data_resp) == 0:
print('Ping OK')
else:
print('Ping ERR')



Expand Down Expand Up @@ -362,6 +454,9 @@ def do_wink(h):
elif action == 'bootloader-destroy':
h = open_u2f(SN)
bootloader_destroy(h)
elif action == 'ping':
h = open_u2f(SN)
do_ping(h, sys.argv[2])
else:
print( 'error: invalid action: ', action)
sys.exit(1)
Expand Down