mirror of
https://github.com/polhenarejos/pico-fido.git
synced 2025-12-18 00:54:41 +08:00
Adding first commit of OTP.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -50,13 +50,26 @@ option(ENABLE_OATH_APP "Enable/disable OATH application" ON)
|
||||
if(ENABLE_OATH_APP)
|
||||
add_definitions(-DENABLE_OATH_APP=1)
|
||||
message(STATUS "OATH Application: \t\t enabled")
|
||||
set(USB_ITF_CCID 1)
|
||||
else()
|
||||
add_definitions(-DENABLE_OATH_APP=0)
|
||||
message(STATUS "OATH Application: \t\t disabled")
|
||||
set(USB_ITF_CCID 0)
|
||||
endif(ENABLE_OATH_APP)
|
||||
|
||||
option(ENABLE_OTP_APP "Enable/disable OTP application" ON)
|
||||
if(ENABLE_OTP_APP)
|
||||
add_definitions(-DENABLE_OTP_APP=1)
|
||||
message(STATUS "OTP Application: \t\t enabled")
|
||||
else()
|
||||
add_definitions(-DENABLE_OTP_APP=0)
|
||||
message(STATUS "OTP Application: \t\t disabled")
|
||||
endif(ENABLE_OTP_APP)
|
||||
|
||||
if(ENABLE_OTP_APP OR ENABLE_OATH_APP)
|
||||
set(USB_ITF_CCID 1)
|
||||
else()
|
||||
set(USB_ITF_CCID 0)
|
||||
endif()
|
||||
|
||||
target_sources(pico_fido PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/fido.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/files.c
|
||||
@@ -82,6 +95,11 @@ target_sources(pico_fido PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/oath.c
|
||||
)
|
||||
endif()
|
||||
if (${ENABLE_OTP_APP})
|
||||
target_sources(pico_fido PUBLIC
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/otp.c
|
||||
)
|
||||
endif()
|
||||
|
||||
set(USB_ITF_HID 1)
|
||||
include(pico-hsm-sdk/pico_hsm_sdk_import.cmake)
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#define EF_LARGEBLOB 0x1101 // Large Blob Array
|
||||
#define EF_OATH_CRED 0xBA00 // OATH Creds at 0xBA00 - 0xBAFE
|
||||
#define EF_OATH_CODE 0xBAFF
|
||||
#define EF_OTP_SLOT1 0xBB00
|
||||
#define EF_OTP_SLOT2 0xBB01
|
||||
|
||||
extern file_t *ef_keydev;
|
||||
extern file_t *ef_certdev;
|
||||
|
||||
151
src/fido/otp.c
Normal file
151
src/fido/otp.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "fido.h"
|
||||
#include "hsm.h"
|
||||
#include "apdu.h"
|
||||
#include "files.h"
|
||||
#include "random.h"
|
||||
#include "version.h"
|
||||
#include "asn1.h"
|
||||
|
||||
#define FIXED_SIZE 16
|
||||
#define KEY_SIZE 16
|
||||
#define UID_SIZE 6
|
||||
#define KEY_SIZE_OATH 20
|
||||
#define ACC_CODE_SIZE 6
|
||||
|
||||
#define CONFIG1_VALID 0x01
|
||||
#define CONFIG2_VALID 0x02
|
||||
#define CONFIG1_TOUCH 0x04
|
||||
#define CONFIG2_TOUCH 0x08
|
||||
#define CONFIG_LED_INV 0x10
|
||||
#define CONFIG_STATUS_MASK 0x1f
|
||||
|
||||
static uint8_t config_seq[2] = {1};
|
||||
|
||||
typedef struct otp_config {
|
||||
uint8_t fixed_data[FIXED_SIZE];
|
||||
uint8_t uid[UID_SIZE];
|
||||
uint8_t aes_key[KEY_SIZE];
|
||||
uint8_t acc_code[ACC_CODE_SIZE];
|
||||
uint8_t fixed_size;
|
||||
uint8_t ext_flags;
|
||||
uint8_t tkt_flags;
|
||||
uint8_t cfg_flags;
|
||||
uint8_t rfu[2];
|
||||
uint16_t crc;
|
||||
} __attribute__((packed)) otp_config_t;
|
||||
|
||||
static const size_t otp_config_size = sizeof(otp_config_t);
|
||||
|
||||
int otp_process_apdu();
|
||||
int otp_unload();
|
||||
|
||||
const uint8_t otp_aid[] = {
|
||||
7,
|
||||
0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01
|
||||
};
|
||||
|
||||
app_t *otp_select(app_t *a, const uint8_t *aid, uint8_t aid_len) {
|
||||
if (!memcmp(aid, otp_aid+1, MIN(aid_len,otp_aid[0]))) {
|
||||
a->aid = otp_aid;
|
||||
a->process_apdu = otp_process_apdu;
|
||||
a->unload = otp_unload;
|
||||
return a;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void __attribute__ ((constructor)) otp_ctor() {
|
||||
register_app(otp_select);
|
||||
}
|
||||
|
||||
int otp_unload() {
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
uint16_t otp_status(uint8_t slot) {
|
||||
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++] = config_seq[slot];
|
||||
res_APDU[res_APDU_size++] = 0;
|
||||
res_APDU[res_APDU_size++] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | (config_seq[0] > 0 ? CONFIG1_VALID : 0x00) | (config_seq[1] > 0 ? CONFIG2_VALID : 0x00);
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_otp() {
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
if (p2 != 0x00) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (p1 == 0x01 || p1 == 0x03) { // Configure slot
|
||||
if (apdu.nc != otp_config_size+ACC_CODE_SIZE)
|
||||
return SW_WRONG_LENGTH();
|
||||
if (apdu.data[48] != 0 || apdu.data[49] != 0)
|
||||
return SW_WRONG_DATA();
|
||||
uint8_t slot = p1 == 0x01 ? 0 : 1;
|
||||
file_t *ef = file_new(p1 == 0x01 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
|
||||
if (file_has_data(ef)) {
|
||||
otp_config_t *otpc = (otp_config_t *)file_get_data(ef);
|
||||
if (memcmp(otpc->acc_code, apdu.data+otp_config_size, ACC_CODE_SIZE) != 0)
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
for (int c = 0; c < otp_config_size; c++) {
|
||||
if (apdu.data[c] != 0) {
|
||||
flash_write_data_to_file(ef, apdu.data, otp_config_size);
|
||||
low_flash_available();
|
||||
config_seq[slot]++;
|
||||
return otp_status(slot);
|
||||
}
|
||||
}
|
||||
// Delete slot
|
||||
delete_file(ef);
|
||||
config_seq[slot] = 0;
|
||||
return otp_status(slot);
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
#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 },
|
||||
{ 0x00, 0x0}
|
||||
};
|
||||
|
||||
int otp_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();
|
||||
}
|
||||
Reference in New Issue
Block a user