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 * 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 * 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 * 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
74
75#ifndef __IMG4_H
76#define __IMG4_H
77
78#include <os/base.h>
79#include <stdint.h>
80#include <stdbool.h>
81#include <sys/cdefs.h>
82
83#define __IMG4_INDIRECT 1
84
85/*
86 * This header is used in the pmap layer in xnu, which is in osfmk, which does
87 * not have access to most of the BSD headers. (But for some reason it does have
88 * access to sys/cdefs.h.) The only thing we need from that header is the
89 * errno_t typedef though, so if we can't get to it, then just typeded it
90 * ourselves.
91 */
92#if MACH_KERNEL_PRIVATE
93typedef int errno_t;
94#else
95#include <sys/types.h>
96#endif
97
98#if !IMG4_PROJECT_BUILD
99#include <img4/api.h>
100#endif
101
102__BEGIN_DECLS;
103
104/*!
105 * @typedef img4_tag_t
106 * A type describing an Image4 tag.
107 */
108IMG4_API_AVAILABLE_20180112
109typedef uint32_t img4_tag_t;
110
111/*!
112 * @typedef img4_section_t
113 * A type describing the sections of an Image4 object.
114 *
115 * @const IMG4_SECTION_MANIFEST
116 * The manifest section.
117 *
118 * @const IMG4_SECTION_OBJECT
119 * The object section.
120 *
121 * @const IMG4_SECTION_RESTOREINFO
122 * The restore info section.
123 */
124OS_ENUM(img4_section, uint8_t,
125 IMG4_SECTION_MANIFEST,
126 IMG4_SECTION_OBJECT,
127 IMG4_SECTION_RESTOREINFO,
128) IMG4_API_AVAILABLE_20180112;
129
130/*!
131 * @typedef img4_custom_tag_handler_t
132 * A handler for a tag unrecognized by the implementation.
133 *
134 * @param tag
135 * The FourCC tag.
136 *
137 * @param ctx
138 * The user-provided context pointer given to either
139 * {@link img4_get_trusted_payload} or
140 * {@link img4_get_trusted_external_payload}.
141 */
142IMG4_API_AVAILABLE_20180112
143typedef errno_t (*img4_custom_tag_handler_t)(
144 img4_tag_t tag,
145 img4_section_t section,
146 void *ctx);
147
148/*!
149 * @typedef img4_custom_tag_t
150 * A type describing a custom tag and its handler.
151 *
152 * @property i4ct_tag
153 * The FourCC tag.
154 *
155 * @property i4ct_section
156 * The section in which the tag is expected. If {@link IMG4_SECTION_OBJECT} is
157 * given, the object corresponding to the tag given to
158 * {@link img4_get_trusted_payload} or {@link img4_get_trusted_external_payload}
159 * will be consulted for the tag.
160 *
161 * @property i4ct_handler
162 * The handler for the tag.
163 */
164IMG4_API_AVAILABLE_20180112
165typedef struct _img4_custom_tag {
166 img4_tag_t i4ct_tag;
167 img4_section_t i4ct_section;
168 img4_custom_tag_handler_t i4ct_handler;
169} img4_custom_tag_t;
170
171/*!
172 * @typedef img4_destructor_t
173 * A type describing a destructor routine for an Image4 object.
174 *
175 * @param ptr
176 * A pointer to the buffer to dispose of.
177 *
178 * @param len
179 * The length of the buffer.
180 */
181IMG4_API_AVAILABLE_20180112
182typedef void (*img4_destructor_t)(
183 void *ptr,
184 size_t len);
185
186/*!
187 * @typedef img4_flags_t
188 * A flagset modifying the behavior of an {@link img4_t}.
189 *
190 * @const I4F_INIT
191 * No flags set. This value is suitable for initialization purposes.
192 *
193 * @const I4F_TRUST_MANIFEST
194 * Causes the implementation to bypass trust evaluation for the manifest, i.e.
195 * it will not verify that a manifest has been signed by Apple before trusting
196 * it.
197 *
198 * This option is for testing purposes only and is not respected on the RELEASE
199 * variant of the implementation.
200 *
201 * @const I4F_FORCE_MIXNMATCH
202 * Causes the implementation to bypass mix-n-match policy evaluation and always
203 * allow mix-n-match, irrespective of the previous boot stage's conclusion or
204 * manifest policy.
205 *
206 * This option is for testing purposes only and is not respected on the RELEASE
207 * variant of the implementation.
208 */
209OS_ENUM(img4_flags, uint64_t,
210 I4F_INIT = 0,
211 I4F_TRUST_MANIFEST = (1 << 0),
212 I4F_FORCE_MIXNMATCH = (1 << 1),
213) IMG4_API_AVAILABLE_20180112;
214
215#if TARGET_OS_OSX || defined(PLATFORM_MacOSX)
216typedef char _img4_opaque_data_64[656];
217typedef char _img4_opaque_data_32[476];
218#elif TARGET_OS_IOS || defined(PLATFORM_iPhoneOS)
219typedef char _img4_opaque_data_64[656];
220typedef char _img4_opaque_data_32[476];
221#elif TARGET_OS_WATCH || defined(PLATFORM_WatchOS)
222typedef char _img4_opaque_data_64[656];
223typedef char _img4_opaque_data_32[488];
224#elif TARGET_OS_TV || defined(PLATFORM_tvOS) || defined(PLATFORM_AppleTVOS)
225typedef char _img4_opaque_data_64[656];
226typedef char _img4_opaque_data_32[476];
227#elif TARGET_OS_BRIDGE || defined(PLATFORM_BridgeOS)
228typedef char _img4_opaque_data_64[656];
229typedef char _img4_opaque_data_32[476];
230#else
231#error "Unsupported platform"
232#endif
233
234/*!
235 * @typedef img4_t
236 * An opaque structure representing Image4 data. The Image4 data must contain a
237 * manifest and may optionally contain a payload. Neither this type nor the APIs
238 * APIs which manipulate it are thread-safe.
239 */
240IMG4_API_AVAILABLE_20180112
241typedef struct _img4 {
242#if __ILP64__ || __LP64__
243 _img4_opaque_data_64 __opaque;
244#else
245 _img4_opaque_data_32 __opaque;
246#endif
247} img4_t;
248
249#if TARGET_OS_OSX || defined(PLATFORM_MacOSX)
250typedef char _img4_payload_opaque_data_64[488];
251typedef char _img4_payload_opaque_data_32[316];
252#elif TARGET_OS_IOS || defined(PLATFORM_iPhoneOS)
253typedef char _img4_payload_opaque_data_64[488];
254typedef char _img4_payload_opaque_data_32[316];
255#elif TARGET_OS_WATCH || defined(PLATFORM_WatchOS)
256typedef char _img4_payload_opaque_data_64[488];
257typedef char _img4_payload_opaque_data_32[316];
258#elif TARGET_OS_TV || defined(PLATFORM_tvOS) || defined(PLATFORM_AppleTVOS)
259typedef char _img4_payload_opaque_data_64[488];
260typedef char _img4_payload_opaque_data_32[316];
261#elif TARGET_OS_BRIDGE || defined(PLATFORM_BridgeOS)
262typedef char _img4_payload_opaque_data_64[488];
263typedef char _img4_payload_opaque_data_32[316];
264#else
265#error "Unsupported platform"
266#endif
267
268/*!
269 * @typedef img4_payload_t
270 * An opaque structure describing Image4 payload data. Neither this type nor the
271 * APIs which manipulate it are thread-safe.
272 */
273IMG4_API_AVAILABLE_20180112
274typedef struct _img4_payload {
275#if __ILP64__ || __LP64__
276 _img4_payload_opaque_data_64 __opaque;
277#else
278 _img4_payload_opaque_data_32 __opaque;
279#endif
280} img4_payload_t;
281
282#if !IMG4_PROJECT_BUILD
283#include <img4/environment.h>
284#include <img4/payload.h>
285#endif
286
287/*!
288 * @function img4_init
289 * Initializes an Image4.
290 *
291 * @param i4
292 * A pointer to the storage to initialize.
293 *
294 * @param flags
295 * Flags to modify initialization.
296 *
297 * @param bytes
298 * The Image4 data from which to initialize. If a destructor is provided,
299 * control of this buffer transfers to the Image4.
300 *
301 * @param len
302 * The length of the Image4 data.
303 *
304 * @param destructor
305 * A destructor for the Image4 data. May be NULL if the buffer does not require
306 * explicit deallocation (e.g. because the buffer is stack data).
307 *
308 * @result
309 * Upon success, zero is returned. The implementation may also return one of the
310 * following error codes directly:
311 *
312 * [EILSEQ] The data is not valid Image4 data
313 * [EFTYPE] The data does not contain an Image4 manifest
314 *
315 * @discussion
316 * The bytes given to this routine must represent an Image4 manifest. They may
317 * optionally also represent an Image4 payload.
318 */
319IMG4_API_AVAILABLE_20180112
320OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
321errno_t
322img4_init(img4_t *i4, img4_flags_t flags, const uint8_t *bytes, size_t len,
323 img4_destructor_t destructor);
324
325/*!
326 * @function img4_set_custom_tag_handler
327 * Sets custom tag handlers for an Image4. These handlers are invoked during
328 * trust evaluation of the Image4.
329 *
330 * @param i4
331 * The Image4 to modify.
332 *
333 * @param tags
334 * An array of custom tag structures which specify the custom tags expected.
335 * This must be constant storage. Passing heap or stack storage will result in
336 * undefined behavior.
337 *
338 * @param tags_cnt
339 * The number of items in the {@link tags} array.
340 *
341 * @discussion
342 * Invocations of custom tag handlers occur during trust evaluation. You should
343 * not assume that the Image4 is trusted within the scope of a custom tag
344 * handler. Trustworthiness can only be determined by consulting the return
345 * value of {@link img4_get_trusted_payload} or
346 * {@link img4_get_trusted_external_payload}.
347 */
348IMG4_API_AVAILABLE_20180112
349OS_EXPORT OS_NONNULL1 OS_NONNULL2
350void
351img4_set_custom_tag_handler(img4_t *i4,
352 const img4_custom_tag_t *tags, size_t tags_cnt);
353
354/*!
355 * @function img4_get_trusted_payload
356 * Obtains the trusted payload bytes from the Image4.
357 *
358 * @param i4
359 * The Image4 to query.
360 *
361 * @param tag
362 * The tag for the payload to obtain.
363 *
364 * @param env
365 * The environment against which to validate the Image4.
366 *
367 * @param ctx
368 * The context pointer to pass to the routines defined in the environment (if
369 * a custom environment was passed) and to any custom tag handlers.
370 *
371 * @param bytes
372 * A pointer to the storage where the pointer to the payload buffer will be
373 * written on success.
374 *
375 * @param len
376 * A pointer to the storage where the length of the payload buffer will be
377 * written on success.
378 *
379 * @result
380 * Upon success, zero is returned. The implementation may also return one of the
381 * following error codes directly:
382 *
383 * [ENOENT] The Image4 does not contain a payload for the specified tag
384 * [EAUTH] The Image4 manifest was not authentic
385 * [EACCES] The environment given does not satisfy the manifest
386 * constraints
387 * [EACCES] The environment and manifest do not agree on a digest
388 * algorithm
389 * [EILSEQ] The payload for the given tag does not match its description
390 * in the manifest
391 * [EIO] The payload could not be fetched
392 *
393 * Additionally, errors from the routines specified in the
394 * {@link img4_environment_t} may be returned.
395 *
396 * @discussion
397 * This routine will perform the following validation:
398 *
399 * 1. Validate that the Image4 manifest is authentic (i.e. was signed by
400 * Apple)
401 * 2. Validate that the given environment satisfies the constraints in the
402 * manifest
403 * 3. Validate that the measurement of the payload for the given tag matches
404 * the measurement in the manifest
405 *
406 * If any one of these validation checks fails, the payload is considered
407 * untrustworthy and is not returned.
408 */
409IMG4_API_AVAILABLE_20180112
410OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3 OS_NONNULL5 OS_NONNULL6
411errno_t
412img4_get_trusted_payload(img4_t *i4, img4_tag_t tag,
413 const img4_environment_t *env, void *ctx,
414 const uint8_t **bytes, size_t *len);
415
416/*!
417 * @function img4_get_trusted_external_payload
418 * Obtains the trusted payload bytes from the external Image4 payload after
419 * validating them against the object description in the Image4's manifest.
420 *
421 * @param i4
422 * The Image4 to query.
423 *
424 * @param payload
425 * The payload to validate.
426 *
427 * @param env
428 * The environment against which to validate the Image4.
429 *
430 * @param ctx
431 * The context pointer to pass to the routines defined in the environment and to
432 * any custom tag handlers.
433 *
434 * @param bytes
435 * A pointer to the storage where the pointer to the payload buffer will be
436 * written on success.
437 *
438 * @param len
439 * A pointer to the storage where the length of the payload buffer will be
440 * written on success.
441 *
442 * @result
443 * Upon success, zero is returned. The implementation may also return one of the
444 * following error codes directly:
445 *
446 * [ENOENT] The Image4 does not contain an object describing the given
447 * payload
448 * [EAUTH] The Image4 manifest was not authentic
449 * [EACCES] The environment given does not satisfy the manifest
450 * constraints
451 * [EACCES] The environment and manifest do not agree on a digest
452 * algorithm
453 * [EILSEQ] The payload for the given tag does not match its description
454 * in the manifest
455 * [EIO] The payload could not be fetched
456 *
457 * Otherwise, an error from the underlying Image4 implementation will be
458 * returned.
459 *
460 * @discussion
461 * This routine performs the same validation steps as
462 * {@link img4_get_trusted_payload}.
463 */
464IMG4_API_AVAILABLE_20180112
465OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
466errno_t
467img4_get_trusted_external_payload(img4_t *i4, img4_payload_t *payload,
468 const img4_environment_t *env, void *ctx,
469 const uint8_t **bytes, size_t *len);
470
471/*!
472 * @function img4_get_entitlement_bool
473 * Queries the Image4 manifest for a Boolean entitlement value.
474 *
475 * @param i4
476 * The Image4 to query.
477 *
478 * @param entitlement
479 * The tag for the entitlement to query.
480 *
481 * @result
482 * The Boolean value of the entitlement. If the entitlement was not present,
483 * false is returned. If the entitlement was present but did not have a Boolean
484 * value, false is returned.
485 *
486 * @discussion
487 * This routine does not trigger validation of the Image4. Therefore the result
488 * result of this routine cannot be used to confer trust without also having
489 * obtained a valid payload.
490 */
491IMG4_API_AVAILABLE_20180112
492OS_EXPORT OS_WARN_RESULT OS_NONNULL1
493bool
494img4_get_entitlement_bool(img4_t *i4, img4_tag_t entitlement);
495
496/*!
497 * @function img4_get_object_entitlement_bool
498 * Queries the specified object in the Image4 manifest for a Boolean entitlement
499 * value.
500 *
501 * @param i4
502 * The Image4 to query.
503 *
504 * @param object
505 * The tag for the object to query.
506 *
507 * @param entitlement
508 * The tag for the entitlement to query.
509 *
510 * @result
511 * The Boolean value of the entitlement. If the entitlement was not present,
512 * false is returned. If the entitlement was present but did not have a Boolean
513 * value, false is returned. If the object specified was not present, false is
514 * returned.
515 *
516 * @discussion
517 * See discussion for {@link img4_get_entitlement_bool}.
518 */
519IMG4_API_AVAILABLE_20180112
520OS_EXPORT OS_WARN_RESULT OS_NONNULL1
521bool
522img4_get_object_entitlement_bool(img4_t *i4, img4_tag_t object,
523 img4_tag_t entitlement);
524
525/*!
526 * @function img4_destroy
527 * Destroys an Image4 and disposes of associated resources.
528 *
529 * @param i4
530 * The Image4 to destroy.
531 *
532 * @discussion
533 * The destructor passed to {@link img4_init} is called as a result of this
534 * routine, if any was set.
535 */
536IMG4_API_AVAILABLE_20180112
537OS_EXPORT OS_NONNULL1
538void
539img4_destroy(img4_t *i4);
540
541__END_DECLS;
542
543#endif // __IMG4_H
544