1 /*! 2 * @header 3 * Encapsulation which describes an Image4 environment. The environment 4 * encompasses chip properties and trust evaluation policies, including digest 5 * algorithm selection and secure boot level enforcement. 6 */ 7 #ifndef __IMAGE4_API_ENVIRONMENT_H 8 #define __IMAGE4_API_ENVIRONMENT_H 9 10 #include <image4/image4.h> 11 #include <image4/types.h> 12 #include <image4/coprocessor.h> 13 #include <stdbool.h> 14 15 __BEGIN_DECLS 16 OS_ASSUME_NONNULL_BEGIN 17 OS_ASSUME_PTR_ABI_SINGLE_BEGIN 18 19 #pragma mark Forward Types 20 /*! 21 * @typedef image4_environment_storage_t 22 * The canonical type for environment storage. 23 */ 24 typedef struct _image4_environment_storage image4_environment_storage_t; 25 26 /*! 27 * @typedef image4_environment_query_boot_nonce_t 28 * A callback to provide the boot nonce for the environment. 29 * 30 * @param env 31 * The environment for which to retrieve the boot nonce. 32 * 33 * @param n 34 * Storage in which the callee should write the nonce upon successful return. 35 * 36 * @param n_len 37 * Storage in which the callee should write the nonce length upon successful 38 * return. 39 * 40 * On function entry, the content of this parameter is undefined. 41 * 42 * @param _ctx 43 * The context pointer which was provided during the environment's construction. 44 * 45 * @result 46 * The callee is expected to return zero on success. Otherwise, the callee may 47 * return one of the following POSIX error codes: 48 * 49 * [ENOTSUP] Obtaining the boot nonce is not supported; this will cause the 50 * implementation to act as if no callback was specified 51 * [ENOENT] The boot nonce does not exist 52 * [ENXIO] The boot nonce is not yet available for the environment, and 53 * the environment's bootstrap nonce (if any) should be used for 54 * anti-replay instead 55 * 56 * @discussion 57 * This callback is utilized by exec, sign, and boot trust evaluations. 58 */ 59 typedef errno_t (*image4_environment_query_boot_nonce_t)( 60 const image4_environment_t *env, 61 uint8_t n[__static_size _Nonnull IMAGE4_NONCE_MAX_LEN], 62 size_t *n_len, 63 void *_ctx 64 ); 65 66 /*! 67 * @typedef image4_environment_query_nonce_digest_t 68 * A callback to provide a nonce digest for use during preflight trust 69 * evaluations. 70 * 71 * @param env 72 * The environment for which to retrieve the boot nonce. 73 * 74 * @param nd 75 * Storage in which the callee should write the nonce digest upon successful 76 * return. 77 * 78 * @param nd_len 79 * Storage in which the callee should write the nonce digest length upon 80 * successful return. 81 * 82 * On function entry, the content of this parameter is undefined. 83 * 84 * @param _ctx 85 * The context pointer which was provided during the environment's construction. 86 * 87 * @result 88 * The callee is expected to return zero on success. Otherwise, the callee may 89 * return one of the following POSIX error codes: 90 * 91 * [ENOTSUP] Obtaining the nonce digest is not supported; this will cause 92 * the implementation to act as if no callback was specified 93 * [ENOENT] The nonce digest does not exist 94 * 95 * @discussion 96 * This callback is utilized by preflight, sign, and boot trust evaluations. In 97 * sign and trust trust evaluations, it is only called if the nonce itself 98 * cannot be obtained from either the environment internally or the boot nonce 99 * callback. 100 */ 101 typedef errno_t (*image4_environment_query_nonce_digest_t)( 102 const image4_environment_t *env, 103 uint8_t nd[__static_size _Nonnull IMAGE4_NONCE_DIGEST_MAX_LEN], 104 size_t *nd_len, 105 void *_ctx 106 ); 107 108 /*! 109 * @typedef image4_environment_identifier_bool_t 110 * A callback which conveys the value of a Boolean identifier associated with 111 * the environment during an identification. 112 * 113 * @param nv 114 * The environment which is being identified. 115 * 116 * @param id4 117 * The Boolean identifier. 118 * 119 * @param val 120 * The value of the identifier. 121 * 122 * @param _ctx 123 * The context pointer which was provided during the environment's construction. 124 */ 125 typedef void (*image4_environment_identifier_bool_t)( 126 const image4_environment_t *nv, 127 const image4_identifier_t *id4, 128 bool val, 129 void *_ctx 130 ); 131 132 /*! 133 * @typedef image4_environment_identifier_integer_t 134 * A callback which conveys the value of an unsigned 64-bit integer identifier 135 * associated with the environment during an identification. 136 * 137 * @param nv 138 * The environment which is being identified. 139 * 140 * @param id4 141 * The integer identifier. 142 * 143 * @param val 144 * The value of the identifier. 145 * 146 * @param _ctx 147 * The context pointer which was provided during the environment's construction. 148 */ 149 typedef void (*image4_environment_identifier_integer_t)( 150 const image4_environment_t *nv, 151 const image4_identifier_t *id4, 152 uint64_t val, 153 void *_ctx 154 ); 155 156 /*! 157 * @typedef image4_environment_identifier_data_t 158 * A callback which conveys the value of an octet string identifier associated 159 * with the environment during an identification. 160 * 161 * @param nv 162 * The environment which is being identified. 163 * 164 * @param id4 165 * The octet string identifier. 166 * 167 * @param vp 168 * A pointer to the octet string bytes. 169 * 170 * @param vp_len 171 * The length of the octet string indicated by {@link vp}. 172 * 173 * @param _ctx 174 * The context pointer which was provided during the environment's construction. 175 */ 176 typedef void (*image4_environment_identifier_data_t)( 177 const image4_environment_t *nv, 178 const image4_identifier_t *id4, 179 const void *vp, 180 size_t vp_len, 181 void *_ctx 182 ); 183 184 /*! 185 * @const IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION 186 * The version of the {@link image4_environment_callbacks_t} structure supported 187 * by the implementation. 188 */ 189 #define IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION (0u) 190 191 /*! 192 * @struct image4_environment_callbacks_t 193 * A callback structure which may be given to influence the behavior of an 194 * {@link image4_environment_t}. 195 * 196 * @field nvcb_version 197 * The version of the structure. Initialize to 198 * {@link IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION}. 199 * 200 * @field nvcb_query_boot_nonce 201 * The callback to query the boot nonce. 202 * 203 * @field nvcb_query_nonce_digest 204 * The callback to query a nonce digest. 205 * 206 * @field nvcb_construct_boot 207 * The callback to construct the boot sequence for the environment. 208 * 209 * @field nvcb_identifier_bool 210 * The callback to convey a Boolean identifier in the environment. 211 * 212 * @field nvcb_identifier_integer 213 * The callback to convey an integer identifier in the environment. 214 * 215 * @field nvcb_identifier_data 216 * The callback to convey an octet string identifier in the environment. 217 */ 218 typedef struct _image4_environment_callbacks { 219 image4_struct_version_t nvcb_version; 220 image4_environment_query_boot_nonce_t _Nullable nvcb_query_boot_nonce; 221 image4_environment_query_nonce_digest_t _Nullable nvcb_query_nonce_digest; 222 image4_environment_identifier_bool_t _Nullable nvcb_identifier_bool; 223 image4_environment_identifier_integer_t _Nullable nvcb_identifier_integer; 224 image4_environment_identifier_data_t _Nullable nvcb_identifier_data; 225 } image4_environment_callbacks_t; 226 227 /*! 228 * @const IMAGE4_ENVIRONMENT_STRUCT_VERSION 229 * The version of the {@link image4_environment_t} structure supported by the 230 * implementation. 231 */ 232 #define IMAGE4_ENVIRONMENT_STRUCT_VERSION (0u) 233 234 /*! 235 * @struct image4_environment_storage_t 236 * An opaque structure which is guaranteed to be large enough to accommodate an 237 * {@link image4_environment_t}. 238 * 239 * @field __opaque 240 * The opaque storage. 241 */ 242 struct _image4_environment_storage { 243 uint8_t __opaque[256]; 244 }; 245 246 /*! 247 * @const IMAGE4_TRUST_STORAGE_INIT 248 * Initializer for a {@link image4_environment_storage_t} object. 249 */ 250 #define IMAGE4_ENVIRONMENT_STORAGE_INIT (image4_environment_storage_t){ \ 251 .__opaque = { 0x00 }, \ 252 } 253 254 #pragma mark API 255 /*! 256 * @function image4_environment_init 257 * Initializes an environment in which to perform a trust evaluation. 258 * 259 * @param storage 260 * The storage structure. 261 * 262 * @param coproc 263 * The coprocessor which will perform the evaluation. If NULL, 264 * {@link IMAGE4_COPROCESSOR_HOST} will be assumed. 265 * 266 * @param handle 267 * The specific environment and policy within the coprocessor to use for 268 * performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this 269 * parameter is ignored. 270 * 271 * @result 272 * An initialized {@link image4_environment_t} object. 273 */ 274 IMAGE4_API_AVAILABLE_SPRING_2024 275 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 276 image4_environment_t * 277 _image4_environment_init( 278 image4_environment_storage_t *storage, 279 const image4_coprocessor_t *_Nullable coproc, 280 image4_coprocessor_handle_t handle, 281 image4_struct_version_t v); 282 #define image4_environment_init(_storage, _coproc, _handle) \ 283 _image4_environment_init( \ 284 (_storage), \ 285 (_coproc), \ 286 (_handle), \ 287 IMAGE4_ENVIRONMENT_STRUCT_VERSION) 288 IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_environment_init); 289 290 /*! 291 * @function image4_environment_new 292 * Allocates an environment in which to perform a trust evaluation. 293 * 294 * @param coproc 295 * The coprocessor which will perform the evaluation. If NULL, 296 * {@link IMAGE4_COPROCESSOR_HOST} will be assumed. 297 * 298 * @param handle 299 * The specific environment and policy within the coprocessor to use for 300 * performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this 301 * parameter is ignored. 302 * 303 * @result 304 * A newly-allocated and initialized {@link image4_environment_t} object. The 305 * caller is responsible for disposing of this object with 306 * {@link image4_environment_destroy} when it is no longer needed. 307 * 308 * If insufficient resources were available to allocate the object, or if the 309 * host runtime does not have an allocator, NULL is returned. 310 */ 311 IMAGE4_API_AVAILABLE_SPRING_2024 312 OS_EXPORT OS_WARN_RESULT 313 image4_environment_t *_Nullable 314 image4_environment_new( 315 const image4_coprocessor_t *_Nullable coproc, 316 image4_coprocessor_handle_t handle); 317 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_new); 318 319 /*! 320 * @function image4_environment_set_secure_boot 321 * Sets the desired secure boot level of the environment. 322 * 323 * @param nv 324 * The environment to manipulate. 325 * 326 * @param secure_boot 327 * The desired secure boot level. 328 * 329 * @discussion 330 * If the environment designated by the coprocessor and handle does not support 331 * secure boot, this is a no-op. 332 */ 333 IMAGE4_API_AVAILABLE_SPRING_2024 334 OS_EXPORT OS_NONNULL1 335 void 336 image4_environment_set_secure_boot( 337 image4_environment_t *nv, 338 image4_secure_boot_t secure_boot); 339 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_secure_boot); 340 341 /*! 342 * @function image4_environment_set_nonce_domain 343 * Sets the nonce domain number for the environment. This value will be returned 344 * as the value for the coprocessor's nonce domain property during environment 345 * iteration (e.g. if the environment is a Cryptex1 coprocessor handle, the ndom 346 * property). 347 * 348 * @param nv 349 * The environment to modify. 350 * 351 * @param nonce_domain 352 * The nonce domain number to set. 353 * 354 * @discussion 355 * This operation does not impact trust evaluation, which always defers to the 356 * nonce domain signed into the manifest if one is present. It is intended to 357 * support two workflows: 358 * 359 * 1. Constructing a personalization request using the callbacks associated 360 * with {@link image4_environment_identify} by allowing all the code that 361 * sets the values of the TSS request to reside in the identifier 362 * callbacks 363 * 2. Related to the above, performing nonce management operations on the 364 * nonce slot associated by the given domain (e.g. generating a proposal 365 * nonce with {@link image4_environment_generate_nonce_proposal}) 366 * 367 * Certain coprocessor environments recognize a nonce domain entitlement, but 368 * only one valid value for that entitlement (e.g. 369 * {@link IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT}). These environments do not 370 * require the nonce domain to be set; it is automatically recognized based on 371 * the static properties of the coprocessor. 372 */ 373 IMAGE4_API_AVAILABLE_SPRING_2024 374 OS_EXPORT OS_NONNULL1 375 void 376 image4_environment_set_nonce_domain( 377 image4_environment_t *nv, 378 uint32_t nonce_domain); 379 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_nonce_domain); 380 381 /*! 382 * @function image4_environment_set_callbacks 383 * Sets the callbacks for an environment. 384 * 385 * @param nv 386 * The environment to manipulate. 387 * 388 * @param callbacks 389 * The callback structure. 390 * 391 * @param _ctx 392 * The caller-defined context to be passed to each callback. 393 */ 394 IMAGE4_API_AVAILABLE_SPRING_2024 395 OS_EXPORT OS_NONNULL1 OS_NONNULL2 396 void 397 image4_environment_set_callbacks( 398 image4_environment_t *nv, 399 const image4_environment_callbacks_t *callbacks, 400 void *_Nullable _ctx); 401 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_callbacks); 402 403 /*! 404 * @function image4_environment_identify 405 * Identifies the environment and provides the identity via the callbacks 406 * specified in the {@link image4_environment_callbacks_t} structure set for 407 * the environment. 408 * 409 * @param nv 410 * The environment to identify. 411 * 412 * @discussion 413 * If no callbacks were provided, or if no identifier callbacks were set in the 414 * callback structure, the implementation's behavior is undefined. 415 */ 416 IMAGE4_API_AVAILABLE_SPRING_2024 417 OS_EXPORT OS_NONNULL1 418 void 419 image4_environment_identify( 420 const image4_environment_t *nv); 421 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_identify); 422 423 /*! 424 * @function image4_environment_copy_nonce_digest 425 * Copies the digest of the specified nonce. 426 * 427 * @param nv 428 * The environment to query. 429 * 430 * @param digest 431 * Upon successful return, the digest of the live nonce for the environment. On 432 * failure, the contents of this structure are undefined. 433 * 434 * @result 435 * Upon success, zero is returned. Otherwise, the implementation may directly 436 * return one of the following POSIX error codes: 437 * 438 * [EPERM] The caller lacks the entitlement required to access the 439 * desired nonce 440 * [ENOTSUP] The environment does not manage a nonce for anti-replay 441 * [ESTALE] The nonce has been invalidated and will not be available until 442 * the next boot 443 */ 444 IMAGE4_API_AVAILABLE_SPRING_2024 445 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 446 errno_t 447 image4_environment_copy_nonce_digest( 448 const image4_environment_t *nv, 449 image4_nonce_digest_t *digest); 450 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_copy_nonce_digest); 451 452 /*! 453 * @function image4_environment_roll_nonce 454 * Invalidates the live nonce for the environment such that a new nonce will be 455 * generated at the next boot. 456 * 457 * @param nv 458 * The environment to manipulate. 459 * 460 * @result 461 * Upon success, zero is returned. Otherwise, the implementation may directly 462 * return one of the following POSIX error codes: 463 * 464 * [EPERM] The caller lacks the entitlement required to access the 465 * desired nonce 466 * [ENOTSUP] The environment does not manage a nonce for anti-replay 467 */ 468 IMAGE4_API_AVAILABLE_SPRING_2024 469 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 470 errno_t 471 image4_environment_roll_nonce( 472 const image4_environment_t *nv); 473 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_roll_nonce); 474 475 /*! 476 * @function image4_environment_generate_nonce_proposal 477 * Generates a nonce proposal for the environment and returns the hash of the 478 * proposal. 479 * 480 * @param nv 481 * The environment to manipulate. 482 * 483 * @param digest 484 * Upon successful return, the digest of the nonce proposal which was generated. 485 * On failure, the contents of this structure are undefined. 486 * 487 * @result 488 * Upon success, zero is returned. Otherwise, the implementation may directly 489 * return one of the following POSIX error codes: 490 * 491 * [EPERM] The caller lacks the entitlement required to manipulate the 492 * desired nonce 493 * [ENOTSUP] The environment does not manage a nonce for anti-replay 494 */ 495 IMAGE4_API_AVAILABLE_SPRING_2024 496 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 497 errno_t 498 image4_environment_generate_nonce_proposal( 499 const image4_environment_t *nv, 500 image4_nonce_digest_t *digest); 501 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_generate_nonce_proposal); 502 503 /*! 504 * @function image4_environment_commit_nonce_proposal 505 * Commits the nonce proposal corresponding to the digest provided by the caller 506 * such that it will be accepted and live at the next boot. 507 * 508 * @param nv 509 * The environment to manipulate. 510 * 511 * @param digest 512 * The digest of the proposal to commit. 513 * 514 * @result 515 * Upon success, zero is returned. Otherwise, the implementation may directly 516 * return one of the following POSIX error codes: 517 * 518 * [EPERM] The caller lacks the entitlement required to manipulate the 519 * desired nonce 520 * [ENOTSUP] The environment does not manage a nonce for anti-replay 521 * [ENODEV] There is no proposal for the given nonce 522 * [EILSEQ] The digest provided by the caller does not correspond to the 523 * active proposal; this may occur if another subsystem 524 * generates a proposal for the environment 525 */ 526 IMAGE4_API_AVAILABLE_SPRING_2024 527 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 528 errno_t 529 image4_environment_commit_nonce_proposal( 530 const image4_environment_t *nv, 531 const image4_nonce_digest_t *digest); 532 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_commit_nonce_proposal); 533 534 /*! 535 * @function image4_environment_get_nonce_handle 536 * Obtains the appropriate nonce handle to include in a signing request for the 537 * environment. 538 * 539 * @param nv 540 * The environment to query. 541 * 542 * @param handle 543 * Upon successful return, the handle appropriate for the signing request's 544 * nonce domain field. On failure, this parameter's value is undefined. 545 * 546 * @result 547 * Upon success, zero is returned. Otherwise, the implementation may directly 548 * return one of the following POSIX error codes: 549 * 550 * [ENOTSUP] The environment does not manage a nonce for anti-replay 551 * [ENOENT] The environment does not support identifing a nonce by its 552 * handle in the personalization request 553 * 554 * @discussion 555 * This function is not implemented and will be removed. See discussion in 556 * {@link image4_environment_set_nonce_handle} for guidance as to how to 557 * implement the relevant workflows. 558 */ 559 IMAGE4_API_AVAILABLE_SPRING_2024 560 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 561 errno_t 562 image4_environment_get_nonce_handle( 563 const image4_environment_t *nv, 564 uint64_t *handle); 565 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_get_nonce_handle); 566 567 /*! 568 * @function image4_environment_destroy 569 * Disposes an environment object which was created via 570 * {@link image4_environment_new}. 571 * 572 * @param nv 573 * A pointer to the environment object. Upon return, this storage will be set to 574 * NULL. If the object pointed to by this parameter is NULL, this is a no-op. 575 * 576 * @discussion 577 * If this routine is called on an environment object which was not allocated, 578 * it is a no-op. 579 */ 580 IMAGE4_API_AVAILABLE_SPRING_2024 581 OS_EXPORT OS_NONNULL1 582 void 583 image4_environment_destroy( 584 image4_environment_t *_Nonnull *_Nullable nv); 585 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_destroy); 586 587 OS_ASSUME_PTR_ABI_SINGLE_END 588 OS_ASSUME_NONNULL_END 589 __END_DECLS 590 591 #endif // __IMAGE4_API_ENVIRONMENT_H 592