xref: /aosp_15_r20/hardware/interfaces/identity/aidl/default/libeic/EicProvisioning.c (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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