xref: /aosp_15_r20/external/open-dice/src/cbor_cert_op.c (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1*60b67249SAndroid Build Coastguard Worker // Copyright 2021 Google LLC
2*60b67249SAndroid Build Coastguard Worker //
3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*60b67249SAndroid Build Coastguard Worker // the License at
6*60b67249SAndroid Build Coastguard Worker //
7*60b67249SAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*60b67249SAndroid Build Coastguard Worker //
9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*60b67249SAndroid Build Coastguard Worker // the License.
14*60b67249SAndroid Build Coastguard Worker 
15*60b67249SAndroid Build Coastguard Worker // This is a DiceGenerateCertificate implementation that generates a CWT-style
16*60b67249SAndroid Build Coastguard Worker // CBOR certificate. The function DiceCoseEncodePublicKey depends on the
17*60b67249SAndroid Build Coastguard Worker // signature algorithm type, and must be implemented elsewhere.
18*60b67249SAndroid Build Coastguard Worker 
19*60b67249SAndroid Build Coastguard Worker #include <stddef.h>
20*60b67249SAndroid Build Coastguard Worker #include <stdint.h>
21*60b67249SAndroid Build Coastguard Worker #include <string.h>
22*60b67249SAndroid Build Coastguard Worker 
23*60b67249SAndroid Build Coastguard Worker #include "dice/cbor_writer.h"
24*60b67249SAndroid Build Coastguard Worker #include "dice/config/cose_key_config.h"
25*60b67249SAndroid Build Coastguard Worker #include "dice/dice.h"
26*60b67249SAndroid Build Coastguard Worker #include "dice/ops.h"
27*60b67249SAndroid Build Coastguard Worker #include "dice/ops/trait/cose.h"
28*60b67249SAndroid Build Coastguard Worker #include "dice/utils.h"
29*60b67249SAndroid Build Coastguard Worker 
30*60b67249SAndroid Build Coastguard Worker // Max size of COSE_Key encoding.
31*60b67249SAndroid Build Coastguard Worker #define DICE_MAX_PUBLIC_KEY_SIZE (DICE_PUBLIC_KEY_BUFFER_SIZE + 32)
32*60b67249SAndroid Build Coastguard Worker // Max size of the COSE_Sign1 protected attributes.
33*60b67249SAndroid Build Coastguard Worker #define DICE_MAX_PROTECTED_ATTRIBUTES_SIZE 16
34*60b67249SAndroid Build Coastguard Worker 
EncodeProtectedAttributes(void * context,DicePrincipal principal,size_t buffer_size,uint8_t * buffer,size_t * encoded_size)35*60b67249SAndroid Build Coastguard Worker static DiceResult EncodeProtectedAttributes(void* context,
36*60b67249SAndroid Build Coastguard Worker                                             DicePrincipal principal,
37*60b67249SAndroid Build Coastguard Worker                                             size_t buffer_size, uint8_t* buffer,
38*60b67249SAndroid Build Coastguard Worker                                             size_t* encoded_size) {
39*60b67249SAndroid Build Coastguard Worker   // Constants per RFC 8152.
40*60b67249SAndroid Build Coastguard Worker   const int64_t kCoseHeaderAlgLabel = 1;
41*60b67249SAndroid Build Coastguard Worker 
42*60b67249SAndroid Build Coastguard Worker   struct CborOut out;
43*60b67249SAndroid Build Coastguard Worker   CborOutInit(buffer, buffer_size, &out);
44*60b67249SAndroid Build Coastguard Worker   CborWriteMap(/*num_elements=*/1, &out);
45*60b67249SAndroid Build Coastguard Worker   // Add the algorithm.
46*60b67249SAndroid Build Coastguard Worker   DiceKeyParam key_param;
47*60b67249SAndroid Build Coastguard Worker   DiceResult result = DiceGetKeyParam(context, principal, &key_param);
48*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
49*60b67249SAndroid Build Coastguard Worker     return result;
50*60b67249SAndroid Build Coastguard Worker   }
51*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseHeaderAlgLabel, &out);
52*60b67249SAndroid Build Coastguard Worker   CborWriteInt(key_param.cose_key_algorithm, &out);
53*60b67249SAndroid Build Coastguard Worker   *encoded_size = CborOutSize(&out);
54*60b67249SAndroid Build Coastguard Worker   if (CborOutOverflowed(&out)) {
55*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
56*60b67249SAndroid Build Coastguard Worker   }
57*60b67249SAndroid Build Coastguard Worker   return kDiceResultOk;
58*60b67249SAndroid Build Coastguard Worker }
59*60b67249SAndroid Build Coastguard Worker 
EncodeCoseTbs(const uint8_t * protected_attributes,size_t protected_attributes_size,size_t payload_size,const uint8_t * aad,size_t aad_size,size_t buffer_size,uint8_t * buffer,uint8_t ** payload,size_t * encoded_size)60*60b67249SAndroid Build Coastguard Worker static DiceResult EncodeCoseTbs(const uint8_t* protected_attributes,
61*60b67249SAndroid Build Coastguard Worker                                 size_t protected_attributes_size,
62*60b67249SAndroid Build Coastguard Worker                                 size_t payload_size, const uint8_t* aad,
63*60b67249SAndroid Build Coastguard Worker                                 size_t aad_size, size_t buffer_size,
64*60b67249SAndroid Build Coastguard Worker                                 uint8_t* buffer, uint8_t** payload,
65*60b67249SAndroid Build Coastguard Worker                                 size_t* encoded_size) {
66*60b67249SAndroid Build Coastguard Worker   struct CborOut out;
67*60b67249SAndroid Build Coastguard Worker   CborOutInit(buffer, buffer_size, &out);
68*60b67249SAndroid Build Coastguard Worker   // TBS is an array of four elements.
69*60b67249SAndroid Build Coastguard Worker   CborWriteArray(/*num_elements=*/4, &out);
70*60b67249SAndroid Build Coastguard Worker   // Context string field.
71*60b67249SAndroid Build Coastguard Worker   CborWriteTstr("Signature1", &out);
72*60b67249SAndroid Build Coastguard Worker   // Protected attributes from COSE_Sign1.
73*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(protected_attributes_size, protected_attributes, &out);
74*60b67249SAndroid Build Coastguard Worker   // Additional authenticated data.
75*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(aad_size, aad, &out);
76*60b67249SAndroid Build Coastguard Worker   // Space for the payload, to be filled in by the caller.
77*60b67249SAndroid Build Coastguard Worker   *payload = CborAllocBstr(payload_size, &out);
78*60b67249SAndroid Build Coastguard Worker   *encoded_size = CborOutSize(&out);
79*60b67249SAndroid Build Coastguard Worker   if (CborOutOverflowed(&out)) {
80*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
81*60b67249SAndroid Build Coastguard Worker   }
82*60b67249SAndroid Build Coastguard Worker   return kDiceResultOk;
83*60b67249SAndroid Build Coastguard Worker }
84*60b67249SAndroid Build Coastguard Worker 
EncodeCoseSign1(void * context,const uint8_t * protected_attributes,size_t protected_attributes_size,const uint8_t * payload,size_t payload_size,bool move_payload,const uint8_t signature[DICE_SIGNATURE_BUFFER_SIZE],size_t buffer_size,uint8_t * buffer,size_t * encoded_size)85*60b67249SAndroid Build Coastguard Worker static DiceResult EncodeCoseSign1(
86*60b67249SAndroid Build Coastguard Worker     void* context, const uint8_t* protected_attributes,
87*60b67249SAndroid Build Coastguard Worker     size_t protected_attributes_size, const uint8_t* payload,
88*60b67249SAndroid Build Coastguard Worker     size_t payload_size, bool move_payload,
89*60b67249SAndroid Build Coastguard Worker     const uint8_t signature[DICE_SIGNATURE_BUFFER_SIZE], size_t buffer_size,
90*60b67249SAndroid Build Coastguard Worker     uint8_t* buffer, size_t* encoded_size) {
91*60b67249SAndroid Build Coastguard Worker   struct CborOut out;
92*60b67249SAndroid Build Coastguard Worker   CborOutInit(buffer, buffer_size, &out);
93*60b67249SAndroid Build Coastguard Worker   // COSE_Sign1 is an array of four elements.
94*60b67249SAndroid Build Coastguard Worker   CborWriteArray(/*num_elements=*/4, &out);
95*60b67249SAndroid Build Coastguard Worker   // Protected attributes.
96*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(protected_attributes_size, protected_attributes, &out);
97*60b67249SAndroid Build Coastguard Worker   // Empty map for unprotected attributes.
98*60b67249SAndroid Build Coastguard Worker   CborWriteMap(/*num_pairs=*/0, &out);
99*60b67249SAndroid Build Coastguard Worker   // Payload.
100*60b67249SAndroid Build Coastguard Worker   if (move_payload) {
101*60b67249SAndroid Build Coastguard Worker     // The payload is already present in the buffer, so we can move it into
102*60b67249SAndroid Build Coastguard Worker     // place.
103*60b67249SAndroid Build Coastguard Worker     uint8_t* payload_alloc = CborAllocBstr(payload_size, &out);
104*60b67249SAndroid Build Coastguard Worker     if (payload_alloc) {
105*60b67249SAndroid Build Coastguard Worker       // We're assuming what we've written above is small enough that it doesn't
106*60b67249SAndroid Build Coastguard Worker       // overwrite the payload. Check in case that stops being true.
107*60b67249SAndroid Build Coastguard Worker       if (payload < payload_alloc) {
108*60b67249SAndroid Build Coastguard Worker         return kDiceResultPlatformError;
109*60b67249SAndroid Build Coastguard Worker       }
110*60b67249SAndroid Build Coastguard Worker       memmove(payload_alloc, payload, payload_size);
111*60b67249SAndroid Build Coastguard Worker     }
112*60b67249SAndroid Build Coastguard Worker   } else {
113*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(payload_size, payload, &out);
114*60b67249SAndroid Build Coastguard Worker   }
115*60b67249SAndroid Build Coastguard Worker   DiceKeyParam key_param;
116*60b67249SAndroid Build Coastguard Worker   DiceResult result =
117*60b67249SAndroid Build Coastguard Worker       DiceGetKeyParam(context, kDicePrincipalAuthority, &key_param);
118*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
119*60b67249SAndroid Build Coastguard Worker     return result;
120*60b67249SAndroid Build Coastguard Worker   }
121*60b67249SAndroid Build Coastguard Worker   // Signature.
122*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(/*num_elements=*/key_param.signature_size, signature, &out);
123*60b67249SAndroid Build Coastguard Worker   *encoded_size = CborOutSize(&out);
124*60b67249SAndroid Build Coastguard Worker   if (CborOutOverflowed(&out)) {
125*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
126*60b67249SAndroid Build Coastguard Worker   }
127*60b67249SAndroid Build Coastguard Worker   return kDiceResultOk;
128*60b67249SAndroid Build Coastguard Worker }
129*60b67249SAndroid Build Coastguard Worker 
DiceCoseSignAndEncodeSign1(void * context,const uint8_t * payload,size_t payload_size,const uint8_t * aad,size_t aad_size,const uint8_t private_key[DICE_PRIVATE_KEY_BUFFER_SIZE],size_t buffer_size,uint8_t * buffer,size_t * encoded_size)130*60b67249SAndroid Build Coastguard Worker DiceResult DiceCoseSignAndEncodeSign1(
131*60b67249SAndroid Build Coastguard Worker     void* context, const uint8_t* payload, size_t payload_size,
132*60b67249SAndroid Build Coastguard Worker     const uint8_t* aad, size_t aad_size,
133*60b67249SAndroid Build Coastguard Worker     const uint8_t private_key[DICE_PRIVATE_KEY_BUFFER_SIZE], size_t buffer_size,
134*60b67249SAndroid Build Coastguard Worker     uint8_t* buffer, size_t* encoded_size) {
135*60b67249SAndroid Build Coastguard Worker   DiceResult result;
136*60b67249SAndroid Build Coastguard Worker 
137*60b67249SAndroid Build Coastguard Worker   *encoded_size = 0;
138*60b67249SAndroid Build Coastguard Worker 
139*60b67249SAndroid Build Coastguard Worker   // The encoded protected attributes are used in the TBS and the final
140*60b67249SAndroid Build Coastguard Worker   // COSE_Sign1 structure.
141*60b67249SAndroid Build Coastguard Worker   uint8_t protected_attributes[DICE_MAX_PROTECTED_ATTRIBUTES_SIZE];
142*60b67249SAndroid Build Coastguard Worker   size_t protected_attributes_size = 0;
143*60b67249SAndroid Build Coastguard Worker   result = EncodeProtectedAttributes(
144*60b67249SAndroid Build Coastguard Worker       context, kDicePrincipalAuthority, sizeof(protected_attributes),
145*60b67249SAndroid Build Coastguard Worker       protected_attributes, &protected_attributes_size);
146*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
147*60b67249SAndroid Build Coastguard Worker     return kDiceResultPlatformError;
148*60b67249SAndroid Build Coastguard Worker   }
149*60b67249SAndroid Build Coastguard Worker 
150*60b67249SAndroid Build Coastguard Worker   // Construct a To-Be-Signed (TBS) structure based on the relevant fields of
151*60b67249SAndroid Build Coastguard Worker   // the COSE_Sign1.
152*60b67249SAndroid Build Coastguard Worker   uint8_t* payload_buffer;
153*60b67249SAndroid Build Coastguard Worker   result = EncodeCoseTbs(protected_attributes, protected_attributes_size,
154*60b67249SAndroid Build Coastguard Worker                          payload_size, aad, aad_size, buffer_size, buffer,
155*60b67249SAndroid Build Coastguard Worker                          &payload_buffer, encoded_size);
156*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
157*60b67249SAndroid Build Coastguard Worker     // Check how big the buffer needs to be in total.
158*60b67249SAndroid Build Coastguard Worker     size_t final_encoded_size = 0;
159*60b67249SAndroid Build Coastguard Worker     EncodeCoseSign1(context, protected_attributes, protected_attributes_size,
160*60b67249SAndroid Build Coastguard Worker                     payload, payload_size, /*move_payload=*/false,
161*60b67249SAndroid Build Coastguard Worker                     /*signature=*/NULL, /*buffer_size=*/0, /*buffer=*/NULL,
162*60b67249SAndroid Build Coastguard Worker                     &final_encoded_size);
163*60b67249SAndroid Build Coastguard Worker     if (*encoded_size < final_encoded_size) {
164*60b67249SAndroid Build Coastguard Worker       *encoded_size = final_encoded_size;
165*60b67249SAndroid Build Coastguard Worker     }
166*60b67249SAndroid Build Coastguard Worker     return result;
167*60b67249SAndroid Build Coastguard Worker   }
168*60b67249SAndroid Build Coastguard Worker   memcpy(payload_buffer, payload, payload_size);
169*60b67249SAndroid Build Coastguard Worker 
170*60b67249SAndroid Build Coastguard Worker   // Sign the TBS with the authority key.
171*60b67249SAndroid Build Coastguard Worker   uint8_t signature[DICE_SIGNATURE_BUFFER_SIZE];
172*60b67249SAndroid Build Coastguard Worker   result = DiceSign(context, buffer, *encoded_size, private_key, signature);
173*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
174*60b67249SAndroid Build Coastguard Worker     return result;
175*60b67249SAndroid Build Coastguard Worker   }
176*60b67249SAndroid Build Coastguard Worker 
177*60b67249SAndroid Build Coastguard Worker   // The final certificate is an untagged COSE_Sign1 structure.
178*60b67249SAndroid Build Coastguard Worker   return EncodeCoseSign1(context, protected_attributes,
179*60b67249SAndroid Build Coastguard Worker                          protected_attributes_size, payload, payload_size,
180*60b67249SAndroid Build Coastguard Worker                          /*move_payload=*/false, signature, buffer_size, buffer,
181*60b67249SAndroid Build Coastguard Worker                          encoded_size);
182*60b67249SAndroid Build Coastguard Worker }
183*60b67249SAndroid Build Coastguard Worker 
184*60b67249SAndroid Build Coastguard Worker // Encodes a CBOR Web Token (CWT) with an issuer, subject, and additional
185*60b67249SAndroid Build Coastguard Worker // fields.
EncodeCwt(void * context,const DiceInputValues * input_values,const char * authority_id_hex,const char * subject_id_hex,const uint8_t * encoded_public_key,size_t encoded_public_key_size,size_t buffer_size,uint8_t * buffer,size_t * encoded_size)186*60b67249SAndroid Build Coastguard Worker static DiceResult EncodeCwt(void* context, const DiceInputValues* input_values,
187*60b67249SAndroid Build Coastguard Worker                             const char* authority_id_hex,
188*60b67249SAndroid Build Coastguard Worker                             const char* subject_id_hex,
189*60b67249SAndroid Build Coastguard Worker                             const uint8_t* encoded_public_key,
190*60b67249SAndroid Build Coastguard Worker                             size_t encoded_public_key_size, size_t buffer_size,
191*60b67249SAndroid Build Coastguard Worker                             uint8_t* buffer, size_t* encoded_size) {
192*60b67249SAndroid Build Coastguard Worker   // Constants per RFC 8392.
193*60b67249SAndroid Build Coastguard Worker   const int64_t kCwtIssuerLabel = 1;
194*60b67249SAndroid Build Coastguard Worker   const int64_t kCwtSubjectLabel = 2;
195*60b67249SAndroid Build Coastguard Worker   // Constants per the Open Profile for DICE specification.
196*60b67249SAndroid Build Coastguard Worker   const int64_t kCodeHashLabel = -4670545;
197*60b67249SAndroid Build Coastguard Worker   const int64_t kCodeDescriptorLabel = -4670546;
198*60b67249SAndroid Build Coastguard Worker   const int64_t kConfigHashLabel = -4670547;
199*60b67249SAndroid Build Coastguard Worker   const int64_t kConfigDescriptorLabel = -4670548;
200*60b67249SAndroid Build Coastguard Worker   const int64_t kAuthorityHashLabel = -4670549;
201*60b67249SAndroid Build Coastguard Worker   const int64_t kAuthorityDescriptorLabel = -4670550;
202*60b67249SAndroid Build Coastguard Worker   const int64_t kModeLabel = -4670551;
203*60b67249SAndroid Build Coastguard Worker   const int64_t kSubjectPublicKeyLabel = -4670552;
204*60b67249SAndroid Build Coastguard Worker   const int64_t kKeyUsageLabel = -4670553;
205*60b67249SAndroid Build Coastguard Worker   const int64_t kProfileNameLabel = -4670554;
206*60b67249SAndroid Build Coastguard Worker   // Key usage constant per RFC 5280.
207*60b67249SAndroid Build Coastguard Worker   const uint8_t kKeyUsageCertSign = 32;
208*60b67249SAndroid Build Coastguard Worker 
209*60b67249SAndroid Build Coastguard Worker   // Count the number of entries.
210*60b67249SAndroid Build Coastguard Worker   uint32_t map_pairs = 7;
211*60b67249SAndroid Build Coastguard Worker   if (input_values->code_descriptor_size > 0) {
212*60b67249SAndroid Build Coastguard Worker     map_pairs += 1;
213*60b67249SAndroid Build Coastguard Worker   }
214*60b67249SAndroid Build Coastguard Worker   if (input_values->config_type == kDiceConfigTypeDescriptor) {
215*60b67249SAndroid Build Coastguard Worker     map_pairs += 2;
216*60b67249SAndroid Build Coastguard Worker   } else {
217*60b67249SAndroid Build Coastguard Worker     map_pairs += 1;
218*60b67249SAndroid Build Coastguard Worker   }
219*60b67249SAndroid Build Coastguard Worker   if (input_values->authority_descriptor_size > 0) {
220*60b67249SAndroid Build Coastguard Worker     map_pairs += 1;
221*60b67249SAndroid Build Coastguard Worker   }
222*60b67249SAndroid Build Coastguard Worker 
223*60b67249SAndroid Build Coastguard Worker   DiceKeyParam key_param;
224*60b67249SAndroid Build Coastguard Worker   DiceResult result =
225*60b67249SAndroid Build Coastguard Worker       DiceGetKeyParam(context, kDicePrincipalSubject, &key_param);
226*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
227*60b67249SAndroid Build Coastguard Worker     return result;
228*60b67249SAndroid Build Coastguard Worker   }
229*60b67249SAndroid Build Coastguard Worker   if (key_param.profile_name) {
230*60b67249SAndroid Build Coastguard Worker     map_pairs += 1;
231*60b67249SAndroid Build Coastguard Worker   }
232*60b67249SAndroid Build Coastguard Worker 
233*60b67249SAndroid Build Coastguard Worker   struct CborOut out;
234*60b67249SAndroid Build Coastguard Worker   CborOutInit(buffer, buffer_size, &out);
235*60b67249SAndroid Build Coastguard Worker   CborWriteMap(map_pairs, &out);
236*60b67249SAndroid Build Coastguard Worker   // Add the issuer.
237*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCwtIssuerLabel, &out);
238*60b67249SAndroid Build Coastguard Worker   CborWriteTstr(authority_id_hex, &out);
239*60b67249SAndroid Build Coastguard Worker   // Add the subject.
240*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCwtSubjectLabel, &out);
241*60b67249SAndroid Build Coastguard Worker   CborWriteTstr(subject_id_hex, &out);
242*60b67249SAndroid Build Coastguard Worker   // Add the code hash.
243*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCodeHashLabel, &out);
244*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(DICE_HASH_SIZE, input_values->code_hash, &out);
245*60b67249SAndroid Build Coastguard Worker   // Add the code descriptor, if provided.
246*60b67249SAndroid Build Coastguard Worker   if (input_values->code_descriptor_size > 0) {
247*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kCodeDescriptorLabel, &out);
248*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(input_values->code_descriptor_size,
249*60b67249SAndroid Build Coastguard Worker                   input_values->code_descriptor, &out);
250*60b67249SAndroid Build Coastguard Worker   }
251*60b67249SAndroid Build Coastguard Worker   // Add the config inputs.
252*60b67249SAndroid Build Coastguard Worker   if (input_values->config_type == kDiceConfigTypeDescriptor) {
253*60b67249SAndroid Build Coastguard Worker     uint8_t config_descriptor_hash[DICE_HASH_SIZE];
254*60b67249SAndroid Build Coastguard Worker     // Skip hashing if we're not going to use the answer.
255*60b67249SAndroid Build Coastguard Worker     if (!CborOutOverflowed(&out)) {
256*60b67249SAndroid Build Coastguard Worker       result = DiceHash(context, input_values->config_descriptor,
257*60b67249SAndroid Build Coastguard Worker                         input_values->config_descriptor_size,
258*60b67249SAndroid Build Coastguard Worker                         config_descriptor_hash);
259*60b67249SAndroid Build Coastguard Worker       if (result != kDiceResultOk) {
260*60b67249SAndroid Build Coastguard Worker         return result;
261*60b67249SAndroid Build Coastguard Worker       }
262*60b67249SAndroid Build Coastguard Worker     }
263*60b67249SAndroid Build Coastguard Worker     // Add the config descriptor.
264*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kConfigDescriptorLabel, &out);
265*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(input_values->config_descriptor_size,
266*60b67249SAndroid Build Coastguard Worker                   input_values->config_descriptor, &out);
267*60b67249SAndroid Build Coastguard Worker     // Add the Config hash.
268*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kConfigHashLabel, &out);
269*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(DICE_HASH_SIZE, config_descriptor_hash, &out);
270*60b67249SAndroid Build Coastguard Worker   } else if (input_values->config_type == kDiceConfigTypeInline) {
271*60b67249SAndroid Build Coastguard Worker     // Add the inline config.
272*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kConfigDescriptorLabel, &out);
273*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(DICE_INLINE_CONFIG_SIZE, input_values->config_value, &out);
274*60b67249SAndroid Build Coastguard Worker   }
275*60b67249SAndroid Build Coastguard Worker   // Add the authority inputs.
276*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kAuthorityHashLabel, &out);
277*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(DICE_HASH_SIZE, input_values->authority_hash, &out);
278*60b67249SAndroid Build Coastguard Worker   if (input_values->authority_descriptor_size > 0) {
279*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kAuthorityDescriptorLabel, &out);
280*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(input_values->authority_descriptor_size,
281*60b67249SAndroid Build Coastguard Worker                   input_values->authority_descriptor, &out);
282*60b67249SAndroid Build Coastguard Worker   }
283*60b67249SAndroid Build Coastguard Worker   uint8_t mode_byte = input_values->mode;
284*60b67249SAndroid Build Coastguard Worker   uint8_t key_usage = kKeyUsageCertSign;
285*60b67249SAndroid Build Coastguard Worker   // Add the mode input.
286*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kModeLabel, &out);
287*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(/*data_sisze=*/1, &mode_byte, &out);
288*60b67249SAndroid Build Coastguard Worker   // Add the subject public key.
289*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kSubjectPublicKeyLabel, &out);
290*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(encoded_public_key_size, encoded_public_key, &out);
291*60b67249SAndroid Build Coastguard Worker   // Add the key usage.
292*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kKeyUsageLabel, &out);
293*60b67249SAndroid Build Coastguard Worker   CborWriteBstr(/*data_size=*/1, &key_usage, &out);
294*60b67249SAndroid Build Coastguard Worker   // Add the profile name
295*60b67249SAndroid Build Coastguard Worker   if (key_param.profile_name) {
296*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kProfileNameLabel, &out);
297*60b67249SAndroid Build Coastguard Worker     CborWriteTstr(key_param.profile_name, &out);
298*60b67249SAndroid Build Coastguard Worker   }
299*60b67249SAndroid Build Coastguard Worker   *encoded_size = CborOutSize(&out);
300*60b67249SAndroid Build Coastguard Worker   if (CborOutOverflowed(&out)) {
301*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
302*60b67249SAndroid Build Coastguard Worker   }
303*60b67249SAndroid Build Coastguard Worker   return kDiceResultOk;
304*60b67249SAndroid Build Coastguard Worker }
305*60b67249SAndroid Build Coastguard Worker 
DiceGenerateCertificate(void * context,const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const DiceInputValues * input_values,size_t certificate_buffer_size,uint8_t * certificate,size_t * certificate_actual_size)306*60b67249SAndroid Build Coastguard Worker DiceResult DiceGenerateCertificate(
307*60b67249SAndroid Build Coastguard Worker     void* context,
308*60b67249SAndroid Build Coastguard Worker     const uint8_t subject_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
309*60b67249SAndroid Build Coastguard Worker     const uint8_t authority_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
310*60b67249SAndroid Build Coastguard Worker     const DiceInputValues* input_values, size_t certificate_buffer_size,
311*60b67249SAndroid Build Coastguard Worker     uint8_t* certificate, size_t* certificate_actual_size) {
312*60b67249SAndroid Build Coastguard Worker   DiceResult result = kDiceResultOk;
313*60b67249SAndroid Build Coastguard Worker 
314*60b67249SAndroid Build Coastguard Worker   *certificate_actual_size = 0;
315*60b67249SAndroid Build Coastguard Worker   if (input_values->config_type != kDiceConfigTypeDescriptor &&
316*60b67249SAndroid Build Coastguard Worker       input_values->config_type != kDiceConfigTypeInline) {
317*60b67249SAndroid Build Coastguard Worker     return kDiceResultInvalidInput;
318*60b67249SAndroid Build Coastguard Worker   }
319*60b67249SAndroid Build Coastguard Worker 
320*60b67249SAndroid Build Coastguard Worker   // Declare buffers which are cleared on 'goto out'.
321*60b67249SAndroid Build Coastguard Worker   uint8_t subject_private_key[DICE_PRIVATE_KEY_BUFFER_SIZE];
322*60b67249SAndroid Build Coastguard Worker   uint8_t authority_private_key[DICE_PRIVATE_KEY_BUFFER_SIZE];
323*60b67249SAndroid Build Coastguard Worker 
324*60b67249SAndroid Build Coastguard Worker   // Derive keys and IDs from the private key seeds.
325*60b67249SAndroid Build Coastguard Worker   uint8_t subject_public_key[DICE_PUBLIC_KEY_BUFFER_SIZE];
326*60b67249SAndroid Build Coastguard Worker   result = DiceKeypairFromSeed(context, kDicePrincipalSubject,
327*60b67249SAndroid Build Coastguard Worker                                subject_private_key_seed, subject_public_key,
328*60b67249SAndroid Build Coastguard Worker                                subject_private_key);
329*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
330*60b67249SAndroid Build Coastguard Worker     goto out;
331*60b67249SAndroid Build Coastguard Worker   }
332*60b67249SAndroid Build Coastguard Worker 
333*60b67249SAndroid Build Coastguard Worker   DiceKeyParam subject_key_param;
334*60b67249SAndroid Build Coastguard Worker   DiceKeyParam authority_key_param;
335*60b67249SAndroid Build Coastguard Worker   result = DiceGetKeyParam(context, kDicePrincipalSubject, &subject_key_param);
336*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
337*60b67249SAndroid Build Coastguard Worker     goto out;
338*60b67249SAndroid Build Coastguard Worker   }
339*60b67249SAndroid Build Coastguard Worker   result =
340*60b67249SAndroid Build Coastguard Worker       DiceGetKeyParam(context, kDicePrincipalAuthority, &authority_key_param);
341*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
342*60b67249SAndroid Build Coastguard Worker     goto out;
343*60b67249SAndroid Build Coastguard Worker   }
344*60b67249SAndroid Build Coastguard Worker 
345*60b67249SAndroid Build Coastguard Worker   uint8_t subject_id[DICE_ID_SIZE];
346*60b67249SAndroid Build Coastguard Worker   result =
347*60b67249SAndroid Build Coastguard Worker       DiceDeriveCdiCertificateId(context, subject_public_key,
348*60b67249SAndroid Build Coastguard Worker                                  subject_key_param.public_key_size, subject_id);
349*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
350*60b67249SAndroid Build Coastguard Worker     goto out;
351*60b67249SAndroid Build Coastguard Worker   }
352*60b67249SAndroid Build Coastguard Worker   char subject_id_hex[41];
353*60b67249SAndroid Build Coastguard Worker   DiceHexEncode(subject_id, sizeof(subject_id), subject_id_hex,
354*60b67249SAndroid Build Coastguard Worker                 sizeof(subject_id_hex));
355*60b67249SAndroid Build Coastguard Worker   subject_id_hex[sizeof(subject_id_hex) - 1] = '\0';
356*60b67249SAndroid Build Coastguard Worker 
357*60b67249SAndroid Build Coastguard Worker   uint8_t authority_public_key[DICE_PUBLIC_KEY_BUFFER_SIZE];
358*60b67249SAndroid Build Coastguard Worker   result = DiceKeypairFromSeed(context, kDicePrincipalAuthority,
359*60b67249SAndroid Build Coastguard Worker                                authority_private_key_seed, authority_public_key,
360*60b67249SAndroid Build Coastguard Worker                                authority_private_key);
361*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
362*60b67249SAndroid Build Coastguard Worker     goto out;
363*60b67249SAndroid Build Coastguard Worker   }
364*60b67249SAndroid Build Coastguard Worker 
365*60b67249SAndroid Build Coastguard Worker   uint8_t authority_id[DICE_ID_SIZE];
366*60b67249SAndroid Build Coastguard Worker   result = DiceDeriveCdiCertificateId(context, authority_public_key,
367*60b67249SAndroid Build Coastguard Worker                                       authority_key_param.public_key_size,
368*60b67249SAndroid Build Coastguard Worker                                       authority_id);
369*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
370*60b67249SAndroid Build Coastguard Worker     goto out;
371*60b67249SAndroid Build Coastguard Worker   }
372*60b67249SAndroid Build Coastguard Worker   char authority_id_hex[41];
373*60b67249SAndroid Build Coastguard Worker   DiceHexEncode(authority_id, sizeof(authority_id), authority_id_hex,
374*60b67249SAndroid Build Coastguard Worker                 sizeof(authority_id_hex));
375*60b67249SAndroid Build Coastguard Worker   authority_id_hex[sizeof(authority_id_hex) - 1] = '\0';
376*60b67249SAndroid Build Coastguard Worker 
377*60b67249SAndroid Build Coastguard Worker   // The public key encoded as a COSE_Key structure is embedded in the CWT.
378*60b67249SAndroid Build Coastguard Worker   uint8_t encoded_public_key[DICE_MAX_PUBLIC_KEY_SIZE];
379*60b67249SAndroid Build Coastguard Worker   size_t encoded_public_key_size = 0;
380*60b67249SAndroid Build Coastguard Worker   result = DiceCoseEncodePublicKey(
381*60b67249SAndroid Build Coastguard Worker       context, kDicePrincipalSubject, subject_public_key,
382*60b67249SAndroid Build Coastguard Worker       sizeof(encoded_public_key), encoded_public_key, &encoded_public_key_size);
383*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
384*60b67249SAndroid Build Coastguard Worker     result = kDiceResultPlatformError;
385*60b67249SAndroid Build Coastguard Worker     goto out;
386*60b67249SAndroid Build Coastguard Worker   }
387*60b67249SAndroid Build Coastguard Worker 
388*60b67249SAndroid Build Coastguard Worker   // The encoded protected attributes are used in the TBS and the final
389*60b67249SAndroid Build Coastguard Worker   // COSE_Sign1 structure.
390*60b67249SAndroid Build Coastguard Worker   uint8_t protected_attributes[DICE_MAX_PROTECTED_ATTRIBUTES_SIZE];
391*60b67249SAndroid Build Coastguard Worker   size_t protected_attributes_size = 0;
392*60b67249SAndroid Build Coastguard Worker   result = EncodeProtectedAttributes(
393*60b67249SAndroid Build Coastguard Worker       context, kDicePrincipalAuthority, sizeof(protected_attributes),
394*60b67249SAndroid Build Coastguard Worker       protected_attributes, &protected_attributes_size);
395*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
396*60b67249SAndroid Build Coastguard Worker     result = kDiceResultPlatformError;
397*60b67249SAndroid Build Coastguard Worker     goto out;
398*60b67249SAndroid Build Coastguard Worker   }
399*60b67249SAndroid Build Coastguard Worker 
400*60b67249SAndroid Build Coastguard Worker   // Find out how big the CWT will be.
401*60b67249SAndroid Build Coastguard Worker   size_t cwt_size;
402*60b67249SAndroid Build Coastguard Worker   EncodeCwt(context, input_values, authority_id_hex, subject_id_hex,
403*60b67249SAndroid Build Coastguard Worker             encoded_public_key, encoded_public_key_size, /*buffer_size=*/0,
404*60b67249SAndroid Build Coastguard Worker             /*buffer=*/NULL, &cwt_size);
405*60b67249SAndroid Build Coastguard Worker 
406*60b67249SAndroid Build Coastguard Worker   // We need space to assemble the TBS. The size of the buffer needed depends on
407*60b67249SAndroid Build Coastguard Worker   // the size of the CWT, which is outside our control (e.g. it might have a
408*60b67249SAndroid Build Coastguard Worker   // very large config descriptor). So we use the certificate buffer as
409*60b67249SAndroid Build Coastguard Worker   // temporary storage; if we run out of space we will make sure the caller
410*60b67249SAndroid Build Coastguard Worker   // knows the size we actually need for this.
411*60b67249SAndroid Build Coastguard Worker   // Encode the TBS, leaving space for the final payload (the CWT).
412*60b67249SAndroid Build Coastguard Worker   uint8_t* cwt_ptr;
413*60b67249SAndroid Build Coastguard Worker   size_t tbs_size;
414*60b67249SAndroid Build Coastguard Worker   result =
415*60b67249SAndroid Build Coastguard Worker       EncodeCoseTbs(protected_attributes, protected_attributes_size, cwt_size,
416*60b67249SAndroid Build Coastguard Worker                     /*aad=*/NULL, /*aad_size=*/0, certificate_buffer_size,
417*60b67249SAndroid Build Coastguard Worker                     certificate, &cwt_ptr, &tbs_size);
418*60b67249SAndroid Build Coastguard Worker 
419*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
420*60b67249SAndroid Build Coastguard Worker     // There wasn't enough space to put together the TBS. The total buffer size
421*60b67249SAndroid Build Coastguard Worker     // we need is either the amount needed for the TBS, or the amount needed for
422*60b67249SAndroid Build Coastguard Worker     // encoded payload and signature.
423*60b67249SAndroid Build Coastguard Worker     size_t final_encoded_size = 0;
424*60b67249SAndroid Build Coastguard Worker     EncodeCoseSign1(context, protected_attributes, protected_attributes_size,
425*60b67249SAndroid Build Coastguard Worker                     cwt_ptr, cwt_size, /*move_payload=*/false,
426*60b67249SAndroid Build Coastguard Worker                     /*signature=*/NULL, /*buffer_size=*/0, /*buffer=*/NULL,
427*60b67249SAndroid Build Coastguard Worker                     &final_encoded_size);
428*60b67249SAndroid Build Coastguard Worker     *certificate_actual_size =
429*60b67249SAndroid Build Coastguard Worker         final_encoded_size > tbs_size ? final_encoded_size : tbs_size;
430*60b67249SAndroid Build Coastguard Worker     result = kDiceResultBufferTooSmall;
431*60b67249SAndroid Build Coastguard Worker     goto out;
432*60b67249SAndroid Build Coastguard Worker   }
433*60b67249SAndroid Build Coastguard Worker 
434*60b67249SAndroid Build Coastguard Worker   // Now we can encode the payload directly into the allocated BSTR in the TBS.
435*60b67249SAndroid Build Coastguard Worker   size_t final_cwt_size;
436*60b67249SAndroid Build Coastguard Worker   result = EncodeCwt(context, input_values, authority_id_hex, subject_id_hex,
437*60b67249SAndroid Build Coastguard Worker                      encoded_public_key, encoded_public_key_size, cwt_size,
438*60b67249SAndroid Build Coastguard Worker                      cwt_ptr, &final_cwt_size);
439*60b67249SAndroid Build Coastguard Worker   if (result == kDiceResultBufferTooSmall || final_cwt_size != cwt_size) {
440*60b67249SAndroid Build Coastguard Worker     result = kDiceResultPlatformError;
441*60b67249SAndroid Build Coastguard Worker   }
442*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
443*60b67249SAndroid Build Coastguard Worker     goto out;
444*60b67249SAndroid Build Coastguard Worker   }
445*60b67249SAndroid Build Coastguard Worker 
446*60b67249SAndroid Build Coastguard Worker   // Sign the now-complete TBS.
447*60b67249SAndroid Build Coastguard Worker   uint8_t signature[DICE_SIGNATURE_BUFFER_SIZE];
448*60b67249SAndroid Build Coastguard Worker   result = DiceSign(context, certificate, tbs_size, authority_private_key,
449*60b67249SAndroid Build Coastguard Worker                     signature);
450*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
451*60b67249SAndroid Build Coastguard Worker     goto out;
452*60b67249SAndroid Build Coastguard Worker   }
453*60b67249SAndroid Build Coastguard Worker 
454*60b67249SAndroid Build Coastguard Worker   // And now we can produce the complete CoseSign1, including the signature, and
455*60b67249SAndroid Build Coastguard Worker   // moving the payload into place as we do it.
456*60b67249SAndroid Build Coastguard Worker   result = EncodeCoseSign1(
457*60b67249SAndroid Build Coastguard Worker       context, protected_attributes, protected_attributes_size, cwt_ptr,
458*60b67249SAndroid Build Coastguard Worker       cwt_size, /*move_payload=*/true, signature, certificate_buffer_size,
459*60b67249SAndroid Build Coastguard Worker       certificate, certificate_actual_size);
460*60b67249SAndroid Build Coastguard Worker 
461*60b67249SAndroid Build Coastguard Worker out:
462*60b67249SAndroid Build Coastguard Worker   DiceClearMemory(context, sizeof(subject_private_key), subject_private_key);
463*60b67249SAndroid Build Coastguard Worker   DiceClearMemory(context, sizeof(authority_private_key),
464*60b67249SAndroid Build Coastguard Worker                   authority_private_key);
465*60b67249SAndroid Build Coastguard Worker 
466*60b67249SAndroid Build Coastguard Worker   return result;
467*60b67249SAndroid Build Coastguard Worker }
468*60b67249SAndroid Build Coastguard Worker 
DiceCoseEncodePublicKey(void * context,DicePrincipal principal,const uint8_t public_key[DICE_PUBLIC_KEY_BUFFER_SIZE],size_t buffer_size,uint8_t * buffer,size_t * encoded_size)469*60b67249SAndroid Build Coastguard Worker DiceResult DiceCoseEncodePublicKey(
470*60b67249SAndroid Build Coastguard Worker     void* context, DicePrincipal principal,
471*60b67249SAndroid Build Coastguard Worker     const uint8_t public_key[DICE_PUBLIC_KEY_BUFFER_SIZE], size_t buffer_size,
472*60b67249SAndroid Build Coastguard Worker     uint8_t* buffer, size_t* encoded_size) {
473*60b67249SAndroid Build Coastguard Worker   DiceKeyParam key_param;
474*60b67249SAndroid Build Coastguard Worker   DiceResult result = DiceGetKeyParam(context, principal, &key_param);
475*60b67249SAndroid Build Coastguard Worker   if (result != kDiceResultOk) {
476*60b67249SAndroid Build Coastguard Worker     return result;
477*60b67249SAndroid Build Coastguard Worker   }
478*60b67249SAndroid Build Coastguard Worker   struct CborOut out;
479*60b67249SAndroid Build Coastguard Worker   CborOutInit(buffer, buffer_size, &out);
480*60b67249SAndroid Build Coastguard Worker   if (key_param.cose_key_type == kCoseKeyKtyOkp) {
481*60b67249SAndroid Build Coastguard Worker     CborWriteMap(/*num_pairs=*/5, &out);
482*60b67249SAndroid Build Coastguard Worker   } else if (key_param.cose_key_type == kCoseKeyKtyEc2) {
483*60b67249SAndroid Build Coastguard Worker     CborWriteMap(/*num_pairs=*/6, &out);
484*60b67249SAndroid Build Coastguard Worker   } else {
485*60b67249SAndroid Build Coastguard Worker     return kDiceResultInvalidInput;
486*60b67249SAndroid Build Coastguard Worker   }
487*60b67249SAndroid Build Coastguard Worker   // Add the key type.
488*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseKeyKtyLabel, &out);
489*60b67249SAndroid Build Coastguard Worker   CborWriteInt(key_param.cose_key_type, &out);
490*60b67249SAndroid Build Coastguard Worker   // Add the algorithm.
491*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseKeyAlgLabel, &out);
492*60b67249SAndroid Build Coastguard Worker   CborWriteInt(key_param.cose_key_algorithm, &out);
493*60b67249SAndroid Build Coastguard Worker   // Add the KeyOps.
494*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseKeyOpsLabel, &out);
495*60b67249SAndroid Build Coastguard Worker   CborWriteArray(/*num_elements=*/1, &out);
496*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseKeyOpsVerify, &out);
497*60b67249SAndroid Build Coastguard Worker   // Add the curve.
498*60b67249SAndroid Build Coastguard Worker   CborWriteInt(kCoseKeyCrvLabel, &out);
499*60b67249SAndroid Build Coastguard Worker   CborWriteInt(key_param.cose_key_curve, &out);
500*60b67249SAndroid Build Coastguard Worker 
501*60b67249SAndroid Build Coastguard Worker   // Add the public key.
502*60b67249SAndroid Build Coastguard Worker   if (key_param.cose_key_type == kCoseKeyKtyOkp) {
503*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kCoseKeyXLabel, &out);
504*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(key_param.public_key_size, public_key, &out);
505*60b67249SAndroid Build Coastguard Worker   } else if (key_param.cose_key_type == kCoseKeyKtyEc2) {
506*60b67249SAndroid Build Coastguard Worker     // Add the subject public key x and y coordinates
507*60b67249SAndroid Build Coastguard Worker     int xy_param_size = key_param.public_key_size / 2;
508*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kCoseKeyXLabel, &out);
509*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(xy_param_size, &public_key[0], &out);
510*60b67249SAndroid Build Coastguard Worker     CborWriteInt(kCoseKeyYLabel, &out);
511*60b67249SAndroid Build Coastguard Worker     CborWriteBstr(xy_param_size, &public_key[xy_param_size], &out);
512*60b67249SAndroid Build Coastguard Worker   }
513*60b67249SAndroid Build Coastguard Worker 
514*60b67249SAndroid Build Coastguard Worker   *encoded_size = CborOutSize(&out);
515*60b67249SAndroid Build Coastguard Worker   if (CborOutOverflowed(&out)) {
516*60b67249SAndroid Build Coastguard Worker     return kDiceResultBufferTooSmall;
517*60b67249SAndroid Build Coastguard Worker   }
518*60b67249SAndroid Build Coastguard Worker   return kDiceResultOk;
519*60b67249SAndroid Build Coastguard Worker }
520