1/*!
2 * @header
3 * Encapsulation which describes an Image4 trust object. This object can perform
4 * an evaluation in the context of a given environment, record properties that
5 * were encountered during evaluation, and deliver the evaluation result to the
6 * caller according to the type of evaluation being performed.
7 */
8#ifndef __IMAGE4_API_TRUST_H
9#define __IMAGE4_API_TRUST_H
10
11#include <image4/image4.h>
12#include <image4/types.h>
13#include <stdint.h>
14#include <stdbool.h>
15
16#if __has_include(<sys/types.h>)
17#include <sys/types.h>
18#else
19typedef int errno_t;
20#endif
21
22__BEGIN_DECLS
23OS_ASSUME_NONNULL_BEGIN
24OS_ASSUME_PTR_ABI_SINGLE_BEGIN
25
26#pragma mark Supporting Types
27/*!
28 * @typedef image4_trust_flags_t
29 * Flags that may be provided to influence the behavior of an
30 * {@link image4_trust_t} object.
31 *
32 * @const IMAGE4_TRUST_FLAG_INIT
33 * No flags set. This value is suitable for initialization purposes.
34 *
35 * @const IMAGE4_TRUST_FLAG_VIOLATION_PANIC
36 * Upon encountering a violation during trust evaluation, the implementation
37 * should abort the current context.
38 */
39OS_CLOSED_OPTIONS(image4_trust_flags, uint64_t,
40 IMAGE4_TRUST_FLAG_INIT = 0,
41 IMAGE4_TRUST_FLAG_VIOLATION_PANIC = (1 << 0),
42);
43
44/*!
45 * @typedef image4_trust_section_t
46 * An enumeration of property sections in an Image4 manifest or object. Note
47 * that this is not strictly aligned with the concept of a "section" as defined
48 * in the Image4 specification.
49 *
50 * @const IMAGE4_TRUST_SECTION_CERTIFICATE
51 * The certificate properties within the manifest section.
52 *
53 * @const IMAGE4_TRUST_SECTION_MANIFEST
54 * The top-level properties in the manifest section.
55 *
56 * @const IMAGE4_TRUST_SECTION_OBJECT
57 * The properties associated with a particular object in the manifest section.
58 *
59 * @const IMAGE4_TRUST_SECTION_RESTORE_INFO
60 * The top-level properties in the RestoreInfo section. The RestoreInfo section
61 * is only recognized by the implementation when the trust object has been
62 * initialized with an IMG4 object that contains an IM4R section.
63 *
64 * This constant first became available in API version 20231103.
65 *
66 * @const IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES
67 * The properties associated with the payload that is associated with the trust
68 * object, either by initializing the object with an IMG4 object, or by setting
69 * a payload with {@link image4_trust_set_payload}.
70 *
71 * This constant first became available in API version 20231103.
72 */
73OS_CLOSED_ENUM(image4_trust_section, uint64_t,
74 IMAGE4_TRUST_SECTION_CERTIFICATE,
75 IMAGE4_TRUST_SECTION_MANIFEST,
76 IMAGE4_TRUST_SECTION_OBJECT,
77 IMAGE4_TRUST_SECTION_RESTORE_INFO,
78 IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES,
79 _IMAGE4_TRUST_SECTION_CNT,
80);
81
82/*!
83 * @typedef image4_trust_evaluation_result_t
84 * A callback for the result of a trust evaluation.
85 *
86 * @param trst
87 * The trust object.
88 *
89 * @param result
90 * Upon success, the prescribed payload resulting from the type of trust
91 * evaluation. If the trust evaluation type does not deliver a payload, or the
92 * trust evaluation failed, NULL will be passed.
93 *
94 * @param result_len
95 * The length of the buffer referenced by {@link payload}. If {@link payload} is
96 * NULL, zero will be passed.
97 *
98 * @param error
99 * A POSIX error code describing the result of the trust evaluation. Upon
100 * success, zero will be passed.
101 *
102 * @param context
103 * The caller-provided context pointer. If no context pointer was set, NULL will
104 * be passed.
105 */
106typedef void (*image4_trust_evaluation_result_t)(
107 const image4_trust_t *trst,
108 const void *_Nullable result,
109 size_t result_len,
110 errno_t error,
111 void *_Nullable context
112);
113
114/*!
115 * @const IMAGE4_TRUST_STRUCT_VERSION
116 * The version of the {@link image4_trust_t} structure supported by the
117 * implementation.
118 */
119#define IMAGE4_TRUST_STRUCT_VERSION (0u)
120
121/*!
122 * @header image4_trust_storage_t
123 * An opaque structure which is guaranteed to be large enough to accommodate an
124 * {@link image4_trust_t}.
125 *
126 * @field __opaque
127 * The opaque storage.
128 *
129 * @discussion
130 * The size of this object was set in API version 20231103.
131 */
132typedef struct _image4_trust_storage {
133 uint8_t __opaque[1920];
134} image4_trust_storage_t;
135
136/*!
137 * @const IMAGE4_TRUST_STORAGE_INIT
138 * Initializer for a {@link image4_trust_storage_t} object.
139 */
140#define IMAGE4_TRUST_STORAGE_INIT (image4_trust_storage_t){ \
141 .__opaque = { 0x00 }, \
142}
143
144#pragma mark API
145/*!
146 * @function image4_trust_init
147 * Convert a {@link image4_trust_storage_t} to an initialized
148 * {@link image4_trust_t} object.
149 *
150 * @param storage
151 * The storage structure.
152 *
153 * @param environment
154 * The environment in which the trust evaluation should be performed.
155 *
156 * @param evaluation
157 * The trust evaluation type that should be performed.
158 *
159 * @param manifest
160 * A pointer to the Image4 manifest bytes. This buffer may refer to a stitched
161 * manifest and payload object, in which case the implementation will extract
162 * the manifest portion.
163 *
164 * These bytes are not copied into any implementation storage, and the caller is
165 * responsible for ensuring that this memory remains valid for the duration of
166 * the trust object's use.
167 *
168 * @param manifest_len
169 * The length of the buffer referenced by {@link manifest}.
170 *
171 * @param flags
172 * Flags to influence the behavior of the resulting trust object.
173 *
174 * @result
175 * An initialized {@link image4_trust_t} object.
176 */
177IMAGE4_API_AVAILABLE_SPRING_2024
178OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL4
179image4_trust_t *
180_image4_trust_init(
181 image4_trust_storage_t *storage,
182 const image4_environment_t *environment,
183 const image4_trust_evaluation_t *evaluation,
184 const void *__sized_by(manifest_len) manifest,
185 size_t manifest_len,
186 image4_trust_flags_t flags,
187 image4_struct_version_t v);
188#define image4_trust_init(_storage, _environment, _evaluation, \
189 _manifest, _manifest_len, _flags) \
190 _image4_trust_init( \
191 (_storage), \
192 (_environment), \
193 (_evaluation), \
194 (_manifest), \
195 (_manifest_len), \
196 (_flags), \
197 IMAGE4_TRUST_STRUCT_VERSION)
198IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_init);
199
200/*!
201 * @function image4_trust_new
202 * Allocates a trust object.
203 *
204 * @param nv
205 * The environment in which the trust evaluation should be performed.
206 *
207 * @param eval
208 * The trust evaluation type that should be performed.
209 *
210 * @param manifest
211 * A pointer to the Image4 manifest bytes. This buffer may refer to a stitched
212 * manifest and payload object, in which case the implementation will extract
213 * the manifest portion.
214 *
215 * These bytes are not copied into any implementation storage, and the caller is
216 * responsible for ensuring that this memory remains valid for the duration of
217 * the trust object's use.
218 *
219 * @param manifest_len
220 * The length of the buffer referenced by {@link manifest}.
221 *
222 * @param flags
223 * Flags to influence the behavior of the resulting trust object.
224 *
225 * @result
226 * A newly-allocated and initialized {@link image4_trust_t} object. The caller
227 * is responsible for disposing of this object with {@link image4_trust_destroy}
228 * when it is no longer needed.
229 *
230 * If insufficient resources were available to allocate the object, or if the
231 * host runtime does not have an allocator, NULL is returned.
232 */
233IMAGE4_API_AVAILABLE_SPRING_2024
234OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3
235image4_trust_t *_Nullable
236image4_trust_new(
237 const image4_environment_t *nv,
238 const image4_trust_evaluation_t *eval,
239 const void *__sized_by(manifest_len) manifest,
240 size_t manifest_len,
241 image4_trust_flags_t flags);
242IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_new);
243
244/*!
245 * @function image4_trust_set_payload
246 * Sets the payload to be used during the trust evaluation.
247 *
248 * @param trst
249 * The trust object.
250 *
251 * @param type
252 * The four-character code of the payload.
253 *
254 * @param bytes
255 * A pointer to the payload bytes to authenticate during trust evaluation. This
256 * buffer may refer to a stitched manifest and payload object, in which case the
257 * implementation will extract the payload portion.
258 *
259 * If the buffer does not refer to either a valid Image4 manifest or payload,
260 * the implementation will conclude that it is a bare Image4 payload -- that is,
261 * a payload which is not Image4-wrapped.
262 *
263 * These bytes are not copied into any implementation storage, and the caller is
264 * responsible for ensuring that this memory remains valid for the duration of
265 * the trust object's use.
266 *
267 * @param len
268 * The length of the buffer referenced by {@link bytes}.
269 */
270IMAGE4_API_AVAILABLE_SPRING_2024
271OS_EXPORT OS_NONNULL1 OS_NONNULL3
272void
273image4_trust_set_payload(
274 image4_trust_t *trst,
275 uint32_t type,
276 const void *__sized_by(len) bytes,
277 size_t len);
278IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_payload);
279
280/*!
281 * @function image4_trust_set_booter
282 * Establish a link between the trust object and another trust object
283 * representing a previous stage of boot, securing it to that stage of boot.
284 * This may be called multiple times. Successive calls secure the previously-
285 * specified booter stage to the newly-specified booter stage, establishing a
286 * chain of trust from the last stage to the first stage.
287 *
288 * @param trst
289 * The trust object. This object must have been created with one of the
290 * following trust evaluation types:
291 *
292 * - {@link IMAGE4_TRUST_EVALUATION_PREFLIGHT}
293 * - {@link IMAGE4_TRUST_EVALUATION_SIGN}
294 *
295 * @param booter
296 * The trust object representing the previous stage of boot for {@link trst}.
297 * This object must have been created with the
298 * {@link IMAGE4_TRUST_EVALUATION_BOOT} trust evaluation type.
299 *
300 * This object is not copied into any implementation storage, and the caller is
301 * responsible for ensuring that it remains valid for the duration of the trust
302 * object's use.
303 *
304 * @discussion
305 * Trust objects with booter stages cannot be used to execute firmware because
306 * they are only intended to simulate a boot by replicating side effects of
307 * previous evaluations into the ultimate environment used by the trust object.
308 *
309 * In order to execute firmware, the environment must be consistent with the
310 * requirements of the manifest without modifications being required.
311 */
312IMAGE4_API_AVAILABLE_SPRING_2024
313OS_EXPORT OS_NONNULL1 OS_NONNULL2
314void
315image4_trust_set_booter(
316 image4_trust_t *trst,
317 const image4_trust_t *booter);
318IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_booter);
319
320/*!
321 * @function image4_trust_record_property_bool
322 * Records the specified Boolean value into caller-provided storage.
323 *
324 * @param trst
325 * The trust object.
326 *
327 * @param type
328 * The type of property to be recorded (currently either manifest or object).
329 *
330 * @param tag
331 * The four character code of the property to capture.
332 *
333 * @param vp
334 * A pointer to the storage where the value should be written.
335 *
336 * @param vpp
337 * A pointer to storage where a pointer to the value should be written. This
338 * allows the caller to know whether the property was encountered during the
339 * trust evaluation at all. If the property was encountered, the storage
340 * referred to by this pointer will hold the same pointer given in the
341 * {@link vp} parameter.
342 *
343 * If the property was not encountered during trust evaluation, the contents of
344 * this storage are undefined. The caller should initialize the storage to a
345 * reasonable default.
346 *
347 * This may be NULL.
348 *
349 * @discussion
350 * If the property represented a constraint which was not satisfied, the
351 * implementation will not record its value.
352 *
353 * If the property associated with the given tag is present, but is not a
354 * Boolean, the implementation will not record its value.
355 */
356IMAGE4_API_AVAILABLE_SPRING_2024
357OS_EXPORT OS_NONNULL1 OS_NONNULL4
358void
359image4_trust_record_property_bool(
360 image4_trust_t *trst,
361 image4_trust_section_t type,
362 uint32_t tag,
363 bool *vp,
364 const bool *_Nullable *_Nullable vpp);
365IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_bool);
366
367/*!
368 * @function image4_trust_record_property_integer
369 * Records the specified unsigned integer value into caller-provided storage.
370 *
371 * @param trst
372 * The trust object.
373 *
374 * @param type
375 * The type of property to be recorded (currently either manifest or object).
376 *
377 * @param tag
378 * The four character code of the property to capture.
379 *
380 * @param vp
381 * A pointer to the storage where the value should be written.
382 *
383 * @param vpp
384 * A pointer to storage where a pointer to the value should be written. This
385 * allows the caller to know whether the property was encountered during the
386 * trust evaluation at all. If the property was encountered, the storage
387 * referred to by this pointer will hold the same pointer given in the
388 * {@link vp} parameter.
389 *
390 * If the property was not encountered during trust evaluation, the contents of
391 * this storage are undefined. The caller should initialize the storage to a
392 * reasonable default.
393 *
394 * This may be NULL.
395 *
396 * @discussion
397 * For boring implementation reasons, all integer properties are expressed as
398 * 64-bit unsigned integers. The caller is responsible for enforcing boundaries
399 * on the value recorded.
400 *
401 * If the property represented a constraint which was not satisfied, the
402 * implementation will not record its value.
403 *
404 * If the property associated with the given tag is present, but is not an
405 * integer, the implementation will not record its value.
406 */
407IMAGE4_API_AVAILABLE_SPRING_2024
408OS_EXPORT OS_NONNULL1 OS_NONNULL4
409void
410image4_trust_record_property_integer(
411 image4_trust_t *trst,
412 image4_trust_section_t type,
413 uint32_t tag,
414 uint64_t *vp,
415 const uint64_t *_Nullable *_Nullable vpp);
416IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_integer);
417
418/*!
419 * @function image4_trust_record_property_data
420 * Records a pointer to the specified octet string value into caller-provided
421 * storage.
422 *
423 * @param trst
424 * The trust object.
425 *
426 * @param type
427 * The type of property to be recorded (currently either manifest or object).
428 *
429 * @param tag
430 * The four character code of the property to capture.
431 *
432 * @param vp
433 * A pointer to the storage where the value should be written. The storage
434 * referenced by this pointer ultimately refers to the caller-provided memory
435 * which contains the Image4 manifest, and therefore its lifetime is tied to the
436 * caller's management of that storage.
437 *
438 * If the property was not encountered during trust evaluation, the contents of
439 * this storage are undefined. The caller should initialize the storage to a
440 * reasonable default.
441 *
442 * @param vp_len
443 * A pointer to the storage where the length of the octet string should be
444 * written.
445 *
446 * @discussion
447 * If the property represented a constraint which was not satisfied, the
448 * implementation will not record its value.
449 *
450 * If the property associated with the given tag is present, but is not an octet
451 * string, the implementation will not record its value.
452 *
453 * Properties which are intended to be used as C strings are represented in the
454 * manifest as simple octet strings which may or may not be null-terminated. The
455 * caller should take care to ensure null termination when the data is used,
456 * e.g. by copying the data into a local buffer using strlcpy(3).
457 */
458IMAGE4_API_AVAILABLE_SPRING_2024
459OS_EXPORT OS_NONNULL1 OS_NONNULL4 OS_NONNULL5
460void
461image4_trust_record_property_data(
462 image4_trust_t *trst,
463 image4_trust_section_t type,
464 uint32_t tag,
465 const void *_Nullable *_Nonnull vp,
466 size_t *vp_len);
467IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_data);
468
469/*!
470 * @function image4_trust_evaluate
471 * Perform the trust evaluation.
472 *
473 * @param trst
474 * The trust object.
475 *
476 * @param _ctx
477 * A context parameter to be delivered to the result callback.
478 *
479 * @param result
480 * The callback to invoke with the result of the trust evaluation. This callback
481 * is called directly inline from the implementation and must not re-enter the
482 * calling scope.
483 */
484IMAGE4_API_AVAILABLE_SPRING_2024
485OS_EXPORT OS_NONNULL1 OS_NONNULL3
486void
487image4_trust_evaluate(
488 const image4_trust_t *trst,
489 void *_Nullable _ctx,
490 image4_trust_evaluation_result_t result);
491IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_evaluate);
492
493/*!
494 * @function image4_trust_destroy
495 * Disposes a trust object which was created via {@link image4_trust_new}.
496 *
497 * @param nv
498 * A pointer to the trust object. Upon return, this storage will be set to NULL.
499 * If the object pointed to by this parameter is NULL, this is a no-op.
500 *
501 * @discussion
502 * If this routine is called on an environment object which was not allocated,
503 * it is a no-op.
504 */
505IMAGE4_API_AVAILABLE_SPRING_2024
506OS_EXPORT OS_NONNULL1
507void
508image4_trust_destroy(
509 image4_trust_t *_Nonnull *_Nullable trst);
510IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_destroy);
511
512OS_ASSUME_PTR_ABI_SINGLE_END
513OS_ASSUME_NONNULL_END
514__END_DECLS
515
516#endif // __IMAGE4_API_TRUST_H
517