Merge pull request #121 from solokeys/nfc

Nfc
This commit is contained in:
Conor Patrick
2019-03-01 21:43:12 -05:00
committed by GitHub
29 changed files with 4191 additions and 300 deletions

30
fido2/apdu.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef _APDU_H_
#define _APDU_H_
#include <stdint.h>
typedef struct
{
uint8_t cla;
uint8_t ins;
uint8_t p1;
uint8_t p2;
uint8_t lc;
} __attribute__((packed)) APDU_HEADER;
#define APDU_FIDO_U2F_REGISTER 0x01
#define APDU_FIDO_U2F_AUTHENTICATE 0x02
#define APDU_FIDO_U2F_VERSION 0x03
#define APDU_FIDO_NFCCTAP_MSG 0x10
#define APDU_INS_SELECT 0xA4
#define APDU_INS_READ_BINARY 0xB0
#define SW_SUCCESS 0x9000
#define SW_GET_RESPONSE 0x6100 // Command successfully executed; 'XX' bytes of data are available and can be requested using GET RESPONSE.
#define SW_WRONG_LENGTH 0x6700
#define SW_COND_USE_NOT_SATISFIED 0x6985
#define SW_FILE_NOT_FOUND 0x6a82
#define SW_INS_INVALID 0x6d00 // Instruction code not supported or invalid
#define SW_INTERNAL_EXCEPTION 0x6f00
#endif //_APDU_H_

View File

@@ -336,7 +336,12 @@ static int ctap_make_auth_data(struct rpId * rp, CborEncoder * map, uint8_t * au
count = auth_data_update_count(&authData->head);
device_set_status(CTAPHID_STATUS_UPNEEDED);
int but = ctap_user_presence_test();
// if NFC - not need to click a button
int but = 1;
if(!device_is_nfc())
{
but = ctap_user_presence_test();
}
if (!but)
{
@@ -1586,7 +1591,10 @@ void ctap_init()
exit(1);
}
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
if (! device_is_nfc())
{
crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV);
}
#ifdef BRIDGE_TO_WALLET
wallet_init();

View File

@@ -86,5 +86,22 @@ void boot_st_bootloader();
// HID wink command
void device_wink();
typedef enum {
DEVICE_LOW_POWER_IDLE = 0,
DEVICE_LOW_POWER_FAST = 1,
DEVICE_FAST = 2,
} DEVICE_CLOCK_RATE;
// Set the clock rate for the device.
// Three modes are targetted for Solo.
// 0: Lowest clock rate for NFC.
// 1: fastest clock rate supported at a low power setting for NFC FIDO.
// 2: fastest clock rate. Generally for USB interface.
void device_set_clock_rate(DEVICE_CLOCK_RATE param);
// Returns 1 if operating in NFC mode.
// 0 otherwise.
bool device_is_nfc();
#endif

View File

@@ -91,10 +91,10 @@ int16_t extend_fido2(CredentialId * credid, uint8_t * output)
}
}
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len)
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len)
{
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) req->payload;
struct u2f_authenticate_request * auth = (struct u2f_authenticate_request *) payload;
uint16_t rcode;
if (req->ins == U2F_AUTHENTICATE)

View File

@@ -7,8 +7,9 @@
#ifndef EXTENSIONS_H_
#define EXTENSIONS_H_
#include "u2f.h"
#include "apdu.h"
int16_t extend_u2f(struct u2f_request_apdu* req, uint32_t len);
int16_t extend_u2f(APDU_HEADER * req, uint8_t * payload, uint32_t len);
int16_t extend_fido2(CredentialId * credid, uint8_t * output);

View File

@@ -48,6 +48,8 @@ struct logtag tagtable[] = {
{TAG_STOR,"STOR"},
{TAG_BOOT,"BOOT"},
{TAG_EXT,"EXT"},
{TAG_NFC,"NFC"},
{TAG_NFC_APDU, "NAPDU"},
};
@@ -68,7 +70,7 @@ void LOG(uint32_t tag, const char * filename, int num, const char * fmt, ...)
{
if (tag & tagtable[i].tagn)
{
if (tagtable[i].tag[0]) printf("[%s] ", tagtable[i].tag);
if (tagtable[i].tag[0] && !(tag & TAG_NO_TAG)) printf("[%s] ", tagtable[i].tag);
i = 0;
break;
}

View File

@@ -23,27 +23,30 @@ void set_logging_tag(uint32_t tag);
typedef enum
{
TAG_GEN = (1 << 0),
TAG_MC = (1 << 1),
TAG_GA = (1 << 2),
TAG_CP = (1 << 3),
TAG_ERR = (1 << 4),
TAG_PARSE= (1 << 5),
TAG_CTAP = (1 << 6),
TAG_U2F = (1 << 7),
TAG_DUMP = (1 << 8),
TAG_GREEN = (1 << 9),
TAG_RED= (1 << 10),
TAG_TIME= (1 << 11),
TAG_HID = (1 << 12),
TAG_USB = (1 << 13),
TAG_WALLET = (1 << 14),
TAG_STOR = (1 << 15),
TAG_DUMP2 = (1 << 16),
TAG_BOOT = (1 << 17),
TAG_EXT = (1 << 18),
TAG_GEN = (1 << 0),
TAG_MC = (1 << 1),
TAG_GA = (1 << 2),
TAG_CP = (1 << 3),
TAG_ERR = (1 << 4),
TAG_PARSE = (1 << 5),
TAG_CTAP = (1 << 6),
TAG_U2F = (1 << 7),
TAG_DUMP = (1 << 8),
TAG_GREEN = (1 << 9),
TAG_RED = (1 << 10),
TAG_TIME = (1 << 11),
TAG_HID = (1 << 12),
TAG_USB = (1 << 13),
TAG_WALLET = (1 << 14),
TAG_STOR = (1 << 15),
TAG_DUMP2 = (1 << 16),
TAG_BOOT = (1 << 17),
TAG_EXT = (1 << 18),
TAG_NFC = (1 << 19),
TAG_NFC_APDU = (1 << 20),
TAG_FILENO = (1u << 31)
TAG_NO_TAG = (1UL << 30),
TAG_FILENO = (1UL << 31)
} LOG_TAG;
#if DEBUG_LEVEL > 0

View File

@@ -25,40 +25,33 @@ int main()
uint32_t t1 = 0;
set_logging_mask(
/*0*/
// TAG_GEN|
// TAG_MC |
// TAG_GA |
TAG_WALLET |
TAG_STOR |
// TAG_CP |
// TAG_CTAP|
// TAG_HID|
/*TAG_U2F|*/
// TAG_PARSE |
// TAG_TIME|
// TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
/*0*/
//TAG_GEN|
//TAG_MC |
//TAG_GA |
//TAG_WALLET |
TAG_STOR |
//TAG_NFC_APDU |
TAG_NFC |
//TAG_CP |
//TAG_CTAP|
//TAG_HID|
//TAG_U2F|
//TAG_PARSE |
//TAG_TIME|
//TAG_DUMP|
TAG_GREEN|
TAG_RED|
TAG_ERR
);
device_init();
printf1(TAG_GEN,"init device\n");
usbhid_init();
printf1(TAG_GEN,"init usb\n");
ctaphid_init();
printf1(TAG_GEN,"init ctaphid\n");
ctap_init();
printf1(TAG_GEN,"init ctap\n");
memset(hidmsg,0,sizeof(hidmsg));
printf1(TAG_GEN,"recv'ing hid msg \n");
// printf1(TAG_GEN,"recv'ing hid msg \n");
while(1)
@@ -80,6 +73,7 @@ int main()
{
}
ctaphid_check_timeouts();
}
// Should never get here

View File

@@ -10,6 +10,7 @@
#include "crypto.h"
#include "log.h"
#include "device.h"
#include "apdu.h"
#include "wallet.h"
#ifdef ENABLE_U2F_EXTENSIONS
#include "extensions.h"
@@ -27,12 +28,12 @@ void u2f_reset_response();
static CTAP_RESPONSE * _u2f_resp = NULL;
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
void u2f_request_ex(APDU_HEADER *req, uint8_t *payload, uint32_t len, CTAP_RESPONSE * resp)
{
uint16_t rcode = 0;
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
uint8_t byte;
ctap_response_init(resp);
u2f_set_writeback_buffer(resp);
if (req->cla != 0)
@@ -42,7 +43,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
goto end;
}
#ifdef ENABLE_U2F_EXTENSIONS
rcode = extend_u2f(req, len);
rcode = extend_u2f(req, payload, len);
#endif
if (rcode != U2F_SW_NO_ERROR && rcode != U2F_SW_CONDITIONS_NOT_SATISFIED) // If the extension didn't do anything...
{
@@ -59,7 +60,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{
timestamp();
rcode = u2f_register((struct u2f_register_request*)req->payload);
rcode = u2f_register((struct u2f_register_request*)payload);
printf1(TAG_TIME,"u2f_register time: %d ms\n", timestamp());
}
@@ -67,7 +68,7 @@ void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
case U2F_AUTHENTICATE:
printf1(TAG_U2F, "U2F_AUTHENTICATE\n");
timestamp();
rcode = u2f_authenticate((struct u2f_authenticate_request*)req->payload, req->p1);
rcode = u2f_authenticate((struct u2f_authenticate_request*)payload, req->p1);
printf1(TAG_TIME,"u2f_authenticate time: %d ms\n", timestamp());
break;
case U2F_VERSION:
@@ -109,6 +110,22 @@ end:
printf1(TAG_U2F,"u2f resp: "); dump_hex1(TAG_U2F, _u2f_resp->data, _u2f_resp->length);
}
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp)
{
if (len < 5 || !req)
return;
uint32_t alen = req[4];
u2f_request_ex((APDU_HEADER *)req, &req[5], alen, resp);
}
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp)
{
uint32_t len = ((req->LC3) | ((uint32_t)req->LC2 << 8) | ((uint32_t)req->LC1 << 16));
u2f_request_ex((APDU_HEADER *)req, req->payload, len, resp);
}
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len)
{
@@ -156,7 +173,7 @@ static void u2f_make_auth_tag(struct u2f_key_handle * kh, uint8_t * appid, uint8
memmove(tag, hashbuf, CREDENTIAL_TAG_SIZE);
}
static int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey)
int8_t u2f_new_keypair(struct u2f_key_handle * kh, uint8_t * appid, uint8_t * pubkey)
{
ctap_generate_rng(kh->key, U2F_KEY_HANDLE_KEY_SIZE);
u2f_make_auth_tag(kh, appid, kh->tag);
@@ -203,12 +220,12 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
}
else
{
return U2F_SW_WRONG_DATA;
return U2F_SW_WRONG_PAYLOAD;
}
}
if (
control != U2F_AUTHENTICATE_SIGN ||
req->khl != U2F_KEY_HANDLE_SIZE ||
(control != U2F_AUTHENTICATE_SIGN && control != U2F_AUTHENTICATE_SIGN_NO_USER) ||
req->khl != U2F_KEY_HANDLE_SIZE ||
u2f_appid_eq(&req->kh, req->app) != 0 || // Order of checks is important
u2f_load_key(&req->kh, req->app) != 0
@@ -217,12 +234,17 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
return U2F_SW_WRONG_DATA;
}
// dont-enforce-user-presence-and-sign
if (control == U2F_AUTHENTICATE_SIGN_NO_USER)
up = 0;
if (ctap_user_presence_test() == 0)
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
if(!device_is_nfc() && up)
{
if (ctap_user_presence_test() == 0)
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
}
count = ctap_atomic_count(0);
hash[0] = (count >> 24) & 0xff;
@@ -231,14 +253,14 @@ static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t c
hash[3] = (count >> 0) & 0xff;
crypto_sha256_init();
crypto_sha256_update(req->app,32);
crypto_sha256_update(&up,1);
crypto_sha256_update(hash,4);
crypto_sha256_update(req->chal,32);
crypto_sha256_update(req->app, 32);
crypto_sha256_update(&up, 1);
crypto_sha256_update(hash, 4);
crypto_sha256_update(req->chal, 32);
crypto_sha256_final(hash);
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F,hash,32);
printf1(TAG_U2F, "sha256: "); dump_hex1(TAG_U2F, hash, 32);
crypto_ecc256_sign(hash, 32, sig);
u2f_response_writeback(&up,1);
@@ -264,10 +286,13 @@ static int16_t u2f_register(struct u2f_register_request * req)
const uint16_t attest_size = attestation_cert_der_size;
if ( ! ctap_user_presence_test())
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
if(!device_is_nfc())
{
if ( ! ctap_user_presence_test())
{
return U2F_SW_CONDITIONS_NOT_SATISFIED;
}
}
if ( u2f_new_keypair(&key_handle, req->app, pubkey) == -1)
{

View File

@@ -38,6 +38,7 @@
// U2F Authenticate
#define U2F_AUTHENTICATE_CHECK 0x7
#define U2F_AUTHENTICATE_SIGN 0x3
#define U2F_AUTHENTICATE_SIGN_NO_USER 0x8
// Command status responses
@@ -94,9 +95,14 @@ struct u2f_authenticate_request
};
// u2f_request send a U2F message to U2F protocol
// @req U2F message
// @req U2F message
void u2f_request(struct u2f_request_apdu* req, CTAP_RESPONSE * resp);
// u2f_request send a U2F message to NFC protocol
// @req data with iso7816 apdu message
// @len data length
void u2f_request_nfc(uint8_t * req, int len, CTAP_RESPONSE * resp);
int8_t u2f_response_writeback(const uint8_t * buf, uint16_t len);
void u2f_reset_response();