3 * Image4 interfaces. These interfaces encapsulate the basic concepts required
4 * for authenticating and validating Image4 manifests as being authoritative.
8 * An environment is a description of a host comprised of hardware identifiers
9 * and policy configurations. For example, the environment of an iPhone may
10 * include the following hardware identifiers (among others):
13 * A number identifying the chip design.
16 * A number identifying the board.
19 * A number uniquely identifying a specific instance of a chip.
21 * The environment also includes policy information derived by previous stages
22 * of secure boot. Examples of such policy are:
24 * Mix-n-Match Prevention
25 * Whether firmware payloads from multiple, valid secure boot manifests
26 * should be prevented from being executed on the host environment. The
30 * An Image4 manifest is a set of constraints that describe a host environment.
31 * For example, a manifest may have been signed such that it is only valid for a
32 * single host environment. In this case, the manifest may include specific
33 * values for ChipID, BoardID, UniqueChipID, etc. Such a manifest is said to be
34 * personalized for that environment.
36 * If an environment meets the constraints in a manifest, that manifest is said
37 * to be authoritative over the environment.
39 * The manifest also includes one or more objects which may be executed in the
43 * An object is a description of a payload. An object can describe any payload,
44 * not just the payload that is in the Image4. An object describes a payload by
45 * means of its digest. Examples of objects present in a secure boot manifest
46 * are the kernelcache and the static trust cache.
48 * If an authoritative manifest accurately describes an object, then that object
49 * may be executed in the host environment. The mechanics of execution typically
50 * involve mapping its payload into a privileged memory region. For example,
51 * when the kernelcache is executed, its payload bytes are mapped into the range
52 * of memory associated with supervisor mode.
55 * A payload is the raw sequence of bytes that is described by an object. When
56 * described via an Image4 object, payloads are first wrapped in Image4 encoding
57 * to associate a tag with them. The resulting series of bytes is what is
58 * contained in a .im4p file.
60 * An Image4 file may only contain a single payload (even though a manifest may
61 * describe multiple payloads through multiple objects).
64 * A tag is a FourCC which can identify any of the following:
66 * - an object property (e.g. the 'DGST' property)
67 * - a manifest property (e.g. the 'BORD' property)
68 * - a certificate property
69 * - a type of object (e.g. 'krnl')
71 * Tags comprised of all-caps are reserved for the Image4 specification.
73 * @section Secure Boot Policy
74 * Manifests are evaluated with the Secure Boot evaluation policy. Broadly
75 * speaking, this policy:
77 * - enforces that manifest identifiers match the host's silicon
79 * - enforces that the epoch of the certificate which signed the manifest is
80 * greater than or equal to the host silicon's epoch
81 * - enforces that the current manifest is the same one that was used in the
82 * previous stage of Secure Boot unless mix-n-match is allowed
84 * For manifests which lack a CHMH property, mix-n-match policy is enforced as
87 * (1) If the previous stage of Secure Boot disallows mix-n-match and the
88 * manifest does not possess the AMNM entitlement, the hash of the
89 * manifest will be enforced against the hash of the manifest which was
90 * evaluated by the previous stage of Secure Boot.
92 * (2) If the previous stage of Secure Boot allows mix-n-match or the manifest
93 * possesses the AMNM entitlement, the manifest's constraints will be
94 * enforced on the environment, but the manifest will not be expected to
95 * be consistent with the manifest evaluated in the previous stage of
96 * Secure Boot, i.e. the hash of the previous manifest will not be
97 * enforced against the manifest being evaluated.
99 * Enforcement of the manifest's constraints will include the value of the
100 * BNCH tag in the manifest, if any. Therefore the caller should always
101 * provide a nonce value to the implementation via {@link img4_set_nonce}
102 * if this option is used.
104 * For manifests which possess a CHMH property, mix-n-match policy is enforced
107 * (1) If the previous stage of Secure Boot disallows mix-n-match or the
108 * manifest does not possess the AMNM entitlement, the value of the CHMH
109 * property will be enforced against the hash of the manifest which was
110 * evaluated by the previous stage of Secure Boot.
112 * (2) If the previous stage of Secure Boot allows mix-n-match and the
113 * manifest possesses the AMNM entitlement, all of the manifest's
114 * constraints will be enforced on the environment except for the CHMH
115 * constraint, which will be ignored.
117 * Enforcement of the manifest's constraints will include the value of the
118 * BNCH tag in the manifest, if any. Therefore the caller should always
119 * provide a nonce value to the implementation via {@link img4_set_nonce}
120 * if this option is used.
122 * The CHMH policy may be expressed as the following truth table:
124 * AMNM [manifest] Verify Manifest Hash [environment] Enforce CHMH
138 #include <sys/cdefs.h>
141 #if !defined(OS_CLOSED_ENUM)
142 #define OS_CLOSED_ENUM(...) OS_ENUM(__VA_ARGS__)
145 #if !defined(OS_OPTIONS)
146 #define OS_OPTIONS(...) OS_ENUM(__VA_ARGS__)
149 #if !defined(OS_CLOSED_OPTIONS)
150 #define OS_CLOSED_OPTIONS(...) OS_ENUM(__VA_ARGS__)
154 #define __IMG4_INDIRECT 1
157 * When used from the pmap layer, this header pulls in the types from libsa,
158 * which conflict with the BSD sys/types.h header that we need to pull in. But
159 * we only need it for the errno_t typedef and the vnode_t typedef. So when
160 * building MACH_KERNEL_PRIVATE, we do two things:
162 * 1. Explicitly pull in <sys/_types/_errno_t.h>, so we get errno_t and
163 * nothing else (no transitive #include's)
164 * 2. #define _SYS_TYPES_H_ before #includ'ing <sys/kernel_types.h> so that
165 * we don't get the transitive #include of <sys/types.h> but we still get
166 * the definitions we need
168 #if MACH_KERNEL_PRIVATE
169 #define _SYS_TYPES_H_ 1
170 #include <sys/kernel_types.h>
171 #include <sys/_types/_errno_t.h>
173 #include <sys/kernel_types.h>
174 #include <sys/types.h>
177 #if !IMG4_PROJECT_BUILD
178 #include <img4/api.h>
184 * @typedef img4_tag_t
185 * A type describing an Image4 tag.
187 IMG4_API_AVAILABLE_20180112
188 typedef uint32_t img4_tag_t
;
191 * @typedef img4_section_t
192 * A type describing the sections of an Image4 object.
194 * @const IMG4_SECTION_MANIFEST
195 * The manifest section.
197 * @const IMG4_SECTION_OBJECT
198 * The object section.
200 * @const IMG4_SECTION_RESTOREINFO
201 * The restore info section.
203 OS_ENUM(img4_section
, uint8_t,
204 IMG4_SECTION_MANIFEST
,
206 IMG4_SECTION_RESTOREINFO
,
207 ) IMG4_API_AVAILABLE_20180112
;
210 * @typedef img4_destructor_t
211 * A type describing a destructor routine for an Image4 object.
214 * A pointer to the buffer to dispose of.
217 * The length of the buffer.
219 IMG4_API_AVAILABLE_20180112
220 typedef void (*img4_destructor_t
)(
225 * @typedef img4_flags_t
226 * A flagset modifying the behavior of an {@link img4_t}.
229 * No flags set. This value is suitable for initialization purposes.
231 * @const I4F_TRUST_MANIFEST
232 * Causes the implementation to bypass trust evaluation for the manifest, i.e.
233 * it will not verify that a manifest has been signed by Apple before trusting
236 * This option is for testing purposes only and is not respected on the RELEASE
237 * variant of the implementation.
239 * @const I4F_FORCE_MIXNMATCH
240 * Causes the implementation to bypass mix-n-match policy evaluation and always
241 * allow mix-n-match, irrespective of the previous boot stage's conclusion or
242 * manifest policy. This also allows replay of manifests whose personalization
243 * has been invalidated by rolling the nonce.
245 * This option is for testing purposes only and is not respected on the RELEASE
246 * variant of the implementation.
248 * @const I4F_FIRST_STAGE
249 * Indicates that the manifest being evaluated is the first link in the secure
250 * boot chain. This causes the implementation to enforce the manifest directly
251 * on the environment rather than requiring that a previous stage has already
252 * done so by way of checking the previous stage's boot manifest hash. In effect
253 * this disables the mix-n-match enforcement policy.
255 * The critical difference between this flag and {@link I4F_FORCE_MIXNMATCH} is
256 * that this flag will cause the entire manifest to be enforced on the
257 * environment, including the anti-replay token in BNCH.
258 * {@link I4F_FORCE_MIXNMATCH} will ignore the nonce.
260 * It is illegal to use a manifest which possesses a CHMH tag as a first-stage
263 OS_CLOSED_OPTIONS(img4_flags
, uint64_t,
265 I4F_TRUST_MANIFEST
= (1 << 0),
266 I4F_FORCE_MIXNMATCH
= (1 << 1),
267 I4F_FIRST_STAGE
= (1 << 2),
268 ) IMG4_API_AVAILABLE_20180112
;
270 typedef char _img4_opaque_data_64
[696];
272 typedef char _img4_opaque_data_32
[520];
276 * An opaque structure representing Image4 data. The Image4 data must contain a
277 * manifest and may optionally contain a payload. Neither this type nor the APIs
278 * APIs which manipulate it are thread-safe.
280 IMG4_API_AVAILABLE_20180112
281 typedef struct _img4
{
282 #if __ILP64__ || __LP64__
283 _img4_opaque_data_64 __opaque
;
285 _img4_opaque_data_32 __opaque
;
289 typedef char _img4_payload_opaque_data_64
[504];
291 #if __ARM_ARCH_7A__ || __ARM_ARCH_7S__ || __ARM_ARCH_7K__ || \
292 __ARM64_ARCH_8_32__ || __i386__
293 typedef char _img4_payload_opaque_data_32
[328];
295 typedef char _img4_payload_opaque_data_32
[332];
299 * @typedef img4_payload_t
300 * An opaque structure describing Image4 payload data. Neither this type nor the
301 * APIs which manipulate it are thread-safe.
303 IMG4_API_AVAILABLE_20180112
304 typedef struct _img4_payload
{
305 #if __ILP64__ || __LP64__
306 _img4_payload_opaque_data_64 __opaque
;
308 _img4_payload_opaque_data_32 __opaque
;
312 #if !IMG4_PROJECT_BUILD
313 #include <img4/environment.h>
314 #include <img4/nonce.h>
315 #include <img4/payload.h>
319 #include "environment.h"
325 * @function img4_init
326 * Initializes an Image4.
329 * A pointer to the storage to initialize.
332 * Flags to modify initialization.
335 * The Image4 data from which to initialize. If a destructor is provided,
336 * control of this buffer transfers to the Image4.
339 * The length of the Image4 data.
342 * A destructor for the Image4 data. May be NULL if the buffer does not require
343 * explicit deallocation (e.g. because the buffer is stack data).
346 * Upon success, zero is returned. The implementation may also return one of the
347 * following error codes directly:
349 * [EILSEQ] The data is not valid Image4 data
350 * [EFTYPE] The data does not contain an Image4 manifest
353 * The bytes given to this routine must represent an Image4 manifest. They may
354 * optionally also represent an Image4 payload.
356 #if !XNU_KERNEL_PRIVATE
357 IMG4_API_AVAILABLE_20180112
358 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
360 img4_init(img4_t
*i4
, img4_flags_t flags
, const uint8_t *bytes
, size_t len
,
361 img4_destructor_t destructor
);
363 #define img4_init(...) (img4if->i4if_init(__VA_ARGS__))
367 * @function img4_set_nonce
368 * Sets the anti-reply token to be used during manifest enforcement. This value
369 * will be compared against the value of the manifest's BNCH property.
372 * The Image4 to modify.
375 * The bytes which comprise the anti-replay token.
378 * The length of the anti-replay token.
381 * If a nonce is not set prior to a call to either
382 * {@link img4_get_trusted_payload} or
383 * {@link img4_get_trusted_external_payload}, the implementation will act as
384 * though there is no nonce in the environment. Therefore, any manifests which
385 * have a BNCH property constraint will fail to validate.
387 #if !XNU_KERNEL_PRIVATE
388 IMG4_API_AVAILABLE_20180112
389 OS_EXPORT OS_NONNULL1 OS_NONNULL2
391 img4_set_nonce(img4_t
*i4
, const void *bytes
, size_t len
);
393 #define img4_set_nonce(...) (img4if->i4if_set_nonce(__VA_ARGS__))
397 * @function img4_set_nonce_domain
398 * Sets the nonce domain to be consulted for the anti-replay token during
399 * manifest enforcement.
402 * The Image4 to modify.
405 * The nonce domain to use for anti-replay.
408 * See discussion for {@link img4_set_nonce}.
410 #if !XNU_KERNEL_PRIVATE
411 IMG4_API_AVAILABLE_20181106
412 OS_EXPORT OS_NONNULL1 OS_NONNULL2
414 img4_set_nonce_domain(img4_t
*i4
, const img4_nonce_domain_t
*nd
);
416 #define img4_set_nonce_domain(...) \
417 (img4if->i4if_v1.set_nonce_domain(__VA_ARGS__))
421 * @function img4_get_trusted_payload
422 * Obtains the trusted payload bytes from the Image4.
425 * The Image4 to query.
428 * The tag for the payload to obtain.
431 * The environment against which to validate the Image4.
434 * A pointer to the storage where the pointer to the payload buffer will be
435 * written on success.
438 * A pointer to the storage where the length of the payload buffer will be
439 * written on success.
442 * Upon success, zero is returned. The implementation may also return one of the
443 * following error codes directly:
445 * [ENOENT] The Image4 does not contain a payload for the specified tag
446 * [EAUTH] The Image4 manifest was not authentic
447 * [EACCES] The environment given does not satisfy the manifest
449 * [ESTALE] The nonce specified is not valid
450 * [EACCES] The environment and manifest do not agree on a digest
452 * [EILSEQ] The payload for the given tag does not match its description
454 * [EIO] The payload could not be fetched
456 * Additionally, errors from the routines specified in the
457 * {@link img4_environment_t} may be returned.
460 * This routine will perform the following validation:
462 * 1. Validate that the Image4 manifest is authentic (i.e. was signed by
464 * 2. Validate that the given environment satisfies the constraints in the
466 * 3. Validate that the measurement of the payload for the given tag matches
467 * the measurement in the manifest
469 * If any one of these validation checks fails, the payload is considered
470 * untrustworthy and is not returned.
472 #if !XNU_KERNEL_PRIVATE
473 IMG4_API_AVAILABLE_20180112
474 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3 OS_NONNULL4 OS_NONNULL5
476 img4_get_trusted_payload(img4_t
*i4
, img4_tag_t tag
,
477 const img4_environment_t
*env
, const uint8_t **bytes
, size_t *len
);
479 #define img4_get_trusted_payload(...) \
480 (img4if->i4if_get_trusted_payload(__VA_ARGS__))
484 * @function img4_get_trusted_external_payload
485 * Obtains the trusted payload bytes from the external Image4 payload after
486 * validating them against the object description in the Image4's manifest.
489 * The Image4 to query.
492 * The payload to validate.
495 * The environment against which to validate the Image4.
498 * A pointer to the storage where the pointer to the payload buffer will be
499 * written on success.
501 * If the payload objects was initialized with
502 * {@link img4_payload_init_with_vnode_4xnu}, this parameter should be NULL, as
503 * there will be no in-memory buffer to return.
506 * A pointer to the storage where the length of the payload buffer will be
507 * written on success.
509 * If the payload objects was initialized with
510 * {@link img4_payload_init_with_vnode_4xnu}, this parameter should be NULL, as
511 * there will be no in-memory buffer to return.
514 * Upon success, zero is returned. The implementation may also return one of the
515 * following error codes directly:
517 * [ENOENT] The Image4 does not contain an object describing the given
519 * [EAUTH] The Image4 manifest was not authentic
520 * [EACCES] The environment given does not satisfy the manifest
522 * [ESTALE] The nonce specified is not valid
523 * [EACCES] The environment and manifest do not agree on a digest
525 * [EILSEQ] The payload for the given tag does not match its description
527 * [EIO] The payload could not be fetched
528 * [EIO] The payload was initialized with
529 * {@link img4_payload_init_with_vnode_4xnu}, and reading from
530 * the vnode stalled repeatedly beyond the implementation's
533 * If the payload was initialized with
534 * {@link img4_payload_init_with_vnode_4xnu}, any error returned by
535 * {@link vnode_getattr} or {@link vn_rdwr} may be returned.
537 * If the payload was initialized with
538 * {@link img4_payload_init_with_fd_4MSM}, any error returned by stat(2),
539 * read(2), or malloc(3) may be returned.
541 * Otherwise, an error from the underlying Image4 implementation will be
545 * This routine performs the same validation steps as
546 * {@link img4_get_trusted_payload}.
548 #if !XNU_KERNEL_PRIVATE
549 IMG4_API_AVAILABLE_20180112
550 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3
552 img4_get_trusted_external_payload(img4_t
*i4
, img4_payload_t
*payload
,
553 const img4_environment_t
*env
, const uint8_t **bytes
, size_t *len
);
555 #define img4_get_trusted_external_payload(...) \
556 (img4if->i4if_get_trusted_external_payload(__VA_ARGS__))
560 * @function img4_destroy
561 * Destroys an Image4 and disposes of associated resources.
564 * The Image4 to destroy.
567 * The destructor passed to {@link img4_init} is called as a result of this
568 * routine, if any was set.
570 #if !XNU_KERNEL_PRIVATE
571 IMG4_API_AVAILABLE_20180112
572 OS_EXPORT OS_NONNULL1
574 img4_destroy(img4_t
*i4
);
576 #define img4_destroy(...) (img4if->i4if_destroy(__VA_ARGS__))