diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b040ad..8eee727 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,6 +95,7 @@ set(SOURCES ${SOURCES} ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_config.c ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_vendor.c ${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_large_blobs.c + ${CMAKE_CURRENT_LIST_DIR}/src/fido/management.c ) if (${ENABLE_OATH_APP}) set(SOURCES ${SOURCES} diff --git a/src/fido/management.c b/src/fido/management.c new file mode 100644 index 0000000..1e42b5e --- /dev/null +++ b/src/fido/management.c @@ -0,0 +1,116 @@ +/* + * This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "fido.h" +#include "hsm.h" +#include "apdu.h" +#include "version.h" + +int man_process_apdu(); +int man_unload(); + +const uint8_t man_aid[] = { + 8, + 0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17 +}; + +app_t *man_select(app_t *a, const uint8_t *aid, uint8_t aid_len) { + if (!memcmp(aid, man_aid + 1, MIN(aid_len, man_aid[0]))) { + a->aid = man_aid; + a->process_apdu = man_process_apdu; + a->unload = man_unload; + sprintf((char *)res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR); + res_APDU_size = strlen((char *)res_APDU); + apdu.ne = res_APDU_size; + return a; + } + return NULL; +} + +void __attribute__((constructor)) man_ctor() { + register_app(man_select); +} + +int man_unload() { + return CCID_OK; +} + +int man_get_config() { + res_APDU_size = 0; + res_APDU[res_APDU_size++] = 0; // Overall length. Filled later + res_APDU[res_APDU_size++] = 0x01; + res_APDU[res_APDU_size++] = 2; + res_APDU[res_APDU_size++] = 0x02; + res_APDU[res_APDU_size++] = 0x01 | 0x02 | 0x20; + res_APDU[res_APDU_size++] = 0x02; + res_APDU[res_APDU_size++] = 4; +#ifndef ENABLE_EMULATION + pico_get_unique_board_id_string((char *) res_APDU + res_APDU_size, 4); +#endif + res_APDU_size += 4; + res_APDU[res_APDU_size++] = 0x03; + res_APDU[res_APDU_size++] = 2; + res_APDU[res_APDU_size++] = 0x02; + res_APDU[res_APDU_size++] = 0x01 | 0x02 | 0x20; + res_APDU[res_APDU_size++] = 0x04; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = 0x01; + res_APDU[res_APDU_size++] = 0x05; + res_APDU[res_APDU_size++] = 3; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; + res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; + res_APDU[res_APDU_size++] = 0; + res_APDU[res_APDU_size++] = 0x08; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = 0x80; + res_APDU[res_APDU_size++] = 0x0A; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = 0x00; + res_APDU[res_APDU_size++] = 0x0D; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = 0x00; + res_APDU[res_APDU_size++] = 0x0E; + res_APDU[res_APDU_size++] = 1; + res_APDU[res_APDU_size++] = 0x00; + res_APDU[0] = res_APDU_size - 1; + return 0; +} + +int cmd_read_config() { + man_get_config(); + return SW_OK(); +} + +#define INS_READ_CONFIG 0x1D + +static const cmd_t cmds[] = { + { INS_READ_CONFIG, cmd_read_config }, + { 0x00, 0x0 } +}; + +int man_process_apdu() { + if (CLA(apdu) != 0x00) { + return SW_CLA_NOT_SUPPORTED(); + } + for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { + if (cmd->ins == INS(apdu)) { + int r = cmd->cmd_handler(); + return r; + } + } + return SW_INS_NOT_SUPPORTED(); +} diff --git a/src/fido/otp.c b/src/fido/otp.c index ed913d7..9ea7820 100644 --- a/src/fido/otp.c +++ b/src/fido/otp.c @@ -328,6 +328,8 @@ bool check_crc(const otp_config_t *data) { return crc == 0xF0B8; } +extern int man_get_config(); + int cmd_otp() { uint8_t p1 = P1(apdu), p2 = P2(apdu); if (p2 != 0x00) { @@ -412,35 +414,7 @@ int cmd_otp() { res_APDU_size = 4; } else if (p1 == 0x13) { - res_APDU_size = 0; - res_APDU[res_APDU_size++] = 0; // Overall length. Filled later - res_APDU[res_APDU_size++] = 0x01; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = 0xFF; - res_APDU[res_APDU_size++] = 0x02; - res_APDU[res_APDU_size++] = 4; -#ifndef ENABLE_EMULATION - pico_get_unique_board_id_string((char *) res_APDU + res_APDU_size, 4); -#endif - res_APDU_size += 4; - res_APDU[res_APDU_size++] = 0x03; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = 0x3F; - res_APDU[res_APDU_size++] = 0x04; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = 0x01; - res_APDU[res_APDU_size++] = 0x05; - res_APDU[res_APDU_size++] = 3; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR; - res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR; - res_APDU[res_APDU_size++] = 0; - res_APDU[res_APDU_size++] = 0x08; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = 0x80; - res_APDU[res_APDU_size++] = 0x0A; - res_APDU[res_APDU_size++] = 1; - res_APDU[res_APDU_size++] = 0x00; - res_APDU[0] = res_APDU_size - 1; + man_get_config(); } else if (p1 == 0x30 || p1 == 0x38 || p1 == 0x20 || p1 == 0x28) { file_t *ef = search_dynamic_file(p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2); @@ -477,14 +451,6 @@ int cmd_otp() { } #define INS_OTP 0x01 -#define INS_DELETE 0x02 -#define INS_SET_CODE 0x03 -#define INS_RESET 0x04 -#define INS_LIST 0xa1 -#define INS_CALCULATE 0xa2 -#define INS_VALIDATE 0xa3 -#define INS_CALC_ALL 0xa4 -#define INS_SEND_REMAINING 0xa5 static const cmd_t cmds[] = { { INS_OTP, cmd_otp },