]> git.saurik.com Git - apple/xnu.git/blob - EXTERNAL_HEADERS/img4/img4.h
xnu-6153.11.26.tar.gz
[apple/xnu.git] / EXTERNAL_HEADERS / img4 / img4.h
1 /*!
2 * @header
3 * Image4 interfaces. These interfaces encapsulate the basic concepts required
4 * for authenticating and validating Image4 manifests as being authoritative.
5 * These concepts are:
6 *
7 * @section Environment
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):
11 *
12 * ChipID
13 * A number identifying the chip design.
14 *
15 * BoardID
16 * A number identifying the board.
17 *
18 * UniqueChipID / ECID
19 * A number uniquely identifying a specific instance of a chip.
20 *
21 * The environment also includes policy information derived by previous stages
22 * of secure boot. Examples of such policy are:
23 *
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
27 * default is true.
28 *
29 * @section Manifest
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.
35 *
36 * If an environment meets the constraints in a manifest, that manifest is said
37 * to be authoritative over the environment.
38 *
39 * The manifest also includes one or more objects which may be executed in the
40 * environment.
41 *
42 * @section Object
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.
47 *
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.
53 *
54 * Payload
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.
59 *
60 * An Image4 file may only contain a single payload (even though a manifest may
61 * describe multiple payloads through multiple objects).
62 *
63 * Tag
64 * A tag is a FourCC which can identify any of the following:
65 *
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')
70 *
71 * Tags comprised of all-caps are reserved for the Image4 specification.
72 *
73 * @section Secure Boot Policy
74 * Manifests are evaluated with the Secure Boot evaluation policy. Broadly
75 * speaking, this policy:
76 *
77 * - enforces that manifest identifiers match the host's silicon
78 * identifiers,
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
83 *
84 * For manifests which lack a CHMH property, mix-n-match policy is enforced as
85 * follows
86 *
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.
91 *
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.
98 *
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.
103 *
104 * For manifests which possess a CHMH property, mix-n-match policy is enforced
105 * as follows:
106 *
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.
111 *
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.
116 *
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.
121 *
122 * The CHMH policy may be expressed as the following truth table:
123 *
124 * AMNM [manifest] Verify Manifest Hash [environment] Enforce CHMH
125 * 0 0 Y
126 * 0 1 Y
127 * 1 0 N
128 * 1 1 Y
129 */
130
131
132 #ifndef __IMG4_H
133 #define __IMG4_H
134
135 #include <os/base.h>
136 #include <stdint.h>
137 #include <stdbool.h>
138 #include <sys/cdefs.h>
139
140 #if KERNEL
141 #if !defined(OS_CLOSED_ENUM)
142 #define OS_CLOSED_ENUM(...) OS_ENUM(__VA_ARGS__)
143 #endif
144
145 #if !defined(OS_OPTIONS)
146 #define OS_OPTIONS(...) OS_ENUM(__VA_ARGS__)
147 #endif
148
149 #if !defined(OS_CLOSED_OPTIONS)
150 #define OS_CLOSED_OPTIONS(...) OS_ENUM(__VA_ARGS__)
151 #endif
152 #endif
153
154 #define __IMG4_INDIRECT 1
155
156 /*
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:
161 *
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
167 */
168 #if MACH_KERNEL_PRIVATE
169 #define _SYS_TYPES_H_ 1
170 #include <sys/kernel_types.h>
171 #include <sys/_types/_errno_t.h>
172 #else
173 #include <sys/kernel_types.h>
174 #include <sys/types.h>
175 #endif
176
177 #if !IMG4_PROJECT_BUILD
178 #include <img4/api.h>
179 #endif
180
181 __BEGIN_DECLS;
182
183 /*!
184 * @typedef img4_tag_t
185 * A type describing an Image4 tag.
186 */
187 IMG4_API_AVAILABLE_20180112
188 typedef uint32_t img4_tag_t;
189
190 /*!
191 * @typedef img4_section_t
192 * A type describing the sections of an Image4 object.
193 *
194 * @const IMG4_SECTION_MANIFEST
195 * The manifest section.
196 *
197 * @const IMG4_SECTION_OBJECT
198 * The object section.
199 *
200 * @const IMG4_SECTION_RESTOREINFO
201 * The restore info section.
202 */
203 OS_ENUM(img4_section, uint8_t,
204 IMG4_SECTION_MANIFEST,
205 IMG4_SECTION_OBJECT,
206 IMG4_SECTION_RESTOREINFO,
207 ) IMG4_API_AVAILABLE_20180112;
208
209 /*!
210 * @typedef img4_destructor_t
211 * A type describing a destructor routine for an Image4 object.
212 *
213 * @param ptr
214 * A pointer to the buffer to dispose of.
215 *
216 * @param len
217 * The length of the buffer.
218 */
219 IMG4_API_AVAILABLE_20180112
220 typedef void (*img4_destructor_t)(
221 void *ptr,
222 size_t len);
223
224 /*!
225 * @typedef img4_flags_t
226 * A flagset modifying the behavior of an {@link img4_t}.
227 *
228 * @const I4F_INIT
229 * No flags set. This value is suitable for initialization purposes.
230 *
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
234 * it.
235 *
236 * This option is for testing purposes only and is not respected on the RELEASE
237 * variant of the implementation.
238 *
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.
244 *
245 * This option is for testing purposes only and is not respected on the RELEASE
246 * variant of the implementation.
247 *
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.
254 *
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.
259 *
260 * It is illegal to use a manifest which possesses a CHMH tag as a first-stage
261 * manifest.
262 */
263 OS_CLOSED_OPTIONS(img4_flags, uint64_t,
264 I4F_INIT = 0,
265 I4F_TRUST_MANIFEST = (1 << 0),
266 I4F_FORCE_MIXNMATCH = (1 << 1),
267 I4F_FIRST_STAGE = (1 << 2),
268 ) IMG4_API_AVAILABLE_20180112;
269
270 typedef char _img4_opaque_data_64[696];
271
272 typedef char _img4_opaque_data_32[520];
273
274 /*!
275 * @typedef img4_t
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.
279 */
280 IMG4_API_AVAILABLE_20180112
281 typedef struct _img4 {
282 #if __ILP64__ || __LP64__
283 _img4_opaque_data_64 __opaque;
284 #else
285 _img4_opaque_data_32 __opaque;
286 #endif
287 } img4_t;
288
289 typedef char _img4_payload_opaque_data_64[504];
290
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];
294 #else
295 typedef char _img4_payload_opaque_data_32[332];
296 #endif
297
298 /*!
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.
302 */
303 IMG4_API_AVAILABLE_20180112
304 typedef struct _img4_payload {
305 #if __ILP64__ || __LP64__
306 _img4_payload_opaque_data_64 __opaque;
307 #else
308 _img4_payload_opaque_data_32 __opaque;
309 #endif
310 } img4_payload_t;
311
312 #if !IMG4_PROJECT_BUILD
313 #include <img4/environment.h>
314 #include <img4/nonce.h>
315 #include <img4/payload.h>
316 #endif
317
318 #if IMG4_TAPI
319 #include "environment.h"
320 #include "nonce.h"
321 #include "payload.h"
322 #endif
323
324 /*!
325 * @function img4_init
326 * Initializes an Image4.
327 *
328 * @param i4
329 * A pointer to the storage to initialize.
330 *
331 * @param flags
332 * Flags to modify initialization.
333 *
334 * @param bytes
335 * The Image4 data from which to initialize. If a destructor is provided,
336 * control of this buffer transfers to the Image4.
337 *
338 * @param len
339 * The length of the Image4 data.
340 *
341 * @param destructor
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).
344 *
345 * @result
346 * Upon success, zero is returned. The implementation may also return one of the
347 * following error codes directly:
348 *
349 * [EILSEQ] The data is not valid Image4 data
350 * [EFTYPE] The data does not contain an Image4 manifest
351 *
352 * @discussion
353 * The bytes given to this routine must represent an Image4 manifest. They may
354 * optionally also represent an Image4 payload.
355 */
356 #if !XNU_KERNEL_PRIVATE
357 IMG4_API_AVAILABLE_20180112
358 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
359 errno_t
360 img4_init(img4_t *i4, img4_flags_t flags, const uint8_t *bytes, size_t len,
361 img4_destructor_t destructor);
362 #else
363 #define img4_init(...) (img4if->i4if_init(__VA_ARGS__))
364 #endif
365
366 /*!
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.
370 *
371 * @param i4
372 * The Image4 to modify.
373 *
374 * @param bytes
375 * The bytes which comprise the anti-replay token.
376 *
377 * @param len
378 * The length of the anti-replay token.
379 *
380 * @discussion
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.
386 */
387 #if !XNU_KERNEL_PRIVATE
388 IMG4_API_AVAILABLE_20180112
389 OS_EXPORT OS_NONNULL1 OS_NONNULL2
390 void
391 img4_set_nonce(img4_t *i4, const void *bytes, size_t len);
392 #else
393 #define img4_set_nonce(...) (img4if->i4if_set_nonce(__VA_ARGS__))
394 #endif
395
396 /*!
397 * @function img4_set_nonce_domain
398 * Sets the nonce domain to be consulted for the anti-replay token during
399 * manifest enforcement.
400 *
401 * @param i4
402 * The Image4 to modify.
403 *
404 * @param nd
405 * The nonce domain to use for anti-replay.
406 *
407 * @discussion
408 * See discussion for {@link img4_set_nonce}.
409 */
410 #if !XNU_KERNEL_PRIVATE
411 IMG4_API_AVAILABLE_20181106
412 OS_EXPORT OS_NONNULL1 OS_NONNULL2
413 void
414 img4_set_nonce_domain(img4_t *i4, const img4_nonce_domain_t *nd);
415 #else
416 #define img4_set_nonce_domain(...) \
417 (img4if->i4if_v1.set_nonce_domain(__VA_ARGS__))
418 #endif
419
420 /*!
421 * @function img4_get_trusted_payload
422 * Obtains the trusted payload bytes from the Image4.
423 *
424 * @param i4
425 * The Image4 to query.
426 *
427 * @param tag
428 * The tag for the payload to obtain.
429 *
430 * @param env
431 * The environment against which to validate the Image4.
432 *
433 * @param bytes
434 * A pointer to the storage where the pointer to the payload buffer will be
435 * written on success.
436 *
437 * @param len
438 * A pointer to the storage where the length of the payload buffer will be
439 * written on success.
440 *
441 * @result
442 * Upon success, zero is returned. The implementation may also return one of the
443 * following error codes directly:
444 *
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
448 * constraints
449 * [ESTALE] The nonce specified is not valid
450 * [EACCES] The environment and manifest do not agree on a digest
451 * algorithm
452 * [EILSEQ] The payload for the given tag does not match its description
453 * in the manifest
454 * [EIO] The payload could not be fetched
455 *
456 * Additionally, errors from the routines specified in the
457 * {@link img4_environment_t} may be returned.
458 *
459 * @discussion
460 * This routine will perform the following validation:
461 *
462 * 1. Validate that the Image4 manifest is authentic (i.e. was signed by
463 * Apple)
464 * 2. Validate that the given environment satisfies the constraints in the
465 * manifest
466 * 3. Validate that the measurement of the payload for the given tag matches
467 * the measurement in the manifest
468 *
469 * If any one of these validation checks fails, the payload is considered
470 * untrustworthy and is not returned.
471 */
472 #if !XNU_KERNEL_PRIVATE
473 IMG4_API_AVAILABLE_20180112
474 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3 OS_NONNULL4 OS_NONNULL5
475 errno_t
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);
478 #else
479 #define img4_get_trusted_payload(...) \
480 (img4if->i4if_get_trusted_payload(__VA_ARGS__))
481 #endif
482
483 /*!
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.
487 *
488 * @param i4
489 * The Image4 to query.
490 *
491 * @param payload
492 * The payload to validate.
493 *
494 * @param env
495 * The environment against which to validate the Image4.
496 *
497 * @param bytes
498 * A pointer to the storage where the pointer to the payload buffer will be
499 * written on success.
500 *
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.
504 *
505 * @param len
506 * A pointer to the storage where the length of the payload buffer will be
507 * written on success.
508 *
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.
512 *
513 * @result
514 * Upon success, zero is returned. The implementation may also return one of the
515 * following error codes directly:
516 *
517 * [ENOENT] The Image4 does not contain an object describing the given
518 * payload
519 * [EAUTH] The Image4 manifest was not authentic
520 * [EACCES] The environment given does not satisfy the manifest
521 * constraints
522 * [ESTALE] The nonce specified is not valid
523 * [EACCES] The environment and manifest do not agree on a digest
524 * algorithm
525 * [EILSEQ] The payload for the given tag does not match its description
526 * in the manifest
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
531 * tolerance
532 *
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.
536 *
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.
540 *
541 * Otherwise, an error from the underlying Image4 implementation will be
542 * returned.
543 *
544 * @discussion
545 * This routine performs the same validation steps as
546 * {@link img4_get_trusted_payload}.
547 */
548 #if !XNU_KERNEL_PRIVATE
549 IMG4_API_AVAILABLE_20180112
550 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3
551 errno_t
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);
554 #else
555 #define img4_get_trusted_external_payload(...) \
556 (img4if->i4if_get_trusted_external_payload(__VA_ARGS__))
557 #endif
558
559 /*!
560 * @function img4_destroy
561 * Destroys an Image4 and disposes of associated resources.
562 *
563 * @param i4
564 * The Image4 to destroy.
565 *
566 * @discussion
567 * The destructor passed to {@link img4_init} is called as a result of this
568 * routine, if any was set.
569 */
570 #if !XNU_KERNEL_PRIVATE
571 IMG4_API_AVAILABLE_20180112
572 OS_EXPORT OS_NONNULL1
573 void
574 img4_destroy(img4_t *i4);
575 #else
576 #define img4_destroy(...) (img4if->i4if_destroy(__VA_ARGS__))
577 #endif
578
579 __END_DECLS;
580
581 #endif // __IMG4_H