]> git.saurik.com Git - apple/xnu.git/blob - EXTERNAL_HEADERS/img4/img4.h
c3faf5a28351c5c47e35a3c4e74d50cb04a35182
[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 #define __IMG4_INDIRECT 1
141
142 /*
143 * This header is used in the pmap layer in xnu, which is in osfmk, which does
144 * not have access to most of the BSD headers. (But for some reason it does have
145 * access to sys/cdefs.h.) The only thing we need from that header is the
146 * errno_t typedef though, so if we can't get to it, then just typedef it
147 * ourselves.
148 */
149 #if MACH_KERNEL_PRIVATE
150 typedef int errno_t;
151 #else
152 #include <sys/types.h>
153 #endif
154
155 #if !IMG4_PROJECT_BUILD
156 #include <img4/api.h>
157 #endif
158
159 __BEGIN_DECLS;
160
161 /*!
162 * @typedef img4_tag_t
163 * A type describing an Image4 tag.
164 */
165 IMG4_API_AVAILABLE_20180112
166 typedef uint32_t img4_tag_t;
167
168 /*!
169 * @typedef img4_section_t
170 * A type describing the sections of an Image4 object.
171 *
172 * @const IMG4_SECTION_MANIFEST
173 * The manifest section.
174 *
175 * @const IMG4_SECTION_OBJECT
176 * The object section.
177 *
178 * @const IMG4_SECTION_RESTOREINFO
179 * The restore info section.
180 */
181 OS_ENUM(img4_section, uint8_t,
182 IMG4_SECTION_MANIFEST,
183 IMG4_SECTION_OBJECT,
184 IMG4_SECTION_RESTOREINFO,
185 ) IMG4_API_AVAILABLE_20180112;
186
187 /*!
188 * @typedef img4_destructor_t
189 * A type describing a destructor routine for an Image4 object.
190 *
191 * @param ptr
192 * A pointer to the buffer to dispose of.
193 *
194 * @param len
195 * The length of the buffer.
196 */
197 IMG4_API_AVAILABLE_20180112
198 typedef void (*img4_destructor_t)(
199 void *ptr,
200 size_t len);
201
202 /*!
203 * @typedef img4_flags_t
204 * A flagset modifying the behavior of an {@link img4_t}.
205 *
206 * @const I4F_INIT
207 * No flags set. This value is suitable for initialization purposes.
208 *
209 * @const I4F_TRUST_MANIFEST
210 * Causes the implementation to bypass trust evaluation for the manifest, i.e.
211 * it will not verify that a manifest has been signed by Apple before trusting
212 * it.
213 *
214 * This option is for testing purposes only and is not respected on the RELEASE
215 * variant of the implementation.
216 *
217 * @const I4F_FORCE_MIXNMATCH
218 * Causes the implementation to bypass mix-n-match policy evaluation and always
219 * allow mix-n-match, irrespective of the previous boot stage's conclusion or
220 * manifest policy. This also allows replay of manifests whose personalization
221 * has been invalidated by rolling the nonce.
222 *
223 * This option is for testing purposes only and is not respected on the RELEASE
224 * variant of the implementation.
225 *
226 * @const I4F_FIRST_STAGE
227 * Indicates that the manifest being evaluated is the first link in the secure
228 * boot chain. This causes the implementation to enforce the manifest directly
229 * on the environment rather than requiring that a previous stage has already
230 * done so by way of checking the previous stage's boot manifest hash. In effect
231 * this disables the mix-n-match enforcement policy.
232 *
233 * The critical difference between this flag and {@link I4F_FORCE_MIXNMATCH} is
234 * that this flag will cause the entire manifest to be enforced on the
235 * environment, including the anti-replay token in BNCH.
236 * {@link I4F_FORCE_MIXNMATCH} will ignore the nonce.
237 *
238 * It is illegal to use a manifest which possesses a CHMH tag as a first-stage
239 * manifest.
240 */
241 OS_ENUM(img4_flags, uint64_t,
242 I4F_INIT = 0,
243 I4F_TRUST_MANIFEST = (1 << 0),
244 I4F_FORCE_MIXNMATCH = (1 << 1),
245 I4F_FIRST_STAGE = (1 << 2),
246 ) IMG4_API_AVAILABLE_20180112;
247
248 typedef char _img4_opaque_data_64[696];
249
250 typedef char _img4_opaque_data_32[520];
251
252 /*!
253 * @typedef img4_t
254 * An opaque structure representing Image4 data. The Image4 data must contain a
255 * manifest and may optionally contain a payload. Neither this type nor the APIs
256 * APIs which manipulate it are thread-safe.
257 */
258 IMG4_API_AVAILABLE_20180112
259 typedef struct _img4 {
260 #if __ILP64__ || __LP64__
261 _img4_opaque_data_64 __opaque;
262 #else
263 _img4_opaque_data_32 __opaque;
264 #endif
265 } img4_t;
266
267 typedef char _img4_payload_opaque_data_64[496];
268
269 #if __ARM_ARCH_7S__ || __i386__
270 typedef char _img4_payload_opaque_data_32[324];
271 #else
272 typedef char _img4_payload_opaque_data_32[328];
273 #endif
274
275 /*!
276 * @typedef img4_payload_t
277 * An opaque structure describing Image4 payload data. Neither this type nor the
278 * APIs which manipulate it are thread-safe.
279 */
280 IMG4_API_AVAILABLE_20180112
281 typedef struct _img4_payload {
282 #if __ILP64__ || __LP64__
283 _img4_payload_opaque_data_64 __opaque;
284 #else
285 _img4_payload_opaque_data_32 __opaque;
286 #endif
287 } img4_payload_t;
288
289 #if !IMG4_PROJECT_BUILD
290 #include <img4/environment.h>
291 #include <img4/nonce.h>
292 #include <img4/payload.h>
293 #endif
294
295 #if IMG4_TAPI
296 #include "environment.h"
297 #include "nonce.h"
298 #include "payload.h"
299 #endif
300
301 /*!
302 * @function img4_init
303 * Initializes an Image4.
304 *
305 * @param i4
306 * A pointer to the storage to initialize.
307 *
308 * @param flags
309 * Flags to modify initialization.
310 *
311 * @param bytes
312 * The Image4 data from which to initialize. If a destructor is provided,
313 * control of this buffer transfers to the Image4.
314 *
315 * @param len
316 * The length of the Image4 data.
317 *
318 * @param destructor
319 * A destructor for the Image4 data. May be NULL if the buffer does not require
320 * explicit deallocation (e.g. because the buffer is stack data).
321 *
322 * @result
323 * Upon success, zero is returned. The implementation may also return one of the
324 * following error codes directly:
325 *
326 * [EILSEQ] The data is not valid Image4 data
327 * [EFTYPE] The data does not contain an Image4 manifest
328 *
329 * @discussion
330 * The bytes given to this routine must represent an Image4 manifest. They may
331 * optionally also represent an Image4 payload.
332 */
333 #if !MACH_KERNEL_PRIVATE
334 IMG4_API_AVAILABLE_20180112
335 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
336 errno_t
337 img4_init(img4_t *i4, img4_flags_t flags, const uint8_t *bytes, size_t len,
338 img4_destructor_t destructor);
339 #else
340 #define img4_init(...) (img4if->i4if_init(__VA_ARGS__))
341 #endif
342
343 /*!
344 * @function img4_set_nonce
345 * Sets the anti-reply token to be used during manifest enforcement. This value
346 * will be compared against the value of the manifest's BNCH property.
347 *
348 * @param i4
349 * The Image4 to modify.
350 *
351 * @param bytes
352 * The bytes which comprise the anti-replay token.
353 *
354 * @param len
355 * The length of the anti-replay token.
356 *
357 * @discussion
358 * If a nonce is not set prior to a call to either
359 * {@link img4_get_trusted_payload} or
360 * {@link img4_get_trusted_external_payload}, the implementation will act as
361 * though there is no nonce in the environment. Therefore, any manifests which
362 * have a BNCH property constraint will fail to validate.
363 */
364 #if !MACH_KERNEL_PRIVATE
365 IMG4_API_AVAILABLE_20180112
366 OS_EXPORT OS_NONNULL1 OS_NONNULL2
367 void
368 img4_set_nonce(img4_t *i4, const void *bytes, size_t len);
369 #else
370 #define img4_set_nonce(...) (img4if->i4if_set_nonce(__VA_ARGS__))
371 #endif
372
373 /*!
374 * @function img4_set_nonce_domain
375 * Sets the nonce domain to be consulted for the anti-replay token during
376 * manifest enforcement.
377 *
378 * @param i4
379 * The Image4 to modify.
380 *
381 * @param nd
382 * The nonce domain to use for anti-replay.
383 *
384 * @discussion
385 * See discussion for {@link img4_set_nonce}.
386 */
387 #if !MACH_KERNEL_PRIVATE
388 IMG4_API_AVAILABLE_20181106
389 OS_EXPORT OS_NONNULL1 OS_NONNULL2
390 void
391 img4_set_nonce_domain(img4_t *i4, const img4_nonce_domain_t *nd);
392 #else
393 #define img4_set_nonce_domain(...) \
394 (img4if->i4if_v1.set_nonce_domain(__VA_ARGS__))
395 #endif
396
397 /*!
398 * @function img4_get_trusted_payload
399 * Obtains the trusted payload bytes from the Image4.
400 *
401 * @param i4
402 * The Image4 to query.
403 *
404 * @param tag
405 * The tag for the payload to obtain.
406 *
407 * @param env
408 * The environment against which to validate the Image4.
409 *
410 * @param bytes
411 * A pointer to the storage where the pointer to the payload buffer will be
412 * written on success.
413 *
414 * @param len
415 * A pointer to the storage where the length of the payload buffer will be
416 * written on success.
417 *
418 * @result
419 * Upon success, zero is returned. The implementation may also return one of the
420 * following error codes directly:
421 *
422 * [ENOENT] The Image4 does not contain a payload for the specified tag
423 * [EAUTH] The Image4 manifest was not authentic
424 * [EACCES] The environment given does not satisfy the manifest
425 * constraints
426 * [ESTALE] The nonce specified is not valid
427 * [EACCES] The environment and manifest do not agree on a digest
428 * algorithm
429 * [EILSEQ] The payload for the given tag does not match its description
430 * in the manifest
431 * [EIO] The payload could not be fetched
432 *
433 * Additionally, errors from the routines specified in the
434 * {@link img4_environment_t} may be returned.
435 *
436 * @discussion
437 * This routine will perform the following validation:
438 *
439 * 1. Validate that the Image4 manifest is authentic (i.e. was signed by
440 * Apple)
441 * 2. Validate that the given environment satisfies the constraints in the
442 * manifest
443 * 3. Validate that the measurement of the payload for the given tag matches
444 * the measurement in the manifest
445 *
446 * If any one of these validation checks fails, the payload is considered
447 * untrustworthy and is not returned.
448 */
449 #if !MACH_KERNEL_PRIVATE
450 IMG4_API_AVAILABLE_20180112
451 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3 OS_NONNULL4 OS_NONNULL5
452 errno_t
453 img4_get_trusted_payload(img4_t *i4, img4_tag_t tag,
454 const img4_environment_t *env, const uint8_t **bytes, size_t *len);
455 #else
456 #define img4_get_trusted_payload(...) \
457 (img4if->i4if_get_trusted_payload(__VA_ARGS__))
458 #endif
459
460 /*!
461 * @function img4_get_trusted_external_payload
462 * Obtains the trusted payload bytes from the external Image4 payload after
463 * validating them against the object description in the Image4's manifest.
464 *
465 * @param i4
466 * The Image4 to query.
467 *
468 * @param payload
469 * The payload to validate.
470 *
471 * @param env
472 * The environment against which to validate the Image4.
473 *
474 * @param bytes
475 * A pointer to the storage where the pointer to the payload buffer will be
476 * written on success.
477 *
478 * @param len
479 * A pointer to the storage where the length of the payload buffer will be
480 * written on success.
481 *
482 * @result
483 * Upon success, zero is returned. The implementation may also return one of the
484 * following error codes directly:
485 *
486 * [ENOENT] The Image4 does not contain an object describing the given
487 * payload
488 * [EAUTH] The Image4 manifest was not authentic
489 * [EACCES] The environment given does not satisfy the manifest
490 * constraints
491 * [ESTALE] The nonce specified is not valid
492 * [EACCES] The environment and manifest do not agree on a digest
493 * algorithm
494 * [EILSEQ] The payload for the given tag does not match its description
495 * in the manifest
496 * [EIO] The payload could not be fetched
497 *
498 * Otherwise, an error from the underlying Image4 implementation will be
499 * returned.
500 *
501 * @discussion
502 * This routine performs the same validation steps as
503 * {@link img4_get_trusted_payload}.
504 */
505 #if !MACH_KERNEL_PRIVATE
506 IMG4_API_AVAILABLE_20180112
507 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL4
508 OS_NONNULL5
509 errno_t
510 img4_get_trusted_external_payload(img4_t *i4, img4_payload_t *payload,
511 const img4_environment_t *env, const uint8_t **bytes, size_t *len);
512 #else
513 #define img4_get_trusted_external_payload(...) \
514 (img4if->i4if_get_trusted_external_payload(__VA_ARGS__))
515 #endif
516
517 /*!
518 * @function img4_destroy
519 * Destroys an Image4 and disposes of associated resources.
520 *
521 * @param i4
522 * The Image4 to destroy.
523 *
524 * @discussion
525 * The destructor passed to {@link img4_init} is called as a result of this
526 * routine, if any was set.
527 */
528 #if !MACH_KERNEL_PRIVATE
529 IMG4_API_AVAILABLE_20180112
530 OS_EXPORT OS_NONNULL1
531 void
532 img4_destroy(img4_t *i4);
533 #else
534 #define img4_destroy(...) (img4if->i4if_destroy(__VA_ARGS__))
535 #endif
536
537 __END_DECLS;
538
539 #endif // __IMG4_H