1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker * Copyright 2020, The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker *
4*4d7e907cSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker *
8*4d7e907cSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker *
10*4d7e907cSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker */
16*4d7e907cSAndroid Build Coastguard Worker
17*4d7e907cSAndroid Build Coastguard Worker #include "EicProvisioning.h"
18*4d7e907cSAndroid Build Coastguard Worker #include "EicCommon.h"
19*4d7e907cSAndroid Build Coastguard Worker
20*4d7e907cSAndroid Build Coastguard Worker #include <inttypes.h>
21*4d7e907cSAndroid Build Coastguard Worker
22*4d7e907cSAndroid Build Coastguard Worker // Global used for assigning ids for provisioning objects.
23*4d7e907cSAndroid Build Coastguard Worker //
24*4d7e907cSAndroid Build Coastguard Worker static uint32_t gProvisioningLastIdAssigned = 0;
25*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningInit(EicProvisioning * ctx,bool testCredential)26*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) {
27*4d7e907cSAndroid Build Coastguard Worker eicMemSet(ctx, '\0', sizeof(EicProvisioning));
28*4d7e907cSAndroid Build Coastguard Worker
29*4d7e907cSAndroid Build Coastguard Worker if (!eicNextId(&gProvisioningLastIdAssigned)) {
30*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error getting id for object");
31*4d7e907cSAndroid Build Coastguard Worker return false;
32*4d7e907cSAndroid Build Coastguard Worker }
33*4d7e907cSAndroid Build Coastguard Worker ctx->id = gProvisioningLastIdAssigned;
34*4d7e907cSAndroid Build Coastguard Worker
35*4d7e907cSAndroid Build Coastguard Worker ctx->testCredential = testCredential;
36*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsRandom(ctx->storageKey, EIC_AES_128_KEY_SIZE)) {
37*4d7e907cSAndroid Build Coastguard Worker return false;
38*4d7e907cSAndroid Build Coastguard Worker }
39*4d7e907cSAndroid Build Coastguard Worker
40*4d7e907cSAndroid Build Coastguard Worker return true;
41*4d7e907cSAndroid Build Coastguard Worker }
42*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningInitForUpdate(EicProvisioning * ctx,bool testCredential,const char * docType,size_t docTypeLength,const uint8_t * encryptedCredentialKeys,size_t encryptedCredentialKeysSize)43*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType,
44*4d7e907cSAndroid Build Coastguard Worker size_t docTypeLength, const uint8_t* encryptedCredentialKeys,
45*4d7e907cSAndroid Build Coastguard Worker size_t encryptedCredentialKeysSize) {
46*4d7e907cSAndroid Build Coastguard Worker uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101];
47*4d7e907cSAndroid Build Coastguard Worker
48*4d7e907cSAndroid Build Coastguard Worker // For feature version 202009 it's 52 bytes long and for feature version 202101 it's 86
49*4d7e907cSAndroid Build Coastguard Worker // bytes (the additional data is the ProofOfProvisioning SHA-256). We need
50*4d7e907cSAndroid Build Coastguard Worker // to support loading all feature versions.
51*4d7e907cSAndroid Build Coastguard Worker //
52*4d7e907cSAndroid Build Coastguard Worker bool expectPopSha256 = false;
53*4d7e907cSAndroid Build Coastguard Worker if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 + 28) {
54*4d7e907cSAndroid Build Coastguard Worker /* do nothing */
55*4d7e907cSAndroid Build Coastguard Worker } else if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 + 28) {
56*4d7e907cSAndroid Build Coastguard Worker expectPopSha256 = true;
57*4d7e907cSAndroid Build Coastguard Worker } else {
58*4d7e907cSAndroid Build Coastguard Worker eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize);
59*4d7e907cSAndroid Build Coastguard Worker return false;
60*4d7e907cSAndroid Build Coastguard Worker }
61*4d7e907cSAndroid Build Coastguard Worker
62*4d7e907cSAndroid Build Coastguard Worker eicMemSet(ctx, '\0', sizeof(EicProvisioning));
63*4d7e907cSAndroid Build Coastguard Worker
64*4d7e907cSAndroid Build Coastguard Worker if (!eicNextId(&gProvisioningLastIdAssigned)) {
65*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error getting id for object");
66*4d7e907cSAndroid Build Coastguard Worker return false;
67*4d7e907cSAndroid Build Coastguard Worker }
68*4d7e907cSAndroid Build Coastguard Worker ctx->id = gProvisioningLastIdAssigned;
69*4d7e907cSAndroid Build Coastguard Worker
70*4d7e907cSAndroid Build Coastguard Worker ctx->testCredential = testCredential;
71*4d7e907cSAndroid Build Coastguard Worker
72*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys,
73*4d7e907cSAndroid Build Coastguard Worker encryptedCredentialKeysSize,
74*4d7e907cSAndroid Build Coastguard Worker // DocType is the additionalAuthenticatedData
75*4d7e907cSAndroid Build Coastguard Worker (const uint8_t*)docType, docTypeLength, credentialKeys)) {
76*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error decrypting CredentialKeys");
77*4d7e907cSAndroid Build Coastguard Worker return false;
78*4d7e907cSAndroid Build Coastguard Worker }
79*4d7e907cSAndroid Build Coastguard Worker
80*4d7e907cSAndroid Build Coastguard Worker // It's supposed to look like this;
81*4d7e907cSAndroid Build Coastguard Worker //
82*4d7e907cSAndroid Build Coastguard Worker // Feature version 202009:
83*4d7e907cSAndroid Build Coastguard Worker //
84*4d7e907cSAndroid Build Coastguard Worker // CredentialKeys = [
85*4d7e907cSAndroid Build Coastguard Worker // bstr, ; storageKey, a 128-bit AES key
86*4d7e907cSAndroid Build Coastguard Worker // bstr, ; credentialPrivKey, the private key for credentialKey
87*4d7e907cSAndroid Build Coastguard Worker // ]
88*4d7e907cSAndroid Build Coastguard Worker //
89*4d7e907cSAndroid Build Coastguard Worker // Feature version 202101:
90*4d7e907cSAndroid Build Coastguard Worker //
91*4d7e907cSAndroid Build Coastguard Worker // CredentialKeys = [
92*4d7e907cSAndroid Build Coastguard Worker // bstr, ; storageKey, a 128-bit AES key
93*4d7e907cSAndroid Build Coastguard Worker // bstr, ; credentialPrivKey, the private key for credentialKey
94*4d7e907cSAndroid Build Coastguard Worker // bstr ; proofOfProvisioning SHA-256
95*4d7e907cSAndroid Build Coastguard Worker // ]
96*4d7e907cSAndroid Build Coastguard Worker //
97*4d7e907cSAndroid Build Coastguard Worker // where storageKey is 16 bytes, credentialPrivateKey is 32 bytes, and proofOfProvisioning
98*4d7e907cSAndroid Build Coastguard Worker // SHA-256 is 32 bytes.
99*4d7e907cSAndroid Build Coastguard Worker //
100*4d7e907cSAndroid Build Coastguard Worker if (credentialKeys[0] != (expectPopSha256 ? 0x83 : 0x82) || // array of two or three elements
101*4d7e907cSAndroid Build Coastguard Worker credentialKeys[1] != 0x50 || // 16-byte bstr
102*4d7e907cSAndroid Build Coastguard Worker credentialKeys[18] != 0x58 || credentialKeys[19] != 0x20) { // 32-byte bstr
103*4d7e907cSAndroid Build Coastguard Worker eicDebug("Invalid CBOR for CredentialKeys");
104*4d7e907cSAndroid Build Coastguard Worker return false;
105*4d7e907cSAndroid Build Coastguard Worker }
106*4d7e907cSAndroid Build Coastguard Worker if (expectPopSha256) {
107*4d7e907cSAndroid Build Coastguard Worker if (credentialKeys[52] != 0x58 || credentialKeys[53] != 0x20) { // 32-byte bstr
108*4d7e907cSAndroid Build Coastguard Worker eicDebug("Invalid CBOR for CredentialKeys");
109*4d7e907cSAndroid Build Coastguard Worker return false;
110*4d7e907cSAndroid Build Coastguard Worker }
111*4d7e907cSAndroid Build Coastguard Worker }
112*4d7e907cSAndroid Build Coastguard Worker eicMemCpy(ctx->storageKey, credentialKeys + 2, EIC_AES_128_KEY_SIZE);
113*4d7e907cSAndroid Build Coastguard Worker eicMemCpy(ctx->credentialPrivateKey, credentialKeys + 20, EIC_P256_PRIV_KEY_SIZE);
114*4d7e907cSAndroid Build Coastguard Worker // Note: We don't care about the previous ProofOfProvisioning SHA-256
115*4d7e907cSAndroid Build Coastguard Worker ctx->isUpdate = true;
116*4d7e907cSAndroid Build Coastguard Worker return true;
117*4d7e907cSAndroid Build Coastguard Worker }
118*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningShutdown(EicProvisioning * ctx)119*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningShutdown(EicProvisioning* ctx) {
120*4d7e907cSAndroid Build Coastguard Worker if (ctx->id == 0) {
121*4d7e907cSAndroid Build Coastguard Worker eicDebug("Trying to shut down provsioning with id 0");
122*4d7e907cSAndroid Build Coastguard Worker return false;
123*4d7e907cSAndroid Build Coastguard Worker }
124*4d7e907cSAndroid Build Coastguard Worker eicDebug("Shut down provsioning with id %" PRIu32, ctx->id);
125*4d7e907cSAndroid Build Coastguard Worker eicMemSet(ctx, '\0', sizeof(EicProvisioning));
126*4d7e907cSAndroid Build Coastguard Worker return true;
127*4d7e907cSAndroid Build Coastguard Worker }
128*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningGetId(EicProvisioning * ctx,uint32_t * outId)129*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningGetId(EicProvisioning* ctx, uint32_t* outId) {
130*4d7e907cSAndroid Build Coastguard Worker *outId = ctx->id;
131*4d7e907cSAndroid Build Coastguard Worker return true;
132*4d7e907cSAndroid Build Coastguard Worker }
133*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningCreateCredentialKey(EicProvisioning * ctx,const uint8_t * challenge,size_t challengeSize,const uint8_t * applicationId,size_t applicationIdSize,const uint8_t * attestationKeyBlob,size_t attestationKeyBlobSize,const uint8_t * attestationKeyCert,size_t attestationKeyCertSize,uint8_t * publicKeyCert,size_t * publicKeyCertSize)134*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge,
135*4d7e907cSAndroid Build Coastguard Worker size_t challengeSize, const uint8_t* applicationId,
136*4d7e907cSAndroid Build Coastguard Worker size_t applicationIdSize, const uint8_t* attestationKeyBlob,
137*4d7e907cSAndroid Build Coastguard Worker size_t attestationKeyBlobSize,
138*4d7e907cSAndroid Build Coastguard Worker const uint8_t* attestationKeyCert,
139*4d7e907cSAndroid Build Coastguard Worker size_t attestationKeyCertSize, uint8_t* publicKeyCert,
140*4d7e907cSAndroid Build Coastguard Worker size_t* publicKeyCertSize) {
141*4d7e907cSAndroid Build Coastguard Worker if (ctx->isUpdate) {
142*4d7e907cSAndroid Build Coastguard Worker eicDebug("Cannot create CredentialKey on update");
143*4d7e907cSAndroid Build Coastguard Worker return false;
144*4d7e907cSAndroid Build Coastguard Worker }
145*4d7e907cSAndroid Build Coastguard Worker
146*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsCreateCredentialKey(ctx->credentialPrivateKey, challenge, challengeSize,
147*4d7e907cSAndroid Build Coastguard Worker applicationId, applicationIdSize, ctx->testCredential,
148*4d7e907cSAndroid Build Coastguard Worker attestationKeyBlob, attestationKeyBlobSize, attestationKeyCert,
149*4d7e907cSAndroid Build Coastguard Worker attestationKeyCertSize, publicKeyCert, publicKeyCertSize)) {
150*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error creating credential key");
151*4d7e907cSAndroid Build Coastguard Worker return false;
152*4d7e907cSAndroid Build Coastguard Worker }
153*4d7e907cSAndroid Build Coastguard Worker return true;
154*4d7e907cSAndroid Build Coastguard Worker }
155*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningStartPersonalization(EicProvisioning * ctx,int accessControlProfileCount,const int * entryCounts,size_t numEntryCounts,const char * docType,size_t docTypeLength,size_t expectedProofOfProvisioningSize)156*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount,
157*4d7e907cSAndroid Build Coastguard Worker const int* entryCounts, size_t numEntryCounts,
158*4d7e907cSAndroid Build Coastguard Worker const char* docType, size_t docTypeLength,
159*4d7e907cSAndroid Build Coastguard Worker size_t expectedProofOfProvisioningSize) {
160*4d7e907cSAndroid Build Coastguard Worker if (numEntryCounts >= EIC_MAX_NUM_NAMESPACES) {
161*4d7e907cSAndroid Build Coastguard Worker return false;
162*4d7e907cSAndroid Build Coastguard Worker }
163*4d7e907cSAndroid Build Coastguard Worker if (accessControlProfileCount >= EIC_MAX_NUM_ACCESS_CONTROL_PROFILE_IDS) {
164*4d7e907cSAndroid Build Coastguard Worker return false;
165*4d7e907cSAndroid Build Coastguard Worker }
166*4d7e907cSAndroid Build Coastguard Worker
167*4d7e907cSAndroid Build Coastguard Worker ctx->numEntryCounts = numEntryCounts;
168*4d7e907cSAndroid Build Coastguard Worker if (numEntryCounts > EIC_MAX_NUM_NAMESPACES) {
169*4d7e907cSAndroid Build Coastguard Worker return false;
170*4d7e907cSAndroid Build Coastguard Worker }
171*4d7e907cSAndroid Build Coastguard Worker for (size_t n = 0; n < numEntryCounts; n++) {
172*4d7e907cSAndroid Build Coastguard Worker if (entryCounts[n] >= 256) {
173*4d7e907cSAndroid Build Coastguard Worker return false;
174*4d7e907cSAndroid Build Coastguard Worker }
175*4d7e907cSAndroid Build Coastguard Worker ctx->entryCounts[n] = entryCounts[n];
176*4d7e907cSAndroid Build Coastguard Worker }
177*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespace = -1;
178*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespaceNumProcessed = 0;
179*4d7e907cSAndroid Build Coastguard Worker
180*4d7e907cSAndroid Build Coastguard Worker eicCborInit(&ctx->cbor, NULL, 0);
181*4d7e907cSAndroid Build Coastguard Worker
182*4d7e907cSAndroid Build Coastguard Worker // What we're going to sign is the COSE ToBeSigned structure which
183*4d7e907cSAndroid Build Coastguard Worker // looks like the following:
184*4d7e907cSAndroid Build Coastguard Worker //
185*4d7e907cSAndroid Build Coastguard Worker // Sig_structure = [
186*4d7e907cSAndroid Build Coastguard Worker // context : "Signature" / "Signature1" / "CounterSignature",
187*4d7e907cSAndroid Build Coastguard Worker // body_protected : empty_or_serialized_map,
188*4d7e907cSAndroid Build Coastguard Worker // ? sign_protected : empty_or_serialized_map,
189*4d7e907cSAndroid Build Coastguard Worker // external_aad : bstr,
190*4d7e907cSAndroid Build Coastguard Worker // payload : bstr
191*4d7e907cSAndroid Build Coastguard Worker // ]
192*4d7e907cSAndroid Build Coastguard Worker //
193*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, 4);
194*4d7e907cSAndroid Build Coastguard Worker eicCborAppendStringZ(&ctx->cbor, "Signature1");
195*4d7e907cSAndroid Build Coastguard Worker
196*4d7e907cSAndroid Build Coastguard Worker // The COSE Encoded protected headers is just a single field with
197*4d7e907cSAndroid Build Coastguard Worker // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just
198*4d7e907cSAndroid Build Coastguard Worker // hard-code the CBOR encoding:
199*4d7e907cSAndroid Build Coastguard Worker static const uint8_t coseEncodedProtectedHeaders[] = {0xa1, 0x01, 0x26};
200*4d7e907cSAndroid Build Coastguard Worker eicCborAppendByteString(&ctx->cbor, coseEncodedProtectedHeaders,
201*4d7e907cSAndroid Build Coastguard Worker sizeof(coseEncodedProtectedHeaders));
202*4d7e907cSAndroid Build Coastguard Worker
203*4d7e907cSAndroid Build Coastguard Worker // We currently don't support Externally Supplied Data (RFC 8152 section 4.3)
204*4d7e907cSAndroid Build Coastguard Worker // so external_aad is the empty bstr
205*4d7e907cSAndroid Build Coastguard Worker static const uint8_t externalAad[0] = {};
206*4d7e907cSAndroid Build Coastguard Worker eicCborAppendByteString(&ctx->cbor, externalAad, sizeof(externalAad));
207*4d7e907cSAndroid Build Coastguard Worker
208*4d7e907cSAndroid Build Coastguard Worker // For the payload, the _encoded_ form follows here. We handle this by simply
209*4d7e907cSAndroid Build Coastguard Worker // opening a bstr, and then writing the CBOR. This requires us to know the
210*4d7e907cSAndroid Build Coastguard Worker // size of said bstr, ahead of time.
211*4d7e907cSAndroid Build Coastguard Worker eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, expectedProofOfProvisioningSize);
212*4d7e907cSAndroid Build Coastguard Worker ctx->expectedCborSizeAtEnd = expectedProofOfProvisioningSize + ctx->cbor.size;
213*4d7e907cSAndroid Build Coastguard Worker
214*4d7e907cSAndroid Build Coastguard Worker eicOpsSha256Init(&ctx->proofOfProvisioningDigester);
215*4d7e907cSAndroid Build Coastguard Worker eicCborEnableSecondaryDigesterSha256(&ctx->cbor, &ctx->proofOfProvisioningDigester);
216*4d7e907cSAndroid Build Coastguard Worker
217*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, 5);
218*4d7e907cSAndroid Build Coastguard Worker eicCborAppendStringZ(&ctx->cbor, "ProofOfProvisioning");
219*4d7e907cSAndroid Build Coastguard Worker eicCborAppendString(&ctx->cbor, docType, docTypeLength);
220*4d7e907cSAndroid Build Coastguard Worker
221*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, accessControlProfileCount);
222*4d7e907cSAndroid Build Coastguard Worker
223*4d7e907cSAndroid Build Coastguard Worker return true;
224*4d7e907cSAndroid Build Coastguard Worker }
225*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningAddAccessControlProfile(EicProvisioning * ctx,int id,const uint8_t * readerCertificate,size_t readerCertificateSize,bool userAuthenticationRequired,uint64_t timeoutMillis,uint64_t secureUserId,uint8_t outMac[28],uint8_t * scratchSpace,size_t scratchSpaceSize)226*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id,
227*4d7e907cSAndroid Build Coastguard Worker const uint8_t* readerCertificate,
228*4d7e907cSAndroid Build Coastguard Worker size_t readerCertificateSize,
229*4d7e907cSAndroid Build Coastguard Worker bool userAuthenticationRequired,
230*4d7e907cSAndroid Build Coastguard Worker uint64_t timeoutMillis, uint64_t secureUserId,
231*4d7e907cSAndroid Build Coastguard Worker uint8_t outMac[28], uint8_t* scratchSpace,
232*4d7e907cSAndroid Build Coastguard Worker size_t scratchSpaceSize) {
233*4d7e907cSAndroid Build Coastguard Worker EicCbor cborBuilder;
234*4d7e907cSAndroid Build Coastguard Worker eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize);
235*4d7e907cSAndroid Build Coastguard Worker
236*4d7e907cSAndroid Build Coastguard Worker if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize,
237*4d7e907cSAndroid Build Coastguard Worker userAuthenticationRequired, timeoutMillis, secureUserId)) {
238*4d7e907cSAndroid Build Coastguard Worker return false;
239*4d7e907cSAndroid Build Coastguard Worker }
240*4d7e907cSAndroid Build Coastguard Worker
241*4d7e907cSAndroid Build Coastguard Worker // Calculate and return MAC
242*4d7e907cSAndroid Build Coastguard Worker uint8_t nonce[12];
243*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsRandom(nonce, 12)) {
244*4d7e907cSAndroid Build Coastguard Worker return false;
245*4d7e907cSAndroid Build Coastguard Worker }
246*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsEncryptAes128Gcm(ctx->storageKey, nonce, NULL, 0, cborBuilder.buffer,
247*4d7e907cSAndroid Build Coastguard Worker cborBuilder.size, outMac)) {
248*4d7e907cSAndroid Build Coastguard Worker return false;
249*4d7e907cSAndroid Build Coastguard Worker }
250*4d7e907cSAndroid Build Coastguard Worker
251*4d7e907cSAndroid Build Coastguard Worker // The ACP CBOR in the provisioning receipt doesn't include secureUserId so build
252*4d7e907cSAndroid Build Coastguard Worker // it again.
253*4d7e907cSAndroid Build Coastguard Worker eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize);
254*4d7e907cSAndroid Build Coastguard Worker if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize,
255*4d7e907cSAndroid Build Coastguard Worker userAuthenticationRequired, timeoutMillis,
256*4d7e907cSAndroid Build Coastguard Worker 0 /* secureUserId */)) {
257*4d7e907cSAndroid Build Coastguard Worker return false;
258*4d7e907cSAndroid Build Coastguard Worker }
259*4d7e907cSAndroid Build Coastguard Worker
260*4d7e907cSAndroid Build Coastguard Worker // Append the CBOR from the local builder to the digester.
261*4d7e907cSAndroid Build Coastguard Worker eicCborAppend(&ctx->cbor, cborBuilder.buffer, cborBuilder.size);
262*4d7e907cSAndroid Build Coastguard Worker
263*4d7e907cSAndroid Build Coastguard Worker return true;
264*4d7e907cSAndroid Build Coastguard Worker }
265*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningBeginAddEntry(EicProvisioning * ctx,const uint8_t * accessControlProfileIds,size_t numAccessControlProfileIds,const char * nameSpace,size_t nameSpaceLength,const char * name,size_t nameLength,uint64_t entrySize,uint8_t * scratchSpace,size_t scratchSpaceSize)266*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
267*4d7e907cSAndroid Build Coastguard Worker size_t numAccessControlProfileIds, const char* nameSpace,
268*4d7e907cSAndroid Build Coastguard Worker size_t nameSpaceLength, const char* name, size_t nameLength,
269*4d7e907cSAndroid Build Coastguard Worker uint64_t entrySize, uint8_t* scratchSpace,
270*4d7e907cSAndroid Build Coastguard Worker size_t scratchSpaceSize) {
271*4d7e907cSAndroid Build Coastguard Worker uint8_t* additionalDataCbor = scratchSpace;
272*4d7e907cSAndroid Build Coastguard Worker const size_t additionalDataCborBufSize = scratchSpaceSize;
273*4d7e907cSAndroid Build Coastguard Worker size_t additionalDataCborSize;
274*4d7e907cSAndroid Build Coastguard Worker
275*4d7e907cSAndroid Build Coastguard Worker // We'll need to calc and store a digest of additionalData to check that it's the same
276*4d7e907cSAndroid Build Coastguard Worker // additionalData being passed in for every eicProvisioningAddEntryValue() call...
277*4d7e907cSAndroid Build Coastguard Worker if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
278*4d7e907cSAndroid Build Coastguard Worker nameSpace, nameSpaceLength, name, nameLength,
279*4d7e907cSAndroid Build Coastguard Worker additionalDataCbor, additionalDataCborBufSize,
280*4d7e907cSAndroid Build Coastguard Worker &additionalDataCborSize, ctx->additionalDataSha256)) {
281*4d7e907cSAndroid Build Coastguard Worker return false;
282*4d7e907cSAndroid Build Coastguard Worker }
283*4d7e907cSAndroid Build Coastguard Worker
284*4d7e907cSAndroid Build Coastguard Worker if (ctx->curNamespace == -1) {
285*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespace = 0;
286*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespaceNumProcessed = 0;
287*4d7e907cSAndroid Build Coastguard Worker // Opens the main map: { * Namespace => [ + Entry ] }
288*4d7e907cSAndroid Build Coastguard Worker eicCborAppendMap(&ctx->cbor, ctx->numEntryCounts);
289*4d7e907cSAndroid Build Coastguard Worker eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
290*4d7e907cSAndroid Build Coastguard Worker // Opens the per-namespace array: [ + Entry ]
291*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]);
292*4d7e907cSAndroid Build Coastguard Worker }
293*4d7e907cSAndroid Build Coastguard Worker
294*4d7e907cSAndroid Build Coastguard Worker if (ctx->curNamespaceNumProcessed == ctx->entryCounts[ctx->curNamespace]) {
295*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespace += 1;
296*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespaceNumProcessed = 0;
297*4d7e907cSAndroid Build Coastguard Worker eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength);
298*4d7e907cSAndroid Build Coastguard Worker // Opens the per-namespace array: [ + Entry ]
299*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]);
300*4d7e907cSAndroid Build Coastguard Worker }
301*4d7e907cSAndroid Build Coastguard Worker
302*4d7e907cSAndroid Build Coastguard Worker eicCborAppendMap(&ctx->cbor, 3);
303*4d7e907cSAndroid Build Coastguard Worker eicCborAppendStringZ(&ctx->cbor, "name");
304*4d7e907cSAndroid Build Coastguard Worker eicCborAppendString(&ctx->cbor, name, nameLength);
305*4d7e907cSAndroid Build Coastguard Worker
306*4d7e907cSAndroid Build Coastguard Worker ctx->curEntrySize = entrySize;
307*4d7e907cSAndroid Build Coastguard Worker ctx->curEntryNumBytesReceived = 0;
308*4d7e907cSAndroid Build Coastguard Worker
309*4d7e907cSAndroid Build Coastguard Worker eicCborAppendStringZ(&ctx->cbor, "value");
310*4d7e907cSAndroid Build Coastguard Worker
311*4d7e907cSAndroid Build Coastguard Worker ctx->curNamespaceNumProcessed += 1;
312*4d7e907cSAndroid Build Coastguard Worker return true;
313*4d7e907cSAndroid Build Coastguard Worker }
314*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningAddEntryValue(EicProvisioning * ctx,const uint8_t * accessControlProfileIds,size_t numAccessControlProfileIds,const char * nameSpace,size_t nameSpaceLength,const char * name,size_t nameLength,const uint8_t * content,size_t contentSize,uint8_t * outEncryptedContent,uint8_t * scratchSpace,size_t scratchSpaceSize)315*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const uint8_t* accessControlProfileIds,
316*4d7e907cSAndroid Build Coastguard Worker size_t numAccessControlProfileIds, const char* nameSpace,
317*4d7e907cSAndroid Build Coastguard Worker size_t nameSpaceLength, const char* name, size_t nameLength,
318*4d7e907cSAndroid Build Coastguard Worker const uint8_t* content, size_t contentSize,
319*4d7e907cSAndroid Build Coastguard Worker uint8_t* outEncryptedContent, uint8_t* scratchSpace,
320*4d7e907cSAndroid Build Coastguard Worker size_t scratchSpaceSize) {
321*4d7e907cSAndroid Build Coastguard Worker uint8_t* additionalDataCbor = scratchSpace;
322*4d7e907cSAndroid Build Coastguard Worker const size_t additionalDataCborBufSize = scratchSpaceSize;
323*4d7e907cSAndroid Build Coastguard Worker size_t additionalDataCborSize;
324*4d7e907cSAndroid Build Coastguard Worker uint8_t calculatedSha256[EIC_SHA256_DIGEST_SIZE];
325*4d7e907cSAndroid Build Coastguard Worker
326*4d7e907cSAndroid Build Coastguard Worker if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds,
327*4d7e907cSAndroid Build Coastguard Worker nameSpace, nameSpaceLength, name, nameLength,
328*4d7e907cSAndroid Build Coastguard Worker additionalDataCbor, additionalDataCborBufSize,
329*4d7e907cSAndroid Build Coastguard Worker &additionalDataCborSize,
330*4d7e907cSAndroid Build Coastguard Worker calculatedSha256)) {
331*4d7e907cSAndroid Build Coastguard Worker return false;
332*4d7e907cSAndroid Build Coastguard Worker }
333*4d7e907cSAndroid Build Coastguard Worker if (eicCryptoMemCmp(calculatedSha256, ctx->additionalDataSha256, EIC_SHA256_DIGEST_SIZE) != 0) {
334*4d7e907cSAndroid Build Coastguard Worker eicDebug("SHA-256 mismatch of additionalData");
335*4d7e907cSAndroid Build Coastguard Worker return false;
336*4d7e907cSAndroid Build Coastguard Worker }
337*4d7e907cSAndroid Build Coastguard Worker
338*4d7e907cSAndroid Build Coastguard Worker eicCborAppend(&ctx->cbor, content, contentSize);
339*4d7e907cSAndroid Build Coastguard Worker
340*4d7e907cSAndroid Build Coastguard Worker uint8_t nonce[12];
341*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsRandom(nonce, 12)) {
342*4d7e907cSAndroid Build Coastguard Worker return false;
343*4d7e907cSAndroid Build Coastguard Worker }
344*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsEncryptAes128Gcm(ctx->storageKey, nonce, content, contentSize, additionalDataCbor,
345*4d7e907cSAndroid Build Coastguard Worker additionalDataCborSize, outEncryptedContent)) {
346*4d7e907cSAndroid Build Coastguard Worker return false;
347*4d7e907cSAndroid Build Coastguard Worker }
348*4d7e907cSAndroid Build Coastguard Worker
349*4d7e907cSAndroid Build Coastguard Worker // If done with this entry, close the map
350*4d7e907cSAndroid Build Coastguard Worker ctx->curEntryNumBytesReceived += contentSize;
351*4d7e907cSAndroid Build Coastguard Worker if (ctx->curEntryNumBytesReceived == ctx->curEntrySize) {
352*4d7e907cSAndroid Build Coastguard Worker eicCborAppendStringZ(&ctx->cbor, "accessControlProfiles");
353*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&ctx->cbor, numAccessControlProfileIds);
354*4d7e907cSAndroid Build Coastguard Worker for (size_t n = 0; n < numAccessControlProfileIds; n++) {
355*4d7e907cSAndroid Build Coastguard Worker eicCborAppendNumber(&ctx->cbor, accessControlProfileIds[n]);
356*4d7e907cSAndroid Build Coastguard Worker }
357*4d7e907cSAndroid Build Coastguard Worker }
358*4d7e907cSAndroid Build Coastguard Worker return true;
359*4d7e907cSAndroid Build Coastguard Worker }
360*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningFinishAddingEntries(EicProvisioning * ctx,uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE])361*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningFinishAddingEntries(
362*4d7e907cSAndroid Build Coastguard Worker EicProvisioning* ctx, uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]) {
363*4d7e907cSAndroid Build Coastguard Worker uint8_t cborSha256[EIC_SHA256_DIGEST_SIZE];
364*4d7e907cSAndroid Build Coastguard Worker
365*4d7e907cSAndroid Build Coastguard Worker eicCborAppendBool(&ctx->cbor, ctx->testCredential);
366*4d7e907cSAndroid Build Coastguard Worker eicCborFinal(&ctx->cbor, cborSha256);
367*4d7e907cSAndroid Build Coastguard Worker
368*4d7e907cSAndroid Build Coastguard Worker // This verifies that the correct expectedProofOfProvisioningSize value was
369*4d7e907cSAndroid Build Coastguard Worker // passed in at eicStartPersonalization() time.
370*4d7e907cSAndroid Build Coastguard Worker if (ctx->cbor.size != ctx->expectedCborSizeAtEnd) {
371*4d7e907cSAndroid Build Coastguard Worker eicDebug("CBOR size is %zd, was expecting %zd", ctx->cbor.size, ctx->expectedCborSizeAtEnd);
372*4d7e907cSAndroid Build Coastguard Worker return false;
373*4d7e907cSAndroid Build Coastguard Worker }
374*4d7e907cSAndroid Build Coastguard Worker
375*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsEcDsa(ctx->credentialPrivateKey, cborSha256, signatureOfToBeSigned)) {
376*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error signing proofOfProvisioning");
377*4d7e907cSAndroid Build Coastguard Worker return false;
378*4d7e907cSAndroid Build Coastguard Worker }
379*4d7e907cSAndroid Build Coastguard Worker
380*4d7e907cSAndroid Build Coastguard Worker return true;
381*4d7e907cSAndroid Build Coastguard Worker }
382*4d7e907cSAndroid Build Coastguard Worker
eicProvisioningFinishGetCredentialData(EicProvisioning * ctx,const char * docType,size_t docTypeLength,uint8_t * encryptedCredentialKeys,size_t * encryptedCredentialKeysSize)383*4d7e907cSAndroid Build Coastguard Worker bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType,
384*4d7e907cSAndroid Build Coastguard Worker size_t docTypeLength,
385*4d7e907cSAndroid Build Coastguard Worker uint8_t* encryptedCredentialKeys,
386*4d7e907cSAndroid Build Coastguard Worker size_t* encryptedCredentialKeysSize) {
387*4d7e907cSAndroid Build Coastguard Worker EicCbor cbor;
388*4d7e907cSAndroid Build Coastguard Worker uint8_t cborBuf[86];
389*4d7e907cSAndroid Build Coastguard Worker
390*4d7e907cSAndroid Build Coastguard Worker if (*encryptedCredentialKeysSize < 86 + 28) {
391*4d7e907cSAndroid Build Coastguard Worker eicDebug("encryptedCredentialKeysSize is %zd which is insufficient");
392*4d7e907cSAndroid Build Coastguard Worker return false;
393*4d7e907cSAndroid Build Coastguard Worker }
394*4d7e907cSAndroid Build Coastguard Worker
395*4d7e907cSAndroid Build Coastguard Worker eicCborInit(&cbor, cborBuf, sizeof(cborBuf));
396*4d7e907cSAndroid Build Coastguard Worker eicCborAppendArray(&cbor, 3);
397*4d7e907cSAndroid Build Coastguard Worker eicCborAppendByteString(&cbor, ctx->storageKey, EIC_AES_128_KEY_SIZE);
398*4d7e907cSAndroid Build Coastguard Worker eicCborAppendByteString(&cbor, ctx->credentialPrivateKey, EIC_P256_PRIV_KEY_SIZE);
399*4d7e907cSAndroid Build Coastguard Worker uint8_t popSha256[EIC_SHA256_DIGEST_SIZE];
400*4d7e907cSAndroid Build Coastguard Worker eicOpsSha256Final(&ctx->proofOfProvisioningDigester, popSha256);
401*4d7e907cSAndroid Build Coastguard Worker eicCborAppendByteString(&cbor, popSha256, EIC_SHA256_DIGEST_SIZE);
402*4d7e907cSAndroid Build Coastguard Worker if (cbor.size > sizeof(cborBuf)) {
403*4d7e907cSAndroid Build Coastguard Worker eicDebug("Exceeded buffer size");
404*4d7e907cSAndroid Build Coastguard Worker return false;
405*4d7e907cSAndroid Build Coastguard Worker }
406*4d7e907cSAndroid Build Coastguard Worker
407*4d7e907cSAndroid Build Coastguard Worker uint8_t nonce[12];
408*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsRandom(nonce, 12)) {
409*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error getting random");
410*4d7e907cSAndroid Build Coastguard Worker return false;
411*4d7e907cSAndroid Build Coastguard Worker }
412*4d7e907cSAndroid Build Coastguard Worker if (!eicOpsEncryptAes128Gcm(
413*4d7e907cSAndroid Build Coastguard Worker eicOpsGetHardwareBoundKey(ctx->testCredential), nonce, cborBuf, cbor.size,
414*4d7e907cSAndroid Build Coastguard Worker // DocType is the additionalAuthenticatedData
415*4d7e907cSAndroid Build Coastguard Worker (const uint8_t*)docType, docTypeLength, encryptedCredentialKeys)) {
416*4d7e907cSAndroid Build Coastguard Worker eicDebug("Error encrypting CredentialKeys");
417*4d7e907cSAndroid Build Coastguard Worker return false;
418*4d7e907cSAndroid Build Coastguard Worker }
419*4d7e907cSAndroid Build Coastguard Worker *encryptedCredentialKeysSize = cbor.size + 28;
420*4d7e907cSAndroid Build Coastguard Worker
421*4d7e907cSAndroid Build Coastguard Worker return true;
422*4d7e907cSAndroid Build Coastguard Worker }
423