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