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 #if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION) 18 #error "Never include this file directly, include libeic.h instead." 19 #endif 20 21 #ifndef ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H 22 #define ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 #include "EicCbor.h" 29 30 // The maximum size we support for public keys in reader certificates. 31 #define EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE 65 32 33 // Constant used to convey that no session is associated with a presentation. 34 #define EIC_PRESENTATION_ID_UNSET 0 35 36 typedef struct { 37 // A non-zero number unique for this EicPresentation instance 38 uint32_t id; 39 40 int featureLevel; 41 42 uint8_t storageKey[EIC_AES_128_KEY_SIZE]; 43 uint8_t credentialPrivateKey[EIC_P256_PRIV_KEY_SIZE]; 44 45 uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]; 46 47 // If non-zero (not EIC_PRESENTATION_ID_UNSET), the id of the EicSession object this 48 // presentation object is associated with. 49 uint32_t sessionId; 50 51 // The challenge generated with eicPresentationCreateAuthChallenge() 52 uint64_t authChallenge; 53 54 // Set by eicPresentationSetAuthToken() and contains the fields 55 // from the passed in authToken and verificationToken. 56 // 57 uint64_t authTokenChallenge; 58 uint64_t authTokenSecureUserId; 59 uint64_t authTokenTimestamp; 60 uint64_t verificationTokenTimestamp; 61 62 // The public key for the reader. 63 // 64 // (During the process of pushing reader certificates, this is also used to store 65 // the public key of the previously pushed certificate.) 66 // 67 uint8_t readerPublicKey[EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE]; 68 size_t readerPublicKeySize; 69 70 // This is set to true only if eicPresentationValidateRequestMessage() successfully 71 // validated the requestMessage. 72 // 73 // Why even record this? Because there's no requirement the HAL actually calls that 74 // function and we validate ACPs before it's called... so it's possible that a 75 // compromised HAL could trick us into marking ACPs as authorized while they in fact 76 // aren't. 77 bool requestMessageValidated; 78 bool buildCbor; 79 80 // Set to true initialized as a test credential. 81 bool testCredential; 82 83 // Set to true if the evaluation of access control checks in 84 // eicPresentationStartRetrieveEntryValue() resulted EIC_ACCESS_CHECK_RESULT_OK 85 bool accessCheckOk; 86 87 // These are bitmasks indicating which of the possible 32 access control profiles are 88 // authorized. They are built up by eicPresentationValidateAccessControlProfile(). 89 // 90 uint32_t accessControlProfileMaskValidated; // True if the profile was validated. 91 uint32_t accessControlProfileMaskUsesReaderAuth; // True if the ACP is using reader auth 92 uint32_t accessControlProfileMaskFailedReaderAuth; // True if failed reader auth 93 uint32_t accessControlProfileMaskFailedUserAuth; // True if failed user auth 94 95 // SHA-256 for AdditionalData, updated for each entry. 96 uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]; 97 98 // SHA-256 of ProofOfProvisioning. Set to NUL-bytes or initialized from CredentialKeys data 99 // if credential was created with feature version 202101 or later. 100 uint8_t proofOfProvisioningSha256[EIC_SHA256_DIGEST_SIZE]; 101 102 size_t expectedCborSizeAtEnd; 103 EicCbor cbor; 104 } EicPresentation; 105 106 // If sessionId is zero (EIC_PRESENTATION_ID_UNSET), the presentation object is not associated 107 // with a session object. Otherwise it's the id of the session object. 108 // 109 bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential, 110 const char* docType, size_t docTypeLength, 111 const uint8_t* encryptedCredentialKeys, 112 size_t encryptedCredentialKeysSize); 113 114 bool eicPresentationShutdown(EicPresentation* ctx); 115 116 bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId); 117 118 bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, 119 size_t docTypeLength, time_t now, 120 uint8_t* publicKeyCert, size_t* publicKeyCertSize, 121 uint8_t signingKeyBlob[60]); 122 123 // Create an ephemeral key-pair. 124 // 125 // The private key is stored in |ctx->ephemeralPrivateKey| and also returned in 126 // |ephemeralPrivateKey|. 127 // 128 bool eicPresentationCreateEphemeralKeyPair(EicPresentation* ctx, 129 uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]); 130 131 // Returns a non-zero challenge in |authChallenge|. 132 bool eicPresentationCreateAuthChallenge(EicPresentation* ctx, uint64_t* authChallenge); 133 134 // Starts retrieveing entries. 135 // 136 bool eicPresentationStartRetrieveEntries(EicPresentation* ctx); 137 138 // Sets the auth-token. 139 bool eicPresentationSetAuthToken(EicPresentation* ctx, uint64_t challenge, uint64_t secureUserId, 140 uint64_t authenticatorId, int hardwareAuthenticatorType, 141 uint64_t timeStamp, const uint8_t* mac, size_t macSize, 142 uint64_t verificationTokenChallenge, 143 uint64_t verificationTokenTimeStamp, 144 int verificationTokenSecurityLevel, 145 const uint8_t* verificationTokenMac, 146 size_t verificationTokenMacSize); 147 148 // Function to push certificates in the reader certificate chain. 149 // 150 // This should start with the root certificate (e.g. the last in the chain) and 151 // continue up the chain, ending with the certificate for the reader. 152 // 153 // Calls to this function should be interleaved with calls to the 154 // eicPresentationValidateAccessControlProfile() function, see below. 155 // 156 bool eicPresentationPushReaderCert(EicPresentation* ctx, const uint8_t* certX509, 157 size_t certX509Size); 158 159 // Checks an access control profile. 160 // 161 // Returns false if an error occurred while checking the profile (e.g. MAC doesn't check out). 162 // 163 // Returns in |accessGranted| whether access is granted. 164 // 165 // If |readerCertificate| is non-empty and the public key of one of those 166 // certificates appear in the chain presented by the reader, this function must 167 // be called after pushing that certificate using 168 // eicPresentationPushReaderCert(). 169 // 170 // The scratchSpace should be set to a buffer at least 512 bytes. It's done 171 // this way to avoid allocating stack space. 172 // 173 bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id, 174 const uint8_t* readerCertificate, 175 size_t readerCertificateSize, 176 bool userAuthenticationRequired, int timeoutMillis, 177 uint64_t secureUserId, const uint8_t mac[28], 178 bool* accessGranted, 179 uint8_t* scratchSpace, 180 size_t scratchSpaceSize); 181 182 // Validates that the given requestMessage is signed by the public key in the 183 // certificate last set with eicPresentationPushReaderCert(). 184 // 185 // The format of the signature is the same encoding as the 'signature' field of 186 // COSE_Sign1 - that is, it's the R and S integers both with the same length as 187 // the key-size. 188 // 189 // Must be called after eicPresentationPushReaderCert() have been used to push 190 // the final certificate. Which is the certificate of the reader itself. 191 // 192 bool eicPresentationValidateRequestMessage(EicPresentation* ctx, const uint8_t* sessionTranscript, 193 size_t sessionTranscriptSize, 194 const uint8_t* requestMessage, size_t requestMessageSize, 195 int coseSignAlg, 196 const uint8_t* readerSignatureOfToBeSigned, 197 size_t readerSignatureOfToBeSignedSize); 198 199 typedef enum { 200 // Returned if access is granted. 201 EIC_ACCESS_CHECK_RESULT_OK, 202 203 // Returned if an error occurred checking for access. 204 EIC_ACCESS_CHECK_RESULT_FAILED, 205 206 // Returned if access was denied because item is configured without any 207 // access control profiles. 208 EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES, 209 210 // Returned if access was denied because of user authentication. 211 EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED, 212 213 // Returned if access was denied because of reader authentication. 214 EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED, 215 } EicAccessCheckResult; 216 217 // Passes enough information to calculate the MACing key 218 // 219 bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTranscript, 220 size_t sessionTranscriptSize, 221 const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE], 222 const uint8_t signingKeyBlob[60], const char* docType, 223 size_t docTypeLength, unsigned int numNamespacesWithValues, 224 size_t expectedDeviceNamespacesSize); 225 226 // The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024 227 // bytes, the bigger the better). It's done this way to avoid allocating stack 228 // space. 229 // 230 EicAccessCheckResult eicPresentationStartRetrieveEntryValue( 231 EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength, 232 const char* name, size_t nameLength, 233 unsigned int newNamespaceNumEntries, int32_t entrySize, 234 const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, 235 uint8_t* scratchSpace, size_t scratchSpaceSize); 236 237 // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes. 238 // 239 // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to 240 // avoid allocating stack space. 241 // 242 bool eicPresentationRetrieveEntryValue(EicPresentation* ctx, const uint8_t* encryptedContent, 243 size_t encryptedContentSize, uint8_t* content, 244 const char* nameSpace, size_t nameSpaceLength, 245 const char* name, size_t nameLength, 246 const uint8_t* accessControlProfileIds, 247 size_t numAccessControlProfileIds, 248 uint8_t* scratchSpace, 249 size_t scratchSpaceSize); 250 251 // Returns the HMAC-SHA256 of |ToBeMaced| as per RFC 8051 "6.3. How to Compute 252 // and Verify a MAC". 253 bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMaced, 254 size_t* digestToBeMacedSize); 255 256 // The data returned in |signatureOfToBeSigned| contains the ECDSA signature of 257 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process" 258 // where content is set to the ProofOfDeletion CBOR. 259 // 260 bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength, 261 const uint8_t* challenge, size_t challengeSize, 262 bool includeChallenge, size_t proofOfDeletionCborSize, 263 uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]); 264 265 // The data returned in |signatureOfToBeSigned| contains the ECDSA signature of 266 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process" 267 // where content is set to the ProofOfOwnership CBOR. 268 // 269 bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, size_t docTypeLength, 270 bool testCredential, const uint8_t* challenge, size_t challengeSize, 271 size_t proofOfOwnershipCborSize, 272 uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]); 273 274 #ifdef __cplusplus 275 } 276 #endif 277 278 #endif // ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H 279