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

"pkcs11-tool --test" fails with a SIPR card #1524

Closed
srsross opened this issue Nov 2, 2018 · 17 comments · Fixed by #1532
Closed

"pkcs11-tool --test" fails with a SIPR card #1524

srsross opened this issue Nov 2, 2018 · 17 comments · Fixed by #1532
Labels

Comments

@srsross
Copy link
Contributor

srsross commented Nov 2, 2018

Problem Description

pkcs11-tool --test fails with a test SIPR card.

On Fedora 28, I am using a test Secure Internet Protocol Router (SIPR) smart card (with a CoolKey applet) that fails the testing sequence of pkcs11-tool --test with the error of:

error: PKCS11 function C_SignFinal failed: rv = CKR_ARGUMENTS_BAD (0x7)

Proposed Resolution

none

Steps to reproduce

The OpenSC version is:

$ rpm -q opensc
opensc-0.19.0-1.fc28.x86_64

Following is the command line output:

$ OPENSC_CONF=/tmp/opensc-x86_64.conf.sross.debug2 pkcs11-tool --module /usr/lib64/opensc-pkcs11.so --test --login
Using slot 0 with a present token (0x0)
Logging in to "POTTER.HARRY.5000001239 (POTTER.".
Please enter User PIN:
C_SeedRandom() and C_GenerateRandom():
  seeding (C_SeedRandom) not supported
  seems to be OK
Digests:
  all 4 digest functions seem to work
  MD5: OK
  SHA-1: OK
  RIPEMD160: OK
Signatures (currently only for RSA)
  testing key 0 (signing key for harry.potter.2)
error: PKCS11 function C_SignFinal failed: rv = CKR_ARGUMENTS_BAD (0x7)
Aborting.
$ echo $?
1
$

I dunno if this has any relation to #1225 which is titled "pkcs11-tool tests with random data in RSA_X_509 mechanism are failing with modern cards".

The content of my OpenSC configuration file is:

app default {
        debug = 3;
         debug_file = /tmp/opensc-debug.log
        card_drivers = coolkey, internal;
}

Logs

The OpenSC debug log (with "debug=3") is at https://gist.github.com/srsross/c303c8a6a268c52850f5fd7fad7b4d10

@srsross srsross changed the title "pkcs "pkcs11-tool --test" fails with a SIPR card Nov 2, 2018
@frankmorgner
Copy link
Member

Please check #1515

@hajikhorasani
Copy link
Contributor

@srsross you can use the CryptokiMPX to generate more useful logs:
https://github.com/hajikhorasani/cryptokimpx

@srsross
Copy link
Contributor Author

srsross commented Nov 6, 2018

Please check #1515

@frankmorgner Thanks for your suggestion.

As per @dengert in #1515, I changed

CRYPTO_secure_malloc_init(4096, 32);

to

CRYPTO_secure_malloc_init(65536, 32);

in ctx.c from commit eaed345. However, I still see the same issue of pkcs11-tool --test --login reporting the error of

error: PKCS11 function C_SignFinal failed: rv = CKR_ARGUMENTS_BAD (0x7)

I posted the opensc-debug.log at https://gist.github.com/srsross/34cb3603fe1748c66712a70c3ec63b49

@dengert
Copy link
Member

dengert commented Nov 7, 2018

This looks like a card-coolkey.c bug

0x7fa618bfb740 11:56:09.380 [opensc-pkcs11] apdu.c:339:sc_check_apdu: Invalid Case 3 short APDU: cse=03 cla=b0 ins=54 p1=00 p2=00 lc=257 le=0

The card is always using short APDUs where Lc must be <=255.
I bet the problem is around here where Lc is set:
985 sendbuflen += nonce_len;
991 apdu.lc = sendbuflen;

I have no way to test this...

@srsross
Copy link
Contributor Author

srsross commented Nov 7, 2018

@dengert Thanks for taking a look at the log.

This looks like a card-coolkey.c bug

0x7fa618bfb740 11:56:09.380 [opensc-pkcs11] apdu.c:339:sc_check_apdu: Invalid Case 3 short APDU: cse=03 cla=b0 ins=54 p1=00 p2=00 lc=257 le=0

The card is always using short APDUs where Lc must be <=255.
I bet the problem is around here where Lc is set:
985 sendbuflen += nonce_len;
991 apdu.lc = sendbuflen;

After looking through the code that you pointed out in card-coolkey.c, it appears to me that the logic of adding the nonce to the end of the send-buffer, and then updating the variable recording the length of the send-buffer, is correct. It seems that the amount of data (namely 249 bytes as shown in line 5248 of the log), plus the appended 8-byte nonce, brings the total length to 257 bytes which (as you point out) exceeds the length of data expected for SC_APDU_CASE_3_SHORT.

I have no way to test this...

If you have any suggestions, I would be able to test them with the card.

@dengert
Copy link
Member

dengert commented Nov 7, 2018

Were did you get the "Secure Internet Protocol Router (SIPR) smart card (with a CoolKey applet)".
Do you know what size keys it has?

Do you know by other means that it has a COOLKEY applet? Do you have any documentation on the applet?

The ATR appears to be
3B FF 14 00 FF 81 31 FE 45 80 25 A0 00 00 00 56 57 53 43 36 35 30 04 00 3C
look at: ATR Parser

Your card appears to be mentioned in this:
https://www.air-watch.com/downloads/resources/vmware-horizon-view-federal-secure-desktop.pdf
"SafeNet SC650 Coolkey applet"

It also appears to be related to: #943

The card-coolkey.c driver says it can handle 1K, 2K, and 3K RSA keys. The operation looks like it is using a 2K key. The use of the nonce with a 2K key may not be tested.

Using a 3K key would require someway to pass more the 255 bytes of data. Dos the applet support extended APDUs?

There are a number of ways to pass more then 255 bytes while using short APDUs. Some cards support Command Chaining. Some cards use some other form of multiple APDUs.
Look for "apdu.flags |= SC_APDU_FLAGS_CHAINING;` 8 OpenSC drivers use this.
In this case Lc can be > 255.

I am not a COOLKEY expert.

@srsross
Copy link
Contributor Author

srsross commented Nov 9, 2018

@dengert Thanks for your in-depth response.

Were did you get the "Secure Internet Protocol Router (SIPR) smart card (with a CoolKey applet)".

I received this test card from one of our customers.

Do you know what size keys it has?

It has public keys with 2048 bits.

Do you know by other means that it has a COOLKEY applet?

It responds to APDUs for the CoolKey applet. See the below interaction with the card using the scriptor application from the pcsc-tools package on Fedora/CentOS.

$ scriptor
No reader given: using OmniKey CardMan 3121 00 00
Using T=0 protocol
Reading commands from STDIN

# Reset the SIPR card with CN = POTTER.HARRY.5000001239
# The card responds with its ATR.
reset
> RESET

< OK: 3B FF 14 00 FF 81 31 FE 45 80 25 A0 00 00 00 56 57 53 43 36 35 30 04 00 3C

# Select AID CoolKey, Select File
00a4040006627601ff0000
> 00 a4 04 00 06 62 76 01 ff 00 00
< 90 00 : Normal processing.


# Send CoolKey No OP
b071000000
> b0 71 00 00 00
< 90 00 : Normal processing.

# CKYGetLifeCycle
b0f2000004
> b0 f2 00 00 04
< 0F 01 01 01 90 00 : Normal processing.

# CKYGetBuildID
b070000004
> b0 70 00 00 04 
< 54 DE 79 0F 90 00 : Normal processing.
                                                                 
# CKYGetStatus
b03c000010
> b0 3c 00 00 10 
< 01 01 01 04 00 00 7F FF 00 00 71 26 01 06 00 00 
90 00 : Normal processing.
# The last two bytes indicate that there are zero "Logged in Identities".

# CKYVerify Pin
# PIN is "77777777".
# Provide the PIN as part of the command.
b0420000083737373737373737
> b0 42 00 00 08 37 37 37 37 37 37 37 37 
< 75 21 BE 37 55 F2 FB F4 90 00 : Normal processing.
# This card returned the nonce in the first eight bytes.

# CKYGetStatus
b03c000010
> b0 3c 00 00 10
< 01 01 01 04 00 00 7F FF 00 00 71 26 01 06 00 01
90 00 : Normal processing.
# The last two bytes indicate that there is one "Logged in Identities".

#CKYLogout
# Use nonce returned by CKYVerify Pin, above, in the CKYLogout command.
b0610000087521be3755f2fbf4
> b0 61 00 00 08 75 21 be 37 55 f2 fb f4
< 90 00 : Normal processing.
# Note the normal logout without an error.

# CKYGetStatus
b03c000010
> b0 3c 00 00 10
< 01 01 01 04 00 00 7F FF 00 00 71 26 01 06 00 00
90 00 : Normal processing.
# Note that the count of  "Logged in Identities" is now zero in the
# last two bytes of the response.  This is as expected.

# Send CoolKey No OP
b071000000
> b0 71 00 00 00
< 90 00 : Normal processing.

Do you have any documentation on the applet?

See https://github.com/elmarco/coolkey/blob/master/applet/doc/CoolKeyApplet.odt.

The ATR appears to be
3B FF 14 00 FF 81 31 FE 45 80 25 A0 00 00 00 56 57 53 43 36 35 30 04 00 3C
look at: ATR Parser

Yes, that is the correct ATR.

Your card appears to be mentioned in this:
https://www.air-watch.com/downloads/resources/vmware-horizon-view-federal-secure-desktop.pdf
"SafeNet SC650 Coolkey applet"

Yes, the card is a SafeNet SC650 v4 card.

It also appears to be related to: #943

Yes, at least to the extent that the applet on the card is CoolKey.

The card-coolkey.c driver says it can handle 1K, 2K, and 3K RSA keys. The operation looks like it is using a 2K key. The use of the nonce with a 2K key may not be tested.

Thanks for pointing out the RSA initialization for those three key lengths in the coolkey_init() function.

Using a 3K key would require someway to pass more the 255 bytes of data. Dos the applet support extended APDUs?

I don't know whether or not it supports extended APDUs. How would I check this?

There are a number of ways to pass more then 255 bytes while using short APDUs. Some cards support Command Chaining. Some cards use some other form of multiple APDUs.
Look for "apdu.flags |= SC_APDU_FLAGS_CHAINING;` 8 OpenSC drivers use this.
In this case Lc can be > 255.

Is there any way to test (maybe via scriptor) whether or not this particular card supports Command Chaining?

I am not a COOLKEY expert.

That would make two of us!

@dengert
Copy link
Member

dengert commented Nov 10, 2018

Looking closer at the source, it looks like coolkey_rsa_op is called, with data length of 256:
card-coolkey.c:1694:coolkey_rsa_op: datalen=256 outlen=1024

in line 1734 coolkey_rsa_op calls:

r = coolkey_write_object(card, COOLKEY_DL_OBJECT_ID, 0, len_buf, sizeof(len_buf),priv->nonce, sizeof(priv->nonce));

so in line 1179 coolkey_write_object writes out parameters and 2 bytes of length:

     r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_WRITE_OBJECT, 0, 0,
            (u8 *)&params, sizeof(params.head)+operation_len, NULL, 0, nonce, nonce_size);

card-coolkey.c:940:coolkey_apdu_io: 54 00 00 11 : 255 256

resulting in this APDU:

B0 54 00 00 13 FF FF FF FF 00 00 00 00 02 01 00 6B 6F BD FE B2 E7 44 D0

02 is size of length and length is 01 00 or 256 bytes and 8 byte nonce 6B 6F BD FE B2 E7 44 D0

So far so good.

at line 1740 coolkey_write_object is called to write out the data that is 256 bytes long:

      r = coolkey_write_object(card, COOLKEY_DL_OBJECT_ID, 2, data, datalen, priv->nonce,
                       sizeof(priv->nonce));

coolkey_write_object then calls coolkey_apdu_io in a loop to write out chunks of data of size:
operation_len = MIN(left, COOLKEY_MAX_CHUNK_SIZE);
and does this in line 1179:

           r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_WRITE_OBJECT, 0, 0,
                (u8 *)&params, sizeof(params.head)+operation_len, NULL, 0, nonce, nonce_size);

card-coolkey.c:940:coolkey_apdu_io: 54 00 00 249 : 255 256

So here is the problem:
operation_len for the first chuck is 249. coolkey_apdu_io then adds on the nonce of 8 bytes
resulting in Lc=257.

I suspect other card may be using a smaller nonce. A 6 byte nonce would write 255 bytes and work.
But your card has a 8 byte nonce.

So the the line 71:
#define COOLKEY_MAX_CHUNK_SIZE 240 /* must be less than 255-8 */
is not clear. When data is written, coolkey_write_object_param_t contains a coolkey_read_object_param_t that is 9 bytes and a 240 COOLKEY_MAX_CHUNK_SIZE buffer.

I assume in the comment 255-8 the 8 is for max nonce.
So the numbers don't match up 240+8+9=257.

I would suggest that COOLKEY_MAX_CHUNK_SIZE be left at 240 (not sure if the card applet
may require this) so try something like:

@srsross can you try this:
card-coolkey.c-chunk.txt

Someone who understands COOLKEY @Jakuje ? needs to look at this too.

@dengert
Copy link
Member

dengert commented Nov 10, 2018

In the above patch the MAX should be MIN. Sorry

@Jakuje
Copy link
Member

Jakuje commented Nov 10, 2018

@dengert Thank you for the analysis. It looks correct as well as the patch (with the addition in the last comment).

Unfortunately I have only 1K RSA key on my testing card so I am not able to test this case (I will ask around on Monday if we could get some bigger keys ... 1K is really not sensible these days). At this moment, probably only @sross is the one who can test your patch.

@dengert
Copy link
Member

dengert commented Nov 10, 2018

In addition to a 2048 bit key the nonce must be bigger the 6 for a failure. What size nonce does your test card have?

@Jakuje
Copy link
Member

Jakuje commented Nov 10, 2018

@srsross
Copy link
Contributor Author

srsross commented Nov 12, 2018

@denger and @Jakuje Thanks for your analysis and comments.

@srsross can you try this:
card-coolkey.c-chunk.txt

You're patch works! Following are the details.

I used the following patch file. It is pretty much the same as that of @dengert but (as he pointed out) replaces MAX() with MIN(). I also replaced 255 with card->max_send_size and added a necessary closing parenthesis.

diff --git a/src/libopensc/card-coolkey.c b/src/libopensc/card-coolkey.c
index e320290..088d880 100644
--- a/src/libopensc/card-coolkey.c
+++ b/src/libopensc/card-coolkey.c
@@ -1168,12 +1168,16 @@ static int coolkey_write_object(sc_card_t *card, unsigned long object_id,
        size_t operation_len;
        size_t left = buf_len;
        int r;
+       size_t max_operation_len;
+       
+       /* set limit for 255 and short write */
+       max_operation_len = MIN(COOLKEY_MAX_CHUNK_SIZE, (card->max_send_size - sizeof(coolkey_read_object_param_t) - nonce_size));

        ulong2bebytes(&params.head.object_id[0], object_id);

        do {
                ulong2bebytes(&params.head.offset[0], offset);
-               operation_len = MIN(left, COOLKEY_MAX_CHUNK_SIZE);
+               operation_len = MIN(left, max_operation_len);
                params.head.length = operation_len;
                memcpy(params.buf, buf, operation_len);
                r = coolkey_apdu_io(card, COOLKEY_CLASS, COOLKEY_INS_WRITE_OBJECT, 0, 0,

The OpenSC log from my test run with the POTTER.HARRY SIPR card is:
https://gist.github.com/srsross/23005f4e92afdb286f14be5cefaf1db2
The OpenSC code is from commit eaed345 where the only change is the above patch (i.e., no change to the CRYPTO_secure_malloc_init() call.)

The command line output is the following:

$ OPENSC_CONF=~/Tmp/OpenSC/opensc-x86_64.conf.sross.debug2 /usr/local/bin/pkcs11-tool --module /usr/local/lib/opensc-pkcs11.so --test --login
Using slot 0 with a present token (0x0)
Logging in to "POTTER.HARRY.5000001239 (POTTER.".
Please enter User PIN: 
C_SeedRandom() and C_GenerateRandom():
  seeding (C_SeedRandom) not supported
  seems to be OK
Digests:
  all 4 digest functions seem to work
  MD5: OK
  SHA-1: OK
  RIPEMD160: OK
Signatures (currently only for RSA)
  testing key 0 (signing key for harry.potter.2) 
  all 4 signature functions seem to work
  testing signature mechanisms:
    RSA-X-509: OK
    RSA-PKCS: OK
    SHA1-RSA-PKCS: OK
    MD5-RSA-PKCS: OK
    RIPEMD160-RSA-PKCS: OK
    SHA256-RSA-PKCS: OK
  testing key 1 (2048 bits, label=encryption key for harry.potter.2) with 1 signature mechanism -- can't be used to sign/verify, skipping
  testing key 2 (2048 bits, label=Identity Key for harry.potter.2) with 1 signature mechanism
    RSA-X-509: OK
Verify (currently only for RSA)
  testing key 0 (signing key for harry.potter.2)
    RSA-X-509: OK
    RSA-PKCS: OK
    SHA1-RSA-PKCS: OK
    MD5-RSA-PKCS: OK
    RIPEMD160-RSA-PKCS: OK
  testing key 1 (encryption key for harry.potter.2) with 1 mechanism -- can't be used to sign/verify, skipping
  testing key 2 (Identity Key for harry.potter.2) with 1 mechanism
    RSA-X-509: OK
Unwrap: not implemented
Decryption (currently only for RSA)
  testing key 0 (signing key for harry.potter.2)  -- can't be used to decrypt, skipping
  testing key 1 (encryption key for harry.potter.2) 
    RSA-X-509: OK
    RSA-PKCS: OK
  testing key 2 (Identity Key for harry.potter.2)  -- can't be used to decrypt, skipping
No errors

What is the next step?

@dengert
Copy link
Member

dengert commented Nov 12, 2018

You could submit the patch as a Pull request. Or @Jakuje or I could submit it.

@srsross
Copy link
Contributor Author

srsross commented Nov 13, 2018

You could submit the patch as a Pull request. Or @Jakuje or I could submit it.

@dengert, given that you did the digging through the code and log, and provided the patch, please feel free to submit it. (Otherwise, I could do it.)

One other change could be made to the patch: change the comment from

/* set limit for 255 and short write */

to something like

/* set limit for the card's maximum send size and short write */

@dengert
Copy link
Member

dengert commented Nov 13, 2018

I would prefer one of you who can test the PR submit the PR. @Jakuje or @srsross

srsross added a commit to srsross/OpenSC that referenced this issue Nov 14, 2018
For a problem description, see <OpenSC#1524>.
In a nutshell, for a card with the CoolKey applet and 2048-bit keys,
the command
	pkcs11-tool --test --login
fails to complete all of its tests.

This commit consists of a patch from @dengert.

To avoid triggering an error when the data exceeds 255 bytes, this commit
limits the amount of the payload sent to the CoolKey applet on the card based
on the maximum amount of data that the card can receive, and overhead bytes
(namely, a header and nonce) that accompany the payload.

With this change, the command
	pkcs11-tool --test --login
succeeds.
@srsross
Copy link
Contributor Author

srsross commented Nov 14, 2018

Pull Reqest is #1532.

frankmorgner pushed a commit that referenced this issue Nov 19, 2018
For a problem description, see <#1524>.
In a nutshell, for a card with the CoolKey applet and 2048-bit keys,
the command
	pkcs11-tool --test --login
fails to complete all of its tests.

This commit consists of a patch from @dengert.

To avoid triggering an error when the data exceeds 255 bytes, this commit
limits the amount of the payload sent to the CoolKey applet on the card based
on the maximum amount of data that the card can receive, and overhead bytes
(namely, a header and nonce) that accompany the payload.

With this change, the command
	pkcs11-tool --test --login
succeeds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants