]>
Commit | Line | Data |
---|---|---|
0a7de745 A |
1 | /*! |
2 | * @header | |
3 | * Provides an interface for managing nonces to govern the lifetime of a | |
cb323159 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. | |
0a7de745 A |
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 | |
f427ee49 | 49 | #error "Please #include <img4/firmware.h> instead of this file directly" |
0a7de745 A |
50 | #endif // __IMG4_INDIRECT |
51 | ||
cb323159 A |
52 | #if IMG4_TAPI |
53 | #include "tapi.h" | |
54 | #endif | |
55 | ||
0a7de745 A |
56 | /*! |
57 | * @typedef img4_nonce_domain_t | |
58 | * An opaque type describing a nonce domain. | |
59 | */ | |
60 | IMG4_API_AVAILABLE_20181106 | |
61 | typedef struct _img4_nonce_domain img4_nonce_domain_t; | |
62 | ||
63 | /*! | |
f427ee49 | 64 | * @const IMG4_NONCE_STRUCT_VERSION |
0a7de745 A |
65 | * The version of the {@link img4_nonce_t} structure supported by the |
66 | * implementation. | |
67 | */ | |
f427ee49 A |
68 | #define IMG4_NONCE_STRUCT_VERSION ((img4_struct_version_t)0) |
69 | #define IMG4_NONCE_VERSION IMG4_NONCE_STRUCT_VERSION | |
0a7de745 A |
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 | */ | |
f427ee49 | 76 | #define IMG4_NONCE_MAX_LENGTH (48u) |
0a7de745 A |
77 | |
78 | /*! | |
79 | * @typedef img4_nonce_t | |
80 | * A structure describing a nonce. | |
81 | * | |
82 | * @field i4n_version | |
83 | * The version of the structure. When declaring this structure, you must | |
84 | * initialize this field to {@link IMG4_NONCE_VERSION}. | |
85 | * | |
86 | * @field i4n_nonce | |
87 | * The bytes comprising the nonce. | |
88 | * | |
89 | * @field i4n_length | |
90 | * The length of the nonce. Will be at most {@link IMG4_NONCE_MAX_LENGTH}. | |
91 | */ | |
92 | IMG4_API_AVAILABLE_20181106 | |
93 | typedef struct _img4_nonce { | |
94 | img4_struct_version_t i4n_version; | |
95 | const uint8_t i4n_nonce[IMG4_NONCE_MAX_LENGTH]; | |
96 | uint32_t i4n_length; | |
97 | } img4_nonce_t; | |
98 | ||
99 | /*! | |
100 | * @const IMG4_NONCE_INIT | |
101 | * A convenience initializer for {@link img4_nonce_t} which ensures that the | |
102 | * {@link i4n_version} field is properly initialized. | |
103 | */ | |
104 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L | |
f427ee49 | 105 | #define IMG4_NONCE_INIT (img4_nonce_t){.i4n_version = IMG4_NONCE_STRUCT_VERSION} |
0a7de745 | 106 | #elif defined(__cplusplus) && __cplusplus >= 201103L |
f427ee49 | 107 | #define IMG4_NONCE_INIT (img4_nonce_t{IMG4_NONCE_STRUCT_VERSION}) |
0a7de745 A |
108 | #elif defined(__cplusplus) |
109 | #define IMG4_NONCE_INIT \ | |
f427ee49 | 110 | (img4_nonce_t((img4_nonce_t){IMG4_NONCE_STRUCT_VERSION})) |
0a7de745 | 111 | #else |
f427ee49 A |
112 | #define IMG4_NONCE_INIT {IMG4_NONCE_STRUCT_VERSION} |
113 | #endif | |
114 | ||
115 | /*! | |
116 | * @const IMG4_NONCE_ZERO | |
117 | * A convenience initializer for {@link img4_nonce_t} which initializes a 48- | |
118 | * byte nonce of all zeroes. | |
119 | */ | |
120 | #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L | |
121 | #define IMG4_NONCE_ZERO (img4_nonce_t){ \ | |
122 | .i4n_version = IMG4_NONCE_STRUCT_VERSION, \ | |
123 | .i4n_nonce = {0}, \ | |
124 | .i4n_length = IMG4_NONCE_MAX_LENGTH, \ | |
125 | } | |
0a7de745 A |
126 | #endif |
127 | ||
128 | /*! | |
129 | * @const IMG4_NONCE_DOMAIN_TRUST_CACHE | |
130 | * The nonce domain governing trust cache personalizations. Use of this domain | |
131 | * requires the | |
132 | * | |
133 | * com.apple.private.img4.nonce.trust-cache | |
134 | * | |
135 | * entitlement. | |
136 | */ | |
cb323159 | 137 | #if !XNU_KERNEL_PRIVATE |
0a7de745 A |
138 | IMG4_API_AVAILABLE_20181106 |
139 | OS_EXPORT | |
140 | const struct _img4_nonce_domain _img4_nonce_domain_trust_cache; | |
141 | #define IMG4_NONCE_DOMAIN_TRUST_CACHE (&_img4_nonce_domain_trust_cache) | |
142 | #else | |
143 | #define IMG4_NONCE_DOMAIN_TRUST_CACHE (img4if->i4if_v1.nonce_domain_trust_cache) | |
144 | #endif | |
145 | ||
cb323159 A |
146 | /*! |
147 | * @const IMG4_NONCE_DOMAIN_PDI | |
148 | * The nonce domain governing disk image personalizations. Use of this domain | |
149 | * requires the | |
150 | * | |
151 | * com.apple.private.img4.nonce.pdi | |
152 | * | |
153 | * entitlement. The nonce for this domain is regenerated once every boot. | |
154 | */ | |
155 | #if !XNU_KERNEL_PRIVATE | |
156 | IMG4_API_AVAILABLE_20181106 | |
157 | OS_EXPORT | |
158 | const struct _img4_nonce_domain _img4_nonce_domain_pdi; | |
159 | #define IMG4_NONCE_DOMAIN_PDI (&_img4_nonce_domain_pdi) | |
160 | #else | |
161 | #define IMG4_NONCE_DOMAIN_PDI (img4if->i4if_v3.nonce_domain_pdi) | |
162 | #endif | |
163 | ||
164 | /*! | |
165 | * @const IMG4_NONCE_DOMAIN_CRYPTEX | |
166 | * The nonce domain governing cryptex personalizations. Use of this domain | |
167 | * requires the | |
168 | * | |
169 | * com.apple.private.img4.nonce.cryptex | |
170 | * | |
171 | * entitlement. | |
172 | */ | |
173 | #if !XNU_KERNEL_PRIVATE | |
174 | IMG4_API_AVAILABLE_20181106 | |
175 | OS_EXPORT | |
176 | const struct _img4_nonce_domain _img4_nonce_domain_cryptex; | |
177 | #define IMG4_NONCE_DOMAIN_CRYPTEX (&_img4_nonce_domain_cryptex) | |
178 | #else | |
f427ee49 | 179 | #define IMG4_NONCE_DOMAIN_CRYPTEX (img4if->i4if_v3.nonce_domain_cryptex) |
cb323159 A |
180 | #endif |
181 | ||
0a7de745 A |
182 | /*! |
183 | * @function img4_nonce_domain_copy_nonce | |
184 | * Copies the current value of the nonce in the given domain. | |
185 | * | |
186 | * @param nd | |
187 | * The nonce domain. | |
188 | * | |
189 | * @param n | |
190 | * Upon successful return, storage that will contain the current nonce. The | |
191 | * provided structure's {@link i4n_version} must be initialized to | |
192 | * {@link IMG4_NONCE_VERSION}. | |
193 | * | |
194 | * @result | |
195 | * Upon success, zero is returned. The implementation may also return one of the | |
196 | * following error codes directly: | |
197 | * | |
198 | * [ESTALE] The nonce for the given domain has been invalidated, and the | |
199 | * host must reboot in order to generate a new one | |
200 | * [EPERM] The caller lacked the entitlement necessary to read the | |
201 | * given nonce | |
202 | */ | |
cb323159 | 203 | #if !XNU_KERNEL_PRIVATE |
0a7de745 A |
204 | IMG4_API_AVAILABLE_20181106 |
205 | OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 | |
206 | errno_t | |
207 | img4_nonce_domain_copy_nonce(const img4_nonce_domain_t *nd, img4_nonce_t *n); | |
208 | #else | |
209 | #define img4_nonce_domain_copy_nonce(...) \ | |
f427ee49 | 210 | (img4if->i4if_v1.nonce_domain_copy_nonce(__VA_ARGS__)) |
0a7de745 A |
211 | #endif |
212 | ||
213 | /*! | |
214 | * @function img4_nonce_domain_roll_nonce | |
215 | * Invalidates the current nonce for the given domain and forces a re-generation | |
216 | * of the domain's nonce seed at the next boot. | |
217 | * | |
218 | * @param nd | |
219 | * The nonce domain. | |
220 | * | |
221 | * @result | |
222 | * Upon success, zero is returned. The kernel implementation will never return | |
223 | * a non-zero code. The userspace implementation may return one of the following | |
224 | * error codes directly: | |
225 | * | |
226 | * [EPERM] The caller lacked the entitlement necessary to roll the | |
227 | * given nonce | |
228 | */ | |
cb323159 | 229 | #if !XNU_KERNEL_PRIVATE |
0a7de745 A |
230 | IMG4_API_AVAILABLE_20181106 |
231 | OS_EXPORT OS_NONNULL1 | |
232 | errno_t | |
233 | img4_nonce_domain_roll_nonce(const img4_nonce_domain_t *nd); | |
234 | #else | |
235 | #define img4_nonce_domain_roll_nonce(...) \ | |
f427ee49 | 236 | (img4if->i4if_v1.nonce_domain_roll_nonce(__VA_ARGS__)) |
0a7de745 A |
237 | #endif |
238 | ||
239 | #endif // __IMG4_NONCE_H |