Skip to content

Commit 0b26c52

Browse files
committed
u2f: replace U2F header with newer ones
Fix U2F constants, add more checks.
1 parent 6d6e5a1 commit 0b26c52

3 files changed

Lines changed: 176 additions & 206 deletions

File tree

firmware/u2f.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
// About 1/2 Second according to values used in protect.c
4444
#define U2F_TIMEOUT (800000/2)
45-
#define U2F_OUT_PKT_BUFFER_LEN 128
45+
#define U2F_OUT_PKT_BUFFER_LEN 130
4646

4747
// Initialise without a cid
4848
static uint32_t cid = 0;
@@ -100,8 +100,13 @@ uint32_t next_cid(void)
100100
return cid;
101101
}
102102

103+
// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-hid-protocol-v1.2-ps-20170411.html#message--and-packet-structure
104+
// states the following:
105+
// With a packet size of 64 bytes (max for full-speed devices), this means that
106+
// the maximum message payload length is 64 - 7 + 128 * (64 - 5) = 7609 bytes.
107+
#define U2F_MAXIMUM_PAYLOAD_LENGTH 7609
103108
typedef struct {
104-
uint8_t buf[57+127*59];
109+
uint8_t buf[U2F_MAXIMUM_PAYLOAD_LENGTH];
105110
uint8_t *buf_ptr;
106111
uint32_t len;
107112
uint8_t seq;
@@ -282,7 +287,7 @@ void u2fhid_init(const U2FHID_FRAME *in)
282287
{
283288
const U2FHID_INIT_REQ *init_req = (const U2FHID_INIT_REQ *)&in->init.data;
284289
U2FHID_FRAME f;
285-
U2FHID_INIT_RESP resp;
290+
U2FHID_INIT_RESP resp = {0};
286291

287292
debugLog(0, "", "u2fhid_init");
288293

@@ -295,7 +300,7 @@ void u2fhid_init(const U2FHID_FRAME *in)
295300
f.cid = in->cid;
296301
f.init.cmd = U2FHID_INIT;
297302
f.init.bcnth = 0;
298-
f.init.bcntl = U2FHID_INIT_RESP_SIZE;
303+
f.init.bcntl = sizeof(resp);
299304

300305
memcpy(resp.nonce, init_req->nonce, sizeof(init_req->nonce));
301306
resp.cid = in->cid == CID_BROADCAST ? next_cid() : in->cid;
@@ -363,6 +368,11 @@ void u2fhid_msg(const APDU *a, uint32_t len)
363368

364369
void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len)
365370
{
371+
if (len > U2F_MAXIMUM_PAYLOAD_LENGTH) {
372+
debugLog(0, "", "send_u2fhid_msg failed");
373+
return;
374+
}
375+
366376
U2FHID_FRAME f;
367377
uint8_t *p = (uint8_t *)data;
368378
uint32_t l = len;

firmware/u2f/u2f.h

Lines changed: 73 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,113 @@
1-
/*
2-
Copyright (C) 2013-2015 Yubico AB
3-
4-
This program is free software; you can redistribute it and/or modify it
5-
under the terms of the GNU Lesser General Public License as published by
6-
the Free Software Foundation; either version 2.1, or (at your option) any
7-
later version.
8-
9-
This program is distributed in the hope that it will be useful, but
10-
WITHOUT ANY WARRANTY; without even the implied warranty of
11-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
12-
General Public License for more details.
13-
14-
You should have received a copy of the GNU Lesser General Public License
15-
along with this program; if not, see <http://www.gnu.org/licenses/>.
16-
*/
17-
18-
// Common U2F raw message format header.
19-
// 2014-08-14 J Ehrensvard, Yubico, Inc.
1+
/**
2+
* Copyright FIDO Alliance, 2017
3+
*
4+
* Licensed under CC-BY:
5+
* https://creativecommons.org/licenses/by/4.0/legalcode
6+
*
7+
* Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com
8+
*/
209

2110
#ifndef __U2F_H_INCLUDED__
2211
#define __U2F_H_INCLUDED__
2312

24-
#ifdef _MSC_VER // Windows
25-
typedef unsigned char uint8_t;
26-
typedef unsigned short uint16_t;
27-
typedef unsigned int uint32_t;
13+
#ifdef _MSC_VER // Windows
14+
typedef unsigned char uint8_t;
15+
typedef unsigned short uint16_t;
16+
typedef unsigned int uint32_t;
2817
typedef unsigned long int uint64_t;
2918
#else
3019
#include <stdint.h>
3120
#endif
3221

3322
#ifdef __cplusplus
34-
extern "C"
35-
{
23+
extern "C" {
3624
#endif
3725

3826
// General constants
3927

40-
#define U2F_EC_KEY_SIZE 32 // EC key size in bytes
41-
#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
42-
#define U2F_MAX_KH_SIZE 128 // Max size of key handle
43-
#define U2F_MAX_ATT_CERT_SIZE 1024 // Max size of attestation certificate
44-
#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature
45-
#define U2F_CTR_SIZE 4 // Size of counter field
46-
#define U2F_APPID_SIZE 32 // Size of application id
47-
#define U2F_CHAL_SIZE 32 // Size of challenge
28+
#define U2F_EC_KEY_SIZE 32 // EC key size in bytes
29+
#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
30+
#define U2F_MAX_KH_SIZE 128 // Max size of key handle
31+
#define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate
32+
#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature
33+
#define U2F_CTR_SIZE 4 // Size of counter field
34+
#define U2F_APPID_SIZE 32 // Size of application id
35+
#define U2F_CHAL_SIZE 32 // Size of challenge
4836

4937
#define ENC_SIZE(x) ((x + 7) & 0xfff8)
5038

5139
// EC (uncompressed) point
5240

53-
#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format
41+
#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format
5442

55-
typedef struct
56-
{
57-
uint8_t pointFormat; // Point type
58-
uint8_t x[U2F_EC_KEY_SIZE]; // X-value
59-
uint8_t y[U2F_EC_KEY_SIZE]; // Y-value
60-
} U2F_EC_POINT;
43+
typedef struct __attribute__((packed)) {
44+
uint8_t pointFormat; // Point type
45+
uint8_t x[U2F_EC_KEY_SIZE]; // X-value
46+
uint8_t y[U2F_EC_KEY_SIZE]; // Y-value
47+
} U2F_EC_POINT;
6148

6249
// U2F native commands
6350

64-
#define U2F_REGISTER 0x01 // Registration command
65-
#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command
66-
#define U2F_VERSION 0x03 // Read version string command
51+
#define U2F_REGISTER 0x01 // Registration command
52+
#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command
53+
#define U2F_VERSION 0x03 // Read version string command
6754

68-
#define U2F_VENDOR_FIRST 0x40 // First vendor defined command
69-
#define U2F_VENDOR_LAST 0x7f // Last vendor defined command
55+
#define U2F_VENDOR_FIRST 0x40 // First vendor defined command
56+
#define U2F_VENDOR_LAST 0xbf // Last vendor defined command
7057

7158
// U2F_CMD_REGISTER command defines
7259

73-
#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier
74-
#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier
75-
76-
typedef struct
77-
{
78-
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
79-
uint8_t appId[U2F_APPID_SIZE]; // Application id
80-
} U2F_REGISTER_REQ;
81-
82-
typedef struct
83-
{
84-
uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2)
85-
U2F_EC_POINT pubKey; // Generated public key
86-
uint8_t keyHandleLen; // Length of key handle
87-
uint8_t keyHandleCertSig[U2F_MAX_KH_SIZE + // Key handle
88-
U2F_MAX_ATT_CERT_SIZE + // Attestation certificate
89-
U2F_MAX_EC_SIG_SIZE]; // Registration signature
90-
} U2F_REGISTER_RESP;
60+
#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier
61+
#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier
62+
63+
typedef struct __attribute__((packed)) {
64+
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
65+
uint8_t appId[U2F_APPID_SIZE]; // Application id
66+
} U2F_REGISTER_REQ;
67+
68+
typedef struct __attribute__((packed)) {
69+
uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2)
70+
U2F_EC_POINT pubKey; // Generated public key
71+
uint8_t keyHandleLen; // Length of key handle
72+
uint8_t keyHandleCertSig[
73+
U2F_MAX_KH_SIZE + // Key handle
74+
U2F_MAX_ATT_CERT_SIZE + // Attestation certificate
75+
U2F_MAX_EC_SIG_SIZE]; // Registration signature
76+
} U2F_REGISTER_RESP;
9177

9278
// U2F_CMD_AUTHENTICATE command defines
9379

9480
// Authentication control byte
9581

96-
#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign
97-
#define U2F_AUTH_CHECK_ONLY 0x07 // Check only
98-
#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set
99-
100-
typedef struct
101-
{
102-
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
103-
uint8_t appId[U2F_APPID_SIZE]; // Application id
104-
uint8_t keyHandleLen; // Length of key handle
105-
uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle
106-
} U2F_AUTHENTICATE_REQ;
107-
108-
typedef struct
109-
{
110-
uint8_t flags; // U2F_AUTH_FLAG_ values
111-
uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian)
112-
uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature
113-
} U2F_AUTHENTICATE_RESP;
114-
115-
// Common raw message format (ISO7816-4:2005 mapping)
116-
117-
typedef struct
118-
{
119-
uint8_t cla; // Class - reserved
120-
uint8_t ins; // U2F instruction
121-
uint8_t p1; // U2F parameter 1
122-
uint8_t p2; // U2F parameter 2
123-
uint8_t lc1; // Length field, set to zero
124-
uint8_t lc2; // Length field, MSB
125-
uint8_t lc3; // Length field, LSB
126-
uint8_t data[1]; // Data field
127-
} U2F_MSG;
82+
#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign
83+
#define U2F_AUTH_CHECK_ONLY 0x07 // Check only
84+
#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set
85+
86+
typedef struct __attribute__((packed)) {
87+
uint8_t chal[U2F_CHAL_SIZE]; // Challenge
88+
uint8_t appId[U2F_APPID_SIZE]; // Application id
89+
uint8_t keyHandleLen; // Length of key handle
90+
uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle
91+
} U2F_AUTHENTICATE_REQ;
92+
93+
typedef struct __attribute__((packed)) {
94+
uint8_t flags; // U2F_AUTH_FLAG_ values
95+
uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian)
96+
uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature
97+
} U2F_AUTHENTICATE_RESP;
12898

12999
// Command status responses
130100

131-
#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR
132-
#define U2F_SW_WRONG_LENGTH 0x6700 // SW_WRONG_LENGTH
133-
#define U2F_SW_DATA_INVALID 0x6984 // SW_WRONG_DATA
134-
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED
135-
#define U2F_SW_WRONG_DATA 0x6a80 // SW_WRONG_DATA
136-
#define U2F_SW_INS_NOT_SUPPORTED 0x6d00 // SW_INS_NOT_SUPPORTED
137-
#define U2F_SW_CLA_NOT_SUPPORTED 0x6e00 // SW_CLA_NOT_SUPPORTED
101+
#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR
102+
#define U2F_SW_WRONG_LENGTH 0x6700 // SW_WRONG_LENGTH
103+
#define U2F_SW_WRONG_DATA 0x6A80 // SW_WRONG_DATA
104+
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED
105+
#define U2F_SW_COMMAND_NOT_ALLOWED 0x6986 // SW_COMMAND_NOT_ALLOWED
106+
#define U2F_SW_INS_NOT_SUPPORTED 0x6D00 // SW_INS_NOT_SUPPORTED
107+
#define U2F_SW_CLA_NOT_SUPPORTED 0x6E00 // SW_CLA_NOT_SUPPORTED
138108

139109
#ifdef __cplusplus
140110
}
141111
#endif
142112

143-
#endif // __U2F_H_INCLUDED__
113+
#endif // __U2F_H_INCLUDED__

0 commit comments

Comments
 (0)