1 /*
2  * Copyright 2021 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 static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 
25 import java.lang.annotation.Retention;
26 import java.util.Collection;
27 
28 
29 /**
30  * An object that contains the result of retrieving data from a credential. This is used to return
31  * data requested in a {@link PresentationSession}.
32  */
33 public abstract class CredentialDataResult {
34     /**
35      * @hide
36      */
CredentialDataResult()37     protected CredentialDataResult() {}
38 
39     /**
40      * Returns a CBOR structure containing the retrieved device-signed data.
41      *
42      * <p>This structure - along with the session transcript - may be cryptographically
43      * authenticated to prove to the reader that the data is from a trusted credential and
44      * {@link #getDeviceMac()} can be used to get a MAC.
45      *
46      * <p>The CBOR structure which is cryptographically authenticated is the
47      * {@code DeviceAuthenticationBytes} structure according to the following
48      * <a href="https://tools.ietf.org/html/rfc8610">CDDL</a> schema:
49      *
50      * <pre>
51      *   DeviceAuthentication = [
52      *     "DeviceAuthentication",
53      *     SessionTranscript,
54      *     DocType,
55      *     DeviceNameSpacesBytes
56      *   ]
57      *
58      *   DocType = tstr
59      *   SessionTranscript = any
60      *   DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
61      *   DeviceAuthenticationBytes = #6.24(bstr .cbor DeviceAuthentication)
62      * </pre>
63      *
64      * <p>where
65      *
66      * <pre>
67      *   DeviceNameSpaces = {
68      *     * NameSpace => DeviceSignedItems
69      *   }
70      *
71      *   DeviceSignedItems = {
72      *     + DataItemName => DataItemValue
73      *   }
74      *
75      *   NameSpace = tstr
76      *   DataItemName = tstr
77      *   DataItemValue = any
78      * </pre>
79      *
80      * <p>The returned data is the binary encoding of the {@code DeviceNameSpaces} structure
81      * as defined above.
82      *
83      * @return The bytes of the {@code DeviceNameSpaces} CBOR structure.
84      */
getDeviceNameSpaces()85     public abstract @NonNull byte[] getDeviceNameSpaces();
86 
87     /**
88      * Returns a message authentication code over the {@code DeviceAuthenticationBytes} CBOR
89      * specified in {@link #getDeviceNameSpaces()}, to prove to the reader that the data
90      * is from a trusted credential.
91      *
92      * <p>The MAC proves to the reader that the data is from a trusted credential. This code is
93      * produced by using the key agreement and key derivation function from the ciphersuite
94      * with the authentication private key and the reader ephemeral public key to compute a
95      * shared message authentication code (MAC) key, then using the MAC function from the
96      * ciphersuite to compute a MAC of the authenticated data. See section 9.2.3.5 of
97      * ISO/IEC 18013-5 for details of this operation.
98      *
99      * <p>If the session transcript or reader ephemeral key wasn't set on the {@link
100      * PresentationSession} used to obtain this data no message authencation code will be produced
101      * and this method will return {@code null}.
102      *
103      * @return A COSE_Mac0 structure with the message authentication code as described above
104      *         or {@code null} if the conditions specified above are not met.
105      */
getDeviceMac()106     public abstract @Nullable byte[] getDeviceMac();
107 
108     /**
109      * Returns a signature over the {@code DeviceAuthenticationBytes} CBOR
110      * specified in {@link #getDeviceNameSpaces()}, to prove to the reader that the data
111      * is from a trusted credential.
112      *
113      * <p>The signature is made using the authentication private key. See section 9.1.3.4 of
114      * ISO/IEC 18013-5:2021 for details of this operation.
115      *
116      * <p>If the session transcript or reader ephemeral key wasn't set on the {@link
117      * PresentationSession} used to obtain this data no signature will be produced and this method
118      * will return {@code null}.
119      *
120      * <p>This is only implemented in feature version 202301 or later. If not implemented, the call
121      * fails with {@link UnsupportedOperationException}. See
122      * {@link android.content.pm.PackageManager#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} for known
123      * feature versions.
124      *
125      * @return A COSE_Sign1 structure as described above or {@code null} if the conditions
126      *     specified above are not met.
127      */
getDeviceSignature()128     public @Nullable byte[] getDeviceSignature() {
129         throw new UnsupportedOperationException();
130     }
131 
132     /**
133      * Returns the static authentication data associated with the dynamic authentication
134      * key used to MAC the data returned by {@link #getDeviceNameSpaces()}.
135      *
136      * @return The static authentication data associated with dynamic authentication key used to
137      * MAC the data.
138      */
getStaticAuthenticationData()139     public abstract @NonNull byte[] getStaticAuthenticationData();
140 
141     /**
142      * Gets the device-signed entries that was returned.
143      *
144      * @return an object to examine the entries returned.
145      */
getDeviceSignedEntries()146     public abstract @NonNull Entries getDeviceSignedEntries();
147 
148     /**
149      * Gets the issuer-signed entries that was returned.
150      *
151      * @return an object to examine the entries returned.
152      */
getIssuerSignedEntries()153     public abstract @NonNull Entries getIssuerSignedEntries();
154 
155     /**
156      * A class for representing data elements returned.
157      */
158     public interface Entries {
159         /** Value was successfully retrieved. */
160         int STATUS_OK = 0;
161 
162         /** The entry does not exist. */
163         int STATUS_NO_SUCH_ENTRY = 1;
164 
165         /** The entry was not requested. */
166         int STATUS_NOT_REQUESTED = 2;
167 
168         /** The entry wasn't in the request message. */
169         int STATUS_NOT_IN_REQUEST_MESSAGE = 3;
170 
171         /** The entry was not retrieved because user authentication failed. */
172         int STATUS_USER_AUTHENTICATION_FAILED = 4;
173 
174         /** The entry was not retrieved because reader authentication failed. */
175         int STATUS_READER_AUTHENTICATION_FAILED = 5;
176 
177         /**
178          * The entry was not retrieved because it was configured without any access
179          * control profile.
180          */
181         int STATUS_NO_ACCESS_CONTROL_PROFILES = 6;
182 
183         /**
184          * Gets the names of namespaces with retrieved entries.
185          *
186          * @return collection of name of namespaces containing retrieved entries. May be empty if no
187          *     data was retrieved.
188          */
getNamespaces()189         @NonNull Collection<String> getNamespaces();
190 
191         /**
192          * Get the names of all requested entries in a name space.
193          *
194          * <p>This includes the name of entries that wasn't successfully retrieved.
195          *
196          * @param namespaceName the namespace name to get entries for.
197          * @return A collection of names for the given namespace or the empty collection if no
198          *   entries was returned for the given name space.
199          */
getEntryNames(@onNull String namespaceName)200         @NonNull Collection<String> getEntryNames(@NonNull String namespaceName);
201 
202         /**
203          * Get the names of all entries that was successfully retrieved from a name space.
204          *
205          * <p>This only return entries for which {@link #getStatus(String, String)} will return
206          * {@link #STATUS_OK}.
207          *
208          * @param namespaceName the namespace name to get entries for.
209          * @return The entries in the given namespace that were successfully rerieved or the
210          *   empty collection if no entries was returned for the given name space.
211          */
getRetrievedEntryNames(@onNull String namespaceName)212         @NonNull Collection<String> getRetrievedEntryNames(@NonNull String namespaceName);
213 
214         /**
215          * Gets the status of an entry.
216          *
217          * <p>This returns {@link #STATUS_OK} if the value was retrieved, {@link
218          * #STATUS_NO_SUCH_ENTRY} if the given entry wasn't retrieved, {@link
219          * #STATUS_NOT_REQUESTED} if it wasn't requested, {@link #STATUS_NOT_IN_REQUEST_MESSAGE} if
220          * the request message was set but the entry wasn't present in the request message, {@link
221          * #STATUS_USER_AUTHENTICATION_FAILED} if the value wasn't retrieved because the necessary
222          * user authentication wasn't performed, {@link #STATUS_READER_AUTHENTICATION_FAILED} if
223          * the supplied reader certificate chain didn't match the set of certificates the entry was
224          * provisioned with, or {@link #STATUS_NO_ACCESS_CONTROL_PROFILES} if the entry was
225          * configured without any access control profiles.
226          *
227          * @param namespaceName the namespace name of the entry.
228          * @param name the name of the entry to get the value for.
229          * @return the status indicating whether the value was retrieved and if not, why.
230          */
getStatus(@onNull String namespaceName, @NonNull String name)231         @Status int getStatus(@NonNull String namespaceName, @NonNull String name);
232 
233         /**
234          * Gets the raw CBOR data for the value of an entry.
235          *
236          * <p>This should only be called on an entry for which the {@link #getStatus(String,
237          * String)} method returns {@link #STATUS_OK}.
238          *
239          * @param namespaceName the namespace name of the entry.
240          * @param name the name of the entry to get the value for.
241          * @return the raw CBOR data or {@code null} if no entry with the given name exists.
242          */
getEntry(@onNull String namespaceName, @NonNull String name)243         @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name);
244 
245         /**
246          * The type of the entry status.
247          * @hide
248          */
249         @Retention(SOURCE)
250         @IntDef({STATUS_OK, STATUS_NO_SUCH_ENTRY, STATUS_NOT_REQUESTED,
251                     STATUS_NOT_IN_REQUEST_MESSAGE, STATUS_USER_AUTHENTICATION_FAILED,
252                     STATUS_READER_AUTHENTICATION_FAILED, STATUS_NO_ACCESS_CONTROL_PROFILES})
253                     @interface Status {}
254     }
255 
256 }
257