1 /* 2 * Copyright © 2017-2024 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /*! 29 * @header 30 * Encapsulation which describes an Image4 trust object. This object can perform 31 * an evaluation in the context of a given environment, record properties that 32 * were encountered during evaluation, and deliver the evaluation result to the 33 * caller according to the type of evaluation being performed. 34 */ 35 #ifndef __IMAGE4_API_TRUST_H 36 #define __IMAGE4_API_TRUST_H 37 38 #include <image4/image4.h> 39 #include <image4/types.h> 40 #include <stdint.h> 41 #include <stdbool.h> 42 43 #if __has_include(<sys/types.h>) 44 #include <sys/types.h> 45 #else 46 typedef int errno_t; 47 #endif 48 49 __BEGIN_DECLS 50 OS_ASSUME_NONNULL_BEGIN 51 OS_ASSUME_PTR_ABI_SINGLE_BEGIN 52 53 #pragma mark Supporting Types 54 /*! 55 * @typedef image4_trust_flags_t 56 * Flags that may be provided to influence the behavior of an 57 * {@link image4_trust_t} object. 58 * 59 * @const IMAGE4_TRUST_FLAG_INIT 60 * No flags set. This value is suitable for initialization purposes. 61 * 62 * @const IMAGE4_TRUST_FLAG_VIOLATION_PANIC 63 * Upon encountering a violation during trust evaluation, the implementation 64 * should abort the current context. 65 */ 66 OS_CLOSED_OPTIONS(image4_trust_flags, uint64_t, 67 IMAGE4_TRUST_FLAG_INIT = 0, 68 IMAGE4_TRUST_FLAG_VIOLATION_PANIC = (1 << 0), 69 ); 70 71 /*! 72 * @typedef image4_trust_section_t 73 * An enumeration of property sections in an Image4 manifest or object. Note 74 * that this is not strictly aligned with the concept of a "section" as defined 75 * in the Image4 specification. 76 * 77 * @const IMAGE4_TRUST_SECTION_CERTIFICATE 78 * The certificate properties within the manifest section. 79 * 80 * @const IMAGE4_TRUST_SECTION_MANIFEST 81 * The top-level properties in the manifest section. 82 * 83 * @const IMAGE4_TRUST_SECTION_OBJECT 84 * The properties associated with a particular object in the manifest section. 85 * 86 * @const IMAGE4_TRUST_SECTION_RESTORE_INFO 87 * The top-level properties in the RestoreInfo section. The RestoreInfo section 88 * is only recognized by the implementation when the trust object has been 89 * initialized with an IMG4 object that contains an IM4R section. 90 * 91 * @availability 92 * This constant first became available in API version 20231103. 93 * 94 * @const IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES 95 * The properties associated with the payload that is associated with the trust 96 * object, either by initializing the object with an IMG4 object, or by setting 97 * a payload with {@link image4_trust_set_payload}. 98 * 99 * @availability 100 * This constant first became available in API version 20231103. 101 */ 102 OS_CLOSED_ENUM(image4_trust_section, uint64_t, 103 IMAGE4_TRUST_SECTION_CERTIFICATE, 104 IMAGE4_TRUST_SECTION_MANIFEST, 105 IMAGE4_TRUST_SECTION_OBJECT, 106 IMAGE4_TRUST_SECTION_RESTORE_INFO, 107 IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES, 108 _IMAGE4_TRUST_SECTION_CNT, 109 ); 110 111 /*! 112 * @typedef image4_trust_evaluation_result_t 113 * A callback for the result of a trust evaluation. 114 * 115 * @param trst 116 * The trust object. 117 * 118 * @param result 119 * Upon success, the prescribed payload resulting from the type of trust 120 * evaluation. If the trust evaluation type does not deliver a payload, or the 121 * trust evaluation failed, NULL will be passed. 122 * 123 * @param result_len 124 * The length of the buffer referenced by {@link payload}. If {@link payload} is 125 * NULL, zero will be passed. 126 * 127 * @param error 128 * A POSIX error code describing the result of the trust evaluation. Upon 129 * success, zero will be passed. The implementation may directly return any of 130 * the following: 131 * 132 * [EILSEQ] The manifest or payload data is not valid Image4 data 133 * [EFTYPE] The manifest is not a valid Image4 manifest, or the payload 134 * type does not match the type specified to 135 * {@link image4_trust_set_payload} 136 * [ENOENT] The manifest does not authenticate the payload specified to 137 * {@link image4_trust_set_payload} 138 * [EAUTH] The manifest was signed by a key which was either not issued 139 * by the expected certificate authority, or the manifest 140 * violated the signing key's constraints 141 * [EACCES] The manifest constraints were violated by the environment 142 * [ESTALE] The manifest has been invalidated and is no longer valid for 143 * the provided environment 144 * [ENOEXEC] The payload measurement does not match the measurement 145 * expected in the manifest 146 * [E2BIG] The caller specified a result buffer via 147 * {@link image4_trust_set_result_buffer}, and the buffer was 148 * not sufficient to hold the result 149 * 150 * @param context 151 * The caller-provided context pointer. If no context pointer was set, NULL will 152 * be passed. 153 */ 154 typedef void (*image4_trust_evaluation_result_t)( 155 const image4_trust_t *trst, 156 const void *_Nullable __sized_by(result_len) result, 157 size_t result_len, 158 errno_t error, 159 void *_Nullable context 160 ); 161 162 /*! 163 * @const IMAGE4_TRUST_STRUCT_VERSION 164 * The version of the {@link image4_trust_t} structure supported by the 165 * implementation. 166 */ 167 #define IMAGE4_TRUST_STRUCT_VERSION (1u) 168 169 /*! 170 * @header image4_trust_storage_t 171 * An opaque structure which is guaranteed to be large enough to accommodate an 172 * {@link image4_trust_t}. 173 * 174 * @field __opaque 175 * The opaque storage. 176 * 177 * @discussion 178 * The size of this object was set in API version 20231103. 179 */ 180 typedef struct _image4_trust_storage { 181 uint8_t __opaque[2048]; 182 } image4_trust_storage_t; 183 184 /*! 185 * @const IMAGE4_TRUST_STORAGE_INIT 186 * Initializer for a {@link image4_trust_storage_t} object. 187 */ 188 #define IMAGE4_TRUST_STORAGE_INIT (image4_trust_storage_t){ \ 189 .__opaque = { 0x00 }, \ 190 } 191 192 #pragma mark API 193 /*! 194 * @function image4_trust_init 195 * Convert a {@link image4_trust_storage_t} to an initialized 196 * {@link image4_trust_t} object. 197 * 198 * @param storage 199 * The storage structure. 200 * 201 * @param nv 202 * The environment in which the trust evaluation should be performed. 203 * 204 * @param evaluation 205 * The trust evaluation type that should be performed. 206 * 207 * @param manifest 208 * A pointer to the Image4 manifest bytes. This buffer may refer to a stitched 209 * manifest and payload object, in which case the implementation will extract 210 * the manifest portion. 211 * 212 * These bytes are not copied into any implementation storage, and the caller is 213 * responsible for ensuring that this memory remains valid for the duration of 214 * the trust object's use. 215 * 216 * @param manifest_len 217 * The length of the buffer referenced by {@link manifest}. 218 * 219 * @param flags 220 * Flags to influence the behavior of the resulting trust object. 221 * 222 * @result 223 * An initialized {@link image4_trust_t} object. 224 */ 225 IMAGE4_API_AVAILABLE_SPRING_2024 226 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL4 227 image4_trust_t * 228 _image4_trust_init( 229 image4_trust_storage_t *storage, 230 const image4_environment_t *nv, 231 const image4_trust_evaluation_t *evaluation, 232 const void *__sized_by(manifest_len) manifest, 233 size_t manifest_len, 234 image4_trust_flags_t flags, 235 image4_struct_version_t v); 236 #define image4_trust_init(_storage, _environment, _evaluation, \ 237 _manifest, _manifest_len, _flags) \ 238 _image4_trust_init( \ 239 (_storage), \ 240 (_environment), \ 241 (_evaluation), \ 242 (_manifest), \ 243 (_manifest_len), \ 244 (_flags), \ 245 IMAGE4_TRUST_STRUCT_VERSION) 246 IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_init); 247 248 /*! 249 * @function image4_trust_new 250 * Allocates a trust object. 251 * 252 * @param nv 253 * The environment in which the trust evaluation should be performed. 254 * 255 * @param eval 256 * The trust evaluation type that should be performed. 257 * 258 * @param manifest 259 * A pointer to the Image4 manifest bytes. This buffer may refer to a stitched 260 * manifest and payload object, in which case the implementation will extract 261 * the manifest portion. 262 * 263 * These bytes are not copied into any implementation storage, and the caller is 264 * responsible for ensuring that this memory remains valid for the duration of 265 * the trust object's use. 266 * 267 * @param manifest_len 268 * The length of the buffer referenced by {@link manifest}. 269 * 270 * @param flags 271 * Flags to influence the behavior of the resulting trust object. 272 * 273 * @result 274 * A newly-allocated and initialized {@link image4_trust_t} object. The caller 275 * is responsible for disposing of this object with {@link image4_trust_destroy} 276 * when it is no longer needed. 277 * 278 * If insufficient resources were available to allocate the object, or if the 279 * host runtime does not have an allocator, NULL is returned. 280 */ 281 IMAGE4_API_AVAILABLE_SPRING_2024 282 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 283 image4_trust_t *_Nullable 284 image4_trust_new( 285 const image4_environment_t *nv, 286 const image4_trust_evaluation_t *eval, 287 const void *__sized_by(manifest_len) manifest, 288 size_t manifest_len, 289 image4_trust_flags_t flags); 290 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_new); 291 292 /*! 293 * @function image4_trust_set_payload 294 * Sets the payload to be used during the trust evaluation. 295 * 296 * @param trst 297 * The trust object. 298 * 299 * @param type 300 * The four-character code of the payload. 301 * 302 * @param bytes 303 * A pointer to the payload bytes to authenticate during trust evaluation. This 304 * buffer may refer to a stitched manifest and payload object, in which case the 305 * implementation will extract the payload portion. 306 * 307 * If the buffer does not refer to either a valid Image4 manifest or payload, 308 * the implementation will conclude that it is a bare Image4 payload -- that is, 309 * a payload which is not Image4-wrapped. 310 * 311 * These bytes are not copied into any implementation storage, and the caller is 312 * responsible for ensuring that this memory remains valid for the duration of 313 * the trust object's use. 314 * 315 * @param len 316 * The length of the buffer referenced by {@link bytes}. 317 */ 318 IMAGE4_API_AVAILABLE_SPRING_2024 319 OS_EXPORT OS_NONNULL1 OS_NONNULL3 320 void 321 image4_trust_set_payload( 322 image4_trust_t *trst, 323 uint32_t type, 324 const void *__sized_by(len) bytes, 325 size_t len); 326 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_payload); 327 328 /*! 329 * @function image4_trust_set_booter 330 * Establish a link between the trust object and another trust object 331 * representing a previous stage of boot, securing it to that stage of boot. 332 * This may be called multiple times. Successive calls secure the previously- 333 * specified booter stage to the newly-specified booter stage, establishing a 334 * chain of trust from the last stage to the first stage. 335 * 336 * @param trst 337 * The trust object. This object must have been created with one of the 338 * following trust evaluation types: 339 * 340 * - {@link IMAGE4_TRUST_EVALUATION_PREFLIGHT} 341 * - {@link IMAGE4_TRUST_EVALUATION_SIGN} 342 * 343 * @param booter 344 * The trust object representing the previous stage of boot for {@link trst}. 345 * This object must have been created with the 346 * {@link IMAGE4_TRUST_EVALUATION_BOOT} trust evaluation type. 347 * 348 * This object is not copied into any implementation storage, and the caller is 349 * responsible for ensuring that it remains valid for the duration of the trust 350 * object's use. 351 * 352 * @discussion 353 * Trust objects with booter stages cannot be used to execute firmware because 354 * they are only intended to simulate a boot by replicating side effects of 355 * previous evaluations into the ultimate environment used by the trust object. 356 * 357 * In order to execute firmware, the environment must be consistent with the 358 * requirements of the manifest without modifications being required. 359 */ 360 IMAGE4_API_AVAILABLE_SPRING_2024 361 OS_EXPORT OS_NONNULL1 OS_NONNULL2 362 void 363 image4_trust_set_booter( 364 image4_trust_t *trst, 365 const image4_trust_t *booter); 366 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_booter); 367 368 /*! 369 * @function image4_trust_set_result_buffer 370 * Provide a caller-owned buffer into which trust evaluation results will be 371 * written. This is useful for trust evaluations which may allocate memory for 372 * the result, such as {@link IMAGE4_TRUST_EVALUATION_NORMALIZE}. 373 * 374 * @param trst 375 * The trust object. 376 * 377 * @param p 378 * The caller-managed buffer. This parameter may be NULL, in which case the 379 * existing caller-managed buffer is cleared from the object. 380 * 381 * @param p_len 382 * The length of the buffer provided in {@link p}. 383 * 384 * @discussion 385 * The caller retains ownership of the buffer and is responsible for 386 * deallocating it when it is no longer needed. 387 * 388 * If this buffer is too small for the complete result, the trust evaluation 389 * callback will deliver E2BIG. 390 * 391 * @availability 392 * This function first became available in API version 20240503. 393 */ 394 IMAGE4_API_AVAILABLE_FALL_2024 395 OS_EXPORT OS_NONNULL1 OS_NONNULL2 396 void 397 image4_trust_set_result_buffer( 398 image4_trust_t *trst, 399 void *_Nullable __sized_by(p_len) p, 400 size_t p_len); 401 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_result_buffer); 402 403 /*! 404 * @function image4_trust_record_property_bool 405 * Records the specified Boolean value into caller-provided storage. 406 * 407 * @param trst 408 * The trust object. 409 * 410 * @param type 411 * The type of property to be recorded (currently either manifest or object). 412 * 413 * @param tag 414 * The four character code of the property to capture. 415 * 416 * @param vp 417 * A pointer to the storage where the value should be written. 418 * 419 * @param vpp 420 * A pointer to storage where a pointer to the value should be written. This 421 * allows the caller to know whether the property was encountered during the 422 * trust evaluation at all. If the property was encountered, the storage 423 * referred to by this pointer will hold the same pointer given in the 424 * {@link vp} parameter. 425 * 426 * If the property was not encountered during trust evaluation, the contents of 427 * this storage are undefined. The caller should initialize the storage to a 428 * reasonable default. 429 * 430 * This may be NULL. 431 * 432 * @discussion 433 * If the property represented a constraint which was not satisfied, the 434 * implementation will not record its value. 435 * 436 * If the property associated with the given tag is present, but is not a 437 * Boolean, the implementation will not record its value. 438 */ 439 IMAGE4_API_AVAILABLE_SPRING_2024 440 OS_EXPORT OS_NONNULL1 OS_NONNULL4 441 void 442 image4_trust_record_property_bool( 443 image4_trust_t *trst, 444 image4_trust_section_t type, 445 uint32_t tag, 446 bool *vp, 447 const bool *_Nullable *_Nullable vpp); 448 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_bool); 449 450 /*! 451 * @function image4_trust_record_property_integer 452 * Records the specified unsigned integer value into caller-provided storage. 453 * 454 * @param trst 455 * The trust object. 456 * 457 * @param type 458 * The type of property to be recorded (currently either manifest or object). 459 * 460 * @param tag 461 * The four character code of the property to capture. 462 * 463 * @param vp 464 * A pointer to the storage where the value should be written. 465 * 466 * @param vpp 467 * A pointer to storage where a pointer to the value should be written. This 468 * allows the caller to know whether the property was encountered during the 469 * trust evaluation at all. If the property was encountered, the storage 470 * referred to by this pointer will hold the same pointer given in the 471 * {@link vp} parameter. 472 * 473 * If the property was not encountered during trust evaluation, the contents of 474 * this storage are undefined. The caller should initialize the storage to a 475 * reasonable default. 476 * 477 * This may be NULL. 478 * 479 * @discussion 480 * For boring implementation reasons, all integer properties are expressed as 481 * 64-bit unsigned integers. The caller is responsible for enforcing boundaries 482 * on the value recorded. 483 * 484 * If the property represented a constraint which was not satisfied, the 485 * implementation will not record its value. 486 * 487 * If the property associated with the given tag is present, but is not an 488 * integer, the implementation will not record its value. 489 */ 490 IMAGE4_API_AVAILABLE_SPRING_2024 491 OS_EXPORT OS_NONNULL1 OS_NONNULL4 492 void 493 image4_trust_record_property_integer( 494 image4_trust_t *trst, 495 image4_trust_section_t type, 496 uint32_t tag, 497 uint64_t *vp, 498 const uint64_t *_Nullable *_Nullable vpp); 499 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_integer); 500 501 /*! 502 * @function image4_trust_record_property_data 503 * Records a pointer to the specified octet string value into caller-provided 504 * storage. 505 * 506 * @param trst 507 * The trust object. 508 * 509 * @param type 510 * The type of property to be recorded (currently either manifest or object). 511 * 512 * @param tag 513 * The four character code of the property to capture. 514 * 515 * @param vp 516 * A pointer to the storage where the value should be written. The storage 517 * referenced by this pointer ultimately refers to the caller-provided memory 518 * which contains the Image4 manifest, and therefore its lifetime is tied to the 519 * caller's management of that storage. 520 * 521 * If the property was not encountered during trust evaluation, the contents of 522 * this storage are undefined. The caller should initialize the storage to a 523 * reasonable default. 524 * 525 * @param vp_len 526 * A pointer to the storage where the length of the octet string should be 527 * written. 528 * 529 * @discussion 530 * If the property represented a constraint which was not satisfied, the 531 * implementation will not record its value. 532 * 533 * If the property associated with the given tag is present, but is not an octet 534 * string, the implementation will not record its value. 535 * 536 * Properties which are intended to be used as C strings are represented in the 537 * manifest as simple octet strings which may or may not be null-terminated. The 538 * caller should take care to ensure null termination when the data is used, 539 * e.g. by copying the data into a local buffer using strlcpy(3). 540 */ 541 IMAGE4_API_AVAILABLE_SPRING_2024 542 OS_EXPORT OS_NONNULL1 OS_NONNULL4 OS_NONNULL5 543 void 544 image4_trust_record_property_data( 545 image4_trust_t *trst, 546 image4_trust_section_t type, 547 uint32_t tag, 548 const void *_Nullable *_Nonnull vp, 549 size_t *vp_len); 550 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_data); 551 552 /*! 553 * @function image4_trust_evaluate 554 * Perform the trust evaluation. 555 * 556 * @param trst 557 * The trust object. 558 * 559 * @param _ctx 560 * A context parameter to be delivered to the result callback. 561 * 562 * @param result 563 * The callback to invoke with the result of the trust evaluation. This callback 564 * is called directly inline from the implementation and must not re-enter the 565 * calling scope. 566 */ 567 IMAGE4_API_AVAILABLE_SPRING_2024 568 OS_EXPORT OS_NONNULL1 OS_NONNULL3 569 void 570 image4_trust_evaluate( 571 const image4_trust_t *trst, 572 void *_Nullable _ctx, 573 image4_trust_evaluation_result_t result); 574 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_evaluate); 575 576 /*! 577 * @function image4_trust_destroy 578 * Disposes a trust object which was created via {@link image4_trust_new}. 579 * 580 * @param nv 581 * A pointer to the trust object. Upon return, this storage will be set to NULL. 582 * If the object pointed to by this parameter is NULL, this is a no-op. 583 * 584 * @discussion 585 * If this routine is called on an environment object which was not allocated, 586 * it is a no-op. 587 */ 588 IMAGE4_API_AVAILABLE_SPRING_2024 589 OS_EXPORT OS_NONNULL1 590 void 591 image4_trust_destroy( 592 image4_trust_t *_Nonnull *_Nullable trst); 593 IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_destroy); 594 595 OS_ASSUME_PTR_ABI_SINGLE_END 596 OS_ASSUME_NONNULL_END 597 __END_DECLS 598 599 #endif // __IMAGE4_API_TRUST_H 600