blob: 94e5a116d7a8b0a4c14662d75146094410f4129b [file] [log] [blame]
/*
* Hid gadget driver daemon for FIDO2
*
* Copyright (C) 2019 James.Bottomley@HansenPartnership.com
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "u2f.h"
#include "u2f_hid.h"
static int dev;
static void process_error(U2FHID_FRAME *frame, int err)
{
char buf[HID_RPT_SIZE];
U2FHID_FRAME *reply = (U2FHID_FRAME *)buf;
int count;
memset(buf, 0, sizeof(buf));
reply->cid = frame->cid;
reply->init.cmd = U2FHID_ERROR;
reply->init.bcnth = 0;
reply->init.bcntl = sizeof(reply) + 1;
reply->init.data[0] = err;
count = write(dev, buf, sizeof(buf));
printf("wrote error frame %d\n", count);
}
static void process_init(U2FHID_FRAME *frame)
{
char buf[HID_RPT_SIZE];
U2FHID_FRAME *reply = (U2FHID_FRAME *)buf;
U2FHID_INIT_REQ *req = (U2FHID_INIT_REQ *)frame->init.data;
U2FHID_INIT_RESP *resp = (U2FHID_INIT_RESP *)reply->init.data;
int count;
if (MSG_LEN(*frame) != sizeof(U2FHID_INIT_REQ)) {
fprintf(stderr, "INIT message wrong length %d != %ld\n",
MSG_LEN(*frame),
sizeof(U2FHID_INIT_REQ));
process_error(frame, ERR_INVALID_LEN);
return;
}
if (frame->cid != CID_BROADCAST) {
fprintf(stderr, "INIT message to wrong cid %x\n", frame->cid);
process_error(frame, ERR_INVALID_CMD);
return;
}
memset(buf, 0, sizeof(buf));
reply->cid = CID_BROADCAST;
reply->init.cmd = U2FHID_INIT;
reply->init.bcnth = 0;
reply->init.bcntl = 17;
printf("setting reply size to %ld\n", sizeof(*resp));
memcpy(resp->nonce, req->nonce, sizeof(req->nonce));
resp->cid = 1;
resp->versionInterface = U2FHID_IF_VERSION;
count = write(dev, buf, sizeof(buf));
printf("written %d bytes\n", count);
}
static void command_loop(void)
{
int count;
uint8_t buf[HID_RPT_SIZE];
U2FHID_FRAME *frame = (U2FHID_FRAME *)buf;
count = read(dev, buf, sizeof(buf));
printf("received %d bytes\n", count);
if (frame->init.cmd == U2FHID_INIT) {
printf("Got INIT\n");
process_init(frame);
} else {
printf("Got unknown command 0x%x\n", FRAME_CMD(*frame));
process_error(frame, ERR_INVALID_CMD);
}
}
int main(int argc, const char *argv[])
{
if (argc != 2) {
fprintf(stderr, "need hidg device\n");
exit(1);
}
dev = open(argv[1], O_RDWR);
if (dev < 0) {
perror("Failed to open HIDG");
exit(1);
}
for (;;) {
command_loop();
}
}