2019-02-12 22:18:17 +00:00
|
|
|
// Copyright 2019 SoloKeys Developers
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
|
|
|
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
|
|
|
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
|
|
|
// copied, modified, or distributed except according to those terms.
|
2018-04-29 01:40:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2018-05-01 03:27:26 +00:00
|
|
|
#include <string.h>
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-06-02 18:44:12 +00:00
|
|
|
#include "device.h"
|
2018-04-29 01:40:13 +00:00
|
|
|
#include "ctaphid.h"
|
2018-05-03 02:52:41 +00:00
|
|
|
#include "ctap.h"
|
2018-05-26 16:51:56 +00:00
|
|
|
#include "u2f.h"
|
2018-04-29 01:40:13 +00:00
|
|
|
#include "time.h"
|
2018-05-01 03:27:26 +00:00
|
|
|
#include "util.h"
|
2018-06-03 04:50:46 +00:00
|
|
|
#include "log.h"
|
2018-12-04 05:15:58 +00:00
|
|
|
#include "extensions.h"
|
2019-09-16 09:00:13 +00:00
|
|
|
#include "version.h"
|
2019-02-25 01:41:58 +00:00
|
|
|
|
2019-02-26 18:31:14 +00:00
|
|
|
// move custom SHA512 command out,
|
2019-02-25 01:41:58 +00:00
|
|
|
// and the following headers too
|
|
|
|
#include "sha2.h"
|
|
|
|
#include "crypto.h"
|
|
|
|
|
2018-12-01 19:42:49 +00:00
|
|
|
#include APP_CONFIG
|
2018-04-29 01:40:13 +00:00
|
|
|
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
IDLE = 0,
|
|
|
|
HANDLING_REQUEST,
|
|
|
|
} CTAP_STATE;
|
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
EMPTY = 0,
|
|
|
|
BUFFERING,
|
|
|
|
BUFFERED,
|
2018-10-28 20:30:55 +00:00
|
|
|
HID_ERROR,
|
|
|
|
HID_IGNORE,
|
2018-05-01 03:27:26 +00:00
|
|
|
} CTAP_BUFFER_STATE;
|
|
|
|
|
2018-05-07 04:00:06 +00:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
uint8_t cmd;
|
|
|
|
uint32_t cid;
|
|
|
|
uint16_t bcnt;
|
|
|
|
int offset;
|
|
|
|
int bytes_written;
|
|
|
|
uint8_t seq;
|
|
|
|
uint8_t buf[HID_MESSAGE_SIZE];
|
|
|
|
} CTAPHID_WRITE_BUFFER;
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
struct CID
|
|
|
|
{
|
|
|
|
uint32_t cid;
|
|
|
|
uint64_t last_used;
|
|
|
|
uint8_t busy;
|
|
|
|
uint8_t last_cmd;
|
|
|
|
};
|
|
|
|
|
2018-05-07 04:00:06 +00:00
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
#define SUCESS 0
|
|
|
|
#define SEQUENCE_ERROR 1
|
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
static int state;
|
2018-05-28 18:14:59 +00:00
|
|
|
static struct CID CIDS[10];
|
|
|
|
#define CID_MAX (sizeof(CIDS)/sizeof(struct CID))
|
2018-05-01 03:35:56 +00:00
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
static uint64_t active_cid_timestamp;
|
2018-05-01 03:35:56 +00:00
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
static uint8_t ctap_buffer[CTAPHID_BUFFER_SIZE];
|
2018-05-28 19:38:30 +00:00
|
|
|
static uint32_t ctap_buffer_cid;
|
2018-05-01 03:27:26 +00:00
|
|
|
static int ctap_buffer_cmd;
|
2018-05-02 02:22:52 +00:00
|
|
|
static uint16_t ctap_buffer_bcnt;
|
2018-05-01 03:27:26 +00:00
|
|
|
static int ctap_buffer_offset;
|
|
|
|
static int ctap_packet_seq;
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-05-04 01:27:29 +00:00
|
|
|
static void buffer_reset();
|
|
|
|
|
2018-05-07 04:00:06 +00:00
|
|
|
#define CTAPHID_WRITE_INIT 0x01
|
|
|
|
#define CTAPHID_WRITE_FLUSH 0x02
|
|
|
|
#define CTAPHID_WRITE_RESET 0x04
|
|
|
|
|
|
|
|
#define ctaphid_write_buffer_init(x) memset(x,0,sizeof(CTAPHID_WRITE_BUFFER))
|
|
|
|
static void ctaphid_write(CTAPHID_WRITE_BUFFER * wb, void * _data, int len);
|
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
void ctaphid_init()
|
|
|
|
{
|
|
|
|
state = IDLE;
|
2018-05-04 01:27:29 +00:00
|
|
|
buffer_reset();
|
2018-11-13 06:45:59 +00:00
|
|
|
//ctap_reset_state();
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
static uint32_t get_new_cid()
|
2018-05-01 03:35:56 +00:00
|
|
|
{
|
2018-05-28 18:14:59 +00:00
|
|
|
static uint32_t cid = 1;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
cid++;
|
|
|
|
}while(cid == 0 || cid == 0xffffffff);
|
|
|
|
return cid;
|
2018-05-01 03:35:56 +00:00
|
|
|
}
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
static int8_t add_cid(uint32_t cid)
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
2019-01-06 16:41:56 +00:00
|
|
|
uint32_t i;
|
2018-05-28 18:14:59 +00:00
|
|
|
for(i = 0; i < CID_MAX-1; i++)
|
|
|
|
{
|
|
|
|
if (!CIDS[i].busy)
|
|
|
|
{
|
|
|
|
CIDS[i].cid = cid;
|
|
|
|
CIDS[i].busy = 1;
|
|
|
|
CIDS[i].last_used = millis();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2018-05-01 03:35:56 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
static int8_t cid_exists(uint32_t cid)
|
|
|
|
{
|
2019-01-06 16:41:56 +00:00
|
|
|
uint32_t i;
|
2018-05-28 18:14:59 +00:00
|
|
|
for(i = 0; i < CID_MAX-1; i++)
|
2018-05-01 03:35:56 +00:00
|
|
|
{
|
2018-05-28 18:14:59 +00:00
|
|
|
if (CIDS[i].cid == cid)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
2018-05-01 03:35:56 +00:00
|
|
|
}
|
2018-05-28 18:14:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-01 03:35:56 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
static int8_t cid_refresh(uint32_t cid)
|
|
|
|
{
|
2019-01-06 16:41:56 +00:00
|
|
|
uint32_t i;
|
2018-05-28 18:14:59 +00:00
|
|
|
for(i = 0; i < CID_MAX-1; i++)
|
|
|
|
{
|
|
|
|
if (CIDS[i].cid == cid)
|
|
|
|
{
|
|
|
|
CIDS[i].last_used = millis();
|
2018-05-29 04:16:26 +00:00
|
|
|
CIDS[i].busy = 1;
|
2018-05-28 18:14:59 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
|
|
|
|
2018-05-28 20:04:06 +00:00
|
|
|
static int8_t cid_del(uint32_t cid)
|
|
|
|
{
|
2019-01-06 16:41:56 +00:00
|
|
|
uint32_t i;
|
2018-05-28 20:04:06 +00:00
|
|
|
for(i = 0; i < CID_MAX-1; i++)
|
|
|
|
{
|
|
|
|
if (CIDS[i].cid == cid)
|
|
|
|
{
|
|
|
|
CIDS[i].busy = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
static int is_broadcast(CTAPHID_PACKET * pkt)
|
|
|
|
{
|
|
|
|
return (pkt->cid == CTAPHID_BROADCAST_CID);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int is_init_pkt(CTAPHID_PACKET * pkt)
|
|
|
|
{
|
2018-05-26 21:41:13 +00:00
|
|
|
return (pkt->pkt.init.cmd == CTAPHID_INIT);
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
static int is_cont_pkt(CTAPHID_PACKET * pkt)
|
|
|
|
{
|
2018-05-13 03:22:23 +00:00
|
|
|
return !(pkt->pkt.init.cmd & TYPE_INIT);
|
2018-05-01 03:27:26 +00:00
|
|
|
}
|
|
|
|
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
static int buffer_packet(CTAPHID_PACKET * pkt)
|
|
|
|
{
|
|
|
|
if (pkt->pkt.init.cmd & TYPE_INIT)
|
|
|
|
{
|
|
|
|
ctap_buffer_bcnt = ctaphid_packet_len(pkt);
|
|
|
|
int pkt_len = (ctap_buffer_bcnt < CTAPHID_INIT_PAYLOAD_SIZE) ? ctap_buffer_bcnt : CTAPHID_INIT_PAYLOAD_SIZE;
|
|
|
|
ctap_buffer_cmd = pkt->pkt.init.cmd;
|
2018-05-28 19:38:30 +00:00
|
|
|
ctap_buffer_cid = pkt->cid;
|
2018-05-01 03:27:26 +00:00
|
|
|
ctap_buffer_offset = pkt_len;
|
|
|
|
ctap_packet_seq = -1;
|
|
|
|
memmove(ctap_buffer, pkt->pkt.init.payload, pkt_len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int leftover = ctap_buffer_bcnt - ctap_buffer_offset;
|
|
|
|
int diff = leftover - CTAPHID_CONT_PAYLOAD_SIZE;
|
|
|
|
ctap_packet_seq++;
|
|
|
|
if (ctap_packet_seq != pkt->pkt.cont.seq)
|
|
|
|
{
|
|
|
|
return SEQUENCE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (diff <= 0)
|
|
|
|
{
|
|
|
|
// only move the leftover amount
|
|
|
|
memmove(ctap_buffer + ctap_buffer_offset, pkt->pkt.cont.payload, leftover);
|
|
|
|
ctap_buffer_offset += leftover;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memmove(ctap_buffer + ctap_buffer_offset, pkt->pkt.cont.payload, CTAPHID_CONT_PAYLOAD_SIZE);
|
|
|
|
ctap_buffer_offset += CTAPHID_CONT_PAYLOAD_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SUCESS;
|
|
|
|
}
|
|
|
|
|
2018-05-04 01:27:29 +00:00
|
|
|
static void buffer_reset()
|
|
|
|
{
|
|
|
|
ctap_buffer_bcnt = 0;
|
|
|
|
ctap_buffer_offset = 0;
|
|
|
|
ctap_packet_seq = 0;
|
2018-05-28 19:38:30 +00:00
|
|
|
ctap_buffer_cid = 0;
|
2018-05-04 01:27:29 +00:00
|
|
|
}
|
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
static int buffer_status()
|
|
|
|
{
|
|
|
|
if (ctap_buffer_bcnt == 0)
|
|
|
|
{
|
|
|
|
return EMPTY;
|
|
|
|
}
|
|
|
|
else if (ctap_buffer_offset == ctap_buffer_bcnt)
|
|
|
|
{
|
|
|
|
return BUFFERED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return BUFFERING;
|
|
|
|
}
|
|
|
|
}
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
static int buffer_cmd()
|
|
|
|
{
|
|
|
|
return ctap_buffer_cmd;
|
|
|
|
}
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-05-28 19:38:30 +00:00
|
|
|
static uint32_t buffer_cid()
|
|
|
|
{
|
|
|
|
return ctap_buffer_cid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-02 02:22:52 +00:00
|
|
|
static int buffer_len()
|
|
|
|
{
|
|
|
|
return ctap_buffer_bcnt;
|
|
|
|
}
|
|
|
|
|
2018-05-07 04:00:06 +00:00
|
|
|
// Buffer data and send in HID_MESSAGE_SIZE chunks
|
|
|
|
// if len == 0, FLUSH
|
|
|
|
static void ctaphid_write(CTAPHID_WRITE_BUFFER * wb, void * _data, int len)
|
|
|
|
{
|
|
|
|
uint8_t * data = (uint8_t *)_data;
|
2018-05-12 16:23:14 +00:00
|
|
|
if (_data == NULL)
|
2018-05-07 04:00:06 +00:00
|
|
|
{
|
|
|
|
if (wb->offset == 0 && wb->bytes_written == 0)
|
|
|
|
{
|
|
|
|
memmove(wb->buf, &wb->cid, 4);
|
|
|
|
wb->offset += 4;
|
|
|
|
|
|
|
|
wb->buf[4] = wb->cmd;
|
|
|
|
wb->buf[5] = (wb->bcnt & 0xff00) >> 8;
|
|
|
|
wb->buf[6] = (wb->bcnt & 0xff) >> 0;
|
|
|
|
wb->offset += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wb->offset > 0)
|
|
|
|
{
|
|
|
|
memset(wb->buf + wb->offset, 0, HID_MESSAGE_SIZE - wb->offset);
|
2019-11-19 20:22:48 +00:00
|
|
|
usbhid_send(wb->buf);
|
2018-05-07 04:00:06 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
if (wb->offset == 0 )
|
|
|
|
{
|
|
|
|
memmove(wb->buf, &wb->cid, 4);
|
|
|
|
wb->offset += 4;
|
|
|
|
|
|
|
|
if (wb->bytes_written == 0)
|
|
|
|
{
|
|
|
|
wb->buf[4] = wb->cmd;
|
|
|
|
wb->buf[5] = (wb->bcnt & 0xff00) >> 8;
|
|
|
|
wb->buf[6] = (wb->bcnt & 0xff) >> 0;
|
|
|
|
wb->offset += 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wb->buf[4] = wb->seq++;
|
|
|
|
wb->offset += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wb->buf[wb->offset++] = data[i];
|
|
|
|
wb->bytes_written += 1;
|
|
|
|
if (wb->offset == HID_MESSAGE_SIZE)
|
|
|
|
{
|
2019-11-19 20:22:48 +00:00
|
|
|
usbhid_send(wb->buf);
|
2018-05-07 04:00:06 +00:00
|
|
|
wb->offset = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-02 02:22:52 +00:00
|
|
|
|
|
|
|
static void ctaphid_send_error(uint32_t cid, uint8_t error)
|
|
|
|
{
|
2018-05-07 04:00:06 +00:00
|
|
|
CTAPHID_WRITE_BUFFER wb;
|
|
|
|
ctaphid_write_buffer_init(&wb);
|
|
|
|
|
|
|
|
wb.cid = cid;
|
|
|
|
wb.cmd = CTAPHID_ERROR;
|
|
|
|
wb.bcnt = 1;
|
|
|
|
|
|
|
|
ctaphid_write(&wb, &error, 1);
|
|
|
|
ctaphid_write(&wb, NULL, 0);
|
2018-05-02 02:22:52 +00:00
|
|
|
}
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
static void send_init_response(uint32_t oldcid, uint32_t newcid, uint8_t * nonce)
|
|
|
|
{
|
|
|
|
CTAPHID_INIT_RESPONSE init_resp;
|
|
|
|
CTAPHID_WRITE_BUFFER wb;
|
|
|
|
ctaphid_write_buffer_init(&wb);
|
|
|
|
wb.cid = oldcid;
|
|
|
|
wb.cmd = CTAPHID_INIT;
|
|
|
|
wb.bcnt = 17;
|
|
|
|
|
|
|
|
memmove(init_resp.nonce, nonce, 8);
|
|
|
|
init_resp.cid = newcid;
|
2018-10-28 20:30:55 +00:00
|
|
|
init_resp.protocol_version = CTAPHID_PROTOCOL_VERSION;
|
2018-05-28 18:14:59 +00:00
|
|
|
init_resp.version_major = 0;//?
|
|
|
|
init_resp.version_minor = 0;//?
|
|
|
|
init_resp.build_version = 0;//?
|
|
|
|
init_resp.capabilities = CTAP_CAPABILITIES;
|
|
|
|
|
|
|
|
ctaphid_write(&wb,&init_resp,sizeof(CTAPHID_INIT_RESPONSE));
|
|
|
|
ctaphid_write(&wb,NULL,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-02 18:44:12 +00:00
|
|
|
void ctaphid_check_timeouts()
|
2018-05-28 18:14:59 +00:00
|
|
|
{
|
|
|
|
uint8_t i;
|
|
|
|
for(i = 0; i < CID_MAX; i++)
|
|
|
|
{
|
|
|
|
if (CIDS[i].busy && ((millis() - CIDS[i].last_used) >= 750))
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf1(TAG_HID, "TIMEOUT CID: %08x\n", CIDS[i].cid);
|
2018-05-28 18:14:59 +00:00
|
|
|
ctaphid_send_error(CIDS[i].cid, CTAP1_ERR_TIMEOUT);
|
2018-10-30 05:50:46 +00:00
|
|
|
CIDS[i].busy = 0;
|
|
|
|
if (CIDS[i].cid == buffer_cid())
|
|
|
|
{
|
|
|
|
buffer_reset();
|
|
|
|
}
|
|
|
|
// memset(CIDS + i, 0, sizeof(struct CID));
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
void ctaphid_update_status(int8_t status)
|
|
|
|
{
|
|
|
|
CTAPHID_WRITE_BUFFER wb;
|
|
|
|
printf1(TAG_HID, "Send device update %d!\n",status);
|
|
|
|
ctaphid_write_buffer_init(&wb);
|
|
|
|
|
|
|
|
wb.cid = buffer_cid();
|
|
|
|
wb.cmd = CTAPHID_KEEPALIVE;
|
|
|
|
wb.bcnt = 1;
|
|
|
|
|
|
|
|
ctaphid_write(&wb, &status, 1);
|
|
|
|
ctaphid_write(&wb, NULL, 0);
|
|
|
|
}
|
2018-05-28 18:14:59 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
static int ctaphid_buffer_packet(uint8_t * pkt_raw, uint8_t * cmd, uint32_t * cid, int * len)
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
|
|
|
CTAPHID_PACKET * pkt = (CTAPHID_PACKET *)(pkt_raw);
|
|
|
|
|
2018-06-03 04:50:46 +00:00
|
|
|
printf1(TAG_HID, "Recv packet\n");
|
|
|
|
printf1(TAG_HID, " CID: %08x \n", pkt->cid);
|
|
|
|
printf1(TAG_HID, " cmd: %02x\n", pkt->pkt.init.cmd);
|
2019-01-06 16:41:56 +00:00
|
|
|
if (!is_cont_pkt(pkt)) {printf1(TAG_HID, " length: %d\n", ctaphid_packet_len(pkt));}
|
2018-04-29 01:40:13 +00:00
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
int ret;
|
2018-05-04 01:27:29 +00:00
|
|
|
uint32_t oldcid;
|
2018-05-28 18:14:59 +00:00
|
|
|
uint32_t newcid;
|
2018-05-03 02:52:41 +00:00
|
|
|
|
2018-05-01 03:27:26 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
*cid = pkt->cid;
|
2018-05-01 03:27:26 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
if (is_init_pkt(pkt))
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
2018-05-28 18:14:59 +00:00
|
|
|
if (ctaphid_packet_len(pkt) != 8)
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR, "Error,invalid length field for init packet\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_LENGTH;
|
|
|
|
return HID_ERROR;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
if (pkt->cid == 0)
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"Error, invalid cid 0\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_CHANNEL;
|
|
|
|
return HID_ERROR;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ctaphid_init();
|
|
|
|
if (is_broadcast(pkt))
|
|
|
|
{
|
|
|
|
// Check if any existing cids are busy first ?
|
2018-06-03 04:50:46 +00:00
|
|
|
printf1(TAG_HID,"adding a new cid\n");
|
2018-05-28 18:14:59 +00:00
|
|
|
oldcid = CTAPHID_BROADCAST_CID;
|
|
|
|
newcid = get_new_cid();
|
|
|
|
ret = add_cid(newcid);
|
|
|
|
// handle init here
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf1(TAG_HID, "synchronizing to cid\n");
|
2018-05-28 18:14:59 +00:00
|
|
|
oldcid = pkt->cid;
|
|
|
|
newcid = pkt->cid;
|
|
|
|
if (cid_exists(newcid))
|
|
|
|
ret = cid_refresh(newcid);
|
2018-04-29 01:40:13 +00:00
|
|
|
else
|
2018-05-28 18:14:59 +00:00
|
|
|
ret = add_cid(newcid);
|
|
|
|
}
|
|
|
|
if (ret == -1)
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR, "Error, not enough memory for new CID. return BUSY.\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_CHANNEL_BUSY;
|
|
|
|
return HID_ERROR;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
send_init_response(oldcid, newcid, pkt->pkt.init.payload);
|
2018-06-02 18:44:12 +00:00
|
|
|
cid_del(newcid);
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
return HID_IGNORE;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-05-28 19:38:30 +00:00
|
|
|
if (pkt->cid == CTAPHID_BROADCAST_CID)
|
|
|
|
{
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_CHANNEL;
|
|
|
|
return HID_ERROR;
|
2018-05-28 19:38:30 +00:00
|
|
|
}
|
2018-10-30 05:50:46 +00:00
|
|
|
|
|
|
|
if (! cid_exists(pkt->cid) && ! is_cont_pkt(pkt))
|
|
|
|
{
|
|
|
|
if (buffer_status() == EMPTY)
|
|
|
|
{
|
|
|
|
add_cid(pkt->cid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
if (cid_exists(pkt->cid))
|
|
|
|
{
|
2018-05-28 19:38:30 +00:00
|
|
|
if (buffer_status() == BUFFERING)
|
|
|
|
{
|
|
|
|
if (pkt->cid == buffer_cid() && ! is_cont_pkt(pkt))
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"INVALID_SEQ\n");
|
|
|
|
printf2(TAG_ERR,"Have %d/%d bytes\n", ctap_buffer_offset, ctap_buffer_bcnt);
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_SEQ;
|
|
|
|
return HID_ERROR;
|
2018-05-28 19:38:30 +00:00
|
|
|
}
|
|
|
|
else if (pkt->cid != buffer_cid())
|
|
|
|
{
|
2018-10-30 05:50:46 +00:00
|
|
|
if (! is_cont_pkt(pkt))
|
|
|
|
{
|
|
|
|
printf2(TAG_ERR,"BUSY with %08x\n", buffer_cid());
|
|
|
|
*cmd = CTAP1_ERR_CHANNEL_BUSY;
|
|
|
|
return HID_ERROR;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid);
|
|
|
|
return HID_IGNORE;
|
|
|
|
}
|
2018-05-28 19:38:30 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-28 18:14:59 +00:00
|
|
|
if (! is_cont_pkt(pkt))
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
2018-05-28 19:38:30 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
if (ctaphid_packet_len(pkt) > CTAPHID_BUFFER_SIZE)
|
2018-05-01 03:27:26 +00:00
|
|
|
{
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_LENGTH;
|
|
|
|
return HID_ERROR;
|
2018-05-01 03:27:26 +00:00
|
|
|
}
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
2018-05-28 19:38:30 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (buffer_status() == EMPTY || pkt->cid != buffer_cid())
|
|
|
|
{
|
2018-10-30 05:50:46 +00:00
|
|
|
printf2(TAG_ERR,"ignoring random cont packet from %04x\n",pkt->cid);
|
2018-10-28 20:30:55 +00:00
|
|
|
return HID_IGNORE;
|
2018-05-28 19:38:30 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-30 05:50:46 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
if (buffer_packet(pkt) == SEQUENCE_ERROR)
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"Buffering sequence error\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_INVALID_SEQ;
|
|
|
|
return HID_ERROR;
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
2018-05-28 18:14:59 +00:00
|
|
|
ret = cid_refresh(pkt->cid);
|
|
|
|
if (ret != 0)
|
2018-04-29 01:40:13 +00:00
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"Error, refresh cid failed\n");
|
2018-05-28 18:14:59 +00:00
|
|
|
exit(1);
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
else if (is_cont_pkt(pkt))
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"ignoring unwarranted cont packet\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
|
2018-05-28 18:14:59 +00:00
|
|
|
// Ignore
|
2018-10-28 20:30:55 +00:00
|
|
|
return HID_IGNORE;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-06-03 04:50:46 +00:00
|
|
|
printf2(TAG_ERR,"BUSY\n");
|
2018-10-28 20:30:55 +00:00
|
|
|
*cmd = CTAP1_ERR_CHANNEL_BUSY;
|
|
|
|
return HID_ERROR;
|
2018-05-28 18:14:59 +00:00
|
|
|
}
|
2018-04-29 01:40:13 +00:00
|
|
|
}
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
*len = buffer_len();
|
|
|
|
*cmd = buffer_cmd();
|
|
|
|
return buffer_status();
|
|
|
|
}
|
2018-05-01 03:27:26 +00:00
|
|
|
|
2019-02-27 01:58:56 +00:00
|
|
|
extern void _check_ret(CborError ret, int line, const char * filename);
|
|
|
|
#define check_hardcore(r) _check_ret(r,__LINE__, __FILE__);\
|
|
|
|
if ((r) != CborNoError) exit(1);
|
|
|
|
|
2019-10-08 15:34:58 +00:00
|
|
|
|
2019-10-08 16:09:20 +00:00
|
|
|
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb);
|
2019-10-08 15:34:58 +00:00
|
|
|
|
2020-02-13 21:58:53 +00:00
|
|
|
|
|
|
|
extern void solo_lock_if_not_already();
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
uint8_t ctaphid_handle_packet(uint8_t * pkt_raw)
|
|
|
|
{
|
2019-10-08 15:58:23 +00:00
|
|
|
uint8_t cmd = 0;
|
2018-10-28 20:30:55 +00:00
|
|
|
uint32_t cid;
|
2019-10-08 15:58:23 +00:00
|
|
|
int len = 0;
|
2019-01-06 06:19:14 +00:00
|
|
|
#ifndef DISABLE_CTAPHID_CBOR
|
2018-10-28 20:30:55 +00:00
|
|
|
int status;
|
2019-01-06 06:19:14 +00:00
|
|
|
#endif
|
2018-05-28 18:14:59 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
static uint8_t is_busy = 0;
|
|
|
|
static CTAPHID_WRITE_BUFFER wb;
|
|
|
|
CTAP_RESPONSE ctap_resp;
|
|
|
|
|
|
|
|
int bufstatus = ctaphid_buffer_packet(pkt_raw, &cmd, &cid, &len);
|
2019-10-08 15:58:23 +00:00
|
|
|
ctaphid_write_buffer_init(&wb);
|
2018-10-28 20:30:55 +00:00
|
|
|
|
2019-10-08 16:09:20 +00:00
|
|
|
wb.cid = cid;
|
|
|
|
wb.cmd = cmd;
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
if (bufstatus == HID_IGNORE)
|
2018-05-01 03:27:26 +00:00
|
|
|
{
|
2018-10-28 20:30:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2018-05-02 02:22:52 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
if (bufstatus == HID_ERROR)
|
|
|
|
{
|
|
|
|
cid_del(cid);
|
2018-10-30 05:50:46 +00:00
|
|
|
if (cmd == CTAP1_ERR_INVALID_SEQ)
|
|
|
|
{
|
|
|
|
buffer_reset();
|
|
|
|
}
|
2018-10-28 20:30:55 +00:00
|
|
|
ctaphid_send_error(cid, cmd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bufstatus == BUFFERING)
|
|
|
|
{
|
|
|
|
active_cid_timestamp = millis();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(cmd)
|
|
|
|
{
|
2018-07-15 03:03:25 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
case CTAPHID_INIT:
|
|
|
|
printf2(TAG_ERR,"CTAPHID_INIT, error this should already be handled\n");
|
|
|
|
exit(1);
|
|
|
|
break;
|
2018-07-15 03:03:25 +00:00
|
|
|
#ifndef DISABLE_CTAPHID_PING
|
2018-10-28 20:30:55 +00:00
|
|
|
case CTAPHID_PING:
|
|
|
|
printf1(TAG_HID,"CTAPHID_PING\n");
|
|
|
|
|
|
|
|
wb.bcnt = len;
|
2019-02-13 01:28:48 +00:00
|
|
|
timestamp();
|
2018-10-28 20:30:55 +00:00
|
|
|
ctaphid_write(&wb, ctap_buffer, len);
|
|
|
|
ctaphid_write(&wb, NULL,0);
|
2019-02-13 01:28:48 +00:00
|
|
|
printf1(TAG_TIME,"PING writeback: %d ms\n",timestamp());
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
break;
|
2018-07-15 03:03:25 +00:00
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_CTAPHID_WINK
|
2018-10-28 20:30:55 +00:00
|
|
|
case CTAPHID_WINK:
|
|
|
|
printf1(TAG_HID,"CTAPHID_WINK\n");
|
2018-05-02 02:22:52 +00:00
|
|
|
|
2018-05-07 04:00:06 +00:00
|
|
|
|
2018-12-09 01:37:30 +00:00
|
|
|
device_wink();
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
ctaphid_write(&wb,NULL,0);
|
2018-05-02 02:22:52 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
break;
|
2018-07-15 03:03:25 +00:00
|
|
|
#endif
|
|
|
|
#ifndef DISABLE_CTAPHID_CBOR
|
2018-10-28 20:30:55 +00:00
|
|
|
case CTAPHID_CBOR:
|
|
|
|
printf1(TAG_HID,"CTAPHID_CBOR\n");
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
printf2(TAG_ERR,"Error,invalid 0 length field for cbor packet\n");
|
|
|
|
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
|
|
|
|
return 0;
|
2018-05-01 03:27:26 +00:00
|
|
|
}
|
2018-10-28 20:30:55 +00:00
|
|
|
if (is_busy)
|
|
|
|
{
|
|
|
|
printf1(TAG_HID,"Channel busy for CBOR\n");
|
|
|
|
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
is_busy = 1;
|
|
|
|
ctap_response_init(&ctap_resp);
|
|
|
|
status = ctap_request(ctap_buffer, len, &ctap_resp);
|
|
|
|
|
|
|
|
wb.bcnt = (ctap_resp.length+1);
|
2019-12-01 22:55:17 +00:00
|
|
|
wb.cid = cid;
|
|
|
|
wb.cmd = cmd;
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
|
|
|
|
|
2019-02-13 01:28:48 +00:00
|
|
|
timestamp();
|
2018-10-28 20:30:55 +00:00
|
|
|
ctaphid_write(&wb, &status, 1);
|
|
|
|
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
|
|
|
ctaphid_write(&wb, NULL, 0);
|
2019-02-13 01:28:48 +00:00
|
|
|
printf1(TAG_TIME,"CBOR writeback: %d ms\n",timestamp());
|
2018-10-28 20:30:55 +00:00
|
|
|
is_busy = 0;
|
2018-05-01 03:27:26 +00:00
|
|
|
break;
|
2018-10-28 20:30:55 +00:00
|
|
|
#endif
|
|
|
|
case CTAPHID_MSG:
|
2018-05-02 02:22:52 +00:00
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
printf1(TAG_HID,"CTAPHID_MSG\n");
|
|
|
|
if (len == 0)
|
|
|
|
{
|
|
|
|
printf2(TAG_ERR,"Error,invalid 0 length field for MSG/U2F packet\n");
|
|
|
|
ctaphid_send_error(cid, CTAP1_ERR_INVALID_LENGTH);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (is_busy)
|
|
|
|
{
|
|
|
|
printf1(TAG_HID,"Channel busy for MSG\n");
|
|
|
|
ctaphid_send_error(cid, CTAP1_ERR_CHANNEL_BUSY);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
is_busy = 1;
|
|
|
|
ctap_response_init(&ctap_resp);
|
|
|
|
u2f_request((struct u2f_request_apdu*)ctap_buffer, &ctap_resp);
|
|
|
|
|
|
|
|
wb.bcnt = (ctap_resp.length);
|
2019-12-01 22:55:17 +00:00
|
|
|
wb.cid = cid;
|
|
|
|
wb.cmd = cmd;
|
|
|
|
|
2018-10-28 20:30:55 +00:00
|
|
|
|
|
|
|
ctaphid_write(&wb, ctap_resp.data, ctap_resp.length);
|
|
|
|
ctaphid_write(&wb, NULL, 0);
|
|
|
|
is_busy = 0;
|
|
|
|
break;
|
|
|
|
case CTAPHID_CANCEL:
|
|
|
|
printf1(TAG_HID,"CTAPHID_CANCEL\n");
|
|
|
|
is_busy = 0;
|
|
|
|
break;
|
2019-10-08 15:34:58 +00:00
|
|
|
|
|
|
|
default:
|
2019-10-08 16:09:20 +00:00
|
|
|
if (ctaphid_custom_command(len, &ctap_resp, &wb) != 0){
|
2019-10-08 15:34:58 +00:00
|
|
|
is_busy = 0;
|
|
|
|
}else{
|
|
|
|
printf2(TAG_ERR, "error, unimplemented HID cmd: %02x\r\n", buffer_cmd());
|
|
|
|
ctaphid_send_error(cid, CTAP1_ERR_INVALID_COMMAND);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cid_del(cid);
|
|
|
|
buffer_reset();
|
|
|
|
|
|
|
|
printf1(TAG_HID,"\n");
|
|
|
|
if (!is_busy) return cmd;
|
|
|
|
else return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-10-08 16:09:20 +00:00
|
|
|
uint8_t ctaphid_custom_command(int len, CTAP_RESPONSE * ctap_resp, CTAPHID_WRITE_BUFFER * wb)
|
2019-10-08 15:34:58 +00:00
|
|
|
{
|
2019-10-08 15:58:23 +00:00
|
|
|
ctap_response_init(ctap_resp);
|
|
|
|
|
2019-10-27 12:58:34 +00:00
|
|
|
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
2019-10-08 15:34:58 +00:00
|
|
|
uint32_t param;
|
2019-10-08 15:58:23 +00:00
|
|
|
#endif
|
|
|
|
#if defined(IS_BOOTLOADER)
|
|
|
|
uint8_t is_busy;
|
|
|
|
#endif
|
2019-10-08 15:34:58 +00:00
|
|
|
|
2019-10-08 16:09:20 +00:00
|
|
|
switch(wb->cmd)
|
2019-10-08 15:34:58 +00:00
|
|
|
{
|
2018-12-04 05:15:58 +00:00
|
|
|
#if defined(IS_BOOTLOADER)
|
|
|
|
case CTAPHID_BOOT:
|
|
|
|
printf1(TAG_HID,"CTAPHID_BOOT\n");
|
2019-10-08 15:34:58 +00:00
|
|
|
u2f_set_writeback_buffer(ctap_resp);
|
2018-12-04 05:15:58 +00:00
|
|
|
is_busy = bootloader_bridge(len, ctap_buffer);
|
2019-10-27 15:52:44 +00:00
|
|
|
wb->bcnt = 1 + ctap_resp->length;
|
2018-12-04 05:15:58 +00:00
|
|
|
|
2019-10-08 15:34:58 +00:00
|
|
|
ctaphid_write(wb, &is_busy, 1);
|
2019-10-08 15:42:17 +00:00
|
|
|
ctaphid_write(wb, ctap_resp->data, ctap_resp->length);
|
2019-10-08 15:34:58 +00:00
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
2018-12-04 06:30:53 +00:00
|
|
|
#endif
|
2019-10-27 12:58:34 +00:00
|
|
|
#if defined(SOLO)
|
2018-12-04 06:30:53 +00:00
|
|
|
case CTAPHID_ENTERBOOT:
|
|
|
|
printf1(TAG_HID,"CTAPHID_ENTERBOOT\n");
|
|
|
|
boot_solo_bootloader();
|
2019-10-08 15:34:58 +00:00
|
|
|
wb->bcnt = 0;
|
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
2018-12-04 05:15:58 +00:00
|
|
|
#endif
|
2020-03-25 17:10:50 +00:00
|
|
|
#if defined(SOLO)
|
|
|
|
case CTAPHID_REBOOT:
|
|
|
|
device_reboot();
|
|
|
|
return 1;
|
|
|
|
#endif
|
2019-10-08 15:34:58 +00:00
|
|
|
|
2018-12-06 00:35:22 +00:00
|
|
|
#if !defined(IS_BOOTLOADER)
|
|
|
|
case CTAPHID_GETRNG:
|
|
|
|
printf1(TAG_HID,"CTAPHID_GETRNG\n");
|
2019-10-08 15:34:58 +00:00
|
|
|
wb->bcnt = ctap_buffer[0];
|
|
|
|
if (!wb->bcnt)
|
|
|
|
wb->bcnt = 57;
|
|
|
|
memset(ctap_buffer,0,wb->bcnt);
|
|
|
|
ctap_generate_rng(ctap_buffer, wb->bcnt);
|
|
|
|
ctaphid_write(wb, ctap_buffer, wb->bcnt);
|
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
2018-12-06 00:35:22 +00:00
|
|
|
break;
|
2019-09-16 09:12:09 +00:00
|
|
|
#endif
|
2019-09-16 09:00:30 +00:00
|
|
|
|
|
|
|
case CTAPHID_GETVERSION:
|
|
|
|
printf1(TAG_HID,"CTAPHID_GETVERSION\n");
|
2019-10-27 13:03:17 +00:00
|
|
|
wb->bcnt = 4;
|
2019-09-16 09:00:30 +00:00
|
|
|
ctap_buffer[0] = SOLO_VERSION_MAJ;
|
|
|
|
ctap_buffer[1] = SOLO_VERSION_MIN;
|
|
|
|
ctap_buffer[2] = SOLO_VERSION_PATCH;
|
2019-10-27 14:06:39 +00:00
|
|
|
#if defined(SOLO)
|
2019-10-27 13:03:17 +00:00
|
|
|
ctap_buffer[3] = solo_is_locked();
|
2019-10-27 14:06:39 +00:00
|
|
|
#else
|
|
|
|
ctap_buffer[3] = 0;
|
|
|
|
#endif
|
2019-10-27 13:03:17 +00:00
|
|
|
ctaphid_write(wb, ctap_buffer, 4);
|
2019-10-08 15:34:58 +00:00
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
2019-09-16 09:00:30 +00:00
|
|
|
break;
|
2019-02-27 01:58:56 +00:00
|
|
|
|
2020-02-13 21:58:53 +00:00
|
|
|
// Remove on next release
|
|
|
|
#if !defined(IS_BOOTLOADER) && defined(SOLO)
|
|
|
|
case 0x99:
|
|
|
|
solo_lock_if_not_already();
|
|
|
|
wb->bcnt = 0;
|
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
|
2019-10-27 12:58:34 +00:00
|
|
|
#if !defined(IS_BOOTLOADER) && (defined(SOLO_EXPERIMENTAL))
|
2019-10-08 15:34:58 +00:00
|
|
|
case CTAPHID_LOADKEY:
|
|
|
|
/**
|
|
|
|
* Load external key. Useful for enabling backups.
|
2019-10-29 12:22:11 +00:00
|
|
|
* bytes: 4 4 96
|
|
|
|
* payload: version [maj rev patch RFU]| counter_replacement (BE) | master_key |
|
2019-10-08 15:34:58 +00:00
|
|
|
*
|
|
|
|
* Counter should be increased by a large amount, e.g. (0x10000000)
|
|
|
|
* to outdo any previously lost/broken keys.
|
|
|
|
*/
|
|
|
|
printf1(TAG_HID,"CTAPHID_LOADKEY\n");
|
2019-10-29 12:22:11 +00:00
|
|
|
if (len != 104)
|
2019-10-08 15:34:58 +00:00
|
|
|
{
|
|
|
|
printf2(TAG_ERR,"Error, invalid length.\n");
|
2019-10-08 16:09:20 +00:00
|
|
|
ctaphid_send_error(wb->cid, CTAP1_ERR_INVALID_LENGTH);
|
2019-10-08 15:34:58 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2019-10-29 12:22:11 +00:00
|
|
|
param = ctap_buffer[0] << 16;
|
|
|
|
param |= ctap_buffer[1] << 8;
|
|
|
|
param |= ctap_buffer[2] << 0;
|
|
|
|
if (param != 0){
|
2019-10-29 13:09:53 +00:00
|
|
|
ctaphid_send_error(wb->cid, CTAP2_ERR_UNSUPPORTED_OPTION);
|
|
|
|
return 1;
|
2019-10-29 12:22:11 +00:00
|
|
|
}
|
2018-10-28 20:30:55 +00:00
|
|
|
|
2019-10-08 15:34:58 +00:00
|
|
|
// Ask for THREE button presses
|
|
|
|
if (ctap_user_presence_test(8000) > 0)
|
2019-10-29 12:16:04 +00:00
|
|
|
if (ctap_user_presence_test(2000) > 0)
|
|
|
|
if (ctap_user_presence_test(2000) > 0)
|
2019-10-08 15:34:58 +00:00
|
|
|
{
|
2019-10-29 12:47:14 +00:00
|
|
|
ctap_load_external_keys(ctap_buffer + 8);
|
2019-10-29 12:22:11 +00:00
|
|
|
param = ctap_buffer[7];
|
|
|
|
param |= ctap_buffer[6] << 8;
|
|
|
|
param |= ctap_buffer[5] << 16;
|
|
|
|
param |= ctap_buffer[4] << 24;
|
2019-10-08 15:34:58 +00:00
|
|
|
ctap_atomic_count(param);
|
|
|
|
|
|
|
|
wb->bcnt = 0;
|
|
|
|
|
|
|
|
ctaphid_write(wb, NULL, 0);
|
|
|
|
return 1;
|
|
|
|
}
|
2018-05-01 03:27:26 +00:00
|
|
|
|
2019-10-08 15:34:58 +00:00
|
|
|
printf2(TAG_ERR, "Error, invalid length.\n");
|
2019-10-08 16:09:20 +00:00
|
|
|
ctaphid_send_error(wb->cid, CTAP2_ERR_OPERATION_DENIED);
|
2019-10-08 15:34:58 +00:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|