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