-
Notifications
You must be signed in to change notification settings - Fork 775
NIST Secure Messaging moved from PIV to separate sm/sm-nist.c #3098
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
base: master
Are you sure you want to change the base?
Conversation
This looks promising, thank you. but it will need some time for a review. Just some quick comments regarding your questions: If we switch to the SM implementation in sm/sm-nist.c rather than card-piv.c, then it would be good to remove the duplicated code in card-piv.c Looking at the implementation, sm-nist.c does include a padding content indicator and it padds data with 0x80..0x00. So padding is exactly what is defined in iso-sm.c. A better integration into the existing infrastructure would avoid the modifications of sm-ico.c. From what you write, creating the protected short lenght C-APDUs with chainging is very much like creating the protected extended length C-APDU without chaining: In both cases the input data is encoded identitically, this single blob is encrypted identically and this single block is maced identically. Only when sending this one big SM APDU, you need to split up the apdu->data into multiple chunks with multiple sc_transmit_apdu calls rather. Same for the response APDU: once all GET RESPONSES are done, decoding/decrypting is identically. I think that part is easily integrated in iso-sm.c in the transmit phase - all steps before that can stay as they are. I think it would be best to move the existing padding of the data to be MACed into sm-eac.c, because the padding content indicator seems to refer to the plain text data only. sm-ico.c should then only forward the unpadded data to be MACed via My approach with sm-eac.c was to include the crypto stuff that is required to establish an E2E channel to the card. That does not only include the encryption/decryption of APDUs, but also the stuff for establishing the session keys when verifying PIN or terminal keys. Having that in mind, I think sm-nist.c should keep sm_nist_start as entry point with the raw paring code and parsing or managing the pairing code should stay in card-piv.c |
Thanks for the review. I would also request any developers (MyEID?) who might want to use the NIST PIV SM in some other card driver also comment on their plans.
Yes that is the plan. I left it with both ways as I was trying to move some SM code to sm/sm-nist. if we move the code, the old version and the I really don't want to spend a lot of time on this unless it is going to be used by some other card driver.
The changes to
Yes, that what it does, by using the SC_APDU_FLAGS_SM_CHAINING which is in OpenSC 0.24.0 9933d62
No way am if going to try modify sm-eac.c This exercise was more of a prof of concept. And as I said above, I don't want to spend anymore time on it unless there is some other card driver that would actual use sm-nist.
|
I've added a commit on top of you PR, which avoids padding the data-to-be-mac'ed including the changes to sm-eac.c and sm-iso.c so you don't have to. |
Regarding the padding, I just realized that your code includes a sanity check whether the padding is OK and it doesn't add any padding. That sanity check may be removed, because sm-iso.c already does this im |
388929c works. I will look closer at what code in sm-nist could be removed and at squashing many of the commits. If you want I can post an opensc-debug log. |
3cf9949
to
55a6fe9
Compare
Aventra was kind enough to send me some, soon to be release, MyEID cards one of which is configured as a PIV card. The others are not yet configured. The cards using the PIV applet or the MyEID applet can use the NIST sp800-73-4 Secure messaging. Changes added this week include changes to card-myeid.c to use SM. Aventra's vision is to use the PIV applet only if MyEID code is not available on sys systems. The cards are populated using the MyEID applet and additional commands can be used to setup mapping of the certificates and keys to be used from either applet. The test card with both applets was not formatted for PKCS15 but the certificates can still read by opensc-explorer so it was possible to read the SM cert-signer and CVC certificate using ISO 7816-4 APDU commands, to do the SM authentication and use SM for some simple non PKCS15 commands such as read the serial number. (Since setting up the SM should be done early, having a fixed path to these files on the card should be included in their documentation.) So there is still a lot to do including using pkcs15-tool to configure the card, and add commands in some tool to configure the PIV applet to use keys, objects and certificates created by pkcs15-tool. Aventra used the OpenSC PIV SM code during development of the on card SM code. This PR has makes it possible to easily use the SM from the card-myeid.c |
This PR also fixes some .github issues with "awk" not being available on some fedora systems. I would suggest that these be reviewed by others and committed be others.
|
|
src/sm/sm-eac.c
Outdated
|
||
if (!card || !ctx || !ctx->priv_data || !macdata) { | ||
r = SC_ERROR_INVALID_ARGUMENTS; | ||
goto err; | ||
} | ||
eacsmctx = ctx->priv_data; | ||
|
||
inbuf = BUF_MEM_create_init(data, datalen); | ||
r = iso_add_80_pad(data, datalen, ctx->block_length, &p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea not to include padding into the authenticate
and verify_authentication
callback is that padding is done before calling those functions. The reasoning is that with the padding content indicator from ISO-7816, padding to a block size is clearly handled at the ISO level rather than at the card driver level, where the actual MAC is calculated or verified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change was made because of your commit "avoid padding mac data" 2014-4-11
currently listed in my branch as: 2245a69 It also removed some code I though would be needed but it is not.
added iso_add_80_pad(const u8 *data, size_t datalen, size_t block_size, u8 **padded)
to sm-iso.h
and sm-iso.c
. But in sm-eac.c
it is used as `iso_add_80_pad(ctx, data, datalen, &p);`` which did not compile. So 37a5415 was added. If this is not correct what should it be?
As an example of OPENSC_DRIVER=myeid gdb --args ./opensc-tool --serial
opensc-debug-250407-myeid-sm-serial.txt
shows the myeid_init
establishing the PIV SM then reading the serial number starting on line 403.
The reasoning is that with the padding content indicator from ISO-7816, padding to a block size is clearly handled at the ISO level rather than at the card driver level, where the actual MAC is calculated or verified.
The sm-nist is implemented to be called by the card driver and the sm-nist calls the sm-iso calls as needed.
src/sm/sm-iso.c
Outdated
@@ -349,7 +352,10 @@ static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card, | |||
break; | |||
case SC_APDU_CASE_3_SHORT: | |||
case SC_APDU_CASE_3_EXT: | |||
if (apdu->ins & 1) { | |||
if (ctx->padding_tag == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reasoning behind this change?
The current idea is that the indicator is always prepended if the instruction code is even, because odd instructions indicate a BER-TLV payload (ISO 7816-4):
In the interindustry class, bit b1 of INS indicates a data field format as follows.
If bit b1 is set to 0 (even INS code), then no indication is provided.
If bit b1 is set to 1 (odd INS code), payloads (if any) shall be encoded in BER-TLV (see 8.1).
Do you want to support BER-TLV content for an even INS, because NIST SP 800 73-4 always uses 0x87
with indicator and encrypted context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to support BER-TLV content for an even INS, because NIST SP 800 73-4 always uses 0x87 with indicator and encrypted context?
I would say yes, but maybe this in not needed. It has been a year. I will have to run gdb to have a look, if this change is really need or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes I remember (even though its been 11 years now ^^)... I thought that the padding in PIV was different, but it turns out that both padding mechanisms are the same. So it seems the commit from back then is not correct, because indeed the mac data is padded in all cases. compare, NIST.SP.800-73pt2-5 Fig. 2. PIV data integrity of command with 9303_p11_cons_en.pdf Figure 5. Computation of an SM command APDU for even INS Byte, fr example. So this old commit could be removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The NIST PIV SM treats even and odd ins the same and needs the padding character.
The code in in the PR in effect skips over the } else if (apdu->ins & 1) {
in line 358 so even and odd are treated like even.
NIST SP 800-73pt2-5:
Secure messaging specified in this section CAN be applied to the following commands:
• GET DATA (this is odd 'CB' for PIV, but the MyEID uses 'CA' and SM works on the one test I have run with it)
• VERIFY (`20` even)
• CHANGE REFERENCE DATA
• GENERAL AUTHENTICATE"
Table 21. Secure messaging data objects
Tag Description
'87' **Padding content indicator byte** followed by the encrypted data
'8E' Cryptographic checksum (MAC)
'97' Le
'99' Status word
Doing some further testing, setting in sm-nist.c
ctx->padding_tag = 0;
adding to sm-iso.c
sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "prepend_padding_indicator: %d, padding_indicator %02X",
prepend_padding_indicator, ctx->padding_indicator);
and using pkcs11-tool --login --test
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] apdu.c:367:sc_single_transmit: CLA:0, INS:CB, P1:3F, P2:FF, data(5) 0x7fffffffc080
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] sm.c:133:sc_sm_single_transmit: called
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] sm.c:134:sc_sm_single_transmit: SM_MODE:200
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] sm-nist.c:2138:sm_nist_pre_transmit: returning with: 0 (Success)
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] sm-iso.c:383:sm_encrypt:
Protected Le (plain) (1 byte):
00 .
P:46338; T:0x140737346566144 16:24:11.810 [opensc-pkcs11] sm-iso.c:224:format_data:
Data to encrypt (16 bytes):
5C 03 5F C1 0C 80 00 00 00 00 00 00 00 00 00 00 \._.............
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-iso.c:230:format_data:
Cryptogram (16 bytes):
D3 BC 8F 27 34 F5 E6 A9 51 64 7F CE 54 4C 13 AB ...'4...Qd..TL..
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-iso.c:232:format_data: prepend_padding_indicator: 0, padding_indicator 01
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-iso.c:400:sm_encrypt:
Padding-content indicator followed by cryptogram (plain) (16 bytes):
D3 BC 8F 27 34 F5 E6 A9 51 64 7F CE 54 4C 13 AB ...'4...Qd..TL..
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Cryptogram'
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1833:asn1_encode_entry: type=4, tag=0x80000005, parm=0x555555606d40, len=16
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=18
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Padding-content indicator followed by cryptogram' (not present)
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=0
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Protected Le'
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1833:asn1_encode_entry: type=4, tag=0x80000017, parm=0x555555606d80, len=1
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=3
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Cryptographic Checksum' (not present)
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=0
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-iso.c:458:sm_encrypt:
Data to authenticate (37 bytes):
0C CB 3F FF 80 00 00 00 00 00 00 00 00 00 00 00 ..?.............
85 10 D3 BC 8F 27 34 F5 E6 A9 51 64 7F CE 54 4C .....'4...Qd..TL
13 AB 97 01 00
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-nist.c:1958:sm_nist_authenticate: called
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] sm-iso.c:467:sm_encrypt:
Cryptographic Checksum (plain) (8 bytes):
3C E0 FD 86 E1 67 A7 29 <....g.)
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Cryptogram'
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1833:asn1_encode_entry: type=4, tag=0x80000005, parm=0x555555606d40, len=16
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=18
P:46338; T:0x140737346566144 16:24:11.811 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Padding-content indicator followed by cryptogram' (not present)
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=0
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Protected Le'
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:1833:asn1_encode_entry: type=4, tag=0x80000017, parm=0x555555606d80, len=1
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=3
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:1828:asn1_encode_entry: encoding 'Cryptographic Checksum'
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:1833:asn1_encode_entry: type=4, tag=0x8000000e, parm=0x555555695500, len=8
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] asn1.c:2026:asn1_encode_entry: length of encoded item=10
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] sm-iso.c:518:sm_encrypt:
ASN.1 encoded encrypted APDU data (31 bytes):
85 10 D3 BC 8F 27 34 F5 E6 A9 51 64 7F CE 54 4C .....'4...Qd..TL
13 AB 97 01 00 8E 08 3C E0 FD 86 E1 67 A7 29 .......<....g.)
P:46338; T:0x140737346566144 16:24:11.812 [opensc-pkcs11] reader-pcsc.c:245:pcsc_internal_transmit: called
P:46338; T:0x140737346566144 16:24:11.842 [opensc-pkcs11] reader-pcsc.c:337:pcsc_transmit:
Incoming APDU (2 bytes):
69 88 i.
meaning the card did not accept the SM encoding.
(This shows another problem, the code turned off SM, and ran the rest without SM. which needs to be addressed.)
With `sctx->padding_tag = 1; the difference is in:
P:50526; T:0x140737346566144 16:31:26.151 [opensc-pkcs11] sm-iso.c:224:format_data:
Data to encrypt (16 bytes):
5C 03 5F C1 0C 80 00 00 00 00 00 00 00 00 00 00 \._.............
P:50526; T:0x140737346566144 16:31:26.151 [opensc-pkcs11] sm-iso.c:230:format_data:
Cryptogram (16 bytes):
BE 53 89 F8 D1 4D 1F 86 1F 62 79 4C FE 06 43 64 .S...M...byL..Cd
P:50526; T:0x140737346566144 16:31:26.151 [opensc-pkcs11] sm-iso.c:232:format_data: prepend_padding_indicator: 1, padding_indicator 01
P:50526; T:0x140737346566144 16:31:26.151 [opensc-pkcs11] sm-iso.c:400:sm_encrypt:
Padding-content indicator followed by cryptogram (plain) (17 bytes):
01 BE 53 89 F8 D1 4D 1F 86 1F 62 79 4C FE 06 43 ..S...M...byL..C
64
So the code needs to add the padding byte. The choice of the name ctx->padding_tag
could be changed,
and the if statement code be reworked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks for the clarification. I think it would be most flexible if you could add a general flag
to struct iso_sm_ctx
, which handles these kinds of exceptions. Something like ISO_SM_FLAG_ALWAYS_PADDING_INDICATOR
would be fine. However, it should be needed to be set explicitly, because I still believe the BER-TLV ruling above is the correct reading. At least SC-HSM is also adhering to it and will require no content indicator in odd instructions.
src/sm/sm-iso.h
Outdated
@@ -162,6 +164,12 @@ struct iso_sm_ctx { | |||
|
|||
/** @brief Padding-content indicator byte (ISO 7816-4 Table 30) */ | |||
u8 padding_indicator; | |||
/** @brief if 1 use tag 87 */ | |||
u8 padding_tag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/sm/sm-iso.c
Outdated
@@ -466,6 +473,11 @@ static int sm_encrypt(const struct iso_sm_ctx *ctx, sc_card_t *card, | |||
sm_apdu->data = sm_data; | |||
sm_apdu->datalen = sm_data_len; | |||
sm_apdu->lc = sm_data_len; | |||
if (ctx->use_sm_chaining && sm_apdu->datalen > 255) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really need a dedicated flag use_sm_chaining
? If you added sm_apdu->flags |= SC_APDU_FLAGS_CHAINING
, then sc_transmit_apdu()
would pick this up and split the APDU into short length and send all of it subsequently, right? So just returning a complete long APDU from the ISO layer with chaining enabled would be enough to let the transmit code handle the sending. At first glance, it looks like the chaining flag could be added in the pre_transmit
hook for the PIV card.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need this. The ISO model is to process every APDU in a chain operations, where PIV does the mac and encryption on whatever data need to be sent then breaks it up whine chaining. Same for response.
I can also send a debug log of PIV doing this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ISO model is to process every APDU in a chain operations
Why do you think so? AFAICT, sm-iso.c always builds a single SM APDU from a signle non encrypted APDU. Currently, the cards I have tested are all supporting extended length, which is then also used for the encryption - no need for chaining. In case of PIV, the same encoding and encryption routine can be used with the only difference the the SM APDU is not sent as one single (extended) APDU, but possibly chopped into multiple short APDUs. From what I read, this is exactly what the code in apdu.c does, when the chaining flag is set.
src/sm/sm-iso.h
Outdated
/** @brief do_not_split_apdu into multiple apdus */ | ||
u8 use_sm_chaining; | ||
/** @brief get response is always in clear */ | ||
u8 get_response_in_clear; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
similar as with the chaining, we already have the management of GET RESPONSE built into sc_transmit()
. I believe if you would not set SC_APDU_FLAGS_NO_GET_RESP on the SM apdu, then sc_transmit()
would do what you want, i.e. call sc_get_response()
without applying SM. As sc_get_response()
delegates this command to the driver call back get_response
, you're in full control on how this is executed. In PIV, the default implementation of the iso driver is used. I suggest you use the pre_transmit
hook to write a private variable for disabling SM on GET RESPONSE, and then use the post_transmit
hook to reset this variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sm-nist.c has sm_nist_pre_transmit
and sm_nist_post_transmit
routines and can selectively apply SM on some commands, all or at none. the default is if contactless, apply on all, if contact, GET_DATA is done in clear, with pin, and crypto with SM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I wanted to say is that the handling you want should already be present in apdu.c and I believe it is not needed to duplicate this code for SM APDUs
@frankmorgner I have adding code based on switches that default to 0 so they should not be a problem for existing code in sm-iso
NIST SP 800-73pt2-5 "Fig. 3. Single command under secure messaging" is for short commands. Note it requires the use of short APDUs, There is no mention of extended APDUs although some cards support it as an extension. The difference between |
@frankmorgner The last one was NIST SP 800-73pt2-5 "4.2.4. Command With PIV Secure Messaging" says: "Command chaining will be needed if the secure messaging data field to be transported is larger than 255 bytes." and figure 3 an figure 4 show the difference. NIST does not mention extended APDUs, although some cards may support it. |
f937fd9
to
a127fe6
Compare
src/libopensc/card-myeid.c
Outdated
_sc_card_add_rsa_alg(card, 768, flags, 0); | ||
_sc_card_add_rsa_alg(card, 1024, flags, 0); | ||
_sc_card_add_rsa_alg(card, 1536, flags, 0); | ||
} | ||
_sc_card_add_rsa_alg(card, 2048, flags, 0); | ||
|
||
if (card_caps.card_supported_features & MYEID_CARD_CAP_RSA) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
where can this MYEID_CARD_CAP_RSA
be switched on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"The Aventra MyEID PKI Smart Card Reference manual Ver. 3.0.6" says "Date:10.3.2016 Version:2.1.0 Description:
Added GET DATA: MyEID CARD CAPABILITIES"
APDU 00 CA 01 AA 0C there is a version 1 and version 2 (since MyEID 5, the tests cards are 5 but not certified and have version 4.9.1)
The card returns 02 00 6D 10 00 00 00 01 00 02 09 00 90 00
02 is version
006D says: Specifies capabilities supported in this version of MyEID.
bit flags, bytes in big endian order:
bit 0 (0001h): RSA algorithm
bit 1 (0002h): DES/3DES algorithm
bit 2 (0004h): AES algorithm
bit 3 (0008h): ECDSA and ECDH algorithms
bit 4 (0010h): GridPIN
bit 5 (0020h): PIV emulation
bit 6 (0040h): Supports Windows Smart Card Framework ID.
bits 6-15: RFU
1000 max RSA 4096
0000 no DES3
0100 max AES 256
02 09 max EC 521
00 Security certifications looks like this is added in version 2 of the structure
The 4.9.1 test cards are not certified yet
There are still some basic questions above. What's the status of this topic, how are you going to proceed? |
Yes. Aventra sent me 5 MyEID version 4.9.1 cards in April along with a PDF "Aventra MyEID PKI Smart Card Reference manual The MyEID code in OpenSC can be used to provision the card with 4 privkey, pubkey and certificates. Additional APDUs can be used to enable PIV mode, and may the keys and certificates. I have been working on using additional scripts to create a PIV CVC certificate, sign it with a subCA key and then create files for the CVC certificate and write it to the card using opensc-explorer. The SubCA certificate is written using pkcs15-init lie any other certificate. As part of the Reference manual is how to put and get data objects (PIV Initialization Parameters) that map the pkcs15 file paths to PIV key and certificate objects. The data object (Secure Messaging Parameters) lists the Algorithm ids 0x27 and/or 0x2E that can be used, the path the CVCs for these Algorithms, and the path to the SubCA (FID of the Secure Messaging Certificate Signer certificate.) These are written and or read using opensc-explorer. Just recently I have been able to use this PR, some additional changes not yet committed and these scripts to use the the PIV SM code with the MyEID card-myeid.c. Using Needless to say there is still a lot to be done:
@hhonkanen Thanks for the cards and documentation. |
601f174
to
706cd2b
Compare
@frankmorgner You also mentioned EAC setting a flag, but the only flag, I see, related to APDU in EAC code is
This will call In my view, these two ways of getting around SM encoding each APDU are independent and there is no conflict, because SC_APDU_FLAGS_SM_CHAINING is only set when using PIV SM. Now that it has been shown that the MyEID cards can use the sm-nist, I want to simplify the PR. The current PR allows building with or with or without PIV SM or building with the PIV SM code in I would like to have the PR to be either no PIV SM, or PIV SM using The current PR also contains changed to MyEID code to use sm/sm-nist. I would like to back that our of this PR and make that a separate PR, as it is not complete and is just an addon. |
I have pushed a new version of this PR. This removes some 1860 lines of code that were included to allow building PIV SM using either the version totally in card-piv.c or building with most of the PIV SM code in sm/sm-nist.c Now that the sm/nist.c code appears to work as expected, there is no need to have 2 versions in card-piv.c I have also not included any of the MyEID SM code, which will depend on the PR. I have already shown that the MyEID changes can use the sm/nist. There is more work to be done, including support for non X.509 certificates in OpenSC pkcs15. Pkcs15 specs defines other types of certificates, including CVC certificates. Much of the testing was done using opensc-explorer to issue specific MyEID apdus, that should be done in pkcs15init or some additional MyEID tool.
@frankmorgner So far I do not see any conflicts with EAC's use of ENVELOPE and the flags set and used only by this PR. This last run points out some formatting issues which I hope to address this week. |
Add CSE and FLAGS to APDU debug message Very useful when debugging SM code. Pass code formating test that inserts blanks in wrong places. data(%"SC_FORMAT_LEN_SIZE_T"u) %p is replaced with datalen:%"SC_FORMAT_LEN_SIZE_T"u data:%p Changes to be committed: modified: src/libopensc/apdu.c
The PIV SM code is moved to sm-nist.c so it could be used by other card drivers. sm-nist.c uses sm-iso.c code to simplify the process as sugested. This required some changes to sm-iso.h and sm-iso.c as NIST sp800-73-4 encodes and adds CMAC for the entire transaction then send it to the card using command chaining of a single PUT_DATA command. Original sm-iso.c would break up a payload and encode and MAC each part and sent as seperate APDUs. The response data handled in similar fashion. Changes to be committed: modified: src/libopensc/Makefile.am modified: src/libopensc/card-piv.c modified: src/sm/Makefile.am modified: src/sm/sm-iso.c modified: src/sm/sm-iso.h new file: src/sm/sm-nist.c new file: src/sm/sm-nist.h
ENABLE_SM_NIST (enabled by default) is used to build sm/sm-nist.c based on NIST sp800-73-4 Secure Messaging which was moved from card-piv.c to so it can be used by other card drivers. ENABLE_PIV_SM (enabled by default) is used within card-piv.c to use the sm-nist code if ENABLE_SM_NIST is defined. If sm-nist is used by other card drivers, data needed such as the SM EC key reference and certificate with the public key and CVC certificates will need to be provided by the card driver. The card driver will also determine which APDUs will be protected by SM.
sm_nist_params_t is used to pass parameters and shared data to sm_nist_start. This allows a card driver to provide certificates and flags outside of the strict PIV requirements so other card drivers can use the NIST SM as defined in NIST sp800-73-4 but store the certificates X509 or CVC as PKCS15 files. sm_nist_params_cleanup can be used by a card driver to cleanup the sm_nist_params_t which can be part of a card driver's private data. On branch sm-nist Changes to be committed: modified: src/sm/sm-nist.c modified: src/sm/sm-nist.h
Changes to be committed: modified: src/libopensc/card-piv.c
On branch sm-nist Changes to be committed: modified: src/libopensc/card-piv.c
Thse are the changes need to get sm-nist.c to use sm-iso routines with 4 added modifications changes controlled by flags listed in sm-iso.h The default values are all 0 so sm-iso should continue to work. The major changes was to get sm-iso to support short APDUs using command chaining. Still to be done in error handling. On branch sm-nist Changes to be committed: modified: sm-iso.c modified: sm-iso.h modified: sm-nist.c
@frankmorgner If there is still some question about the SC_APDU_FLAGS_SM_CHAINING flag, maybe a better name would be SC_APDU_FLAGS_SM_ALREADY_ENCODED which tells apdu.c to not call SM to encode it again. It prevent apdu.c while dividing up the data into chunks and encoding each chunk again. It is not the SC_APDU_FLAGS_CHAINING flag, which tells apdu.c to break up the data into chucks. |
With the introduction of Secure Messaging in PIV driver last year, some developers where questioning why the PIV SM was implemented in
card-piv.c
rather then usingsm/sm-iso.c
where it could be used by other card drivers. It was suggested that MyEID may have some interest in using it.This proof of concept PR moves most of the PIV SM code to
sm/sm-nist.c
where, with some additional work, it could be used by other card drivers.The concern at the time of writing the PIV SM code was that
sm/sm-iso.c
did not support the same SM as used by PIV SM.sm/sm-iso.c
applied SM to a single APDU. PIV SM applies SM to the data to be sent, then uses APDU chaining and Get Response to send and receiver the secured data and response using multiple APDUs. ISO-7816-4 10: " Secure messaging (SM) protects all or part of a C-RP, or a concatenation of consecutive data fields (payload fragmentation, see 5.3),..." i.e. chaining and get response.CMAC is used by PIV SM and the MAC is not padded.
The padding tag byte is not used in PIV SM.
To address these issues, flags were added to
iso_sm_ctx
insm/sm-iso.h
and used bysm/sm-iso.c
and several other places.card-piv.c
was modified to allow for building without any SM, with the current PIV SM implementation or to use thesm/sm-nist.c
that uses the modifiedsm-iso.c
. This was done as it was not clear which code could be moved tosm/sm-nist.c
so there many#if defined..
statements.If this POC code becomes a PR, there would be only two build options with NO SM, or use
sm/sm-nist.c
. (OpenSSL and EC support is required in any case.)There is still a lot to do. For example, where should the pairing code handled. Is there code in
card-piv.c
that should be moved. No testing was done to have multiple applications trying to use the same card at same time.configure.ac
was modified for testing to force all the github actions it check thesm/nist.c code
.There is no known PIV applet that supports SM that could be run virtually for testing. As far as I know, only Jakub and I have cards from Idemia.
@frankmorgner, MyEID or other developers would this be useful to proceed with this code, or not?