Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PIV Secure Messaging as defined in NIST 800-73-4 5/2015
Looking for other users who have cards that support PIV SM and VCI for testing. Changes to PIV code for SM as defined in NIST 800-73-4. Section 4.1 The Key Establishment Protocol is done in piv_sm_open. Step names and variable names were chosen to match the names used used in 800-73-4. piv_get_sm_apdu, piv_free_sm_apdu, and piv_sm_close use the builtin SM apdu handling. This version calls piv_sm_open once from piv_init. and card->sm_ctx.sm_mode is set. See TODO below. PR has been tested with pkcs11-tool -O and --test --login using a "IDEMIA ID-One PIV 2.4 on Cosmo V8.1" with vendor provided certificates (about 25 certificates and keys) and other data objects. The test card does not have a "pairing code object" need for VCI for use over a contactless interface (NFC), But code has been added to support pairing to allow testing. The PIV SM code is only enabled if ENABLE_SM, ENABLE_OPENSSL and OPENSSL_NO_EC is not defined. It was tested with --disable_sm A card indicates it can suport SM in the response to SELECT_AID. If card can support SM, but OpenSC was built without ENABLE_SM a sc_log message will say so. card-piv.c use SC_APDU_FLAGS_SM_CHAINING from previous commit. This allows the PIV to pass a plain ADPU which needs command chaining, to SM and piv_get_sm_apdu and will encrypt and MAC the data before command chaining is done in apdu.c NIST sp800-73-4 3.3.2 extends pin policy usage flags for optional VCI and OCC are defined. Checked with valgrind, pkcs11 -O and pkcs11-tool --test --login If card supports SM it is turned on in piv_init, so if card is reset or interfered with from other process, SM will not restart. Signer certificates and CVC certificates are verified. If interfered with by other processes, and SM session is lost, it is restarted. TODO Need a way to give user paring code from card over usb after login if it is not printed on card or distributed in some other way. MD_MAX_KEY_CONTAINERS 32 add piv_logout PIV test card have more the 12 keys. "card_driver PIV_II {" block in opensc.conf See: etc/opensc.conf.example.in piv_max_object_size - removes the code to read first 8 bytes to get object size and use piv_max_object_size as read buffer size. default is 16K, max is 65K piv_use_sm - default, never, always default - use it for PIN, crypto and reading objects that are PIN protected Other objects are read in the clear for performance. never - Don't use SM, even if card supports it. Can help is situations were problems ith SM, and to debug other PIN or cryto problems. always -Like default, but read all objects using SM. piv_pairing_code - Card may require user to enter 8 digit pairing code to use VCI so card can be used over contactless as if using contact reader. VCI requires SM, and encrypts everything. All can be set via env. PIV_USE_SM= PIV_PAIRING_CODE= Used of a contactless reader is identified by the ATR 3B 8X 80 01 .... Rework PIV card matching and init for less overhead. piv_match_card_continued was committed in 4222036 2018-02-28 to handle limitations in card.c on not allowing *_match_card to pass anything other the card->type to *_init routines. These restrictions were removed in 2c0d1b9 2018-07-05. piv_match_card_continued is only called once, from piv_match_card does some checks, sets card->type, allocates piv_private_data_t, saves it in card->drv_data, calls sc_lock. If piv_match_card_continued fails, piv_match_card will call sc_lock, piv_finish and return 0 (failed to match). And just in case piv_match_card is not called, piv_init will call piv_match_card_continued. And if it fails will call sc_unlock, piv_finish and return SC_ERROR_INVALID_CARD. The card lock is finally released at end of piv_init. This allows no interference from other process during piv_match_card and piv_init. If CSAI 0xAC tag is found in the response to a SELECT AID and is used to say the card supports SM. It will still do this even if built without SM so it will show up in debug logs. PIV specs are vague and some PIV applets and a 0xAC tag for every algorithm and not just for SM. PIV Secure Messaging requires at least OpenSSL-1.1.1 or OpenSSL-3.0.0 Added equivelent code from PR 2366. Pairing code is optional, and only used when creating a VCI over contetless reader. It can be provided via env PIV_PAIRING_CODE or in opensc.conf. In any case the paring code, if provided, must be 8 ASCII digits. There is no not easy way to tell the user the code is invalid. "piv_parse_pairing_code" is added to check the length and digits. The caller will add a debug log entry if it is invalid so there is a record of the failure. With 800-73-4 Secure Messaging the SELECT AID response specifies which cryptographic algorithms under tag 0xAC are supported for Secure Messaging. The code was using the discovery object to test if the PIV applet is active as some cards have a card issue of losing the login state if the SELECT AID is used instead. (None of these cards support SM so reading the discovey object was as good as doing SELECT_AID.) The problme was found while running in contactless mode, card would work the first time becaus the discovery object would not find the PIV applet so a SELECT AID was done and it would also update the the cryptographic algorithms. When run a second time, reading the discovery object would work but the SELECT AID would only be done near the end of match routine for card types the may support 800-73-4. The duplicate "sc_atr" was not listed as one the need to have SELECT AID done. PIV change processing of CVC certificates At the request of others va github comment, the method to used to extract an optional intermediate CVC certificate was changed. Unlike other certificate objects in 800-73-4, "Table 42. Secure Messaging Certificate Signer" the "Intermediate CVC (Conditional)" does not have an enclosing tag, but uses the 0x7F21 tag. Later the 0x7F21 tag is considered part of the certificate and a hash of the the full certificate is sent to the card as part of SM. OpenSC has a number of asn1 routines such as "sc_asn1_find" to find tags but once found, they only return the address of the value(V) and its length(L) but do not return the address of the found tag(T). The previous code reconstructed the address of the found tag be calculating the number of bytes it took to encode (L) and known tag(T). 800-73-4 says the "Intermediate CVC (Conditional)" immediately follows the "CertInfo" so the address of the following byte is saved to locate where the "Intermediate CVC (Conditional)" could start. Rename dec_counter to resp_enc_counter as name was misleading 800-74-4 says: "(i.e., the IV used to encrypt the first response after successful completion of the key establishment protocol shall be generated by encrypting '80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01' with SKENC)." Use the same (encrypted) IV the card used to encrypt the response when decrypting the response. Explain how SM APDU case is derived Added comment and used defines to show how the APDU for SM is derived from the plain APDU. and how it will allow for extended APDUs if NIST allows them or card vendor in known to support them. Changes to be committed: modified: etc/opensc.conf.example.in modified: src/libopensc/card-piv.c modified: src/libopensc/cards.h modified: src/libopensc/pkcs15-piv.c modified: src/libopensc/types.h
- Loading branch information