1/*!
2 * @header
3 * Provides an interface for managing nonces to govern the lifetime of a
4 * personalization performed with TSS. A nonce managed by this interface may
5 * be used in a TSS signing request as the value for the BNCH tag.
6 *
7 * These interfaces require the caller to possess the
8 *
9 * com.apple.private.security.AppleImage4.user-client
10 *
11 * entitlement.
12 *
13 * @section Threat Model
14 * The adversary possesses the following:
15 *
16 * 1. a manifest which was previously valid but has since been invalidated
17 * by rolling the nonce associated with it
18 * 2. user-level code execution
19 * 3. knowledge of the raw nonce value for the previously-valid manifest
20 *
21 * The defense against this adversary is a system in which knowledge of the raw
22 * nonce is insufficient to impact the evaluation of a personalization. This
23 * system has the following characteristics:
24 *
25 * 1. A nonce seed is stored in an nvram variable which is only writable by
26 * the kernel
27 * 2. When making a new signing request, the nonce seed is encrypted by a
28 * UID1-derived key in-kernel and then hashed -- the output of this
29 * operation the nonce to be used in the signing request
30 * 3. On boot, AppleImage4 obtains the nonce seed from nvram and stores it
31 * in a data structure which will be covered by KTRR
32 * 4. When evaluating a manifest, AppleImage4 reads the raw nonce from the
33 * KTRR-covered data structure and validates it with the same
34 * transformation as was done in (2)
35 * 5. When the nonce is to be invalidated, AppleImage4 sets a flag in an
36 * nvram variable which is only writable by the kernel
37 * 6. On the subsequent boot, AppleImage4 notices the flag, generates a new
38 * nonce and repeats the procedure in (3)
39 *
40 * In this system, the raw nonce seed never leaves the kernel, and the nonce
41 * itself is a non-reversible representation of the seed.
42 */
43
44
45#ifndef __IMG4_NONCE_H
46#define __IMG4_NONCE_H
47
48#ifndef __IMG4_INDIRECT
49#error "Please #include <img4/firmware.h> instead of this file directly"
50#endif // __IMG4_INDIRECT
51
52__BEGIN_DECLS
53OS_ASSUME_NONNULL_BEGIN
54OS_ASSUME_PTR_ABI_SINGLE_BEGIN
55
56/*!
57 * @typedef img4_nonce_domain_t
58 * An opaque type describing a nonce domain.
59 */
60IMG4_API_AVAILABLE_20181106
61typedef struct _img4_nonce_domain img4_nonce_domain_t;
62
63/*!
64 * @const IMG4_NONCE_STRUCT_VERSION
65 * The version of the {@link img4_nonce_t} structure supported by the
66 * implementation.
67 */
68#define IMG4_NONCE_STRUCT_VERSION ((img4_struct_version_t)0)
69#define IMG4_NONCE_VERSION IMG4_NONCE_STRUCT_VERSION
70
71/*!
72 * @const IMG4_NONCE_MAX_LENGTH
73 * The maximum length of a nonce. Currently, this is the length of a SHA2-384
74 * hash.
75 */
76#define IMG4_NONCE_MAX_LENGTH (48u)
77
78/*!
79 * @typedef img4_nonce_domain_index_t
80 * An enumeration describing nonce domains.
81 *
82 * @const IMG4_NONCE_DOMAIN_INDEX_TEST
83 * The enumerated constant corresponding to the internal test nonce domain.
84 *
85 * @const IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE
86 * The enumerated constant corresponding to
87 * {@link IMG4_NONCE_DOMAIN_TRUST_CACHE}.
88 *
89 * @const IMG4_NONCE_DOMAIN_INDEX_PDI
90 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_TRUST_PDI}.
91 *
92 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX
93 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_CRYPTEX}.
94 *
95 * @const IMG4_NONCE_DOMAIN_INDEX_DDI
96 * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_DDI}.
97 *
98 * @const IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX
99 * The enumerated constant corresponding to
100 * {@link IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX}.
101 *
102 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB
103 * The enumerated constant corresponding to
104 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB}.
105 *
106 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT
107 * The enumerated constant corresponding to
108 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT}.
109 *
110 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET
111 * The enumerated constant corresponding to
112 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET}.
113 *
114 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_GENERIC
115 * The enumerated constant corresponding to
116 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC}.
117 *
118 * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SIMULATOR
119 * The enumerated constant corresponding to
120 * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR}.
121 *
122 * @const _IMG4_NONCE_DOMAIN_INDEX_CNT
123 * A sentinel value indicating the number of nonce domains.
124 */
125IMG4_API_AVAILABLE_20210521
126OS_CLOSED_ENUM(img4_nonce_domain_index, uint64_t,
127 IMG4_NONCE_DOMAIN_INDEX_TEST = 0,
128 IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE,
129 IMG4_NONCE_DOMAIN_INDEX_PDI,
130 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX,
131 IMG4_NONCE_DOMAIN_INDEX_DDI,
132 IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX,
133 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB,
134 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT,
135 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET,
136 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_GENERIC,
137 IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SIMULATOR,
138 _IMG4_NONCE_DOMAIN_INDEX_CNT,
139);
140
141/*!
142 * @typedef img4_nonce_t
143 * A structure describing a nonce.
144 *
145 * @field i4n_version
146 * The version of the structure. When declaring this structure, you must
147 * initialize this field to {@link IMG4_NONCE_VERSION}.
148 *
149 * @field i4n_nonce
150 * The bytes comprising the nonce.
151 *
152 * @field i4n_length
153 * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}.
154 *
155 * @discussion
156 * The {@link i4n_nonce} field was previously const. This was a terrible idea,
157 * and the const storage qualifier was removed without adjusting the structure
158 * version.
159 */
160IMG4_API_AVAILABLE_20181106
161typedef struct _img4_nonce {
162 img4_struct_version_t i4n_version;
163 uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH];
164 uint32_t i4n_length;
165} img4_nonce_t;
166
167/*!
168 * @const IMG4_NONCE_INIT
169 * A convenience initializer for {@link img4_nonce_t} which ensures that the
170 * {@link i4n_version} field is properly initialized.
171 */
172#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
173#define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION}
174#elif defined(__cplusplus) && __cplusplus >= 201103L
175#define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION})
176#elif defined(__cplusplus)
177#define IMG4_NONCE_INIT \
178 (img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION}))
179#else
180#define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION}
181#endif
182
183/*!
184 * @const IMG4_NONCE_ZERO
185 * A convenience initializer for {@link img4_nonce_t} which initializes a 48-
186 * byte nonce of all zeroes.
187 */
188#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
189#define IMG4_NONCE_ZERO (img4_nonce_t){ \
190 .i4n_version = IMG4_NONCE_STRUCT_VERSION, \
191 .i4n_nonce = {0}, \
192 .i4n_length = IMG4_NONCE_MAX_LENGTH, \
193}
194#endif
195
196/*!
197 * @const IMG4_NONCE_DOMAIN_TRUST_CACHE
198 * The nonce domain governing trust cache personalizations. Use of this domain
199 * requires the
200 *
201 * com.apple.private.img4.nonce.trust-cache
202 *
203 * entitlement.
204 */
205#if !XNU_KERNEL_PRIVATE
206IMG4_API_AVAILABLE_20181106
207OS_EXPORT
208const struct _img4_nonce_domain _img4_nonce_domain_trust_cache;
209#define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache)
210#else
211#define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache)
212#endif
213
214/*!
215 * @const IMG4_NONCE_DOMAIN_PDI
216 * The nonce domain governing disk image personalizations. Use of this domain
217 * requires the
218 *
219 * com.apple.private.img4.nonce.pdi
220 *
221 * entitlement. The nonce for this domain is regenerated once every boot.
222 */
223#if !XNU_KERNEL_PRIVATE
224IMG4_API_AVAILABLE_20181106
225OS_EXPORT
226const struct _img4_nonce_domain _img4_nonce_domain_pdi;
227#define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi)
228#else
229#define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi)
230#endif
231
232/*!
233 * @const IMG4_NONCE_DOMAIN_CRYPTEX
234 * The nonce domain governing cryptex personalizations. Use of this domain
235 * requires the
236 *
237 * com.apple.private.img4.nonce.cryptex
238 *
239 * entitlement.
240 */
241#if !XNU_KERNEL_PRIVATE
242IMG4_API_AVAILABLE_20181106
243OS_EXPORT
244const struct _img4_nonce_domain _img4_nonce_domain_cryptex;
245#define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex)
246#else
247#define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex)
248#endif
249
250/*!
251 * @const IMG4_NONCE_DOMAIN_DDI
252 * The nonce domain governing developer disk image personalizations. Use of this
253 * domain requires the
254 *
255 * com.apple.private.img4.nonce.ddi
256 *
257 * entitlement.
258 */
259#if !XNU_KERNEL_PRIVATE
260IMG4_API_AVAILABLE_20181106
261OS_EXPORT
262const struct _img4_nonce_domain _img4_nonce_domain_ddi;
263#define IMG4_NONCE_DOMAIN_DDI (&_img4_nonce_domain_ddi)
264#else
265#define IMG4_NONCE_DOMAIN_DDI (img4if->i4if_v12.nonce_domain_ddi)
266#endif
267
268/*!
269 * @const IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX
270 * The nonce domain governing ephemeral cryptex personalizations. Use of this
271 * domain requires the
272 *
273 * com.apple.private.img4.nonce.ephemeral-cryptex
274 *
275 * entitlement.
276 */
277#if !XNU_KERNEL_PRIVATE
278IMG4_API_AVAILABLE_20210305
279OS_EXPORT
280const struct _img4_nonce_domain _img4_nonce_domain_ephemeral_cryptex;
281#define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
282 (&_img4_nonce_domain_ephemeral_cryptex)
283#else
284#define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
285 (img4if->i4if_v12.nonce_domain_ephemeral_cryptex)
286#endif
287
288/*!
289 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB
290 * The nonce domain which acts as a null stub for the snuf value for Cryptex1
291 * processors. This domain corresponds to a value of 0 for the
292 * Cryptex1,NonceDomain tag. Use of this domain requires the
293 *
294 * com.apple.private.img4.nonce.cryptex1.snuf-stub
295 *
296 * entitlement.
297 */
298#if !XNU_KERNEL_PRIVATE
299IMG4_API_AVAILABLE_20220322
300OS_EXPORT
301const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_snuf_stub;
302#define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \
303 (&_img4_nonce_domain_cryptex1_snuf_stub)
304#else
305#define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \
306 (img4if->i4if_v18.nonce_domain_cryptex1_snuf_stub)
307#endif
308
309/*!
310 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT
311 * The nonce domain governing personalizations for the virtual Cryptex1
312 * coprocessor's boot objects. This domain corresponds to a value of 1 for the
313 * Cryptex1,NonceDomain tag. Use of this domain requires the
314 *
315 * com.apple.private.img4.nonce.cryptex1.boot
316 *
317 * entitlement.
318 */
319#if !XNU_KERNEL_PRIVATE
320IMG4_API_AVAILABLE_20211112
321OS_EXPORT
322const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_boot;
323#define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \
324 (&_img4_nonce_domain_cryptex1_boot)
325#else
326#define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \
327 (img4if->i4if_v16.nonce_domain_cryptex1_boot)
328#endif
329
330/*!
331 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET
332 * The nonce domain governing personalizations for the virtual Cryptex1
333 * coprocessor's asset brain objects. This domain corresponds to a value of 2
334 * for the Cryptex1,NonceDomain tag. Use of this domain requires the
335 *
336 * com.apple.private.img4.nonce.cryptex1.asset
337 *
338 * entitlement.
339 */
340#if !XNU_KERNEL_PRIVATE
341IMG4_API_AVAILABLE_20211112
342OS_EXPORT
343const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_asset;
344#define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \
345 (&_img4_nonce_domain_cryptex1_asset)
346#else
347#define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \
348 (img4if->i4if_v16.nonce_domain_cryptex1_asset)
349#endif
350
351/*!
352 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC
353 * The nonce domain governing personalizations for the virtual Cryptex1
354 * coprocessor's generic supplemental objects. This domain corresponds to a
355 * value of 3 for the Cryptex1,NonceDomain tag. Use of this domain requires the
356 *
357 * com.apple.private.img4.nonce.cryptex1.supplemental
358 *
359 * entitlement.
360 */
361#if !XNU_KERNEL_PRIVATE
362IMG4_API_AVAILABLE_20221202
363OS_EXPORT
364const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_generic;
365#define IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC \
366 (&_img4_nonce_domain_cryptex1_generic)
367#else
368#define IMG4_NONCE_DOMAIN_CRYPTEX1_GENERIC \
369 (img4if->i4if_v20.nonce_domain_cryptex1_generic)
370#endif
371
372/*!
373 * @const IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR
374 * The nonce domain governing personalizations for the virtual Cryptex1
375 * coprocessor's Simulator runtime objects. This domain corresponds to a value
376 * of 4 for the Cryptex1,NonceDomain tag. Use of this domain requires the
377 *
378 * com.apple.private.img4.nonce.cryptex1.simulator
379 *
380 * entitlement.
381 */
382#if !XNU_KERNEL_PRIVATE
383IMG4_API_AVAILABLE_20221202
384OS_EXPORT
385const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_simulator;
386#define IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR \
387 (&_img4_nonce_domain_cryptex1_simulator)
388#else
389#define IMG4_NONCE_DOMAIN_CRYPTEX1_SIMULATOR \
390 (img4if->i4if_v20.nonce_domain_cryptex1_simulator)
391#endif
392
393/*!
394 * @function img4_nonce_domain_copy_nonce
395 * Copies the current value of the nonce in the given domain.
396 *
397 * @param nd
398 * The nonce domain.
399 *
400 * @param n
401 * Upon successful return, storage that will contain the current nonce. The
402 * provided structure's {@link i4n_version} must be initialized to
403 * {@link IMG4_NONCE_VERSION}.
404 *
405 * @result
406 * Upon success, zero is returned. The implementation may also return one of the
407 * following error codes directly:
408 *
409 * [ESTALE] The nonce for the given domain has been invalidated, and the
410 * host must reboot in order to generate a new one
411 * [EPERM] The caller lacked the entitlement necessary to read the
412 * given nonce
413 * [ENOTSUP] Nonce management is not available on the host
414 * [EACCES] The nonce requested is not accessible in this environment
415 */
416#if !XNU_KERNEL_PRIVATE
417IMG4_API_AVAILABLE_20210305
418OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
419errno_t
420img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
421#else
422#define img4_nonce_domain_copy_nonce(...) \
423 (img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__))
424#endif
425
426/*!
427 * @function img4_nonce_domain_roll_nonce
428 * Invalidates the current nonce for the given domain and forces a re-generation
429 * of the domain's nonce seed at the next boot.
430 *
431 * @param nd
432 * The nonce domain.
433 *
434 * @result
435 * Upon success, zero is returned. The kernel implementation will never return
436 * a non-zero code. The userspace implementation may return one of the following
437 * error codes directly:
438 *
439 * [EPERM] The caller lacked the entitlement necessary to roll the
440 * given nonce
441 * [EROFS] The boot mode didn't allow committing to non-volatile storage
442 * [ENOTSUP] Nonce management is not available on the host
443 * [EACCES] The nonce requested is not accessible in this environment
444 */
445#if !XNU_KERNEL_PRIVATE
446IMG4_API_AVAILABLE_20181106
447OS_EXPORT OS_WARN_RESULT OS_NONNULL1
448errno_t
449img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd);
450#else
451#define img4_nonce_domain_roll_nonce(...) \
452 (img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__))
453#endif
454
455/*!
456 * @function img4_nonce_domain_preroll_nonce
457 * Generates a new nonce seed and returns the resulting hash. The new nonce seed
458 * will be in force at the next reboot if and only if the boot manifest hash
459 * changes. Otherwise, the current nonce seed value will remain stable (modulo
460 * the regeneration policy associated with its domain).
461 *
462 * @param nd
463 * The nonce domain.
464 *
465 * @param n
466 * Upon successful return, storage that will contain the current nonce. The
467 * provided structure's {@link i4n_version} must be initialized to
468 * {@link IMG4_NONCE_VERSION}.
469 *
470 * @result
471 * Upon success, zero is returned. The kernel implementation will never return
472 * a non-zero code. The userspace implementation may return one of the following
473 * error codes directly:
474 *
475 * [EPERM] The caller lacked the entitlement necessary to roll the
476 * given nonce
477 * [EROFS] The boot mode didn't allow committing to non-volatile storage
478 * [ENOTSUP] Nonce management is not available on the host
479 * [EACCES] The nonce requested is not accessible in this environment
480 */
481#if !XNU_KERNEL_PRIVATE
482IMG4_API_AVAILABLE_FALL_2021_B
483OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
484errno_t
485img4_nonce_domain_preroll_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
486#else
487#define img4_nonce_domain_preroll_nonce(...) \
488 (img4if->i4if_v14.nonce_domain_preroll_nonce(__VA_ARGS__))
489#endif
490
491/*!
492 * @function img4_nonce_domain_peek_nonce
493 * Copies the current proposed value of a nonce domain.
494 *
495 * @param nd
496 * The nonce domain.
497 *
498 * @param n
499 * Upon successful return, storage that will contain the current proposed
500 * nonce. The provided structure's {@link i4n_version} must be initialized to
501 * {@link IMG4_NONCE_VERSION}.
502 *
503 * @result
504 * Upon success, zero is returned. The implementation may also return one of the
505 * following error codes directly:
506 *
507 * [EPERM] The caller lacked the entitlement necessary to roll the
508 * given nonce
509 * [ENOENT] The nonce doesn't have a proposed value
510 * [ENOTSUP] Nonce management is not available on the host
511 * [EACCES] The nonce requested is not accessible in this environment
512 */
513#if !XNU_KERNEL_PRIVATE
514IMG4_API_AVAILABLE_20220714
515OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
516errno_t
517img4_nonce_domain_peek_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
518#else
519#define img4_nonce_domain_peek_nonce(...) \
520 (img4if->i4if_v19.nonce_domain_peek_nonce(__VA_ARGS__))
521#endif
522
523/*!
524 * @function img4_nonce_domain_get_from_handle
525 * Obtains the nonce domain for the given integer handle.
526 *
527 * @param handle
528 * The nonce domain handle.
529 *
530 * @result
531 * The nonce domain associated with the provided handle. If no domain is
532 * associated with the handle, NULL is returned.
533 */
534#if !XNU_KERNEL_PRIVATE
535IMG4_API_AVAILABLE_20221202
536OS_EXPORT OS_WARN_RESULT
537const img4_nonce_domain_t *_Nullable
538img4_nonce_domain_get_from_handle(uint32_t handle);
539#else
540#define img4_nonce_domain_get_from_handle(...) \
541 (img4if->i4if_v20.nonce_domain_get_from_handle(__VA_ARGS__))
542#endif
543
544OS_ASSUME_PTR_ABI_SINGLE_END
545OS_ASSUME_NONNULL_END
546__END_DECLS
547
548#endif // __IMG4_NONCE_H
549