PIV smart cards and the CERT SET KEY PROV HANDLE PROP ID optimisation
PIV smart cards (NIST SP 800-73 [PIV]) are smart cards with a PIV applet installed. Unlike other smart cards, a PIV card cannot be identified by its ATR — which is contrary to the standard Calais Database architecture.
Cryptographic functions require a context acquired via CryptAcquireContext, specifying a CSP (from the Calais database) and a container. With standard smart cards, the container name is stable — built from the ATR, serial number, or card position.
569f1c0b-0caa-44ea-a695-389f96408132) from certutil -scinfoWhen a smart card is inserted, a service enumerates all containers, finds certificates, and registers them in the user store with a CRYPT_KEY_PROV_INFO structure recording the container and CSP name.
The solution: each time a PIV card is inserted, the container name changes, but the registration is re-done, and the flag CERT_SET_KEY_PROV_HANDLE_PROP_ID (also CERT_SET_KEY_CONTEXT_PROP_ID) is set.
Did you look at CryptAcquireCertificatePrivateKey? It is not simply CertGetCertificateContextProperty(CERT_KEY_PROV_INFO_PROP_ID) followed by CryptAcquireContext.
You can cache a HCRYPTPROV inside a PCCERT_CONTEXT when the flag CERT_SET_KEY_PROV_HANDLE_PROP_ID is set, then retrieve it when the flag CRYPT_ACQUIRE_USE_PROV_INFO_FLAG is set in CryptAcquireCertificatePrivateKey.
This allows you to access a container via its temporary name and optionally benefit from cached authentication. The SILENT_CONTEXT flag can be changed in CryptAcquireCertificatePrivateKey, and the CryptoAPI context is freed when the certificate context is freed.
CryptGetProvParam with PP_UNIQUE_CONTAINER returns the same container name as PP_CONTAINER.