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