uint8_t custom_command(struct u2f_hid_msg * msg) { struct atecc_response res; uint8_t ec; if (msg->cid != U2FHID_BROADCAST) return 0; switch(msg->pkt.init.cmd) { case U2F_CUSTOM_GET_RNG: if (atecc_send_recv(ATECC_CMD_RNG,ATECC_RNG_P1,ATECC_RNG_P2, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res) == 0 ) { memmove(msg->pkt.init.payload, res.buf, 32); U2FHID_SET_LEN(msg, 32); usb_write((uint8_t*)msg, 64); } else { U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); } break; case U2F_CUSTOM_SEED_RNG: ec = atecc_send_recv(ATECC_CMD_NONCE,ATECC_NONCE_RNG_UPDATE,0, msg->pkt.init.payload, 20, appdata.tmp, sizeof(appdata.tmp), &res); U2FHID_SET_LEN(msg, 1); msg->pkt.init.payload[0] = ec == 0 ? 1 : 0; usb_write((uint8_t*)msg, 64); break; case U2F_CUSTOM_WIPE_KEYS: U2FHID_SET_LEN(msg, 1); ec=u2f_wipe_keys(); msg->pkt.init.payload[0] = ec == 0 ? 1 : 0; usb_write((uint8_t*)msg, 64); break; case U2F_CUSTOM_WINK: app_wink(U2F_COLOR_WINK); break; default: return 0; } return 1; }
// Buffers data to a 64 byte buffer before writing it while // handling U2F HID sequencing void u2f_hid_writeback(uint8_t * payload, uint16_t len) { struct u2f_hid_msg * r = (struct u2f_hid_response *) _hid_pkt; _hid_in_session = 1; if (_hid_offset == 0) { r->cid = hid_layer.current_cid; if (!_hid_seq) { r->pkt.init.cmd = hid_layer.current_cmd; U2FHID_SET_LEN(r, hid_layer.res_len); _hid_offset = 7; } else { r->pkt.cont.seq = _hid_seq - 1; _hid_offset = 5; if (_hid_seq-1 > 127) { set_app_error(ERROR_SEQ_EXCEEDED); return; } } } while(len--) { _hid_pkt[_hid_offset++] = *payload++; hid_layer.bytes_written++; if (_hid_offset == HID_PACKET_SIZE) { _hid_offset = 0; _hid_seq++; usb_write(_hid_pkt, HID_PACKET_SIZE); memset(_hid_pkt, 0, HID_PACKET_SIZE); if (len) { u2f_hid_writeback(payload, len); return; } else break; } } }
uint8_t custom_command(struct u2f_hid_msg * msg) { struct atecc_response res; struct u2f_hid_msg * reply = (struct u2f_hid_msg *)appdata.tmp; uint8_t ec; if (msg->cid != U2FHID_BROADCAST) return 0; switch(msg->pkt.init.cmd) { case U2F_CUSTOM_GET_SERIAL_NUMBER: if (atecc_send_recv(ATECC_CMD_READ, ATECC_RW_CONFIG | ATECC_RW_EXT, 0, NULL, 0, reply->pkt.init.payload, sizeof(reply->pkt.init.payload), &res) == 0 ) { if (res.len > 15) res.len = 15; reply->cid = msg->cid; reply->pkt.init.cmd = msg->pkt.init.cmd; U2FHID_SET_LEN(reply, res.len); usb_write((uint8_t*)reply, 64); } else { reply->cid = msg->cid; reply->pkt.init.cmd = msg->pkt.init.cmd; U2FHID_SET_LEN(reply, 0); usb_write((uint8_t*)reply, 64); } break; case U2F_CUSTOM_GET_CONFIG: if (atecc_send_recv(ATECC_CMD_READ, ATECC_RW_CONFIG | ATECC_RW_EXT, (msg->pkt.init.payload[0] << 8) | msg->pkt.init.payload[1], NULL, 0, reply->pkt.init.payload, sizeof(reply->pkt.init.payload), &res) == 0) { if (res.len > 40) res.len = 40; reply->cid = msg->cid; reply->pkt.init.cmd = msg->pkt.init.cmd; U2FHID_SET_LEN(reply, res.len); usb_write((uint8_t*)reply, 64); } else { U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); } break; case U2F_CUSTOM_INIT_CONFIG: atecc_setup_config(); U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); break; case U2F_CUSTOM_LOCK_CONFIG: if (is_locked(appdata.tmp)) { msg->pkt.init.payload[0] = 0xff; U2FHID_SET_LEN(msg, 1); usb_write((uint8_t*)msg, 64); } else if (atecc_send_recv(ATECC_CMD_LOCK, ATECC_LOCK_CONFIG, (msg->pkt.init.payload[0] << 8) | msg->pkt.init.payload[1], NULL, 0, appdata.tmp, sizeof(appdata.tmp), NULL)) { msg->pkt.init.payload[0] = 0xfe; U2FHID_SET_LEN(msg, 1); usb_write((uint8_t*)msg, 64); } else { msg->pkt.init.payload[0] = 0x00; U2FHID_SET_LEN(msg, 1); usb_write((uint8_t*)msg, 64); } break; case U2F_CUSTOM_GEN_ATT_KEY: if (atecc_send_recv(ATECC_CMD_GENKEY, ATECC_GENKEY_PRIVATE, U2F_ATTESTATION_KEY_SLOT, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res) == 0 && res.len <= 64) { U2FHID_SET_LEN(msg, res.len - 1); memmove(msg->pkt.init.payload, res.buf, res.len - 1); usb_write((uint8_t*)msg, 64); } else { U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); } break; /* case U2F_CUSTOM_GET_RNG: if (atecc_send_recv(ATECC_CMD_RNG,ATECC_RNG_P1,ATECC_RNG_P2, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res) == 0 ) { memmove(msg->pkt.init.payload, res.buf, 32); U2FHID_SET_LEN(msg, 32); usb_write((uint8_t*)msg, 64); } else { U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); } break; case U2F_CUSTOM_SEED_RNG: ec = atecc_send_recv(ATECC_CMD_NONCE,ATECC_NONCE_RNG_UPDATE,0, msg->pkt.init.payload, 20, appdata.tmp, sizeof(appdata.tmp), &res); U2FHID_SET_LEN(msg, 1); msg->pkt.init.payload[0] = ec == 0 ? 1 : 0; usb_write((uint8_t*)msg, 64); break; */ case U2F_CUSTOM_WIPE_KEYS: U2FHID_SET_LEN(msg, 1); ec=u2f_wipe_keys(); msg->pkt.init.payload[0] = ec == 0 ? 1 : 0; usb_write((uint8_t*)msg, 64); break; case U2F_CUSTOM_ENTER_BOOTLOADER: USB_Detach(); enterBootloader(); break; case U2F_CUSTOM_INC_COUNT: if (atecc_send_recv(ATECC_CMD_COUNTER, ATECC_COUNTER_INC, ATECC_COUNTER0,NULL,0, appdata.tmp, sizeof(appdata.tmp), &res) == 0) { memmove(msg->pkt.init.payload, res.buf, res.len); U2FHID_SET_LEN(msg, res.len); usb_write((uint8_t*)msg, 64); } else { U2FHID_SET_LEN(msg, 0); usb_write((uint8_t*)msg, 64); } break; default: return 0; } return 1; }