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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 import java.security.InvalidKeyException; 23 import java.security.KeyPair; 24 import java.security.PublicKey; 25 26 /** 27 * Class for presenting multiple documents to a remote verifier. 28 * 29 * <p>This should be used for all interactions with a remote verifier instead of the now deprecated 30 * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])} method. 31 * 32 * Use {@link IdentityCredentialStore#createPresentationSession(int)} to create a {@link 33 * PresentationSession} instance. 34 */ 35 public abstract class PresentationSession { 36 /** 37 * @hide 38 */ PresentationSession()39 protected PresentationSession() {} 40 41 /** 42 * Gets the ephemeral key pair to use to establish a secure channel with the verifier. 43 * 44 * <p>Applications should use this key-pair for the communications channel with the verifier 45 * using a protocol / cipher-suite appropriate for the application. One example of such a 46 * protocol is the one used for Mobile Driving Licenses, see ISO 18013-5. 47 * 48 * <p>The ephemeral key pair is tied to the {@link PresentationSession} instance so subsequent 49 * calls to this method will return the same key-pair. 50 * 51 * @return ephemeral key pair to use to establish a secure channel with a reader. 52 */ getEphemeralKeyPair()53 public @NonNull abstract KeyPair getEphemeralKeyPair(); 54 55 /** 56 * Set the ephemeral public key provided by the verifier. 57 * 58 * <p>If called, this must be called before any calls to 59 * {@link #getCredentialData(String, CredentialDataRequest)}. 60 * 61 * <p>This method can only be called once per {@link PresentationSession} instance. 62 * 63 * @param readerEphemeralPublicKey The ephemeral public key provided by the reader to 64 * establish a secure session. 65 * @throws InvalidKeyException if the given key is invalid. 66 */ setReaderEphemeralPublicKey(@onNull PublicKey readerEphemeralPublicKey)67 public abstract void setReaderEphemeralPublicKey(@NonNull PublicKey readerEphemeralPublicKey) 68 throws InvalidKeyException; 69 70 /** 71 * Set the session transcript. 72 * 73 * <p>If called, this must be called before any calls to 74 * {@link #getCredentialData(String, CredentialDataRequest)}. 75 * 76 * <p>If mdoc session encryption is used (e.g. if {@link #getEphemeralKeyPair()} has been 77 * called) then the X and Y coordinates of the public part of the key-pair returned by {@link 78 * #getEphemeralKeyPair()} must appear somewhere in the bytes of the passed in CBOR. Each of 79 * these coordinates must appear encoded with the most significant bits first and use the exact 80 * amount of bits indicated by the key size of the ephemeral keys. For example, if the 81 * ephemeral key is using the P-256 curve then the 32 bytes for the X coordinate encoded with 82 * the most significant bits first must appear somewhere and ditto for the 32 bytes for the Y 83 * coordinate. 84 * 85 * <p>This method can only be called once per {@link PresentationSession} instance. 86 * 87 * @param sessionTranscript the session transcript. 88 */ setSessionTranscript(@onNull byte[] sessionTranscript)89 public abstract void setSessionTranscript(@NonNull byte[] sessionTranscript); 90 91 /** 92 * Retrieves data from a named credential in the current presentation session. 93 * 94 * <p>If an access control check fails for one of the requested entries or if the entry 95 * doesn't exist, the entry is simply not returned. The application can detect this 96 * by using the {@link CredentialDataResult.Entries#getStatus(String, String)} method on 97 * each of the requested entries. 98 * 99 * <p>The application should not make any assumptions on whether user authentication is needed. 100 * Instead, the application should request the data elements values first and then examine 101 * the returned {@link CredentialDataResult.Entries}. If 102 * {@link CredentialDataResult.Entries#STATUS_USER_AUTHENTICATION_FAILED} is returned the 103 * application should get a 104 * {@link android.hardware.biometrics.BiometricPrompt.CryptoObject} which references this 105 * object and use it with a {@link android.hardware.biometrics.BiometricPrompt}. Upon successful 106 * authentication the application may call 107 * {@link #getCredentialData(String, CredentialDataRequest)} again. 108 * 109 * <p>It is permissible to call this method multiple times using the same credential name. 110 * If this is done the same auth-key will be used. 111 * 112 * <p>If the reader signature is set in the request parameter (via the 113 * {@link CredentialDataRequest.Builder#setReaderSignature(byte[])} method) it must contain 114 * the bytes of a {@code COSE_Sign1} structure as defined in RFC 8152. For the payload 115 * {@code nil} shall be used and the detached payload is the {@code ReaderAuthenticationBytes} 116 * CBOR described below. 117 * <pre> 118 * ReaderAuthentication = [ 119 * "ReaderAuthentication", 120 * SessionTranscript, 121 * ItemsRequestBytes 122 * ] 123 * 124 * ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest) 125 * 126 * ReaderAuthenticationBytes = #6.24(bstr .cbor ReaderAuthentication) 127 * </pre> 128 * 129 * <p>where {@code ItemsRequestBytes} are the bytes of the request message set in 130 * the request parameter (via the 131 * {@link CredentialDataRequest.Builder#setRequestMessage(byte[])} method). 132 * 133 * <p>The public key corresponding to the key used to make the signature, can be found in the 134 * {@code x5chain} unprotected header element of the {@code COSE_Sign1} structure (as as 135 * described in 136 * <a href="https://tools.ietf.org/html/draft-ietf-cose-x509-08">draft-ietf-cose-x509-08</a>). 137 * There will be at least one certificate in said element and there may be more (and if so, 138 * each certificate must be signed by its successor). 139 * 140 * <p>Data elements protected by reader authentication are returned if, and only if, 141 * {@code requestMessage} is signed by the top-most certificate in the reader's certificate 142 * chain, and the data element is configured with an {@link AccessControlProfile} configured 143 * with an X.509 certificate for a key which appear in the certificate chain. 144 * 145 * <p>Note that the request message CBOR is used only for enforcing reader authentication, it's 146 * not used for determining which entries this API will return. The application is expected to 147 * have parsed the request message and filtered it according to user preference and/or consent. 148 * 149 * @param credentialName the name of the credential to retrieve. 150 * @param request the data to retrieve from the credential 151 * @return If the credential wasn't found, returns null. Otherwise a 152 * {@link CredentialDataResult} object containing entry data organized by namespace and 153 * a cryptographically authenticated representation of the same data, bound to the 154 * current session. 155 * @throws NoAuthenticationKeyAvailableException if authentication keys were never 156 * provisioned for the credential or if they 157 * are expired or exhausted their use-count. 158 * @throws InvalidRequestMessageException if the requestMessage is malformed. 159 * @throws InvalidReaderSignatureException if the reader signature is invalid, or it 160 * doesn't contain a certificate chain, or if 161 * the signature failed to validate. 162 * @throws EphemeralPublicKeyNotFoundException if the ephemeral public key was not found in 163 * the session transcript. 164 */ getCredentialData( @onNull String credentialName, @NonNull CredentialDataRequest request)165 public abstract @Nullable CredentialDataResult getCredentialData( 166 @NonNull String credentialName, @NonNull CredentialDataRequest request) 167 throws NoAuthenticationKeyAvailableException, InvalidReaderSignatureException, 168 InvalidRequestMessageException, EphemeralPublicKeyNotFoundException; 169 170 /** 171 * Called by android.hardware.biometrics.CryptoObject#getOpId() to get an 172 * operation handle. 173 * 174 * @hide 175 */ getCredstoreOperationHandle()176 public abstract long getCredstoreOperationHandle(); 177 } 178