mirror of
https://github.com/polhenarejos/pico-openpgp.git
synced 2026-04-09 17:25:51 +02:00
Add support for private DO.
Closes #50. Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -29,10 +29,20 @@ int cmd_get_data() {
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||
if (fid == EF_PRIV_DO_3) {
|
||||
if (!has_pw2 && !has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
}
|
||||
else if (fid == EF_PRIV_DO_4) {
|
||||
if (!has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
}
|
||||
else if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
if (currentEF && currentEF->fid == fid) { // previously selected same EF
|
||||
ef = currentEF;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -32,11 +32,17 @@ int cmd_put_data() {
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if ((fid == EF_PRIV_DO_1 || fid == EF_PRIV_DO_3) && (!has_pw2 && !has_pw3)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if ((fid == EF_PRIV_DO_2 || fid == EF_PRIV_DO_4) && !has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (fid == EF_PW_STATUS) {
|
||||
fid = EF_PW_PRIV;
|
||||
apdu.nc = 4; //we silently ommit the reset parameters
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
if (currentEF && currentEF->fid == fid) { // previously selected same EF
|
||||
ef = currentEF;
|
||||
}
|
||||
if (apdu.nc > 0 && (ef->type & FILE_DATA_FLASH)) {
|
||||
|
||||
@@ -55,12 +55,12 @@ uint8_t historical_bytes[] = {
|
||||
|
||||
uint8_t extended_capabilities[] = {
|
||||
10, 0,
|
||||
0x77, /*
|
||||
0x7f, /*
|
||||
* No Secure Messaging supported
|
||||
* GET CHALLENGE supported
|
||||
* Key import supported
|
||||
* PW status byte can be put
|
||||
* No private_use_DO
|
||||
* private_use_DO
|
||||
* Algorithm attrs are changable
|
||||
* ENC/DEC with AES
|
||||
* KDF-DO available
|
||||
@@ -68,7 +68,7 @@ uint8_t extended_capabilities[] = {
|
||||
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
|
||||
0x00, 128, /* Max size of GET CHALLENGE */
|
||||
0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
|
||||
0x00, 0xff,
|
||||
0x08, 0x00, /* max. length of private DO (2KiB) */
|
||||
0x00, 0x1
|
||||
};
|
||||
|
||||
@@ -476,10 +476,28 @@ file_t file_entries[] = {
|
||||
/* 131 */ { .fid = EF_PW_RETRIES, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 131 */ { .fid = EF_PRIV_DO_1, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 132 */ { .fid = EF_PRIV_DO_2, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 133 */ { .fid = EF_PRIV_DO_3, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||
/* 134 */ { .fid = EF_PRIV_DO_4, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||
/* 135 */ { .fid = EF_PW_RETRIES, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 136 */ { .fid = EF_PW_STATUS, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
|
||||
/* 132 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
||||
/* 137 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
||||
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||
/* 133 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
|
||||
/* 138 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
|
||||
.ef_structure = 0, .acl = ACL_NONE } //end
|
||||
};
|
||||
|
||||
|
||||
@@ -163,4 +163,9 @@
|
||||
|
||||
#define EF_DEV_CONF 0x1122
|
||||
|
||||
#define EF_PRIV_DO_1 0x0101
|
||||
#define EF_PRIV_DO_2 0x0102
|
||||
#define EF_PRIV_DO_3 0x0103
|
||||
#define EF_PRIV_DO_4 0x0104
|
||||
|
||||
#endif
|
||||
|
||||
@@ -201,7 +201,7 @@ def test_extended_capabilities(card):
|
||||
pytest.skip("Yubikey returns 6B00 when no key")
|
||||
else:
|
||||
a = get_data_object(card, 0xc0)
|
||||
assert a == None or match(b'[\x70\x74\x75\x77]\x00\x00.[\x00\x08]\x00\x00\xff[\x00\x01][\x00\x01]', a)
|
||||
assert a == None or match(b'[\x70\x7F\x75\x77]\x00\x00.[\x00\x08]\x00\x08\x00[\x00\x01][\x00\x01]', a)
|
||||
|
||||
def test_key_attributes_1(card):
|
||||
if card.is_yubikey:
|
||||
|
||||
@@ -28,6 +28,26 @@ from card_const import *
|
||||
from constants_for_test import *
|
||||
import pytest
|
||||
|
||||
PRIVATE_DO_0101 = (0x01, 0x01)
|
||||
PRIVATE_DO_0102 = (0x01, 0x02)
|
||||
PRIVATE_DO_0103 = (0x01, 0x03)
|
||||
PRIVATE_DO_0104 = (0x01, 0x04)
|
||||
|
||||
|
||||
def _assert_sw(e, sw_list):
|
||||
sw = e.args[0]
|
||||
assert sw in sw_list
|
||||
|
||||
|
||||
def _expect_security_error(callable_):
|
||||
try:
|
||||
callable_()
|
||||
except ValueError as e:
|
||||
_assert_sw(e, ["6982", "6985"])
|
||||
return
|
||||
assert False
|
||||
|
||||
|
||||
class Test_Card_Personalize_Card_2(object):
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
@@ -202,3 +222,112 @@ class Test_Card_Personalize_Card_2(object):
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_private_do_0101_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_pw3_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0101_write_fail_with_pw1_81(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(
|
||||
lambda: card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_pw1_81")
|
||||
)
|
||||
|
||||
def test_private_do_0101_write_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0101_read_always(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
data = get_data_object(card, 0x0101)
|
||||
assert data == b"priv0101_ok" or data == b"priv0101_pw3_ok"
|
||||
|
||||
def test_private_do_0102_write_fail_with_pw1(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(
|
||||
lambda: card.cmd_put_data(PRIVATE_DO_0102[0], PRIVATE_DO_0102[1], b"priv0102_pw1")
|
||||
)
|
||||
|
||||
def test_private_do_0102_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0102[0], PRIVATE_DO_0102[1], b"priv0102_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0102_read_always(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
data = get_data_object(card, 0x0102)
|
||||
assert data == b"priv0102_ok"
|
||||
|
||||
def test_private_do_0103_read_fail_without_auth(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0103))
|
||||
|
||||
def test_private_do_0103_read_fail_with_pw1_81(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0103))
|
||||
|
||||
def test_private_do_0103_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0103[0], PRIVATE_DO_0103[1], b"priv0103_pw3_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0103_read_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0103)
|
||||
assert data == b"priv0103_pw3_ok"
|
||||
|
||||
def test_private_do_0103_write_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0103[0], PRIVATE_DO_0103[1], b"priv0103_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0103_read_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0103)
|
||||
assert data == b"priv0103_ok"
|
||||
|
||||
def test_private_do_0104_read_fail_without_auth(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0104))
|
||||
|
||||
def test_private_do_0104_read_fail_with_pw1(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0104))
|
||||
|
||||
def test_private_do_0104_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0104[0], PRIVATE_DO_0104[1], b"priv0104_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0104_read_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0104)
|
||||
assert data == b"priv0104_ok"
|
||||
|
||||
Reference in New Issue
Block a user