Smart Card Subsystem Architecture

Updated: February 18, 2010

Applies To: Windows 7, Windows Server 2008 R2

Smart card subsystem architecture

Vendors provide smart cards and smart card readers, and in many cases the smart card and reader vendors are different. Reader drivers are written to the Personal Computer/Smart Card (PC/SC) standard version 1.0. Each smart card must have a CSP that uses the CryptoAPI interfaces to enable cryptographic operations and the WinSCard APIs to enable communications with smart card hardware.

Base CSP and smart card minidriver architecture for Windows 2000, Windows XP, and Windows 2003

A new CSP in Windows called the Base CSP allows smart card vendors to write smart card–specific modules called smart card minidrivers instead of writing CSPs. The Base CSP is a free, optional download available at the Microsoft Web site (https://go.microsoft.com/fwlink/?LinkId=93341).

The following figure illustrates the architecture of CryptoAPI, CSPs, the Base CSP, and smart card minidrivers.

Caching with Base CSP and smart card KSP (Windows Vista and Windows 7)

Data caching

Each CSP implements the current smart card data cache separately. The Base CSP implements a robust caching mechanism that allows a single process to minimize smart card I/O operations.

The existing global cache works as follows:

  1. The application requests a cryptographic operation. For example, a user certificate is to be read from the smart card.

  2. The CSP first checks its cache for the item.

  3. If the item is not found in the cache, or if the item is cached but is not up to date, the item is then read from the smart card.

  4. After any item has been read from the smart card, it is added to the cache. Any existing out-of-date copy of that item is replaced.

Three types of objects or data are cached by the CSP: pins (see PIN caching), certificates, and files. If any of the cached data changes, the corresponding object is re-read from the smart card in successive operations. For example, if a file is written to the smart card, the CSP cache becomes out of date for the files and other processes re-read the smart card at least once to refresh their CSP cache.

The global data cache is hosted in the smart card resource manager. Windows Vista includes two new public Windows smart card API calls, SCardWriteCache and SCardReadCache. These API calls make global data caching functionality available to applications. These API calls are supported starting with Windows Vista and Windows Server 2008.

  1. Every smart card that conforms to the new smart card minidriver specification has a 16-byte card identifier. This value is used to uniquely identify cached data pertaining to a given smart card. The standard Windows GUID type is used.

  2. These APIs allow an application to add data to and read data from the global cache.

PIN caching

The PIN cache helps the user from having to reenter a PIN each time the smart card is unauthenticated. After a smart card is authenticated, it will not differentiate among host-side applications; any application can access private data on the smart card. To mitigate this, the smart card is put under an exclusive state when an application authenticates to the smart card. However, this means that other applications cannot communicate with the smart card and will be blocked. Therefore, such exclusive connections are minimized. The problem is that a protocol such as Kerberos requires multiple signing operations, and therefore will either require exclusive access to the smart card over an extended period, or require multiple authentication operations. This is where the PIN cache is used, and it minimizes exclusive use of the smart card without forcing the user to enter his or her PIN multiple times.

The following example illustrates how this works. In this scenario, there are two applications: Outlook and Internet Explorer. Both applications use smart cards for different purposes.

  1. The user starts Outlook and tries to send a signed e-mail. The private key is on the smart card.

  2. Outlook prompts the user for the smart card PIN. The user enters the correct PIN.

  3. E-mail data is sent to the smart card for the signature operation. The Outlook client formats the response and sends the e-mail.

  4. The user opens Internet Explorer and tries to access a protected site that requires TLS client authentication.

  5. Internet Explorer prompts the user for the smart card PIN. The user enters the correct PIN.

  6. The TLS-related private key operation occurs on the smart card, and the user is authenticated and logged on.

  7. The user returns to Outlook to send another signed e-mail. This time, the user is not prompted for a PIN because the PIN is cached from the previous operation. Similarly, if the user uses Internet Explorer again to do another operation, Internet Explorer will not prompt the user for a PIN.

The Base CSP internally maintains a per-process cache of the PIN. The PIN is stored encrypted in memory. The functions that are used to secure the PIN are RtlEncryptMemory, RtlDecryptMemory, and RtlSecureZeroMemory, which will empty buffers that contained the PIN.

Smart card selection heuristics

Container specification levels

In response to a CryptAcquireContext call in CryptoAPI, the Base CSP will try to match the container that the caller specifies to a specific smart card and reader. The caller can provide a container name with varying levels of specificity, shown in the table below, sorted from most-specific to least-specific requests.

Similarly, in response to a NCryptOpenKey call in CNG, the smart card KSP tries to match the container the same way and takes the same container format as shown in the following table.

Note

Before opening a key by using the smart card KSP, a call to NCryptOpenStorageProvider (MS_SMART_CARD_KEY_STORAGE_PROVIDER) must be made.

Type Name Format

I

Reader Name and Container Name

\\.\<Reader Name>\<Container Name>

II

Reader Name and Container Name (NULL)

\\.\<Reader Name>

III

Container Name Only

<Container Name>

IV

Default Container (NULL) Only

NULL

The Base CSP and smart card KSP each cache smart card handle information about the calling process and about the smart cards the process has accessed. When searching for a smart card container, the Base CSP or smart card KSP first checks its cache for the process. If the cached handle is invalid, or no match is found, the SCardUIDlg API is called to get the card handle.

Container operations

Three container operations can be requested using CryptAcquireContext. These are:

  1. Create a new container. (The CNG equivalent of CryptAcquireContext with dwFlags set to CRYPT_NEWKEYSET is NCryptCreatePersistedKey.)

  2. Open an existing container. (The CNG equivalent of CryptAcquireContext to open the container is NCryptOpenKey.)

  3. Delete a container. (The CNG equivalent of CryptAcquireContext with dwFlags set to CRYPT_DELETEKEYSET is NCryptDeleteKey.)

The heuristics that are used to associate a cryptographic handle with a particular smart card and reader are based on the container operation requested and the level of container specification used.

The following table shows the restrictions for the container creation operation.

Specification Restriction

No silent context

Key container creation must always be able to show UI, such as the PIN prompt.

No overwriting existing containers

If the specified container already exists on the chosen smart card, either choose another smart card or cancel the operation.

Context flags

The following table shows the context flags for the container creation operation restrictions.

Flag Description

CRYPT_SILENT

No UI may be displayed during this operation.

CRYPT_MACHINE_KEYSET

No cached data should be used during this operation.

CRYPT_VERIFYCONTEXT

Only public data may be accessed on the smart card.

In addition to container operations and container specification, you must consider other user options, such as the above CryptAcquireContext flags, during smart card selection.

Important

The CRYPT_SILENT flag cannot be used with container operation 1 (create new container).

Creating a new container in silent context

Applications can call the Base CSP with CRYPT_DEFAULT_CONTAINER_OPTIONAL, set the PIN in silent context, and then create a new container in silent context:

  1. Call CryptAcquireContext by passing the smart card reader name in as type II, specifying the CRYPT_DEFAULT_CONTAINER_OPTIONAL flag.

  2. Call CryptSetProvParam by specifying PP_KEYEXCHANGE_PIN or PP_SIGNATURE_PIN and a null-terminated ASCII PIN.

  3. Release the context acquired in Step 1.

  4. Call CryptAcquireContext with CRYPT_NEWKEYSET specifying the type I format.

  5. Call CryptGenKey to create the key.

Smart card selection behavior

In some of the following scenarios, the user can be prompted to insert a smart card. If the user context is silent, this operation fails and no UI is displayed. Otherwise, in response to the UI, the user may insert a smart card or click Cancel. If the user cancels the operation, the operation fails.

In general, smart card selection behavior is handled by the SCardUIDlgSelectCard API. The Base CSP interacts with this API by calling it directly. The Base CSP also sends callback functions whose purpose is to filter and match candidate smart cards. Callers of CryptAcquireContext provide smart card matching information. Internally, the Base CSP uses a combination of smart card serial numbers, reader names, and container names to find specific smart cards.

Each call to SCardUI * may result in additional information read from a candidate smart card. The Base CSP smart card selection callbacks cache this information.

Making a reader match

For container specification levels I and II, the smart card selection process is less complex because only the smart card in the named reader can be considered a match.

  1. Find the requested reader. If it cannot be found, the process fails. (This requires a cache search by reader name.)

  2. If no smart card is in the reader, the user is prompted to insert a smart card (only in non-silent mode; if the call is made in silent mode, it will fail).

  3. For level II only, the name of the default container on the chosen smart card is determined.

  4. For container operations 2 (open existing) and 3 (delete), find the specified container. If the specified container cannot be found on this smart card, the user is prompted to insert a smart card.

  5. For container operation 1 (create new), if the specified container already exists on this smart card, the process fails.

Making a smart card match

For container specification levels III and IV, a broader method is used to match an appropriate smart card with a user context, because multiple cached smart cards might meet the criteria provided.

Open an existing default container (no reader specified)

Note

This scenario requires that you use the smart card with the Base CSP.

  1. For each smart card that has been accessed by the Base CSP and the handle and container information are cached, the Base CSP looks for a valid default container. An operation is attempted on the cached SCARDHANDLE to verify its validity. If the smart card handle is not valid, the Base CSP continues to search for a new smart card.

  2. If a matching smart card is not found in the Base CSP cache, the Base CSP calls into the smart card subsystem. SCardUIDlgSelectCard() is used with an appropriate callback filter to find a matching smart card with a valid default container.

Open an existing GUID-named container (no reader specified)

Note

This scenario requires that you use the smart card with the Base CSP.

  1. For each smart card that is already registered with the Base CSP, search for the requested container. Attempt an operation on the cached SCARDHANDLE to verify its validity. If the smart card handle is not valid, the smart card's serial number is passed to the SCardUI* API to continue searching for this specific smart card (rather than only a general match for the container name).

  2. If a matching smart card is not found in the Base CSP cache, a call is made into the smart card subsystem. SCardUIDlgSelectCard() is used with an appropriate callback filter to find a matching smart card with the requested container. Or, if a smart card serial number resulted from the search in Step 1, the callback filter attempts to match the serial number, not the container name.

Create a new container (no reader specified)

Note

This scenario requires that you use the smart card with the Base CSP.

If the PIN is not cached, no CRYPT_SILENT is allowed on container creation because the user must be prompted for a PIN, at a minimum.

For other operations, the caller may be able to acquire a "verify" context against the default container (CRYPT_DEFAULT_CONTAINER_OPTIONAL) and then make a CryptSetProvParam call to cache the user PIN for subsequent operations.

  1. For each smart card already known by the CSP, refresh the stored SCARDHANDLE and make the following checks:

    1. If the smart card has been removed, continue the search.

    2. If the smart card is still present but already has the named container, continue the search.

    3. If the smart card is available, but a call to CardQueryFreeSpace indicates that the smart card has insufficient storage for an additional key container, continue the search.

    4. Otherwise, use the first available smart card that meets the above criteria for the container creation.

  2. If a matching smart card is not found in the CSP cache, call into the smart card subsystem. The callback used to filter enumerated smart cards verifies that a candidate smart card does not already have the named container, and that CardQueryFreeSpace indicates that the smart card has sufficient space for an additional container. If no suitable smart card is found, the user is prompted to insert a smart card.

Delete a container

  1. If the specified container name is NULL, then the default container is deleted. Deleting the default container causes a new default container to be selected arbitrarily. For this reason, this operation is not recommended.

  2. For each smart card already known by the CSP, refresh the stored SCARDHANDLE and make the following checks.

    1. If the smart card does not have the named container, continue the search.

    2. If the smart card has the named container, but the smart card handle is no longer valid, store the serial number of the matching smart card and pass it to SCardUI *.

  3. If a matching smart card is not found in the CSP cache, call into the smart card subsystem. The callback used to filter enumerated smart cards should verify that a candidate smart card has the named container. If a serial number was provided as a result of the above cache search, the callback should filter enumerated smart cards on serial number rather than container matches. If the context is non-silent, and no suitable smart card is found, display UI that prompts the user to insert a smart card.

Base CSP and KSP-based architecture in Windows

Base CSP and smart card KSP properties in Windows

The following properties are supported in Windows Vista, Windows 7, Windows Server 2008, and Windows Server 2008 R2.

Note

The API definitions are located in WinCrypt.h and WinSCard.h.

Property Description

PP_USER_CERTSTORE

  • Used to return an HCERTSTORE that contains all user certificates on the smart card

  • Read-only (used only by CryptGetProvParam)

  • Caller responsible for closing the certificate store

  • Certificate encoded using PKCS_7_ASN_ENCODING or X509_ASN_ENCODING

  • CSP should set KEY_PROV_INFO on certificates

  • Certificate store should be assumed to be an in-memory store

  • Certificates should have a valid CRYPT_KEY_PROV_INFO as a property

PP_ROOT_CERTSTORE

  • Read/Write (both CryptGetProvParam and CryptSetProvParam)

  • Used to write a collection of root certificates to the smart card or return an HCERTSTORE containing root certificates from the smart card

  • Used primarily for joining a domain by using a smart card

  • Caller responsible for closing the certificate store

PP_SMARTCARD_READER

  • Read-only (only CryptGetProvParam)

  • Returns the smart card reader name as an ANSI string that is used to construct a fully qualified container name (reader + container)

PP_SMARTCARD_GUID

  • Return smart card GUID (also known as serial number), which should be unique for each smart card

  • Used by the certificate propagation service to track the source of a root certificate

PP_UI_PROMPT

  • Used to set the search string for SCardUIDlgSelectCard card insertion dialog box

  • Persistent for the entire process once it is set

  • Write only (used only by CryptSetProvParam)

Implications for CSPs in Windows

CSPs, including custom smart card CSPs, continue to be supported in Windows Vista and Windows 7. However, this approach is not recommended. Using the existing Base CSP and smart card KSP with the smart card minidriver model for smart cards provides significant benefits in terms of performance and PIN and data caching. The same minidriver can be configured to work under both CryptoAPI and CNG layers, benefiting from enhanced cryptographic support, including elliptic curve cryptography and AES.

If a smart card is registered by both a CSP and a smart card minidriver, then the one that was installed more recently will be used for communication to the smart card.

When to write a smart card minidriver, CSP, or KSP

CSPs and KSPs are meant to be written only if specific functionality is not available in the current smart card minidriver architecture. For example, the smart card minidriver architecture supports hardware security modules (HSMs), so minidriver could be written for an HSM and a CSP or KSP may not be required unless it must support algorithms that are not implemented in the Base CSP or smart card KSP.

For more information about how to write a smart card minidriver, CSP, or KSP, see Enterprise Smart Card Deployment in the Microsoft Windows Smart Card Framework (https://go.microsoft.com/fwlink/?LinkId=93349).