Skip to content

Commit 817d8b3

Browse files
committed
Added first commit of Pico OpenPGP with PIV support.
It shares the PIN of OpenPGP. Signed-off-by: Pol Henarejos <[email protected]>
1 parent 21e3ba1 commit 817d8b3

File tree

3 files changed

+189
-1
lines changed

3 files changed

+189
-1
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ add_executable(pico_openpgp)
3737
set(SOURCES ${SOURCES}
3838
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
3939
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
40+
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
4041
)
4142

4243
set(INCLUDES ${INCLUDES}

src/openpgp/piv.c

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
3+
* Copyright (c) 2022 Pol Henarejos.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, version 3.
8+
*
9+
* This program is distributed in the hope that it will be useful, but
10+
* WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+
* General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include "common.h"
19+
#include "files.h"
20+
#include "apdu.h"
21+
#include "pico_keys.h"
22+
#include "eac.h"
23+
#include "version.h"
24+
#include "pico/unique_id.h"
25+
26+
extern bool has_pw1;
27+
28+
uint8_t piv_aid[] = {
29+
5,
30+
0xA0, 0x00, 0x00, 0x03, 0x8,
31+
};
32+
uint8_t yk_aid[] = {
33+
8,
34+
0xA0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x1, 0x1
35+
};
36+
uint8_t mgmt_aid[] = {
37+
8,
38+
0xA0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
39+
};
40+
41+
int piv_process_apdu();
42+
43+
static void scan_files() {
44+
scan_flash();
45+
}
46+
47+
void init_piv() {
48+
scan_files();
49+
//cmd_select();
50+
}
51+
52+
int piv_unload() {
53+
return CCID_OK;
54+
}
55+
56+
void select_piv_aid() {
57+
res_APDU[res_APDU_size++] = 0x61;
58+
res_APDU[res_APDU_size++] = 0; //filled later
59+
res_APDU[res_APDU_size++] = 0x4F;
60+
res_APDU[res_APDU_size++] = 2;
61+
res_APDU[res_APDU_size++] = 0x01;
62+
res_APDU[res_APDU_size++] = 0x00;
63+
res_APDU[res_APDU_size++] = 0x79;
64+
res_APDU[res_APDU_size++] = 9;
65+
memcpy(res_APDU + res_APDU_size, "\xA0\x00\x00\x03\x08\x00\x00\x10\x00", 9);
66+
res_APDU_size += 9;
67+
const char *app_label = "Pico Keys PIV";
68+
res_APDU[res_APDU_size++] = 0x50;
69+
res_APDU[res_APDU_size++] = strlen(app_label);
70+
memcpy(res_APDU + res_APDU_size, app_label, strlen(app_label));
71+
72+
res_APDU[res_APDU_size++] = 0xAC;
73+
res_APDU[res_APDU_size++] = 12;
74+
res_APDU[res_APDU_size++] = 0x80;
75+
res_APDU[res_APDU_size++] = 7;
76+
memcpy(res_APDU + res_APDU_size, "\x07\x08\x0A\x0C\x11\x14\x2E", 7);
77+
res_APDU_size += 7;
78+
res_APDU[res_APDU_size++] = 0x6;
79+
res_APDU[res_APDU_size++] = 1;
80+
res_APDU[res_APDU_size++] = 0x00;
81+
}
82+
83+
int piv_select_aid(app_t *a) {
84+
a->process_apdu = piv_process_apdu;
85+
a->unload = piv_unload;
86+
init_piv();
87+
select_piv_aid();
88+
return CCID_OK;
89+
}
90+
91+
void __attribute__((constructor)) piv_ctor() {
92+
register_app(piv_select_aid, piv_aid);
93+
register_app(piv_select_aid, yk_aid);
94+
register_app(piv_select_aid, mgmt_aid);
95+
}
96+
97+
static int cmd_version() {
98+
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
99+
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
100+
res_APDU[res_APDU_size++] = 0x0;
101+
return SW_OK();
102+
}
103+
104+
static int cmd_select() {
105+
if (P2(apdu) != 0x1) {
106+
return SW_WRONG_P1P2();
107+
}
108+
if (memcmp(apdu.data, piv_aid, 5) == 0) {
109+
select_piv_aid();
110+
}
111+
return SW_OK();
112+
}
113+
114+
static int cmd_get_serial() {
115+
pico_unique_board_id_t unique_id;
116+
pico_get_unique_board_id(&unique_id);
117+
memcpy(res_APDU, unique_id.id, 4);
118+
res_APDU_size = 4;
119+
return SW_OK();
120+
}
121+
122+
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
123+
static int cmd_verify() {
124+
uint8_t key_ref = P2(apdu);
125+
if (P1(apdu) != 0x00 && P1(apdu) != 0xFF) {
126+
return SW_INCORRECT_P1P2();
127+
}
128+
if (key_ref != 0x80) {
129+
return SW_REFERENCE_NOT_FOUND();
130+
}
131+
file_t *pw, *pw_status;
132+
uint16_t fid = 0x0;
133+
if (key_ref == 0x80) {
134+
fid = EF_PW1;
135+
}
136+
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
137+
return SW_REFERENCE_NOT_FOUND();
138+
}
139+
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
140+
return SW_REFERENCE_NOT_FOUND();
141+
}
142+
if (file_get_data(pw)[0] == 0) { //not initialized
143+
return SW_REFERENCE_NOT_FOUND();
144+
}
145+
if (apdu.nc > 0) {
146+
return check_pin(pw, apdu.data, apdu.nc);
147+
}
148+
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0x3));
149+
if (retries == 0) {
150+
return SW_PIN_BLOCKED();
151+
}
152+
if ((key_ref == 0x80 && has_pw1)) {
153+
return SW_OK();
154+
}
155+
return set_res_sw(0x63, 0xc0 | retries);
156+
}
157+
158+
#define INS_VERIFY 0x20
159+
#define INS_VERSION 0xFD
160+
#define INS_SELECT 0xA4
161+
#define INS_YK_SERIAL 0xF8
162+
#define INS_VERIFY 0x20
163+
164+
static const cmd_t cmds[] = {
165+
{ INS_VERSION, cmd_version },
166+
{ INS_SELECT, cmd_select },
167+
{ INS_YK_SERIAL, cmd_get_serial },
168+
{ INS_VERIFY, cmd_verify },
169+
{ 0x00, 0x0 }
170+
};
171+
172+
int piv_process_apdu() {
173+
sm_unwrap();
174+
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
175+
if (cmd->ins == INS(apdu)) {
176+
int r = cmd->cmd_handler();
177+
sm_wrap();
178+
return r;
179+
}
180+
}
181+
return SW_INS_NOT_SUPPORTED();
182+
}

src/openpgp/version.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@
2424
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
2525

2626

27-
#define PIPGP_VERSION 0x010C
27+
#define PIPGP_VERSION 0x0200
2828

2929
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
3030
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
3131

32+
#define PIV_VERSION 0x0500
33+
34+
#define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
35+
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
36+
3237
#endif

0 commit comments

Comments
 (0)