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