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 |
19 | typedef int errno_t; |
20 | #endif |
21 | |
22 | __BEGIN_DECLS |
23 | OS_ASSUME_NONNULL_BEGIN |
24 | OS_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 | */ |
39 | OS_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 | */ |
73 | OS_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 | */ |
106 | typedef 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 | */ |
132 | typedef 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 | */ |
177 | IMAGE4_API_AVAILABLE_SPRING_2024 |
178 | OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL4 |
179 | image4_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) |
198 | IMAGE4_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 | */ |
233 | IMAGE4_API_AVAILABLE_SPRING_2024 |
234 | OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 |
235 | image4_trust_t *_Nullable |
236 | image4_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); |
242 | IMAGE4_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 | */ |
270 | IMAGE4_API_AVAILABLE_SPRING_2024 |
271 | OS_EXPORT OS_NONNULL1 OS_NONNULL3 |
272 | void |
273 | image4_trust_set_payload( |
274 | image4_trust_t *trst, |
275 | uint32_t type, |
276 | const void *__sized_by(len) bytes, |
277 | size_t len); |
278 | IMAGE4_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 | */ |
312 | IMAGE4_API_AVAILABLE_SPRING_2024 |
313 | OS_EXPORT OS_NONNULL1 OS_NONNULL2 |
314 | void |
315 | image4_trust_set_booter( |
316 | image4_trust_t *trst, |
317 | const image4_trust_t *booter); |
318 | IMAGE4_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 | */ |
356 | IMAGE4_API_AVAILABLE_SPRING_2024 |
357 | OS_EXPORT OS_NONNULL1 OS_NONNULL4 |
358 | void |
359 | image4_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); |
365 | IMAGE4_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 | */ |
407 | IMAGE4_API_AVAILABLE_SPRING_2024 |
408 | OS_EXPORT OS_NONNULL1 OS_NONNULL4 |
409 | void |
410 | image4_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); |
416 | IMAGE4_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 | */ |
458 | IMAGE4_API_AVAILABLE_SPRING_2024 |
459 | OS_EXPORT OS_NONNULL1 OS_NONNULL4 OS_NONNULL5 |
460 | void |
461 | image4_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); |
467 | IMAGE4_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 | */ |
484 | IMAGE4_API_AVAILABLE_SPRING_2024 |
485 | OS_EXPORT OS_NONNULL1 OS_NONNULL3 |
486 | void |
487 | image4_trust_evaluate( |
488 | const image4_trust_t *trst, |
489 | void *_Nullable _ctx, |
490 | image4_trust_evaluation_result_t result); |
491 | IMAGE4_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 | */ |
505 | IMAGE4_API_AVAILABLE_SPRING_2024 |
506 | OS_EXPORT OS_NONNULL1 |
507 | void |
508 | image4_trust_destroy( |
509 | image4_trust_t *_Nonnull *_Nullable trst); |
510 | IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_destroy); |
511 | |
512 | OS_ASSUME_PTR_ABI_SINGLE_END |
513 | OS_ASSUME_NONNULL_END |
514 | __END_DECLS |
515 | |
516 | #endif // __IMAGE4_API_TRUST_H |
517 | |