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