xref: /xnu-8792.81.2/EXTERNAL_HEADERS/img4/nonce.h (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
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 /*!
53  * @typedef img4_nonce_domain_t
54  * An opaque type describing a nonce domain.
55  */
56 IMG4_API_AVAILABLE_20181106
57 typedef struct _img4_nonce_domain img4_nonce_domain_t;
58 
59 /*!
60  * @const IMG4_NONCE_STRUCT_VERSION
61  * The version of the {@link img4_nonce_t} structure supported by the
62  * implementation.
63  */
64 #define IMG4_NONCE_STRUCT_VERSION ((img4_struct_version_t)0)
65 #define IMG4_NONCE_VERSION IMG4_NONCE_STRUCT_VERSION
66 
67 /*!
68  * @const IMG4_NONCE_MAX_LENGTH
69  * The maximum length of a nonce. Currently, this is the length of a SHA2-384
70  * hash.
71  */
72 #define IMG4_NONCE_MAX_LENGTH (48u)
73 
74 /*!
75  * @typedef img4_nonce_domain_index_t
76  * An enumeration describing nonce domains.
77  *
78  * @const IMG4_NONCE_DOMAIN_INDEX_TEST
79  * The enumerated constant corresponding to the internal test nonce domain.
80  *
81  * @const IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE
82  * The enumerated constant corresponding to
83  * {@link IMG4_NONCE_DOMAIN_TRUST_CACHE}.
84  *
85  * @const IMG4_NONCE_DOMAIN_INDEX_PDI
86  * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_TRUST_PDI}.
87  *
88  * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX
89  * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_CRYPTEX}.
90  *
91  * @const IMG4_NONCE_DOMAIN_INDEX_DDI
92  * The enumerated constant corresponding to {@link IMG4_NONCE_DOMAIN_DDI}.
93  *
94  * @const IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX
95  * The enumerated constant corresponding to
96  * {@link IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX}.
97  *
98  * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB
99  * The enumerated constant corresponding to
100  * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB}.
101  *
102  * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT
103  * The enumerated constant corresponding to
104  * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT}.
105  *
106  * @const IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET
107  * The enumerated constant corresponding to
108  * {@link IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET}.
109  *
110  * @const _IMG4_NONCE_DOMAIN_INDEX_CNT
111  * A sentinel value indicating the number of nonce domains.
112  */
113 IMG4_API_AVAILABLE_20210521
114 OS_CLOSED_ENUM(img4_nonce_domain_index, uint64_t,
115 	IMG4_NONCE_DOMAIN_INDEX_TEST = 0,
116 	IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE,
117 	IMG4_NONCE_DOMAIN_INDEX_PDI,
118 	IMG4_NONCE_DOMAIN_INDEX_CRYPTEX,
119 	IMG4_NONCE_DOMAIN_INDEX_DDI,
120 	IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX,
121 	IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_SNUF_STUB,
122 	IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_BOOT,
123 	IMG4_NONCE_DOMAIN_INDEX_CRYPTEX1_ASSET,
124 	_IMG4_NONCE_DOMAIN_INDEX_CNT,
125 );
126 
127 /*!
128  * @typedef img4_nonce_t
129  * A structure describing a nonce.
130  *
131  * @field i4n_version
132  * The version of the structure. When declaring this structure, you must
133  * initialize this field to {@link IMG4_NONCE_VERSION}.
134  *
135  * @field i4n_nonce
136  * The bytes comprising the nonce.
137  *
138  * @field i4n_length
139  * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}.
140  *
141  * @discussion
142  * The {@link i4n_nonce} field was previously const. This was a terrible idea,
143  * and the const storage qualifier was removed without adjusting the structure
144  * version.
145  */
146 IMG4_API_AVAILABLE_20181106
147 typedef struct _img4_nonce {
148 	img4_struct_version_t i4n_version;
149 	uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH];
150 	uint32_t i4n_length;
151 } img4_nonce_t;
152 
153 /*!
154  * @const IMG4_NONCE_INIT
155  * A convenience initializer for {@link img4_nonce_t} which ensures that the
156  * {@link i4n_version} field is properly initialized.
157  */
158 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
159 #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION}
160 #elif defined(__cplusplus) && __cplusplus >= 201103L
161 #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION})
162 #elif defined(__cplusplus)
163 #define IMG4_NONCE_INIT \
164 		(img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION}))
165 #else
166 #define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION}
167 #endif
168 
169 /*!
170  * @const IMG4_NONCE_ZERO
171  * A convenience initializer for {@link img4_nonce_t} which initializes a 48-
172  * byte nonce of all zeroes.
173  */
174 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
175 #define IMG4_NONCE_ZERO (img4_nonce_t){ \
176 	.i4n_version = IMG4_NONCE_STRUCT_VERSION, \
177 	.i4n_nonce = {0}, \
178 	.i4n_length = IMG4_NONCE_MAX_LENGTH, \
179 }
180 #endif
181 
182 /*!
183  * @const IMG4_NONCE_DOMAIN_TRUST_CACHE
184  * The nonce domain governing trust cache personalizations. Use of this domain
185  * requires the
186  *
187  *     com.apple.private.img4.nonce.trust-cache
188  *
189  * entitlement.
190  */
191 #if !XNU_KERNEL_PRIVATE
192 IMG4_API_AVAILABLE_20181106
193 OS_EXPORT
194 const struct _img4_nonce_domain _img4_nonce_domain_trust_cache;
195 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache)
196 #else
197 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache)
198 #endif
199 
200 /*!
201  * @const IMG4_NONCE_DOMAIN_PDI
202  * The nonce domain governing disk image personalizations. Use of this domain
203  * requires the
204  *
205  *     com.apple.private.img4.nonce.pdi
206  *
207  * entitlement. The nonce for this domain is regenerated once every boot.
208  */
209 #if !XNU_KERNEL_PRIVATE
210 IMG4_API_AVAILABLE_20181106
211 OS_EXPORT
212 const struct _img4_nonce_domain _img4_nonce_domain_pdi;
213 #define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi)
214 #else
215 #define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi)
216 #endif
217 
218 /*!
219  * @const IMG4_NONCE_DOMAIN_CRYPTEX
220  * The nonce domain governing cryptex personalizations. Use of this domain
221  * requires the
222  *
223  *     com.apple.private.img4.nonce.cryptex
224  *
225  * entitlement.
226  */
227 #if !XNU_KERNEL_PRIVATE
228 IMG4_API_AVAILABLE_20181106
229 OS_EXPORT
230 const struct _img4_nonce_domain _img4_nonce_domain_cryptex;
231 #define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex)
232 #else
233 #define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex)
234 #endif
235 
236 /*!
237  * @const IMG4_NONCE_DOMAIN_DDI
238  * The nonce domain governing developer disk image personalizations. Use of this
239  * domain requires the
240  *
241  *     com.apple.private.img4.nonce.ddi
242  *
243  * entitlement.
244  */
245 #if !XNU_KERNEL_PRIVATE
246 IMG4_API_AVAILABLE_20181106
247 OS_EXPORT
248 const struct _img4_nonce_domain _img4_nonce_domain_ddi;
249 #define IMG4_NONCE_DOMAIN_DDI (&_img4_nonce_domain_ddi)
250 #else
251 #define IMG4_NONCE_DOMAIN_DDI (img4if->i4if_v12.nonce_domain_ddi)
252 #endif
253 
254 /*!
255  * @const IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX
256  * The nonce domain governing ephemeral cryptex personalizations. Use of this
257  * domain requires the
258  *
259  *     com.apple.private.img4.nonce.ephemeral-cryptex
260  *
261  * entitlement.
262  */
263 #if !XNU_KERNEL_PRIVATE
264 IMG4_API_AVAILABLE_20210305
265 OS_EXPORT
266 const struct _img4_nonce_domain _img4_nonce_domain_ephemeral_cryptex;
267 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
268 		(&_img4_nonce_domain_ephemeral_cryptex)
269 #else
270 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
271 		(img4if->i4if_v12.nonce_domain_ephemeral_cryptex)
272 #endif
273 
274 /*!
275  * @const IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB
276  * The nonce domain which acts as a null stub for the snuf value for Cryptex1
277  * processors. This domain corresponds to a value of 0 for the
278  * Cryptex1,NonceDomain tag. Use of this domain requires the
279  *
280  *     com.apple.private.img4.nonce.cryptex1.snuf-stub
281  *
282  * entitlement.
283  */
284 #if !XNU_KERNEL_PRIVATE
285 IMG4_API_AVAILABLE_20220322
286 OS_EXPORT
287 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_snuf_stub;
288 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \
289 		(&_img4_nonce_domain_cryptex1_snuf_stub)
290 #else
291 #define IMG4_NONCE_DOMAIN_CRYPTEX1_SNUF_STUB \
292 		(img4if->i4if_v18.nonce_domain_cryptex1_snuf_stub)
293 #endif
294 
295 /*!
296  * @const IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT
297  * The nonce domain governing personalizations for the virtual Cryptex1
298  * coprocessor's boot objects. This domain corresponds to a value of 1 for the
299  * Cryptex1,NonceDomain tag. Use of this domain requires the
300  *
301  *     com.apple.private.img4.nonce.cryptex1.boot
302  *
303  * entitlement.
304  */
305 #if !XNU_KERNEL_PRIVATE
306 IMG4_API_AVAILABLE_20211112
307 OS_EXPORT
308 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_boot;
309 #define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \
310 		(&_img4_nonce_domain_cryptex1_boot)
311 #else
312 #define IMG4_NONCE_DOMAIN_CRYPTEX1_BOOT \
313 		(img4if->i4if_v16.nonce_domain_cryptex1_boot)
314 #endif
315 
316 /*!
317  * @const IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET
318  * The nonce domain governing personalizations for the virtual Cryptex1
319  * coprocessor's asset brain objects. This domain corresponds to a value of 2
320  * for the Cryptex1,NonceDomain tag. Use of this domain requires the
321  *
322  *     com.apple.private.img4.nonce.cryptex1.asset
323  *
324  * entitlement.
325  */
326 #if !XNU_KERNEL_PRIVATE
327 IMG4_API_AVAILABLE_20211112
328 OS_EXPORT
329 const struct _img4_nonce_domain _img4_nonce_domain_cryptex1_asset;
330 #define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \
331 		(&_img4_nonce_domain_cryptex1_asset)
332 #else
333 #define IMG4_NONCE_DOMAIN_CRYPTEX1_ASSET \
334 		(img4if->i4if_v16.nonce_domain_cryptex1_asset)
335 #endif
336 
337 /*!
338  * @function img4_nonce_domain_copy_nonce
339  * Copies the current value of the nonce in the given domain.
340  *
341  * @param nd
342  * The nonce domain.
343  *
344  * @param n
345  * Upon successful return, storage that will contain the current nonce. The
346  * provided structure's {@link i4n_version} must be initialized to
347  * {@link IMG4_NONCE_VERSION}.
348  *
349  * @result
350  * Upon success, zero is returned. The implementation may also return one of the
351  * following error codes directly:
352  *
353  *     [ESTALE]     The nonce for the given domain has been invalidated, and the
354  *                  host must reboot in order to generate a new one
355  *     [EPERM]      The caller lacked the entitlement necessary to read the
356  *                  given nonce
357  *     [ENOTSUP]    Nonce management is not available on the host
358  *     [EACCES]     The nonce requested is not accessible in this environment
359  */
360 #if !XNU_KERNEL_PRIVATE
361 IMG4_API_AVAILABLE_20210305
362 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
363 errno_t
364 img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
365 #else
366 #define img4_nonce_domain_copy_nonce(...) \
367 		(img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__))
368 #endif
369 
370 /*!
371  * @function img4_nonce_domain_roll_nonce
372  * Invalidates the current nonce for the given domain and forces a re-generation
373  * of the domain's nonce seed at the next boot.
374  *
375  * @param nd
376  * The nonce domain.
377  *
378  * @result
379  * Upon success, zero is returned. The kernel implementation will never return
380  * a non-zero code. The userspace implementation may return one of the following
381  * error codes directly:
382  *
383  *     [EPERM]      The caller lacked the entitlement necessary to roll the
384  *                  given nonce
385  *     [EROFS]      The boot mode didn't allow committing to non-volatile storage
386  *     [ENOTSUP]    Nonce management is not available on the host
387  *     [EACCES]     The nonce requested is not accessible in this environment
388  */
389 #if !XNU_KERNEL_PRIVATE
390 IMG4_API_AVAILABLE_20181106
391 OS_EXPORT OS_WARN_RESULT OS_NONNULL1
392 errno_t
393 img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd);
394 #else
395 #define img4_nonce_domain_roll_nonce(...) \
396 		(img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__))
397 #endif
398 
399 /*!
400  * @function img4_nonce_domain_preroll_nonce
401  * Generates a new nonce seed and returns the resulting hash. The new nonce seed
402  * will be in force at the next reboot if and only if the boot manifest hash
403  * changes. Otherwise, the current nonce seed value will remain stable (modulo
404  * the regeneration policy associated with its domain).
405  *
406  * @param nd
407  * The nonce domain.
408  *
409  * @param n
410  * Upon successful return, storage that will contain the current nonce. The
411  * provided structure's {@link i4n_version} must be initialized to
412  * {@link IMG4_NONCE_VERSION}.
413  *
414  * @result
415  * Upon success, zero is returned. The kernel implementation will never return
416  * a non-zero code. The userspace implementation may return one of the following
417  * error codes directly:
418  *
419  *     [EPERM]      The caller lacked the entitlement necessary to roll the
420  *                  given nonce
421  *     [EROFS]      The boot mode didn't allow committing to non-volatile storage
422  *     [ENOTSUP]    Nonce management is not available on the host
423  *     [EACCES]     The nonce requested is not accessible in this environment
424  */
425 #if !XNU_KERNEL_PRIVATE
426 IMG4_API_AVAILABLE_FALL_2021_B
427 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
428 errno_t
429 img4_nonce_domain_preroll_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
430 #else
431 #define img4_nonce_domain_preroll_nonce(...) \
432 		(img4if->i4if_v14.nonce_domain_preroll_nonce(__VA_ARGS__))
433 #endif
434 
435 #endif // __IMG4_NONCE_H
436