• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 public abstract class IdentityCredentialStore {
IdentityCredentialStore()77     IdentityCredentialStore() {}
78 
79     /**
80      * Specifies that the cipher suite that will be used to secure communications between the reader
81      * and the prover is using the following primitives
82      *
83      * <ul>
84      * <li>ECKA-DH (Elliptic Curve Key Agreement Algorithm - Diffie-Hellman, see BSI TR-03111).</li>
85      *
86      * <li>HKDF-SHA-256 (see RFC 5869).</li>
87      *
88      * <li>AES-256-GCM (see NIST SP 800-38D).</li>
89      *
90      * <li>HMAC-SHA-256 (see RFC 2104).</li>
91      * </ul>
92      *
93      * <p>The exact way these primitives are combined to derive the session key is specified in
94      * section 9.2.1.4 of ISO/IEC 18013-5 (see description of cipher suite '1').<p>
95      *
96      * <p>
97      * At present this is the only supported cipher suite.
98      */
99     public static final int CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1;
100 
101     /**
102      * Gets the default {@link IdentityCredentialStore}.
103      *
104      * @param context the application context.
105      * @return the {@link IdentityCredentialStore} or {@code null} if the device doesn't
106      *     have hardware-backed support for secure storage of user identity documents.
107      */
getInstance(@onNull Context context)108     public static @Nullable IdentityCredentialStore getInstance(@NonNull Context context) {
109         return CredstoreIdentityCredentialStore.getInstance(context);
110     }
111 
112     /**
113      * Gets the {@link IdentityCredentialStore} for direct access.
114      *
115      * <p>Direct access requires specialized NFC hardware and may not be supported on all
116      * devices even if default store is available. Credentials provisioned to the direct
117      * access store should <strong>always</strong> use reader authentication to protect
118      * data elements.
119      *
120      * @param context the application context.
121      * @return the {@link IdentityCredentialStore} or {@code null} if direct access is not
122      *     supported on this device.
123      */
getDirectAccessInstance(@onNull Context context)124     public static @Nullable IdentityCredentialStore getDirectAccessInstance(@NonNull
125             Context context) {
126         return CredstoreIdentityCredentialStore.getDirectAccessInstance(context);
127     }
128 
129     /**
130      * Gets a list of supported document types.
131      *
132      * <p>Only the direct-access store may restrict the kind of document types that can be used for
133      * credentials. The default store always supports any document type.
134      *
135      * @return The supported document types or the empty array if any document type is supported.
136      */
getSupportedDocTypes()137     public abstract @NonNull String[] getSupportedDocTypes();
138 
139     /**
140      * Creates a new credential.
141      *
142      * <p>When a credential is created, a cryptographic key-pair - CredentialKey - is created which
143      * is used to authenticate the store to the Issuing Authority.  The private part of this
144      * key-pair never leaves secure hardware and the public part can be obtained using
145      * {@link WritableIdentityCredential#getCredentialKeyCertificateChain(byte[])} on the
146      * returned object.
147      *
148      * <p>In addition, all of the Credential data content is imported and a certificate for the
149      * CredentialKey and a signature produced with the CredentialKey are created.  These latter
150      * values may be checked by an issuing authority to verify that the data was imported into
151      * secure hardware and that it was imported unmodified.
152      *
153      * @param credentialName The name used to identify the credential.
154      * @param docType        The document type for the credential.
155      * @return A {@link WritableIdentityCredential} that can be used to create a new credential.
156      * @throws AlreadyPersonalizedException if a credential with the given name already exists.
157      * @throws DocTypeNotSupportedException if the given document type isn't supported by the store.
158      */
createCredential( @onNull String credentialName, @NonNull String docType)159     public abstract @NonNull WritableIdentityCredential createCredential(
160             @NonNull String credentialName, @NonNull String docType)
161             throws AlreadyPersonalizedException, DocTypeNotSupportedException;
162 
163     /**
164      * Retrieve a named credential.
165      *
166      * <p>The cipher suite used to communicate with the remote verifier must also be specified.
167      * Currently only a single cipher-suite is supported. Support for other cipher suites may be
168      * added in a future version of this API.
169      *
170      * @param credentialName the name of the credential to retrieve.
171      * @param cipherSuite    the cipher suite to use for communicating with the verifier.
172      * @return The named credential, or null if not found.
173      */
getCredentialByName(@onNull String credentialName, @Ciphersuite int cipherSuite)174     public abstract @Nullable IdentityCredential getCredentialByName(@NonNull String credentialName,
175             @Ciphersuite int cipherSuite)
176             throws CipherSuiteNotSupportedException;
177 
178     /**
179      * Delete a named credential.
180      *
181      * <p>This method returns a COSE_Sign1 data structure signed by the CredentialKey
182      * with payload set to {@code ProofOfDeletion} as defined below:
183      *
184      * <pre>
185      *     ProofOfDeletion = [
186      *          "ProofOfDeletion",            ; tstr
187      *          tstr,                         ; DocType
188      *          bool                          ; true if this is a test credential, should
189      *                                        ; always be false.
190      *      ]
191      * </pre>
192      *
193      * @param credentialName the name of the credential to delete.
194      * @return {@code null} if the credential was not found, the COSE_Sign1 data structure above
195      *     if the credential was found and deleted.
196      */
deleteCredentialByName(@onNull String credentialName)197     public abstract @Nullable byte[] deleteCredentialByName(@NonNull String credentialName);
198 
199     /** @hide */
200     @IntDef(value = {CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256})
201     @Retention(RetentionPolicy.SOURCE)
202     public @interface Ciphersuite {
203     }
204 
205 }
206