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

NIST Secure Messaging moved from PIV to separate sm/sm-nist.c #3098

Draft
wants to merge 31 commits into
base: master
Choose a base branch
from

Conversation

dengert
Copy link
Member

@dengert dengert commented Apr 4, 2024

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 using sm/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 in sm/sm-iso.h and used by sm/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 the sm/sm-nist.c that uses the modified sm-iso.c. This was done as it was not clear which code could be moved to sm/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 the sm/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?

dengert and others added 30 commits April 5, 2024 08:06
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.

 interactive rebase in progress; onto 993e646
    pick 68f7531 Move PIV SM code from card-piv.c into new sm/sm-nist.c
 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
 On branch sm-nist
 Changes to be committed:
	modified:   sm-nist.c
Equivalent of ccb6f3c

 On branch sm-nist
 Changes to be committed:
	modified:   card-piv.c
This fixes an erroneous call of sc_unlock in piv_match_card_continued in
case of an error, which causes sc_unlock to be called more often than
sc_lock.
Equivalent to b5ee418

 On branch sm-nist
 Changes to be committed:
	modified:   card-piv.c
The use of priv->max_object_size = MAX_FILE_SIZE; causes
SM to exceed 65K when creating SM apdu from plain apdu. The
plain apdu will have 65K, and SM apdu will add 40 bytes.

f05eb3e  "replace PIV_MAX_OBJECT_SIZE with MAX_FILE_SIZE"
introduced the problem.

pcsc internally will allocate another buffer the size of resplen.
SCardTransmit will get a 0x80100008 error.

Remove some TODO comments

Use cipher vs cypher

https://english.stackexchange.com/questions/147965/cipher-vs-cypher

Remove a nit and combined two "#if"... #endif"  sections into one.

Remove piv_is_expected_tag and replace with inline code in 3 places.

 Changes to be committed:
	modified:   src/libopensc/card-piv.c
 On branch PIV-4-extensions
 Changes to be committed:
	modified:   card-piv.c
 On branch sm-nist
 Changes to be committed:
	modified:   src/libopensc/card-piv.c
 Untracked files:
	sm/.sm-nist.c.swp
 Changes to be committed:
	modified:   sm/sm-nist.c
 On branch sm-nist
 Changes to be committed:
	modified:   sm/sm-nist.c
 On branch sm-nist
 Changes to be committed:
	modified:   sm/sm-nist.c
 Changes to be committed:
	modified:   libopensc/card-piv.c
	modified:   libopensc/iso7816.c
	modified:   libopensc/sm.h
	modified:   sm/sm-iso.c
	modified:   sm/sm-iso.h
	modified:   sm/sm-nist.c
 On branch sm-nist
 Changes to be committed:
	modified:   sm-nist.c
 On branch sm-nist
 Changes to be committed:
	modified:   sm/Makefile.am
	modified:   sm/sm-nist.c
Only one, but not both defines:  ENABLE_PIV_SM or ENABLE_NIST_SM
can be set at same time. This it to keep the PIV_SM code
in the source while working on this branch.

 On branch sm-nist
 Changes to be committed:
	modified:   src/libopensc/card-piv.c
piv-pairing code was defined but not used/

 On branch sm-nist
 Changes to be committed:
	modified:   card-piv.c
 On branch sm-nist
 Changes to be committed:
	modified:   ../sm/sm-nist.c
Remove some code that is in driver byt not in  sm-nist

 On branch sm-nist
 Changes to be committed:
	modified:   sm/sm-nist.c
 On branch sm-nist
 Changes to be committed:
	modified:   libopensc/card-piv.c
 On branch sm-nist
 Changes to be committed:
	modified:   ../configure.ac
 On branch sm-nist
 Changes to be committed:
	modified:   sm-iso.c
 On branch sm-nist
 Changes to be committed:
	modified:   card-piv.c
get configure ...
config.h is included more then once, as it does not have the normal
 "#ifndef _SC_file_H", "#define _SC_file_H" as other header files.

Multiple build combinations are supported:
	- Without any PIV SM
	- With SM  contained in card-piv.c
	- With SM in sm-nist.c,  useable by other card drivers
	- Without OpenSSL is a forth, but not very useful for PIV.
it was nessesary to set different defines and not try
and "#undef" any defines from config.h

The sm-nist is experimental.

 On branch sm-nist
 Changes to be committed:
	modified:card-piv.c
@frankmorgner
Copy link
Member

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 authenticate so that you can use it without problems via CMAC.

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

@dengert
Copy link
Member Author

dengert commented Apr 10, 2024

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.

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

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 #if would be removed. By leaving the old code in, and changes are made to the old code, the changes can also be made to the code in sm-nist at a later time.

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.

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.

The changes to sm/sm-iso.c deal with not breaking up the data into multiple blobs, and then using chaining after encryption, MAC additions.

From what you write, creating the protected short lenght C-APDUs with chaining 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.

Yes, that what it does, by using the SC_APDU_FLAGS_SM_CHAINING which is in OpenSC 0.24.0 9933d62

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 authenticate so that you can use it without problems via CMAC.

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.

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

@frankmorgner
Copy link
Member

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.

@frankmorgner
Copy link
Member

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 rm_padding(). Also the other initial comments should be resolved with your response.

@dengert
Copy link
Member Author

dengert commented Apr 12, 2024

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.

@frankmorgner frankmorgner marked this pull request as draft April 22, 2024 21:41
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

Successfully merging this pull request may close these issues.

None yet

2 participants