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:
Pol Henarejos
2024-03-06 18:54:30 +01:00
parent 21e3ba11c6
commit 817d8b39ec
3 changed files with 189 additions and 1 deletions

View File

@@ -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
View 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();
}

View File

@@ -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