Skip to content

Commit

Permalink
PIV Secure Messaging as defined in NIST 800-73-4 5/2015
Browse files Browse the repository at this point in the history
    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
dengert authored and Jakuje committed Sep 12, 2023
1 parent 26b24c7 commit f6b4a2e
Show file tree
Hide file tree
Showing 5 changed files with 3,000 additions and 603 deletions.
38 changes: 38 additions & 0 deletions etc/opensc.conf.example.in
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,44 @@ app default {
# in the 'pkcs11' section below
}

card_driver PIV-II {
# "piv_max_object_size"
# defines the buffer size used to read PIV objects
# Although NIST sp800-73-4 lists object sizes, these are not hard limits.
# Other PIV-like cards may have larger objects.
# Maximum: 65535
# Minimum: 16384
# Default: 16384
# piv_max_object_size = 16384;
# May be set via environment: PIV_MAX_OBJECT_SIZE=16384

# "piv_use_sm"
# NIST sp800-73-4 supports Secure Messaging (SM), an optional feature.
#
# "piv_use_sm" may be set to:
# never - Don't use it. Card will react the same as cards without SM.
# always - Always use SM if card supports it for contact and contactless
# default - If card supports SM use for contactless (NFC) and for PIN, crypto,
# and sensitive objects with contact.
# piv_use_sm = "default";
# May be set via environment: PIV_USE_SM=default

# "piv_pairing_code"
# Virtual Contact Interface (VCI) an optional feature, to allow
# contactless access to card as if it was using the contact reader.
# VCI requires SM. It may also require a pairing code which may be printed on the
# card, given to card owner when card issued or available from the card when used
# with a contact reader. Contact your card issuing agency for details on what your
# card supports.
# Pairing code can be set in opensc.conf or via environment (recommended).
# It is an 8 digit string.
# Default: no pairing code.
# piv_pairing_code = 12345678;
# May be set via environment: PIV_PAIRING_CODE=12345678

# Environment variables override opensc.conf
}

# In addition to the built-in list of known cards in the
# card driver, you can configure a new card for the driver
# using the card_atr block. The goal is to centralize
Expand Down

0 comments on commit f6b4a2e

Please sign in to comment.