xref: /xnu-10063.121.3/EXTERNAL_HEADERS/image4/environment.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
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