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; }
// bad if this gets interrupted int8_t u2f_new_keypair(uint8_t * handle, uint8_t * pubkey) { struct atecc_response res; struct key_handle k; uint8_t keyslot = key_store.num_issued; if (keyslot > U2F_NUM_KEYS-1) { //app_wink(U2F_DEFAULT_COLOR_WINK_OUT_OF_SPACE); return -1; } //watchdog(); atecc_send_recv(ATECC_CMD_GENKEY, ATECC_GENKEY_PRIVATE, keyslot, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res); memmove(pubkey, res.buf, 64); eeprom_read(U2F_KEY_ADDR(keyslot), (uint8_t* )&k, U2F_KEY_HANDLE_SIZE); if (k.index-1 != keyslot) { k.index = keyslot; set_app_error(ERROR_BAD_KEY_STORE); } memmove(handle, &k, U2F_KEY_HANDLE_SIZE); key_store.num_issued++; flush_key_store(); return 0; }
void u2f_sha256_start() { shaoffset = 0; atecc_send_recv(ATECC_CMD_SHA, ATECC_SHA_START, 0,NULL,0, appdata.tmp, sizeof(appdata.tmp), NULL); }
uint32_t u2f_count() { struct atecc_response res; atecc_send_recv(ATECC_CMD_COUNTER, ATECC_COUNTER_INC, ATECC_COUNTER0,NULL,0, appdata.tmp, sizeof(appdata.tmp), &res); return *(uint32_t*)res.buf; }
void u2f_init() { int8_t i,ec; uint8_t * clear = 0; struct atecc_response res; if (is_locked(appdata.tmp)) { eeprom_read(U2F_EEPROM_CONFIG, (uint8_t* )&key_store, sizeof(struct key_storage_header)); // initialize key handles if (key_store.num_keys != U2F_NUM_KEYS) { //watchdog(); for (i=0; i < U2F_NUM_KEYS; i++) { //watchdog(); ec = atecc_send_recv(ATECC_CMD_RNG,ATECC_RNG_P1,ATECC_RNG_P2, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res); if (ec != 0) { //u2f_printb("atecc_send_recv failed ",2,i,-ec); // erase eeprom //eeprom_erase(U2F_EEPROM_CONFIG); // erase ram //for (i=0; i<0x400;i++) //{ // *(clear++) = 0x0; //} // reset //reboot(); return; } res.buf[0] = i+1; eeprom_write(U2F_KEYS_ADDR + i * U2F_KEY_HANDLE_SIZE, res.buf, U2F_KEY_HANDLE_SIZE); } key_store.num_keys = U2F_NUM_KEYS; key_store.valid_keys = 0; key_store.num_issued = 0; flush_key_store(); } } }
void u2f_sha256_update(uint8_t * buf, uint8_t len) { uint8_t i = 0; //watchdog(); while(len--) { shabuf[shaoffset++] = *buf++; if (shaoffset == 64) { atecc_send_recv(ATECC_CMD_SHA, ATECC_SHA_UPDATE, 64,shabuf,64, appdata.tmp, sizeof(appdata.tmp), NULL); shaoffset = 0; } } }
int8_t u2f_ecdsa_sign(uint8_t * dest, uint8_t * handle) { struct atecc_response res; struct key_handle k; uint16_t keyslot = (uint16_t)((struct key_handle *)handle)->index; //watchdog(); if (keyslot > U2F_NUM_KEYS) { return -1; } if (keyslot == 0) { keyslot = U2F_ATTESTATION_KEY_SLOT; } else { keyslot--; } atecc_send_recv(ATECC_CMD_SIGN, ATECC_SIGN_EXTERNAL, keyslot, NULL, 0, appdata.tmp, sizeof(appdata.tmp), &res); if (keyslot != U2F_ATTESTATION_KEY_SLOT) { eeprom_read(U2F_KEY_ADDR(keyslot), (uint8_t* )&k, U2F_KEY_HANDLE_SIZE); if (key_same((struct key_handle *)handle, &k) != 0) { return -1; } } memmove(dest, res.buf, 64); return 0; }
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; }
void u2f_sha256_finish() { atecc_send_recv(ATECC_CMD_SHA, ATECC_SHA_END, shaoffset,shabuf,shaoffset, shabuf, sizeof(shabuf), &res_digest); }