Added first commit of Pico OpenPGP with PIV support.
It shares the PIN of OpenPGP. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -37,6 +37,7 @@ add_executable(pico_openpgp)
|
||||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
|
||||
)
|
||||
|
||||
set(INCLUDES ${INCLUDES}
|
||||
|
||||
182
src/openpgp/piv.c
Normal file
182
src/openpgp/piv.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
|
||||
* 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 "common.h"
|
||||
#include "files.h"
|
||||
#include "apdu.h"
|
||||
#include "pico_keys.h"
|
||||
#include "eac.h"
|
||||
#include "version.h"
|
||||
#include "pico/unique_id.h"
|
||||
|
||||
extern bool has_pw1;
|
||||
|
||||
uint8_t piv_aid[] = {
|
||||
5,
|
||||
0xA0, 0x00, 0x00, 0x03, 0x8,
|
||||
};
|
||||
uint8_t yk_aid[] = {
|
||||
8,
|
||||
0xA0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x1, 0x1
|
||||
};
|
||||
uint8_t mgmt_aid[] = {
|
||||
8,
|
||||
0xA0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
|
||||
};
|
||||
|
||||
int piv_process_apdu();
|
||||
|
||||
static void scan_files() {
|
||||
scan_flash();
|
||||
}
|
||||
|
||||
void init_piv() {
|
||||
scan_files();
|
||||
//cmd_select();
|
||||
}
|
||||
|
||||
int piv_unload() {
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
void select_piv_aid() {
|
||||
res_APDU[res_APDU_size++] = 0x61;
|
||||
res_APDU[res_APDU_size++] = 0; //filled later
|
||||
res_APDU[res_APDU_size++] = 0x4F;
|
||||
res_APDU[res_APDU_size++] = 2;
|
||||
res_APDU[res_APDU_size++] = 0x01;
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
res_APDU[res_APDU_size++] = 0x79;
|
||||
res_APDU[res_APDU_size++] = 9;
|
||||
memcpy(res_APDU + res_APDU_size, "\xA0\x00\x00\x03\x08\x00\x00\x10\x00", 9);
|
||||
res_APDU_size += 9;
|
||||
const char *app_label = "Pico Keys PIV";
|
||||
res_APDU[res_APDU_size++] = 0x50;
|
||||
res_APDU[res_APDU_size++] = strlen(app_label);
|
||||
memcpy(res_APDU + res_APDU_size, app_label, strlen(app_label));
|
||||
|
||||
res_APDU[res_APDU_size++] = 0xAC;
|
||||
res_APDU[res_APDU_size++] = 12;
|
||||
res_APDU[res_APDU_size++] = 0x80;
|
||||
res_APDU[res_APDU_size++] = 7;
|
||||
memcpy(res_APDU + res_APDU_size, "\x07\x08\x0A\x0C\x11\x14\x2E", 7);
|
||||
res_APDU_size += 7;
|
||||
res_APDU[res_APDU_size++] = 0x6;
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
}
|
||||
|
||||
int piv_select_aid(app_t *a) {
|
||||
a->process_apdu = piv_process_apdu;
|
||||
a->unload = piv_unload;
|
||||
init_piv();
|
||||
select_piv_aid();
|
||||
return CCID_OK;
|
||||
}
|
||||
|
||||
void __attribute__((constructor)) piv_ctor() {
|
||||
register_app(piv_select_aid, piv_aid);
|
||||
register_app(piv_select_aid, yk_aid);
|
||||
register_app(piv_select_aid, mgmt_aid);
|
||||
}
|
||||
|
||||
static int cmd_version() {
|
||||
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
|
||||
res_APDU[res_APDU_size++] = 0x0;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_select() {
|
||||
if (P2(apdu) != 0x1) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
if (memcmp(apdu.data, piv_aid, 5) == 0) {
|
||||
select_piv_aid();
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_get_serial() {
|
||||
pico_unique_board_id_t unique_id;
|
||||
pico_get_unique_board_id(&unique_id);
|
||||
memcpy(res_APDU, unique_id.id, 4);
|
||||
res_APDU_size = 4;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
|
||||
static int cmd_verify() {
|
||||
uint8_t key_ref = P2(apdu);
|
||||
if (P1(apdu) != 0x00 && P1(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (key_ref != 0x80) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
file_t *pw, *pw_status;
|
||||
uint16_t fid = 0x0;
|
||||
if (key_ref == 0x80) {
|
||||
fid = EF_PW1;
|
||||
}
|
||||
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (file_get_data(pw)[0] == 0) { //not initialized
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (apdu.nc > 0) {
|
||||
return check_pin(pw, apdu.data, apdu.nc);
|
||||
}
|
||||
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0x3));
|
||||
if (retries == 0) {
|
||||
return SW_PIN_BLOCKED();
|
||||
}
|
||||
if ((key_ref == 0x80 && has_pw1)) {
|
||||
return SW_OK();
|
||||
}
|
||||
return set_res_sw(0x63, 0xc0 | retries);
|
||||
}
|
||||
|
||||
#define INS_VERIFY 0x20
|
||||
#define INS_VERSION 0xFD
|
||||
#define INS_SELECT 0xA4
|
||||
#define INS_YK_SERIAL 0xF8
|
||||
#define INS_VERIFY 0x20
|
||||
|
||||
static const cmd_t cmds[] = {
|
||||
{ INS_VERSION, cmd_version },
|
||||
{ INS_SELECT, cmd_select },
|
||||
{ INS_YK_SERIAL, cmd_get_serial },
|
||||
{ INS_VERIFY, cmd_verify },
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int piv_process_apdu() {
|
||||
sm_unwrap();
|
||||
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
||||
if (cmd->ins == INS(apdu)) {
|
||||
int r = cmd->cmd_handler();
|
||||
sm_wrap();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return SW_INS_NOT_SUPPORTED();
|
||||
}
|
||||
@@ -24,9 +24,14 @@
|
||||
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
|
||||
|
||||
|
||||
#define PIPGP_VERSION 0x010C
|
||||
#define PIPGP_VERSION 0x0200
|
||||
|
||||
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
||||
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
||||
|
||||
#define PIV_VERSION 0x0500
|
||||
|
||||
#define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
|
||||
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user