194 Commits

Author SHA1 Message Date
Pol Henarejos
34c35ed36f Upgrade to v3.4
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 20:24:39 +01:00
Pol Henarejos
7aefacd1d3 Upgrade to v3.4.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 19:32:44 +01:00
Pol Henarejos
f11017fd13 Take led driver on build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 19:32:33 +01:00
Pol Henarejos
9f91376bed Use fastest clk for rp2040.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 19:30:47 +01:00
Pol Henarejos
4e96b0ce5a Use all available boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 19:30:39 +01:00
Pol Henarejos
d35e67c790 Autobuild Pico SDK 2.1.1
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 12:17:46 +01:00
Pol Henarejos
a42c387e02 Add support for ESP32-S2 autobuild.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 12:16:27 +01:00
Pol Henarejos
7050e6b19f Upgrade to version 3.2
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-15 11:24:15 +01:00
Pol Henarejos
1015d2f697 Upgrade to v3.2.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-15 10:54:42 +01:00
Pol Henarejos
5629500a22 Fix header project.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-15 10:53:39 +01:00
Pol Henarejos
46d35bd50f Add rollback version 1.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-15 10:53:27 +01:00
Pol Henarejos
abb4d2326c Fix change PIN for RP2350.
Fixes #27.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-08 15:18:59 +01:00
Pol Henarejos
79912339b0 Add OTP for emulation and test.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-08 15:18:40 +01:00
Pol Henarejos
95a4f7201b Move cmd functions to separate files.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-08 11:46:49 +01:00
Pol Henarejos
b1161c4614 Update Pico Keys SDK EdDSA pointer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-08 10:21:35 +01:00
Pol Henarejos
64a2d240d4 Merge branch 'main' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-05 20:01:42 +01:00
Pol Henarejos
eaa8851719 Move Pico Keys SDK pointer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-27 02:54:07 +01:00
Pol Henarejos
fa8026bca2 Increase TinyUSB esp stack size.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-27 02:51:28 +01:00
Pol Henarejos
e63a58a49e Fix nightly build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-27 02:28:29 +01:00
Pol Henarejos
6fc27c97ca Fix bin name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-27 02:21:44 +01:00
Pol Henarejos
7533585540 Add nightly build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-12-27 02:17:59 +01:00
Pol Henarejos
de9f53acd8 Fix RP2350 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-25 23:52:56 +01:00
Pol Henarejos
7f24b9f6b8 Upgrade to version 3.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 21:35:30 +01:00
Pol Henarejos
4971a22a32 Update README.md
Fix headings
2024-11-10 19:01:10 +01:00
Pol Henarejos
3ed463cc97 Upgrade to version 3.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:57:19 +01:00
Pol Henarejos
4e6a9eaa4c Update README
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:56:55 +01:00
Pol Henarejos
79c69a6617 OTP key is used to mask the DEK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:56:46 +01:00
Pol Henarejos
21a9a731aa Upgrade Pico Keys SDK
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:14:24 +01:00
Pol Henarejos
9b2b2e822a Add compiler options for optimized build.s
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:38:39 +01:00
Pol Henarejos
4ba5e04080 Add PICO_PRODUCT.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:37:19 +01:00
Pol Henarejos
2747083672 Upgrade pico keys sdk.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:36:21 +01:00
Pol Henarejos
442caa2716 Fix macos alignment.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-10-01 13:29:25 +02:00
Pol Henarejos
e9f0b1b58c Update autobuild for local and esp32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-10-01 09:33:22 +02:00
Pol Henarejos
1d508f254d Not used
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 20:10:00 +02:00
Pol Henarejos
09af4625a9 Fix indentation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 20:02:06 +02:00
Pol Henarejos
befe99576c Merge branch 'main' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 20:01:54 +02:00
Pol Henarejos
f1f6800b60 Fix ESP32 support.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:42:52 +02:00
Pol Henarejos
20b5084eee Fix build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:42:44 +02:00
Pol Henarejos
57e8d689fc Add sdkdefaults for esp32
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:26:26 +02:00
Pol Henarejos
77299f7047 Add esp32 cmake.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:23:19 +02:00
Pol Henarejos
2fd07a7dc3 Add EDDSA algo.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:22:30 +02:00
Pol Henarejos
6e11171416 Merge branch 'main' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:22:18 +02:00
Pol Henarejos
631ffbe4a7 Update cmake
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:46:04 +02:00
Pol Henarejos
88e19bae35 Update sdk
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:44:08 +02:00
Pol Henarejos
90af0da7a0 Rename
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:43:41 +02:00
Pol Henarejos
cb2d784522 Update modules
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:38:01 +02:00
Pol Henarejos
e0779a49e7 Add error if a non-supported key is attempted to be imported.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:04:34 +02:00
Pol Henarejos
57e7fc38fb Update pico_sdk_import
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-24 00:45:53 +02:00
Pol Henarejos
f301601bcd Upgrade Pico Keys SDK to add support for OTP.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-16 19:41:15 +02:00
Pol Henarejos
3edf9bbf75 Add support for RP2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-30 13:33:56 +02:00
Pol Henarejos
cde8968068 Update to latest Pico Keys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-30 13:25:01 +02:00
Pol Henarejos
c0b23a7cb3 Fix write offset.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-26 00:51:40 +02:00
Pol Henarejos
0322967865 Free x509 cert on finish.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 21:17:15 +02:00
Pol Henarejos
e8c62e5867 Use bullseye for tests.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:58:26 +02:00
Pol Henarejos
57a6458051 Fix unitialized var.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:58:14 +02:00
Pol Henarejos
6780eb3935 Fix select aid to new callback.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:57:56 +02:00
Pol Henarejos
ac33f5a026 Add bullseye dockerfile.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:46:09 +02:00
Pol Henarejos
1051690b79 Add support to ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-20 00:23:22 +02:00
Pol Henarejos
8a5c734c41 Fix TLV when returning the public key in get metadata.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:16:57 +02:00
Pol Henarejos
c09f96e956 Fix return error when missing metadata.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:06:58 +02:00
Pol Henarejos
c28852d0ea Fix return metadata for PIN/PUK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:05:35 +02:00
Pol Henarejos
209cd389e5 Fix returning error code when no object is found on GET DATA.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:49:39 +02:00
Pol Henarejos
10c3389c51 Fix GET METADATA when ref is CARDMGM.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:48:14 +02:00
Pol Henarejos
197bf3c056 Add management support for YKMAN.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:34:10 +02:00
Pol Henarejos
3a4ca80970 Update VERSION to 2.2 2024-07-16 00:31:34 +02:00
Pol Henarejos
6a10405357 Upgrade to version 2.2
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-07-15 15:16:36 +02:00
Pol Henarejos
1434ef2bd2 Fix for mbedtls 3.6
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-07-15 15:16:36 +02:00
Pol Henarejos
11cb855f81 Fix idVendor and idProduct placeholders for Pico Patcher. Fixes #14 and #15
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-07-15 15:16:31 +02:00
Pol Henarejos
5aba16692d Merge pull request #17 from imkuang/fix_pw1-life-status
Fix conditional error resetting has_pw1 variable
2024-07-15 15:12:26 +02:00
Ming Kuang
886bee5ddc Fix conditional error resetting has_pw1 variable
According to OpenPGP 3.4.1 specifications subsection 4.4.1:
PW status Bytes
1st byte: 00 = PW1 (no. 81) only valid for one PSO:CDS command
          01 = PW1 valid for several PSO:CDS commands

Therefore has_pw1 should be reset to false when the first byte
of the PW status is 0 instead of 1.
2024-07-06 22:09:37 +08:00
Pol Henarejos
20e7c93707 Upgrade patch_vidpid for new Pico Keys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-05-30 19:16:50 +02:00
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
Pol Henarejos
21e3ba11c6 Upgrade to version 1.12.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-02-06 14:15:22 +01:00
Pol Henarejos
2f51786121 Added support for nullbits, pololu 3pi, waveshare rp2040 lcd 1.28 and wavezhare rp2040 one.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-02-06 14:12:12 +01:00
Pol Henarejos
0bee85c6aa Add -DVIDPID=<VALUE> to build a project with a known VID/PID. Supported values: NitroHSM, NitroFIDO2, NitroStart, NitroPro, Nitro3, Yubikey5, YubikeyNeo, YubiHSM, Gnuk, GnuPG
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-12-11 18:15:42 +01:00
Pol Henarejos
7f7e94c639 Use new names and selecting aid.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-11-06 15:23:54 +01:00
Pol Henarejos
a083bcdb3f Use new pico-keys-sdk name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-11-06 14:37:29 +01:00
Pol Henarejos
109e97bcff Rename old pico-hsm-sdk to new name pico-keys-sdk.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-11-06 14:37:19 +01:00
Pol Henarejos
08a40e757a Merge branch 'main' into eddsa 2023-09-05 01:14:02 +02:00
Pol Henarejos
e3728bdb51 Update dockerfile.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-05 01:13:52 +02:00
Pol Henarejos
939c7fa7ab Add workflow to eddsa branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-05 01:10:52 +02:00
Pol Henarejos
91bcd9f9cd Fix EdDSA signature return format.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-05 01:04:44 +02:00
Pol Henarejos
865eafb1f3 Fix Curve25519 key import.
For an unknown reason, curve25519 keys are imported in big endian instead of little endian.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-05 00:25:39 +02:00
Pol Henarejos
88f5bbfd58 Added support for Ed25519.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-05 00:18:06 +02:00
Pol Henarejos
e480d57881 Update HSM SDK pointer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-04 17:26:53 +02:00
Pol Henarejos
9ea894b60b Use mbedtls read/write keys wrappers.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-28 01:25:28 +02:00
Pol Henarejos
3ae7af9812 Create FUNDING.yml 2023-05-17 10:23:06 +02:00
Pol Henarejos
b815dc35c8 Fix initializing DEK for pw3.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-05-17 00:04:57 +02:00
Pol Henarejos
f6fa77368b Upgrade pico hsm sdk.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-05-16 09:24:46 +02:00
Pol Henarejos
93bef128ab Update README.md
Added Pico Patcher link.
2023-05-11 20:09:51 +02:00
Pol Henarejos
11fc49052d Fix conditional interface compilation
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-03-04 14:18:33 +01:00
Pol Henarejos
5eb6822bf5 Update code style.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-03-04 14:08:47 +01:00
Pol Henarejos
f2c1e50ffb Fix test pw1_status
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-03-04 14:08:36 +01:00
Pol Henarejos
80ed59f05c Update patch_vidpid for latest HSM SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-03-04 14:07:18 +01:00
Pol Henarejos
73c1bf786d Upgrade to v1.10
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-06 00:03:18 +01:00
Pol Henarejos
02a5695b61 Added missing file.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-05 00:00:47 +01:00
Pol Henarejos
9310e1af55 Use correct branch name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:58:18 +01:00
Pol Henarejos
8399cd47db Wrong branch name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:57:37 +01:00
Pol Henarejos
dddb9f2824 Lets try manual trigger.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:56:56 +01:00
Pol Henarejos
c97dd77404 Update test.yml
Only master branch is used.
2023-02-04 23:49:55 +01:00
Pol Henarejos
94930e5f7d Some fixes in HSM SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:48:04 +01:00
Pol Henarejos
e697e30c6c Add virtual smart card emulation for CD/CI.
On each push, the software is built in a container, run as a virtual smartcard and test it.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:47:49 +01:00
Pol Henarejos
1288d25999 Adding workflow for autobuild.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:46:20 +01:00
Pol Henarejos
51742153d0 Adding checks for platform.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:45:31 +01:00
Pol Henarejos
1863971a1b It can be safely checked.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:45:07 +01:00
Pol Henarejos
3c7df3aa42 Fix checking length in ECDH.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 23:44:55 +01:00
Pol Henarejos
e5871d5791 Fix returning algo attributes for authentication key.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 21:07:10 +01:00
Pol Henarejos
7ccbb0103f Fix computing length of algorithm attributes.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 21:06:33 +01:00
Pol Henarejos
8e03ce28a3 Fix returning signature in some cases.
In some particular cases where signature has a 0 prepended, mpi is written without that which caused variable length signatures. Now it returns the signature whose length is always the same.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 20:28:33 +01:00
Pol Henarejos
b300ed87f3 Fix returning ecdsa response for keys > 512 bits.
In that case, TLV shall contain 81 length.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 20:27:20 +01:00
Pol Henarejos
7b17cc7b49 Public point is now computed when private key is imported.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 19:44:44 +01:00
Pol Henarejos
abf190f767 Tuned returning public key information for ECDSA.
Despite it was not a bug, it seems some ASN.1 readers do not recognize 0x81/0x82 tags when len < 128.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 19:44:00 +01:00
Pol Henarejos
fda29e0e61 Adding verifies.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 01:44:44 +01:00
Pol Henarejos
d9ed002af2 Signature counter is only increased on PSO:SIGN and not for authentication.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 01:31:34 +01:00
Pol Henarejos
e1407636b8 Fix DEK loading when resetting code is used.
If no pw3, on cmd_reset_retry pw1 is changed without providing the original, since it is done via rc. Thus, there is no way to recover DEK. To solve, another ciphered field is added for loading DEK via rc. In case rc is changed (PUT DATA), DEK is reciphered with new rc.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-04 01:23:03 +01:00
Pol Henarejos
d117442825 Adding emulation support.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 23:28:12 +01:00
Pol Henarejos
365acbd68b Fix setting RC.
When setting RC it was not hashed and then it was not recognized.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 20:21:14 +01:00
Pol Henarejos
f6facc1154 When a private key is imported, a public key is generated and stored.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 20:08:26 +01:00
Pol Henarejos
e914d5f576 Identify before running this test.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 19:17:52 +01:00
Pol Henarejos
5e257729a3 Some fixes.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 19:17:42 +01:00
Pol Henarejos
89ed242fcd Fix historical bytes and ext capabilities test.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 17:44:06 +01:00
Pol Henarejos
4a629fe53f Fix returning size of some DO.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 17:27:02 +01:00
Pol Henarejos
22689b3784 Fix returning DO.
If the TLV container contains a single DO, the header is removed.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 17:25:18 +01:00
Pol Henarejos
4f1cd1f2f8 Fix returning sig counter.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:55:32 +01:00
Pol Henarejos
c9ef78b3c9 Fix returning app data.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:52:55 +01:00
Pol Henarejos
6c81fe4b1c Fix test sex.
By default, sex is \x30.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:49:30 +01:00
Pol Henarejos
3fe15c815c Fix returning chunked data.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:47:46 +01:00
Pol Henarejos
cf53fdd903 Adapt select_applet to new call.
Also fixes sex test.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:32:28 +01:00
Pol Henarejos
29b4aec24e Adapting Cmakefile to new HSM SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:32:03 +01:00
Pol Henarejos
0c63c457e7 Upgrading to newer Pico HSM SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-03 16:31:51 +01:00
Pol Henarejos
2c24c348b5 Adding tests for OpenPGP.
All tests are taken from gnuk. Reader is migrated from pyusb to pyscard.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-02-02 23:08:49 +01:00
Pol Henarejos
32868dfc31 Fix signature counter storage.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-01-09 17:33:43 +01:00
Pol Henarejos
303116ffea Fix P1P2 on termination check.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-01-09 17:10:12 +01:00
Pol Henarejos
23824afc1f Fix importing data with TLV length > 0x7f.
Should fix #3.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-29 20:21:47 +01:00
Pol Henarejos
2c5b67597e Moving pointer of HSM SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-28 18:56:16 +01:00
Pol Henarejos
bcefdb3c84 Upgrading patcher to HSM SDK 3.4
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-25 14:26:06 +01:00
Pol Henarejos
685ee2bbd5 Moving pointer to Pico HSM SDK 3.4
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-25 14:25:50 +01:00
Pol Henarejos
6ae2a91e55 More fixes to build tool.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-23 11:09:38 +01:00
Pol Henarejos
2373f21994 Fix build tool.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-23 11:04:12 +01:00
Pol Henarejos
25bddb7230 Upgrading to version 1.8.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-23 11:00:44 +01:00
Pol Henarejos
418fa9c143 Fix patch tool.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-11-23 10:59:08 +01:00
Pol Henarejos
ce9ef47bb2 Using pico_hsm_sdk cmake library.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-08-31 14:18:37 +02:00
Pol Henarejos
603963123b Upgrade pico-hsm-sdk to v3.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-08-31 14:12:55 +02:00
Pol Henarejos
79ce35e944 Fix endianness of vid/pid patcher.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-08-31 14:12:26 +02:00
Pol Henarejos
5ddfa6382b Upgrading to new pico-hsm-sdk module.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-08-30 17:48:44 +02:00
Pol Henarejos
9a99baafca Renaming submodule.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-08-30 17:48:02 +02:00
Pol Henarejos
819fb99646 Update README.md
Added clarifications for AES.
2022-06-06 14:51:04 +02:00
187 changed files with 11585 additions and 1667 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
# These are supported funding model platforms
github: polhenarejos
custom: ["https://www.paypal.me/polhenarejos"]

73
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,73 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '23 5 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
mode: [ 'pico', 'local' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
# - name: Autobuild
# uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- run: |
echo "Run, Build Application using script"
./workflows/autobuild.sh ${{ matrix.mode }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

35
.github/workflows/nightly.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: "Nightly deploy"
on:
schedule:
- cron: '0 2 * * *'
workflow_dispatch:
jobs:
nightly:
name: Deploy nightly
strategy:
fail-fast: false
matrix:
refs: [main]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ matrix.refs }}
submodules: 'recursive'
- name : Build
env:
PICO_SDK_PATH: ../pico-sdk
run: |
./workflows/autobuild.sh pico
./build_pico_openpgp.sh
./workflows/autobuild.sh esp32
- name: Update nightly release
uses: pyTooling/Actions/releaser@main
with:
tag: nightly-${{ matrix.refs }}
rm: true
token: ${{ secrets.GITHUB_TOKEN }}
files: release/*.*

37
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "Emulation and test"
on:
workflow_dispatch:
push:
branches: [ "main", "piv", "eddsa" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main", "piv", "eddsa" ]
schedule:
- cron: '23 5 * * 4'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository and submodules
uses: actions/checkout@v3
with:
submodules: recursive
- name: Build in container
run: ./tests/build-in-docker.sh
- name: Start emulation and test
run: ./tests/run-test-in-docker.sh

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "pico-ccid"] [submodule "pico-keys-sdk"]
path = pico-ccid path = pico-keys-sdk
url = https://github.com/polhenarejos/pico-ccid.git url = https://github.com/polhenarejos/pico-keys-sdk

View File

@@ -1,99 +1,124 @@
# #
# This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). # This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
# Copyright (c) 2022 Pol Henarejos. # Copyright (c) 2022 Pol Henarejos.
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3. # the Free Software Foundation, version 3.
# #
# This program is distributed in the hope that it will be useful, but # This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of # WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details. # General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
include(pico_sdk_import.cmake) if(ESP_PLATFORM)
set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
else()
if(NOT ENABLE_EMULATION)
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
include(pico_sdk_import.cmake)
endif()
project(pico_openpgp C CXX ASM) project(pico_openpgp C CXX ASM)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
pico_sdk_init() if(NOT ENABLE_EMULATION)
pico_sdk_init()
endif()
add_executable(pico_openpgp) if(NOT DEFINED __FOR_CI)
set(__FOR_CI 0)
endif()
if(__FOR_CI)
add_definitions(-D__FOR_CI)
endif()
if (NOT DEFINED USB_VID) add_executable(pico_openpgp)
set(USB_VID 0xFEFF)
endif() endif()
add_definitions(-DUSB_VID=${USB_VID})
if (NOT DEFINED USB_PID)
set(USB_PID 0xFCFD)
endif()
add_definitions(-DUSB_PID=${USB_PID})
configure_file(${CMAKE_CURRENT_LIST_DIR}/pico-ccid/config/mbedtls_config.h ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/include/mbedtls COPYONLY) set(SOURCES ${SOURCES}
target_sources(pico_openpgp PUBLIC
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb/usb.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb/usb_descriptors.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/ccid2040.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/asn1.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/file.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/flash.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/low_flash.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/random.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/neug.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/crypto_utils.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/eac.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/aes.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/management.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/asn1parse.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_select.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/bignum.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_get_data.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cmac.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_verify.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cipher.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_put_data.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cipher_wrap.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_select_data.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/constant_time.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_import_data.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecdsa.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_version.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecdh.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_change_pin.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecp.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_mse.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecp_curves.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_internal_aut.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/md.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_challenge.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/md5.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_activate_file.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/oid.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_terminate_df.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/platform_util.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_pso.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ripemd160.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_keypair_gen.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/rsa.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/cmd_reset_retry.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/rsa_alt_helpers.c ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/do.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha1.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha256.c
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha512.c
)
target_include_directories(pico_openpgp PUBLIC
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs
${CMAKE_CURRENT_LIST_DIR}/src/openpgp
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/include
${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library
)
target_compile_options(pico_openpgp PUBLIC
-Wall
-Werror
) )
pico_add_extra_outputs(pico_openpgp)
#target_compile_definitions(pico_openpgp PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1) set(USB_ITF_CCID 1)
set(USB_ITF_WCID 1)
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
target_link_libraries(pico_openpgp PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc) SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/openpgp/version.h" 1)
if(ESP_PLATFORM)
project(pico_openpgp)
endif()
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/openpgp
)
if(NOT ESP_PLATFORM)
target_sources(pico_openpgp PUBLIC ${SOURCES})
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
target_compile_options(pico_openpgp PUBLIC
-Wall
)
if(NOT MSVC)
target_compile_options(pico_openpgp PUBLIC
-Werror
)
endif()
if(ENABLE_EMULATION)
if(NOT MSVC)
target_compile_options(pico_openpgp PUBLIC
-fdata-sections
-ffunction-sections
)
endif()
if(APPLE)
target_link_options(pico_openpgp PUBLIC
-Wl,-dead_strip
)
elseif(MSVC)
target_compile_options(pico_openpgp PUBLIC
-WX
)
target_link_libraries(pico_openpgp PUBLIC wsock32 ws2_32 Bcrypt)
else()
target_link_options(pico_openpgp PUBLIC
-Wl,--gc-sections
)
endif(APPLE)
target_link_libraries(pico_openpgp PRIVATE pthread m)
else()
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
endif()
endif()

View File

@@ -1,5 +1,5 @@
# Pico OpenPGP # Pico OpenPGP
This project aims at transforming your Raspberry Pico into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card. This project aims at transforming your Raspberry Pico or ESP32 microcontroller into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card.
OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the [**OpenPGP 3.4.1** specifications](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf "**OpenPGP 3.4.1** specifications"), available at [GnuPG](http://gnupg.org "GnuPG"). OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the [**OpenPGP 3.4.1** specifications](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf "**OpenPGP 3.4.1** specifications"), available at [GnuPG](http://gnupg.org "GnuPG").
@@ -26,9 +26,23 @@ Pico OpenPGP has implemented the following features:
- Key Derivation Function (KDF) for PIN. - Key Derivation Function (KDF) for PIN.
- Manage Security Environment (MSE). - Manage Security Environment (MSE).
- DEK for internal safe storage. - DEK for internal safe storage.
- AES key generation.
- AES ciphering and deciphering.
- Cardholder certificates support.
- Secure Boot and Secure Lock in RP2350 and ESP32-S3 MCUs.
- One Time Programming to store the master key that encrypts all resident keys and seeds.
- Rescue interface to allow recovery of the device if it becomes unresponsive or undetectable.
- LED customization with Pico Commissioner.
All these features are compliant with the specification. Therefore, if you detect some behaviour that is not expected or it does not follow the rules of specs, please open an issue. All these features are compliant with the specification. Therefore, if you detect some behaviour that is not expected or it does not follow the rules of specs, please open an issue.
## AES support
There is no known software that supports AES with OpenPGP. Nevertheless, it can be used with customized PKCS11 modules or interfacing with raw APDU packets.
During asymmetric key generation for DEC key, Pico OpenPGP also generates a 32 bits symmetric key for AES operations.
OpenPGP card 3.4 specifications describe the procedure to perform ciphering (encryption and decryption) with AES via PSO:ENCIPHER and PSO:DECIPHER. Both commands are supported by Pico OpenPGP.
### About Gnuk ### About Gnuk
This project was inspired by [Gnuk](https://wiki.debian.org/GNUK "Gnuk"), a same project but focused on STM32 processor family. Despite the initial idea was to port Gnuk to the Raspberry Pico family, the underlaying architecture is widely different (although boh run on ARM). For instance, the Pico has two ARM cores, with an appropiate SDK able to leverage them. Also, Pico has an internal flash storage, which is farly larger compared to STM32 ROM storage. Finally, the Pico has a complete USB interface based on TinyUSB, which difficults to port Gnuk. These are only few examples of the difficulties of porting Gnuk to the Raspberry Pico. This project was inspired by [Gnuk](https://wiki.debian.org/GNUK "Gnuk"), a same project but focused on STM32 processor family. Despite the initial idea was to port Gnuk to the Raspberry Pico family, the underlaying architecture is widely different (although boh run on ARM). For instance, the Pico has two ARM cores, with an appropiate SDK able to leverage them. Also, Pico has an internal flash storage, which is farly larger compared to STM32 ROM storage. Finally, the Pico has a complete USB interface based on TinyUSB, which difficults to port Gnuk. These are only few examples of the difficulties of porting Gnuk to the Raspberry Pico.
@@ -37,38 +51,72 @@ As a consequence, Pico OpenPGP is designed from zero. Well, not strictly from ze
Whilst Gnuk is OpenPGP 2.0 with small set of enhancements, Pico OpenPGP aims at being OpenPGP 3.4 compliant, with new features (not present in Gnuk), such as Manage Security Environment (MSE) or UIF. Whilst Gnuk is OpenPGP 2.0 with small set of enhancements, Pico OpenPGP aims at being OpenPGP 3.4 compliant, with new features (not present in Gnuk), such as Manage Security Environment (MSE) or UIF.
## Security considerations ## Security considerations
All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DEK is used as a 256 bit AES key to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws. All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico using a Device Encyrption Key (DEK). DEK is a 256 bit AES key used to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws.
At the same time, DEK is encrypted with doubled salted and hashed PIN. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided. At the same time, DEK is encrypted with doubled salted and hashed PIN. For RP2350 and ESP32-S3 microcontrollers it is masked by a secure device 32 bytes key. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided.
If the Pico is stolen the contents of private and secret keys cannot be read without the PIN, even if the flash memory is dumped. If the Pico is stolen the contents of private and secret keys cannot be read without the PIN, even if the flash memory is dumped.
## Download ### RP2350 and ESP32-S3
Please, go to the [Release page](https://github.com/polhenarejos/pico-openpgp/releases "Release page")) and download the UF2 file for your board. RP2350 and ESP32-S3 microcontrollers are equipped with advanced security features, including Secure Boot and Secure Lock, ensuring that firmware integrity and authenticity are tightly controlled. Both devices support the storage of the Device Encryption Key (DEK) in an OTP (One-Time Programmable) memory region, making it permanently inaccessible for external access or tampering. This secure, non-volatile region guarantees that critical security keys are embedded into the hardware, preventing unauthorized access and supporting robust defenses against code injection or firmware modification. Together, Secure Boot and Secure Lock enforce firmware authentication, while the DEK in OTP memory solidifies the foundation for secure operations.
Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you are planning to use it with OpenSC or similar, you should modify Info.plist of CCID driver to add these VID/PID or use the VID/PID patcher as follows: `./patch_vidpid.sh VID:PID input_openpgp_file.uf2 output_openpgp_file.uf2` ### Secure Boot
Secure Boot is a security feature that ensures that only trusted firmware, verified through digital signatures, can be loaded onto the device during the boot process. Once enabled, Secure Boot checks every piece of firmware against a cryptographic signature before execution, rejecting any unauthorized or modified code. This prevents malicious firmware from compromising the devices operation and integrity. With Secure Boot activated, only firmware versions signed by a trusted authority, such as the device manufacturer, will be accepted, ensuring the device remains protected from unauthorized software modifications. **This is irreversible. Once enabled, it CANNOT be disabled.**
**IMPORTANT:** For users wishing to develop and compile custom firmware, a private-public key pair is essential. Activating Secure Boot requires users to generate and manage their own unique private-public key pair. The public key from this pair must be embedded into the device to validate all firmware. Firmware will not boot without a proper digital signature from this key pair. This means that users must sign all future firmware versions with their private key and embed the public key in the device to ensure compatibility.
### Secure Lock
Secure Lock builds on Secure Boot by imposing an even stricter security model. Once activated, Secure Lock prevents any further installation of new boot keys, effectively locking the device to only run firmware that is authorized by the device's primary vendor—in this case, Pico Keys. In addition to preventing additional keys, Secure Lock disables debugging interfaces and puts additional safeguards in place to resist tampering and intrusion attempts. This ensures that the device operates exclusively with the original vendors firmware and resists unauthorized access, making it highly secure against external threats. **This is irreversible. Once enabled, it CANNOT be disabled.**
**IMPORTANT:** Activating Secure Lock not only enables Secure Boot but also invalidates all keys except the official Pico Key. This means that only firmware signed by Pico Key will be recognized, and custom code will no longer be allowed. Once enabled, the Pico Key device will run solely on the official firmware available on the website, with no option for generating or compiling new code for the device.
## Download
**If you own an ESP32-S3 board, go to [ESP32 Flasher](https://www.picokeys.com/esp32-flasher/) for flashing your Pico OpenPGP.**
If you own a Raspberry Pico (RP2040 or RP2350), go to [Download page](https://www.picokeys.com/getting-started/), select your vendor and model and download the proper firmware; or go to [Release page](https://www.github.com/polhenarejos/pico-openpgp/releases/) and download the UF2 file for your board.
Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner").
You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own.
## Build Note that the pure-browser option [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") is the most recommended.
## Build for Raspberry Pico
Before building, ensure you have installed the toolchain for the Pico and the Pico SDK is properly located in your drive. Before building, ensure you have installed the toolchain for the Pico and the Pico SDK is properly located in your drive.
```
git clone https://github.com/polhenarejos/pico-openpgp
git submodule update --init --recursive
cd pico-openpgp
mkdir build
cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678
make
```
Note that `PICO_BOARD`, `USB_VID` and `USB_PID` are optional. If not provided, `pico` board and VID/PID `FEFF:FCFD` will be used.
git clone https://github.com/polhenarejos/pico-openpgp Additionally, you can pass the `VIDPID=value` parameter to build the firmware with a known VID/PID. The supported values are:
cd pico-openpgp
mkdir build
cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678
make
Note that PICO_BOARD, USB_VID and USB_PID are optional. If not provided, pico board and VID/PID FEFF:FCFD will be used. - `NitroHSM`
- `NitroFIDO2`
- `NitroStart`
- `NitroPro`
- `Nitro3`
- `Yubikey5`
- `YubikeyNeo`
- `YubiHSM`
- `Gnuk`
- `GnuPG`
After make ends, the binary file pico_openpgp.uf2 will be generated. Put your pico board into loading mode, by pushing BOOTSEL button while pluging on, and copy the UF2 to the new fresh usb mass storage Pico device. Once copied, the pico mass storage will be disconnected automatically and the pico board will reset with the new firmware. A blinking led will indicate the device is ready to work. After running `make`, the binary file `pico_openpgp.uf2` will be generated. To load this onto your Pico board:
1. Put the Pico board into loading mode by holding the `BOOTSEL` button while plugging it in.
2. Copy the `pico_openpgp.uf2` file to the new USB mass storage device that appears.
3. Once the file is copied, the Pico mass storage device will automatically disconnect, and the Pico board will reset with the new firmware.
4. A blinking LED will indicate that the device is ready to work.
## Operation time ## Operation time
### Keypair generation ### Keypair generation
Generating EC keys is almost instant. RSA keypair generation takes some time, specially for 3072 and 4096 bits. Generating EC keys is almost instant. RSA keypair generation takes some time, specially for `3072` and `4096` bits.
### Keypair generation
Generating EC keys is almost instant. RSA keypair generation takes some time, specially for `3072` and `4096` bits.
| RSA key length (bits) | Average time (seconds) | | RSA key length (bits) | Average time (seconds) |
| :---: | :---: | | :---: | :---: |
@@ -109,7 +157,7 @@ While processing, the Pico OpenPGP is busy and cannot receive additional command
## Driver ## Driver
Pico OpenPGP uses the `openpgp` driver provided by [OpenSC](https://github.com/OpenSC/OpenSC/ "OpenSC"). This driver utilizes the standardized PKCS#11 interface to communicate with the user and it can be used with many engines that accept PKCS#11 interface, such as OpenSSL, P11 library or pkcs11-tool. Pico OpenPGP uses the `openpgp` driver provided by [OpenSC](https://github.com/OpenSC/OpenSC/ "OpenSC"). This driver utilizes the standardized PKCS#11 interface to communicate with the user and it can be used with many engines that accept PKCS#11 interface, such as OpenSSL, P11 library or pkcs11-tool.
It also accepts the use of GnuPG programs (`gpg` and `gpg2`) to manipulate the card. For instance, it can be used with the `gpg --edit-card --expert` interface to change the cryptographic keys, generate new keypairs or simply set the cardholder name. It also accepts the use of GnuPG programs (`gpg` and `gpg2`) to manipulate the card. For instance, it can be used with the `gpg --edit-card --expert` interface to change the cryptographic keys, generate new keypairs or simply set the cardholder name.
@@ -118,10 +166,12 @@ Pico OpenPGP relies on PKCS#15 structure to store and manipulate the internal fi
The way to communicate is exactly the same as with other cards, such as OpenPGP or similar. The way to communicate is exactly the same as with other cards, such as OpenPGP or similar.
### Important ### Important
OpenSC relies on PCSC driver, which reads a list (`Info.plist`) that contains a pair of VID/PID of supported readers. In order to be detectable, you must patch the UF2 binary (if you just downloaded from the [Release section](https://github.com/polhenarejos/pico-openpgp/releases "Release section")) or configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization. OpenSC relies on PCSC driver, which reads a list (`Info.plist`) that contains a pair of VID/PID of supported readers. In order to be detectable, you have several options:
- Use the pure-browser online [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") that commissions the Pico Key on-the-fly without external tools.
- Build and configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization.
## Credits ## Credits
Pico OpenPGP uses the following libraries or portion of code: Pico OpenPGP uses the following libraries or portion of code:
- mbedTLS for cryptographic operations. - MbedTLS for cryptographic operations.
- TinyUSB for low level USB procedures. - TinyUSB for low level USB procedures.

View File

@@ -1 +1 @@
Version=1.4 Version=3.4

View File

@@ -1,21 +1,23 @@
#!/bin/bash #!/bin/bash
VERSION_MAJOR="1" VERSION_MAJOR="3"
VERSION_MINOR="6" VERSION_MINOR="4-eddsa1"
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
#if ! [[ -z "${GITHUB_SHA}" ]]; then
# SUFFIX="${SUFFIX}.${GITHUB_SHA}"
#fi
rm -rf release/* rm -rf release/*
mkdir -p build_release
mkdir -p release
cd build_release cd build_release
PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}"
for board in adafruit_feather_rp2040 adafruit_itsybitsy_rp2040 adafruit_qtpy_rp2040 adafruit_trinkey_qt2040 arduino_nano_rp2040_connect melopero_shake_rp2040 pimoroni_interstate75 pimoroni_keybow2040 pimoroni_pga2040 pimoroni_picolipo_4mb pimoroni_picolipo_16mb pimoroni_picosystem pimoroni_plasma2040 pimoroni_tiny2040 pybstick26_rp2040 sparkfun_micromod sparkfun_promicro sparkfun_thingplus vgaboard waveshare_rp2040_lcd_0.96 waveshare_rp2040_plus_4mb waveshare_rp2040_plus_16mb waveshare_rp2040_zero board_dir=${PICO_SDK_PATH}/src/boards/include/boards
for board in "$board_dir"/*
do do
board_name="$(basename -- $board .h)"
rm -rf * rm -rf *
PICO_SDK_PATH=~/Devel/pico/pico-sdk cmake .. -DPICO_BOARD=$board PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name
make -kj20 make -j`nproc`
mv pico_openpgp.uf2 ../release/pico_openpgp_$board-$VERSION_MAJOR.$VERSION_MINOR.uf2 mv pico_openpgp.uf2 ../release/pico_openpgp_$board_name-$SUFFIX.uf2
done done
rm -rf *
PICO_SDK_PATH=~/Devel/pico/pico-sdk cmake ..
make -kj20
mv pico_openpgp.uf2 ../release/pico_openpgp_pico_generic-$VERSION_MAJOR.$VERSION_MINOR.uf2

View File

@@ -1,23 +1,23 @@
#!/bin/bash #!/bin/bash
# #
# This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). # This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
# Copyright (c) 2022 Pol Henarejos. # Copyright (c) 2022 Pol Henarejos.
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3. # the Free Software Foundation, version 3.
# #
# This program is distributed in the hope that it will be useful, but # This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of # WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details. # General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
VERSION_MAJOR="2" #Version of Pico CCID Core VERSION_MAJOR="5" #Version of Pico Keys SDK
VERSION_MINOR="0" VERSION_MINOR="0"
echo "----------------------------" echo "----------------------------"

Submodule pico-ccid deleted from fe53f9a729

1
pico-keys-sdk Submodule

Submodule pico-keys-sdk added at 4120a8c1a6

View File

@@ -18,9 +18,20 @@ if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_P
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif () endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH) if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT) if (PICO_SDK_FETCH_FROM_GIT)
@@ -29,11 +40,22 @@ if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT_PATH) if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif () endif ()
FetchContent_Declare( # GIT_SUBMODULES_RECURSE was added in 3.17
pico_sdk if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk FetchContent_Declare(
GIT_TAG master pico_sdk
) GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
)
else ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
endif ()
if (NOT pico_sdk) if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK") message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk) FetchContent_Populate(pico_sdk)

56
sdkconfig.defaults Normal file
View File

@@ -0,0 +1,56 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
IGNORE_UNKNOWN_FILES_FOR_MANAGED_COMPONENTS=1
CONFIG_TINYUSB=y
CONFIG_TINYUSB_TASK_STACK_SIZE=16384
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="pico-keys-sdk/config/esp32/partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_WL_SECTOR_SIZE_512=y
CONFIG_WL_SECTOR_MODE_PERF=y
COMPILER_OPTIMIZATION="Performance"
CONFIG_MBEDTLS_CMAC_C=y
CONFIG_MBEDTLS_CHACHA20_C=y
CONFIG_MBEDTLS_POLY1305_C=y
CONFIG_MBEDTLS_CHACHAPOLY_C=y
CONFIG_MBEDTLS_HKDF_C=y
CONFIG_MBEDTLS_HARDWARE_ECC=y
CONFIG_MBEDTLS_HARDWARE_GCM=y
CONFIG_MBEDTLS_DES_C=y
# CONFIG_MBEDTLS_HARDWARE_MPI is not set
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_HARDWARE_AES=y
# CONFIG_MBEDTLS_ROM_MD5 is not set
CONFIG_MBEDTLS_SHA512_C=y
CONFIG_MBEDTLS_TLS_DISABLED=y
# CONFIG_MBEDTLS_TLS_ENABLED is not set
# CONFIG_ESP_TLS_USE_DS_PERIPHERAL is not set
# CONFIG_ESP_WIFI_ENABLED is not set
# CONFIG_ESP_WIFI_MBEDTLS_CRYPTO is not set
# CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT is not set
# CONFIG_WPA_MBEDTLS_CRYPTO is not set
# CONFIG_MBEDTLS_PSK_MODES is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_RSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA is not set
# CONFIG_MBEDTLS_SSL_RENEGOTIATION is not set
# CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 is not set
# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set
# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set
# CONFIG_MBEDTLS_SSL_ALPN is not set
# CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS is not set
# CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS is not set
# CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE is not set
# CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA is not set
# CONFIG_ESP_WIFI_ENABLE_WPA3_SAE is not set
# CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA is not set
CONFIG_ESP_COREDUMP_ENABLE_TO_UART=y

View File

@@ -0,0 +1,6 @@
idf_component_register(
SRCS ${SOURCES}
INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb ../../pico-keys-sdk/tinycbor/src
REQUIRES bootloader_support esp_partition esp_tinyusb zorxx__neopixel mbedtls efuse
)
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)

View File

@@ -0,0 +1,22 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_activate_file() {
return SW_OK();
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "random.h"
int cmd_challenge() {
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
if (!rb) {
return SW_WRONG_LENGTH();
}
memcpy(res_APDU, rb, apdu.ne);
res_APDU_size = apdu.ne;
return SW_OK();
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "otp.h"
int cmd_change_pin() {
if (P1(apdu) != 0x0) {
return SW_WRONG_P1P2();
}
uint16_t fid = 0x1000 | P2(apdu);
file_t *pw;
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t pin_len = file_get_data(pw)[0];
uint16_t r = 0;
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
if (otp_key_1) {
for (int i = 0; i < 32; i++) {
dek[IV_SIZE + i] ^= otp_key_1[i];
}
}
r = check_pin(pw, apdu.data, pin_len);
if (r != 0x9000) {
return r;
}
uint8_t dhash[33];
dhash[0] = apdu.nc - pin_len;
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
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 + 32] = {0};
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);
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
}
else if (P2(apdu) == 0x83) {
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw3);
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
}
file_put_data(tf, def, sizeof(def));
low_flash_available();
return SW_OK();
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "asn1.h"
int cmd_get_data() {
if (apdu.nc > 0) {
return SW_WRONG_LENGTH();
}
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
file_t *ef;
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
ef = currentEF;
}
else {
select_file(ef);
}
if (ef->data) {
uint16_t fids[] = { 1, fid };
uint16_t data_len = parse_do(fids, 1);
uint8_t *p = NULL;
uint16_t tg = 0;
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++;
}
if ((res_APDU[dec - 1] & 0xF0) == 0x80) {
dec += (res_APDU[dec - 1] & 0x0F);
}
if (tg_len + dec == data_len) {
memmove(res_APDU, res_APDU + dec, data_len - dec);
data_len -= dec;
res_APDU_size -= dec;
}
}
//if (apdu.ne > data_len)
// apdu.ne = data_len;
}
return SW_OK();
}
int cmd_get_next_data() {
file_t *ef = NULL;
if (apdu.nc > 0) {
return SW_WRONG_LENGTH();
}
if (!currentEF) {
return SW_RECORD_NOT_FOUND();
}
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if ((currentEF->fid & 0x1FF0) != (fid & 0x1FF0)) {
return SW_WRONG_P1P2();
}
fid = currentEF->fid + 1; //curentEF contains private DO. so, we select the next one
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
select_file(ef);
return cmd_get_data();
}

View File

@@ -0,0 +1,213 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#else
#include "common.h"
#endif
#include "openpgp.h"
#include "random.h"
#include "do.h"
uint16_t tag_len(uint8_t **data) {
size_t len = *(*data)++;
if (len == 0x82) {
len = *(*data)++ << 8;
len |= *(*data)++;
}
else if (len == 0x81) {
len = *(*data)++;
}
return len;
}
int cmd_import_data() {
file_t *ef = NULL;
uint16_t fid = 0x0;
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
return SW_WRONG_P1P2();
}
if (apdu.nc < 5) {
return SW_WRONG_LENGTH();
}
uint8_t *start = apdu.data;
if (*start++ != 0x4D) {
return SW_WRONG_DATA();
}
uint16_t tgl = tag_len(&start);
if (*start != 0xB6 && *start != 0xB8 && *start != 0xA4) {
return SW_WRONG_DATA();
}
if (*start == 0xB6) {
fid = EF_PK_SIG;
}
else if (*start == 0xB8) {
fid = EF_PK_DEC;
}
else if (*start == 0xA4) {
fid = EF_PK_AUT;
}
else {
return SW_WRONG_DATA();
}
start++;
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
start += (*start + 1);
if (*start++ != 0x7F || *start++ != 0x48) {
return SW_WRONG_DATA();
}
tgl = tag_len(&start);
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) {
len[tag - 0x91] = tag_len(&start);
}
else {
return SW_WRONG_DATA();
}
}
if (*start++ != 0x5F || *start++ != 0x48) {
return SW_WRONG_DATA();
}
tgl = tag_len(&start);
end = start + tgl;
for (int t = 0; start < end && t < 9; t++) {
if (len[t] > 0) {
p[t] = start;
start += len[t];
}
}
file_t *algo_ef = search_by_fid(fid - 0x0010, NULL, SPECIFY_EF);
if (!algo_ef) {
return SW_REFERENCE_NOT_FOUND();
}
const uint8_t *algo = algorithm_attr_rsa2k + 1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
algo = file_get_data(algo_ef);
algo_len = file_get_size(algo_ef);
}
int r = 0;
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context rsa;
if (p[0] == NULL || len[0] == 0 || p[1] == NULL || len[1] == 0 || p[2] == NULL ||
len[2] == 0) {
return SW_WRONG_DATA();
}
mbedtls_rsa_init(&rsa);
r = mbedtls_mpi_read_binary(&rsa.E, p[0], len[0]);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = mbedtls_mpi_read_binary(&rsa.P, p[1], len[1]);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = mbedtls_mpi_read_binary(&rsa.Q, p[2], len[2]);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = mbedtls_rsa_import(&rsa, NULL, &rsa.P, &rsa.Q, NULL, &rsa.E);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = mbedtls_rsa_complete(&rsa);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = mbedtls_rsa_check_privkey(&rsa);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
else if (algo[0] == ALGO_ECDSA || algo[0] == ALGO_ECDH || algo[0] == ALGO_EDDSA) {
mbedtls_ecp_keypair ecdsa;
if (p[1] == NULL || len[1] == 0) {
return SW_WRONG_DATA();
}
mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo + 1, algo_len - 1);
if (gid == MBEDTLS_ECP_DP_NONE) {
return SW_FUNC_NOT_SUPPORTED();
}
mbedtls_ecp_keypair_init(&ecdsa);
if (gid == MBEDTLS_ECP_DP_CURVE25519) {
mbedtls_ecp_group_load(&ecdsa.grp, gid);
r = mbedtls_mpi_read_binary(&ecdsa.d, p[1], len[1]);
}
else {
r = mbedtls_ecp_read_key(gid, &ecdsa, p[1], len[1]);
}
if (r != 0) {
mbedtls_ecp_keypair_free(&ecdsa);
return SW_EXEC_ERROR();
}
if (ecdsa.grp.id == MBEDTLS_ECP_DP_ED25519) {
r = mbedtls_ecp_point_edwards(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, random_gen, NULL);
}
else {
r = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL);
}
if (r != 0) {
mbedtls_ecp_keypair_free(&ecdsa);
return SW_EXEC_ERROR();
}
r = store_keys(&ecdsa, ALGO_ECDSA, fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecp_keypair_free(&ecdsa);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
else {
return SW_FUNC_NOT_SUPPORTED();
}
if (fid == EF_PK_SIG) {
reset_sig_count();
}
file_t *pbef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
if (!pbef) {
return SW_REFERENCE_NOT_FOUND();
}
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
res_APDU_size = 0; //make_*_response sets a response. we need to overwrite
return SW_OK();
}

View File

@@ -0,0 +1,77 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "do.h"
int cmd_internal_aut() {
if (P1(apdu) != 0x00 || P2(apdu) != 0x00) {
return SW_WRONG_P1P2();
}
if (!has_pw3 && !has_pw2) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
file_t *algo_ef = search_by_fid(algo_aut, NULL, SPECIFY_EF);
if (!algo_ef) {
return SW_REFERENCE_NOT_FOUND();
}
const uint8_t *algo = algorithm_attr_rsa2k + 1;
if (algo_ef && algo_ef->data) {
algo = file_get_data(algo_ef);
}
file_t *ef = search_by_fid(pk_aut, NULL, SPECIFY_EF);
if (!ef) {
return SW_REFERENCE_NOT_FOUND();
}
if (wait_button_pressed(EF_UIF_AUT) == true) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int r = PICOKEY_OK;
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef, true);
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = rsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
mbedtls_rsa_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
}
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
mbedtls_ecp_keypair ctx;
mbedtls_ecp_keypair_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != PICOKEY_OK) {
mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
mbedtls_ecp_keypair_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
}
return SW_OK();
}

View File

@@ -0,0 +1,138 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "do.h"
#include "random.h"
int cmd_keypair_gen() {
if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
}
if (apdu.nc != 2 && apdu.nc != 5) {
return SW_WRONG_LENGTH();
}
if (!has_pw3 && P1(apdu) == 0x80) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
uint16_t fid = 0x0;
int r = PICOKEY_OK;
if (apdu.data[0] == 0xB6) {
fid = EF_PK_SIG;
}
else if (apdu.data[0] == 0xB8) {
fid = EF_PK_DEC;
}
else if (apdu.data[0] == 0xA4) {
fid = EF_PK_AUT;
}
else {
return SW_WRONG_DATA();
}
file_t *algo_ef = search_by_fid(fid - 0x0010, NULL, SPECIFY_EF);
if (!algo_ef) {
return SW_REFERENCE_NOT_FOUND();
}
const uint8_t *algo = algorithm_attr_rsa2k + 1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
algo = file_get_data(algo_ef);
algo_len = file_get_size(algo_ef);
}
if (P1(apdu) == 0x80) { //generate
if (algo[0] == ALGO_RSA) {
int exponent = 65537, nlen = (algo[1] << 8) | algo[2];
printf("KEYPAIR RSA %d\r\n", nlen);
//if (nlen != 2048 && nlen != 4096)
// return SW_FUNC_NOT_SUPPORTED();
mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa);
uint8_t index = 0;
r = mbedtls_rsa_gen_key(&rsa, random_gen, &index, nlen, exponent);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
printf("KEYPAIR ECDSA\r\n");
mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo + 1, algo_len - 1);
if (gid == MBEDTLS_ECP_DP_NONE) {
return SW_FUNC_NOT_SUPPORTED();
}
mbedtls_ecp_keypair ecdsa;
mbedtls_ecp_keypair_init(&ecdsa);
uint8_t index = 0;
r = mbedtls_ecdsa_genkey(&ecdsa, gid, random_gen, &index);
if (r != 0) {
mbedtls_ecp_keypair_free(&ecdsa);
return SW_EXEC_ERROR();
}
r = store_keys(&ecdsa, algo[0], fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecp_keypair_free(&ecdsa);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
else {
return SW_FUNC_NOT_SUPPORTED();
}
file_t *pbef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
if (!pbef) {
return SW_REFERENCE_NOT_FOUND();
}
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
if (fid == EF_PK_SIG) {
reset_sig_count();
}
else if (fid == EF_PK_DEC) {
// OpenPGP does not allow generating AES keys. So, we generate a new one when gen for DEC is called.
// It is a 256 AES key by default.
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, true);
/* if storing the key fails, we silently continue */
//if (r != PICOKEY_OK)
// return SW_EXEC_ERROR();
}
low_flash_available();
return SW_OK();
}
else if (P1(apdu) == 0x81) { //read
file_t *ef = search_by_fid(fid + 3, NULL, SPECIFY_EF);
if (!ef || !ef->data) {
return SW_REFERENCE_NOT_FOUND();
}
res_APDU_size = file_get_size(ef);
memcpy(res_APDU, file_get_data(ef), res_APDU_size);
return SW_OK();
}
return SW_INCORRECT_P1P2();
}

49
src/openpgp/cmd_mse.c Normal file
View File

@@ -0,0 +1,49 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_mse() {
if (P1(apdu) != 0x41 || (P2(apdu) != 0xA4 && P2(apdu) != 0xB8)) {
return SW_WRONG_P1P2();
}
if (apdu.data[0] != 0x83 || apdu.data[1] != 0x1 ||
(apdu.data[2] != 0x2 && apdu.data[2] != 0x3)) {
return SW_WRONG_DATA();
}
if (P2(apdu) == 0xA4) {
if (apdu.data[2] == 0x2) {
algo_dec = EF_ALGO_PRIV2;
pk_dec = EF_PK_DEC;
}
else if (apdu.data[2] == 0x3) {
algo_dec = EF_ALGO_PRIV3;
pk_dec = EF_PK_AUT;
}
}
else if (P2(apdu) == 0xB8) {
if (apdu.data[2] == 0x2) {
algo_aut = EF_ALGO_PRIV2;
pk_aut = EF_PK_DEC;
}
else if (apdu.data[2] == 0x3) {
algo_aut = EF_ALGO_PRIV3;
pk_aut = EF_PK_AUT;
}
}
return SW_OK();
}

213
src/openpgp/cmd_pso.c Normal file
View File

@@ -0,0 +1,213 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#else
#include "common.h"
#endif
#include "openpgp.h"
#include "do.h"
#include "random.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/asn1.h"
int cmd_pso() {
uint16_t algo_fid = 0x0, pk_fid = 0x0;
bool is_aes = false;
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
if (!has_pw3 && !has_pw1) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
algo_fid = EF_ALGO_PRIV1;
pk_fid = EF_PK_SIG;
}
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
if (!has_pw3 && !has_pw2) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
algo_fid = algo_dec;
pk_fid = pk_dec;
}
else {
return SW_INCORRECT_P1P2();
}
file_t *algo_ef = search_by_fid(algo_fid, NULL, SPECIFY_EF);
if (!algo_ef) {
return SW_REFERENCE_NOT_FOUND();
}
const uint8_t *algo = algorithm_attr_rsa2k + 1;
if (algo_ef && algo_ef->data) {
algo = file_get_data(algo_ef);
}
if (apdu.data[0] == 0x2) { //AES PSO?
if (((apdu.nc - 1) % 16 == 0 && P1(apdu) == 0x80 && P2(apdu) == 0x86) ||
(apdu.nc % 16 == 0 && P1(apdu) == 0x86 && P2(apdu) == 0x80)) {
pk_fid = EF_AES_KEY;
is_aes = true;
}
}
file_t *ef = search_by_fid(pk_fid, NULL, SPECIFY_EF);
if (!ef) {
return SW_REFERENCE_NOT_FOUND();
}
if (wait_button_pressed(pk_fid == EF_PK_SIG ? EF_UIF_SIG : EF_UIF_DEC) == true) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int r = PICOKEY_OK;
int key_size = file_get_size(ef);
if (is_aes) {
uint8_t aes_key[32];
r = load_aes_key(aes_key, ef);
if (r != PICOKEY_OK) {
memset(aes_key, 0, sizeof(aes_key));
return SW_EXEC_ERROR();
}
if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher
r = aes_decrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1);
memset(aes_key, 0, sizeof(aes_key));
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
memcpy(res_APDU, apdu.data + 1, apdu.nc - 1);
res_APDU_size = apdu.nc - 1;
}
else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher
r = aes_encrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data, apdu.nc);
memset(aes_key, 0, sizeof(aes_key));
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
res_APDU[0] = 0x2;
memcpy(res_APDU + 1, apdu.data, apdu.nc);
res_APDU_size = apdu.nc + 1;
}
return SW_OK();
}
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef, true);
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
size_t olen = 0;
r = rsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
mbedtls_rsa_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
//apdu.ne = key_size;
inc_sig_count();
}
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
if (apdu.nc < key_size) { //needs padding
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
}
size_t olen = 0;
r = mbedtls_rsa_pkcs1_decrypt(&ctx,
random_gen,
NULL,
&olen,
apdu.data + 1,
res_APDU,
key_size);
mbedtls_rsa_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
}
}
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
mbedtls_ecp_keypair ctx;
mbedtls_ecp_keypair_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != PICOKEY_OK) {
mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen);
mbedtls_ecp_keypair_free(&ctx);
if (r != 0) {
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
inc_sig_count();
}
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
mbedtls_ecdh_context ctx;
uint8_t kdata[67];
uint8_t *data = apdu.data, *end = data + apdu.nc;
size_t len = 0;
if (mbedtls_asn1_get_tag(&data, end, &len, 0xA6) != 0) {
return SW_WRONG_DATA();
}
if (*data++ != 0x7f) {
return SW_WRONG_DATA();
}
if (mbedtls_asn1_get_tag(&data, end, &len,
0x49) != 0 ||
mbedtls_asn1_get_tag(&data, end, &len, 0x86) != 0) {
return SW_WRONG_DATA();
}
//if (len != 2*key_size-1)
// return SW_WRONG_LENGTH();
memcpy(kdata, file_get_data(ef), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR();
}
mbedtls_ecdh_init(&ctx);
mbedtls_ecp_group_id gid = kdata[0];
r = mbedtls_ecdh_setup(&ctx, gid);
if (r != 0) {
mbedtls_ecdh_free(&ctx);
return SW_DATA_INVALID();
}
r = mbedtls_ecp_read_key(gid, (mbedtls_ecdsa_context *)&ctx.ctx.mbed_ecdh, kdata + 1, key_size - 1);
if (r != 0) {
mbedtls_ecdh_free(&ctx);
return SW_DATA_INVALID();
}
r = mbedtls_ecdh_read_public(&ctx, data - 1, len + 1);
if (r != 0) {
mbedtls_ecdh_free(&ctx);
return SW_DATA_INVALID();
}
size_t olen = 0;
r = mbedtls_ecdh_calc_secret(&ctx,
&olen,
res_APDU,
MBEDTLS_ECP_MAX_BYTES,
random_gen,
NULL);
if (r != 0) {
mbedtls_ecdh_free(&ctx);
return SW_EXEC_ERROR();
}
res_APDU_size = olen;
mbedtls_ecdh_free(&ctx);
}
}
return SW_OK();
}

View File

@@ -0,0 +1,74 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_put_data() {
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
file_t *ef;
if (fid == EF_RESET_CODE) {
fid = EF_RC;
}
else if (fid == EF_ALGO_SIG || fid == EF_ALGO_DEC || fid == EF_ALGO_AUT) {
fid |= 0x1000;
}
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
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
ef = currentEF;
}
if (apdu.nc > 0 && (ef->type & FILE_DATA_FLASH)) {
int r = 0;
if (fid == EF_RC) {
has_rc = false;
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
uint8_t dhash[33];
dhash[0] = apdu.nc;
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
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 + 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 = file_put_data(tf, def, sizeof(def));
}
else {
r = file_put_data(ef, apdu.data, apdu.nc);
}
if (r != PICOKEY_OK) {
return SW_MEMORY_FAILURE();
}
low_flash_available();
}
return SW_OK();
}

View File

@@ -0,0 +1,80 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_reset_retry() {
if (P2(apdu) != 0x81) {
return SW_REFERENCE_NOT_FOUND();
}
if (P1(apdu) == 0x0 || P1(apdu) == 0x2) {
int newpin_len = 0;
file_t *pw = NULL;
has_pw1 = false;
if (!(pw = search_by_fid(EF_PW1, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (P1(apdu) == 0x0) {
file_t *rc;
if (!(rc = search_by_fid(EF_RC, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t pin_len = file_get_data(rc)[0];
if (apdu.nc <= pin_len) {
return SW_WRONG_LENGTH();
}
uint16_t r = check_pin(rc, apdu.data, pin_len);
if (r != 0x9000) {
return r;
}
newpin_len = apdu.nc - pin_len;
has_rc = true;
hash_multi(apdu.data, pin_len, session_rc);
}
else if (P1(apdu) == 0x2) {
if (!has_pw3) {
return SW_CONDITIONS_NOT_SATISFIED();
}
newpin_len = apdu.nc;
}
int r = 0;
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
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 + 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 = 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);
file_put_data(pw, dhash, sizeof(dhash));
if (pin_reset_retries(pw, true) != PICOKEY_OK) {
return SW_MEMORY_FAILURE();
}
low_flash_available();
return SW_OK();
}
return SW_INCORRECT_P1P2();
}

86
src/openpgp/cmd_select.c Normal file
View File

@@ -0,0 +1,86 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_select() {
uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu);
file_t *pe = NULL;
uint16_t fid = 0x0;
if (apdu.nc >= 2) {
fid = get_uint16_t_be(apdu.data);
}
if (!pe) {
if (p1 == 0x0) { //Select MF, DF or EF - File identifier or absent
if (apdu.nc == 0) {
pe = (file_t *) MF;
//ac_fini();
}
else if (apdu.nc == 2) {
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
return SW_REFERENCE_NOT_FOUND();
}
}
}
else if (p1 == 0x01) { //Select child DF - DF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
if (apdu.nc != 0) {
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
if (!(pe = search_by_name(apdu.data, apdu.nc))) {
return SW_REFERENCE_NOT_FOUND();
}
if (card_terminated) {
return set_res_sw(0x62, 0x85);
}
}
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
if (!(pe = search_by_path(apdu.data, apdu.nc, MF))) {
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
if (!(pe = search_by_path(apdu.data, apdu.nc, currentDF))) {
return SW_REFERENCE_NOT_FOUND();
}
}
}
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
if ((p2 & 0xfc) == 0x04) {
process_fci(pe, 0);
}
}
else {
return SW_INCORRECT_P1P2();
}
select_file(pe);
return SW_OK();
}

View File

@@ -0,0 +1,54 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_select_data() {
file_t *ef = NULL;
uint16_t fid = 0x0;
if (P2(apdu) != 0x4) {
return SW_WRONG_P1P2();
}
if (apdu.data[0] != 0x60) {
return SW_WRONG_DATA();
}
if (apdu.nc != apdu.data[1] + 2 || apdu.nc < 5) {
return SW_WRONG_LENGTH();
}
if (apdu.data[2] != 0x5C) {
return SW_WRONG_DATA();
}
if (apdu.data[3] == 2) {
fid = (apdu.data[4] << 8) | apdu.data[5];
}
else {
fid = apdu.data[4];
}
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
fid &= ~0x6000; //Now get private DO
fid += P1(apdu);
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
select_file(ef);
return SW_OK();
}

View File

@@ -0,0 +1,37 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_terminate_df() {
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
}
file_t *retries;
if (!(retries = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!has_pw3 && *(file_get_data(retries) + 6) > 0) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if (apdu.nc != 0) {
return SW_WRONG_LENGTH();
}
initialize_flash(true);
scan_files();
return SW_OK();
}

67
src/openpgp/cmd_verify.c Normal file
View File

@@ -0,0 +1,67 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
int cmd_verify() {
uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu);
if (p1 == 0xFF) {
if (apdu.nc != 0) {
return SW_WRONG_DATA();
}
if (p2 == 0x81) {
has_pw1 = false;
}
else if (p2 == 0x82) {
has_pw2 = false;
}
else if (p2 == 0x83) {
has_pw3 = false;
}
return SW_OK();
}
else if (p1 != 0x0 || (p2 & 0x60) != 0x0) {
return SW_WRONG_P1P2();
}
uint16_t fid = 0x1000 | p2;
if (fid == EF_RC && apdu.nc > 0) {
fid = EF_PW1;
}
file_t *pw, *pw_status;
if (!(pw = search_by_fid(fid, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
if (file_get_data(pw)[0] == 0) { //not initialized
return SW_REFERENCE_NOT_FOUND();
}
if (apdu.nc > 0) {
return check_pin(pw, apdu.data, apdu.nc);
}
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0xf));
if (retries == 0) {
return SW_PIN_BLOCKED();
}
if ((p2 == 0x81 && has_pw1) || (p2 == 0x82 && has_pw2) || (p2 == 0x83 && has_pw3)) {
return SW_OK();
}
return set_res_sw(0x63, 0xc0 | retries);
}

26
src/openpgp/cmd_version.c Normal file
View File

@@ -0,0 +1,26 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "version.h"
int cmd_version() {
res_APDU[res_APDU_size++] = PIPGP_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PIPGP_VERSION_MINOR;
res_APDU[res_APDU_size++] = 0x0;
return SW_OK();
}

394
src/openpgp/do.c Normal file
View File

@@ -0,0 +1,394 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "openpgp.h"
#include "asn1.h"
int parse_do(uint16_t *fids, int mode) {
int len = 0;
file_t *ef;
for (int i = 0; i < fids[0]; i++) {
if ((ef = search_by_fid(fids[i + 1], NULL, SPECIFY_EF))) {
uint16_t data_len;
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
data_len = ((int (*)(const file_t *, int))(ef->data))((const file_t *) ef, mode);
}
else {
if (ef->data) {
data_len = file_get_size(ef);
}
else {
data_len = 0;
}
if (mode == 1) {
if (fids[0] > 1 && res_APDU_size > 0) {
if (fids[i + 1] < 0x0100) {
res_APDU[res_APDU_size++] = fids[i + 1] & 0xff;
}
else {
res_APDU[res_APDU_size++] = fids[i + 1] >> 8;
res_APDU[res_APDU_size++] = fids[i + 1] & 0xff;
}
res_APDU_size += format_tlv_len(data_len, res_APDU + res_APDU_size);
}
if (ef->data) {
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
}
res_APDU_size += data_len;
}
}
len += data_len;
}
}
return len;
}
int parse_trium(uint16_t fid, uint8_t num, size_t size) {
for (uint8_t i = 0; i < num; i++) {
file_t *ef;
if ((ef = search_by_fid(fid + i, NULL, SPECIFY_EF)) && ef->data) {
uint16_t data_len = file_get_size(ef);
memcpy(res_APDU + res_APDU_size, file_get_data(ef), data_len);
res_APDU_size += data_len;
}
else {
memset(res_APDU + res_APDU_size, 0, size);
res_APDU_size += size;
}
}
return num * size;
}
int parse_ch_data(const file_t *f, int mode) {
uint16_t fids[] = {
3,
EF_CH_NAME, EF_LANG_PREF, EF_SEX,
};
res_APDU[res_APDU_size++] = EF_CH_DATA & 0xff;
res_APDU[res_APDU_size++] = 0x82;
uint8_t *lp = res_APDU + res_APDU_size;
res_APDU_size += 2;
parse_do(fids, mode);
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
*lp++ = lpdif >> 8;
*lp++ = lpdif & 0xff;
return lpdif + 4;
}
int parse_sec_tpl(const file_t *f, int mode) {
res_APDU[res_APDU_size++] = EF_SEC_TPL & 0xff;
res_APDU[res_APDU_size++] = 5;
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
if (ef && ef->data) {
res_APDU[res_APDU_size++] = EF_SIG_COUNT & 0xff;
res_APDU[res_APDU_size++] = 3;
memcpy(res_APDU + res_APDU_size, file_get_data(ef), 3);
res_APDU_size += 3;
}
return 5 + 2;
}
int parse_ch_cert(const file_t *f, int mode) {
return 0;
}
int parse_fp(const file_t *f, int mode) {
res_APDU[res_APDU_size++] = EF_FP & 0xff;
res_APDU[res_APDU_size++] = 60;
return parse_trium(EF_FP_SIG, 3, 20) + 2;
}
int parse_cafp(const file_t *f, int mode) {
res_APDU[res_APDU_size++] = EF_CA_FP & 0xff;
res_APDU[res_APDU_size++] = 60;
return parse_trium(EF_FP_CA1, 3, 20) + 2;
}
int parse_ts(const file_t *f, int mode) {
res_APDU[res_APDU_size++] = EF_TS_ALL & 0xff;
res_APDU[res_APDU_size++] = 12;
return parse_trium(EF_TS_SIG, 3, 4) + 2;
}
int parse_keyinfo(const file_t *f, int mode) {
int init_len = res_APDU_size;
if (res_APDU_size > 0) {
res_APDU[res_APDU_size++] = EF_KEY_INFO & 0xff;
res_APDU[res_APDU_size++] = 6;
}
file_t *ef = search_by_fid(EF_PK_SIG, NULL, SPECIFY_ANY);
res_APDU[res_APDU_size++] = 0x00;
if (ef && ef->data) {
res_APDU[res_APDU_size++] = 0x01;
}
else {
res_APDU[res_APDU_size++] = 0x00;
}
ef = search_by_fid(EF_PK_DEC, NULL, SPECIFY_ANY);
res_APDU[res_APDU_size++] = 0x01;
if (ef && ef->data) {
res_APDU[res_APDU_size++] = 0x01;
}
else {
res_APDU[res_APDU_size++] = 0x00;
}
ef = search_by_fid(EF_PK_AUT, NULL, SPECIFY_ANY);
res_APDU[res_APDU_size++] = 0x02;
if (ef && ef->data) {
res_APDU[res_APDU_size++] = 0x01;
}
else {
res_APDU[res_APDU_size++] = 0x00;
}
return res_APDU_size - init_len;
}
int parse_pw_status(const file_t *f, int mode) {
file_t *ef;
int init_len = res_APDU_size;
if (res_APDU_size > 0) {
res_APDU[res_APDU_size++] = EF_PW_STATUS & 0xff;
res_APDU[res_APDU_size++] = 7;
}
ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY);
if (ef && ef->data) {
memcpy(res_APDU + res_APDU_size, file_get_data(ef), 7);
res_APDU_size += 7;
}
return res_APDU_size - init_len;
}
#define ALGO_RSA_1K 0
#define ALGO_RSA_2k 1
#define ALGO_RSA_3K 2
#define ALGO_RSA_4K 3
#define ALGO_X448 4
#define ALGO_P256K1 5
#define ALGO_P256R1 6
#define ALGO_P384R1 7
#define ALGO_P521R1 8
#define ALGO_BP256R1 9
#define ALGO_BP384R1 10
#define ALGO_BP512R1 11
#define ALGO_CV22519 12
const uint8_t algorithm_attr_x448[] = {
4,
ALGO_ECDH,
/* OID of X448 */
0x2b, 0x65, 0x6f
};
const uint8_t algorithm_attr_rsa1k[] = {
6,
ALGO_RSA,
0x04, 0x00, /* Length modulus (in bit): 1024 */
0x00, 0x20, /* Length exponent (in bit): 32 */
0x00 /* 0: Acceptable format is: P and Q */
};
const uint8_t algorithm_attr_rsa2k[] = {
6,
ALGO_RSA,
0x08, 0x00, /* Length modulus (in bit): 2048 */
0x00, 0x20, /* Length exponent (in bit): 32 */
0x00 /* 0: Acceptable format is: P and Q */
};
const uint8_t algorithm_attr_rsa3k[] = {
6,
ALGO_RSA,
0x0C, 0x00, /* Length modulus (in bit): 3072 */
0x00, 0x20, /* Length exponent (in bit): 32 */
0x00 /* 0: Acceptable format is: P and Q */
};
const uint8_t algorithm_attr_rsa4k[] = {
6,
ALGO_RSA,
0x10, 0x00, /* Length modulus (in bit): 4096 */
0x00, 0x20, /* Length exponent (in bit): 32 */
0x00 /* 0: Acceptable format is: P and Q */
};
const uint8_t algorithm_attr_p256k1[] = {
6,
ALGO_ECDSA,
0x2b, 0x81, 0x04, 0x00, 0x0a
};
const uint8_t algorithm_attr_p256r1[] = {
9,
ALGO_ECDSA,
0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07
};
const uint8_t algorithm_attr_p384r1[] = {
6,
ALGO_ECDSA,
0x2B, 0x81, 0x04, 0x00, 0x22
};
const uint8_t algorithm_attr_p521r1[] = {
6,
ALGO_ECDSA,
0x2B, 0x81, 0x04, 0x00, 0x23
};
const uint8_t algorithm_attr_bp256r1[] = {
10,
ALGO_ECDSA,
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07
};
const uint8_t algorithm_attr_bp384r1[] = {
10,
ALGO_ECDSA,
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B
};
const uint8_t algorithm_attr_bp512r1[] = {
10,
ALGO_ECDSA,
0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D
};
const uint8_t algorithm_attr_cv25519[] = {
11,
ALGO_ECDH,
0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01
};
const uint8_t algorithm_attr_ed25519[] = {
10,
ALGO_EDDSA,
0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01
};
int parse_algo(const uint8_t *algo, uint16_t tag) {
res_APDU[res_APDU_size++] = tag & 0xff;
memcpy(res_APDU + res_APDU_size, algo, algo[0] + 1);
res_APDU_size += algo[0] + 1;
return algo[0] + 2;
}
int parse_algoinfo(const file_t *f, int mode) {
int datalen = 0;
if (f->fid == EF_ALGO_INFO) {
res_APDU[res_APDU_size++] = EF_ALGO_INFO & 0xff;
res_APDU[res_APDU_size++] = 0x82;
uint8_t *lp = res_APDU + res_APDU_size;
res_APDU_size += 2;
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_SIG);
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_cv25519, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_x448, EF_ALGO_DEC);
datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_rsa3k, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_rsa4k, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_p256k1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_p256r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_p384r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_p521r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_AUT);
datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_AUT);
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
*lp++ = lpdif >> 8;
*lp++ = lpdif & 0xff;
datalen = lpdif + 4;
}
else if (f->fid == EF_ALGO_SIG || f->fid == EF_ALGO_DEC || f->fid == EF_ALGO_AUT) {
uint16_t fid = 0x1000 | f->fid;
file_t *ef;
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF)) || !ef->data) {
datalen += parse_algo(algorithm_attr_rsa2k, f->fid);
}
else {
uint16_t len = file_get_size(ef);
if (res_APDU_size > 0) {
res_APDU[res_APDU_size++] = f->fid & 0xff;
res_APDU[res_APDU_size++] = len & 0xff;
datalen += 2;
}
memcpy(res_APDU + res_APDU_size, file_get_data(ef), len);
res_APDU_size += len;
datalen += len;
}
}
return datalen;
}
int parse_app_data(const file_t *f, int mode) {
uint16_t fids[] = {
6,
EF_FULL_AID, EF_HIST_BYTES, EF_EXLEN_INFO, EF_GFM, EF_DISCRETE_DO, EF_KEY_INFO
};
res_APDU[res_APDU_size++] = EF_APP_DATA & 0xff;
res_APDU[res_APDU_size++] = 0x82;
uint8_t *lp = res_APDU + res_APDU_size;
res_APDU_size += 2;
parse_do(fids, mode);
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
*lp++ = lpdif >> 8;
*lp++ = lpdif & 0xff;
return lpdif + 4;
}
int parse_discrete_do(const file_t *f, int mode) {
uint16_t fids[] = {
11,
EF_EXT_CAP, EF_ALGO_SIG, EF_ALGO_DEC, EF_ALGO_AUT, EF_PW_STATUS, EF_FP, EF_CA_FP, EF_TS_ALL,
EF_UIF_SIG, EF_UIF_DEC, EF_UIF_AUT
};
res_APDU[res_APDU_size++] = EF_DISCRETE_DO & 0xff;
res_APDU[res_APDU_size++] = 0x82;
uint8_t *lp = res_APDU + res_APDU_size;
res_APDU_size += 2;
parse_do(fids, mode);
uint16_t lpdif = res_APDU + res_APDU_size - lp - 2;
*lp++ = lpdif >> 8;
*lp++ = lpdif & 0xff;
return lpdif + 4;
}

29
src/openpgp/do.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern const uint8_t algorithm_attr_p256k1[];
extern const uint8_t algorithm_attr_p256r1[];
extern const uint8_t algorithm_attr_p384r1[];
extern const uint8_t algorithm_attr_p521r1[];
extern const uint8_t algorithm_attr_bp256r1[];
extern const uint8_t algorithm_attr_bp384r1[];
extern const uint8_t algorithm_attr_bp512r1[];
extern const uint8_t algorithm_attr_cv25519[];
extern const uint8_t algorithm_attr_x448[];
extern const uint8_t algorithm_attr_rsa2k[];
extern const uint8_t algorithm_attr_rsa4096[];
extern const uint8_t algorithm_attr_ed25519[];

View File

@@ -1,17 +1,17 @@
/* /*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos. * Copyright (c) 2022 Pol Henarejos.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3. * the Free Software Foundation, version 3.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -20,12 +20,12 @@
extern const uint8_t openpgp_aid[]; extern const uint8_t openpgp_aid[];
extern const uint8_t openpgp_aid_full[]; extern const uint8_t openpgp_aid_full[];
#define ACL_NONE {0xff,0xff,0xff,0xff,0xff,0xff,0xff} #define ACL_NONE { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
#define ACL_ALL {0} #define ACL_ALL { 0 }
#define ACL_RO {0xff,0xff,0xff,0xff,0xff,0xff,0x00} #define ACL_RO { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }
#define ACL_RW {0xff,0xff,0xff,0xff,0x00,0x00,0x00} #define ACL_RW { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 }
#define ACL_R_WP {0xff,0xff,0xff,0xff,0x90,0x90,0x00} #define ACL_R_WP { 0xff, 0xff, 0xff, 0xff, 0x90, 0x90, 0x00 }
#define ACL_WP {0xff,0xff,0xff,0xff,0x90,0x90,0xff} #define ACL_WP { 0xff, 0xff, 0xff, 0xff, 0x90, 0x90, 0xff }
extern int parse_ch_data(const file_t *f, int mode); extern int parse_ch_data(const file_t *f, int mode);
extern int parse_sec_tpl(const file_t *f, int mode); extern int parse_sec_tpl(const file_t *f, int mode);
@@ -39,113 +39,450 @@ extern int parse_algoinfo(const file_t *f, int mode);
extern int parse_app_data(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_discrete_do(const file_t *f, int mode);
extern int parse_pw_status(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[] = { uint8_t historical_bytes[] = {
10, 0, 10, 0,
0x00, 0x00,
0x31, 0x84, /* Full DF name, GET DATA, MF */ 0x31, 0x84, /* Full DF name, GET DATA, MF */
0x73, 0x73,
0x80, 0x01, 0xC0, /* Full DF name */ 0x80, 0x01, 0xC0, /* Full DF name */
/* 1-byte */ /* 1-byte */
/* Command chaining, No extended Lc and Le */ /* Command chaining, No extended Lc and Le */
0x05, 0x05,
0x90, 0x00 /* Status info */ 0x90, 0x00 /* Status info */
}; };
uint8_t extended_capabilities[] = { uint8_t extended_capabilities[] = {
10, 0, 10, 0,
0x77, /* 0x77, /*
* No Secure Messaging supported * No Secure Messaging supported
* GET CHALLENGE supported * GET CHALLENGE supported
* Key import supported * Key import supported
* PW status byte can be put * PW status byte can be put
* No private_use_DO * No private_use_DO
* Algorithm attrs are changable * Algorithm attrs are changable
* ENC/DEC with AES * ENC/DEC with AES
* KDF-DO available * KDF-DO available
*/ */
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */ 0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 128, /* Max size of GET CHALLENGE */ 0x00, 128, /* Max size of GET CHALLENGE */
0x08, 0x00, /* max. length of cardholder certificate (2KiB) */ 0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
0x00, 0xff, 0x00, 0xff,
0x00, 0x1 0x00, 0x1
}; };
uint8_t feature_mngmnt[] = { uint8_t feature_mngmnt[] = {
3, 0, 3, 0,
0x81, 0x01, 0x20, 0x81, 0x01, 0x20,
}; };
uint8_t exlen_info[] = { uint8_t exlen_info[] = {
8,0, 8, 0,
0x2, 0x2, 0x07, 0xff, 0x2, 0x2, 0x07, 0xff,
0x2, 0x2, 0x08, 0x00, 0x2, 0x2, 0x08, 0x00,
}; };
file_t file_entries[] = { file_t file_entries[] = {
/* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = ACL_NONE }, // MF /* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL,
/* 1 */ { .fid = EF_FULL_AID, .parent = 0, .name = openpgp_aid_full, .type = FILE_TYPE_WORKING_EF, .data = (uint8_t *)openpgp_aid_full, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = 0, .acl = ACL_NONE }, // MF
/* 2 */ { .fid = EF_CH_NAME, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 1 */ { .fid = EF_FULL_AID, .parent = 0, .name = openpgp_aid_full,
/* 3 */ { .fid = EF_LOGIN_DATA, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF, .data = (uint8_t *) openpgp_aid_full,
/* 4 */ { .fid = EF_LANG_PREF, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 5 */ { .fid = EF_SEX, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 2 */ { .fid = EF_CH_NAME, .parent = 0, .name = NULL,
/* 6 */ { .fid = EF_URI_URL, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 7 */ { .fid = EF_HIST_BYTES, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = historical_bytes, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 8 */ { .fid = EF_CH_DATA, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_ch_data, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 3 */ { .fid = EF_LOGIN_DATA, .parent = 0, .name = NULL,
/* 9 */ { .fid = EF_SEC_TPL, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_sec_tpl, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 10 */ { .fid = EF_CH_CERT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_ch_cert, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 11 */ { .fid = EF_EXLEN_INFO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = exlen_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 4 */ { .fid = EF_LANG_PREF, .parent = 0, .name = NULL,
/* 12 */ { .fid = EF_GFM, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = feature_mngmnt, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 13 */ { .fid = EF_SIG_COUNT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 14 */ { .fid = EF_EXT_CAP, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = extended_capabilities, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 5 */ { .fid = EF_SEX, .parent = 0, .name = NULL,
/* 15 */ { .fid = EF_ALGO_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_algoinfo, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 16 */ { .fid = EF_ALGO_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_algoinfo, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 17 */ { .fid = EF_ALGO_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_algoinfo, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 6 */ { .fid = EF_URI_URL, .parent = 0, .name = NULL,
/* 18 */ { .fid = EF_PW_STATUS, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_pw_status, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 19 */ { .fid = EF_FP, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_fp, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 20 */ { .fid = EF_FP_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 7 */ { .fid = EF_HIST_BYTES, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
/* 21 */ { .fid = EF_FP_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .data = historical_bytes, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 22 */ { .fid = EF_FP_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 8 */ { .fid = EF_CH_DATA, .parent = 0, .name = NULL,
/* 23 */ { .fid = EF_CA_FP, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_cafp, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_ch_data,
/* 24 */ { .fid = EF_FP_CA1, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 25 */ { .fid = EF_FP_CA2, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 9 */ { .fid = EF_SEC_TPL, .parent = 0, .name = NULL,
/* 26 */ { .fid = EF_FP_CA3, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_sec_tpl,
/* 27 */ { .fid = EF_TS_ALL, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_ts, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 28 */ { .fid = EF_TS_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 10 */ { .fid = EF_CH_CERT, .parent = 0, .name = NULL,
/* 29 */ { .fid = EF_TS_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_ch_cert,
/* 30 */ { .fid = EF_TS_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 31 */ { .fid = EF_RESET_CODE, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 11 */ { .fid = EF_EXLEN_INFO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
/* 32 */ { .fid = EF_UIF_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .data = exlen_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 33 */ { .fid = EF_UIF_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 12 */ { .fid = EF_GFM, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
/* 34 */ { .fid = EF_UIF_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .data = feature_mngmnt, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 35 */ { .fid = EF_KEY_INFO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_keyinfo, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 13 */ { .fid = EF_SIG_COUNT, .parent = 0, .name = NULL,
/* 36 */ { .fid = EF_ALGO_INFO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_algoinfo, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 37 */ { .fid = EF_APP_DATA, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_app_data, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 38 */ { .fid = EF_DISCRETE_DO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *)parse_discrete_do, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, /* 14 */ { .fid = EF_EXT_CAP, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.data = extended_capabilities, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 15 */ { .fid = EF_ALGO_SIG, .parent = 0, .name = NULL,
/* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_algoinfo,
/* 41 */ { .fid = EF_PW3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 42 */ { .fid = EF_ALGO_PRIV1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 16 */ { .fid = EF_ALGO_DEC, .parent = 0, .name = NULL,
/* 43 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_algoinfo,
/* 44 */ { .fid = EF_ALGO_PRIV3, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 45 */ { .fid = EF_PK_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, /* 17 */ { .fid = EF_ALGO_AUT, .parent = 0, .name = NULL,
/* 46 */ { .fid = EF_PK_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_algoinfo,
/* 47 */ { .fid = EF_PK_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 48 */ { .fid = EF_PB_SIG, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 18 */ { .fid = EF_PW_STATUS, .parent = 0, .name = NULL,
/* 49 */ { .fid = EF_PB_DEC, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_pw_status,
/* 50 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 51 */ { .fid = EF_PW_PRIV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, /* 19 */ { .fid = EF_FP, .parent = 0, .name = NULL,
/* 52 */ { .fid = EF_DEK, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_fp,
/* 53 */ { .fid = EF_KDF, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 54 */ { .fid = EF_CH_1, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE }, /* 20 */ { .fid = EF_FP_SIG, .parent = 0, .name = NULL,
/* 55 */ { .fid = EF_CH_2, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 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 }, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 21 */ { .fid = EF_FP_DEC, .parent = 0, .name = NULL,
/* 57 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO }, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
/* 58 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 22 */ { .fid = EF_FP_AUT, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 23 */ { .fid = EF_CA_FP, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_cafp,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 24 */ { .fid = EF_FP_CA1, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 25 */ { .fid = EF_FP_CA2, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 26 */ { .fid = EF_FP_CA3, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 27 */ { .fid = EF_TS_ALL, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_ts,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 28 */ { .fid = EF_TS_SIG, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 29 */ { .fid = EF_TS_DEC, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 30 */ { .fid = EF_TS_AUT, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 31 */ { .fid = EF_RESET_CODE, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 32 */ { .fid = EF_UIF_SIG, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 33 */ { .fid = EF_UIF_DEC, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 34 */ { .fid = EF_UIF_AUT, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 35 */ { .fid = EF_KEY_INFO, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_keyinfo,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 36 */ { .fid = EF_ALGO_INFO, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_algoinfo,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 37 */ { .fid = EF_APP_DATA, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_app_data,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 38 */ { .fid = EF_DISCRETE_DO, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_discrete_do,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 39 */ { .fid = EF_PW1, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 40 */ { .fid = EF_RC, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 41 */ { .fid = EF_PW3, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 42 */ { .fid = EF_ALGO_PRIV1, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 43 */ { .fid = EF_ALGO_PRIV2, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 44 */ { .fid = EF_ALGO_PRIV3, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 45 */ { .fid = EF_PK_SIG, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 46 */ { .fid = EF_PK_DEC, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 47 */ { .fid = EF_PK_AUT, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
/* 48 */ { .fid = EF_PB_SIG, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 49 */ { .fid = EF_PB_DEC, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 50 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 51 */ { .fid = EF_PW_PRIV, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 52 */ { .fid = EF_DEK, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
/* 53 */ { .fid = EF_KDF, .parent = 0, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 54 */ { .fid = EF_CH_1, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
/* 55 */ { .fid = EF_CH_2, .parent = 0, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
/* 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 },
/* 132 */ { .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,
.ef_structure = 0, .acl = ACL_NONE } //end
}; };
const file_t *MF = &file_entries[0]; const file_t *MF = &file_entries[0];
const file_t *file_openpgp = &file_entries[sizeof(file_entries)/sizeof(file_t)-2]; const file_t *file_openpgp = &file_entries[sizeof(file_entries) / sizeof(file_t) - 2];
const file_t *file_last = &file_entries[sizeof(file_entries)/sizeof(file_t)-1]; const file_t *file_last = &file_entries[sizeof(file_entries) / sizeof(file_t) - 1];

View File

@@ -1,17 +1,17 @@
/* /*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos. * Copyright (c) 2022 Pol Henarejos.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3. * the Free Software Foundation, version 3.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -28,6 +28,7 @@
#define EF_ALGO_PRIV2 0x10c2 #define EF_ALGO_PRIV2 0x10c2
#define EF_ALGO_PRIV3 0x10c3 #define EF_ALGO_PRIV3 0x10c3
#define EF_PW_PRIV 0x10c4 #define EF_PW_PRIV 0x10c4
#define EF_PW_RETRIES 0x10c5
#define EF_PK_SIG 0x10d1 #define EF_PK_SIG 0x10d1
#define EF_PK_DEC 0x10d2 #define EF_PK_DEC 0x10d2
#define EF_PK_AUT 0x10d3 #define EF_PK_AUT 0x10d3
@@ -81,4 +82,85 @@
#define EF_EXLEN_INFO 0x7f66 //C #define EF_EXLEN_INFO 0x7f66 //C
#define EF_GFM 0x7f74 //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
#define EF_DEV_CONF 0x1122
#endif #endif

153
src/openpgp/management.c Normal file
View File

@@ -0,0 +1,153 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "apdu.h"
#include "version.h"
#include "files.h"
#include "asn1.h"
#include "management.h"
int man_process_apdu();
int man_unload();
const uint8_t man_aid[] = {
8,
0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
};
extern void init_piv();
int man_select(app_t *a, uint8_t force) {
(void) force;
a->process_apdu = man_process_apdu;
a->unload = man_unload;
sprintf((char *) res_APDU, "%d.%d.0", PIV_VERSION_MAJOR, PIV_VERSION_MINOR);
res_APDU_size = strlen((char *) res_APDU);
apdu.ne = res_APDU_size;
init_piv();
return PICOKEY_OK;
}
INITIALIZER( man_ctor ) {
register_app(man_select, man_aid);
}
int man_unload() {
return PICOKEY_OK;
}
bool cap_supported(uint16_t cap) {
file_t *ef = search_dynamic_file(EF_DEV_CONF);
if (file_has_data(ef)) {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
asn1_ctx_t ctxi;
asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag == TAG_USB_ENABLED) {
uint16_t ecaps = tag_data[0];
if (tag_len == 2) {
ecaps = (tag_data[0] << 8) | tag_data[1];
}
return ecaps & cap;
}
}
}
return true;
}
int man_get_config() {
file_t *ef = search_dynamic_file(EF_DEV_CONF);
res_APDU_size = 0;
res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
res_APDU[res_APDU_size++] = TAG_USB_SUPPORTED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
res_APDU[res_APDU_size++] = TAG_SERIAL;
res_APDU[res_APDU_size++] = 4;
memcpy(res_APDU + res_APDU_size, pico_serial.id, 4);
res_APDU_size += 4;
res_APDU[res_APDU_size++] = TAG_FORM_FACTOR;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x01;
res_APDU[res_APDU_size++] = TAG_VERSION;
res_APDU[res_APDU_size++] = 3;
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
res_APDU[res_APDU_size++] = 0;
res_APDU[res_APDU_size++] = TAG_NFC_SUPPORTED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
if (!file_has_data(ef)) {
res_APDU[res_APDU_size++] = TAG_USB_ENABLED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = FLAG_EJECT;
res_APDU[res_APDU_size++] = TAG_CONFIG_LOCK;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
res_APDU[res_APDU_size++] = TAG_NFC_ENABLED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
}
else {
memcpy(res_APDU + res_APDU_size, file_get_data(ef), file_get_size(ef));
res_APDU_size += file_get_size(ef);
}
res_APDU[0] = res_APDU_size - 1;
return 0;
}
int cmd_read_config() {
man_get_config();
return SW_OK();
}
int cmd_write_config() {
if (apdu.data[0] != apdu.nc - 1) {
return SW_WRONG_DATA();
}
file_t *ef = file_new(EF_DEV_CONF);
file_put_data(ef, apdu.data + 1, apdu.nc - 1);
low_flash_available();
return SW_OK();
}
#define INS_READ_CONFIG 0x1D
#define INS_WRITE_CONFIG 0x1C
static const cmd_t cmds[] = {
{ INS_READ_CONFIG, cmd_read_config },
{ INS_WRITE_CONFIG, cmd_write_config },
{ 0x00, 0x0 }
};
int man_process_apdu() {
if (CLA(apdu) != 0x00) {
return SW_CLA_NOT_SUPPORTED();
}
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
if (cmd->ins == INS(apdu)) {
int r = cmd->cmd_handler();
return r;
}
}
return SW_INS_NOT_SUPPORTED();
}

55
src/openpgp/management.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MANAGEMENT_H_
#define _MANAGEMENT_H_
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#include "pico/stdlib.h"
#endif
#define TAG_USB_SUPPORTED 0x01
#define TAG_SERIAL 0x02
#define TAG_USB_ENABLED 0x03
#define TAG_FORM_FACTOR 0x04
#define TAG_VERSION 0x05
#define TAG_AUTO_EJECT_TIMEOUT 0x06
#define TAG_CHALRESP_TIMEOUT 0x07
#define TAG_DEVICE_FLAGS 0x08
#define TAG_APP_VERSIONS 0x09
#define TAG_CONFIG_LOCK 0x0A
#define TAG_UNLOCK 0x0B
#define TAG_REBOOT 0x0C
#define TAG_NFC_SUPPORTED 0x0D
#define TAG_NFC_ENABLED 0x0E
#define CAP_OTP 0x01
#define CAP_U2F 0x02
#define CAP_FIDO2 0x200
#define CAP_OATH 0x20
#define CAP_PIV 0x10
#define CAP_OPENPGP 0x08
#define CAP_HSMAUTH 0x100
#define FLAG_REMOTE_WAKEUP 0x40
#define FLAG_EJECT 0x80
extern bool cap_supported(uint16_t cap);
extern int man_get_config();
#endif //_MANAGEMENT_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,17 @@
/* /*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos. * Copyright (c) 2022 Pol Henarejos.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3. * the Free Software Foundation, version 3.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -19,12 +19,64 @@
#define __OPENPGP_H_ #define __OPENPGP_H_
#include "stdlib.h" #include "stdlib.h"
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#include <pico/stdlib.h> #include <pico/stdlib.h>
#include "ccid2040.h"
extern bool has_pw1;
extern bool has_pw3;
#endif #endif
#include "pico_keys.h"
#include "apdu.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h"
#include "crypto_utils.h"
#include "files.h"
extern bool has_pw1;
extern bool has_pw2;
extern bool has_pw3;
extern bool has_rc;
extern uint8_t session_pw1[32];
extern uint8_t session_rc[32];
extern uint8_t session_pw3[32];
extern uint8_t dek[IV_SIZE + 32];
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_EDDSA 0x16
#define ALGO_AES 0x70
#define ALGO_AES_128 0x71
#define ALGO_AES_192 0x72
#define ALGO_AES_256 0x74
extern void select_file(file_t *pe);
extern int parse_do(uint16_t *fids, int mode);
extern int load_dek();
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
extern mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len);
extern int reset_sig_count();
extern uint16_t algo_dec, algo_aut, pk_dec, pk_aut;
extern bool wait_button_pressed(uint16_t fid);
extern void scan_files();
extern int load_aes_key(uint8_t *aes_key, file_t *fkey);
extern int inc_sig_count();
extern int dek_encrypt(uint8_t *data, size_t len);
extern int dek_decrypt(uint8_t *data, size_t len);
#endif

1330
src/openpgp/piv.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,17 @@
/* /*
* This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
* Copyright (c) 2022 Pol Henarejos. * Copyright (c) 2022 Pol Henarejos.
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3. * the Free Software Foundation, version 3.
* *
* This program is distributed in the hope that it will be useful, but * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of * WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@@ -23,8 +23,13 @@
#define OPGP_VERSION_MAJOR ((OPGP_VERSION >> 8) & 0xff) #define OPGP_VERSION_MAJOR ((OPGP_VERSION >> 8) & 0xff)
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff) #define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
#define PIV_VERSION 0x0507
#define PIPGP_VERSION 0x0106 #define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
#define PIPGP_VERSION 0x0304
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff) #define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff) #define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)

View File

@@ -0,0 +1 @@
from card_test_check_card import *

View File

@@ -0,0 +1 @@
from card_test_empty_card import *

View File

@@ -0,0 +1 @@
from card_test_set_attr import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_personalize_card_1 import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_personalize_card_2 import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_public_key_operations import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_ds_counter2 import *

View File

@@ -0,0 +1,24 @@
"""
test_005_keygen.py - test key generation
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from card_test_keygen import *

View File

@@ -0,0 +1,24 @@
"""
test_005_keygen.py - test key generation
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from card_test_public_key_operations_kg import *

View File

@@ -0,0 +1,24 @@
"""
test_005_keygen.py - test key generation
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from card_test_ds_counter1 import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_personalize_reset import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_remove_keys import *

View File

@@ -0,0 +1,2 @@
from skip_if_kdfreq import *
from card_test_reset_pw3 import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less_1 import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_public_key_operations_alt import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_ds_counter1 import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less_2 import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_personalize_reset import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_remove_keys import *

View File

@@ -0,0 +1,25 @@
"""
test_005_adminless_kdfnone.py - test admin-less mode
Copyright (C) 2016, 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_if_kdfreq import *
from skip_gnuk_only_tests import *
from card_test_reset_pw3 import *

View File

@@ -0,0 +1,23 @@
"""
test_011_adminfull_kdffull.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_test_kdf_full import *

View File

@@ -0,0 +1,23 @@
"""
test_011_adminfull_kdffull.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_test_personalize_card_1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_rsa2k import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_nistp256r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_brainpoolp256r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_secp256k1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_nistp384r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_brainpoolp384r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_nistp521r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_brainpoolp512r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_curve25519 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_rsa2k import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_nistp256r1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_brainpoolp256r1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_secp256k1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_nistp384r1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_brainpoolp384r1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_nistp521r1 import *

View File

@@ -0,0 +1 @@
from card_test_kg_pko_dsc_brainpoolp512r1 import *

View File

@@ -0,0 +1 @@
from card_test_ki_pko_dsc_curve25519 import *

View File

@@ -0,0 +1,15 @@
import pytest
from card_const import *
from constants_for_test import *
def test_setup_pw1_4(card):
r = card.change_passwd(1, FACTORY_PASSPHRASE_PW1, PW1_TEST4)
assert r
def test_verify_pw1_4(card):
v = card.verify(1, PW1_TEST4)
assert v
def test_verify_pw1_4_2(card):
v = card.verify(2, PW1_TEST4)
assert v

View File

@@ -0,0 +1,23 @@
"""
test_011_adminfull_kdffull.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_test_personalize_reset import *

View File

@@ -0,0 +1,23 @@
"""
test_011_adminfull_kdffull.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_test_remove_keys import *

View File

@@ -0,0 +1,23 @@
"""
test_011_adminfull_kdffull.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from card_test_reset_pw3 import *

View File

@@ -0,0 +1 @@
from skip_if_no_kdf_support import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_kdf_single import *

View File

@@ -0,0 +1,25 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_personalize_card_1 import *
from card_test_personalize_card_2 import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_public_key_operations import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_ds_counter2 import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_personalize_reset import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_remove_keys import *

View File

@@ -0,0 +1,24 @@
"""
test_016_adminfull_kdfsingle.py - test KDF data object
Copyright (C) 2018, 2019 g10 Code GmbH
Author: NIIBE Yutaka <gniibe@fsij.org>
This file is a part of Gnuk, a GnuPG USB Token implementation.
Gnuk is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gnuk is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from skip_gnuk_only_tests import *
from card_test_reset_pw3 import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less_1 import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_public_key_operations_alt import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_ds_counter1 import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_personalize_admin_less_2 import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_personalize_reset import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_remove_keys import *

View File

@@ -0,0 +1,2 @@
from skip_gnuk_only_tests import *
from card_test_reset_pw3 import *

Some files were not shown because too many files have changed in this diff Show More