Added AUTHENTICATE support.

Note that CARD MGM key is NOT encrypted with DEK, since it has to be accessed even without PIN.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2024-03-12 22:04:19 +01:00
parent 817d8b39ec
commit 4cfa2a16bf
5 changed files with 701 additions and 59 deletions

View File

@@ -39,6 +39,7 @@ extern int parse_algoinfo(const file_t *f, int mode);
extern int parse_app_data(const file_t *f, int mode);
extern int parse_discrete_do(const file_t *f, int mode);
extern int parse_pw_status(const file_t *f, int mode);
extern int piv_parse_discovery(const file_t *f);
uint8_t historical_bytes[] = {
10, 0,
@@ -249,10 +250,233 @@ file_t file_entries[] = {
/* 56 */ { .fid = EF_CH_3, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
// ** PIV ** //
/* 57 */ { .fid = EF_PIV_ADMIN_DATA, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 58 */ { .fid = EF_PIV_ATTESTATION, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 59 */ { .fid = EF_PIV_MSCMAP, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 60 */ { .fid = EF_PIV_MSROOTS1, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 61 */ { .fid = EF_PIV_MSROOTS2, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 62 */ { .fid = EF_PIV_MSROOTS3, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 63 */ { .fid = EF_PIV_MSROOTS4, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 64 */ { .fid = EF_PIV_MSROOTS5, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 65 */ { .fid = EF_PIV_KEY_AUTHENTICATION, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 66 */ { .fid = EF_PIV_KEY_CARDMGM, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 67 */ { .fid = EF_PIV_KEY_SIGNATURE, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 68 */ { .fid = EF_PIV_KEY_KEYMGM, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 69 */ { .fid = EF_PIV_KEY_CARDAUTH, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 70 */ { .fid = EF_PIV_KEY_RETIRED1, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 71 */ { .fid = EF_PIV_KEY_RETIRED2, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 72 */ { .fid = EF_PIV_KEY_RETIRED3, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 73 */ { .fid = EF_PIV_KEY_RETIRED4, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 74 */ { .fid = EF_PIV_KEY_RETIRED5, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 75 */ { .fid = EF_PIV_KEY_RETIRED6, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 76 */ { .fid = EF_PIV_KEY_RETIRED7, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 77 */ { .fid = EF_PIV_KEY_RETIRED8, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 78 */ { .fid = EF_PIV_KEY_RETIRED9, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 79 */ { .fid = EF_PIV_KEY_RETIRED10, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 80 */ { .fid = EF_PIV_KEY_RETIRED11, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 81 */ { .fid = EF_PIV_KEY_RETIRED12, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 82 */ { .fid = EF_PIV_KEY_RETIRED12, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 83 */ { .fid = EF_PIV_KEY_RETIRED13, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 84 */ { .fid = EF_PIV_KEY_RETIRED14, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 85 */ { .fid = EF_PIV_KEY_RETIRED15, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 86 */ { .fid = EF_PIV_KEY_RETIRED16, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 87 */ { .fid = EF_PIV_KEY_RETIRED17, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 88 */ { .fid = EF_PIV_KEY_RETIRED18, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 89 */ { .fid = EF_PIV_KEY_RETIRED19, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 90 */ { .fid = EF_PIV_KEY_RETIRED20, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 91 */ { .fid = EF_PIV_KEY_ATTESTATION, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 92 */ { .fid = EF_PIV_CAPABILITY, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 93 */ { .fid = EF_PIV_CHUID, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 94 */ { .fid = EF_PIV_AUTHENTICATION, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 95 */ { .fid = EF_PIV_FINGERPRINTS, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 96 */ { .fid = EF_PIV_SECURITY, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 97 */ { .fid = EF_PIV_FACIAL, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 98 */ { .fid = EF_PIV_PRINTED, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 99 */ { .fid = EF_PIV_SIGNATURE, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 100 */ { .fid = EF_PIV_KEY_MANAGEMENT, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 101 */ { .fid = EF_PIV_CARD_AUTH, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 102 */ { .fid = EF_PIV_DISCOVERY, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) piv_parse_discovery,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 103 */ { .fid = EF_PIV_KEY_HISTORY, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 104 */ { .fid = EF_PIV_IRIS, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 105 */ { .fid = EF_PIV_BITGT, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 106 */ { .fid = EF_PIV_SM_SIGNER, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 107 */ { .fid = EF_PIV_PC_REF_DATA, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 108 */ { .fid = EF_PIV_RETIRED1, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 109 */ { .fid = EF_PIV_RETIRED2, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 110 */ { .fid = EF_PIV_RETIRED3, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 111 */ { .fid = EF_PIV_RETIRED4, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 112 */ { .fid = EF_PIV_RETIRED5, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 113 */ { .fid = EF_PIV_RETIRED6, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 114 */ { .fid = EF_PIV_RETIRED7, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 115 */ { .fid = EF_PIV_RETIRED8, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 116 */ { .fid = EF_PIV_RETIRED9, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 117 */ { .fid = EF_PIV_RETIRED10, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 118 */ { .fid = EF_PIV_RETIRED11, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 119 */ { .fid = EF_PIV_RETIRED12, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 120 */ { .fid = EF_PIV_RETIRED13, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 121 */ { .fid = EF_PIV_RETIRED14, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 122 */ { .fid = EF_PIV_RETIRED15, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 123 */ { .fid = EF_PIV_RETIRED16, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 124 */ { .fid = EF_PIV_RETIRED17, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 125 */ { .fid = EF_PIV_RETIRED18, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 126 */ { .fid = EF_PIV_RETIRED19, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 127 */ { .fid = EF_PIV_RETIRED20, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 128 */ { .fid = EF_PIV_PIN, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 129 */ { .fid = EF_PIV_PUK, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 130 */ { .fid = EF_META, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
/* 57 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
/* 131 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 58 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL,
/* 132 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL,
.ef_structure = 0, .acl = ACL_NONE } //end
};

View File

@@ -81,4 +81,83 @@
#define EF_EXLEN_INFO 0x7f66 //C
#define EF_GFM 0x7f74 //C
// PIV
#define EF_PIV_PIN 0x1184
#define EF_PIV_PUK 0x1185
#define EF_PIV_ADMIN_DATA 0xff00
#define EF_PIV_ATTESTATION 0xff01
#define EF_PIV_MSCMAP 0xff10
#define EF_PIV_MSROOTS1 0xff11
#define EF_PIV_MSROOTS2 0xff12
#define EF_PIV_MSROOTS3 0xff13
#define EF_PIV_MSROOTS4 0xff14
#define EF_PIV_MSROOTS5 0xff15
#define EF_PIV_KEY_AUTHENTICATION 0x009a
#define EF_PIV_KEY_CARDMGM 0x009b
#define EF_PIV_KEY_SIGNATURE 0x009c
#define EF_PIV_KEY_KEYMGM 0x009d
#define EF_PIV_KEY_CARDAUTH 0x009e
#define EF_PIV_KEY_RETIRED1 0x0082
#define EF_PIV_KEY_RETIRED2 0x0083
#define EF_PIV_KEY_RETIRED3 0x0084
#define EF_PIV_KEY_RETIRED4 0x0085
#define EF_PIV_KEY_RETIRED5 0x0086
#define EF_PIV_KEY_RETIRED6 0x0087
#define EF_PIV_KEY_RETIRED7 0x0088
#define EF_PIV_KEY_RETIRED8 0x0089
#define EF_PIV_KEY_RETIRED9 0x008a
#define EF_PIV_KEY_RETIRED10 0x008b
#define EF_PIV_KEY_RETIRED11 0x008c
#define EF_PIV_KEY_RETIRED12 0x008d
#define EF_PIV_KEY_RETIRED13 0x008e
#define EF_PIV_KEY_RETIRED14 0x008f
#define EF_PIV_KEY_RETIRED15 0x0090
#define EF_PIV_KEY_RETIRED16 0x0091
#define EF_PIV_KEY_RETIRED17 0x0092
#define EF_PIV_KEY_RETIRED18 0x0096 // It's 0x9e but assigned to EF_SIG_COUNT
#define EF_PIV_KEY_RETIRED19 0x0094
#define EF_PIV_KEY_RETIRED20 0x0095
#define EF_PIV_KEY_ATTESTATION 0x00fb // It's 0xf9 but assigned to EF_KDF
#define EF_PIV_CAPABILITY 0xc107
#define EF_PIV_CHUID 0xc102
#define EF_PIV_AUTHENTICATION 0xc105 /* cert for 9a key */
#define EF_PIV_FINGERPRINTS 0xc103
#define EF_PIV_SECURITY 0xc106
#define EF_PIV_FACIAL 0xc108
#define EF_PIV_PRINTED 0xc109
#define EF_PIV_SIGNATURE 0xc10a /* cert for 9c key */
#define EF_PIV_KEY_MANAGEMENT 0xc10b /* cert for 9d key */
#define EF_PIV_CARD_AUTH 0xc101 /* cert for 9e key */
#define EF_PIV_DISCOVERY 0x007e
#define EF_PIV_KEY_HISTORY 0xc10c
#define EF_PIV_IRIS 0xc121
#define EF_PIV_BITGT 0x7f61
#define EF_PIV_SM_SIGNER 0xc122
#define EF_PIV_PC_REF_DATA 0xc123
#define EF_PIV_RETIRED1 0xc10d
#define EF_PIV_RETIRED2 0xc10e
#define EF_PIV_RETIRED3 0xc10f
#define EF_PIV_RETIRED4 0xc110
#define EF_PIV_RETIRED5 0xc111
#define EF_PIV_RETIRED6 0xc112
#define EF_PIV_RETIRED7 0xc113
#define EF_PIV_RETIRED8 0xc114
#define EF_PIV_RETIRED9 0xc115
#define EF_PIV_RETIRED10 0xc116
#define EF_PIV_RETIRED11 0xc117
#define EF_PIV_RETIRED12 0xc118
#define EF_PIV_RETIRED13 0xc119
#define EF_PIV_RETIRED14 0xc11a
#define EF_PIV_RETIRED15 0xc11b
#define EF_PIV_RETIRED16 0xc11c
#define EF_PIV_RETIRED17 0xc11d
#define EF_PIV_RETIRED18 0xc11e
#define EF_PIV_RETIRED19 0xc11f
#define EF_PIV_RETIRED20 0xc120
#endif

View File

@@ -174,8 +174,32 @@ void scan_files() {
memset((char *) ef->data + 12, 0, 4);
#endif
}
if ((ef = search_by_fid(EF_PW1, NULL, SPECIFY_ANY))) {
bool reset_dek = false;
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("DEK is empty\r\n");
const uint8_t def1[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
const uint8_t def3[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
uint8_t def[IV_SIZE + 32 + 32 + 32];
const uint8_t *dek = random_bytes_get(IV_SIZE + 32);
memcpy(def, dek, IV_SIZE + 32);
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
hash_multi(def1, sizeof(def1), session_pw1);
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
memset(session_pw1, 0, sizeof(session_pw1));
hash_multi(def3, sizeof(def3), session_pw3);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32, 32);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
memset(session_pw3, 0, sizeof(session_pw3));
flash_write_data_to_file(ef, def, sizeof(def));
reset_dek = true;
}
}
if ((ef = search_by_fid(EF_PW1, NULL, SPECIFY_ANY))) {
if (!ef->data || reset_dek) {
printf("PW1 is empty. Initializing with default password\r\n");
const uint8_t def[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
uint8_t dhash[33];
@@ -185,7 +209,7 @@ void scan_files() {
}
}
if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) {
if (!ef->data) {
if (!ef->data || reset_dek) {
printf("RC is empty. Initializing with default password\r\n");
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
@@ -196,7 +220,7 @@ void scan_files() {
}
}
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
if (!ef->data) {
if (!ef->data || reset_dek) {
printf("PW3 is empty. Initializing with default password\r\n");
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
@@ -220,28 +244,6 @@ void scan_files() {
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("DEK is empty\r\n");
const uint8_t def1[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
const uint8_t def3[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
uint8_t def[IV_SIZE + 32 + 32 + 32];
const uint8_t *dek = random_bytes_get(IV_SIZE + 32);
memcpy(def, dek, IV_SIZE + 32);
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
hash_multi(def1, sizeof(def1), session_pw1);
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
memset(session_pw1, 0, sizeof(session_pw1));
hash_multi(def3, sizeof(def3), session_pw3);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32, 32);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
memset(session_pw3, 0, sizeof(session_pw3));
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_SIG, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("UIF SIG is empty. Initializing to default\r\n");
@@ -281,8 +283,10 @@ void scan_files() {
low_flash_available();
}
extern bool has_pwpiv;
extern uint8_t session_pwpiv[32];
int load_dek() {
if (!has_pw1 && !has_pw2 && !has_pw3) {
if (!has_pw1 && !has_pw2 && !has_pw3 && !has_pwpiv) {
return CCID_NO_LOGIN;
}
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
@@ -299,6 +303,11 @@ int load_dek() {
memcpy(dek + IV_SIZE, file_get_data(tf) + IV_SIZE + 32 + 32, 32);
r = aes_decrypt_cfb_256(session_pw3, dek, dek + IV_SIZE, 32);
}
else if (has_pwpiv) {
memcpy(dek, file_get_data(tf), IV_SIZE);
memcpy(dek + IV_SIZE, file_get_data(tf) + IV_SIZE + 32 + 32 + 32, 32);
r = aes_decrypt_cfb_256(session_pwpiv, dek, dek + IV_SIZE, 32);
}
if (r != 0) {
return CCID_EXEC_ERROR;
}
@@ -578,14 +587,6 @@ int parse_pw_status(const file_t *f, int mode) {
return res_APDU_size - init_len;
}
#define ALGO_RSA 0x01
#define ALGO_ECDH 0x12
#define ALGO_ECDSA 0x13
#define ALGO_AES 0x70
#define ALGO_AES_128 0x71
#define ALGO_AES_192 0x72
#define ALGO_AES_256 0x74
#define ALGO_RSA_1K 0
#define ALGO_RSA_2k 1
#define ALGO_RSA_3K 2
@@ -849,13 +850,13 @@ int pin_reset_retries(const file_t *pin, bool force) {
if (!pw_status) {
return CCID_ERR_FILE_NOT_FOUND;
}
uint8_t p[7];
memcpy(p, file_get_data(pw_status), 7);
uint8_t retries = p[3 + (pin->fid & 0x3)];
uint8_t p[64];
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
uint8_t retries = p[3 + (pin->fid & 0xf)];
if (retries == 0 && force == false) { //blocked
return CCID_ERR_BLOCKED;
}
p[3 + (pin->fid & 0x3)] = 3;
p[3 + (pin->fid & 0xf)] = 3;
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
low_flash_available();
return r;
@@ -869,19 +870,19 @@ int pin_wrong_retry(const file_t *pin) {
if (!pw_status) {
return CCID_ERR_FILE_NOT_FOUND;
}
uint8_t p[7];
memcpy(p, file_get_data(pw_status), 7);
if (p[3 + (pin->fid & 0x3)] > 0) {
p[3 + (pin->fid & 0x3)] -= 1;
uint8_t p[64];
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
if (p[3 + (pin->fid & 0xf)] > 0) {
p[3 + (pin->fid & 0xf)] -= 1;
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
if (r != CCID_OK) {
return r;
}
low_flash_available();
if (p[3 + (pin->fid & 0x3)] == 0) {
if (p[3 + (pin->fid & 0xf)] == 0) {
return CCID_ERR_BLOCKED;
}
return p[3 + (pin->fid & 0x3)];
return p[3 + (pin->fid & 0xf)];
}
return CCID_ERR_BLOCKED;
}
@@ -972,7 +973,7 @@ static int cmd_verify() {
if (apdu.nc > 0) {
return check_pin(pw, apdu.data, apdu.nc);
}
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0x3));
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0xf));
if (retries == 0) {
return SW_PIN_BLOCKED();
}

View File

@@ -29,4 +29,14 @@
extern bool has_pw1;
extern bool has_pw3;
extern int store_keys(void *key_ctx, int type, uint16_t key_id);
#define ALGO_RSA 0x01
#define ALGO_ECDH 0x12
#define ALGO_ECDSA 0x13
#define ALGO_AES 0x70
#define ALGO_AES_128 0x71
#define ALGO_AES_192 0x72
#define ALGO_AES_256 0x74
#endif

View File

@@ -19,11 +19,27 @@
#include "files.h"
#include "apdu.h"
#include "pico_keys.h"
#include "random.h"
#include "eac.h"
#include "crypto_utils.h"
#include "version.h"
#ifndef ENABLE_EMULATION
#include "pico/unique_id.h"
#endif
#include "asn1.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/rsa.h"
#include "mbedtls/aes.h"
#include "openpgp.h"
extern bool has_pw1;
#define PIV_ALGO_AES128 0x08
#define PIV_ALGO_AES192 0x0a
#define PIV_ALGO_AES256 0x0c
#define PIV_ALGO_RSA1024 0x06
#define PIV_ALGO_RSA2048 0x07
#define PIV_ALGO_ECCP256 0x11
#define PIV_ALGO_ECCP384 0x14
#define PIV_ALGO_X25519 0xE1
uint8_t piv_aid[] = {
5,
@@ -38,10 +54,145 @@ uint8_t mgmt_aid[] = {
0xA0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
};
int piv_process_apdu();
bool has_pwpiv = false;
uint8_t session_pwpiv[32];
int piv_process_apdu();
/*
static int piv_generate_key(uint8_t key_ref, uint8_t algo) {
int r = CCID_OK;
if (algo == PIV_ALGO_AES128 || algo == PIV_ALGO_AES192 || algo == PIV_ALGO_AES256) {
size_t ksize = 0;
if (algo == PIV_ALGO_AES128) {
ksize = 16;
}
else if (algo == PIV_ALGO_AES192) {
ksize = 24;
}
else if (algo == PIV_ALGO_AES256) {
ksize = 32;
}
const uint8_t *key = random_bytes_get(ksize);
r = store_keys((uint8_t *)key, ALGO_AES, key_ref);
}
else if (algo == PIV_ALGO_RSA1024 || algo == PIV_ALGO_RSA2048) {
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa);
int exponent = 65537, nlen = 0;
if (algo == PIV_ALGO_RSA1024) {
nlen = 1024;
}
else if (algo == PIV_ALGO_RSA2048) {
nlen = 2048;
}
r = mbedtls_rsa_gen_key(&rsa, random_gen, NULL, nlen, exponent);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return CCID_EXEC_ERROR;
}
r = store_keys(&rsa, ALGO_RSA, key_ref);
mbedtls_rsa_free(&rsa);
}
else if (algo == PIV_ALGO_ECCP256 || algo == PIV_ALGO_ECCP384 || algo == PIV_ALGO_X25519) {
mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa);
mbedtls_ecp_group_id gid = MBEDTLS_ECP_DP_NONE;
if (algo == PIV_ALGO_ECCP256) {
gid = MBEDTLS_ECP_DP_SECP256R1;
}
else if (algo == PIV_ALGO_ECCP384) {
gid = MBEDTLS_ECP_DP_SECP384R1;
}
else if (algo == PIV_ALGO_X25519) {
gid = MBEDTLS_ECP_DP_CURVE25519;
}
r = mbedtls_ecdsa_genkey(&ecdsa, gid, random_gen, NULL);
if (r != 0) {
mbedtls_ecdsa_free(&ecdsa);
return CCID_EXEC_ERROR;
}
r = store_keys(&ecdsa, ALGO_ECDSA, key_ref);
mbedtls_ecdsa_free(&ecdsa);
}
if (r != CCID_OK) {
return CCID_ERR_NO_MEMORY;
}
uint8_t meta[] = { algo, 0, 0, 1 };
if ((r = meta_add(key_ref, meta, sizeof(meta))) != CCID_OK) {
return r;
}
low_flash_available();
return r;
}
*/
static void scan_files() {
scan_flash();
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_EF);
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
if (file_get_size(ef) == 0) {
printf("PW status is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3, 3, 3 };
flash_write_data_to_file(ef, def, sizeof(def));
}
else if (file_get_size(ef) == 7) {
printf("PW status is older. Initializing to default\r\n");
uint8_t def[9] = { 0 };
memcpy(def, file_get_data(ef), 7);
def[7] = def[8] = 3; // PIV retries
flash_write_data_to_file(ef, def, sizeof(def));
}
}
bool reset_dek = false;
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY)) || true) {
if (file_get_size(ef) == 0 || file_get_size(ef) == IV_SIZE+32*3 || true) {
printf("DEK is empty or older\r\n");
const uint8_t defpin[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
const uint8_t *dek = random_bytes_get(IV_SIZE + 32);
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
if (file_get_size(ef) > 0) {
memcpy(def, file_get_data(ef), file_get_size(ef));
}
else {
memcpy(def, dek, IV_SIZE);
}
memcpy(def + IV_SIZE + 32*3, dek + IV_SIZE, 32);
hash_multi(defpin, sizeof(defpin), session_pwpiv);
aes_encrypt_cfb_256(session_pwpiv, def, def + IV_SIZE + 32*3, 32);
flash_write_data_to_file(ef, def, sizeof(def));
has_pwpiv = true;
uint8_t *key = (uint8_t *)"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08";
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_ANY);
flash_write_data_to_file(ef, key, 24);
uint8_t meta[] = { PIV_ALGO_AES192, 0, 0, 1 };
meta_add(EF_PIV_KEY_CARDMGM, meta, sizeof(meta));
has_pwpiv = false;
memset(session_pwpiv, 0, sizeof(session_pwpiv));
reset_dek = true;
}
}
if ((ef = search_by_fid(EF_PIV_PIN, NULL, SPECIFY_ANY))) {
if (!ef->data || reset_dek) {
printf("PIV PIN is empty. Initializing with default password\r\n");
const uint8_t def[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
uint8_t dhash[33];
dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash + 1);
flash_write_data_to_file(ef, dhash, sizeof(dhash));
}
}
if ((ef = search_by_fid(EF_PIV_PUK, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("PIV PUK is empty. Initializing with default password\r\n");
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
uint8_t dhash[33];
dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash + 1);
flash_write_data_to_file(ef, dhash, sizeof(dhash));
}
}
low_flash_available();
}
void init_piv() {
@@ -111,10 +262,20 @@ static int cmd_select() {
return SW_OK();
}
int piv_parse_discovery(const file_t *ef) {
memcpy(res_APDU, "\x7E\x12\x4F\x0B\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00\x5F\x2F\x02\x40\x10", 20);
res_APDU_size = 20;
return res_APDU_size;
}
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);
#ifndef ENABLE_EMULATION
pico_unique_board_id_t unique_id;
pico_get_unique_board_id(&unique_id);
memcpy(res_APDU, unique_id.id, 4);
#else
memset(res_APDU, 0, 4);
#endif
res_APDU_size = 4;
return SW_OK();
}
@@ -129,10 +290,7 @@ static int cmd_verify() {
return SW_REFERENCE_NOT_FOUND();
}
file_t *pw, *pw_status;
uint16_t fid = 0x0;
if (key_ref == 0x80) {
fid = EF_PW1;
}
uint16_t fid = EF_PIV_PIN;
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
@@ -143,29 +301,199 @@ static int cmd_verify() {
return SW_REFERENCE_NOT_FOUND();
}
if (apdu.nc > 0) {
return check_pin(pw, apdu.data, apdu.nc);
uint16_t ret = check_pin(pw, apdu.data, apdu.nc);
if (ret == 0x9000) {
has_pwpiv = true;
hash_multi(apdu.data, apdu.nc, session_pwpiv);
}
return ret; //SW already set
}
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0x3));
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0xf));
if (retries == 0) {
return SW_PIN_BLOCKED();
}
if ((key_ref == 0x80 && has_pw1)) {
if ((key_ref == 0x80 && has_pwpiv)) {
return SW_OK();
}
return set_res_sw(0x63, 0xc0 | retries);
}
static int cmd_get_data() {
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
return SW_INCORRECT_P1P2();
}
if (apdu.data[0] != 0x5C || (apdu.data[1] & 0x80) || apdu.data[1] >= 4 || apdu.data[1] == 0) {
return SW_WRONG_DATA();
}
uint32_t fid = apdu.data[2];
for (uint8_t lt = 1; lt < apdu.data[1]; lt++) {
fid <<= 8;
fid |= apdu.data[2 + lt];
}
if ((fid & 0xFFFF00) != 0x5FC100 && fid != EF_PIV_BITGT && fid != EF_PIV_DISCOVERY) {
return SW_REFERENCE_NOT_FOUND();
}
file_t *ef = NULL;
if ((ef = search_by_fid((uint16_t)(fid & 0xFFFF), NULL, SPECIFY_EF))) {
uint16_t data_len = 0;
res_APDU_size = 2; // Minimum: TAG+LEN
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
data_len = ((int (*)(const file_t *))(ef->data))((const file_t *) ef);
}
else {
if (ef->data) {
data_len = file_get_size(ef);
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
}
}
if (data_len > 255) {
memmove(res_APDU + res_APDU_size + 2, res_APDU + res_APDU_size, data_len);
}
else if (data_len > 127) {
memmove(res_APDU + res_APDU_size + 1, res_APDU + res_APDU_size, data_len);
}
res_APDU[0] = 0x53;
res_APDU_size = 1 + format_tlv_len(data_len, res_APDU + 1) + data_len;
}
return SW_OK();
}
static int cmd_get_metadata() {
if (P1(apdu) != 0x00) {
return SW_INCORRECT_P1P2();
}
uint8_t *meta = NULL;
int meta_len = 0;
if ((meta_len = meta_find(P2(apdu), &meta)) <= 0) {
return SW_REFERENCE_NOT_FOUND();
}
res_APDU[res_APDU_size++] = 0x1;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = meta[0];
res_APDU[res_APDU_size++] = 0x2;
res_APDU[res_APDU_size++] = 2;
res_APDU[res_APDU_size++] = meta[1];
res_APDU[res_APDU_size++] = meta[2];
res_APDU[res_APDU_size++] = 0x3;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = meta[3];
return SW_OK();
}
uint8_t challenge[16];
bool has_challenge = false;
static int cmd_authenticate() {
uint8_t algo = P1(apdu), key_ref = P2(apdu);
if (apdu.nc == 0) {
return SW_WRONG_LENGTH();
}
if (apdu.data[0] != 0x7C) {
return SW_WRONG_DATA();
}
size_t t7c = 0;
uint8_t *c7c = NULL;
if (!asn1_find_tag(apdu.data, (uint16_t)apdu.nc, 0x7C, &t7c, &c7c) || t7c == 0 || c7c == NULL) {
return SW_WRONG_DATA();
}
size_t t80 = 0, t81 = 0, t82 = 0;
uint8_t *c80 = NULL, *c81 = NULL, *c82 = NULL;
asn1_find_tag(c7c, t7c, 0x80, &t80, &c80);
asn1_find_tag(c7c, t7c, 0x81, &t81, &c81);
asn1_find_tag(c7c, t7c, 0x82, &t82, &c82);
if (c80) {
if (t80 == 0) {
memcpy(challenge, random_bytes_get(sizeof(challenge)), sizeof(challenge));
if (algo == PIV_ALGO_AES128 || algo == PIV_ALGO_AES192 || algo == PIV_ALGO_AES256) {
if (key_ref != EF_PIV_KEY_CARDMGM) {
return SW_INCORRECT_P1P2();
}
file_t *ef_mgm = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_EF);
if (!file_has_data(ef_mgm)) {
return SW_MEMORY_FAILURE();
}
uint16_t mgm_len = file_get_size(ef_mgm);
if ((algo == PIV_ALGO_AES128 && mgm_len != 16) || (algo == PIV_ALGO_AES192 && mgm_len != 24) || (algo == PIV_ALGO_AES256 && mgm_len != 32)) {
return SW_INCORRECT_P1P2();
}
mbedtls_aes_context ctx;
mbedtls_aes_init(&ctx);
int r = mbedtls_aes_setkey_enc(&ctx, file_get_data(ef_mgm), mgm_len * 8);
if (r != 0) {
mbedtls_aes_free(&ctx);
return SW_EXEC_ERROR();
}
res_APDU[res_APDU_size++] = 0x7C;
res_APDU[res_APDU_size++] = 10;
res_APDU[res_APDU_size++] = 0x80;
res_APDU[res_APDU_size++] = 16;
r = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, challenge, res_APDU + res_APDU_size);
res_APDU_size += 16;
mbedtls_aes_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
}
has_challenge = true;
}
else {
if (!has_challenge) {
return SW_COMMAND_NOT_ALLOWED();
}
if (sizeof(challenge) != t80 || memcmp(c80, challenge, t80) != 0) {
return SW_DATA_INVALID();
}
if (!c81 || t81 == 0) {
return SW_INCORRECT_PARAMS();
}
if (key_ref != EF_PIV_KEY_CARDMGM) {
return SW_INCORRECT_P1P2();
}
file_t *ef_mgm = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_EF);
if (!file_has_data(ef_mgm)) {
return SW_MEMORY_FAILURE();
}
uint16_t mgm_len = file_get_size(ef_mgm);
if ((algo == PIV_ALGO_AES128 && mgm_len != 16) || (algo == PIV_ALGO_AES192 && mgm_len != 24) || (algo == PIV_ALGO_AES256 && mgm_len != 32)) {
return SW_INCORRECT_P1P2();
}
mbedtls_aes_context ctx;
mbedtls_aes_init(&ctx);
int r = mbedtls_aes_setkey_enc(&ctx, file_get_data(ef_mgm), mgm_len * 8);
if (r != 0) {
mbedtls_aes_free(&ctx);
return SW_EXEC_ERROR();
}
res_APDU[res_APDU_size++] = 0x7C;
res_APDU[res_APDU_size++] = 10;
res_APDU[res_APDU_size++] = 0x82;
res_APDU[res_APDU_size++] = 16;
r = mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, c81, res_APDU + res_APDU_size);
res_APDU_size += 16;
mbedtls_aes_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
}
}
return SW_OK();
}
#define INS_VERIFY 0x20
#define INS_VERSION 0xFD
#define INS_SELECT 0xA4
#define INS_YK_SERIAL 0xF8
#define INS_VERIFY 0x20
#define INS_GET_DATA 0xCB
#define INS_GET_METADATA 0xF7
#define INS_AUTHENTICATE 0x87
static const cmd_t cmds[] = {
{ INS_VERSION, cmd_version },
{ INS_SELECT, cmd_select },
{ INS_YK_SERIAL, cmd_get_serial },
{ INS_VERIFY, cmd_verify },
{ INS_GET_DATA, cmd_get_data },
{ INS_GET_METADATA, cmd_get_metadata },
{ INS_AUTHENTICATE, cmd_authenticate },
{ 0x00, 0x0 }
};