| /* |
| * Copyright 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.security.identity; |
| |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.content.Context; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * An interface to a secure store for user identity documents. |
| * |
| * <p>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. |
| * |
| * <p>Multiple credentials can be created. Each credential comprises:</p> |
| * <ul> |
| * <li>A document type, which is a string.</li> |
| * |
| * <li>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.</li> |
| * |
| * <li>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 <a href="http://cbor.io/">CBOR</a>.</li> |
| * |
| * <li>A set of access control profiles (up to 32), each with a profile ID and a specification |
| * of the conditions which satisfy the profile's requirements.</li> |
| * |
| * <li>An asymmetric key pair which is used to authenticate the credential to the Issuing |
| * Authority, called the <em>CredentialKey</em>.</li> |
| * |
| * <li>A set of zero or more named reader authentication public keys, which are used to |
| * authenticate an authorized reader to the credential.</li> |
| * |
| * <li>A set of named signing keys, which are used to sign collections of values and session |
| * transcripts.</li> |
| * </ul> |
| * |
| * <p>Implementing support for user identity documents in secure storage requires dedicated |
| * hardware-backed support and may not always be available. |
| * |
| * <p>Two different credential stores exist - the <em>default</em> store and the |
| * <em>direct access</em> 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. |
| * |
| * <p>Credentials provisioned to the direct access store should <strong>always</strong> 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. |
| * |
| * <p>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 which feature version the hardware implements (if any |
| * at all) using |
| * {@link android.content.pm#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} and |
| * {@link android.content.pm#FEATURE_IDENTITY_CREDENTIAL_HARDWARE_DIRECT_ACCESS}. |
| * Methods which only work on certain feature versions are clearly documented as |
| * such. |
| */ |
| public abstract class IdentityCredentialStore { |
| IdentityCredentialStore() {} |
| |
| /** |
| * Specifies that the cipher suite that will be used to secure communications between the reader |
| * and the prover is using the following primitives |
| * |
| * <ul> |
| * <li>ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111).</li> |
| * |
| * <li>HKDF-SHA-256 (see RFC 5869).</li> |
| * |
| * <li>AES-256-GCM (see NIST SP 800-38D).</li> |
| * |
| * <li>HMAC-SHA-256 (see RFC 2104).</li> |
| * </ul> |
| * |
| * <p>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').<p> |
| * |
| * <p> |
| * At present this is the only supported cipher suite. |
| */ |
| public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1; |
| |
| /** |
| * Gets the default {@link IdentityCredentialStore}. |
| * |
| * @param context the application context. |
| * @return the {@link IdentityCredentialStore} or {@code null} if the device doesn't |
| * have hardware-backed support for secure storage of user identity documents. |
| */ |
| public static @Nullable IdentityCredentialStore getInstance(@NonNull Context context) { |
| return CredstoreIdentityCredentialStore.getInstance(context); |
| } |
| |
| /** |
| * Gets the {@link IdentityCredentialStore} for direct access. |
| * |
| * <p>Direct access requires specialized NFC hardware and may not be supported on all |
| * devices even if default store is available. Credentials provisioned to the direct |
| * access store should <strong>always</strong> use reader authentication to protect |
| * data elements. |
| * |
| * @param context the application context. |
| * @return the {@link IdentityCredentialStore} or {@code null} if direct access is not |
| * supported on this device. |
| */ |
| public static @Nullable IdentityCredentialStore getDirectAccessInstance(@NonNull |
| Context context) { |
| return CredstoreIdentityCredentialStore.getDirectAccessInstance(context); |
| } |
| |
| /** |
| * Gets a list of supported document types. |
| * |
| * <p>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. |
| * |
| * @return The supported document types or the empty array if any document type is supported. |
| */ |
| public abstract @NonNull String[] getSupportedDocTypes(); |
| |
| /** |
| * Creates a new credential. |
| * |
| * <p>When a credential is created, a cryptographic key-pair - CredentialKey - is created which |
| * is used to authenticate the store to the Issuing Authority. The private part of this |
| * key-pair never leaves secure hardware and the public part can be obtained using |
| * {@link WritableIdentityCredential#getCredentialKeyCertificateChain(byte[])} on the |
| * returned object. |
| * |
| * <p>In addition, all of the Credential data content is imported and a certificate for the |
| * CredentialKey and a signature produced with the CredentialKey are created. These latter |
| * values may be checked by an issuing authority to verify that the data was imported into |
| * secure hardware and that it was imported unmodified. |
| * |
| * @param credentialName The name used to identify the credential. |
| * @param docType The document type for the credential. |
| * @return A {@link WritableIdentityCredential} that can be used to create a new credential. |
| * @throws AlreadyPersonalizedException if a credential with the given name already exists. |
| * @throws DocTypeNotSupportedException if the given document type isn't supported by the store. |
| */ |
| public abstract @NonNull WritableIdentityCredential createCredential( |
| @NonNull String credentialName, @NonNull String docType) |
| throws AlreadyPersonalizedException, DocTypeNotSupportedException; |
| |
| /** |
| * Retrieve a named credential. |
| * |
| * <p>The cipher suite used to communicate with the remote verifier must also be specified. |
| * Currently only a single cipher-suite is supported. Support for other cipher suites may be |
| * added in a future version of this API. |
| * |
| * @param credentialName the name of the credential to retrieve. |
| * @param cipherSuite the cipher suite to use for communicating with the verifier. |
| * @return The named credential, or null if not found. |
| */ |
| public abstract @Nullable IdentityCredential getCredentialByName(@NonNull String credentialName, |
| @Ciphersuite int cipherSuite) |
| throws CipherSuiteNotSupportedException; |
| |
| /** |
| * Delete a named credential. |
| * |
| * <p>This method returns a COSE_Sign1 data structure signed by the CredentialKey |
| * with payload set to {@code ProofOfDeletion} as defined below: |
| * |
| * <pre> |
| * ProofOfDeletion = [ |
| * "ProofOfDeletion", ; tstr |
| * tstr, ; DocType |
| * bool ; true if this is a test credential, should |
| * ; always be false. |
| * ] |
| * </pre> |
| * |
| * @param credentialName the name of the credential to delete. |
| * @return {@code null} if the credential was not found, the COSE_Sign1 data structure above |
| * if the credential was found and deleted. |
| * @deprecated Use {@link IdentityCredential#delete(byte[])} instead. |
| */ |
| @Deprecated |
| public abstract @Nullable byte[] deleteCredentialByName(@NonNull String credentialName); |
| |
| /** |
| * Creates a new presentation session. |
| * |
| * <p>This method gets an object to be used for interaction with a remote verifier for |
| * presentation of one or more credentials. |
| * |
| * <p>This is only implemented in feature version 202201 or later. If not implemented, the call |
| * fails with {@link UnsupportedOperationException}. See |
| * {@link android.content.pm.PackageManager#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} for known |
| * feature versions. |
| * |
| * @param cipherSuite the cipher suite to use for communicating with the verifier. |
| * @return The presentation session. |
| */ |
| public @NonNull PresentationSession createPresentationSession(@Ciphersuite int cipherSuite) |
| throws CipherSuiteNotSupportedException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| /** @hide */ |
| @IntDef(value = {CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256}) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface Ciphersuite { |
| } |
| } |