1 /*! 2 * @header 3 * Interfaces for manipulating Image4 firmware objects. 4 */ 5 #ifndef __IMG4_FIRMWARE_H 6 #define __IMG4_FIRMWARE_H 7 8 #define __IMG4_INDIRECT 1 9 #include <img4/api.h> 10 11 /*! 12 * @discussion 13 * When used from the pmap layer, this header pulls in the types from libsa, 14 * which conflict with the BSD sys/types.h header that we need to pull in. But 15 * we only need it for the errno_t typedef and the vnode_t typedef. So when 16 * building MACH_KERNEL_PRIVATE, we do two things: 17 * 18 * 1. Explicitly pull in <sys/_types/_errno_t.h>, so we get errno_t and 19 * nothing else (no transitive #include's) 20 * 2. #define _SYS_TYPES_H_ before #includ'ing <sys/kernel_types.h> so that 21 * we don't get the transitive #include of <sys/types.h> but we still get 22 * the definitions we need 23 */ 24 #if IMG4_TARGET_XNU 25 #if MACH_KERNEL_PRIVATE 26 #define _SYS_TYPES_H_ 1 27 #include <sys/kernel_types.h> 28 #include <sys/_types/_errno_t.h> 29 #else 30 #include <sys/kernel_types.h> 31 #include <sys/types.h> 32 #endif 33 34 #if XNU_KERNEL_PRIVATE 35 #include <img4/4xnu.h> 36 #endif 37 #endif // IMG4_TARGET_XNU 38 39 #if IMG4_TARGET_DARWIN 40 #include <os/stdio.h> 41 #include <sys/types.h> 42 #include <img4/4ignition.h> 43 #include <img4/4MSU.h> 44 #endif 45 46 __BEGIN_DECLS 47 OS_ASSUME_NONNULL_BEGIN 48 49 /*! 50 * @typedef img4_4cc_t 51 * A type which represents a four-character code (4cc) that identifies the 52 * firmware. These 4cc's are statically assigned and correspond to long-form tag 53 * names -- e.g. the 4cc 'krnl' corresponds to the "KernelCache" tag. 54 */ 55 IMG4_API_AVAILABLE_20200508 56 typedef uint32_t img4_4cc_t; 57 58 /*! 59 * @typedef img4_buff_t 60 * A structure describing a buffer. See {@link _img4_buff}. 61 */ 62 IMG4_API_AVAILABLE_20200508 63 typedef struct _img4_buff img4_buff_t; 64 65 /*! 66 * @const IMG4_DGST_STRUCT_VERSION 67 * The version of the {@link img4_dgst_t} structure supported by the 68 * implementation. 69 */ 70 #define IMG4_DGST_STRUCT_VERSION (0u) 71 72 /*! 73 * @const IMG4_DGST_MAX_LEN 74 * The maximum length of a digest representable by an {@link img4_dgst_t}. 75 */ 76 #define IMG4_DGST_MAX_LEN (48u) 77 78 /*! 79 * @typedef img4_dgst_t 80 * A type representing an Image4 identifier which is a digest. 81 * 82 * @field i4d_len 83 * The version of the structure. Initialize to {@link IMG4_DGST_STRUCT_VERSION}. 84 * 85 * @field i4d_len 86 * The length of the digest. 87 * 88 * @field i4d_bytes 89 * The digest bytes. 90 */ 91 IMG4_API_AVAILABLE_20200508 92 typedef struct _img4_dgst { 93 img4_struct_version_t i4d_version; 94 size_t i4d_len; 95 uint8_t i4d_bytes[IMG4_DGST_MAX_LEN]; 96 } img4_dgst_t; 97 98 /*! 99 * @const IMG4_DGST_INIT 100 * A convenience initializer for an {@link img4_dgst_t} structure. 101 */ 102 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 103 #define IMG4_DGST_INIT (img4_dgst_t){ \ 104 .i4d_version = IMG4_DGST_STRUCT_VERSION, \ 105 .i4d_len = 0, \ 106 .i4d_bytes = {0}, \ 107 } 108 #elif defined(__cplusplus) && __cplusplus >= 201103L 109 #define IMG4_DGST_INIT (img4_dgst_t{ \ 110 IMG4_DGST_STRUCT_VERSION, \ 111 0, \ 112 {0}, \ 113 }) 114 #elif defined(__cplusplus) 115 #define IMG4_DGST_INIT (img4_nonce_t((img4_nonce_t){ \ 116 IMG4_DGST_STRUCT_VERSION, \ 117 0, \ 118 {0}, \ 119 })) 120 #else 121 #define IMG4_DGST_INIT {IMG4_DGST_STRUCT_VERSION} 122 #endif 123 124 /*! 125 * @struct _img4_cstr 126 * A type representing an Image4 identifier which is a C-string. These 127 * identifiers can be no more than 64 bytes in length, including the null 128 * terminating byte. 129 * 130 * @field i4b_len 131 * The length of the C-string, not including the null terminating byte. 132 * 133 * @field i4b_cstr 134 * The null-terminated C-string. 135 * 136 * @discussion 137 * This structure is intentionally unversioned. It should never evolve into 138 * anything more complex than it is. 139 */ 140 IMG4_API_AVAILABLE_20210113 141 typedef struct _img4_cstr { 142 size_t i4cs_len; 143 char i4cs_cstr[64]; 144 } img4_cstr_t; 145 146 /*! 147 * @const IMG4_CSTR_INIT 148 * A convenience initializer for an {@link img4_cstr_t}. 149 */ 150 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 151 #define IMG4_CSTR_INIT (img4_cstr_t){ \ 152 .i4cs_len = 0, \ 153 .i4cs_cstr = {0}, \ 154 } 155 #elif defined(__cplusplus) && __cplusplus >= 201103L 156 #define IMG4_CSTR_INIT (img4_cstr_t{ \ 157 0, \ 158 {0}, \ 159 }) 160 #elif defined(__cplusplus) 161 #define IMG4_CSTR_INIT \ 162 (img4_cstr_t((img4_cstr_t){ \ 163 0, \ 164 {0}, \ 165 })) 166 #else 167 #define IMG4_CSTR_INIT {0} 168 #endif 169 170 /*! 171 * @typedef img4_chip_t 172 * An opaque type describing a destination chip environment for the firmware 173 * image. 174 */ 175 IMG4_API_AVAILABLE_20200508 176 typedef struct _img4_chip img4_chip_t; 177 178 /*! 179 * @typedef img4_firmware_t 180 * An opaque type describing an Image4 firmware object. 181 */ 182 IMG4_API_AVAILABLE_20200508 183 typedef struct _img4_firmware *img4_firmware_t; 184 185 /*! 186 * @typedef img4_image_t 187 * An opaque type describing an authenticated Image4 firmware image. 188 */ 189 IMG4_API_AVAILABLE_20200508 190 typedef struct _img4_image *img4_image_t; 191 192 /*! 193 * @typedef img4_runtime_t 194 * A structure describing required primitives in the operating environment's 195 * runtime. See {@link _img4_runtime}. 196 */ 197 IMG4_API_AVAILABLE_20200508 198 typedef struct _img4_runtime img4_runtime_t; 199 200 OS_ASSUME_NONNULL_END 201 202 #include <img4/nonce.h> 203 #include <img4/object.h> 204 #include <img4/chip.h> 205 #include <img4/chip_ap.h> 206 #include <img4/chip_ap_category.h> 207 #include <img4/chip_ap_software.h> 208 #include <img4/chip_cryptex1.h> 209 #include <img4/chip_sep.h> 210 #include <img4/chip_x86.h> 211 #include <img4/image.h> 212 #include <img4/runtime.h> 213 214 OS_ASSUME_NONNULL_BEGIN 215 216 /*! 217 * @typedef img4_firmware_authenticated_execute_t 218 * A firmware execution function. This function is called when the firmware has 219 * been successfully authenticated and is ready for execution. 220 * 221 * @param fw 222 * The firmware which has been authenticated. 223 * 224 * @param image 225 * The resulting firmware image that may be executed. The implementation will 226 * pass NULL if there was a failure. 227 * 228 * This object is automatically freed by the implementation upon return. 229 * 230 * @param error 231 * An error code describing the result of the authentication. If authentication 232 * was successful, the implementation will pass zero. Otherwise, one of the 233 * following error codes will be provided: 234 * 235 * [EILSEQ] The firmware data is not valid Image4 data -- this will not 236 * be passed for firmwares created with 237 * {@link IMG4_FIRMWARE_FLAG_BARE} 238 * [EFTYPE] The attached manifest is not a valid Image4 manifest 239 * [ENOENT] The attached manifest does not authenticate this type of 240 * firmware 241 * [EAUTH] The attached manifest is not authentic (i.e. was not signed 242 * by an Apple CA) 243 * [EACCES] The given chip does not satisfy the constraints of the 244 * attached manifest 245 * [ESTALE] The manifest has been invalidated and is no longer valid for 246 * the provided chip 247 * [ENOEXEC] The firmware has been corrupted, or the given chip does not 248 * satisfy the constraints of the corresponding object in the 249 * attached manifest 250 * 251 * @param _ctx 252 * The user-provided context pointer. 253 */ 254 IMG4_API_AVAILABLE_20200508 255 typedef void (*img4_firmware_authenticated_execute_t)( 256 const img4_firmware_t fw, 257 img4_image_t _Nullable image, 258 errno_t error, 259 void *_ctx 260 ); 261 262 #if IMG4_TARGET_EFI 263 typedef void (*img4_firmware_authenticated_execute_efi_t)( 264 const img4_firmware_t fw, 265 img4_image_t _Nullable image, 266 EFI_STATUS status, 267 void *_ctx 268 ); 269 #endif 270 271 /*! 272 * @define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION 273 * The version of the {@link img4_firmware_execution_context_t} structure 274 * supported by the implementation. 275 */ 276 #define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION (1u) 277 278 /*! 279 * @typedef img4_firmware_execution_context_t 280 * A structure describing the context in which a firmware is to be executed. 281 * 282 * @field i4fex_version 283 * The version of the structure supported by the implementation. Initialize to 284 * {@link IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION}. 285 * 286 * @field i4fex_execute 287 * A pointer to the firmware execution function. 288 * 289 * @field i4fex_execute_efi 290 * A pointer to the EFI-specific firmware execution function. This is only 291 * available in the EFI environment. If both this field and 292 * {@link i4fex_execute} are specified in the execution context, the 293 * one which is called by the implementation will be undefined. 294 * 295 * This field was added in version 1 of the structure. It was not appended to 296 * the end of the structure since the non-EFI structure did not change, and the 297 * structure did not previously exist in the EFI environment. The version 298 * increment was not strictly necessary, but was done for hygienic reasons. 299 * 300 * @field i4fex_context 301 * A caller-provided context pointer that will be passed to functions invoked 302 * from the execution context. 303 */ 304 IMG4_API_AVAILABLE_20200508 305 typedef struct _img4_firmware_execution_context { 306 img4_struct_version_t i4fex_version; 307 img4_firmware_authenticated_execute_t i4fex_execute; 308 #if IMG4_TARGET_EFI 309 img4_firmware_authenticated_execute_efi_t i4fex_execute_efi; 310 #endif 311 void *i4fex_context; 312 } img4_firmware_execution_context_t; 313 314 /*! 315 * @typedef img4_firmware_flags_t 316 * A bitfield modifying the behavior of an {@link img4_firmware_t} object. 317 * 318 * @const IMG4_FIRMWARE_FLAG_INIT 319 * No bits set. This value is suitable for initialization purposes. 320 * 321 * @const IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST 322 * The manifest authenticating the firmware is attached (i.e. the buffer given 323 * represents a .img4 file). 324 * 325 * @const IMG4_FIRMWARE_FLAG_BARE 326 * The firmware image is not wrapped with an Image4 payload structure. This flag 327 * is mutually exclusive with {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST}, and 328 * if both are present, the implementation's behavior is undefined. 329 * 330 * @const IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE 331 * The firmware image extends an existing chain of trust. If set, the 332 * runtime must provide a {@link i4rt_get_digest} function which returns a 333 * digest for {@link IMG4_IDENTIFIER_CHMH}. 334 * 335 * If set, the firmware may optionally provide a {@link i4rt_get_bool} function 336 * which returns a value for {@link IMG4_IDENTIFIER_AMNM}. 337 * 338 * @const IMG4_FIRMWARE_FLAG_RESPECT_AMNM 339 * Forces the implementation to respect the manifest's AMNM entitlement if it is 340 * present, even if the validation is creating a new chain of trust. This is 341 * technically maybe sort of against the Image4 spec, but it is useful for 342 * certain internal workflows (cf. v2.3, §2.2.10). 343 * 344 * This flag has no effect if {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} is 345 * also passed. 346 * 347 * @const IMG4_FIRMWARE_FLAG_PASSTHROUGH 348 * Causes the wrapped payload bytes to be delivered to the image execution 349 * callback. These bytes do not have the Image4 wrapping stripped. 350 * 351 * @const IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY 352 * Force anti-replay enforcement even when performing just manifest evaluation 353 * without executing a firmware. When executing a firmware, this flag need not 354 * be passed in since anti-replay enforcement is always enabled. 355 */ 356 IMG4_API_AVAILABLE_20200508 357 OS_CLOSED_OPTIONS(img4_firmware_flags, uint64_t, 358 IMG4_FIRMWARE_FLAG_INIT, 359 IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST = (1 << 0), 360 IMG4_FIRMWARE_FLAG_BARE = (1 << 1), 361 IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE = (1 << 2), 362 IMG4_FIRMWARE_FLAG_RESPECT_AMNM = (1 << 3), 363 IMG4_FIRMWARE_FLAG_PASSTHROUGH = (1 << 4), 364 IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY = (1 << 5), 365 ); 366 367 /*! 368 * @function img4_firmware_new 369 * Allocate and initialize a new firmware object. 370 * 371 * @param rt 372 * The runtime in which to initialize the object. 373 * 374 * @param _4cc 375 * The 4cc which distinguishes the firmware. 376 * 377 * @param buff 378 * A buffer containing a valid Image4 payload (usually the contents of either a 379 * .im4p or .img4 file). 380 * 381 * Upon return, the destructor in the buffer is replaced with NULL, and the 382 * implementation assumes responsibility for deallocating the underlying memory. 383 * 384 * @param flags 385 * Flags modifying the behavior of the object. 386 * 387 * @result 388 * A new firmware object or NULL if there was an allocation failure. If 389 * {@link rt} has a NULL allocation function, NULL is returned. 390 * 391 * @discussion 392 * The resulting object assumes ownership of the given buffer. 393 * 394 * In the Darwin userspace runtime, NULL will not be returned. 395 */ 396 #if !XNU_KERNEL_PRIVATE 397 IMG4_API_AVAILABLE_20200508 398 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4 399 img4_firmware_t _Nullable 400 img4_firmware_new(const img4_runtime_t *rt, 401 const img4_firmware_execution_context_t *exec, 402 img4_4cc_t _4cc, 403 img4_buff_t *buff, 404 img4_firmware_flags_t flags); 405 #else 406 #define img4_firmware_new(...) (img4if->i4if_v7.firmware_new(__VA_ARGS__)) 407 #endif 408 409 /*! 410 * @function img4_firmware_new_from_vnode_4xnu 411 * Allocate and initialize a new firmware object from a vnode. 412 * 413 * @param rt 414 * The runtime in which to initialize the object. This interface is only 415 * supported with the Darwin kernel runtime. If any other runtime is provided, 416 * the implementation's behavior is undefined. 417 * 418 * @param _4cc 419 * The 4cc which distinguishes the firmware. 420 * 421 * @param vn 422 * A vnode representing a valid Image4 payload (usually the contents of either a 423 * .im4p or .img4 file). 424 * 425 * @param flags 426 * Flags modifying the behavior of the object. 427 * 428 * @result 429 * A new firmware object or NULL if there was an allocation failure. 430 * 431 * @discussion 432 * Verification of a vnode is performed by reading in chunks of data, updating 433 * an ongoing hash operation with that data, and then discarding it. Therefore, 434 * firmware objects created in this manner can only guarantee their validity at 435 * the time the check was performed since the vnode's contents are not kept in 436 * memory and may be tampered with after validation has been performed. 437 * 438 * As such, on successful execution, the image passed to the 439 * {@link img4_firmware_authenticated_execute_t} function of the execution 440 * context is NULL. 441 * 442 * Firmwares created with this interface cannot be created with the 443 * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag. 444 */ 445 #if IMG4_TARGET_XNU 446 #if !XNU_KERNEL_PRIVATE 447 IMG4_API_AVAILABLE_20200508 448 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4 449 img4_firmware_t _Nullable 450 img4_firmware_new_from_vnode_4xnu(const img4_runtime_t *rt, 451 const img4_firmware_execution_context_t *exec, 452 img4_4cc_t _4cc, 453 vnode_t vn, 454 img4_firmware_flags_t flags); 455 #else 456 #define img4_firmware_new_from_vnode_4xnu(...) \ 457 (img4if->i4if_v7.firmware_new_from_vnode_4xnu(__VA_ARGS__)) 458 #endif // !XNU_KERNEL_PRIVATE 459 #endif // IMG4_TARGET_XNU 460 461 /*! 462 * @function img4_firmware_new_from_fd_4MSM 463 * Allocate and initialize a new firmware object from a file descriptor. 464 * 465 * @param rt 466 * The runtime in which to initialize the object. This interface is only 467 * supported with the Darwin userspace runtime. If any other runtime is 468 * provided, the implementation's behavior is undefined. 469 * 470 * @param _4cc 471 * The 4cc which distinguishes the firmware. 472 * 473 * @param fd 474 * A pointer to a file descriptor representing a valid Image4 payload (usually 475 * the contents of either a .im4p or .img4 file). The object assumes ownership 476 * of the descriptor, and upon return, the value referenced by the pointer will 477 * be set to -1. 478 * 479 * @param flags 480 * Flags modifying the behavior of the object. 481 * 482 * @result 483 * A new firmware object. The implementation will not return NULL. 484 * 485 * @discussion 486 * This interface is the userspace equivalent of 487 * {@link img4_firmware_new_from_vnode_4xnu}, and all the same caveats apply. 488 */ 489 #if IMG4_TARGET_DARWIN 490 IMG4_API_AVAILABLE_20200508 491 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 492 img4_firmware_t 493 img4_firmware_new_from_fd_4MSM(const img4_runtime_t *rt, 494 const img4_firmware_execution_context_t *exec, 495 img4_4cc_t _4cc, 496 os_fd_t *fd, 497 img4_firmware_flags_t flags); 498 #endif 499 500 /*! 501 * @function img4_firmware_init_from_buff 502 * Initializes a buffer as a firmware object. This interface is useful for 503 * runtimes which do not provide for dynamic memory allocation. 504 * 505 * @param storage 506 * A pointer to the storage to use for the firmware object. 507 * 508 * @param len 509 * The size of the buffer. 510 * 511 * @discussion 512 * The caller is expected to pass a buffer that is "big enough". If the provided 513 * buffer is too small, the implementation will abort the caller. 514 * 515 * @example 516 * 517 * uint8_t _buff[IMG4_FIRMWARE_SIZE_RECOMMENDED]; 518 * img4_firmware_t fw = NULL; 519 * 520 * fw = img4_firmware_init_from_buff(_buff, sizeof(_buff)); 521 * img4_firmware_init(fw, IMG4_RUNTIME_DEFAULT, &exec_context, 522 * kImg4Tag_krnl, fw_buff, 0); 523 */ 524 #if !XNU_KERNEL_PRIVATE 525 IMG4_API_AVAILABLE_20200508 526 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 527 img4_firmware_t 528 img4_firmware_init_from_buff(void *buff, size_t len); 529 #else 530 #define img4_firmware_init_from_buff(...) \ 531 (img4if->i4if_v7.firmware_init_from_buff(__VA_ARGS__)) 532 #endif 533 534 /*! 535 * @function img4_firmware_init 536 * Initialize a firmware object. 537 * 538 * @param fw 539 * A pointer to the storage for the firmware object. This pointer should refer 540 * to a region of memory that is sufficient to hold a {@link img4_firmware_t} 541 * object. This size should be queried with the {@link i4rt_object_size} 542 * function of the runtime. 543 * 544 * @param rt 545 * The runtime in which to initialize the object. 546 * 547 * @param _4cc 548 * The 4cc which distinguishes the firmware. 549 * 550 * @param buff 551 * A buffer containing a valid Image4 payload (usually the contents of either a 552 * .im4p or .img4 file). 553 * 554 * Upon return, the destructor in the buffer is replaced with NULL, and the 555 * implementation assumes responsibility for deallocating the underlying memory. 556 * 557 * @param flags 558 * Flags modifying the behavior of the object. 559 * 560 * @discussion 561 * The resulting object assumes ownership of the given buffer. This routine 562 * should only be used when dynamic memory allocation is not available in the 563 * runtime. Otherwise, use {@link img4_firmware_new}. 564 */ 565 #if !XNU_KERNEL_PRIVATE 566 IMG4_API_AVAILABLE_20200508 567 OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL5 568 void 569 img4_firmware_init(img4_firmware_t fw, 570 const img4_runtime_t *rt, 571 const img4_firmware_execution_context_t *exec, 572 img4_4cc_t _4cc, 573 img4_buff_t *buff, 574 img4_firmware_flags_t flags); 575 #else 576 #define img4_firmware_init(...) (img4if->i4if_v7.firmware_init(__VA_ARGS__)) 577 #endif 578 579 /*! 580 * @function img4_firmware_init_sentinel 581 * Initialize a firmware object as a sentinel without any manifest attached. 582 * This firmware has no object tag and is not executable. It is only suitable 583 * for use with {@link img4_firmware_attach_manifest} and 584 * {@link img4_firmware_evaluate} to determine whether a manifest is acceptable 585 * to a particular chip environment. 586 * 587 * @param fw 588 * A pointer to the storage for the firmware object. This pointer should refer 589 * to a region of memory that is sufficient to hold a {@link img4_firmware_t} 590 * object. This size should be queried with the {@link i4rt_object_size} 591 * function of the runtime. 592 * 593 * @param rt 594 * The runtime in which to initialize the object. 595 * 596 * @param flags 597 * Flags modifying the behavior of the object. 598 * 599 * @discussion 600 * Sentinel firmwares do not enforce anti-replay, so 601 * {@link img4_firmware_evaluate} will not return ESTALE when evaluating such 602 * firmwares. Anti-replay enforcement can be enabled by using 603 * {@link IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY}. 604 */ 605 #if !XNU_KERNEL_PRIVATE 606 IMG4_API_AVAILABLE_20211126 607 OS_EXPORT OS_NONNULL1 OS_NONNULL2 608 void 609 img4_firmware_init_sentinel(img4_firmware_t fw, 610 const img4_runtime_t *rt, 611 img4_firmware_flags_t flags); 612 #else 613 #define img4_firmware_init_sentinel(...) \ 614 (img4if->i4if_v17.firmware_init_sentinel(__VA_ARGS__)) 615 #endif 616 617 /*! 618 * @function img4_firmware_attach_manifest 619 * Attaches a signed manifest to the firmware. 620 * 621 * @param fw 622 * The firmware to manipulate. 623 * 624 * @param buff 625 * A buffer containing a valid Image4 manifest (usually the contents of either a 626 * .im4m or .img4 file). 627 * 628 * Upon return, the destructor in the buffer is replaced with NULL, and the 629 * implementation assumes responsibility for deallocating the underlying memory. 630 * 631 * @discussion 632 * If this interface is called on a firmware created with the 633 * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag, the implementation's 634 * behavior is undefined. 635 * 636 * This interface must be called on any firmware created with the 637 * {@link IMG4_FIRMWARE_FLAG_BARE} flag. 638 * 639 * The object assumes ownership of the given buffer. 640 */ 641 #if !XNU_KERNEL_PRIVATE 642 IMG4_API_AVAILABLE_20200508 643 OS_EXPORT OS_NONNULL1 OS_NONNULL2 644 void 645 img4_firmware_attach_manifest(img4_firmware_t fw, 646 img4_buff_t *buff); 647 #else 648 #define img4_firmware_attach_manifest(...) \ 649 (img4if->i4if_v7.firmware_attach_manifest(__VA_ARGS__)) 650 #endif 651 652 /*! 653 * @function img4_firmware_select_chip 654 * Returns the chip from the provided array which may be used to authenticate 655 * the firmware. 656 * 657 * @param fw 658 * The firmware to query. 659 * 660 * @param acceptable_chips 661 * An array of chips the caller finds acceptable to verify the firmware. 662 * 663 * @param acceptable_chips_cnt 664 * The number of elements in {@link acceptable_chips}. 665 * 666 * @result 667 * If the manifest may be authenticated by the certificate chain associated with 668 * one of the manifests provided in {@link acceptable_chips}, that chip is 669 * returned. If the manifest cannot be authenticated with any of the provided 670 * chips, NULL is returned. 671 * 672 * @discussion 673 * The result of calling this function on a firmware which does not have a 674 * manifest attached is undefined. 675 * 676 * If multiple chips may be used to authenticate the firmware, the 677 * implementation does not define which of those chips will be returned. 678 * 679 * If the firmware was created without the 680 * {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} flag, this function will return 681 * NULL. This function cannot be used to establish new trust chains, only to 682 * verify an existing one. 683 */ 684 #if !XNU_KERNEL_PRIVATE 685 IMG4_API_AVAILABLE_20200724 686 OS_EXPORT OS_WARN_RESULT 687 const img4_chip_t *_Nullable 688 img4_firmware_select_chip(const img4_firmware_t fw, 689 const img4_chip_select_array_t _Nonnull acceptable_chips, 690 size_t acceptable_chips_cnt); 691 #else 692 #define img4_firmware_select_chip(...) \ 693 (img4if->i4if_v10.firmware_select_chip(__VA_ARGS__)) 694 #endif 695 696 /*! 697 * @function img4_firmware_execute 698 * Authenticate the firmware and execute it within its context. 699 * 700 * @param fw 701 * The firmware to execute. 702 * 703 * @param chip 704 * The chip on which to execute the firmware. 705 * 706 * @param nonce 707 * The nonce to use for authentication. May be NULL if the chip environment does 708 * not maintain an anti-replay token or if a chained evaluation is being 709 * performed. 710 * 711 * @discussion 712 * The implementation will always invoke the 713 * {@link img4_firmware_authenticated_execute_t} provided in the execution 714 * context with either a successful result or a failure. All error handling must 715 * take place in that context. 716 * 717 * The {@link img4_firmware_authenticated_execute_t} is called before the 718 * implementation returns. 719 * 720 * The result of executing a firmware without a manifest attached (either via 721 * {@link img4_firmware_attach_manifest} or by creating the firmware with the 722 * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined. 723 */ 724 #if !XNU_KERNEL_PRIVATE 725 IMG4_API_AVAILABLE_20200508 726 OS_EXPORT OS_NONNULL1 OS_NONNULL2 727 void 728 img4_firmware_execute(img4_firmware_t fw, 729 const img4_chip_t *chip, 730 const img4_nonce_t *_Nullable nonce); 731 #else 732 #define img4_firmware_execute(...) \ 733 (img4if->i4if_v7.firmware_execute(__VA_ARGS__)) 734 #endif 735 736 /*! 737 * @function img4_firmware_evaluate 738 * Evaluate the firmware for authenticity. 739 * 740 * @param fw 741 * The firmware to evaluate. 742 * 743 * @param chip 744 * The chip on which to evaluate the firmware. 745 * 746 * @param nonce 747 * The nonce to use for authentication. May be NULL if the chip environment does 748 * not maintain an anti-replay token or if a chained evaluation is being 749 * performed. 750 * 751 * @result 752 * An error code describing the result of the authentication. If authentication 753 * was successful, zero is returned. Otherwise, one of the following error codes 754 * will be returned: 755 * 756 * [EILSEQ] The firmware data is not valid Image4 data -- this will not 757 * be returned for firmwares created with 758 * {@link IMG4_FIRMWARE_FLAG_BARE} 759 * [EFTYPE] The attached manifest is not a valid Image4 manifest 760 * [ENOENT] The attached manifest does not authenticate this type of 761 * firmware 762 * [EAUTH] The attached manifest is not authentic (i.e. was not signed 763 * by an Apple CA) 764 * [EACCES] The given chip does not satisfy the constraints of the 765 * attached manifest 766 * [ESTALE] The manifest has been invalidated and is no longer valid for 767 * the provided chip 768 * [ENOEXEC] The firmware has been corrupted, or the given chip does not 769 * satisfy the constraints of the corresponding object in the 770 * attached manifest 771 * [EPWROFF] The chip environment has not yet booted; most chip 772 * environments are booted and available by the time the caller 773 * has begun executing, but some require additional 774 * initialization before they can execute objects 775 * 776 * @discussion 777 * This interface should be used when the caller is only concerned with the 778 * authenticity and integrity of the firmware image and does not intend to 779 * execute it. 780 * 781 * The result of evaluating a firmware without a manifest attached (either via 782 * {@link img4_firmware_attach_manifest} or by creating the firmware with the 783 * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined. 784 */ 785 #if !XNU_KERNEL_PRIVATE 786 IMG4_API_AVAILABLE_20200608 787 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 788 errno_t 789 img4_firmware_evaluate(img4_firmware_t fw, 790 const img4_chip_t *chip, 791 const img4_nonce_t *_Nullable nonce); 792 #else 793 #define img4_firmware_evaluate(...) \ 794 (img4if->i4if_v9.firmware_evaluate(__VA_ARGS__)) 795 #endif 796 797 /*! 798 * @function img4_firmware_destroy 799 * Destroys a firmware object and releases the associated resources according to 800 * the runtime's specification. 801 * 802 * @param fw 803 * A pointer to the firmware object. 804 * 805 * Upon return, this will be replaced with a known-invalid pointer value. This 806 * parameter may be NULL in which case the implementation will return 807 * immediately. 808 * 809 * @discussion 810 * The implementation will invoke the provided deallocation function of the 811 * buffer object underlying the firmware. 812 */ 813 #if !XNU_KERNEL_PRIVATE 814 IMG4_API_AVAILABLE_20200508 815 OS_EXPORT 816 void 817 img4_firmware_destroy(img4_firmware_t _Nonnull *_Nullable fw); 818 #else 819 #define img4_firmware_destroy(...) \ 820 (img4if->i4if_v7.firmware_destroy(__VA_ARGS__)) 821 #endif 822 823 OS_ASSUME_NONNULL_END 824 __END_DECLS 825 826 #endif // __IMG4_FIRMWARE_H 827