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` 43*6c41aba5SPatrick Williams static failure_reason verify_payload_blob_magic( 44*6c41aba5SPatrick Williams 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` 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 { 142c66ebc35SPatrick Williams *payload_image_mauv_data_offset = 143c66ebc35SPatrick 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` 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 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` 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` 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` 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` 450c66ebc35SPatrick Williams failure_reason validate_payload_image_mauv( 451c66ebc35SPatrick Williams const struct libcr51sign_ctx* const ctx, 452dca92e47SWilly Tu const struct libcr51sign_intf* const intf, 453c66ebc35SPatrick 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