48 Commits
v1.12 ... v2.0

Author SHA1 Message Date
Pol Henarejos
a2c00863f6 Upgrade to version 2.0.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-05-23 19:22:59 +02:00
Pol Henarejos
b61af665b8 Change size of tag_len() for uint16.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-05-23 18:44:57 +02:00
Pol Henarejos
20387c955e Use latest version of Pico Keys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-05-23 18:40:24 +02:00
Pol Henarejos
0198386734 Merge branch 'piv' 2024-05-23 18:32:26 +02:00
Pol Henarejos
ce6eb6e8e6 Fix overflow when importing data.
Fixes #12.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-05-23 18:32:15 +02:00
Pol Henarejos
e0daea80af Add PIV tests.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-28 01:20:48 +01:00
Pol Henarejos
a9797ae1ba Added x509 extensions to attesting certificates.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 19:12:14 +01:00
Pol Henarejos
877e5c0a5c Fix attestation verification.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 18:50:55 +01:00
Pol Henarejos
f4c3a75d66 Compute public point on load key.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 18:45:23 +01:00
Pol Henarejos
b1e09b7047 Fix fetching some certs.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 18:10:04 +01:00
Pol Henarejos
e8ad4baa70 Fix operation with slot 93.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 15:24:11 +01:00
Pol Henarejos
42f9402f8b Fix key deletion.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 15:18:01 +01:00
Pol Henarejos
c609050b3c Fix keygen in slot 93.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-27 15:11:29 +01:00
Pol Henarejos
1e22908de1 Fix PIN POLICY
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 20:58:38 +01:00
Pol Henarejos
f8974ff183 Add PIN policy check on AUTHENTICATE.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 19:52:47 +01:00
Pol Henarejos
a49aab43d7 Added support for RSA 3072 and RSA 4096 import and fixed RSA signature/decryption.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 19:41:06 +01:00
Pol Henarejos
f20449fee3 Fix RSA signature.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 19:38:17 +01:00
Pol Henarejos
85b6c90d39 Added support for key import.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 13:00:42 +01:00
Pol Henarejos
9fe59a551a Added support for ATTESTATION.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-26 12:13:51 +01:00
Pol Henarejos
ad5e98ce89 Fix PUK change.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-25 13:32:57 +01:00
Pol Henarejos
a5bb1cd721 Add 3DES support.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-25 13:25:40 +01:00
Pol Henarejos
e2bbe927af Only mark MGM if challenge is the same. Otherwise, send OK silently.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-25 12:43:16 +01:00
Pol Henarejos
c35beb5b0e Reset PIN status on select.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-25 11:43:10 +01:00
Pol Henarejos
beabcdd8a6 Add RESET command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-25 11:42:24 +01:00
Pol Henarejos
d45a0bfc20 Fix verify on change pin.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-24 02:19:55 +01:00
Pol Henarejos
61261aa1d6 Add meta data when generatin keypair and returning public key on get metadata.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-24 02:19:39 +01:00
Pol Henarejos
6f1af52510 Add missing EF_PW_RETRIES file.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-24 01:23:58 +01:00
Pol Henarejos
1c10b0186e Added support for SET RETRIES.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-22 20:38:01 +01:00
Pol Henarejos
e0e1b3758e Added support for dynamic number of maximum retries. 3 by default
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-22 20:37:47 +01:00
Pol Henarejos
e3112d5cdf Added support for RESET RETRY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-22 20:14:03 +01:00
Pol Henarejos
13f848dafb Added CHANGE PIN command.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-22 20:07:59 +01:00
Pol Henarejos
36420ef098 Added support for move-key.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-21 23:12:58 +01:00
Pol Henarejos
9de33f8969 Fix RETIRED18 comment.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-21 23:12:45 +01:00
Pol Henarejos
ba941d6cad Fixed chained response in other interfaces.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-21 22:02:13 +01:00
Pol Henarejos
17d476a9e2 Fix crash on PIN change.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-21 22:01:41 +01:00
Pol Henarejos
2e70af60db Add support for SET_MGM_KEY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-21 22:01:09 +01:00
Pol Henarejos
2db451f858 Update test.yml
Add piv branch.
2024-03-21 16:43:21 +01:00
Pol Henarejos
62743bbb3c Fix ECDSA signature encoding.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-20 10:12:16 +01:00
Pol Henarejos
1197389e02 Fix response length encoding.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-20 10:11:03 +01:00
Pol Henarejos
9bcb6c1d7e Fixed chained response.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-20 00:07:14 +01:00
Pol Henarejos
ec08c06196 Added support for PUT DATA.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-20 00:06:42 +01:00
Pol Henarejos
de43604db6 Added support for APDU chaining.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-19 18:55:21 +01:00
Pol Henarejos
2f24c3d9a8 Added support for PIV signature.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-19 17:56:36 +01:00
Pol Henarejos
0b7c8da592 KEK use is optional.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-19 17:56:00 +01:00
Pol Henarejos
d96bbb9b4b Use new asn1 structs.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-14 23:22:19 +01:00
Pol Henarejos
ebec1b1022 Add PIV asymmetric keygen.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-14 23:22:01 +01:00
Pol Henarejos
4cfa2a16bf 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>
2024-03-12 22:04:19 +01:00
Pol Henarejos
817d8b39ec Added first commit of Pico OpenPGP with PIV support.
It shares the PIN of OpenPGP.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-03-06 18:54:30 +01:00
23 changed files with 2102 additions and 131 deletions

View File

@@ -14,10 +14,10 @@ name: "Emulation and test"
on:
workflow_dispatch:
push:
branches: [ "main" ]
branches: [ "main", "piv" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
branches: [ "main", "piv" ]
schedule:
- cron: '23 5 * * 4'

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}

View File

@@ -1 +1 @@
Version=1.12
Version=2.0

View File

@@ -1,7 +1,7 @@
#!/bin/bash
VERSION_MAJOR="1"
VERSION_MINOR="12"
VERSION_MAJOR="2"
VERSION_MINOR="0"
rm -rf release/*
cd build_release

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,236 @@ 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 },
/* 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 },
/* 57 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
/* 132 */ { .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,
/* 133 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
.ef_structure = 0, .acl = ACL_NONE } //end
};

View File

@@ -28,6 +28,7 @@
#define EF_ALGO_PRIV2 0x10c2
#define EF_ALGO_PRIV3 0x10c3
#define EF_PW_PRIV 0x10c4
#define EF_PW_RETRIES 0x10c5
#define EF_PK_SIG 0x10d1
#define EF_PK_DEC 0x10d2
#define EF_PK_AUT 0x10d3
@@ -81,4 +82,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 0x93 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

@@ -22,8 +22,6 @@
#include "random.h"
#include "eac.h"
#include "crypto_utils.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/asn1.h"
#include "asn1.h"
@@ -174,52 +172,7 @@ void scan_files() {
memset((char *) ef->data + 12, 0, 4);
#endif
}
if ((ef = search_by_fid(EF_PW1, NULL, SPECIFY_ANY))) {
if (!ef->data) {
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];
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_RC, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("RC 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));
}
}
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("PW3 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));
}
}
if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("SigCount is empty. Initializing to zero\r\n");
const uint8_t def[3] = { 0 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("PW status is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
bool reset_dek = false;
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("DEK is empty\r\n");
@@ -239,50 +192,105 @@ void scan_files() {
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));
file_put_data(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];
dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash + 1);
file_put_data(ef, dhash, sizeof(dhash));
}
}
if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) {
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 };
uint8_t dhash[33];
dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash + 1);
file_put_data(ef, dhash, sizeof(dhash));
}
}
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
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 };
uint8_t dhash[33];
dhash[0] = sizeof(def);
double_hash_pin(def, sizeof(def), dhash + 1);
file_put_data(ef, dhash, sizeof(dhash));
}
}
if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("SigCount is empty. Initializing to zero\r\n");
const uint8_t def[3] = { 0 };
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("PW status is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3 };
file_put_data(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");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_DEC, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("UIF DEC is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_AUT, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("UIF AUT is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_KDF, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("KDF is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x81, 0x1, 0x0 };
flash_write_data_to_file(ef, def, sizeof(def));
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_SEX, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("Sex is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x30 };
flash_write_data_to_file(ef, def, sizeof(def));
file_put_data(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_ANY))) {
if (!ef->data) {
printf("PW retries is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x1, 3, 3, 3 };
file_put_data(ef, def, sizeof(def));
}
}
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 +307,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;
}
@@ -471,7 +484,7 @@ int inc_sig_count() {
uint32_t counter = (p[0] << 16) | (p[1] << 8) | p[2];
counter++;
uint8_t q[3] = { (counter >> 16) & 0xff, (counter >> 8) & 0xff, counter & 0xff };
int r = flash_write_data_to_file(ef, q, sizeof(q));
int r = file_put_data(ef, q, sizeof(q));
if (r != CCID_OK) {
return CCID_EXEC_ERROR;
}
@@ -485,7 +498,7 @@ int reset_sig_count() {
return CCID_ERR_FILE_NOT_FOUND;
}
uint8_t q[3] = { 0 };
int r = flash_write_data_to_file(ef, q, sizeof(q));
int r = file_put_data(ef, q, sizeof(q));
if (r != CCID_OK) {
return CCID_EXEC_ERROR;
}
@@ -578,14 +591,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
@@ -820,8 +825,10 @@ static int cmd_get_data() {
uint16_t data_len = parse_do(fids, 1);
uint8_t *p = NULL;
uint16_t tg = 0;
size_t tg_len = 0;
if (walk_tlv(res_APDU, data_len, &p, &tg, &tg_len, NULL)) {
uint16_t tg_len = 0;
asn1_ctx_t ctxi;
asn1_ctx_init(res_APDU, data_len, &ctxi);
if (walk_tlv(&ctxi, &p, &tg, &tg_len, NULL)) {
uint8_t dec = 2;
if ((tg & 0x1f) == 0x1f) {
dec++;
@@ -846,17 +853,22 @@ int pin_reset_retries(const file_t *pin, bool force) {
return CCID_ERR_NULL_PARAM;
}
file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!pw_status) {
file_t *pw_retries = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_EF);
if (!pw_status || !pw_retries) {
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)];
if (3 + (pin->fid & 0xf) >= file_get_size(pw_status) || (pin->fid & 0xf) >= file_get_size(pw_retries)) {
return CCID_ERR_MEMORY_FATAL;
}
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;
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
uint8_t max_retries = file_get_data(pw_retries)[(pin->fid & 0xf)];
p[3 + (pin->fid & 0xf)] = max_retries;
int r = file_put_data(pw_status, p, file_get_size(pw_status));
low_flash_available();
return r;
}
@@ -869,19 +881,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;
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
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 = file_put_data(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 +984,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();
}
@@ -1014,21 +1026,21 @@ static int cmd_put_data() {
uint8_t dhash[33];
dhash[0] = apdu.nc;
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
r = flash_write_data_to_file(ef, dhash, sizeof(dhash));
r = file_put_data(ef, dhash, sizeof(dhash));
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
if (!tf) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t def[IV_SIZE + 32 + 32 + 32];
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
memcpy(def, file_get_data(tf), file_get_size(tf));
hash_multi(apdu.data, apdu.nc, session_rc);
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
aes_encrypt_cfb_256(session_rc, def, def + IV_SIZE + 32, 32);
r = flash_write_data_to_file(tf, def, sizeof(def));
r = file_put_data(tf, def, sizeof(def));
}
else {
r = flash_write_data_to_file(ef, apdu.data, apdu.nc);
r = file_put_data(ef, apdu.data, apdu.nc);
}
if (r != CCID_OK) {
return SW_MEMORY_FAILURE();
@@ -1059,13 +1071,13 @@ static int cmd_change_pin() {
uint8_t dhash[33];
dhash[0] = apdu.nc - pin_len;
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
flash_write_data_to_file(pw, dhash, sizeof(dhash));
file_put_data(pw, dhash, sizeof(dhash));
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
if (!tf) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t def[IV_SIZE + 32 + 32 + 32];
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
memcpy(def, file_get_data(tf), file_get_size(tf));
if (P2(apdu) == 0x81) {
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
@@ -1077,7 +1089,7 @@ static int cmd_change_pin() {
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
}
flash_write_data_to_file(tf, def, sizeof(def));
file_put_data(tf, def, sizeof(def));
low_flash_available();
return SW_OK();
}
@@ -1124,17 +1136,17 @@ static int cmd_reset_retry() {
if (!tf) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t def[IV_SIZE + 32 + 32 + 32];
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
memcpy(def, file_get_data(tf), file_get_size(tf));
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
r = flash_write_data_to_file(tf, def, sizeof(def));
r = file_put_data(tf, def, sizeof(def));
uint8_t dhash[33];
dhash[0] = newpin_len;
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
flash_write_data_to_file(pw, dhash, sizeof(dhash));
file_put_data(pw, dhash, sizeof(dhash));
if (pin_reset_retries(pw, true) != CCID_OK) {
return SW_MEMORY_FAILURE();
}
@@ -1144,7 +1156,7 @@ static int cmd_reset_retry() {
return SW_INCORRECT_P1P2();
}
int store_keys(void *key_ctx, int type, uint16_t key_id) {
int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) {
int r, key_size = 0;
uint8_t kdata[4096 / 8]; //worst
@@ -1182,14 +1194,16 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
}
memcpy(kdata, key_ctx, key_size);
}
r = dek_encrypt(kdata, key_size);
if (r != CCID_OK) {
return r;
if (use_kek) {
r = dek_encrypt(kdata, key_size);
if (r != CCID_OK) {
return r;
}
}
//r = aes_encrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size);
//if (r != CCID_OK)
// return r;
r = flash_write_data_to_file(ef, kdata, key_size);
r = file_put_data(ef, kdata, key_size);
if (r != CCID_OK) {
return r;
}
@@ -1197,11 +1211,11 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
return CCID_OK;
}
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) {
int key_size = file_get_size(fkey);
uint8_t kdata[4096 / 8];
memcpy(kdata, file_get_data(fkey), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
if (use_dek && dek_decrypt(kdata, key_size) != 0) {
return CCID_EXEC_ERROR;
}
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
@@ -1231,11 +1245,11 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
return CCID_OK;
}
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_dek) {
int key_size = file_get_size(fkey);
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
memcpy(kdata, file_get_data(fkey), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
if (use_dek && dek_decrypt(kdata, key_size) != 0) {
return CCID_EXEC_ERROR;
}
mbedtls_ecp_group_id gid = kdata[0];
@@ -1244,6 +1258,12 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
mbedtls_ecdsa_free(ctx);
return CCID_EXEC_ERROR;
}
mbedtls_platform_zeroize(kdata, sizeof(kdata));
r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL);
if (r != 0) {
mbedtls_ecdsa_free(ctx);
return CCID_EXEC_ERROR;
}
return CCID_OK;
}
@@ -1376,7 +1396,7 @@ static int cmd_keypair_gen() {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid);
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK) {
@@ -1397,7 +1417,7 @@ static int cmd_keypair_gen() {
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
r = store_keys(&ecdsa, algo[0], fid);
r = store_keys(&ecdsa, algo[0], fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK) {
@@ -1411,7 +1431,7 @@ static int cmd_keypair_gen() {
if (!pbef) {
return SW_REFERENCE_NOT_FOUND();
}
r = flash_write_data_to_file(pbef, res_APDU, res_APDU_size);
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
@@ -1424,7 +1444,7 @@ static int cmd_keypair_gen() {
uint8_t aes_key[32]; //maximum AES key size
uint8_t key_size = 32;
memcpy(aes_key, random_bytes_get(key_size), key_size);
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY);
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY, true);
/* if storing the key fails, we silently continue */
//if (r != CCID_OK)
// return SW_EXEC_ERROR();
@@ -1452,7 +1472,7 @@ int rsa_sign(mbedtls_rsa_context *ctx,
uint8_t *d = (uint8_t *) data, *end = d + data_len, *hsh = NULL;
size_t seq_len = 0, hash_len = 0;
int key_size = ctx->len, r = 0;
mbedtls_md_type_t md = MBEDTLS_MD_SHA256;
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
if (mbedtls_asn1_get_tag(&d, end, &seq_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0) {
mbedtls_asn1_buf mdb;
@@ -1608,7 +1628,7 @@ static int cmd_pso() {
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef);
r = load_private_key_rsa(&ctx, ef, true);
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
@@ -1647,7 +1667,7 @@ static int cmd_pso() {
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
@@ -1777,7 +1797,7 @@ static int cmd_internal_aut() {
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef);
r = load_private_key_rsa(&ctx, ef, true);
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
@@ -1793,7 +1813,7 @@ static int cmd_internal_aut() {
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA) {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
@@ -1840,7 +1860,7 @@ static int cmd_mse() {
return SW_OK();
}
size_t tag_len(uint8_t **data) {
uint16_t tag_len(uint8_t **data) {
size_t len = *(*data)++;
if (len == 0x82) {
len = *(*data)++ << 8;
@@ -1865,7 +1885,7 @@ static int cmd_import_data() {
if (*start++ != 0x4D) {
return SW_WRONG_DATA();
}
size_t tgl = tag_len(&start);
uint16_t tgl = tag_len(&start);
if (*start != 0xB6 && *start != 0xB8 && *start != 0xA4) {
return SW_WRONG_DATA();
}
@@ -1893,7 +1913,8 @@ static int cmd_import_data() {
return SW_WRONG_DATA();
}
tgl = tag_len(&start);
uint8_t *end = start + tgl, len[9] = { 0 }, *p[9] = { 0 };
uint8_t *end = start + tgl, *p[9] = { 0 };
uint16_t len[9] = { 0 };
while (start < end) {
uint8_t tag = *start++;
if ((tag >= 0x91 && tag <= 0x97) || tag == 0x99) {
@@ -1963,7 +1984,7 @@ static int cmd_import_data() {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid);
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK) {
@@ -1996,7 +2017,7 @@ static int cmd_import_data() {
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
r = store_keys(&ecdsa, ALGO_ECDSA, fid);
r = store_keys(&ecdsa, ALGO_ECDSA, fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK) {
@@ -2010,7 +2031,7 @@ static int cmd_import_data() {
if (!pbef) {
return SW_REFERENCE_NOT_FOUND();
}
r = flash_write_data_to_file(pbef, res_APDU, res_APDU_size);
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != CCID_OK) {
return SW_EXEC_ERROR();
}

View File

@@ -25,8 +25,35 @@
#include "pico_keys.h"
#include "apdu.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h"
extern bool has_pw1;
extern bool has_pw3;
extern int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek);
extern void make_rsa_response(mbedtls_rsa_context *rsa);
extern void make_ecdsa_response(mbedtls_ecdsa_context *ecdsa);
extern int ecdsa_sign(mbedtls_ecdsa_context *ctx,
const uint8_t *data,
size_t data_len,
uint8_t *out,
size_t *out_len);
extern int rsa_sign(mbedtls_rsa_context *ctx,
const uint8_t *data,
size_t data_len,
uint8_t *out,
size_t *out_len);
extern int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek);
extern int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_dek);
extern int pin_reset_retries(const file_t *pin, bool force);
#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

1313
src/openpgp/piv.c Normal file

File diff suppressed because it is too large Load Diff

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 0x0507
#define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
#endif

View File

@@ -22,6 +22,20 @@ RUN apt install -y libccid \
cmake \
vsmartcard-vpcd \
libgcrypt-dev \
libssl-dev \
check \
gengetopt \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install pytest pycvc cryptography pyscard
RUN git clone https://github.com/Yubico/yubico-piv-tool
WORKDIR /yubico-piv-tool
RUN git checkout tags/yubico-piv-tool-2.5.1
ADD tests/docker/jammy/yubico-piv-tool.patch /yubico-piv-tool/yubico-piv-tool.patch
RUN git apply yubico-piv-tool.patch
RUN mkdir build
WORKDIR /yubico-piv-tool/build
RUN cmake .. -DENABLE_HARDWARE_TESTS=1
RUN make -j`nproc`
RUN make install
WORKDIR /
RUN ldconfig

View File

@@ -0,0 +1,68 @@
diff --git a/lib/tests/api.c b/lib/tests/api.c
index fb7c1a8..b569ec3 100644
--- a/lib/tests/api.c
+++ b/lib/tests/api.c
@@ -515,7 +515,7 @@ START_TEST(test_pin_policy_always) {
unsigned char rand[128] = {0};
size_t sig_len = sizeof(signature);
- size_t padlen = 256;
+ size_t padlen = 512;
unsigned int enc_len;
unsigned int data_len;
@@ -1009,8 +1009,8 @@ END_TEST
START_TEST(test_pin_cache) {
ykpiv_rc res;
ykpiv_state *local_state;
- unsigned char data[256] = {0};
- unsigned char data_in[256] = {0};
+ unsigned char data[512] = {0};
+ unsigned char data_in[512] = {0};
int len = sizeof(data);
size_t len2 = sizeof(data);
@@ -1028,17 +1028,17 @@ START_TEST(test_pin_cache) {
ck_assert_int_eq(res, YKPIV_OK);
// Verify decryption does not work without auth
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
ck_assert_int_eq(res, YKPIV_AUTHENTICATION_ERROR);
// Verify decryption does work when authed
res = ykpiv_verify_select(g_state, "123456", 6, NULL, true);
ck_assert_int_eq(res, YKPIV_OK);
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
ck_assert_int_eq(res, YKPIV_OK);
// Verify PIN policy allows continuing to decrypt without re-verifying
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
ck_assert_int_eq(res, YKPIV_OK);
// Create a new ykpiv state, connect, and close it.
@@ -1059,7 +1059,7 @@ START_TEST(test_pin_cache) {
//
// Note that you can verify that this fails by rebuilding with
// DISABLE_PIN_CACHE set to 1.
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
ck_assert_int_eq(res, YKPIV_OK);
}
END_TEST
diff --git a/tools/confirm.sh b/tools/confirm.sh
index 81c10ac..4ab15c5 100755
--- a/tools/confirm.sh
+++ b/tools/confirm.sh
@@ -20,7 +20,8 @@ echo "WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WA
echo "******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* *******" >&0
echo >&0
echo -n "Are you SURE you wish to proceed? If so, type 'CONFIRM': " >&0
-
+echo "0"
+exit 0
read CONFIRM
if [[ "x$CONFIRM" != "xCONFIRM" ]]; then
echo "1"

View File

@@ -49,7 +49,7 @@
: ${MBEDTLS_DOCKER_GUEST:=jammy}
DOCKER_IMAGE_TAG="pico-hsm-test:${MBEDTLS_DOCKER_GUEST}"
DOCKER_IMAGE_TAG="pico-openpgp-test:${MBEDTLS_DOCKER_GUEST}"
# Make sure docker is available
if ! which docker > /dev/null; then
@@ -79,7 +79,7 @@ ${DOCKER} image build \
--cache-from=${DOCKER_IMAGE_TAG} \
--network host \
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
tests/docker/${MBEDTLS_DOCKER_GUEST}
-f tests/docker/${MBEDTLS_DOCKER_GUEST}/Dockerfile .
run_in_docker()
{

33
tests/scripts/attestation.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
source ./tests/scripts/func.sh
echo -n " Fetch attestation certificate... "
piv read-cert -sf9 -o sf9.pem
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
for alg in ${algs[*]}; do
for slot in ${slots[*]}; do
echo " Test attestation with ${alg} in slot ${slot}"
echo -n " Keygen... "
gen_and_check $alg $slot && echo -e ".\t${OK}" || exit $?
echo -n " Fetch attesting certificate... "
piv attest -s$slot -o attestation.pem
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
echo -n " OpenSSL verify attestation... "
e=$(openssl verify -CAfile sf9.pem attestation.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q ": OK" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Key deletion... "
delete_key $alg $slot && echo -e ".\t${OK}" || exit $?
done
done
rm -rf cert.pem
rm -rf sf9.pem

6
tests/scripts/cli-test.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
chmod a+x tests/scripts/*.sh
echo "======== CLI Test suite ========"
./tests/scripts/yubico-piv-tool.sh

38
tests/scripts/func.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
OK="\033[32mok\033[0m"
FAIL="\033[31mfail\033[0m"
READER="u"
piv() {
yubico-piv-tool -r${READER} -a$@
}
gen_and_check() {
e=$(piv generate -s$2 -A$1 -opublic.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Successfully generated a new private key" <<< $e && echo -n "." || exit $?
e=$(piv status 2>&1)
e=${e//$'\t'/}
e=${e//$'\n'/}
test $? -eq 0 && echo -n "." || exit $?
grep -q "Slot $2:Algorithm:$1" <<< $e && echo -n "." || exit $?
}
delete_key() {
piv delete-key -s$2 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
piv delete-cert -s$2 > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(piv status 2>&1)
test $? -eq 0 && echo -n "." || exit $?
q=$(grep -q "Slot $2: Algorithm: $1" <<< $e)
test $? -eq 1 && echo -n "." || exit $?
rm -rf public.pem
}
gen_and_delete() {
gen_and_check $1 $2
test $? -eq 0 && echo -n "." || exit $?
delete_key $1 $2
test $? -eq 0 && echo -n "." || exit $?
}

12
tests/scripts/keygen.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
source ./tests/scripts/func.sh
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
for alg in ${algs[*]}; do
for slot in ${slots[*]}; do
echo -n " Test ${alg} in slot ${slot}... "
gen_and_delete ${alg} $slot && echo -e ".\t${OK}" || exit $?
done
done

46
tests/scripts/signatures.sh Executable file
View File

@@ -0,0 +1,46 @@
#!/bin/bash
source ./tests/scripts/func.sh
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
for alg in ${algs[*]}; do
for slot in ${slots[*]}; do
echo " Test signature with ${alg} in slot ${slot}"
echo -n " Keygen... "
gen_and_check $alg $slot && echo -e ".\t${OK}" || exit $?
echo -n " Test request certificate... "
e=$(piv verify -arequest -P123456 -s$slot -S'/CN=bar/OU=test/O=example.com/' -ipublic.pem -ocert.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Successfully verified PIN" <<< $e && echo -n "." || exit $?
grep -q "Successfully generated a certificate request" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " OpenSSL verify request... "
e=$(openssl req -verify -in cert.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q " OK" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Test self-signed certificate... "
e=$(piv verify -aselfsign -P123456 -s$slot -S'/CN=bar/OU=test/O=example.com/' -ipublic.pem -ocert.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Successfully verified PIN" <<< $e && echo -n "." || exit $?
grep -q "Successfully generated a new self signed certificate" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Test signature... "
e=$(piv verify-pin -atest-signature -s$slot -P123456 -icert.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Successful" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " OpenSSL verify cert... "
e=$(openssl verify -CAfile cert.pem cert.pem 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q ": OK" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Key deletion... "
delete_key $alg $slot && echo -e ".\t${OK}" || exit $?
done
done
rm -rf cert.pem

10
tests/scripts/version.sh Executable file
View File

@@ -0,0 +1,10 @@
#!/bin/bash
source ./tests/scripts/func.sh
# Get version
echo -n " Test version... "
e=$(piv version 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "Application version" <<< $e && echo -n "." || exit $?
grep -q " found" <<< $e && echo -e ".\t${OK}" || exit $?

View File

@@ -0,0 +1,17 @@
#!/bin/bash
source ./tests/scripts/func.sh
reset
test $? -eq 0 || exit $?
echo -n " Test PKCS11 tool..."
gen_and_check rsa:2048
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --test -l --pin 648219 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "No errors" <<< $e && echo -n "." || exit $?
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
#e=$(pkcs11-tool --test-ec -l --pin 648219 --id 1 --key-type ec:secp256r1 2>&1)
#test $? -eq 0 && echo -n "." || exit $?
#grep -q "==> OK" <<< $e && echo -e ".\t${OK}" || exit $?

View File

@@ -0,0 +1,30 @@
#!/bin/bash
source ./tests/scripts/func.sh
echo "==== Test version ===="
./tests/scripts/version.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test asymmetric keygen ===="
./tests/scripts/keygen.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test self-signed certificates ===="
./tests/scripts/signatures.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test attestation ===="
./tests/scripts/attestation.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}

View File

@@ -1,7 +1,30 @@
#!/bin/bash -eu
#!/bin/bash
OK="\t\033[32mok\033[0m"
FAIL="\t\033[31mfail\033[0m"
fail() {
echo -e "${FAIL}"
exit 1
}
echo -n "Start PCSC..."
/usr/sbin/pcscd &
sleep 2
rm -rf memory.flash
./build_in_docker/pico_openpgp > /dev/null &
test $? -eq 0 && echo -e "${OK}" || {
echo -e "${FAIL}"
exit 1
}
sleep 1
rm -f memory.flash
echo -n "Start Pico OpenPGP..."
./build_in_docker/pico_openpgp > /dev/null 2>&1 &
test $? -eq 0 && echo -n "." || fail
sleep 1
ATR="3b:da:18:ff:81:b1:fe:75:1f:03:00:31:f5:73:c0:01:60:00:90:00:1c"
e=$(opensc-tool -an 2>&1)
grep -q "${ATR}" <<< $e && echo -n "." || fail
test $? -eq 0 && echo -e "${OK}" || fail
pytest tests -W ignore::DeprecationWarning
./tests/scripts/cli-test.sh