xref: /xnu-11215.41.3/EXTERNAL_HEADERS/image4/environment.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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 environment. The environment
31  * encompasses chip properties and trust evaluation policies, including digest
32  * algorithm selection and secure boot level enforcement.
33  */
34 #ifndef __IMAGE4_API_ENVIRONMENT_H
35 #define __IMAGE4_API_ENVIRONMENT_H
36 
37 #include <image4/image4.h>
38 #include <image4/types.h>
39 #include <image4/coprocessor.h>
40 #include <stdbool.h>
41 
42 __BEGIN_DECLS
43 OS_ASSUME_NONNULL_BEGIN
44 OS_ASSUME_PTR_ABI_SINGLE_BEGIN
45 
46 #pragma mark Forward Types
47 /*!
48  * @typedef image4_environment_storage_t
49  * The canonical type for environment storage.
50  */
51 typedef struct _image4_environment_storage image4_environment_storage_t;
52 
53 /*!
54  * @typedef image4_environment_query_boot_nonce_t
55  * A callback to provide the boot nonce for the environment.
56  *
57  * @param nv
58  * The environment for which to retrieve the boot nonce.
59  *
60  * @param n
61  * Storage in which the callee should write the nonce upon successful return.
62  *
63  * @param n_len
64  * Storage in which the callee should write the nonce length upon successful
65  * return.
66  *
67  * On function entry, the content of this parameter is undefined.
68  *
69  * @param _ctx
70  * The context pointer which was provided during the environment's construction.
71  *
72  * @result
73  * The callee is expected to return zero on success. Otherwise, the callee may
74  * return one of the following POSIX error codes:
75  *
76  *     [ENOTSUP]  Obtaining the boot nonce is not supported; this will cause the
77  *                implementation to act as if no callback was specified
78  *     [ENOENT]   The boot nonce does not exist
79  *     [ENXIO]    The boot nonce is not yet available for the environment, and
80  *                the environment's bootstrap nonce (if any) should be used for
81  *                anti-replay instead
82  *
83  * @discussion
84  * This callback is utilized by exec, sign, and boot trust evaluations.
85  */
86 typedef errno_t (*image4_environment_query_boot_nonce_t)(
87 	const image4_environment_t *nv,
88 	uint8_t n[__static_size _Nonnull IMAGE4_NONCE_MAX_LEN],
89 	size_t *n_len,
90 	void *_ctx
91 );
92 
93 /*!
94  * @typedef image4_environment_query_nonce_digest_t
95  * A callback to provide a nonce digest for use during preflight trust
96  * evaluations.
97  *
98  * @param nv
99  * The environment for which to retrieve the boot nonce.
100  *
101  * @param nd
102  * Storage in which the callee should write the nonce digest upon successful
103  * return.
104  *
105  * @param nd_len
106  * Storage in which the callee should write the nonce digest length upon
107  * successful return.
108  *
109  * On function entry, the content of this parameter is undefined.
110  *
111  * @param _ctx
112  * The context pointer which was provided during the environment's construction.
113  *
114  * @result
115  * The callee is expected to return zero on success. Otherwise, the callee may
116  * return one of the following POSIX error codes:
117  *
118  *     [ENOTSUP]  Obtaining the nonce digest is not supported; this will cause
119  *                the implementation to act as if no callback was specified
120  *     [ENOENT]   The nonce digest does not exist
121  *
122  * @discussion
123  * This callback is utilized by preflight, sign, and boot trust evaluations. In
124  * sign and trust trust evaluations, it is only called if the nonce itself
125  * cannot be obtained from either the environment internally or the boot nonce
126  * callback.
127  */
128 typedef errno_t (*image4_environment_query_nonce_digest_t)(
129 	const image4_environment_t *nv,
130 	uint8_t nd[__static_size _Nonnull IMAGE4_DIGEST_MAX_LEN],
131 	size_t *nd_len,
132 	void *_ctx
133 );
134 
135 /*!
136  * @typedef image4_environment_identifier_bool_t
137  * A callback which conveys the value of a Boolean identifier associated with
138  * the environment during an identification.
139  *
140  * @param nv
141  * The environment which is being identified.
142  *
143  * @param id4
144  * The Boolean identifier.
145  *
146  * @param val
147  * The value of the identifier.
148  *
149  * @param _ctx
150  * The context pointer which was provided during the environment's construction.
151  */
152 typedef void (*image4_environment_identifier_bool_t)(
153 	const image4_environment_t *nv,
154 	const image4_identifier_t *id4,
155 	bool val,
156 	void *_ctx
157 );
158 
159 /*!
160  * @typedef image4_environment_identifier_integer_t
161  * A callback which conveys the value of an unsigned 64-bit integer identifier
162  * associated with the environment during an identification.
163  *
164  * @param nv
165  * The environment which is being identified.
166  *
167  * @param id4
168  * The integer identifier.
169  *
170  * @param val
171  * The value of the identifier.
172  *
173  * @param _ctx
174  * The context pointer which was provided during the environment's construction.
175  */
176 typedef void (*image4_environment_identifier_integer_t)(
177 	const image4_environment_t *nv,
178 	const image4_identifier_t *id4,
179 	uint64_t val,
180 	void *_ctx
181 );
182 
183 /*!
184  * @typedef image4_environment_identifier_data_t
185  * A callback which conveys the value of an octet string identifier associated
186  * with the environment during an identification.
187  *
188  * @param nv
189  * The environment which is being identified.
190  *
191  * @param id4
192  * The octet string identifier.
193  *
194  * @param vp
195  * A pointer to the octet string bytes.
196  *
197  * @param vp_len
198  * The length of the octet string indicated by {@link vp}.
199  *
200  * @param _ctx
201  * The context pointer which was provided during the environment's construction.
202  */
203 typedef void (*image4_environment_identifier_data_t)(
204 	const image4_environment_t *nv,
205 	const image4_identifier_t *id4,
206 	const void *vp,
207 	size_t vp_len,
208 	void *_ctx
209 );
210 
211 /*!
212  * @const IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION
213  * The version of the {@link image4_environment_callbacks_t} structure supported
214  * by the implementation.
215  */
216 #define IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION (0u)
217 
218 /*!
219  * @struct image4_environment_callbacks_t
220  * A callback structure which may be given to influence the behavior of an
221  * {@link image4_environment_t}.
222  *
223  * @field nvcb_version
224  * The version of the structure. Initialize to
225  * {@link IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION}.
226  *
227  * @field nvcb_query_boot_nonce
228  * The callback to query the boot nonce.
229  *
230  * @field nvcb_query_nonce_digest
231  * The callback to query a nonce digest.
232  *
233  * @field nvcb_construct_boot
234  * The callback to construct the boot sequence for the environment.
235  *
236  * @field nvcb_identifier_bool
237  * The callback to convey a Boolean identifier in the environment.
238  *
239  * @field nvcb_identifier_integer
240  * The callback to convey an integer identifier in the environment.
241  *
242  * @field nvcb_identifier_data
243  * The callback to convey an octet string identifier in the environment.
244  */
245 typedef struct _image4_environment_callbacks {
246 	image4_struct_version_t nvcb_version;
247 	image4_environment_query_boot_nonce_t _Nullable nvcb_query_boot_nonce;
248 	image4_environment_query_nonce_digest_t _Nullable nvcb_query_nonce_digest;
249 	image4_environment_identifier_bool_t _Nullable nvcb_identifier_bool;
250 	image4_environment_identifier_integer_t _Nullable nvcb_identifier_integer;
251 	image4_environment_identifier_data_t _Nullable nvcb_identifier_data;
252 } image4_environment_callbacks_t;
253 
254 /*!
255  * @const IMAGE4_ENVIRONMENT_STRUCT_VERSION
256  * The version of the {@link image4_environment_t} structure supported by the
257  * implementation.
258  */
259 #define IMAGE4_ENVIRONMENT_STRUCT_VERSION (0u)
260 
261 /*!
262  * @struct image4_environment_storage_t
263  * An opaque structure which is guaranteed to be large enough to accommodate an
264  * {@link image4_environment_t}.
265  *
266  * @field __opaque
267  * The opaque storage.
268  */
269 struct _image4_environment_storage {
270 	uint8_t __opaque[256];
271 };
272 
273 /*!
274  * @const IMAGE4_TRUST_STORAGE_INIT
275  * Initializer for a {@link image4_environment_storage_t} object.
276  */
277 #define IMAGE4_ENVIRONMENT_STORAGE_INIT (image4_environment_storage_t){ \
278 	.__opaque = { 0x00 }, \
279 }
280 
281 #pragma mark API
282 /*!
283  * @function image4_environment_init
284  * Initializes an environment in which to perform a trust evaluation.
285  *
286  * @param storage
287  * The storage structure.
288  *
289  * @param coproc
290  * The coprocessor which will perform the evaluation. If NULL,
291  * {@link IMAGE4_COPROCESSOR_HOST} will be assumed.
292  *
293  * @param handle
294  * The specific environment and policy within the coprocessor to use for
295  * performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this
296  * parameter is ignored.
297  *
298  * @result
299  * An initialized {@link image4_environment_t} object.
300  */
301 IMAGE4_API_AVAILABLE_SPRING_2024
302 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
303 image4_environment_t *
304 _image4_environment_init(
305 	image4_environment_storage_t *storage,
306 	const image4_coprocessor_t *_Nullable coproc,
307 	image4_coprocessor_handle_t handle,
308 	image4_struct_version_t v);
309 #define image4_environment_init(_storage, _coproc, _handle) \
310 	_image4_environment_init( \
311 		(_storage), \
312 		(_coproc), \
313 		(_handle), \
314 		IMAGE4_ENVIRONMENT_STRUCT_VERSION)
315 IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_environment_init);
316 
317 /*!
318  * @function image4_environment_init_coproc
319  * A less-verbose form of {@link image4_environment_init}.
320  *
321  * @param _storage
322  * The storage structure.
323  *
324  * @param _coproc_short
325  * The shortened form of the coprocessor name, e.g. `AP` for
326  * `IMAGE4_COPROCESSOR_AP`.
327  *
328  * @param _handle_short
329  * The shortened form of the coprocessor handle name, e.g. `FF00` for
330  * `IMAGE4_COPROCESSOR_AP_FF00`.
331  *
332  * @result
333  * An initialized {@link image4_environment_t} object.
334  *
335  * @example
336  * The following two code snippets are equivalent.
337  *
338  *     nv = image4_environment_init(
339  *             &s,
340  *             IMAGE4_COPROCESSOR_CRYPTEX1,
341  *             IMAGE4_COPROCESSOR_CRYPTEX1_BOOT);
342  * and
343  *
344  *     nv = image4_environment_init_coproc(&s, CRYPTEX1, BOOT);
345  */
346 #define image4_environment_init_coproc(_storage, _coproc_short, _handle_short) \
347 	image4_environment_init( \
348 		(_storage), \
349 		IMAGE4_COPROCESSOR_ ## _coproc_short, \
350 		IMAGE4_COPROCESSOR_HANDLE_ ## _coproc_short ## _ ## _handle_short)
351 
352 /*!
353  * @function image4_environment_new
354  * Allocates an environment in which to perform a trust evaluation.
355  *
356  * @param coproc
357  * The coprocessor which will perform the evaluation. If NULL,
358  * {@link IMAGE4_COPROCESSOR_HOST} will be assumed.
359  *
360  * @param handle
361  * The specific environment and policy within the coprocessor to use for
362  * performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this
363  * parameter is ignored.
364  *
365  * @result
366  * A newly-allocated and initialized {@link image4_environment_t} object. The
367  * caller is responsible for disposing of this object with
368  * {@link image4_environment_destroy} when it is no longer needed.
369  *
370  * If insufficient resources were available to allocate the object, or if the
371  * host runtime does not have an allocator, NULL is returned.
372  */
373 IMAGE4_API_AVAILABLE_SPRING_2024
374 OS_EXPORT OS_WARN_RESULT
375 image4_environment_t *_Nullable
376 image4_environment_new(
377 	const image4_coprocessor_t *_Nullable coproc,
378 	image4_coprocessor_handle_t handle);
379 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_new);
380 
381 /*!
382  * @function image4_environment_new_coproc
383  * A less-verbose form of {@link image4_environment_new}.
384  *
385  * @param _coproc_short
386  * The shortened form of the coprocessor name, e.g. `AP` for
387  * `IMAGE4_COPROCESSOR_AP`.
388  *
389  * @param _handle_short
390  * The shortened form of the coprocessor handle name, e.g. `FF00` for
391  * `IMAGE4_COPROCESSOR_AP_FF00`.
392  *
393  * @result
394  * A newly-allocated and initialized {@link image4_environment_t} object. The
395  * caller is responsible for disposing of this object with
396  * {@link image4_environment_destroy} when it is no longer needed.
397  *
398  * If insufficient resources were available to allocate the object, or if the
399  * host runtime does not have an allocator, NULL is returned.
400  *
401  * @example
402  * The following two code snippets are equivalent.
403  *
404  *     nv = image4_environment_new(
405  *             IMAGE4_COPROCESSOR_CRYPTEX1,
406  *             IMAGE4_COPROCESSOR_CRYPTEX1_BOOT);
407  * and
408  *
409  *     nv = image4_environment_new_coproc(CRYPTEX1, BOOT);
410  */
411 #define image4_environment_new_coproc(_coproc_short, _handle_short) \
412 	image4_environment_new( \
413 		IMAGE4_COPROCESSOR_ ## _coproc_short, \
414 		IMAGE4_COPROCESSOR_HANDLE_ ## _coproc_short ## _ ## _handle_short)
415 
416 /*!
417  * @function image4_environment_set_secure_boot
418  * Sets the desired secure boot level of the environment.
419  *
420  * @param nv
421  * The environment to manipulate.
422  *
423  * @param secure_boot
424  * The desired secure boot level.
425  *
426  * @discussion
427  * If the environment designated by the coprocessor and handle does not support
428  * secure boot, this is a no-op.
429  */
430 IMAGE4_API_AVAILABLE_SPRING_2024
431 OS_EXPORT OS_NONNULL1
432 void
433 image4_environment_set_secure_boot(
434 	image4_environment_t *nv,
435 	image4_secure_boot_t secure_boot);
436 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_secure_boot);
437 
438 /*!
439  * @function image4_environment_set_nonce_domain
440  * Sets the nonce domain number for the environment. This value will be returned
441  * as the value for the coprocessor's nonce domain property during environment
442  * iteration (e.g. if the environment is a Cryptex1 coprocessor handle, the ndom
443  * property).
444  *
445  * @param nv
446  * The environment to modify.
447  *
448  * @param nonce_domain
449  * The nonce domain number to set.
450  *
451  * @discussion
452  * This operation does not impact trust evaluation, which always defers to the
453  * nonce domain signed into the manifest if one is present. It is intended to
454  * support two workflows:
455  *
456  *     1. Constructing a personalization request using the callbacks associated
457  *        with {@link image4_environment_identify} by allowing all the code that
458  *        sets the values of the TSS request to reside in the identifier
459  *        callbacks
460  *     2. Related to the above, performing nonce management operations on the
461  *        nonce slot associated by the given domain (e.g. generating a proposal
462  *        nonce with {@link image4_environment_generate_nonce_proposal})
463  *
464  * Certain coprocessor environments recognize a nonce domain entitlement, but
465  * only one valid value for that entitlement (e.g.
466  * {@link IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT}). These environments do not
467  * require the nonce domain to be set; it is automatically recognized based on
468  * the static properties of the coprocessor.
469  */
470 IMAGE4_API_AVAILABLE_SPRING_2024
471 OS_EXPORT OS_NONNULL1
472 void
473 image4_environment_set_nonce_domain(
474 	image4_environment_t *nv,
475 	uint32_t nonce_domain);
476 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_nonce_domain);
477 
478 /*!
479  * @function image4_environment_set_callbacks
480  * Sets the callbacks for an environment.
481  *
482  * @param nv
483  * The environment to manipulate.
484  *
485  * @param callbacks
486  * The callback structure.
487  *
488  * @param _ctx
489  * The caller-defined context to be passed to each callback.
490  */
491 IMAGE4_API_AVAILABLE_SPRING_2024
492 OS_EXPORT OS_NONNULL1 OS_NONNULL2
493 void
494 image4_environment_set_callbacks(
495 	image4_environment_t *nv,
496 	const image4_environment_callbacks_t *callbacks,
497 	void *_Nullable _ctx);
498 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_callbacks);
499 
500 /*!
501  * @function image4_environment_identify
502  * Identifies the environment and provides the identity via the callbacks
503  * specified in the {@link image4_environment_callbacks_t} structure set for
504  * the environment.
505  *
506  * @param nv
507  * The environment to identify.
508  *
509  * @discussion
510  * If no callbacks were provided, or if no identifier callbacks were set in the
511  * callback structure, the implementation's behavior is undefined.
512  */
513 IMAGE4_API_AVAILABLE_SPRING_2024
514 OS_EXPORT OS_NONNULL1
515 void
516 image4_environment_identify(
517 	const image4_environment_t *nv);
518 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_identify);
519 
520 /*!
521  * @function image4_environment_get_digest_info
522  * Retrieves the CoreCrypto digest info structure which the environment uses to
523  * compute digests.
524  *
525  * @param nv
526  * The environment to query.
527  *
528  * @result
529  * A pointer to the CoreCrypto digest info structure corresponding to the
530  * environment.
531  *
532  * @availability
533  * This function first became available in API version 20231215.
534  */
535 IMAGE4_API_AVAILABLE_FALL_2024
536 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
537 const struct ccdigest_info *
538 image4_environment_get_digest_info(
539 		const image4_environment_t *nv);
540 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_get_digest_info);
541 
542 /*!
543  * @function image4_environment_copy_nonce_digest
544  * Copies the digest of the specified nonce.
545  *
546  * @param nv
547  * The environment to query.
548  *
549  * @param d
550  * Upon successful return, the digest of the live nonce for the environment. On
551  * failure, the contents of this structure are undefined.
552  *
553  * @param d_len
554  * Upon successful return, the length of the nonce digest.
555  *
556  * @result
557  * Upon success, zero is returned. Otherwise, the implementation may directly
558  * return one of the following POSIX error codes:
559  *
560  *     [EPERM]    The caller lacks the entitlement required to access the
561  *                desired nonce
562  *     [ENOTSUP]  The environment does not manage a nonce for anti-replay
563  *     [ESTALE]   The nonce has been invalidated and will not be available until
564  *                the next boot
565  */
566 IMAGE4_API_AVAILABLE_SPRING_2024
567 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3
568 errno_t
569 image4_environment_copy_nonce_digest(
570 	const image4_environment_t *nv,
571 	uint8_t d[__static_size _Nonnull IMAGE4_DIGEST_MAX_LEN],
572 	size_t *d_len);
573 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_copy_nonce_digest);
574 
575 /*!
576  * @function image4_environment_roll_nonce
577  * Invalidates the live nonce for the environment such that a new nonce will be
578  * generated at the next boot.
579  *
580  * @param nv
581  * The environment to manipulate.
582  *
583  * @result
584  * Upon success, zero is returned. Otherwise, the implementation may directly
585  * return one of the following POSIX error codes:
586  *
587  *     [EPERM]    The caller lacks the entitlement required to access the
588  *                desired nonce
589  *     [ENOTSUP]  The environment does not manage a nonce for anti-replay
590  */
591 IMAGE4_API_AVAILABLE_SPRING_2024
592 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
593 errno_t
594 image4_environment_roll_nonce(
595 	const image4_environment_t *nv);
596 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_roll_nonce);
597 
598 /*!
599  * @function image4_environment_generate_nonce_proposal
600  * Generates a nonce proposal for the environment and returns the hash of the
601  * proposal.
602  *
603  * @param nv
604  * The environment to manipulate.
605  *
606  * @param d
607  * Upon successful return, the digest of the proposal nonce which was
608  * generated. On failure, the contents of this structure are undefined.
609  *
610  * @param d_len
611  * Upon successful return, the length of the nonce digest.
612  *
613  * @param n
614  * Upon successful return, the proposal nonce which was generated.
615  *
616  * This parameter may be NULL. If the caller's minimum deployment target is less
617  * than macOS 15 or iOS 17, and the caller is building with -fbounds-checking,
618  * then the caller must pass a non-NULL parameter.
619  *
620  * @param n_len
621  * Upon input, the length of the buffer referred to by {@link n}. Since
622  * {@link n} can be NULL, C does not permit the static qualifier to enforce a
623  * minimum array size, and therefore this parameter communicates the length of
624  * the buffer to the callee. Upon successful return, the this parameter will
625  * be the length of the nonce returned in {@link n}.
626  *
627  * @result
628  * Upon success, zero is returned. Otherwise, the implementation may directly
629  * return one of the following POSIX error codes:
630  *
631  *     [EPERM]    The caller lacks the entitlement required to manipulate the
632  *                desired nonce
633  *     [EACCES]   The caller requested the proposal nonce in addition to its
634  *                digest, and the environment does not support returning the
635  *                nonce to the caller's execution context
636  *     [ENOTSUP]  The environment does not manage a nonce for anti-replay
637  *
638  * @discussion
639  * The {@link n} and {@link n_len} parameters must either both be NULL or non-
640  * NULL. Passing NULL for one but not the other will result in undefined
641  * behavior in the implementation.
642  *
643  * If the caller's minimum deployment target is less than macOS 15 or iOS 17,
644  * and the caller is building with -fbounds-checking, then the caller must pass
645  * non-NULL values for both {@link n} and {@link n_len}. In this case, the value
646  * referred to be {@link n_len} should be 0 to indicate to the implementation
647  * that the proposal nonce itself is not desired.
648  */
649 IMAGE4_API_AVAILABLE_SPRING_2024
650 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
651 errno_t
652 image4_environment_generate_nonce_proposal(
653 	const image4_environment_t *nv,
654 	uint8_t d[__static_size _Nonnull IMAGE4_DIGEST_MAX_LEN],
655 	size_t *d_len,
656 	uint8_t n[__static_array_or_null(IMAGE4_NONCE_MAX_LEN)],
657 	size_t *_Nullable n_len);
658 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_generate_nonce_proposal);
659 
660 /*!
661  * @function image4_environment_commit_nonce_proposal
662  * Commits the nonce proposal corresponding to the digest provided by the caller
663  * such that it will be accepted and live at the next boot.
664  *
665  * @param nv
666  * The environment to manipulate.
667  *
668  * @param d
669  * The digest of the proposal to commit.
670  *
671  * @param d_len
672  * The length of the nonce proposal digest.
673  *
674  * @result
675  * Upon success, zero is returned. Otherwise, the implementation may directly
676  * return one of the following POSIX error codes:
677  *
678  *     [EPERM]    The caller lacks the entitlement required to manipulate the
679  *                desired nonce
680  *     [ENOTSUP]  The environment does not manage a nonce for anti-replay
681  *     [ENODEV]   There is no proposal for the given nonce
682  *     [EILSEQ]   The digest provided by the caller does not correspond to the
683  *                active proposal; this may occur if another subsystem
684  *                generates a proposal for the environment
685  */
686 IMAGE4_API_AVAILABLE_SPRING_2024
687 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
688 errno_t
689 image4_environment_commit_nonce_proposal(
690 	const image4_environment_t *nv,
691 	const uint8_t d[__static_size _Nonnull IMAGE4_DIGEST_MAX_LEN],
692 	size_t *d_len);
693 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_commit_nonce_proposal);
694 
695 /*!
696  * @function image4_environment_flash
697  * Activates an Image4 object with the provided environment.
698  *
699  * @param nv
700  * The environment to manipulate.
701  *
702  * @param object
703  * A pointer to the Image4 object bytes that will be activated. These bytes must
704  * represent a complete Image4 object. If the environment requires personalized
705  * signatures, then the object must also have a RestoreInfo section with the DFU
706  * nonce set in the appropriate property.
707  *
708  * @param object_len
709  * The length of the buffer referenced by {@link object}.
710  *
711  * @param n
712  * Upon successful return, the value of the nonce which was consumed during the
713  * DFU operation. The caller is expected to store this value in a RestoreInfo
714  * section in order to subsequently verify the manifest.
715  *
716  * This parameter may be NULL.
717  *
718  * @param n_len
719  * Upon input, the length of the buffer referred to by {@link n}. Since
720  * {@link n} can be NULL, C does not permit the static qualifier to enforce a
721  * minimum array size, and therefore this parameter communicates the length of
722  * the buffer to the callee. Upon successful return, the this parameter will
723  * be the length of the nonce returned in {@link n}.
724  *
725  * @result
726  * Upon success, zero is returned. Otherwise, the implementation may directly
727  * return one of the following POSIX error codes:
728  *
729  *     [EPERM]    The caller lacks the entitlement required to DFU the
730  *                environment
731  *     [ENOTSUP]  The environment does not support DFU in this target
732  *
733  * The implementation may also return any error that the
734  * {@link image4_trust_evaluation_result_t} callback may deliver to its callee.
735  *
736  * @availability
737  * This function first became available in API version 20240112.
738  *
739  * @discussion
740  * The {@link n} and {@link n_len} parameters must either both be NULL or non-
741  * NULL. Passing NULL for one but not the other will result in undefined
742  * behavior in the implementation.
743  *
744  * If the caller's minimum deployment target is less than macOS 15 or iOS 17,
745  * and the caller is building with -fbounds-checking, then the caller must pass
746  * non-NULL values for both {@link n} and {@link n_len}. In this case, the value
747  * referred to be {@link n_len} should be 0 to indicate to the implementation
748  * that the proposal nonce itself is not desired.
749  */
750 IMAGE4_API_AVAILABLE_FALL_2024
751 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
752 errno_t
753 image4_environment_flash(
754 	const image4_environment_t *nv,
755 	const void *__sized_by(object_len) object,
756 	size_t object_len,
757 	uint8_t n[__static_array_or_null(IMAGE4_NONCE_MAX_LEN)],
758 	size_t *_Nullable n_len);
759 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_flash);
760 
761 /*!
762  * @function image4_environment_destroy
763  * Disposes an environment object which was created via
764  * {@link image4_environment_new}.
765  *
766  * @param nv
767  * A pointer to the environment object. Upon return, this storage will be set to
768  * NULL. If the object pointed to by this parameter is NULL, this is a no-op.
769  *
770  * @discussion
771  * If this routine is called on an environment object which was not allocated,
772  * it is a no-op.
773  */
774 IMAGE4_API_AVAILABLE_SPRING_2024
775 OS_EXPORT OS_NONNULL1
776 void
777 image4_environment_destroy(
778 	image4_environment_t *_Nonnull *_Nullable nv);
779 IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_destroy);
780 
781 #pragma mark Retired
782 IMAGE4_XNU_RETIRED_DIRECT(image4_environment_get_nonce_handle);
783 
784 OS_ASSUME_PTR_ABI_SINGLE_END
785 OS_ASSUME_NONNULL_END
786 __END_DECLS
787 
788 #endif // __IMAGE4_API_ENVIRONMENT_H
789