1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.security.identity; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.content.Context; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 27 /** 28 * An interface to a secure store for user identity documents. 29 * 30 * <p>This interface is deliberately fairly general and abstract. To the extent possible, 31 * specification of the message formats and semantics of communication with credential 32 * verification devices and issuing authorities (IAs) is out of scope. It provides the 33 * interface with secure storage but a credential-specific Android application will be 34 * required to implement the presentation and verification protocols and processes 35 * appropriate for the specific credential type. 36 * 37 * <p>Multiple credentials can be created. Each credential comprises:</p> 38 * <ul> 39 * <li>A document type, which is a string.</li> 40 * 41 * <li>A set of namespaces, which serve to disambiguate value names. It is recommended 42 * that namespaces be structured as reverse domain names so that IANA effectively serves 43 * as the namespace registrar.</li> 44 * 45 * <li>For each namespace, a set of name/value pairs, each with an associated set of 46 * access control profile IDs. Names are strings and values are typed and can be any 47 * value supported by <a href="http://cbor.io/">CBOR</a>.</li> 48 * 49 * <li>A set of access control profiles (up to 32), each with a profile ID and a specification 50 * of the conditions which satisfy the profile's requirements.</li> 51 * 52 * <li>An asymmetric key pair which is used to authenticate the credential to the Issuing 53 * Authority, called the <em>CredentialKey</em>.</li> 54 * 55 * <li>A set of zero or more named reader authentication public keys, which are used to 56 * authenticate an authorized reader to the credential.</li> 57 * 58 * <li>A set of named signing keys, which are used to sign collections of values and session 59 * transcripts.</li> 60 * </ul> 61 * 62 * <p>Implementing support for user identity documents in secure storage requires dedicated 63 * hardware-backed support and may not always be available. 64 * 65 * <p>Two different credential stores exist - the <em>default</em> store and the 66 * <em>direct access</em> store. Most often credentials will be accessed through the default 67 * store but that requires that the Android device be powered up and fully functional. 68 * It is desirable to allow identity credential usage when the Android device's battery is too 69 * low to boot the Android operating system, so direct access to the secure hardware via NFC 70 * may allow data retrieval, if the secure hardware chooses to implement it. 71 * 72 * <p>Credentials provisioned to the direct access store should <strong>always</strong> use reader 73 * authentication to protect data elements. The reason for this is user authentication or user 74 * approval of data release is not possible when the device is off. 75 * 76 * <p>The Identity Credential API is designed to be able to evolve and change over time 77 * but still provide 100% backwards compatibility. This is complicated by the fact that 78 * there may be a version skew between the API used by the application and the version 79 * implemented in secure hardware. To solve this problem, the API provides for a way 80 * for the application to query which feature version the hardware implements (if any 81 * at all) using 82 * {@link android.content.pm#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} and 83 * {@link android.content.pm#FEATURE_IDENTITY_CREDENTIAL_HARDWARE_DIRECT_ACCESS}. 84 * Methods which only work on certain feature versions are clearly documented as 85 * such. 86 */ 87 public abstract class IdentityCredentialStore { IdentityCredentialStore()88 IdentityCredentialStore() {} 89 90 /** 91 * Specifies that the cipher suite that will be used to secure communications between the reader 92 * and the prover is using the following primitives 93 * 94 * <ul> 95 * <li>ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111).</li> 96 * 97 * <li>HKDF-SHA-256 (see RFC 5869).</li> 98 * 99 * <li>AES-256-GCM (see NIST SP 800-38D).</li> 100 * 101 * <li>HMAC-SHA-256 (see RFC 2104).</li> 102 * </ul> 103 * 104 * <p>The exact way these primitives are combined to derive the session key is specified in 105 * section 9.2.1.4 of ISO/IEC 18013-5 (see description of cipher suite '1').<p> 106 * 107 * <p> 108 * At present this is the only supported cipher suite. 109 */ 110 public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1; 111 112 /** 113 * Gets the default {@link IdentityCredentialStore}. 114 * 115 * @param context the application context. 116 * @return the {@link IdentityCredentialStore} or {@code null} if the device doesn't 117 * have hardware-backed support for secure storage of user identity documents. 118 */ getInstance(@onNull Context context)119 public static @Nullable IdentityCredentialStore getInstance(@NonNull Context context) { 120 return CredstoreIdentityCredentialStore.getInstance(context); 121 } 122 123 /** 124 * Gets the {@link IdentityCredentialStore} for direct access. 125 * 126 * <p>Direct access requires specialized NFC hardware and may not be supported on all 127 * devices even if default store is available. Credentials provisioned to the direct 128 * access store should <strong>always</strong> use reader authentication to protect 129 * data elements. 130 * 131 * @param context the application context. 132 * @return the {@link IdentityCredentialStore} or {@code null} if direct access is not 133 * supported on this device. 134 */ getDirectAccessInstance(@onNull Context context)135 public static @Nullable IdentityCredentialStore getDirectAccessInstance(@NonNull 136 Context context) { 137 return CredstoreIdentityCredentialStore.getDirectAccessInstance(context); 138 } 139 140 /** 141 * Gets a list of supported document types. 142 * 143 * <p>Only the direct-access store may restrict the kind of document types that can be used for 144 * credentials. The default store always supports any document type. 145 * 146 * @return The supported document types or the empty array if any document type is supported. 147 */ getSupportedDocTypes()148 public abstract @NonNull String[] getSupportedDocTypes(); 149 150 /** 151 * Creates a new credential. 152 * 153 * <p>When a credential is created, a cryptographic key-pair - CredentialKey - is created which 154 * is used to authenticate the store to the Issuing Authority. The private part of this 155 * key-pair never leaves secure hardware and the public part can be obtained using 156 * {@link WritableIdentityCredential#getCredentialKeyCertificateChain(byte[])} on the 157 * returned object. 158 * 159 * <p>In addition, all of the Credential data content is imported and a certificate for the 160 * CredentialKey and a signature produced with the CredentialKey are created. These latter 161 * values may be checked by an issuing authority to verify that the data was imported into 162 * secure hardware and that it was imported unmodified. 163 * 164 * @param credentialName The name used to identify the credential. 165 * @param docType The document type for the credential. 166 * @return A {@link WritableIdentityCredential} that can be used to create a new credential. 167 * @throws AlreadyPersonalizedException if a credential with the given name already exists. 168 * @throws DocTypeNotSupportedException if the given document type isn't supported by the store. 169 */ createCredential( @onNull String credentialName, @NonNull String docType)170 public abstract @NonNull WritableIdentityCredential createCredential( 171 @NonNull String credentialName, @NonNull String docType) 172 throws AlreadyPersonalizedException, DocTypeNotSupportedException; 173 174 /** 175 * Retrieve a named credential. 176 * 177 * <p>The cipher suite used to communicate with the remote verifier must also be specified. 178 * Currently only a single cipher-suite is supported. Support for other cipher suites may be 179 * added in a future version of this API. 180 * 181 * @param credentialName the name of the credential to retrieve. 182 * @param cipherSuite the cipher suite to use for communicating with the verifier. 183 * @return The named credential, or null if not found. 184 */ getCredentialByName(@onNull String credentialName, @Ciphersuite int cipherSuite)185 public abstract @Nullable IdentityCredential getCredentialByName(@NonNull String credentialName, 186 @Ciphersuite int cipherSuite) 187 throws CipherSuiteNotSupportedException; 188 189 /** 190 * Delete a named credential. 191 * 192 * <p>This method returns a COSE_Sign1 data structure signed by the CredentialKey 193 * with payload set to {@code ProofOfDeletion} as defined below: 194 * 195 * <pre> 196 * ProofOfDeletion = [ 197 * "ProofOfDeletion", ; tstr 198 * tstr, ; DocType 199 * bool ; true if this is a test credential, should 200 * ; always be false. 201 * ] 202 * </pre> 203 * 204 * @param credentialName the name of the credential to delete. 205 * @return {@code null} if the credential was not found, the COSE_Sign1 data structure above 206 * if the credential was found and deleted. 207 * @deprecated Use {@link IdentityCredential#delete(byte[])} instead. 208 */ 209 @Deprecated deleteCredentialByName(@onNull String credentialName)210 public abstract @Nullable byte[] deleteCredentialByName(@NonNull String credentialName); 211 212 /** @hide */ 213 @IntDef(value = {CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256}) 214 @Retention(RetentionPolicy.SOURCE) 215 public @interface Ciphersuite { 216 } 217 } 218