1 /*
2  * Copyright 2020 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  * An object that contains the result of retrieving data from a credential. This is used to return
30  * data requested from a {@link IdentityCredential}.
31  */
32 public abstract class ResultData {
33 
34     /** Value was successfully retrieved. */
35     public static final int STATUS_OK = 0;
36 
37     /** The entry does not exist. */
38     public static final int STATUS_NO_SUCH_ENTRY = 1;
39 
40     /** The entry was not requested. */
41     public static final int STATUS_NOT_REQUESTED = 2;
42 
43     /** The entry wasn't in the request message. */
44     public static final int STATUS_NOT_IN_REQUEST_MESSAGE = 3;
45 
46     /** The entry was not retrieved because user authentication failed. */
47     public static final int STATUS_USER_AUTHENTICATION_FAILED = 4;
48 
49     /** The entry was not retrieved because reader authentication failed. */
50     public static final int STATUS_READER_AUTHENTICATION_FAILED = 5;
51 
52     /**
53      * The entry was not retrieved because it was configured without any access
54      * control profile.
55      */
56     public static final int STATUS_NO_ACCESS_CONTROL_PROFILES = 6;
57 
58     /**
59      * @hide
60      */
ResultData()61     protected ResultData() {}
62 
63     /**
64      * Returns a CBOR structure containing the retrieved data.
65      *
66      * <p>This structure - along with the session transcript - may be cryptographically
67      * authenticated to prove to the reader that the data is from a trusted credential and
68      * {@link #getMessageAuthenticationCode()} can be used to get a MAC.
69      *
70      * <p>The CBOR structure which is cryptographically authenticated is the
71      * {@code DeviceAuthenticationBytes} structure according to the following
72      * <a href="https://tools.ietf.org/html/rfc8610">CDDL</a> schema:
73      *
74      * <pre>
75      *   DeviceAuthentication = [
76      *     "DeviceAuthentication",
77      *     SessionTranscript,
78      *     DocType,
79      *     DeviceNameSpacesBytes
80      *   ]
81      *
82      *   DocType = tstr
83      *   SessionTranscript = any
84      *   DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
85      *   DeviceAuthenticationBytes = #6.24(bstr .cbor DeviceAuthentication)
86      * </pre>
87      *
88      * <p>where
89      *
90      * <pre>
91      *   DeviceNameSpaces = {
92      *     * NameSpace => DeviceSignedItems
93      *   }
94      *
95      *   DeviceSignedItems = {
96      *     + DataItemName => DataItemValue
97      *   }
98      *
99      *   NameSpace = tstr
100      *   DataItemName = tstr
101      *   DataItemValue = any
102      * </pre>
103      *
104      * <p>The returned data is the binary encoding of the {@code DeviceNameSpaces} structure
105      * as defined above.
106      *
107      * @return The bytes of the {@code DeviceNameSpaces} CBOR structure.
108      */
getAuthenticatedData()109     public abstract @NonNull byte[] getAuthenticatedData();
110 
111     /**
112      * Returns a message authentication code over the {@code DeviceAuthenticationBytes} CBOR
113      * specified in {@link #getAuthenticatedData()}, to prove to the reader that the data
114      * is from a trusted credential.
115      *
116      * <p>The MAC proves to the reader that the data is from a trusted credential. This code is
117      * produced by using the key agreement and key derivation function from the ciphersuite
118      * with the authentication private key and the reader ephemeral public key to compute a
119      * shared message authentication code (MAC) key, then using the MAC function from the
120      * ciphersuite to compute a MAC of the authenticated data. See section 9.2.3.5 of
121      * ISO/IEC 18013-5 for details of this operation.
122      *
123      * <p>If the {@code sessionTranscript} parameter passed to
124      * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])} was {@code null}
125      * or the reader ephmeral public key was never set using
126      * {@link IdentityCredential#setReaderEphemeralPublicKey(PublicKey)}, no message
127      * authencation code will be produced and this method will return {@code null}.
128      *
129      * @return A COSE_Mac0 structure with the message authentication code as described above
130      *         or {@code null} if the conditions specified above are not met.
131      */
getMessageAuthenticationCode()132     public abstract @Nullable byte[] getMessageAuthenticationCode();
133 
134     /**
135      * Returns the static authentication data associated with the dynamic authentication
136      * key used to sign or MAC the data returned by {@link #getAuthenticatedData()}.
137      *
138      * @return The static authentication data associated with dynamic authentication key used to
139      * MAC the data.
140      */
getStaticAuthenticationData()141     public abstract @NonNull byte[] getStaticAuthenticationData();
142 
143     /**
144      * Gets the names of namespaces with retrieved entries.
145      *
146      * @return collection of name of namespaces containing retrieved entries. May be empty if no
147      *     data was retrieved.
148      */
getNamespaces()149     public abstract @NonNull Collection<String> getNamespaces();
150 
151     /**
152      * Get the names of all entries.
153      *
154      * <p>This includes the name of entries that wasn't successfully retrieved.
155      *
156      * @param namespaceName the namespace name to get entries for.
157      * @return A collection of names or {@code null} if there are no entries for the given
158      *     namespace.
159      */
getEntryNames(@onNull String namespaceName)160     public abstract @Nullable Collection<String> getEntryNames(@NonNull String namespaceName);
161 
162     /**
163      * Get the names of all entries that was successfully retrieved.
164      *
165      * <p>This only return entries for which {@link #getStatus(String, String)} will return
166      * {@link #STATUS_OK}.
167      *
168      * @param namespaceName the namespace name to get entries for.
169      * @return A collection of names or {@code null} if there are no entries for the given
170      *     namespace.
171      */
getRetrievedEntryNames( @onNull String namespaceName)172     public abstract @Nullable Collection<String> getRetrievedEntryNames(
173             @NonNull String namespaceName);
174 
175     /**
176      * Gets the status of an entry.
177      *
178      * <p>This returns {@link #STATUS_OK} if the value was retrieved, {@link #STATUS_NO_SUCH_ENTRY}
179      * if the given entry wasn't retrieved, {@link #STATUS_NOT_REQUESTED} if it wasn't requested,
180      * {@link #STATUS_NOT_IN_REQUEST_MESSAGE} if the request message was set but the entry wasn't
181      * present in the request message, {@link #STATUS_USER_AUTHENTICATION_FAILED} if the value
182      * wasn't retrieved because the necessary user authentication wasn't performed,
183      * {@link #STATUS_READER_AUTHENTICATION_FAILED} if the supplied reader certificate chain didn't
184      * match the set of certificates the entry was provisioned with, or
185      * {@link #STATUS_NO_ACCESS_CONTROL_PROFILES} if the entry was configured without any access
186      * control profiles.
187      *
188      * @param namespaceName the namespace name of the entry.
189      * @param name the name of the entry to get the value for.
190      * @return the status indicating whether the value was retrieved and if not, why.
191      */
getStatus(@onNull String namespaceName, @NonNull String name)192     public abstract @Status int getStatus(@NonNull String namespaceName, @NonNull String name);
193 
194     /**
195      * Gets the raw CBOR data for the value of an entry.
196      *
197      * <p>This should only be called on an entry for which the {@link #getStatus(String, String)}
198      * method returns {@link #STATUS_OK}.
199      *
200      * @param namespaceName the namespace name of the entry.
201      * @param name the name of the entry to get the value for.
202      * @return the raw CBOR data or {@code null} if no entry with the given name exists.
203      */
getEntry(@onNull String namespaceName, @NonNull String name)204     public abstract @Nullable byte[] getEntry(@NonNull String namespaceName, @NonNull String name);
205 
206     /**
207      * The type of the entry status.
208      * @hide
209      */
210     @Retention(SOURCE)
211     @IntDef({STATUS_OK, STATUS_NO_SUCH_ENTRY, STATUS_NOT_REQUESTED, STATUS_NOT_IN_REQUEST_MESSAGE,
212                         STATUS_USER_AUTHENTICATION_FAILED, STATUS_READER_AUTHENTICATION_FAILED,
213                         STATUS_NO_ACCESS_CONTROL_PROFILES})
214     public @interface Status {
215     }
216 }
217