xref: /xnu-11215.41.3/EXTERNAL_HEADERS/img4/firmware.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
1 /*!
2  * @header
3  * Interfaces for manipulating Image4 firmware objects.
4  */
5 #ifndef __IMG4_FIRMWARE_H
6 #define __IMG4_FIRMWARE_H
7 
8 #define __IMG4_INDIRECT 1
9 #include <img4/api.h>
10 
11 /*!
12  * @discussion
13  * When used from the pmap layer, this header pulls in the types from libsa,
14  * which conflict with the BSD sys/types.h header that we need to pull in. But
15  * we only need it for the errno_t typedef and the vnode_t typedef. So when
16  * building MACH_KERNEL_PRIVATE, we do two things:
17  *
18  *     1. Explicitly pull in <sys/_types/_errno_t.h>, so we get errno_t and
19  *        nothing else (no transitive #include's)
20  *     2. #define _SYS_TYPES_H_ before #includ'ing <sys/kernel_types.h> so that
21  *        we don't get the transitive #include of <sys/types.h> but we still get
22  *        the definitions we need
23  */
24 #if IMG4_TARGET_XNU
25 #if MACH_KERNEL_PRIVATE
26 #define _SYS_TYPES_H_ 1
27 #include <sys/kernel_types.h>
28 #include <sys/_types/_errno_t.h>
29 #else
30 #include <sys/kernel_types.h>
31 #include <sys/types.h>
32 #endif
33 
34 #if XNU_KERNEL_PRIVATE
35 #include <img4/4xnu.h>
36 #endif
37 #endif // IMG4_TARGET_XNU
38 
39 #if IMG4_TARGET_DARWIN
40 #include <os/stdio.h>
41 #include <sys/types.h>
42 #include <img4/4ignition.h>
43 #include <img4/4MSU.h>
44 #endif
45 
46 #include <sys/cdefs.h>
47 
48 __BEGIN_DECLS
49 OS_ASSUME_NONNULL_BEGIN
50 OS_ASSUME_PTR_ABI_SINGLE_BEGIN
51 
52 /*!
53  * @typedef img4_4cc_t
54  * A type which represents a four-character code (4cc) that identifies the
55  * firmware. These 4cc's are statically assigned and correspond to long-form tag
56  * names -- e.g. the 4cc 'krnl' corresponds to the "KernelCache" tag.
57  */
58 IMG4_API_AVAILABLE_20200508
59 typedef uint32_t img4_4cc_t;
60 
61 /*!
62  * @typedef img4_buff_t
63  * A structure describing a buffer. See {@link _img4_buff}.
64  */
65 IMG4_API_AVAILABLE_20200508
66 typedef struct _img4_buff img4_buff_t;
67 
68 /*!
69  * @const IMG4_DGST_STRUCT_VERSION
70  * The version of the {@link img4_dgst_t} structure supported by the
71  * implementation.
72  */
73 #define IMG4_DGST_STRUCT_VERSION (0u)
74 
75 /*!
76  * @const IMG4_DGST_MAX_LEN
77  * The maximum length of a digest representable by an {@link img4_dgst_t}.
78  */
79 #define IMG4_DGST_MAX_LEN (48u)
80 
81 /*!
82  * @typedef img4_dgst_t
83  * A type representing an Image4 identifier which is a digest.
84  *
85  * @field i4d_len
86  * The version of the structure. Initialize to {@link IMG4_DGST_STRUCT_VERSION}.
87  *
88  * @field i4d_len
89  * The length of the digest.
90  *
91  * @field i4d_bytes
92  * The digest bytes.
93  */
94 IMG4_API_AVAILABLE_20200508
95 typedef struct _img4_dgst {
96 	img4_struct_version_t i4d_version;
97 	size_t i4d_len;
98 	uint8_t i4d_bytes[IMG4_DGST_MAX_LEN];
99 } img4_dgst_t;
100 
101 /*!
102  * @const IMG4_DGST_INIT
103  * A convenience initializer for an {@link img4_dgst_t} structure.
104  */
105 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
106 #define IMG4_DGST_INIT (img4_dgst_t){ \
107 	.i4d_version = IMG4_DGST_STRUCT_VERSION, \
108 	.i4d_len = 0, \
109 	.i4d_bytes = {0}, \
110 }
111 #elif defined(__cplusplus) && __cplusplus >= 201103L
112 #define IMG4_DGST_INIT (img4_dgst_t{ \
113 	IMG4_DGST_STRUCT_VERSION, \
114 	0, \
115 	{0}, \
116 })
117 #elif defined(__cplusplus)
118 #define IMG4_DGST_INIT (img4_nonce_t((img4_nonce_t){ \
119 	IMG4_DGST_STRUCT_VERSION, \
120 	0, \
121 	{0}, \
122 }))
123 #else
124 #define IMG4_DGST_INIT {IMG4_DGST_STRUCT_VERSION}
125 #endif
126 
127 /*!
128  * @struct _img4_cstr
129  * A type representing an Image4 identifier which is a C-string. These
130  * identifiers can be no more than 64 bytes in length, including the null
131  * terminating byte.
132  *
133  * @field i4b_len
134  * The length of the C-string, not including the null terminating byte.
135  *
136  * @field i4b_cstr
137  * The null-terminated C-string.
138  *
139  * @discussion
140  * This structure is intentionally unversioned. It should never evolve into
141  * anything more complex than it is.
142  */
143 IMG4_API_AVAILABLE_20210113
144 typedef struct _img4_cstr {
145 	size_t i4cs_len;
146 	char i4cs_cstr[64];
147 } img4_cstr_t;
148 
149 /*!
150  * @const IMG4_CSTR_INIT
151  * A convenience initializer for an {@link img4_cstr_t}.
152  */
153 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
154 #define IMG4_CSTR_INIT (img4_cstr_t){ \
155 	.i4cs_len = 0, \
156 	.i4cs_cstr = {0}, \
157 }
158 #elif defined(__cplusplus) && __cplusplus >= 201103L
159 #define IMG4_CSTR_INIT (img4_cstr_t{ \
160 	0, \
161 	{0}, \
162 })
163 #elif defined(__cplusplus)
164 #define IMG4_CSTR_INIT \
165 		(img4_cstr_t((img4_cstr_t){ \
166 	0, \
167 	{0}, \
168 }))
169 #else
170 #define IMG4_CSTR_INIT {0}
171 #endif
172 
173 /*!
174  * @typedef img4_chip_t
175  * An opaque type describing a destination chip environment for the firmware
176  * image.
177  */
178 IMG4_API_AVAILABLE_20200508
179 typedef struct _img4_chip img4_chip_t;
180 
181 /*!
182  * @typedef img4_firmware_t
183  * An opaque type describing an Image4 firmware object.
184  */
185 IMG4_API_AVAILABLE_20200508
186 typedef struct _img4_firmware *img4_firmware_t;
187 
188 /*!
189  * @typedef img4_image_t
190  * An opaque type describing an authenticated Image4 firmware image.
191  */
192 IMG4_API_AVAILABLE_20200508
193 typedef struct _img4_image *img4_image_t;
194 
195 /*!
196  * @typedef img4_runtime_t
197  * A structure describing required primitives in the operating environment's
198  * runtime. See {@link _img4_runtime}.
199  */
200 IMG4_API_AVAILABLE_20200508
201 typedef struct _img4_runtime img4_runtime_t;
202 
203 OS_ASSUME_PTR_ABI_SINGLE_END
204 OS_ASSUME_NONNULL_END
205 
206 #include <img4/nonce.h>
207 #include <img4/object.h>
208 #include <img4/chip.h>
209 #include <img4/chip_ap.h>
210 #include <img4/chip_ap_category.h>
211 #include <img4/chip_ap_software.h>
212 #include <img4/chip_cryptex1.h>
213 #include <img4/chip_sep.h>
214 #include <img4/chip_x86.h>
215 #include <img4/image.h>
216 #include <img4/runtime.h>
217 
218 #if TXM
219 #include <img4/4txm.h>
220 #endif
221 
222 OS_ASSUME_NONNULL_BEGIN
223 OS_ASSUME_PTR_ABI_SINGLE_BEGIN
224 
225 /*!
226  * @typedef img4_firmware_authenticated_execute_t
227  * A firmware execution function. This function is called when the firmware has
228  * been successfully authenticated and is ready for execution.
229  *
230  * @param fw
231  * The firmware which has been authenticated.
232  *
233  * @param image
234  * The resulting firmware image that may be executed. The implementation will
235  * pass NULL if there was a failure.
236  *
237  * This object is automatically freed by the implementation upon return.
238  *
239  * @param error
240  * An error code describing the result of the authentication. If authentication
241  * was successful, the implementation will pass zero. Otherwise, one of the
242  * following error codes will be provided:
243  *
244  *     [EILSEQ]     The firmware data is not valid Image4 data -- this will not
245  *                  be passed for firmwares created with
246  *                  {@link IMG4_FIRMWARE_FLAG_BARE}
247  *     [EFTYPE]     The attached manifest is not a valid Image4 manifest
248  *     [ENOENT]     The attached manifest does not authenticate this type of
249  *                  firmware
250  *     [EAUTH]      The attached manifest is not authentic (i.e. was not signed
251  *                  by an Apple CA)
252  *     [EACCES]     The given chip does not satisfy the constraints of the
253  *                  attached manifest
254  *     [ESTALE]     The manifest has been invalidated and is no longer valid for
255  *                  the provided chip
256  *     [ENOEXEC]    The firmware has been corrupted, or the given chip does not
257  *                  satisfy the constraints of the corresponding object in the
258  *                  attached manifest
259  *
260  * @param _ctx
261  * The user-provided context pointer.
262  */
263 IMG4_API_AVAILABLE_20200508
264 typedef void (*img4_firmware_authenticated_execute_t)(
265 	const img4_firmware_t fw,
266 	img4_image_t _Nullable image,
267 	errno_t error,
268 	void *_ctx
269 );
270 
271 #if IMG4_TARGET_EFI
272 typedef void (*img4_firmware_authenticated_execute_efi_t)(
273 	const img4_firmware_t fw,
274 	img4_image_t _Nullable image,
275 	EFI_STATUS status,
276 	void *_ctx
277 );
278 #endif
279 
280 /*!
281  * @define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION
282  * The version of the {@link img4_firmware_execution_context_t} structure
283  * supported by the implementation.
284  */
285 #define IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION (1u)
286 
287 /*!
288  * @typedef img4_firmware_execution_context_t
289  * A structure describing the context in which a firmware is to be executed.
290  *
291  * @field i4fex_version
292  * The version of the structure supported by the implementation. Initialize to
293  * {@link IMG4_FIRMWARE_EXECUTION_CONTEXT_STRUCT_VERSION}.
294  *
295  * @field i4fex_execute
296  * A pointer to the firmware execution function.
297  *
298  * @field i4fex_execute_efi
299  * A pointer to the EFI-specific firmware execution function. This is only
300  * available in the EFI environment. If both this field and
301  * {@link i4fex_execute} are specified in the execution context, the
302  * one which is called by the implementation will be undefined.
303  *
304  * This field was added in version 1 of the structure. It was not appended to
305  * the end of the structure since the non-EFI structure did not change, and the
306  * structure did not previously exist in the EFI environment. The version
307  * increment was not strictly necessary, but was done for hygienic reasons.
308  *
309  * @field i4fex_context
310  * A caller-provided context pointer that will be passed to functions invoked
311  * from the execution context.
312  */
313 IMG4_API_AVAILABLE_20200508
314 typedef struct _img4_firmware_execution_context {
315 	img4_struct_version_t i4fex_version;
316 	img4_firmware_authenticated_execute_t i4fex_execute;
317 #if IMG4_TARGET_EFI
318 	img4_firmware_authenticated_execute_efi_t i4fex_execute_efi;
319 #endif
320 	void *i4fex_context;
321 } img4_firmware_execution_context_t;
322 
323 /*!
324  * @typedef img4_firmware_flags_t
325  * A bitfield modifying the behavior of an {@link img4_firmware_t} object.
326  *
327  * @const IMG4_FIRMWARE_FLAG_INIT
328  * No bits set. This value is suitable for initialization purposes.
329  *
330  * @const IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST
331  * The manifest authenticating the firmware is attached (i.e. the buffer given
332  * represents a .img4 file).
333  *
334  * This flag no longer does anything and probably never did. The implementation
335  * assumes that, if {@link img4_firmware_attach_manifest} was not called, then
336  * the manifest is attached to the payload.
337  *
338  * @const IMG4_FIRMWARE_FLAG_BARE
339  * The firmware image is not wrapped with an Image4 payload structure. This flag
340  * is mutually exclusive with {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST}, and
341  * if both are present, the implementation's behavior is undefined.
342  *
343  * @const IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE
344  * The firmware image extends an existing chain of trust.
345  *
346  * This flag no longer does anything; the implementation is now designed to
347  * understand which environments are first-stage or subsequent-stage boots.
348  *
349  * @const IMG4_FIRMWARE_FLAG_RESPECT_AMNM
350  * Forces the implementation to respect the manifest's AMNM entitlement if it is
351  * present, even if the validation is creating a new chain of trust. This is
352  * technically maybe sort of against the Image4 spec, but it is useful for
353  * certain internal workflows (cf. v2.3, §2.2.10).
354  *
355  * This flag has no effect if {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} is
356  * also passed.
357  *
358  * @const IMG4_FIRMWARE_FLAG_PASSTHROUGH
359  * Causes the wrapped payload bytes to be delivered to the image execution
360  * callback. These bytes do not have the Image4 wrapping stripped.
361  *
362  * This flag no longer does anything.
363  *
364  * @const IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY
365  * Force anti-replay enforcement even when performing just manifest evaluation
366  * without executing a firmware. When executing a firmware, this flag need not
367  * be passed in since anti-replay enforcement is always enabled.
368  */
369 IMG4_API_AVAILABLE_20200508
370 OS_CLOSED_OPTIONS(img4_firmware_flags, uint64_t,
371 	IMG4_FIRMWARE_FLAG_INIT,
372 	IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST = (1 << 0),
373 	IMG4_FIRMWARE_FLAG_BARE = (1 << 1),
374 	IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE = (1 << 2),
375 	IMG4_FIRMWARE_FLAG_RESPECT_AMNM = (1 << 3),
376 	IMG4_FIRMWARE_FLAG_PASSTHROUGH = (1 << 4),
377 	IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY = (1 << 5),
378 );
379 
380 /*!
381  * @function img4_firmware_new
382  * Allocate and initialize a new firmware object.
383  *
384  * @param rt
385  * The runtime in which to initialize the object.
386  *
387  * @param _4cc
388  * The 4cc which distinguishes the firmware.
389  *
390  * @param buff
391  * A buffer containing a valid Image4 payload (usually the contents of either a
392  * .im4p or .img4 file).
393  *
394  * Upon return, the destructor in the buffer is replaced with NULL, and the
395  * implementation assumes responsibility for deallocating the underlying memory.
396  *
397  * @param flags
398  * Flags modifying the behavior of the object.
399  *
400  * @result
401  * A new firmware object or NULL if there was an allocation failure. If
402  * {@link rt} has a NULL allocation function, NULL is returned.
403  *
404  * @discussion
405  * The resulting object assumes ownership of the given buffer.
406  *
407  * In the Darwin userspace runtime, NULL will not be returned.
408  */
409 #if !XNU_KERNEL_PRIVATE
410 IMG4_API_AVAILABLE_20200508
411 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4
412 img4_firmware_t _Nullable
413 img4_firmware_new(const img4_runtime_t *rt,
414 		const img4_firmware_execution_context_t *exec,
415 		img4_4cc_t _4cc,
416 		img4_buff_t *buff,
417 		img4_firmware_flags_t flags);
418 #else
419 #define img4_firmware_new(...) (img4if->i4if_v7.firmware_new(__VA_ARGS__))
420 #endif
421 
422 /*!
423  * @function img4_firmware_new_from_vnode_4xnu
424  * Allocate and initialize a new firmware object from a vnode.
425  *
426  * @param rt
427  * The runtime in which to initialize the object. This interface is only
428  * supported with the Darwin kernel runtime. If any other runtime is provided,
429  * the implementation's behavior is undefined.
430  *
431  * @param _4cc
432  * The 4cc which distinguishes the firmware.
433  *
434  * @param vn
435  * A vnode representing a valid Image4 payload (usually the contents of either a
436  * .im4p or .img4 file).
437  *
438  * @param flags
439  * Flags modifying the behavior of the object.
440  *
441  * @result
442  * A new firmware object or NULL if there was an allocation failure.
443  *
444  * @discussion
445  * Verification of a vnode is performed by reading in chunks of data, updating
446  * an ongoing hash operation with that data, and then discarding it. Therefore,
447  * firmware objects created in this manner can only guarantee their validity at
448  * the time the check was performed since the vnode's contents are not kept in
449  * memory and may be tampered with after validation has been performed.
450  *
451  * As such, on successful execution, the image passed to the
452  * {@link img4_firmware_authenticated_execute_t} function of the execution
453  * context is NULL.
454  *
455  * Firmwares created with this interface cannot be created with the
456  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag.
457  */
458 #if IMG4_TARGET_XNU
459 #if !XNU_KERNEL_PRIVATE
460 IMG4_API_AVAILABLE_20200508
461 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2 OS_NONNULL4
462 img4_firmware_t _Nullable
463 img4_firmware_new_from_vnode_4xnu(const img4_runtime_t *rt,
464 		const img4_firmware_execution_context_t *exec,
465 		img4_4cc_t _4cc,
466 		vnode_t vn,
467 		img4_firmware_flags_t flags);
468 #else
469 #define img4_firmware_new_from_vnode_4xnu(...) \
470 		(img4if->i4if_v7.firmware_new_from_vnode_4xnu(__VA_ARGS__))
471 #endif // !XNU_KERNEL_PRIVATE
472 #endif // IMG4_TARGET_XNU
473 
474 /*!
475  * @function img4_firmware_new_from_fd_4MSM
476  * Allocate and initialize a new firmware object from a file descriptor.
477  *
478  * @param rt
479  * The runtime in which to initialize the object. This interface is only
480  * supported with the Darwin userspace runtime. If any other runtime is
481  * provided, the implementation's behavior is undefined.
482  *
483  * @param _4cc
484  * The 4cc which distinguishes the firmware.
485  *
486  * @param fd
487  * A pointer to a file descriptor representing a valid Image4 payload (usually
488  * the contents of either a .im4p or .img4 file). The object assumes ownership
489  * of the descriptor, and upon return, the value referenced by the pointer will
490  * be set to -1.
491  *
492  * @param flags
493  * Flags modifying the behavior of the object.
494  *
495  * @result
496  * A new firmware object. The implementation will not return NULL.
497  *
498  * @discussion
499  * This interface is the userspace equivalent of
500  * {@link img4_firmware_new_from_vnode_4xnu}, and all the same caveats apply.
501  */
502 #if IMG4_TARGET_DARWIN
503 IMG4_API_AVAILABLE_20200508
504 OS_EXPORT OS_WARN_RESULT OS_MALLOC OS_NONNULL1 OS_NONNULL2
505 img4_firmware_t
506 img4_firmware_new_from_fd_4MSM(const img4_runtime_t *rt,
507 		const img4_firmware_execution_context_t *exec,
508 		img4_4cc_t _4cc,
509 		os_fd_t *fd,
510 		img4_firmware_flags_t flags);
511 #endif
512 
513 /*!
514  * @function img4_firmware_init_from_buff
515  * Initializes a buffer as a firmware object. This interface is useful for
516  * runtimes which do not provide for dynamic memory allocation.
517  *
518  * @param storage
519  * A pointer to the storage to use for the firmware object.
520  *
521  * @param len
522  * The size of the buffer.
523  *
524  * @discussion
525  * The caller is expected to pass a buffer that is "big enough". If the provided
526  * buffer is too small, the implementation will abort the caller.
527  *
528  * @example
529  *
530  *     uint8_t _buff[IMG4_FIRMWARE_SIZE_RECOMMENDED];
531  *     img4_firmware_t fw = NULL;
532  *
533  *     fw = img4_firmware_init_from_buff(_buff, sizeof(_buff));
534  *     img4_firmware_init(fw, IMG4_RUNTIME_DEFAULT, &exec_context,
535  *             kImg4Tag_krnl, fw_buff, 0);
536  */
537 #if !XNU_KERNEL_PRIVATE
538 IMG4_API_AVAILABLE_20200508
539 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
540 img4_firmware_t
541 img4_firmware_init_from_buff(void *__sized_by(len) buff, size_t len);
542 #else
543 #define img4_firmware_init_from_buff(...) \
544 		(img4if->i4if_v7.firmware_init_from_buff(__VA_ARGS__))
545 #endif
546 
547 /*!
548  * @function img4_firmware_init
549  * Initialize a firmware object.
550  *
551  * @param fw
552  * A pointer to the storage for the firmware object. This pointer should refer
553  * to a region of memory that is sufficient to hold a {@link img4_firmware_t}
554  * object. This size should be queried with the {@link i4rt_object_size}
555  * function of the runtime.
556  *
557  * @param rt
558  * The runtime in which to initialize the object.
559  *
560  * @param _4cc
561  * The 4cc which distinguishes the firmware.
562  *
563  * @param buff
564  * A buffer containing a valid Image4 payload (usually the contents of either a
565  * .im4p or .img4 file).
566  *
567  * Upon return, the destructor in the buffer is replaced with NULL, and the
568  * implementation assumes responsibility for deallocating the underlying memory.
569  *
570  * @param flags
571  * Flags modifying the behavior of the object.
572  *
573  * @discussion
574  * The resulting object assumes ownership of the given buffer. This routine
575  * should only be used when dynamic memory allocation is not available in the
576  * runtime. Otherwise, use {@link img4_firmware_new}.
577  */
578 #if !XNU_KERNEL_PRIVATE
579 IMG4_API_AVAILABLE_20200508
580 OS_EXPORT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL5
581 void
582 img4_firmware_init(img4_firmware_t fw,
583 		const img4_runtime_t *rt,
584 		const img4_firmware_execution_context_t *exec,
585 		img4_4cc_t _4cc,
586 		img4_buff_t *buff,
587 		img4_firmware_flags_t flags);
588 #else
589 #define img4_firmware_init(...) (img4if->i4if_v7.firmware_init(__VA_ARGS__))
590 #endif
591 
592 /*!
593  * @function img4_firmware_init_sentinel
594  * Initialize a firmware object as a sentinel without any manifest attached.
595  * This firmware has no object tag and is not executable. It is only suitable
596  * for use with {@link img4_firmware_attach_manifest} and
597  * {@link img4_firmware_evaluate} to determine whether a manifest is acceptable
598  * to a particular chip environment.
599  *
600  * @param fw
601  * A pointer to the storage for the firmware object. This pointer should refer
602  * to a region of memory that is sufficient to hold a {@link img4_firmware_t}
603  * object. This size should be queried with the {@link i4rt_object_size}
604  * function of the runtime.
605  *
606  * @param rt
607  * The runtime in which to initialize the object.
608  *
609  * @param flags
610  * Flags modifying the behavior of the object.
611  *
612  * @discussion
613  * Sentinel firmwares do not enforce anti-replay, so
614  * {@link img4_firmware_evaluate} will not return ESTALE when evaluating such
615  * firmwares. Anti-replay enforcement can be enabled by using
616  * {@link IMG4_FIRMWARE_FLAG_FORCE_ANTI_REPLAY}.
617  */
618 #if !XNU_KERNEL_PRIVATE
619 IMG4_API_AVAILABLE_20211126
620 OS_EXPORT OS_NONNULL1 OS_NONNULL2
621 void
622 img4_firmware_init_sentinel(img4_firmware_t fw,
623 		const img4_runtime_t *rt,
624 		img4_firmware_flags_t flags);
625 #else
626 #define img4_firmware_init_sentinel(...) \
627 		(img4if->i4if_v17.firmware_init_sentinel(__VA_ARGS__))
628 #endif
629 
630 /*!
631  * @function img4_firmware_attach_manifest
632  * Attaches a signed manifest to the firmware.
633  *
634  * @param fw
635  * The firmware to manipulate.
636  *
637  * @param buff
638  * A buffer containing a valid Image4 manifest (usually the contents of either a
639  * .im4m or .img4 file).
640  *
641  * Upon return, the destructor in the buffer is replaced with NULL, and the
642  * implementation assumes responsibility for deallocating the underlying memory.
643  *
644  * @discussion
645  * If this interface is called on a firmware created with the
646  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag, the implementation's
647  * behavior is undefined.
648  *
649  * This interface must be called on any firmware created with the
650  * {@link IMG4_FIRMWARE_FLAG_BARE} flag.
651  *
652  * The object assumes ownership of the given buffer.
653  */
654 #if !XNU_KERNEL_PRIVATE
655 IMG4_API_AVAILABLE_20200508
656 OS_EXPORT OS_NONNULL1 OS_NONNULL2
657 void
658 img4_firmware_attach_manifest(img4_firmware_t fw,
659 		img4_buff_t *buff);
660 #else
661 #define img4_firmware_attach_manifest(...) \
662 		(img4if->i4if_v7.firmware_attach_manifest(__VA_ARGS__))
663 #endif
664 
665 /*!
666  * @function img4_firmware_select_chip
667  * Returns the chip from the provided array which may be used to authenticate
668  * the firmware.
669  *
670  * @param fw
671  * The firmware to query.
672  *
673  * @param chips
674  * An array of chips the caller finds acceptable to verify the firmware.
675  *
676  * @param chips_cnt
677  * The number of elements in {@link chips}.
678  *
679  * @result
680  * If the manifest may be authenticated by the certificate chain associated with
681  * one of the manifests provided in {@link chips}, that chip is
682  * returned. If the manifest cannot be authenticated with any of the provided
683  * chips, NULL is returned.
684  *
685  * @discussion
686  * The result of calling this function on a firmware which does not have a
687  * manifest attached is undefined.
688  *
689  * If multiple chips may be used to authenticate the firmware, the
690  * implementation does not define which of those chips will be returned.
691  *
692  * If the firmware was created without the
693  * {@link IMG4_FIRMWARE_FLAG_SUBSEQUENT_STAGE} flag, this function will return
694  * NULL. This function cannot be used to establish new trust chains, only to
695  * verify an existing one.
696  */
697 #if !XNU_KERNEL_PRIVATE
698 IMG4_API_AVAILABLE_20200724
699 OS_EXPORT OS_WARN_RESULT
700 const img4_chip_t *_Nullable
701 img4_firmware_select_chip(const img4_firmware_t fw,
702 		const img4_chip_select_array_t __counted_by(chips_cnt) _Nonnull chips,
703 		size_t chips_cnt);
704 #else
705 #define img4_firmware_select_chip(...) \
706 		(img4if->i4if_v10.firmware_select_chip(__VA_ARGS__))
707 #endif
708 
709 /*!
710  * @function img4_firmware_execute
711  * Authenticate the firmware and execute it within its context.
712  *
713  * @param fw
714  * The firmware to execute.
715  *
716  * @param chip
717  * The chip on which to execute the firmware.
718  *
719  * @param nonce
720  * The nonce to use for authentication. May be NULL if the chip environment does
721  * not maintain an anti-replay token or if a chained evaluation is being
722  * performed.
723  *
724  * @discussion
725  * The implementation will always invoke the
726  * {@link img4_firmware_authenticated_execute_t} provided in the execution
727  * context with either a successful result or a failure. All error handling must
728  * take place in that context.
729  *
730  * The {@link img4_firmware_authenticated_execute_t} is called before the
731  * implementation returns.
732  *
733  * The result of executing a firmware without a manifest attached (either via
734  * {@link img4_firmware_attach_manifest} or by creating the firmware with the
735  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined.
736  */
737 #if !XNU_KERNEL_PRIVATE
738 IMG4_API_AVAILABLE_20200508
739 OS_EXPORT OS_NONNULL1 OS_NONNULL2
740 void
741 img4_firmware_execute(img4_firmware_t fw,
742 		const img4_chip_t *chip,
743 		const img4_nonce_t *_Nullable nonce);
744 #else
745 #define img4_firmware_execute(...) \
746 		(img4if->i4if_v7.firmware_execute(__VA_ARGS__))
747 #endif
748 
749 /*!
750  * @function img4_firmware_evaluate
751  * Evaluate the firmware for authenticity.
752  *
753  * @param fw
754  * The firmware to evaluate.
755  *
756  * @param chip
757  * The chip on which to evaluate the firmware.
758  *
759  * @param nonce
760  * The nonce to use for authentication. May be NULL if the chip environment does
761  * not maintain an anti-replay token or if a chained evaluation is being
762  * performed.
763  *
764  * @result
765  * An error code describing the result of the authentication. If authentication
766  * was successful, zero is returned. Otherwise, one of the following error codes
767  * will be returned:
768  *
769  *     [EILSEQ]     The firmware data is not valid Image4 data -- this will not
770  *                  be returned for firmwares created with
771  *                  {@link IMG4_FIRMWARE_FLAG_BARE}
772  *     [EFTYPE]     The attached manifest is not a valid Image4 manifest
773  *     [ENOENT]     The attached manifest does not authenticate this type of
774  *                  firmware
775  *     [EAUTH]      The attached manifest is not authentic (i.e. was not signed
776  *                  by an Apple CA)
777  *     [EACCES]     The given chip does not satisfy the constraints of the
778  *                  attached manifest
779  *     [ESTALE]     The manifest has been invalidated and is no longer valid for
780  *                  the provided chip
781  *     [ENOEXEC]    The firmware has been corrupted, or the given chip does not
782  *                  satisfy the constraints of the corresponding object in the
783  *                  attached manifest
784  *     [EPWROFF]    The chip environment has not yet booted; most chip
785  *                  environments are booted and available by the time the caller
786  *                  has begun executing, but some require additional
787  *                  initialization before they can execute objects
788  *
789  * @discussion
790  * This interface should be used when the caller is only concerned with the
791  * authenticity and integrity of the firmware image and does not intend to
792  * execute it.
793  *
794  * The result of evaluating a firmware without a manifest attached (either via
795  * {@link img4_firmware_attach_manifest} or by creating the firmware with the
796  * {@link IMG4_FIRMWARE_FLAG_ATTACHED_MANIFEST} flag set) is undefined.
797  */
798 #if !XNU_KERNEL_PRIVATE
799 IMG4_API_AVAILABLE_20200608
800 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
801 errno_t
802 img4_firmware_evaluate(img4_firmware_t fw,
803 		const img4_chip_t *chip,
804 		const img4_nonce_t *_Nullable nonce);
805 #else
806 #define img4_firmware_evaluate(...) \
807 		(img4if->i4if_v9.firmware_evaluate(__VA_ARGS__))
808 #endif
809 
810 /*!
811  * @function img4_firmware_destroy
812  * Destroys a firmware object and releases the associated resources according to
813  * the runtime's specification.
814  *
815  * @param fw
816  * A pointer to the firmware object.
817  *
818  * Upon return, this will be replaced with a known-invalid pointer value. This
819  * parameter may be NULL in which case the implementation will return
820  * immediately.
821  *
822  * @discussion
823  * The implementation will invoke the provided deallocation function of the
824  * buffer object underlying the firmware.
825  */
826 #if !XNU_KERNEL_PRIVATE
827 IMG4_API_AVAILABLE_20200508
828 OS_EXPORT
829 void
830 img4_firmware_destroy(img4_firmware_t _Nullable *_Nonnull fw);
831 #else
832 #define img4_firmware_destroy(...) \
833 		(img4if->i4if_v7.firmware_destroy(__VA_ARGS__))
834 #endif
835 
836 OS_ASSUME_PTR_ABI_SINGLE_END
837 OS_ASSUME_NONNULL_END
838 __END_DECLS
839 
840 #endif // __IMG4_FIRMWARE_H
841