1*dca92e47SWilly Tu #include "stddef.h"
2*dca92e47SWilly Tu 
3*dca92e47SWilly Tu #include <libcr51sign/cr51_image_descriptor.h>
4*dca92e47SWilly Tu #include <libcr51sign/libcr51sign.h>
5*dca92e47SWilly Tu #include <libcr51sign/libcr51sign_internal.h>
6*dca92e47SWilly Tu #include <libcr51sign/libcr51sign_mauv.h>
7*dca92e47SWilly Tu #include <stdint.h>
8*dca92e47SWilly Tu 
9*dca92e47SWilly Tu #ifdef __cplusplus
10*dca92e47SWilly Tu extern "C"
11*dca92e47SWilly Tu {
12*dca92e47SWilly Tu #endif
13*dca92e47SWilly Tu 
14*dca92e47SWilly Tu #define IMAGE_MAUV_MAX_DENYLIST_ENTRIES                                        \
15*dca92e47SWilly Tu     ((IMAGE_MAUV_DATA_MAX_SIZE - sizeof(struct image_mauv)) / sizeof(uint64_t))
16*dca92e47SWilly Tu 
17*dca92e47SWilly Tu _Static_assert(
18*dca92e47SWilly Tu     (sizeof(struct image_mauv) +
19*dca92e47SWilly Tu      IMAGE_MAUV_MAX_DENYLIST_ENTRIES *
20*dca92e47SWilly Tu          MEMBER_SIZE(struct image_mauv, version_denylist[0])) ==
21*dca92e47SWilly Tu         IMAGE_MAUV_DATA_MAX_SIZE,
22*dca92e47SWilly Tu     "IMAGE_MAUV_MAX_DENYLIST_ENTRIES number of denylist entries do not "
23*dca92e47SWilly Tu     "completely fill IMAGE_MAUV_MAX_SIZE bytes assumed for data in struct "
24*dca92e47SWilly Tu     "image_mauv");
25*dca92e47SWilly Tu 
26*dca92e47SWilly Tu // Use wrapper struct to preserve alignment of image_mauv
27*dca92e47SWilly Tu struct full_mauv
28*dca92e47SWilly Tu {
29*dca92e47SWilly Tu     struct image_mauv mauv;
30*dca92e47SWilly Tu     uint8_t extra[IMAGE_MAUV_DATA_MAX_SIZE - sizeof(struct image_mauv)];
31*dca92e47SWilly Tu };
32*dca92e47SWilly Tu 
33*dca92e47SWilly Tu // Verify BLOB magic bytes in payload's image descriptor at the expected offset
34*dca92e47SWilly Tu //
35*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
36*dca92e47SWilly Tu //                 data for the user of the library
37*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
38*dca92e47SWilly Tu //                  and environment
39*dca92e47SWilly Tu // @param[in] payload_blob_offset  Absolute offset of payload BLOB data in
40*dca92e47SWilly Tu //                                 payload's image descriptor
41*dca92e47SWilly Tu //
42*dca92e47SWilly Tu // @return `failure_reason`
43*dca92e47SWilly Tu static failure_reason
44*dca92e47SWilly Tu     verify_payload_blob_magic(const struct libcr51sign_ctx* const ctx,
45*dca92e47SWilly Tu                               const struct libcr51sign_intf* const intf,
46*dca92e47SWilly Tu                               const uint32_t payload_blob_offset)
47*dca92e47SWilly Tu {
48*dca92e47SWilly Tu     int irv = 0;
49*dca92e47SWilly Tu     struct blob payload_blob = {0};
50*dca92e47SWilly Tu 
51*dca92e47SWilly Tu     if (!intf->read)
52*dca92e47SWilly Tu     {
53*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Missing interface intf->read\n", __FUNCTION__);
54*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
55*dca92e47SWilly Tu     }
56*dca92e47SWilly Tu 
57*dca92e47SWilly Tu     irv = intf->read(ctx, payload_blob_offset, sizeof(struct blob),
58*dca92e47SWilly Tu                      (uint8_t*)&payload_blob);
59*dca92e47SWilly Tu     if (irv != LIBCR51SIGN_SUCCESS)
60*dca92e47SWilly Tu     {
61*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Could not read BLOB magic bytes from payload\n",
62*dca92e47SWilly Tu                 __FUNCTION__);
63*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
64*dca92e47SWilly Tu     }
65*dca92e47SWilly Tu 
66*dca92e47SWilly Tu     if (payload_blob.blob_magic != BLOB_MAGIC)
67*dca92e47SWilly Tu     {
68*dca92e47SWilly Tu         CPRINTS(ctx, "%s: BLOB magic bytes read from payload(%x) are invalid\n",
69*dca92e47SWilly Tu                 __FUNCTION__, payload_blob.blob_magic);
70*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
71*dca92e47SWilly Tu     }
72*dca92e47SWilly Tu 
73*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
74*dca92e47SWilly Tu }
75*dca92e47SWilly Tu 
76*dca92e47SWilly Tu // Find offset of Image MAUV data in payload BLOB inside the image descriptor
77*dca92e47SWilly Tu //
78*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
79*dca92e47SWilly Tu //                 data for the user of the library
80*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
81*dca92e47SWilly Tu //                  and environment
82*dca92e47SWilly Tu // @param[in] offset_after_payload_blob_magic  Absolute offset of data after
83*dca92e47SWilly Tu //                                             payload BLOB magic bytes in image
84*dca92e47SWilly Tu //                                             descriptor
85*dca92e47SWilly Tu // @param[in] payload_blob_size  Size of payload BLOB as per its image
86*dca92e47SWilly Tu //                               descriptor
87*dca92e47SWilly Tu // @param[out] payload_image_mauv_data_offset  Absolute offset of Image MAUV
88*dca92e47SWilly Tu //                                             data in payload's image
89*dca92e47SWilly Tu //                                             descriptor
90*dca92e47SWilly Tu // @param[out] payload_image_mauv_data_size  Size of Image MAUV data embedded in
91*dca92e47SWilly Tu //                                           payload's image descriptor
92*dca92e47SWilly Tu //
93*dca92e47SWilly Tu // @return `failure_reason`
94*dca92e47SWilly Tu static failure_reason find_image_mauv_data_offset_in_payload(
95*dca92e47SWilly Tu     const struct libcr51sign_ctx* const ctx,
96*dca92e47SWilly Tu     const struct libcr51sign_intf* const intf,
97*dca92e47SWilly Tu     const uint32_t offset_after_payload_blob_magic,
98*dca92e47SWilly Tu     const uint32_t payload_blob_size,
99*dca92e47SWilly Tu     uint32_t* const restrict payload_image_mauv_data_offset,
100*dca92e47SWilly Tu     uint32_t* const restrict payload_image_mauv_data_size)
101*dca92e47SWilly Tu {
102*dca92e47SWilly Tu     struct blob_data payload_blob_data = {0};
103*dca92e47SWilly Tu     int irv = 0;
104*dca92e47SWilly Tu     bool found_image_mauv_data = false;
105*dca92e47SWilly Tu 
106*dca92e47SWilly Tu     if (!intf->read)
107*dca92e47SWilly Tu     {
108*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Missing interface intf->read\n", __FUNCTION__);
109*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
110*dca92e47SWilly Tu     }
111*dca92e47SWilly Tu     for (uint32_t current_offset = offset_after_payload_blob_magic;
112*dca92e47SWilly Tu          current_offset <= offset_after_payload_blob_magic + payload_blob_size -
113*dca92e47SWilly Tu                                sizeof(struct blob_data);
114*dca92e47SWilly Tu          /* increment based on each blob_data's size in loop */)
115*dca92e47SWilly Tu     {
116*dca92e47SWilly Tu         irv = intf->read(ctx, current_offset, sizeof(struct blob_data),
117*dca92e47SWilly Tu                          (uint8_t*)&payload_blob_data);
118*dca92e47SWilly Tu         if (irv != LIBCR51SIGN_SUCCESS)
119*dca92e47SWilly Tu         {
120*dca92e47SWilly Tu             CPRINTS(ctx, "%s: Could not read BLOB data at offset %x\n",
121*dca92e47SWilly Tu                     __FUNCTION__, current_offset);
122*dca92e47SWilly Tu             return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
123*dca92e47SWilly Tu         }
124*dca92e47SWilly Tu 
125*dca92e47SWilly Tu         if ((current_offset - offset_after_payload_blob_magic) +
126*dca92e47SWilly Tu                 sizeof(struct blob_data) + payload_blob_data.blob_payload_size >
127*dca92e47SWilly Tu             payload_blob_size)
128*dca92e47SWilly Tu         {
129*dca92e47SWilly Tu             CPRINTS(
130*dca92e47SWilly Tu                 ctx,
131*dca92e47SWilly Tu                 "%s: BLOB payload size crosses threshold expected by blob_size "
132*dca92e47SWilly Tu                 "in image descriptor",
133*dca92e47SWilly Tu                 __FUNCTION__);
134*dca92e47SWilly Tu             return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
135*dca92e47SWilly Tu         }
136*dca92e47SWilly Tu 
137*dca92e47SWilly Tu         switch (payload_blob_data.blob_type_magic)
138*dca92e47SWilly Tu         {
139*dca92e47SWilly Tu             case BLOB_TYPE_MAGIC_MAUV:
140*dca92e47SWilly Tu                 if (!found_image_mauv_data)
141*dca92e47SWilly Tu                 {
142*dca92e47SWilly Tu                     *payload_image_mauv_data_offset = current_offset +
143*dca92e47SWilly Tu                                                       sizeof(struct blob_data);
144*dca92e47SWilly Tu                     *payload_image_mauv_data_size =
145*dca92e47SWilly Tu                         payload_blob_data.blob_payload_size;
146*dca92e47SWilly Tu                     found_image_mauv_data = true;
147*dca92e47SWilly Tu                     /* intentional fall-through to increment current offset */
148*dca92e47SWilly Tu                 }
149*dca92e47SWilly Tu                 else
150*dca92e47SWilly Tu                 {
151*dca92e47SWilly Tu                     /* There should be only one Image MAUV in a valid image
152*dca92e47SWilly Tu                      * descriptor */
153*dca92e47SWilly Tu                     CPRINTS(
154*dca92e47SWilly Tu                         ctx,
155*dca92e47SWilly Tu                         "%s: Found multiple Image MAUV BLOB instances in payload\n",
156*dca92e47SWilly Tu                         __FUNCTION__);
157*dca92e47SWilly Tu                     return LIBCR51SIGN_ERROR_INVALID_DESCRIPTOR;
158*dca92e47SWilly Tu                 }
159*dca92e47SWilly Tu             default:
160*dca92e47SWilly Tu                 current_offset += sizeof(struct blob_data) +
161*dca92e47SWilly Tu                                   payload_blob_data.blob_payload_size;
162*dca92e47SWilly Tu                 /* Increment offset to keep the expected alignment */
163*dca92e47SWilly Tu                 current_offset =
164*dca92e47SWilly Tu                     ((current_offset - 1) & ~(BLOB_DATA_ALIGNMENT - 1)) +
165*dca92e47SWilly Tu                     BLOB_DATA_ALIGNMENT;
166*dca92e47SWilly Tu                 break;
167*dca92e47SWilly Tu         }
168*dca92e47SWilly Tu     }
169*dca92e47SWilly Tu     if (!found_image_mauv_data)
170*dca92e47SWilly Tu     {
171*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Did not find Image MAUV BLOB inside payload\n",
172*dca92e47SWilly Tu                 __FUNCTION__);
173*dca92e47SWilly Tu     }
174*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
175*dca92e47SWilly Tu }
176*dca92e47SWilly Tu 
177*dca92e47SWilly Tu // Read Image MAUV data from BLOB inside payload's image descriptor
178*dca92e47SWilly Tu //
179*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
180*dca92e47SWilly Tu //                 data for the user of the library
181*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
182*dca92e47SWilly Tu //                  and environment
183*dca92e47SWilly Tu // @param[in] payload_image_mauv_data_offset  Absolute offset of Image MAUV data
184*dca92e47SWilly Tu //                                            in payload's image descriptor
185*dca92e47SWilly Tu // @param[in] payload_image_mauv_data_size  Size of Image MAUV data embedded in
186*dca92e47SWilly Tu //                                          payload's image descriptor
187*dca92e47SWilly Tu // @param[out] payload_image_mauv_data_buffer  Buffer to store Image MAUV data
188*dca92e47SWilly Tu //                                             read from payload's image
189*dca92e47SWilly Tu //                                             descriptor
190*dca92e47SWilly Tu //
191*dca92e47SWilly Tu // @return `failure_reason`
192*dca92e47SWilly Tu static failure_reason read_image_mauv_data_from_payload(
193*dca92e47SWilly Tu     const struct libcr51sign_ctx* const ctx,
194*dca92e47SWilly Tu     const struct libcr51sign_intf* const intf,
195*dca92e47SWilly Tu     const uint32_t payload_image_mauv_data_offset,
196*dca92e47SWilly Tu     const uint32_t payload_image_mauv_data_size,
197*dca92e47SWilly Tu     struct image_mauv* const restrict payload_image_mauv_data_buffer)
198*dca92e47SWilly Tu {
199*dca92e47SWilly Tu     int irv = 0;
200*dca92e47SWilly Tu 
201*dca92e47SWilly Tu     if (!intf->read)
202*dca92e47SWilly Tu     {
203*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Missing interface intf->read\n", __FUNCTION__);
204*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
205*dca92e47SWilly Tu     }
206*dca92e47SWilly Tu 
207*dca92e47SWilly Tu     if (payload_image_mauv_data_size > IMAGE_MAUV_DATA_MAX_SIZE)
208*dca92e47SWilly Tu     {
209*dca92e47SWilly Tu         CPRINTS(
210*dca92e47SWilly Tu             ctx,
211*dca92e47SWilly Tu             "%s: Payload Image MAUV data size (0x%x) is more than supported "
212*dca92e47SWilly Tu             "maximum size\n",
213*dca92e47SWilly Tu             __FUNCTION__, payload_image_mauv_data_size);
214*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
215*dca92e47SWilly Tu     }
216*dca92e47SWilly Tu 
217*dca92e47SWilly Tu     irv = intf->read(ctx, payload_image_mauv_data_offset,
218*dca92e47SWilly Tu                      payload_image_mauv_data_size,
219*dca92e47SWilly Tu                      (uint8_t*)payload_image_mauv_data_buffer);
220*dca92e47SWilly Tu     if (irv != LIBCR51SIGN_SUCCESS)
221*dca92e47SWilly Tu     {
222*dca92e47SWilly Tu         CPRINTS(ctx,
223*dca92e47SWilly Tu                 "%s: Could not read Image MAUV data from payload @ offset 0x%x "
224*dca92e47SWilly Tu                 "size 0x%x\n",
225*dca92e47SWilly Tu                 __FUNCTION__, payload_image_mauv_data_offset,
226*dca92e47SWilly Tu                 payload_image_mauv_data_size);
227*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_RUNTIME_FAILURE;
228*dca92e47SWilly Tu     }
229*dca92e47SWilly Tu 
230*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
231*dca92e47SWilly Tu }
232*dca92e47SWilly Tu 
233*dca92e47SWilly Tu // Check if Image MAUV allows update to a target payload version
234*dca92e47SWilly Tu //
235*dca92e47SWilly Tu // @param[in] stored_image_mauv_data  Image MAUV data stored in system
236*dca92e47SWilly Tu // @param[in] new_payload_security_version  Payload version
237*dca92e47SWilly Tu //
238*dca92e47SWilly Tu // @return `bool`  `True` if update to target version is allowed by MAUV data
239*dca92e47SWilly Tu static bool does_stored_image_mauv_allow_update(
240*dca92e47SWilly Tu     const struct image_mauv* const stored_image_mauv_data,
241*dca92e47SWilly Tu     const uint64_t new_payload_security_version)
242*dca92e47SWilly Tu {
243*dca92e47SWilly Tu     if (new_payload_security_version <
244*dca92e47SWilly Tu         stored_image_mauv_data->minimum_acceptable_update_version)
245*dca92e47SWilly Tu     {
246*dca92e47SWilly Tu         return false;
247*dca92e47SWilly Tu     }
248*dca92e47SWilly Tu 
249*dca92e47SWilly Tu     for (uint32_t i = 0;
250*dca92e47SWilly Tu          i < stored_image_mauv_data->version_denylist_num_entries; i++)
251*dca92e47SWilly Tu     {
252*dca92e47SWilly Tu         if (stored_image_mauv_data->version_denylist[i] ==
253*dca92e47SWilly Tu             new_payload_security_version)
254*dca92e47SWilly Tu         {
255*dca92e47SWilly Tu             return false;
256*dca92e47SWilly Tu         }
257*dca92e47SWilly Tu     }
258*dca92e47SWilly Tu 
259*dca92e47SWilly Tu     return true;
260*dca92e47SWilly Tu }
261*dca92e47SWilly Tu 
262*dca92e47SWilly Tu // Do a sanity check for values stored in Image MAUV data
263*dca92e47SWilly Tu //
264*dca92e47SWilly Tu // @param[in] image_mauv_data  Image MAUV data
265*dca92e47SWilly Tu // @param[in] image_mauv_data_size  Size of Image MAUV data in bytes
266*dca92e47SWilly Tu //
267*dca92e47SWilly Tu // @return `failure_reason`
268*dca92e47SWilly Tu static failure_reason sanity_check_image_mauv_data(
269*dca92e47SWilly Tu     const struct image_mauv* const restrict image_mauv_data,
270*dca92e47SWilly Tu     const uint32_t image_mauv_data_size)
271*dca92e47SWilly Tu {
272*dca92e47SWilly Tu     uint32_t expected_image_mauv_data_size = 0;
273*dca92e47SWilly Tu 
274*dca92e47SWilly Tu     if (image_mauv_data_size < sizeof(struct image_mauv))
275*dca92e47SWilly Tu     {
276*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Image MAUV data size is smaller than expected\n",
277*dca92e47SWilly Tu                 __FUNCTION__);
278*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
279*dca92e47SWilly Tu     }
280*dca92e47SWilly Tu 
281*dca92e47SWilly Tu     if (image_mauv_data->mauv_struct_version != IMAGE_MAUV_STRUCT_VERSION)
282*dca92e47SWilly Tu     {
283*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Unexpected Image MAUV version\n", __FUNCTION__);
284*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
285*dca92e47SWilly Tu     }
286*dca92e47SWilly Tu 
287*dca92e47SWilly Tu     if (image_mauv_data->payload_security_version == 0)
288*dca92e47SWilly Tu     {
289*dca92e47SWilly Tu         // Handle trivial case of someone not initializing MAUV properly
290*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Payload security version should be greater than 0\n",
291*dca92e47SWilly Tu                 __FUNCTION__);
292*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
293*dca92e47SWilly Tu     }
294*dca92e47SWilly Tu 
295*dca92e47SWilly Tu     if (image_mauv_data->version_denylist_num_entries >
296*dca92e47SWilly Tu         IMAGE_MAUV_MAX_DENYLIST_ENTRIES)
297*dca92e47SWilly Tu     {
298*dca92e47SWilly Tu         CPRINTS(
299*dca92e47SWilly Tu             ctx,
300*dca92e47SWilly Tu             "%s: Version denylist entries in Image MAUV exceed maximum count\n",
301*dca92e47SWilly Tu             __FUNCTION__);
302*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
303*dca92e47SWilly Tu     }
304*dca92e47SWilly Tu 
305*dca92e47SWilly Tu     expected_image_mauv_data_size =
306*dca92e47SWilly Tu         sizeof(struct image_mauv) +
307*dca92e47SWilly Tu         image_mauv_data->version_denylist_num_entries *
308*dca92e47SWilly Tu             MEMBER_SIZE(struct image_mauv, version_denylist[0]);
309*dca92e47SWilly Tu 
310*dca92e47SWilly Tu     if (image_mauv_data_size != expected_image_mauv_data_size)
311*dca92e47SWilly Tu     {
312*dca92e47SWilly Tu         CPRINTS(ctx,
313*dca92e47SWilly Tu                 "%s: Size of Image MAUV data (0x%x) is different than expected "
314*dca92e47SWilly Tu                 "size (0x%x)\n",
315*dca92e47SWilly Tu                 __FUNCTION__, image_mauv_data_size,
316*dca92e47SWilly Tu                 expected_image_mauv_data_size);
317*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
318*dca92e47SWilly Tu     }
319*dca92e47SWilly Tu 
320*dca92e47SWilly Tu     if (!does_stored_image_mauv_allow_update(
321*dca92e47SWilly Tu             image_mauv_data, image_mauv_data->payload_security_version))
322*dca92e47SWilly Tu     {
323*dca92e47SWilly Tu         CPRINTS(ctx,
324*dca92e47SWilly Tu                 "%s: Image MAUV does not allow update to the payload it was "
325*dca92e47SWilly Tu                 "contained in\n",
326*dca92e47SWilly Tu                 __FUNCTION__);
327*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
328*dca92e47SWilly Tu     }
329*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
330*dca92e47SWilly Tu }
331*dca92e47SWilly Tu 
332*dca92e47SWilly Tu // Find and read (if found) Image MAUV from payload's image descriptor
333*dca92e47SWilly Tu //
334*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
335*dca92e47SWilly Tu //                 data for the user of the library
336*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
337*dca92e47SWilly Tu //                  and environment
338*dca92e47SWilly Tu // @param[in] payload_blob_offset  Absolute offset of payload BLOB data in
339*dca92e47SWilly Tu //                                 payload's image descriptor
340*dca92e47SWilly Tu // @param[in] payload_blob_size  Size of payload BLOB data as per payload's
341*dca92e47SWilly Tu //                               image descriptor
342*dca92e47SWilly Tu // @param[out] payload_image_mauv_data_buffer  Buffer to store Image MAUV data
343*dca92e47SWilly Tu //                                             read from payload's image
344*dca92e47SWilly Tu //                                             descriptor
345*dca92e47SWilly Tu // @param[out] payload_image_mauv_data_size  Size of Image MAUV data (in bytes)
346*dca92e47SWilly Tu //                                           read from payload's image
347*dca92e47SWilly Tu //                                           descriptor
348*dca92e47SWilly Tu // @param[out] payload_contains_image_mauv_data  Flag to indicate whether Image
349*dca92e47SWilly Tu //                                               MAUV data is present in
350*dca92e47SWilly Tu //                                               payload's image descriptor
351*dca92e47SWilly Tu //
352*dca92e47SWilly Tu // @return `failure_reason`
353*dca92e47SWilly Tu failure_reason find_and_read_image_mauv_data_from_payload(
354*dca92e47SWilly Tu     const struct libcr51sign_ctx* const ctx,
355*dca92e47SWilly Tu     const struct libcr51sign_intf* const intf,
356*dca92e47SWilly Tu     const uint32_t payload_blob_offset, const uint32_t payload_blob_size,
357*dca92e47SWilly Tu     uint8_t payload_image_mauv_data_buffer[],
358*dca92e47SWilly Tu     uint32_t* const restrict payload_image_mauv_data_size,
359*dca92e47SWilly Tu     bool* const restrict payload_contains_image_mauv_data)
360*dca92e47SWilly Tu {
361*dca92e47SWilly Tu     failure_reason rv = LIBCR51SIGN_SUCCESS;
362*dca92e47SWilly Tu     uint32_t payload_image_mauv_data_offset = 0;
363*dca92e47SWilly Tu 
364*dca92e47SWilly Tu     rv = verify_payload_blob_magic(ctx, intf, payload_blob_offset);
365*dca92e47SWilly Tu     if (rv != LIBCR51SIGN_SUCCESS)
366*dca92e47SWilly Tu     {
367*dca92e47SWilly Tu         return rv;
368*dca92e47SWilly Tu     }
369*dca92e47SWilly Tu 
370*dca92e47SWilly Tu     rv = find_image_mauv_data_offset_in_payload(
371*dca92e47SWilly Tu         ctx, intf, payload_blob_offset + offsetof(struct blob, blobs),
372*dca92e47SWilly Tu         payload_blob_size, &payload_image_mauv_data_offset,
373*dca92e47SWilly Tu         payload_image_mauv_data_size);
374*dca92e47SWilly Tu     if (rv != LIBCR51SIGN_SUCCESS)
375*dca92e47SWilly Tu     {
376*dca92e47SWilly Tu         return rv;
377*dca92e47SWilly Tu     }
378*dca92e47SWilly Tu 
379*dca92e47SWilly Tu     *payload_contains_image_mauv_data = (payload_image_mauv_data_offset != 0);
380*dca92e47SWilly Tu 
381*dca92e47SWilly Tu     if (*payload_contains_image_mauv_data)
382*dca92e47SWilly Tu     {
383*dca92e47SWilly Tu         rv = read_image_mauv_data_from_payload(
384*dca92e47SWilly Tu             ctx, intf, payload_image_mauv_data_offset,
385*dca92e47SWilly Tu             *payload_image_mauv_data_size,
386*dca92e47SWilly Tu             (struct image_mauv*)payload_image_mauv_data_buffer);
387*dca92e47SWilly Tu         if (rv != LIBCR51SIGN_SUCCESS)
388*dca92e47SWilly Tu         {
389*dca92e47SWilly Tu             return rv;
390*dca92e47SWilly Tu         }
391*dca92e47SWilly Tu 
392*dca92e47SWilly Tu         return sanity_check_image_mauv_data(
393*dca92e47SWilly Tu             (struct image_mauv*)payload_image_mauv_data_buffer,
394*dca92e47SWilly Tu             *payload_image_mauv_data_size);
395*dca92e47SWilly Tu     }
396*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
397*dca92e47SWilly Tu }
398*dca92e47SWilly Tu 
399*dca92e47SWilly Tu // Replace stored Image MAUV data with payload Image MAUV data
400*dca92e47SWilly Tu //
401*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
402*dca92e47SWilly Tu //                 data for the user of the library
403*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
404*dca92e47SWilly Tu //                  and environment
405*dca92e47SWilly Tu // @param[in] payload_image_mauv_data  Image MAUV data from payload
406*dca92e47SWilly Tu // @param[in] payload_image_mauv_data_size  Size of Image MAUV data (in bytes)
407*dca92e47SWilly Tu //                                          embedded inside payload
408*dca92e47SWilly Tu //
409*dca92e47SWilly Tu // @return `failure_reason`
410*dca92e47SWilly Tu static failure_reason update_stored_image_mauv_data(
411*dca92e47SWilly Tu     const struct libcr51sign_ctx* const ctx,
412*dca92e47SWilly Tu     const struct libcr51sign_intf* const intf,
413*dca92e47SWilly Tu     const struct image_mauv* const restrict payload_image_mauv_data,
414*dca92e47SWilly Tu     const uint32_t payload_image_mauv_data_size)
415*dca92e47SWilly Tu {
416*dca92e47SWilly Tu     int irv = 0;
417*dca92e47SWilly Tu 
418*dca92e47SWilly Tu     if (!intf->store_new_image_mauv_data)
419*dca92e47SWilly Tu     {
420*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Missing interface intf->store_new_image_mauv_data\n",
421*dca92e47SWilly Tu                 __FUNCTION__);
422*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
423*dca92e47SWilly Tu     }
424*dca92e47SWilly Tu 
425*dca92e47SWilly Tu     irv = intf->store_new_image_mauv_data(
426*dca92e47SWilly Tu         ctx, (uint8_t*)payload_image_mauv_data, payload_image_mauv_data_size);
427*dca92e47SWilly Tu     if (irv != LIBCR51SIGN_SUCCESS)
428*dca92e47SWilly Tu     {
429*dca92e47SWilly Tu         CPRINTS(ctx,
430*dca92e47SWilly Tu                 "%s: Could not store new Image MAUV data from the payload\n",
431*dca92e47SWilly Tu                 __FUNCTION__);
432*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_STORING_NEW_IMAGE_MAUV_DATA;
433*dca92e47SWilly Tu     }
434*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
435*dca92e47SWilly Tu }
436*dca92e47SWilly Tu 
437*dca92e47SWilly Tu // Validates Image MAUV from payload against stored Image MAUV (if present)
438*dca92e47SWilly Tu //
439*dca92e47SWilly Tu // @param[in] ctx  context which describes the image and holds opaque private
440*dca92e47SWilly Tu //                 data for the user of the library
441*dca92e47SWilly Tu // @param[in] intf  function pointers which interface to the current system
442*dca92e47SWilly Tu //                  and environment
443*dca92e47SWilly Tu // @param[in] payload_blob_offset  Absolute offset of BLOB data embedded in
444*dca92e47SWilly Tu //                                 image descriptor. `0` if BLOB data is not
445*dca92e47SWilly Tu //                                 present in image descriptor
446*dca92e47SWilly Tu // @param[in] payload_blob_size  Size of BLOB data from `blob_size` field in
447*dca92e47SWilly Tu //                               image descriptor
448*dca92e47SWilly Tu //
449*dca92e47SWilly Tu // @return `failure_reason`
450*dca92e47SWilly Tu failure_reason
451*dca92e47SWilly Tu     validate_payload_image_mauv(const struct libcr51sign_ctx* const ctx,
452*dca92e47SWilly Tu                                 const struct libcr51sign_intf* const intf,
453*dca92e47SWilly Tu                                 const uint32_t payload_blob_offset,
454*dca92e47SWilly Tu                                 const uint32_t payload_blob_size)
455*dca92e47SWilly Tu {
456*dca92e47SWilly Tu     uint32_t payload_image_mauv_data_size = 0;
457*dca92e47SWilly Tu     struct full_mauv payload_image_mauv_data_buffer = {0};
458*dca92e47SWilly Tu 
459*dca92e47SWilly Tu     uint32_t stored_image_mauv_data_size = 0;
460*dca92e47SWilly Tu     struct full_mauv stored_image_mauv_data_buffer = {0};
461*dca92e47SWilly Tu 
462*dca92e47SWilly Tu     bool payload_contains_image_mauv_data = false;
463*dca92e47SWilly Tu 
464*dca92e47SWilly Tu     failure_reason rv = LIBCR51SIGN_SUCCESS;
465*dca92e47SWilly Tu     int irv = 0;
466*dca92e47SWilly Tu 
467*dca92e47SWilly Tu     bool payload_blob_present = (payload_blob_offset != 0);
468*dca92e47SWilly Tu     if (payload_blob_present)
469*dca92e47SWilly Tu     {
470*dca92e47SWilly Tu         rv = find_and_read_image_mauv_data_from_payload(
471*dca92e47SWilly Tu             ctx, intf, payload_blob_offset, payload_blob_size,
472*dca92e47SWilly Tu             (uint8_t*)&payload_image_mauv_data_buffer,
473*dca92e47SWilly Tu             &payload_image_mauv_data_size, &payload_contains_image_mauv_data);
474*dca92e47SWilly Tu         if (rv != LIBCR51SIGN_SUCCESS)
475*dca92e47SWilly Tu         {
476*dca92e47SWilly Tu             return rv;
477*dca92e47SWilly Tu         }
478*dca92e47SWilly Tu     }
479*dca92e47SWilly Tu 
480*dca92e47SWilly Tu     if (!intf->retrieve_stored_image_mauv_data)
481*dca92e47SWilly Tu     {
482*dca92e47SWilly Tu         if (payload_contains_image_mauv_data)
483*dca92e47SWilly Tu         {
484*dca92e47SWilly Tu             CPRINTS(
485*dca92e47SWilly Tu                 ctx,
486*dca92e47SWilly Tu                 "%s: Payload contains Image MAUV data but required interface "
487*dca92e47SWilly Tu                 "intf->retrieve_stored_image_mauv_data is missing\n",
488*dca92e47SWilly Tu                 __FUNCTION__);
489*dca92e47SWilly Tu             return LIBCR51SIGN_ERROR_INVALID_INTERFACE;
490*dca92e47SWilly Tu         }
491*dca92e47SWilly Tu         CPRINTS(
492*dca92e47SWilly Tu             ctx,
493*dca92e47SWilly Tu             "%s: Payload does not contain Image MAUV data and interface "
494*dca92e47SWilly Tu             "intf->retrieve_stored_image_mauv_data is missing. Skipping MAUV "
495*dca92e47SWilly Tu             "check for backward compatibility.\n",
496*dca92e47SWilly Tu             __FUNCTION__);
497*dca92e47SWilly Tu         return LIBCR51SIGN_SUCCESS;
498*dca92e47SWilly Tu     }
499*dca92e47SWilly Tu 
500*dca92e47SWilly Tu     irv = intf->retrieve_stored_image_mauv_data(
501*dca92e47SWilly Tu         ctx, (uint8_t*)&stored_image_mauv_data_buffer,
502*dca92e47SWilly Tu         &stored_image_mauv_data_size, IMAGE_MAUV_DATA_MAX_SIZE);
503*dca92e47SWilly Tu     if (irv == LIBCR51SIGN_NO_STORED_MAUV_FOUND)
504*dca92e47SWilly Tu     {
505*dca92e47SWilly Tu         CPRINTS(
506*dca92e47SWilly Tu             ctx,
507*dca92e47SWilly Tu             "%s: Stored Image MAUV data not present in the system. Skipping Image "
508*dca92e47SWilly Tu             "MAUV check\n",
509*dca92e47SWilly Tu             __FUNCTION__);
510*dca92e47SWilly Tu         if (payload_contains_image_mauv_data)
511*dca92e47SWilly Tu         {
512*dca92e47SWilly Tu             return update_stored_image_mauv_data(
513*dca92e47SWilly Tu                 ctx, intf, (struct image_mauv*)&payload_image_mauv_data_buffer,
514*dca92e47SWilly Tu                 payload_image_mauv_data_size);
515*dca92e47SWilly Tu         }
516*dca92e47SWilly Tu         return LIBCR51SIGN_SUCCESS;
517*dca92e47SWilly Tu     }
518*dca92e47SWilly Tu     if (irv != LIBCR51SIGN_SUCCESS)
519*dca92e47SWilly Tu     {
520*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Could not retrieve Image MAUV stored in system\n",
521*dca92e47SWilly Tu                 __FUNCTION__);
522*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_RETRIEVING_STORED_IMAGE_MAUV_DATA;
523*dca92e47SWilly Tu     }
524*dca92e47SWilly Tu     if (stored_image_mauv_data_size > IMAGE_MAUV_DATA_MAX_SIZE)
525*dca92e47SWilly Tu     {
526*dca92e47SWilly Tu         CPRINTS(ctx,
527*dca92e47SWilly Tu                 "%s: Stored Image MAUV data size (0x%x) is more than supported "
528*dca92e47SWilly Tu                 "maximum size\n",
529*dca92e47SWilly Tu                 __FUNCTION__, stored_image_mauv_data_size);
530*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_INVALID_IMAGE_MAUV_DATA;
531*dca92e47SWilly Tu     }
532*dca92e47SWilly Tu 
533*dca92e47SWilly Tu     rv = sanity_check_image_mauv_data(
534*dca92e47SWilly Tu         (struct image_mauv*)&stored_image_mauv_data_buffer,
535*dca92e47SWilly Tu         stored_image_mauv_data_size);
536*dca92e47SWilly Tu     if (rv != LIBCR51SIGN_SUCCESS)
537*dca92e47SWilly Tu     {
538*dca92e47SWilly Tu         return rv;
539*dca92e47SWilly Tu     }
540*dca92e47SWilly Tu 
541*dca92e47SWilly Tu     if (!payload_contains_image_mauv_data)
542*dca92e47SWilly Tu     {
543*dca92e47SWilly Tu         CPRINTS(ctx, "%s: Image MAUV expected to be present in payload",
544*dca92e47SWilly Tu                 __FUNCTION__);
545*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_EXPECTS_PAYLOAD_IMAGE_MAUV;
546*dca92e47SWilly Tu     }
547*dca92e47SWilly Tu 
548*dca92e47SWilly Tu     if (!does_stored_image_mauv_allow_update(
549*dca92e47SWilly Tu             (struct image_mauv*)&stored_image_mauv_data_buffer,
550*dca92e47SWilly Tu             ((struct image_mauv*)&payload_image_mauv_data_buffer)
551*dca92e47SWilly Tu                 ->payload_security_version))
552*dca92e47SWilly Tu     {
553*dca92e47SWilly Tu         CPRINTS(ctx,
554*dca92e47SWilly Tu                 "%s: Stored Image MAUV data does not allow update to payload "
555*dca92e47SWilly Tu                 "version\n",
556*dca92e47SWilly Tu                 __FUNCTION__);
557*dca92e47SWilly Tu         return LIBCR51SIGN_ERROR_STORED_IMAGE_MAUV_DOES_NOT_ALLOW_UPDATE_TO_PAYLOAD;
558*dca92e47SWilly Tu     }
559*dca92e47SWilly Tu 
560*dca92e47SWilly Tu     if (((struct image_mauv*)&payload_image_mauv_data_buffer)
561*dca92e47SWilly Tu             ->mauv_update_timestamp >
562*dca92e47SWilly Tu         ((struct image_mauv*)&stored_image_mauv_data_buffer)
563*dca92e47SWilly Tu             ->mauv_update_timestamp)
564*dca92e47SWilly Tu     {
565*dca92e47SWilly Tu         return update_stored_image_mauv_data(
566*dca92e47SWilly Tu             ctx, intf, (struct image_mauv*)&payload_image_mauv_data_buffer,
567*dca92e47SWilly Tu             payload_image_mauv_data_size);
568*dca92e47SWilly Tu     }
569*dca92e47SWilly Tu     return LIBCR51SIGN_SUCCESS;
570*dca92e47SWilly Tu }
571*dca92e47SWilly Tu 
572*dca92e47SWilly Tu #ifdef __cplusplus
573*dca92e47SWilly Tu } //  extern "C"
574*dca92e47SWilly Tu #endif
575