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