Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New epass2003 token fails to initialize with error Failed to create PKCS #15 meta structure: Card command failed #3034

Open
faryon93 opened this issue Feb 17, 2024 · 23 comments

Comments

@faryon93
Copy link

faryon93 commented Feb 17, 2024

Problem Description

I'm trying to initialize a newly acquired Feitian ePass 2003 token (blue case) with the steps provided by the wiki article. But creating the PKCS#15 structure fails with the error Failed to create PKCS #15 meta structure: Card command failed. Erasing the token seems to work fine.

I tried with the latest release version 0.24.0 shipped with arch linux and the current version from master branch eda86e4

Proposed Resolution

I haven't been able to get the token working in the meantime.

Steps to reproduce

$: pkcs11-tool -L
Available slots:
Slot 0 (0x0): Feitian ePass2003 00 00
  (token not recognized)

$: opensc-tool --version
OpenSC-0.24.0-125-geda86e4bb, rev: eda86e4bb, commit-time: 2024-02-15 22:23:44 +0100

 $: pkcs15-init -E -T
Using reader with a card: Feitian ePass2003 00 00
$: pkcs15-init --create-pkcs15 -T -p pkcs15+onepin --pin 123456 --puk 12345678 --label "Test"
Using reader with a card: Feitian ePass2003 00 00
Failed to create PKCS #15 meta structure: Card command failed

Logs

You can find full logs with -vvvvvv of both commands here: https://pastebin.com/AwByRSFW

@popovec
Copy link
Member

popovec commented Feb 17, 2024

I assume that the manufacturer has again changed the procedure for "token erase" .. and OpenSC is unable to really erase the token.

P:38606; T:0x126356886358912 10:09:59.586 [pkcs15-init] card-epass2003.c:258:epass2003_check_sw: Conditions of use not satisfied

Probably, even if you manage to initialize the token, digital signature operations will not work.

It seems that all EPASS2003 tokens that use the FIPS-certified MAC method (the message "Warning, MAC is not checked" appears in the opensc log) are not supported in OpenSC. This cannot be solved without information from the manufacturer.

@faryon93
Copy link
Author

Thank you for the fast analysis of the problem, even if this is bad news :)

@FeitianSmartcardReader maybe you can help here?

@dengert
Copy link
Member

dengert commented Feb 17, 2024

The line numbers in the trace don't match what is in master. You may want to try with latest code.

OpenSC will hide pin commands in the log. Try setting OPENSC_DEBUG=8 or add two more "v"s to " -vvvvvv" to log pin commands. It might be the pin code is not using SM or is trying to check the MAC.

P:38606; T:0x126356886358912 10:09:59.586 [pkcs15-init] card-epass2003.c:258:epass2003_check_sw: Conditions of use not satisfied

This is misleading. It says the MAC verification code for the FIPS has not been implemented, (it should be). But for now the processing continues because the FIPS SM is working in both directions as the MAC is being treated as being correct.

epass2003_pkcs15_erase_card and epass2003_pkcs15_init_card are called it first log and look like they work.

In second log pkcs15init/pkcs15-epass2003.c:223 pkcs15init/epass2003_pkcs15_create_pin is called. Looks like both the PIN and PUK are written in the SM blocks

Outgoing APDU (67 bytes):
8C E3 00 00 3D 87 31 01 D7 3B 7A 02 ED 46 B0 E2 ....=.1..;z..F..
F3 73 1C 93 C1 97 DE C1 A1 5F 21 27 67 92 E5 01 .s......._!'g...
28 42 41 82 B5 F1 4D CC A6 6B 29 2A 34 FF 3E 0C (BA...M..k)*4.>.
28 F6 CD 43 4C B9 0A 9C 8E 08 E6 AE 12 C2 9A 51 (..CL..........Q
BB 64 00 

 
Outgoing APDU (67 bytes):
8C E3 00 00 3D 87 31 01 5B 0C 6F C0 B9 C6 D3 31 ....=.1.[.o....1
8B 82 C4 93 D4 4D A6 12 FB 2A 15 73 1D 95 64 21 .....M...*.s..d!
AE EF F9 01 FD 5C 78 75 D8 6A 43 B4 07 9A 26 2E .....\xu.jC...&.
8E F8 33 4A B7 05 54 CE 8E 08 06 9C 99 5B 07 28 ..3J..T......[.(
B1 5C 00 

epass2003_pkcs15_create_pin checks for max pin size of 16 so one thing to try is use a 16 byte PIN and PUK,
as they could have changed how pin is padded (code pads pin with 0.)

It could also be they have changed the minimal size of pin.

P:38623; T:0x136111207963520 10:10:19.059 [pkcs15-init] sec.c:203:sc_pin_cmd: called
P:38623; T:0x136111207963520 10:10:19.065 [pkcs15-init] sec.c:259:sc_pin_cmd: returning with: -1200 (Card command failed)
P:38623; T:0x136111207963520 10:10:19.065 [pkcs15-init] pkcs15-pin.c:443:sc_pkcs15_verify_pin_with_session_pin: PIN cmd result -1200

OpenSC will hide pin commands in the log. Try setting OPENSC_DEBUG=8 or add two more "v"s to " -vvvvvv" to log pin commands. It might be the pin code is not using SM or is trying to check the MAC.

@faryon93
Copy link
Author

The line numbers in the trace don't match what is in master. You may want to try with latest code.

OpenSC will hide pin commands in the log. Try setting OPENSC_DEBUG=8 or add two more "v"s to " -vvvvvv" to log pin commands. It might be the pin code is not using SM or is trying to check the MAC.

Hmmm I was sure I recorded the traces with the latest version of master. Nevertheless I recompiled OpenSC and made sure to run the newest version and recorded new traces with more verbose logging. The behavior hasn't changed and and initializing the token fails with same error.

I'm sorry I can't use the pkcs15-init --version command, as it is terminating prematurely, when opening the card fails. So we'll have to use opensc-tool to verify the revision which OpenSC was built with.

$: opensc-tool --version                                                                                                                                                                                             
OpenSC-0.24.0-127-g2361870cc, rev: 2361870cc, commit-time: 2024-02-18 00:32:31 +0100

Logs can be found here:
$: pkcs15-init -vvvvvvvv -E -T &> epass2003_erase.log
https://pastebin.com/08NKmmzd

$: pkcs15-init -vvvvvvvvv --create-pkcs15 -T -p pkcs15+onepin --pin 123456 --puk 12345678 --label "Test"
https://pastebin.com/TLRpizur

epass2003_pkcs15_create_pin checks for max pin size of 16 so one thing to try is use a 16 byte PIN and PUK, as they could have changed how pin is padded (code pads pin with 0.)

I tried using 16 characters long PIN and PUK with the following command. Is that correct way of doing it?

$: pkcs15-init -vvvvvvvv --create-pkcs15 -T -p pkcs15+onepin --pin 1111111111111111 --puk 2222222222222222 --label "Test" &> epass2003_16bytes.log

The resulting error is the same, as with a shorter PIN/PUK. See full log: https://pastebin.com/sXBrJY4W

@dengert
Copy link
Member

dengert commented Feb 18, 2024

The failure appears to be coming from:

Outgoing APDU (16 bytes):
0C 82 01 81 0A 8E 08 05 23 55 BF 2B E6 BF 2F 00 ........#U.+../.
...
Incoming APDU (2 bytes):
69 88
...
P:71771; T:0x123439976598400 12:10:15.992 [pkcs15-init] card-epass2003.c:3279:get_external_key_retries: APDU get_external_key_retries failed: -1200 (Card command failed)
P:71771; T:0x123439976598400 12:10:15.992 [pkcs15-init] card-epass2003.c:3435:epass2003_pin_cmd: Verification failed (remaining tries: 0)
P:71771; T:0x123439976598400 12:10:15.992 [pkcs15-init] card-epass2003.c:3437:epass2003_pin_cmd: verify pin failed: -1200 (Card command failed)
P:71771; T:0x123439976598400 12:10:15.992 [pkcs15-init] sec.c:259:sc_pin_cmd: returning with: -1200 (Card command failed)

and the messages are from: https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-epass2003.c#L3433-L3437

69 88 is "Incorrect secure messaging DOs"

There are twp 0C 82 01 81 commands. Theses are "EXTERNAL AUTHENTICATE command-response pair"

The first looks like a verify that works. It passes in some encrypted data. The second has no date (other then the SM MAC) and comments says it it to get the tries left, but the card does not like the SM data.

It could be only OpenSC code tries to get the retries. Newer cards may implement this.

So if you are willing to try something, replace line 3433 r = get_external_key_retries(card, 0x80 | kid, &retries); with retries=5;

@faryon93
Copy link
Author

@dengert Your guess was bang on. With your suggest modifications (patch below) the pkcs#15 initialization completes without errors. Thank you for your work :)

When I'm reading the blame correct, this part of the code is there for 8y. So I'm not sure why newer tokes don't support this function...

The patch I used to make initialization work:

diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c
index 7f9f00e72..8cad7c70f 100644
--- a/src/libopensc/card-epass2003.c
+++ b/src/libopensc/card-epass2003.c
@@ -3430,7 +3430,8 @@ epass2003_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries
                                data->pin1.len);
                LOG_TEST_RET(card->ctx, r, "verify pin failed");
 
-               r = get_external_key_retries(card, 0x80 | kid, &retries);
+               //r = get_external_key_retries(card, 0x80 | kid, &retries);
+               retires = 5;
                if (retries < pin_low)
                        sc_log(card->ctx, "Verification failed (remaining tries: %d)", retries);

I'm going to try the crypto functions (generate keys, signing) tomorrow.

@faryon93
Copy link
Author

Generating Keys works, but signing data does not work. I think I'm now where the author of issue #2843 was before erasing the token.

@dengert
Copy link
Member

dengert commented Feb 19, 2024

So if you are willing to try something, replace line 3433 r = get_external_key_retries(card, 0x80 | kid, &retries); with retries=5;

Good to hear it works. But eliminating the code is not the real solution.

@xaqfan comments on this? is 5d6f7cb involved?

Some additional info I have come up with:

The issue appears to be how a case 1 APDU (non Lc and no Le) is handled with SM. The difference in your card and my card is at:
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-epass2003.c#L1242-L1249 for a special case APDU.

Your card has exdata->bFipsCertification = 0x01 mine does not.

Using my old epass2003 from 2011 ATR with version: 01:00:11
3b:9f:95:81:31:fe:9f:00:66:46:53:05:01:00:11:71:df:00:00:03:90:00:80
Yours has with version: 10:52:39
3b:9f:95:81:31:fe:9f:00:66:46:53:05:10:52:39:71:df:00:00:03:90:00:eb

The newest cards known to OpenSC are from 2022 with version: 23:00:25
See: https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/card-epass2003.c#L51-L58

So your card is somewhere in between.

Running with ./pkcs15-tool --verify and entering the PIN:

Outgoing APDU (35 bytes):
0C 82 01 81 1D 87 11 01 78 C5 4D 4A BD C2 09 85 ........x.MJ....
05 D7 51 91 4B 27 57 67 8E 08 62 47 19 63 AB 5C ..Q.K'Wg..bG.c.\
DF E8 00
Incoming APDU (16 bytes):
99 02 90 00 8E 08 ED 26 67 F9 D2 70 47 56 90 00

and request to get tries left as:

Outgoing APDU (16 bytes):
0C 82 01 81 0A 8E 08 5D 59 CD C3 37 4C D3 8B 00
Incoming APDU (16 bytes):
99 02 63 C6 8E 08 72 07 A6 00 35 24 E1 08 63 C6

@popovec
Copy link
Member

popovec commented Feb 19, 2024

The issue appears to be how a case 1 APDU (non Lc and no Le) is handled with SMThe issue appears to be how a case 1 APDU (non Lc and no Le) is handled with SM

For APDU CASE 1 (no Le, field, Lc=0), the initialization vector is not used in this mode when generating the MAC (analysed from the code), I assume this is some workaround. Perhaps the author of the code can say more.

@dengert
Copy link
Member

dengert commented Feb 19, 2024

For APDU CASE 1 (no Le, field, Lc=0), the initialization vector is not used in this mode when generating the MAC (analysed from the code), I assume this is some workaround. Perhaps the author of the code can say more.

Yes, maybe a bug in some early tokens which is now fixed in newer ones? Just need to know which ones have the bug.

@faryon93
Copy link
Author

Removing the whole construct_mac_tlv_case1() path of the if statement and always use the standard construct_mac_tlv() call results in the same error as before.

@dengert
Copy link
Member

dengert commented Feb 19, 2024

I think I have found the problem. construct_mac_tlv_case1 is only called from

1242         if(exdata->bFipsCertification && plain->lc == 0 && apdu_buf[1] == 0x82 && apdu_buf[2] == 0x01){
1243                 if(0 != construct_mac_tlv_case1(card, apdu_buf, data_tlv_len, le_tlv_len, mac_tlv, &mac_tlv_len, exdata->smtype))

Both of you said old cards worked, as mine does, which would never call it.
The difference between construct_mac_tlv1 and construct_mac_tlv_case1 as there is no data to be encrypted.

But size_t block_size = 4 as the data MACed should endup as a multiple of the AES key size of 16.

If can both of you can try this with new or old keys?
The code with the bug was introduced in 622e6e2 2022-04-25 13:36:47 and you both have tokens from 2023.
I assume your "old: tokens were long before and may not have the exdata->bFipsCertification.

diff --git a/src/libopensc/card-epass2003.c b/src/libopensc/card-epass2003.c
index 7f9f00e72..bd3c0e453 100644
--- a/src/libopensc/card-epass2003.c
+++ b/src/libopensc/card-epass2003.c
@@ -1110,7 +1110,7 @@ construct_mac_tlv_case1(struct sc_card *card, unsigned char *apdu_buf, size_t da
        unsigned char *mac_tlv, size_t * mac_tlv_len, const unsigned char key_type)
 {
     int r;
-    size_t block_size = 4;
+    size_t block_size = (KEY_TYPE_AES == key_type ? 16 : 8);
     unsigned char mac[4096] = { 0 };
     size_t mac_len;
     int i = (KEY_TYPE_AES == key_type ? 15 : 7);

@faryon93
Copy link
Author

faryon93 commented Feb 20, 2024

@dengert thank you for your patch suggestion. Unfortunately I don't think it has the desired effect on the new token, as the initialization fails with the same error as before (see trace: https://pastebin.com/1W7asJhE).

I'm really sorry that I wont be able to test anything with an older version of the token, as the newly bought one should be a replacement for my older one, because I broke the older one mechanically :(

@dengert
Copy link
Member

dengert commented Feb 20, 2024

The OpenSC card-epass2003.c have many comments about using SCP01:

	/* This is a FIPS certified card using SCP01 security messaging. */
/*0x00:plain; 0x01:scp01 sm*/
#define SM_SCP01				0x01
	unsigned char sm;		/* SM_PLAIN or SM_SCP01 */
/* According to GlobalPlatform Card Specification's SCP01
/* According to GlobalPlatform Card Specification's SCP01
	exdata->sm = SM_SCP01;
./libopensc/card-epass2003.c

But it appears that for FIPS-2 SCP03 is required. (But I am not sure.)

https://globalplatform.org/wp-content/uploads/2019/03/GPC_2.2_D_SCP03_v1.0.pdf

"6.2.6. APDU Command C-MAC and C-DECRYPTION Generation and Verification
"No encryption shall be applied to a command where there is no command data field: in this case the
message shall be protected as defined in section 6.2.4 APDU Command C-MAC Generation and
Verification. Otherwise the Off-Card Entity performs the process detailed hereafter."

Since all the other commands have a data field (Lc is present) accept the one that fails. I want to use a debugger to see if 6.2.4 is handled as expected.

Unfortunately I do not have a epass2003 newer then 2011 to test with. But have ordered 2, should have next week.

https://csrc.nist.rip/Projects/Cryptographic-Algorithm-Validation-Program/Validation/Validation-List/KDF
Is from 2016 and lists several Feitian devices.

@dengert
Copy link
Member

dengert commented Feb 22, 2024

Don't have new epass2003 yet, but did find three PDF datasheets with picture of tokens.
https://www.ftsafe.com/Support/Resources?tree_id=159
The A1+ and A2 have embossed "FIPS-2 Level 3" on same side with green ovel with "ePass2003"
Both say:

"With combined compatibility of Microsoft Minidriver and OpenSC, the ePass2003 is compatible with applications running on Windows, Linux and Mac and therefore is the ideal choice for all industries requiring high level protection such as government, enterprise, financial institutions and media companies."

Will see about compatibility with Minidriver and OpenSC, and what other tools they provide to use these.

@faryon93
Copy link
Author

Unfortunately I do not have a epass2003 newer then 2011 to test with. But have ordered 2, should have next week.

Thank you for putting that much effort into this. If I can help, try something etc. don't hesitate to ask.

The A1+ and A2 have embossed "FIPS-2 Level 3" on same side with green ovel with "ePass2003"

The embossed FIPS marking is not present on my tokens.

In the meantime I got response from the reseller I bought the tokens from. Information is more or less the same as @drodgers-immt already pointed out: Feitian had to rework the tokens to be compliant with FIPS Level 3.
As we are seeing FIPS related implementation efforts in OpenSC I'm not sure if the implementation was changed once again (more recently) and broke compatibility or the initial FIPS support had it's flaws.

@faryon93
Copy link
Author

faryon93 commented Feb 28, 2024

The reseller I purchased the tokens from finally got a response from @FeitianSmartcardReader. They said that they are aware of the problem and are already working on a solution to make the tokens compatible with OpenSC again but there is no ETA for the changes.

@dengert
Copy link
Member

dengert commented Feb 28, 2024

The https://github.com/FeitianSmartcardReader tell the reseller what was the problem?
The ePass2003 and SafeNet #3048 problem maybe related. They both are FIPS-2 compliant.

FIPS-2 appears to require SCP03 as defined in GlobalPlatform v2.2

card-epass2003.c uses older SCP01 and card-idprime.c does not use any Secure Messaging.

OpenSC does not appear to support SCP03 (grep of the code does not have "SCP03") but gp.c does have a comment with "GlobalPlatform 2.3.1"

If either of these cards work on Windows with the vendor's minidriver, the difference should show up in a USB trace as the formats of the APDUs is different. SCP01 follows ISO7816 SM formats with TLV formats whereas SCP03 appears to use APDUs with the 0x80 bit set which says non ISO7816 APDUs, and does not use all the TLVs like SCP01.

@dengert
Copy link
Member

dengert commented Feb 28, 2024

If OpenSC needs SCP03, https://github.com/kaoh/globalplatform looks interesting.

  • Written in C
  • Runs on Windows, Linux and MacOS.
  • Actively being maintained.
  • Some contributors appear to be with Yubico
  • Use OpenSSL

@faryon93
Copy link
Author

faryon93 commented Feb 28, 2024

The https://github.com/FeitianSmartcardReader tell the reseller what was the problem?

Unfortunately they didn't provide technical details what the problem is. But they provided the manufacturers software. The software has a login button and shows the remaining tries when entering the wrong pin. I captured the communication with wireshark. The command sequence is similar to OpenSC.

  1. Request a challange (INS = 0x84)
  2. Read Retry Count (INS = 0x82)

There is a slight difference between OpenSC and the original software. OpenSC additionally transmits a trailing 0x00 byte.

windows (original software)
  <- 0c 82 01 81 0a 8e 08 8b 3c 30 36 d2 99 7e 16
  -> 99 02 63 c9 8e 08 44 22 87 e6 44 e1 89 46 63 c9

linux (opensc)
  <- 0C 82 01 81 0A 8E 08 7C E3 55 17 8F C1 55 9E 00
  -> 69 88

I tried stripping the trailing byte but result was the same. Maybe the token ignores trailing bytes.

@dengert
Copy link
Member

dengert commented Feb 29, 2024

The last 00 maybe misleading. It is the Le 00 which says host is willing to accept up to 256 bytes. Card returns up to 256 bytes, and if there is even more returns 61xx. It is really outside of the SM.

The error message indicates 69 88 says there is a problem with the SM. Which may have something to do with not a Le in the encrypted or encoded data as the original APDU does not have any data to be returned. But with SM there is at least the MAC and the status bytes need to be returned.

(My two ePass2003s are somewhere between San Francisco and Chicago (3,425.91 km) probably on a truck, expected delivery on late Saturday.)

@dengert
Copy link
Member

dengert commented Feb 29, 2024

I don't have the test ePass2003 cards yet, but if you havetime, can you try this WIP:
https://github.com/dengert/OpenSC/tree/epass2003-sm-new

I think what be going on, is for APDUs that do not send any data (like checking log in state and possibly key generation)
encryption and padding may have been done which caused the MAC to be wrong.

"GlobalPlatform Card Specification 2.2.1" says about SCP01: "If confidentiality is required, the off-card entity encrypts the “clear text” data field of the command message being transmitted to the card. (If the APDU command does not originally contain command data, encryption is not performed.)"

The code now uses construct_mac_tlv_case1 for those types of commands. Really old card may not have checked this and more recent cards may. The FIPS-2 cards may require SCP03 which is another issue.

@faryon93
Copy link
Author

faryon93 commented Feb 29, 2024

@dengert thank you for all your efforts. I'm happy to test whatever you have.

With the changes from your branch, creation does not succeed but fails at an earlier step. Now external_key_auth fails (with same error code) when trying to obtain the challange. (See https://pastebin.com/j7CQaDWs for full log).

Requesting a challenge seems to be a Case 2 APDU...

sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x84, 0x00, 0x00);
...so it might not be okay to use the construct_mac_tlv_case1 for this APDU too.

What I found interesting: only APDUs with use the construct_mac_tlv_case1 (this is the APDU for querying the retry count only) use a modified version of the CMAC algorithm by calling aes128_encrypt_cmac_ft instead of aes128_encrypt_cmac. Maybe the modified version of CMAC algorithm is not correct anymore?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants