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