IdentityCredentialStore

abstract class IdentityCredentialStore


An interface to a secure store for user identity documents.

This interface is deliberately fairly general and abstract. To the extent possible, specification of the message formats and semantics of communication with credential verification devices and issuing authorities (IAs) is out of scope. It provides the interface with secure storage but a credential-specific Android application will be required to implement the presentation and verification protocols and processes appropriate for the specific credential type.

Multiple credentials can be created. Each credential comprises:

  • A document type, which is a string.
  • A set of namespaces, which serve to disambiguate value names. It is recommended that namespaces be structured as reverse domain names so that IANA effectively serves as the namespace registrar.
  • For each namespace, a set of name/value pairs, each with an associated set of access control profile IDs. Names are strings and values are typed and can be any value supported by CBOR.
  • A set of access control profiles, each with a profile ID and a specification of the conditions which satisfy the profile's requirements.
  • An asymmetric key pair which is used to authenticate the credential to the Issuing Authority, called the CredentialKey.
  • A set of zero or more named reader authentication public keys, which are used to authenticate an authorized reader to the credential.
  • A set of named signing keys, which are used to sign collections of values and session transcripts.

Implementing support for user identity documents in secure storage requires dedicated hardware-backed support and may not always be available. In addition to hardware-backed Identity Credential support (which is only available in Android 11 and later and only if the device has support for the Identity Credential HAL), this Jetpack has an Android Keystore backed implementation (also known as the "software" implementation) which works on any Android device with API level 24 or later.

The Identity Credential API is designed to be able to evolve and change over time but still provide 100% backwards compatibility. This is complicated by the fact that there may be a version skew between the API used by the application and the version implemented in secure hardware. To solve this problem, the API provides for a way for the application to query for hardware capabilities through IdentityCredentialStoreCapabilities. The software-based store is designed so it implements all capabilities that don't explicitly require hardware features. Each of the methods in that class will state whether it's implemented in the software-based implementation.

When provisioning a document, applications should use getInstance to obtain an IdentityCredentialStore instance. This method returns a hardware-backed store if available and a software-based store if not and the application should use IdentityCredentialStoreCapabilities to examine if the store supports the capabilities required by the application. In the negative, the application can obtain the software-based store by calling getSoftwareInstance.

Since it's possible for an OS upgrade on a device to include an updated version of the drivers used for secure hardware, it's possible that getInstance returns the software implementation at one point and the hardware implementation at a later point. Therefore, applications should only use getInstance only when creating a credential, record whether it's hardware- or software-backed (using isHardwareBacked, and then use this information when retrieving the credential (using either getSoftwareInstance or getHardwareInstance).

Apart from hardware- vs software-backed, two different flavors of credential stores exist - the default store and the direct access store. Most often credentials will be accessed through the default store but that requires that the Android device be powered up and fully functional. It is desirable to allow identity credential usage when the Android device's battery is too low to boot the Android operating system, so direct access to the secure hardware via NFC may allow data retrieval, if the secure hardware chooses to implement it.

Credentials provisioned to the direct access store should always use reader authentication to protect data elements. The reason for this is user authentication or user approval of data release is not possible when the device is off.

Summary

Constants

const Int

Specifies that the cipher suite that will be used to secure communications between the reader and the prover is using the following primitives

Public functions

abstract WritableIdentityCredential
createCredential(credentialName: String, docType: String)

Creates a new credential.

abstract ByteArray<Byte>?
deleteCredentialByName(credentialName: String)

This function is deprecated.

Use delete instead.

IdentityCredentialStoreCapabilities

Returns the capabilities of the store.

abstract IdentityCredential?
getCredentialByName(credentialName: String, cipherSuite: Int)

Retrieve a named credential.

java-static IdentityCredentialStore

Gets the IdentityCredentialStore for direct access.

java-static IdentityCredentialStore?

Gets a IdentityCredentialStore implemented via secure hardware using the Identity Credential HAL.

java-static IdentityCredentialStore
getInstance(context: Context)

Gets the default IdentityCredentialStore.

java-static IdentityCredentialStore

Gets a IdentityCredentialStore implemented via Android Keystore.

abstract Array<String!>

This function is deprecated.

Use getSupportedDocTypes instead.

java-static Boolean

Checks if direct-access is supported.

Constants

CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256

Added in 1.0.0-alpha04
const val CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1: Int

Specifies that the cipher suite that will be used to secure communications between the reader and the prover is using the following primitives

  • ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111).
  • HKDF-SHA-256 (see RFC 5869).
  • AES-256-GCM (see NIST SP 800-38D).
  • HMAC-SHA-256 (see RFC 2104).

The exact way these primitives are combined to derive the session key is specified in section 9.2.1.4 of ISO/IEC 18013-5 (see description of cipher suite '1').

At present this is the only supported cipher suite.

Public functions

createCredential

Added in 1.0.0-alpha04
abstract fun createCredential(credentialName: String, docType: String): WritableIdentityCredential

Creates a new credential.

Parameters
credentialName: String

The name used to identify the credential.

docType: String

The document type for the credential.

Returns
WritableIdentityCredential

A @{link WritableIdentityCredential} that can be used to create a new credential.

Throws
androidx.security.identity.AlreadyPersonalizedException

if a credential with the given name already exists.

androidx.security.identity.DocTypeNotSupportedException

if the given document type isn't supported by the store.

deleteCredentialByName

Added in 1.0.0-alpha04
Deprecated in 1.0.0-alpha04
abstract fun deleteCredentialByName(credentialName: String): ByteArray<Byte>?

Delete a named credential.

This method returns a COSE_Sign1 data structure signed by the CredentialKey with payload set to ProofOfDeletion as defined below:

    ProofOfDeletion = [
         "ProofOfDeletion",            ; tstr
         tstr,                         ; DocType
         bool                          ; true if this is a test credential, should
                                       ; always be false.
     ]
Parameters
credentialName: String

the name of the credential to delete.

Returns
ByteArray<Byte>?

null if the credential was not found, the COSE_Sign1 data structure above if the credential was found and deleted.

getCapabilities

Added in 1.0.0-alpha04
fun getCapabilities(): IdentityCredentialStoreCapabilities

Returns the capabilities of the store.

Returns
IdentityCredentialStoreCapabilities

the capabilities of the store

getCredentialByName

Added in 1.0.0-alpha04
abstract fun getCredentialByName(credentialName: String, cipherSuite: Int): IdentityCredential?

Retrieve a named credential.

Parameters
credentialName: String

the name of the credential to retrieve.

cipherSuite: Int

the cipher suite to use for communicating with the verifier.

Returns
IdentityCredential?

The named credential, or null if not found.

getDirectAccessInstance

Added in 1.0.0-alpha04
java-static fun getDirectAccessInstance(context: Context): IdentityCredentialStore

Gets the IdentityCredentialStore for direct access. This should only be called if isDirectAccessSupported returns true.

Parameters
context: Context

the application context.

Returns
IdentityCredentialStore

the IdentityCredentialStore or null if direct access is not supported on this device.

getHardwareInstance

Added in 1.0.0-alpha04
java-static fun getHardwareInstance(context: Context): IdentityCredentialStore?

Gets a IdentityCredentialStore implemented via secure hardware using the Identity Credential HAL.

This only works on devices running Android 11 or later and only if the device has support for the Identity Credential HAL.

Returns
IdentityCredentialStore?

an implementation of IdentityCredentialStore implemented in secure hardware or null if the device doesn't support the Android Identity Credential HAL.

getInstance

Added in 1.0.0-alpha04
java-static fun getInstance(context: Context): IdentityCredentialStore

Gets the default IdentityCredentialStore.

Parameters
context: Context

the application context.

getSoftwareInstance

Added in 1.0.0-alpha04
java-static fun getSoftwareInstance(context: Context): IdentityCredentialStore

Gets a IdentityCredentialStore implemented via Android Keystore. This is also known as the software implementation.

Returns
IdentityCredentialStore

an implementation of IdentityCredentialStore implemented on top of Android Keystore.

getSupportedDocTypes

Added in 1.0.0-alpha04
Deprecated in 1.0.0-alpha04
abstract fun getSupportedDocTypes(): Array<String!>

Gets a list of supported document types.

Only the direct-access store may restrict the kind of document types that can be used for credentials. The default store always supports any document type.

Returns
Array<String!>

The supported document types or the empty array if any document type is supported.

isDirectAccessSupported

Added in 1.0.0-alpha04
java-static fun isDirectAccessSupported(context: Context): Boolean

Checks if direct-access is supported.

Direct access requires specialized NFC hardware and may not be supported on all devices even if default store is available.

Because Android is not running when direct-access credentials are presented, there is no way for the user to consent to release of credential data. Therefore, credentials provisioned to the direct access store should always use reader authentication to protect data elements such that only readers authorized by the issuer can access them. The setReaderCertificate method can be used at provisioning time to set which reader (or group of readers) are authorized to access data elements.

Parameters
context: Context

the application context.

Returns
Boolean

true if direct-access is supported.