Skip to content

Commit

Permalink
u2f: replace U2F header with newer ones
Browse files Browse the repository at this point in the history
Fix U2F constants, add more checks.
  • Loading branch information
prusnak committed Dec 17, 2018
1 parent 6d6e5a1 commit 0b26c52
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 206 deletions.
18 changes: 14 additions & 4 deletions firmware/u2f.c
Expand Up @@ -42,7 +42,7 @@


// About 1/2 Second according to values used in protect.c // About 1/2 Second according to values used in protect.c
#define U2F_TIMEOUT (800000/2) #define U2F_TIMEOUT (800000/2)
#define U2F_OUT_PKT_BUFFER_LEN 128 #define U2F_OUT_PKT_BUFFER_LEN 130


// Initialise without a cid // Initialise without a cid
static uint32_t cid = 0; static uint32_t cid = 0;
Expand Down Expand Up @@ -100,8 +100,13 @@ uint32_t next_cid(void)
return cid; return cid;
} }


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


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


Expand All @@ -295,7 +300,7 @@ void u2fhid_init(const U2FHID_FRAME *in)
f.cid = in->cid; f.cid = in->cid;
f.init.cmd = U2FHID_INIT; f.init.cmd = U2FHID_INIT;
f.init.bcnth = 0; f.init.bcnth = 0;
f.init.bcntl = U2FHID_INIT_RESP_SIZE; f.init.bcntl = sizeof(resp);


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


void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len) void send_u2fhid_msg(const uint8_t cmd, const uint8_t *data, const uint32_t len)
{ {
if (len > U2F_MAXIMUM_PAYLOAD_LENGTH) {
debugLog(0, "", "send_u2fhid_msg failed");
return;
}

U2FHID_FRAME f; U2FHID_FRAME f;
uint8_t *p = (uint8_t *)data; uint8_t *p = (uint8_t *)data;
uint32_t l = len; uint32_t l = len;
Expand Down
176 changes: 73 additions & 103 deletions firmware/u2f/u2f.h
@@ -1,143 +1,113 @@
/* /**
Copyright (C) 2013-2015 Yubico AB * Copyright FIDO Alliance, 2017
*
This program is free software; you can redistribute it and/or modify it * Licensed under CC-BY:
under the terms of the GNU Lesser General Public License as published by * https://creativecommons.org/licenses/by/4.0/legalcode
the Free Software Foundation; either version 2.1, or (at your option) any *
later version. * Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com
*/
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/

// Common U2F raw message format header.
// 2014-08-14 J Ehrensvard, Yubico, Inc.


#ifndef __U2F_H_INCLUDED__ #ifndef __U2F_H_INCLUDED__
#define __U2F_H_INCLUDED__ #define __U2F_H_INCLUDED__


#ifdef _MSC_VER // Windows #ifdef _MSC_VER // Windows
typedef unsigned char uint8_t; typedef unsigned char uint8_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;
typedef unsigned int uint32_t; typedef unsigned int uint32_t;
typedef unsigned long int uint64_t; typedef unsigned long int uint64_t;
#else #else
#include <stdint.h> #include <stdint.h>
#endif #endif


#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif


// General constants // General constants


#define U2F_EC_KEY_SIZE 32 // EC key size in bytes #define U2F_EC_KEY_SIZE 32 // EC key size in bytes
#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point #define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
#define U2F_MAX_KH_SIZE 128 // Max size of key handle #define U2F_MAX_KH_SIZE 128 // Max size of key handle
#define U2F_MAX_ATT_CERT_SIZE 1024 // Max size of attestation certificate #define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate
#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature #define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature
#define U2F_CTR_SIZE 4 // Size of counter field #define U2F_CTR_SIZE 4 // Size of counter field
#define U2F_APPID_SIZE 32 // Size of application id #define U2F_APPID_SIZE 32 // Size of application id
#define U2F_CHAL_SIZE 32 // Size of challenge #define U2F_CHAL_SIZE 32 // Size of challenge


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


// EC (uncompressed) point // EC (uncompressed) point


#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format #define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format


typedef struct typedef struct __attribute__((packed)) {
{ uint8_t pointFormat; // Point type
uint8_t pointFormat; // Point type uint8_t x[U2F_EC_KEY_SIZE]; // X-value
uint8_t x[U2F_EC_KEY_SIZE]; // X-value uint8_t y[U2F_EC_KEY_SIZE]; // Y-value
uint8_t y[U2F_EC_KEY_SIZE]; // Y-value } U2F_EC_POINT;
} U2F_EC_POINT;


// U2F native commands // U2F native commands


#define U2F_REGISTER 0x01 // Registration command #define U2F_REGISTER 0x01 // Registration command
#define U2F_AUTHENTICATE 0x02 // Authenticate/sign command #define U2F_AUTHENTICATE 0x02 // Authenticate/sign command
#define U2F_VERSION 0x03 // Read version string command #define U2F_VERSION 0x03 // Read version string command


#define U2F_VENDOR_FIRST 0x40 // First vendor defined command #define U2F_VENDOR_FIRST 0x40 // First vendor defined command
#define U2F_VENDOR_LAST 0x7f // Last vendor defined command #define U2F_VENDOR_LAST 0xbf // Last vendor defined command


// U2F_CMD_REGISTER command defines // U2F_CMD_REGISTER command defines


#define U2F_REGISTER_ID 0x05 // Version 2 registration identifier #define U2F_REGISTER_ID 0x05 // Version 2 registration identifier
#define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier #define U2F_REGISTER_HASH_ID 0x00 // Version 2 hash identintifier


typedef struct typedef struct __attribute__((packed)) {
{ uint8_t chal[U2F_CHAL_SIZE]; // Challenge
uint8_t chal[U2F_CHAL_SIZE]; // Challenge uint8_t appId[U2F_APPID_SIZE]; // Application id
uint8_t appId[U2F_APPID_SIZE]; // Application id } U2F_REGISTER_REQ;
} U2F_REGISTER_REQ;

typedef struct __attribute__((packed)) {
typedef struct uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2)
{ U2F_EC_POINT pubKey; // Generated public key
uint8_t registerId; // Registration identifier (U2F_REGISTER_ID_V2) uint8_t keyHandleLen; // Length of key handle
U2F_EC_POINT pubKey; // Generated public key uint8_t keyHandleCertSig[
uint8_t keyHandleLen; // Length of key handle U2F_MAX_KH_SIZE + // Key handle
uint8_t keyHandleCertSig[U2F_MAX_KH_SIZE + // Key handle U2F_MAX_ATT_CERT_SIZE + // Attestation certificate
U2F_MAX_ATT_CERT_SIZE + // Attestation certificate U2F_MAX_EC_SIG_SIZE]; // Registration signature
U2F_MAX_EC_SIG_SIZE]; // Registration signature } U2F_REGISTER_RESP;
} U2F_REGISTER_RESP;


// U2F_CMD_AUTHENTICATE command defines // U2F_CMD_AUTHENTICATE command defines


// Authentication control byte // Authentication control byte


#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign #define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign
#define U2F_AUTH_CHECK_ONLY 0x07 // Check only #define U2F_AUTH_CHECK_ONLY 0x07 // Check only
#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set #define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set


typedef struct typedef struct __attribute__((packed)) {
{ uint8_t chal[U2F_CHAL_SIZE]; // Challenge
uint8_t chal[U2F_CHAL_SIZE]; // Challenge uint8_t appId[U2F_APPID_SIZE]; // Application id
uint8_t appId[U2F_APPID_SIZE]; // Application id uint8_t keyHandleLen; // Length of key handle
uint8_t keyHandleLen; // Length of key handle uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle
uint8_t keyHandle[U2F_MAX_KH_SIZE]; // Key handle } U2F_AUTHENTICATE_REQ;
} U2F_AUTHENTICATE_REQ;

typedef struct __attribute__((packed)) {
typedef struct uint8_t flags; // U2F_AUTH_FLAG_ values
{ uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian)
uint8_t flags; // U2F_AUTH_FLAG_ values uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature
uint8_t ctr[U2F_CTR_SIZE]; // Counter field (big-endian) } U2F_AUTHENTICATE_RESP;
uint8_t sig[U2F_MAX_EC_SIG_SIZE]; // Signature
} U2F_AUTHENTICATE_RESP;

// Common raw message format (ISO7816-4:2005 mapping)

typedef struct
{
uint8_t cla; // Class - reserved
uint8_t ins; // U2F instruction
uint8_t p1; // U2F parameter 1
uint8_t p2; // U2F parameter 2
uint8_t lc1; // Length field, set to zero
uint8_t lc2; // Length field, MSB
uint8_t lc3; // Length field, LSB
uint8_t data[1]; // Data field
} U2F_MSG;


// Command status responses // Command status responses


#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR #define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR
#define U2F_SW_WRONG_LENGTH 0x6700 // SW_WRONG_LENGTH #define U2F_SW_WRONG_LENGTH 0x6700 // SW_WRONG_LENGTH
#define U2F_SW_DATA_INVALID 0x6984 // SW_WRONG_DATA #define U2F_SW_WRONG_DATA 0x6A80 // SW_WRONG_DATA
#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED #define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED
#define U2F_SW_WRONG_DATA 0x6a80 // SW_WRONG_DATA #define U2F_SW_COMMAND_NOT_ALLOWED 0x6986 // SW_COMMAND_NOT_ALLOWED
#define U2F_SW_INS_NOT_SUPPORTED 0x6d00 // SW_INS_NOT_SUPPORTED #define U2F_SW_INS_NOT_SUPPORTED 0x6D00 // SW_INS_NOT_SUPPORTED
#define U2F_SW_CLA_NOT_SUPPORTED 0x6e00 // SW_CLA_NOT_SUPPORTED #define U2F_SW_CLA_NOT_SUPPORTED 0x6E00 // SW_CLA_NOT_SUPPORTED


#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif


#endif // __U2F_H_INCLUDED__ #endif // __U2F_H_INCLUDED__

0 comments on commit 0b26c52

Please sign in to comment.