Comments (21)
Hi. Thank you for the interest in the OpenSC project!
We are adding support for the IDPrime cards slowly over last couple of releases with the cards we have access to so any new input is very useful for us. Good thing is that the card is correctly detected. On the first review of the log, it sounds like there is some logical error in reading the certificate (unless that is the part you were heavily redacting, but I assume you removed just the part with the PIN). Can you confirm, there were no removed likes around the line 711 of the log? The reading failure sounds suspicious as it looks like the reading is not called at all:
P:3657753; T:0x140489810786304 10:24:55.972 [opensc-pkcs11] card-idprime.c:884:idprime_read_binary: called; 256 bytes at offset 0
P:3657753; T:0x140489810786304 10:24:55.972 [opensc-pkcs11] card-idprime.c:907:idprime_read_binary: returning with: -1305 (Invalid data)
There is a logic to parse compressed certificates, but if the certificate is not compressed, the read is kept on 0, leading to this failure. Can you try the following patch if it helps?
diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c
index a3aedd98e..84873ce91 100644
--- a/src/libopensc/card-idprime.c
+++ b/src/libopensc/card-idprime.c
@@ -890,7 +890,7 @@ static int idprime_read_binary(sc_card_t *card, unsigned int offset,
if (!priv->cached && offset == 0) {
/* Read what was reported by FCI from select command */
- int left = priv->file_size;
+ int left = priv->file_size > 0 ? priv->file_size : count;
size_t read = 0;
// this function is called to read and uncompress the certificate
from opensc.
Thank you for the quick reply! I did not remove any lines of the log, no - I just blacked out the value of the PIN code.
The suggested patch did not resolve the issue, but the errors appeared to change. Here's the new log.
https://gist.github.com/Nihlus/2bb99bdf6d1b04cb0a880d6dbee7a281
from opensc.
I dug into the code a little myself, and realized that there were other instances of direct use of priv->file_size
in the aforementioned function - replacing those with the initial value of left
appears to produce valid data from the card, but parsing of the actual certificate fails (with an error of -1401 (Invalid ASN.1 object)
.
I'm remiss to share those logs unless I have to since they contain live certificates, but I suspect it has to do with the size of the object being read - it's only ever reading 256 bytes, which seems incorrect to me.
from opensc.
Do you have a patch and debug log towards the error? It might be that for the uncompressed certificates, we need to skip some bytes in the beginning too, which might not be done now.
I think I had cards only with the compressed ones.
from opensc.
I went ahead and removed the certificates from the logs, though I suspect it may cause some trouble when trying to determine the cause. I'll see if I can get my hands on a test card instead of a live one so I can share unredacted logs.
https://gist.github.com/Nihlus/34662a779b86aca913ddb7f3f9edd4e8
Patch is as below; I'm not all that familiar with OpenSC so I may have made some silly mistakes.
--- a/src/libopensc/card-idprime.c
+++ b/src/libopensc/card-idprime.c
@@ -886,30 +886,31 @@
if (!priv->cached && offset == 0) {
/* Read what was reported by FCI from select command */
- int left = priv->file_size;
+ int left = priv->file_size > 0 ? priv->file_size : count;
+ int file_size = left;
size_t read = 0;
// this function is called to read and uncompress the certificate
u8 buffer[SC_MAX_EXT_APDU_BUFFER_SIZE];
u8 *data_buffer = buffer;
- if (sizeof(buffer) < count || sizeof(buffer) < priv->file_size) {
+ if (sizeof(buffer) < count || sizeof(buffer) < (size_t)file_size) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
}
while (left > 0) {
- r = iso_ops->read_binary(card, read, buffer + read, priv->file_size - read, flags);
+ r = iso_ops->read_binary(card, read, buffer + read, file_size - read, flags);
if (r <= 0) {
LOG_FUNC_RETURN(card->ctx, r);
}
left -= r;
read += r;
}
- if (read < 4 || read != priv->file_size) {
+ if (read < 4 || read != (size_t)file_size) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
}
if (buffer[0] == 1 && buffer[1] == 0) {
/* Data will be decompressed later */
data_buffer += 4;
- r = priv->file_size - 4;
+ r = file_size - 4;
if (flags)
*flags |= SC_FILE_FLAG_COMPRESSED_AUTO;
}
from opensc.
Ah, now I see what's going on. It's only reading a single chunk of the file in card.c
- the full file size is actually 2084
bytes, and the function doesn't indicate to sc_read_binary
that it should keep reading.
from opensc.
Got it to work! If you unconditionally cache the real file size in idprime_select_file
instead of only when the header starts with 0x01, 0x00 and drop the changes mentioned before, I can successfully read the certificates from the card.
On top of that, I found a likely bug with the cache allocation - r
is set to the number of bytes read in the last loop iteration if the certificate is not compressed, resulting in a too-short buffer being created. I've included a minimal possible fix for that in the attached patch; though I'd argue that reusing r
in this manner is fairly prone to mistakes.
Subject: [PATCH] card-idprime.c: unconditionally cache real file size
---
Index: src/libopensc/card-idprime.c
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/libopensc/card-idprime.c b/src/libopensc/card-idprime.c
--- a/src/libopensc/card-idprime.c (revision d43cfd8afc59c872f13226b7076cdd2d817aca32)
+++ b/src/libopensc/card-idprime.c (date 1702395880220)
@@ -861,13 +861,8 @@
r = iso_ops->select_file(card, in_path, file_out);
if (r == SC_SUCCESS && file_out != NULL) {
- /* Try to read first bytes of the file to fix FCI in case of
- * compressed certififcate */
- len = iso_ops->read_binary(card, 0, data, data_len, 0);
- if (len == HEADER_LEN && data[0] == 0x01 && data[1] == 0x00) {
- /* Cache the real file size for the caching read_binary() */
- priv->file_size = (*file_out)->size;
- }
+ /* Cache the real file size for the caching read_binary() */
+ priv->file_size = (*file_out)->size;
}
/* Return the exit code of the select command */
return r;
@@ -912,7 +907,9 @@
r = priv->file_size - 4;
if (flags)
*flags |= SC_FILE_FLAG_COMPRESSED_AUTO;
- }
+ } else {
+ r = priv->file_size;
+ }
priv->cache_buf = malloc(r);
if (priv->cache_buf == NULL) {
return SC_ERROR_OUT_OF_MEMORY;
Unfortunately, the troubles don't seem to end there, as signing with the certificate (pkcs11-tool --login --test
) fails with CKR_USER_NOT_LOGGED_IN
.
$ pkcs11-tool --login --test
Using slot 0 with a present token (0x0)
Logging in to "TOKEN".
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
RIPEMD160: OK
SHA-1: OK
SHA256: OK
Ciphers: not implemented
Signatures (currently only for RSA)
testing key 0 (Private key 1)
error: PKCS11 function C_SignFinal failed: rv = CKR_USER_NOT_LOGGED_IN (0x101)
Aborting.
I've saved debug logs for this, but I need to scrub them first. Will get back to you once I either do that or get that test card.
from opensc.
Good to hear that! You can also isolate the signature operation with pkcs11-tool to get cleaner log without running the whole tests:
https://github.com/OpenSC/OpenSC/wiki/Using-pkcs11-tool-and-OpenSSL
I think not much more than the content of the certificates and the PIN values should have possible confidential content. Feel free to open (even WIP) PR.
from opensc.
PR opened! Here are the scrubbed logs for the signing operation: https://gist.github.com/Nihlus/1c78a04cc80f04857757fa8b97045407
from opensc.
P:508603; T:0x140609348577280 18:07:02.223 [opensc-pkcs11] /home/jarl/Programming/source-projects/c/OpenSC/src/pkcs11/pkcs11-object.c:809:C_SignFinal: C_SignFinal() = CKR_DATA_INVALID
this sounds the card returns some invalid data after request for the signature (its different from the previous error which was saying CKR_USER_NOT_LOGGED_IN
). It can be for various reasons, but I would bet on the key reference, which is mostly guessed from the cards we had access to as I was not not able to come with better solution:
OpenSC/src/libopensc/card-idprime.c
Lines 447 to 471 in 6b568b1
This is used in the set security environment APDU before making signature. If you have the proprietary driver and you can intercept APDUs it is using to see what key reference is used for your key (and then try to adjust the guessing to work for your card, ideally without breaking it for other cards).
from opensc.
I've got the driver now (downloadable from https://service.secmaker.com/download-access.aspx) - how would I intercept APDUs in this case?
from opensc.
I've got the driver now (downloadable from https://service.secmaker.com/download-access.aspx) - how would I intercept APDUs in this case?
on linux, it will most probably use pcsc-lite as the PCSC so the simplest thing is to stop the pcscd service, run it in forerground in the debug mode (with --apdu
switch to print APDUs) as described in https://pcsclite.apdu.fr/
from opensc.
That did it, thanks. It looks like the proprietary module is also having trouble with the signing operation on the card, producing a CKR_DEVICE_ERROR
in C_SignFinal
.
Could you test with one of the IDPrime cards with a compressed certificate that you have on hand using the linked-to module? I'd like to rule out an issue with the card itself before going too deep into any one rabbit hole. I've found several PKCS#11 modules from various sources that claim to support the IDPrime 940, but none of them have fully worked.
from opensc.
Aha, nevermind - there was a mostly-hidden patch version available too which works correctly (https://supportportal.thalesgroup.com/csm?id=kb_restricted&sysparm_article=KB0026523). I'll use this library as a reference point in future work.
from opensc.
Okay, after some fiddling I've got the key reference for my certificate sniffed out (using a modified version of https://github.com/eIDuy/apdu-parser - quite a nice program).
22 : MANAGE SECURITY ENVIRONMENT (Sets or replaces one component of the current SE.)
00 22 41 B6 06 80 01 02 84 01 5E
90 00 : Command successfully executed (OK). [I]
90 00
I'm quite a bit out of my depth here, I'm afraid. I can't see any selection of file 0005 in the logs from the proprietary module, which - if I'm understanding the code correctly - should be the file with the key reference map. Instead, it looks at the following files in order:
0201 (16 bytes)
0202 (6 bytes)
0028 (not found)
Whatever it finds in those files are apparently enough, as after that it can list out all the objects on the card. There are a couple of 00 A6 00 00 XX
commands that return XX
number of bytes whose purpose isn't entirely clear, but the data appears to be constant. There are also a lot of D0 39 00 00 00
commands with an also apparently constant return value (20 bytes).
Interestingly, the IDs used appear to be GUIDs with an extra 8 bytes on the end - the object labels are properly formatted GUIDs, and the ID is that GUID without dashes and with the extra data appended. Example output:
Using slot 0 with a present token (0x0)
Certificate Object; type = X.509 cert
label: 93533823-f30c-9cd7-f754-08c4c951c22b
subject: <redacted>
ID: 93533823f30c9cd7f75408c4c951c22b0ca43d99
Public Key Object; RSA 2048 bits
label: 93533823-f30c-9cd7-f754-08c4c951c22b
ID: 93533823f30c9cd7f75408c4c951c22b0ca43d99
Usage: encrypt, verify
Access: local
Private Key Object; RSA
label: 93533823-f30c-9cd7-f754-08c4c951c22b
ID: 93533823f30c9cd7f75408c4c951c22b0ca43d99
Usage: decrypt, sign, unwrap
Access: sensitive, always sensitive, never extractable, local
from opensc.
00 22 41 B6 06 80 01 02 84 01 5E
The data is TLV encoded (INS=0x22, P1,P2=0x41,0xB6, data len 6B).
https://github.com/OpenSC/OpenSC/blob/master/src/libopensc/iso7816.c#L976
We are mostly up for the key references, which is the last block 84 01 5E
. Here the 5E
(hexa) is used for some reason
While in the debug log from previous comments, we read it as 86
(decimal):
P:508603; T:0x140609348577280 18:06:59.756 [opensc-pkcs11] .../card-idprime.c:470:idprime_process_index: Found certificate with fd=1, key_ref=86 corresponding to container "NetiD-1-k1M4I/MMnNc="
This looks like the code goes through the default branch of the switch:
OpenSC/src/libopensc/card-idprime.c
Lines 469 to 472 in 53f81e7
The card is detected as Gemalto IDPrime (generic)
so maybe just updating the ATR mask at the beginning of the card-idprime.c file to match it as a IDPrime 940 might solve the issue (as it will try to read keyrefmap).
from opensc.
Changing the ATR mask helped! We're now past that problem, and there's seemingly just one more to go.
Proprietary:
$: pkcs11-tool --login --test
Using slot 0 with a present token (0x0)
C_SeedRandom() and C_GenerateRandom():
seems to be OK
Digests:
all 4 digest functions seem to work
SHA-1: OK
Signatures (currently only for RSA)
testing key 0 (93533823-f30c-9cd7-f754-08c4c951c22b)
ERR: C_SignUpdate failed: CKR_KEY_FUNCTION_NOT_PERMITTED (0x68)
testing signature mechanisms:
RSA-PKCS: OK
SHA256-RSA-PKCS: OK
Verify (currently only for RSA)
testing key 0 (93533823-f30c-9cd7-f754-08c4c951c22b)
RSA-PKCS: OK
Decryption (currently only for RSA)
testing key 0 (93533823-f30c-9cd7-f754-08c4c951c22b)
RSA-PKCS: OK
RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
This version of OpenSSL only supports SHA1 for OAEP, returning
1 errors
OpenSC:
$: pkcs11-tool --login --test
Using slot 0 with a present token (0x0)
C_SeedRandom() and C_GenerateRandom():
seeding (C_SeedRandom) not supported
seems to be OK
Digests:
all 4 digest functions seem to work
MD5: OK
RIPEMD160: OK
SHA-1: OK
SHA256: OK
Ciphers: not implemented
Signatures (currently only for RSA)
testing key 0 (Private key 1)
all 4 signature functions seem to work
testing signature mechanisms:
RSA-PKCS: OK
SHA256-RSA-PKCS: OK
Verify (currently only for RSA)
testing key 0 (Private key 1)
RSA-PKCS: OK
Decryption (currently only for RSA)
testing key 0 (Private key 1)
RSA-PKCS: OK
RSA-PKCS-OAEP: mgf not set, defaulting to MGF1-SHA256
OAEP parameters: hashAlg=SHA256, mgf=MGF1-SHA256, encoding parameter (Label) present, length 3
error: PKCS11 function C_Decrypt failed: rv = CKR_DATA_INVALID (0x20)
Aborting.
It should be noted that the proprietary module requires libssl1.1, so there's probably some limitation in this card regarding the available hash algorithms or how to request them.
from opensc.
Good to hear that it worked for you! I have the test cards in the office so I will be able to test your changes next week.
The PKCS-OAEP encryption is not very widely used. For most of the logging into your infrastructure, you should be good with signatures. Given the large variety of OAEP parameters, the pkcs11-tool --test
runs just one test with one parameter combination. There are also some limitations of the input and output sizes, which might come into play with the 2k keys. Its possible that the card requires some specific salt length or something. If you want to dig into that deeper, there is p11test that runs larger matrix of tests against cards with different parameters to see if some will work:
The error with the proprietary driver is probably related to the old version of openssl as you mention. And given the card does not support SHA1 digestst with signatures/mgf, it looks like it is not even tried.
from opensc.
Ah, excellent - p11test produces the following output, which looks pretty good to my untrained eyes.
https://gist.github.com/Nihlus/90a244b35a8d700430900724bfcdb06c
from opensc.
Right. There are three working OAEP combinations:
[ RSA_PKCS_OAEP ] [SHA256] [MGF1_SHA256] [ 0] [ ] [ [./] ]
[ RSA_PKCS_OAEP ] [SHA384] [MGF1_SHA384] [ 0] [ ] [ [./] ]
[ RSA_PKCS_OAEP ] [SHA512] [MGF1_SHA512] [ 0] [ ] [ [./] ]
I am not sure why the SHA256 did not work from the pkcs11-tool though. If you want to dig into this deeper, you can see what the pkcs11-tool does differently.
But I think you have mostly working card by now for what you need :) I will update the PR with the test results next week (please update also the ATR matching in the PR as we discussed above).
from opensc.
Yup, I've pushed those changes!
from opensc.
Related Issues (20)
- Private Key Objects of D-TRUST Card 4.1 Multi ECC 2 are not regcognized HOT 1
- Error: Could not add card "/usr/local/lib/opensc-pkcs11-local.so": agent refused operation HOT 2
- New epass2003 token fails to initialize with error `Failed to create PKCS #15 meta structure: Card command failed` HOT 23
- Update Links in README.md before making a release HOT 2
- Building eOI (Slovenian eID) on ubuntu 22.04 HOT 12
- Compiling on Windows ignores CNGSDK_INCL_DIR and CPDK_INCL_DIR env. variables values HOT 2
- Problems with test scripts HOT 9
- Reselection of DF after failure in `sc_pkcs15_decipher` function HOT 5
- PIN change fails with CKR_PIN_LEN_RANGE because current PIN is too long HOT 10
- RFE: tools add --module-init arg for non-standard NSS softokn configDir HOT 5
- ActivIdentity Activkey_Sim 00 00 HOT 3
- CI: Check if refresh in documentation is needed
- doc: Python wrapper HOT 6
- pkcs11-tool: return value is 0 when signature verification fails HOT 3
- PKCS15 framework influence PKCS11 interface HOT 3
- docbook-utf8.xsl missing from release archive HOT 1
- Probable Reasons For CKR_GENERAL_ERROR From C_Login HOT 4
- SC-HSM: Support for storing of ECDSA keys HOT 5
- C_FindObjects does not find keys generated by C_GenerateKeyPair without reinserting HOT 3
- In pkcs11-tool CKA_DERIVE is not set for write-object and keygen HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from opensc.