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