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     bool buildCborEcdsa;
80 
81     // Set to true initialized as a test credential.
82     bool testCredential;
83 
84     // Set to true if the evaluation of access control checks in
85     // eicPresentationStartRetrieveEntryValue() resulted EIC_ACCESS_CHECK_RESULT_OK
86     bool accessCheckOk;
87 
88     // These are bitmasks indicating which of the possible 32 access control profiles are
89     // authorized. They are built up by eicPresentationValidateAccessControlProfile().
90     //
91     uint32_t accessControlProfileMaskValidated;         // True if the profile was validated.
92     uint32_t accessControlProfileMaskUsesReaderAuth;    // True if the ACP is using reader auth
93     uint32_t accessControlProfileMaskFailedReaderAuth;  // True if failed reader auth
94     uint32_t accessControlProfileMaskFailedUserAuth;    // True if failed user auth
95 
96     // SHA-256 for AdditionalData, updated for each entry.
97     uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE];
98 
99     // SHA-256 of ProofOfProvisioning. Set to NUL-bytes or initialized from CredentialKeys data
100     // if credential was created with feature version 202101 or later.
101     uint8_t proofOfProvisioningSha256[EIC_SHA256_DIGEST_SIZE];
102 
103     size_t expectedCborSizeAtEnd;
104     EicCbor cbor;
105 
106     // The selected DeviceKey / AuthKey
107     uint8_t deviceKeyPriv[EIC_P256_PRIV_KEY_SIZE];
108 
109     EicCbor cborEcdsa;
110     size_t expectedCborEcdsaSizeAtEnd;
111 } EicPresentation;
112 
113 // If sessionId is zero (EIC_PRESENTATION_ID_UNSET), the presentation object is not associated
114 // with a session object. Otherwise it's the id of the session object.
115 //
116 bool eicPresentationInit(EicPresentation* ctx, uint32_t sessionId, bool testCredential,
117                          const char* docType, size_t docTypeLength,
118                          const uint8_t* encryptedCredentialKeys,
119                          size_t encryptedCredentialKeysSize);
120 
121 bool eicPresentationShutdown(EicPresentation* ctx);
122 
123 bool eicPresentationGetId(EicPresentation* ctx, uint32_t* outId);
124 
125 bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType,
126                                            size_t docTypeLength, time_t now,
127                                            uint8_t* publicKeyCert, size_t* publicKeyCertSize,
128                                            uint8_t signingKeyBlob[60]);
129 
130 // Create an ephemeral key-pair.
131 //
132 // The private key is stored in |ctx->ephemeralPrivateKey| and also returned in
133 // |ephemeralPrivateKey|.
134 //
135 bool eicPresentationCreateEphemeralKeyPair(EicPresentation* ctx,
136                                            uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]);
137 
138 // Returns a non-zero challenge in |authChallenge|.
139 bool eicPresentationCreateAuthChallenge(EicPresentation* ctx, uint64_t* authChallenge);
140 
141 // Starts retrieveing entries.
142 //
143 bool eicPresentationStartRetrieveEntries(EicPresentation* ctx);
144 
145 // Sets the auth-token.
146 bool eicPresentationSetAuthToken(EicPresentation* ctx, uint64_t challenge, uint64_t secureUserId,
147                                  uint64_t authenticatorId, int hardwareAuthenticatorType,
148                                  uint64_t timeStamp, const uint8_t* mac, size_t macSize,
149                                  uint64_t verificationTokenChallenge,
150                                  uint64_t verificationTokenTimeStamp,
151                                  int verificationTokenSecurityLevel,
152                                  const uint8_t* verificationTokenMac,
153                                  size_t verificationTokenMacSize);
154 
155 // Function to push certificates in the reader certificate chain.
156 //
157 // This should start with the root certificate (e.g. the last in the chain) and
158 // continue up the chain, ending with the certificate for the reader.
159 //
160 // Calls to this function should be interleaved with calls to the
161 // eicPresentationValidateAccessControlProfile() function, see below.
162 //
163 bool eicPresentationPushReaderCert(EicPresentation* ctx, const uint8_t* certX509,
164                                    size_t certX509Size);
165 
166 // Checks an access control profile.
167 //
168 // Returns false if an error occurred while checking the profile (e.g. MAC doesn't check out).
169 //
170 // Returns in |accessGranted| whether access is granted.
171 //
172 // If |readerCertificate| is non-empty and the public key of one of those
173 // certificates appear in the chain presented by the reader, this function must
174 // be called after pushing that certificate using
175 // eicPresentationPushReaderCert().
176 //
177 // The scratchSpace should be set to a buffer at least 512 bytes. It's done
178 // this way to avoid allocating stack space.
179 //
180 bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id,
181                                                  const uint8_t* readerCertificate,
182                                                  size_t readerCertificateSize,
183                                                  bool userAuthenticationRequired, int timeoutMillis,
184                                                  uint64_t secureUserId, const uint8_t mac[28],
185                                                  bool* accessGranted,
186                                                  uint8_t* scratchSpace,
187                                                  size_t scratchSpaceSize);
188 
189 // Validates that the given requestMessage is signed by the public key in the
190 // certificate last set with eicPresentationPushReaderCert().
191 //
192 // The format of the signature is the same encoding as the 'signature' field of
193 // COSE_Sign1 - that is, it's the R and S integers both with the same length as
194 // the key-size.
195 //
196 // Must be called after eicPresentationPushReaderCert() have been used to push
197 // the final certificate. Which is the certificate of the reader itself.
198 //
199 bool eicPresentationValidateRequestMessage(EicPresentation* ctx, const uint8_t* sessionTranscript,
200                                            size_t sessionTranscriptSize,
201                                            const uint8_t* requestMessage, size_t requestMessageSize,
202                                            int coseSignAlg,
203                                            const uint8_t* readerSignatureOfToBeSigned,
204                                            size_t readerSignatureOfToBeSignedSize);
205 
206 typedef enum {
207     // Returned if access is granted.
208     EIC_ACCESS_CHECK_RESULT_OK,
209 
210     // Returned if an error occurred checking for access.
211     EIC_ACCESS_CHECK_RESULT_FAILED,
212 
213     // Returned if access was denied because item is configured without any
214     // access control profiles.
215     EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES,
216 
217     // Returned if access was denied because of user authentication.
218     EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED,
219 
220     // Returned if access was denied because of reader authentication.
221     EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED,
222 } EicAccessCheckResult;
223 
224 // Passes enough information to calculate the MACing key and/or prepare ECDSA signing
225 //
226 bool eicPresentationPrepareDeviceAuthentication(
227         EicPresentation* ctx, const uint8_t* sessionTranscript, size_t sessionTranscriptSize,
228         const uint8_t* readerEphemeralPublicKey, size_t readerEphemeralPublicKeySize,
229         const uint8_t signingKeyBlob[60], const char* docType, size_t docTypeLength,
230         unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize);
231 
232 // The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024
233 // bytes, the bigger the better). It's done this way to avoid allocating stack
234 // space.
235 //
236 EicAccessCheckResult eicPresentationStartRetrieveEntryValue(
237         EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength,
238         const char* name, size_t nameLength,
239         unsigned int newNamespaceNumEntries, int32_t entrySize,
240         const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds,
241         uint8_t* scratchSpace, size_t scratchSpaceSize);
242 
243 // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes.
244 //
245 // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to
246 // avoid allocating stack space.
247 //
248 bool eicPresentationRetrieveEntryValue(EicPresentation* ctx, const uint8_t* encryptedContent,
249                                        size_t encryptedContentSize, uint8_t* content,
250                                        const char* nameSpace, size_t nameSpaceLength,
251                                        const char* name, size_t nameLength,
252                                        const uint8_t* accessControlProfileIds,
253                                        size_t numAccessControlProfileIds,
254                                        uint8_t* scratchSpace,
255                                        size_t scratchSpaceSize);
256 
257 // Returns the HMAC-SHA256 of |ToBeMaced| as per RFC 8051 "6.3. How to Compute
258 // and Verify a MAC".
259 bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMaced,
260                                     size_t* digestToBeMacedSize);
261 
262 // Like eicPresentationFinishRetrieval() but also returns an ECDSA signature.
263 //
264 bool eicPresentationFinishRetrievalWithSignature(EicPresentation* ctx, uint8_t* digestToBeMaced,
265                                                  size_t* digestToBeMacedSize,
266                                                  uint8_t* signatureOfToBeSigned,
267                                                  size_t* signatureOfToBeSignedSize);
268 
269 // The data returned in |signatureOfToBeSigned| contains the ECDSA signature of
270 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process"
271 // where content is set to the ProofOfDeletion CBOR.
272 //
273 bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength,
274                                      const uint8_t* challenge, size_t challengeSize,
275                                      bool includeChallenge, size_t proofOfDeletionCborSize,
276                                      uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]);
277 
278 // The data returned in |signatureOfToBeSigned| contains the ECDSA signature of
279 // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process"
280 // where content is set to the ProofOfOwnership CBOR.
281 //
282 bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, size_t docTypeLength,
283                                    bool testCredential, const uint8_t* challenge, size_t challengeSize,
284                                    size_t proofOfOwnershipCborSize,
285                                    uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]);
286 
287 #ifdef __cplusplus
288 }
289 #endif
290 
291 #endif  // ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H
292