xref: /xnu-8020.121.3/EXTERNAL_HEADERS/img4/nonce.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
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_CNT
99  * A sentinel value indicating the number of nonce domains.
100  */
101 IMG4_API_AVAILABLE_20210521
102 OS_CLOSED_ENUM(img4_nonce_domain_index, uint64_t,
103 	IMG4_NONCE_DOMAIN_INDEX_TEST = 0,
104 	IMG4_NONCE_DOMAIN_INDEX_TRUST_CACHE,
105 	IMG4_NONCE_DOMAIN_INDEX_PDI,
106 	IMG4_NONCE_DOMAIN_INDEX_CRYPTEX,
107 	IMG4_NONCE_DOMAIN_INDEX_DDI,
108 	IMG4_NONCE_DOMAIN_INDEX_EPHEMERAL_CRYPTEX,
109 	_IMG4_NONCE_DOMAIN_INDEX_CNT,
110 );
111 
112 /*!
113  * @typedef img4_nonce_t
114  * A structure describing a nonce.
115  *
116  * @field i4n_version
117  * The version of the structure. When declaring this structure, you must
118  * initialize this field to {@link IMG4_NONCE_VERSION}.
119  *
120  * @field i4n_nonce
121  * The bytes comprising the nonce.
122  *
123  * @field i4n_length
124  * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}.
125  */
126 IMG4_API_AVAILABLE_20181106
127 typedef struct _img4_nonce {
128 	img4_struct_version_t i4n_version;
129 	const uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH];
130 	uint32_t i4n_length;
131 } img4_nonce_t;
132 
133 /*!
134  * @const IMG4_NONCE_INIT
135  * A convenience initializer for {@link img4_nonce_t} which ensures that the
136  * {@link i4n_version} field is properly initialized.
137  */
138 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
139 #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION}
140 #elif defined(__cplusplus) && __cplusplus >= 201103L
141 #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION})
142 #elif defined(__cplusplus)
143 #define IMG4_NONCE_INIT \
144 		(img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION}))
145 #else
146 #define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION}
147 #endif
148 
149 /*!
150  * @const IMG4_NONCE_ZERO
151  * A convenience initializer for {@link img4_nonce_t} which initializes a 48-
152  * byte nonce of all zeroes.
153  */
154 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
155 #define IMG4_NONCE_ZERO (img4_nonce_t){ \
156 	.i4n_version = IMG4_NONCE_STRUCT_VERSION, \
157 	.i4n_nonce = {0}, \
158 	.i4n_length = IMG4_NONCE_MAX_LENGTH, \
159 }
160 #endif
161 
162 /*!
163  * @const IMG4_NONCE_DOMAIN_TRUST_CACHE
164  * The nonce domain governing trust cache personalizations. Use of this domain
165  * requires the
166  *
167  *     com.apple.private.img4.nonce.trust-cache
168  *
169  * entitlement.
170  */
171 #if !XNU_KERNEL_PRIVATE
172 IMG4_API_AVAILABLE_20181106
173 OS_EXPORT
174 const struct _img4_nonce_domain _img4_nonce_domain_trust_cache;
175 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache)
176 #else
177 #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache)
178 #endif
179 
180 /*!
181  * @const IMG4_NONCE_DOMAIN_PDI
182  * The nonce domain governing disk image personalizations. Use of this domain
183  * requires the
184  *
185  *     com.apple.private.img4.nonce.pdi
186  *
187  * entitlement. The nonce for this domain is regenerated once every boot.
188  */
189 #if !XNU_KERNEL_PRIVATE
190 IMG4_API_AVAILABLE_20181106
191 OS_EXPORT
192 const struct _img4_nonce_domain _img4_nonce_domain_pdi;
193 #define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi)
194 #else
195 #define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi)
196 #endif
197 
198 /*!
199  * @const IMG4_NONCE_DOMAIN_CRYPTEX
200  * The nonce domain governing cryptex personalizations. Use of this domain
201  * requires the
202  *
203  *     com.apple.private.img4.nonce.cryptex
204  *
205  * entitlement.
206  */
207 #if !XNU_KERNEL_PRIVATE
208 IMG4_API_AVAILABLE_20181106
209 OS_EXPORT
210 const struct _img4_nonce_domain _img4_nonce_domain_cryptex;
211 #define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex)
212 #else
213 #define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex)
214 #endif
215 
216 /*!
217  * @const IMG4_NONCE_DOMAIN_DDI
218  * The nonce domain governing developer disk image personalizations. Use of this
219  * domain requires the
220  *
221  *     com.apple.private.img4.nonce.ddi
222  *
223  * entitlement.
224  */
225 #if !XNU_KERNEL_PRIVATE
226 IMG4_API_AVAILABLE_20181106
227 OS_EXPORT
228 const struct _img4_nonce_domain _img4_nonce_domain_ddi;
229 #define IMG4_NONCE_DOMAIN_DDI (&_img4_nonce_domain_ddi)
230 #else
231 #define IMG4_NONCE_DOMAIN_DDI (img4if->i4if_v12.nonce_domain_ddi)
232 #endif
233 
234 /*!
235  * @const IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX
236  * The nonce domain governing ephemeral cryptex personalizations. Use of this
237  * domain requires the
238  *
239  *     com.apple.private.img4.nonce.ephemeral-cryptex
240  *
241  * entitlement.
242  */
243 #if !XNU_KERNEL_PRIVATE
244 IMG4_API_AVAILABLE_20210305
245 OS_EXPORT
246 const struct _img4_nonce_domain _img4_nonce_domain_ephemeral_cryptex;
247 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
248 		(&_img4_nonce_domain_ephemeral_cryptex)
249 #else
250 #define IMG4_NONCE_DOMAIN_EPHEMERAL_CRYPTEX \
251 		(img4if->i4if_v12.nonce_domain_ephemeral_cryptex)
252 #endif
253 
254 /*!
255  * @function img4_nonce_domain_copy_nonce
256  * Copies the current value of the nonce in the given domain.
257  *
258  * @param nd
259  * The nonce domain.
260  *
261  * @param n
262  * Upon successful return, storage that will contain the current nonce. The
263  * provided structure's {@link i4n_version} must be initialized to
264  * {@link IMG4_NONCE_VERSION}.
265  *
266  * @result
267  * Upon success, zero is returned. The implementation may also return one of the
268  * following error codes directly:
269  *
270  *     [ESTALE]     The nonce for the given domain has been invalidated, and the
271  *                  host must reboot in order to generate a new one
272  *     [EPERM]      The caller lacked the entitlement necessary to read the
273  *                  given nonce
274  */
275 #if !XNU_KERNEL_PRIVATE
276 IMG4_API_AVAILABLE_20210305
277 OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
278 errno_t
279 img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n);
280 #else
281 #define img4_nonce_domain_copy_nonce(...) \
282 		(img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__))
283 #endif
284 
285 /*!
286  * @function img4_nonce_domain_roll_nonce
287  * Invalidates the current nonce for the given domain and forces a re-generation
288  * of the domain's nonce seed at the next boot.
289  *
290  * @param nd
291  * The nonce domain.
292  *
293  * @result
294  * Upon success, zero is returned. The kernel implementation will never return
295  * a non-zero code. The userspace implementation may return one of the following
296  * error codes directly:
297  *
298  *     [EPERM]      The caller lacked the entitlement necessary to roll the
299  *                  given nonce
300  */
301 #if !XNU_KERNEL_PRIVATE
302 IMG4_API_AVAILABLE_20181106
303 OS_EXPORT OS_NONNULL1
304 errno_t
305 img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd);
306 #else
307 #define img4_nonce_domain_roll_nonce(...) \
308 		(img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__))
309 #endif
310 
311 #endif // __IMG4_NONCE_H
312