]> git.saurik.com Git - apple/xnu.git/blob - bsd/vfs/vfs_cprotect.c
xnu-3789.31.2.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_cprotect.c
1 /*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/cprotect.h>
30 #include <sys/malloc.h>
31 #include <sys/mount_internal.h>
32 #include <sys/filio.h>
33 #include <sys/content_protection.h>
34 #include <libkern/crypto/sha1.h>
35 #include <libkern/libkern.h>
36
37 #define PTR_ADD(type, base, offset) (type)((uintptr_t)(base) + (offset))
38
39 // -- struct cpx --
40
41 /*
42 * This structure contains the unwrapped key and is passed to the lower layers.
43 * It is private so users must use the accessors declared in sys/cprotect.h
44 * to read/write it.
45 */
46
47 // cpx_flags
48 typedef uint32_t cpx_flags_t;
49 enum {
50 CPX_SEP_WRAPPEDKEY = 0x01,
51 CPX_IV_AES_CTX_INITIALIZED = 0x02,
52 CPX_USE_OFFSET_FOR_IV = 0x04,
53
54 // Using AES IV context generated from key
55 CPX_IV_AES_CTX_VFS = 0x08,
56 CPX_SYNTHETIC_OFFSET_FOR_IV = 0x10,
57 };
58
59 struct cpx {
60 #if DEBUG
61 uint32_t cpx_magic1;
62 #endif
63 cpx_flags_t cpx_flags;
64 uint16_t cpx_max_key_len;
65 uint16_t cpx_key_len;
66 aes_encrypt_ctx cpx_iv_aes_ctx; // Context used for generating the IV
67 uint8_t cpx_cached_key[];
68 } __attribute__((packed));
69
70 // -- cpx_t accessors --
71
72 size_t cpx_size(size_t key_size)
73 {
74 size_t size = sizeof(struct cpx) + key_size;
75
76 #if DEBUG
77 size += 4; // Extra for magic
78 #endif
79
80 return size;
81 }
82
83 size_t cpx_sizex(const struct cpx *cpx)
84 {
85 return cpx_size(cpx->cpx_max_key_len);
86 }
87
88 cpx_t cpx_alloc(size_t key_len)
89 {
90 cpx_t cpx;
91
92 MALLOC(cpx, cpx_t, cpx_size(key_len), M_TEMP, M_WAITOK);
93
94 cpx_init(cpx, key_len);
95
96 return cpx;
97 }
98
99 #if DEBUG
100 static const uint32_t cpx_magic1 = 0x7b787063; // cpx{
101 static const uint32_t cpx_magic2 = 0x7870637d; // }cpx
102 #endif
103
104 void cpx_free(cpx_t cpx)
105 {
106 #if DEBUG
107 assert(cpx->cpx_magic1 == cpx_magic1);
108 assert(*PTR_ADD(uint32_t *, cpx, cpx_sizex(cpx) - 4) == cpx_magic2);
109 #endif
110 bzero(cpx->cpx_cached_key, cpx->cpx_max_key_len);
111 FREE(cpx, M_TEMP);
112 }
113
114 void cpx_init(cpx_t cpx, size_t key_len)
115 {
116 #if DEBUG
117 cpx->cpx_magic1 = cpx_magic1;
118 *PTR_ADD(uint32_t *, cpx, cpx_size(key_len) - 4) = cpx_magic2;
119 #endif
120 cpx->cpx_flags = 0;
121 cpx->cpx_key_len = 0;
122 cpx->cpx_max_key_len = key_len;
123 }
124
125 bool cpx_is_sep_wrapped_key(const struct cpx *cpx)
126 {
127 return ISSET(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
128 }
129
130 void cpx_set_is_sep_wrapped_key(struct cpx *cpx, bool v)
131 {
132 if (v)
133 SET(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
134 else
135 CLR(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
136 }
137
138 bool cpx_use_offset_for_iv(const struct cpx *cpx)
139 {
140 return ISSET(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
141 }
142
143 void cpx_set_use_offset_for_iv(struct cpx *cpx, bool v)
144 {
145 if (v)
146 SET(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
147 else
148 CLR(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
149 }
150
151 bool cpx_synthetic_offset_for_iv(const struct cpx *cpx)
152 {
153 return ISSET(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
154 }
155
156 void cpx_set_synthetic_offset_for_iv(struct cpx *cpx, bool v)
157 {
158 if (v)
159 SET(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
160 else
161 CLR(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
162 }
163
164 uint16_t cpx_max_key_len(const struct cpx *cpx)
165 {
166 return cpx->cpx_max_key_len;
167 }
168
169 uint16_t cpx_key_len(const struct cpx *cpx)
170 {
171 return cpx->cpx_key_len;
172 }
173
174 void cpx_set_key_len(struct cpx *cpx, uint16_t key_len)
175 {
176 cpx->cpx_key_len = key_len;
177
178 if (ISSET(cpx->cpx_flags, CPX_IV_AES_CTX_VFS)) {
179 /*
180 * We assume that if the key length is being modified, the key
181 * has changed. As a result, un-set any bits related to the
182 * AES context, if needed. They should be re-generated
183 * on-demand.
184 */
185 CLR(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED | CPX_IV_AES_CTX_VFS);
186 }
187 }
188
189 bool cpx_has_key(const struct cpx *cpx)
190 {
191 return cpx->cpx_key_len > 0;
192 }
193
194 #pragma clang diagnostic push
195 #pragma clang diagnostic ignored "-Wcast-qual"
196 void *cpx_key(const struct cpx *cpx)
197 {
198 return (void *)cpx->cpx_cached_key;
199 }
200 #pragma clang diagnostic pop
201
202 void cpx_set_aes_iv_key(struct cpx *cpx, void *iv_key)
203 {
204 aes_encrypt_key128(iv_key, &cpx->cpx_iv_aes_ctx);
205 SET(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED | CPX_USE_OFFSET_FOR_IV);
206 CLR(cpx->cpx_flags, CPX_IV_AES_CTX_VFS);
207 }
208
209 aes_encrypt_ctx *cpx_iv_aes_ctx(struct cpx *cpx)
210 {
211 if (ISSET(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED))
212 return &cpx->cpx_iv_aes_ctx;
213
214 SHA1_CTX sha1ctxt;
215 uint8_t digest[SHA_DIGEST_LENGTH]; /* Kiv */
216
217 /* First init the cp_cache_iv_key[] */
218 SHA1Init(&sha1ctxt);
219
220 /*
221 * We can only use this when the keys are generated in the AP; As a result
222 * we only use the first 32 bytes of key length in the cache key
223 */
224 SHA1Update(&sha1ctxt, cpx->cpx_cached_key, cpx->cpx_key_len);
225 SHA1Final(digest, &sha1ctxt);
226
227 cpx_set_aes_iv_key(cpx, digest);
228 SET(cpx->cpx_flags, CPX_IV_AES_CTX_VFS);
229
230 return &cpx->cpx_iv_aes_ctx;
231 }
232
233 void cpx_flush(cpx_t cpx)
234 {
235 bzero(cpx->cpx_cached_key, cpx->cpx_max_key_len);
236 bzero(&cpx->cpx_iv_aes_ctx, sizeof(cpx->cpx_iv_aes_ctx));
237 cpx->cpx_flags = 0;
238 cpx->cpx_key_len = 0;
239 }
240
241 bool cpx_can_copy(const struct cpx *src, const struct cpx *dst)
242 {
243 return src->cpx_key_len <= dst->cpx_max_key_len;
244 }
245
246 void cpx_copy(const struct cpx *src, cpx_t dst)
247 {
248 uint16_t key_len = cpx_key_len(src);
249 cpx_set_key_len(dst, key_len);
250 memcpy(cpx_key(dst), cpx_key(src), key_len);
251 dst->cpx_flags = src->cpx_flags;
252 if (ISSET(dst->cpx_flags, CPX_IV_AES_CTX_INITIALIZED))
253 dst->cpx_iv_aes_ctx = src->cpx_iv_aes_ctx;
254 }
255
256 static struct cp_wrap_func g_cp_wrap_func = {};
257
258 static int
259 cp_lock_vfs_callback(mount_t mp, void *arg)
260 {
261 VFS_IOCTL(mp, FIODEVICELOCKED, arg, 0, vfs_context_kernel());
262
263 return 0;
264 }
265
266 int
267 cp_key_store_action(cp_key_store_action_t action)
268 {
269 switch (action) {
270 case CP_ACTION_LOCKED:
271 case CP_ACTION_UNLOCKED:;
272 cp_lock_state_t state = (action == CP_ACTION_LOCKED
273 ? CP_LOCKED_STATE : CP_UNLOCKED_STATE);
274 return vfs_iterate(0, cp_lock_vfs_callback, (void *)(uintptr_t)state);
275 default:
276 return -1;
277 }
278 }
279
280 int
281 cp_register_wraps(cp_wrap_func_t key_store_func)
282 {
283 g_cp_wrap_func.new_key = key_store_func->new_key;
284 g_cp_wrap_func.unwrapper = key_store_func->unwrapper;
285 g_cp_wrap_func.rewrapper = key_store_func->rewrapper;
286 /* do not use invalidater until rdar://12170050 goes in ! */
287 g_cp_wrap_func.invalidater = key_store_func->invalidater;
288 g_cp_wrap_func.backup_key = key_store_func->backup_key;
289
290 return 0;
291 }
292
293 int cp_rewrap_key(cp_cred_t access, uint32_t dp_class,
294 const cp_wrapped_key_t wrapped_key_in,
295 cp_wrapped_key_t wrapped_key_out)
296 {
297 if (!g_cp_wrap_func.rewrapper)
298 return ENXIO;
299 return g_cp_wrap_func.rewrapper(access, dp_class, wrapped_key_in,
300 wrapped_key_out);
301 }
302
303 int cp_new_key(cp_cred_t access, uint32_t dp_class, cp_raw_key_t key_out,
304 cp_wrapped_key_t wrapped_key_out)
305 {
306 if (!g_cp_wrap_func.new_key)
307 return ENXIO;
308 return g_cp_wrap_func.new_key(access, dp_class, key_out, wrapped_key_out);
309 }
310
311 int cp_unwrap_key(cp_cred_t access, const cp_wrapped_key_t wrapped_key_in,
312 cp_raw_key_t key_out)
313 {
314 if (!g_cp_wrap_func.unwrapper)
315 return ENXIO;
316 return g_cp_wrap_func.unwrapper(access, wrapped_key_in, key_out);
317 }
318
319 int cp_get_backup_key(cp_cred_t access, const cp_wrapped_key_t wrapped_key_in,
320 cp_wrapped_key_t wrapped_key_out)
321 {
322 if (!g_cp_wrap_func.backup_key)
323 return ENXIO;
324 return g_cp_wrap_func.backup_key(access, wrapped_key_in, wrapped_key_out);
325 }
326
327 int
328 cp_is_valid_class(int isdir, int32_t protectionclass)
329 {
330 /*
331 * The valid protection classes are from 0 -> N
332 * We use a signed argument to detect unassigned values from
333 * directory entry creation time in HFS.
334 */
335 if (isdir) {
336 /* Directories are not allowed to have F, but they can have "NONE" */
337 return ((protectionclass >= PROTECTION_CLASS_DIR_NONE) &&
338 (protectionclass <= PROTECTION_CLASS_D));
339 }
340 else {
341 return ((protectionclass >= PROTECTION_CLASS_A) &&
342 (protectionclass <= PROTECTION_CLASS_F));
343 }
344 }
345
346 /*
347 * Parses versions of the form 12A316, i.e. <major><minor><revision> and
348 * returns a uint32_t in the form 0xaabbcccc where aa = <major>,
349 * bb = <ASCII char>, cccc = <revision>.
350 */
351 static cp_key_os_version_t
352 parse_os_version(const char *vers)
353 {
354 const char *p = vers;
355
356 int a = 0;
357 while (*p >= '0' && *p <= '9') {
358 a = a * 10 + *p - '0';
359 ++p;
360 }
361
362 if (!a)
363 return 0;
364
365 int b = *p++;
366 if (!b)
367 return 0;
368
369 int c = 0;
370 while (*p >= '0' && *p <= '9') {
371 c = c * 10 + *p - '0';
372 ++p;
373 }
374
375 if (!c)
376 return 0;
377
378 return (a & 0xff) << 24 | b << 16 | (c & 0xffff);
379 }
380
381 cp_key_os_version_t
382 cp_os_version(void)
383 {
384 static cp_key_os_version_t cp_os_version;
385
386 if (cp_os_version)
387 return cp_os_version;
388
389 if (!osversion[0])
390 return 0;
391
392 cp_os_version = parse_os_version(osversion);
393 if (!cp_os_version) {
394 printf("cp_os_version: unable to parse osversion `%s'\n", osversion);
395 cp_os_version = 1;
396 }
397
398 return cp_os_version;
399 }