1 /*
2 * Copyright (c) 2015-2022 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 //for write protection
37 #include <vm/vm_kern.h>
38 #include <vm/vm_map.h>
39
40 #define PTR_ADD(type, base, offset) (type)((uintptr_t)(base) + (offset))
41
42 // -- struct cpx --
43
44 /*
45 * This structure contains the unwrapped key and is passed to the lower layers.
46 * It is private so users must use the accessors declared in sys/cprotect.h
47 * to read/write it.
48 */
49
50 // cpx_flags defined in cprotect.h
51 enum {
52 CPX_SEP_WRAPPEDKEY = 0x01,
53 CPX_IV_AES_CTX_INITIALIZED = 0x02,
54 CPX_USE_OFFSET_FOR_IV = 0x04,
55
56 // Using AES IV context generated from key
57 CPX_IV_AES_CTX_VFS = 0x08,
58 CPX_SYNTHETIC_OFFSET_FOR_IV = 0x10,
59 CPX_COMPOSITEKEY = 0x20,
60
61 //write page protection
62 CPX_WRITE_PROTECTABLE = 0x40
63 };
64
65 /*
66 * variable-length CPX structure. See fixed-length variant in cprotect.h
67 */
68 struct cpx {
69 #if DEBUG
70 uint32_t cpx_magic1;
71 #endif
72 aes_encrypt_ctx *cpx_iv_aes_ctx_ptr;// Pointer to context used for generating the IV
73 cpx_flags_t cpx_flags;
74 uint16_t cpx_max_key_len;
75 uint16_t cpx_key_len;
76 //fixed length up to here. cpx_cached_key is variable-length
77 uint8_t cpx_cached_key[];
78 };
79
80 /* Allows us to switch between CPX types */
81 typedef union cpxunion {
82 struct cpx cpx_var;
83 fcpx_t cpx_fixed;
84 } cpxunion_t;
85
86 ZONE_DEFINE(cpx_zone, "cpx",
87 sizeof(struct fcpx), ZC_ZFREE_CLEARMEM);
88 ZONE_DEFINE(aes_ctz_zone, "AES ctx",
89 sizeof(aes_encrypt_ctx), ZC_ZFREE_CLEARMEM);
90
91 // Note: see struct fcpx defined in sys/cprotect.h
92
93 // -- cpx_t accessors --
94
95 size_t
cpx_size(size_t key_len)96 cpx_size(size_t key_len)
97 {
98 // This should pick up the 'magic' word in DEBUG for free.
99 size_t size = sizeof(struct cpx) + key_len;
100
101 return size;
102 }
103
104 size_t
cpx_sizex(const struct cpx * cpx)105 cpx_sizex(const struct cpx *cpx)
106 {
107 return cpx_size(cpx->cpx_max_key_len);
108 }
109
110 cpx_t
cpx_alloc(size_t key_len,bool needs_ctx)111 cpx_alloc(size_t key_len, bool needs_ctx)
112 {
113 cpx_t cpx = NULL;
114
115 #if CONFIG_KEYPAGE_WP
116 /*
117 * Macs only use 1 key per volume, so force it into its own page.
118 * This way, we can write-protect as needed.
119 */
120 size_t cpsize = cpx_size(key_len);
121
122 // silence warning for needs_ctx
123 (void) needs_ctx;
124
125 if (cpsize < PAGE_SIZE) {
126 /*
127 * Don't use MALLOC to allocate the page-sized structure. Instead,
128 * use kmem_alloc to bypass KASAN since we are supplying our own
129 * unilateral write protection on this page. Note that kmem_alloc
130 * can block.
131 */
132 if (kmem_alloc(kernel_map, (vm_offset_t *)&cpx, PAGE_SIZE,
133 KMA_DATA, VM_KERN_MEMORY_FILE)) {
134 /*
135 * returning NULL at this point (due to failed
136 * allocation) would just result in a panic.
137 *
138 * fall back to attempting a normal kalloc, and don't
139 * let the cpx get marked PROTECTABLE.
140 */
141 /* BEGIN IGNORE CODESTYLE */
142 __typed_allocators_ignore_push
143 cpx = kheap_alloc(KHEAP_DEFAULT, cpx_size(key_len), Z_WAITOK);
144 /* END IGNORE CODESTYLE */
145 __typed_allocators_ignore_pop
146 } else {
147 //mark the page as protectable, since kmem_alloc succeeded.
148 cpx->cpx_flags |= CPX_WRITE_PROTECTABLE;
149 }
150 } else {
151 panic("cpx_size too large ! (%lu)", cpsize);
152 }
153 #else
154 /* If key page write protection disabled, just switch to zalloc */
155
156 // error out if you try to request a key that's too big
157 if (key_len > VFS_CP_MAX_CACHEBUFLEN) {
158 return NULL;
159 }
160
161 // the actual key array is fixed-length, but the amount of usable content can vary, via 'key_len'
162 cpx = zalloc_flags(cpx_zone, Z_WAITOK | Z_ZERO);
163
164 // if our encryption type needs it, alloc the context
165 if (needs_ctx) {
166 cpx_alloc_ctx(cpx);
167 }
168
169 #endif
170 cpx_init(cpx, key_len);
171
172 return cpx;
173 }
174
175 int
cpx_alloc_ctx(cpx_t cpx)176 cpx_alloc_ctx(cpx_t cpx)
177 {
178 #if CONFIG_KEYPAGE_WP
179 (void) cpx;
180 #else
181 if (cpx->cpx_iv_aes_ctx_ptr) {
182 // already allocated?
183 return 0;
184 }
185
186 cpx->cpx_iv_aes_ctx_ptr = zalloc_flags(aes_ctz_zone, Z_WAITOK | Z_ZERO);
187 #endif // CONFIG_KEYPAGE_WP
188
189 return 0;
190 }
191
192 void
cpx_free_ctx(cpx_t cpx)193 cpx_free_ctx(cpx_t cpx)
194 {
195 #if CONFIG_KEYPAGE_WP
196 (void) cpx;
197 # else
198 if (cpx->cpx_iv_aes_ctx_ptr) {
199 zfree(aes_ctz_zone, cpx->cpx_iv_aes_ctx_ptr);
200 }
201 #endif // CONFIG_KEYPAGE_WP
202 }
203
204 void
cpx_writeprotect(cpx_t cpx)205 cpx_writeprotect(cpx_t cpx)
206 {
207 #if CONFIG_KEYPAGE_WP
208 void *cpxstart = (void*)cpx;
209 void *cpxend = (void*)((uint8_t*)cpx + PAGE_SIZE);
210 if (cpx->cpx_flags & CPX_WRITE_PROTECTABLE) {
211 vm_map_protect(kernel_map, (vm_map_offset_t)cpxstart, (vm_map_offset_t)cpxend, (VM_PROT_READ), FALSE);
212 }
213 #else
214 (void) cpx;
215 #endif
216 return;
217 }
218
219 #if DEBUG
220 static const uint32_t cpx_magic1 = 0x7b787063; // cpx{
221 static const uint32_t cpx_magic2 = 0x7870637d; // }cpx
222 #endif
223
224 void
cpx_free(cpx_t cpx)225 cpx_free(cpx_t cpx)
226 {
227 #if DEBUG
228 assert(cpx->cpx_magic1 == cpx_magic1);
229 assert(*PTR_ADD(uint32_t *, cpx, cpx_sizex(cpx) - 4) == cpx_magic2);
230 #endif
231
232 #if CONFIG_KEYPAGE_WP
233 /* unprotect the page before bzeroing */
234 void *cpxstart = (void*)cpx;
235 void *cpxend = (void*)((uint8_t*)cpx + PAGE_SIZE);
236 if (cpx->cpx_flags & CPX_WRITE_PROTECTABLE) {
237 vm_map_protect(kernel_map, (vm_map_offset_t)cpxstart, (vm_map_offset_t)cpxend, (VM_PROT_DEFAULT), FALSE);
238
239 //now zero the memory after un-protecting it
240 bzero(cpx->cpx_cached_key, cpx->cpx_max_key_len);
241
242 //If we are here, then we used kmem_alloc to get the page. Must use kmem_free to drop it.
243 kmem_free(kernel_map, (vm_offset_t)cpx, PAGE_SIZE);
244 return;
245 }
246 #else
247 // free the context if it wasn't already freed
248 cpx_free_ctx(cpx);
249 zfree(cpx_zone, cpx);
250 return;
251 #endif
252 }
253
254 void
cpx_init(cpx_t cpx,size_t key_len)255 cpx_init(cpx_t cpx, size_t key_len)
256 {
257 #if DEBUG
258 cpx->cpx_magic1 = cpx_magic1;
259 *PTR_ADD(uint32_t *, cpx, cpx_size(key_len) - 4) = cpx_magic2;
260 #endif
261 cpx->cpx_flags = 0;
262 cpx->cpx_key_len = 0;
263 assert(key_len <= UINT16_MAX);
264 cpx->cpx_max_key_len = (uint16_t)key_len;
265 }
266
267 bool
cpx_is_sep_wrapped_key(const struct cpx * cpx)268 cpx_is_sep_wrapped_key(const struct cpx *cpx)
269 {
270 return ISSET(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
271 }
272
273 void
cpx_set_is_sep_wrapped_key(struct cpx * cpx,bool v)274 cpx_set_is_sep_wrapped_key(struct cpx *cpx, bool v)
275 {
276 if (v) {
277 SET(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
278 } else {
279 CLR(cpx->cpx_flags, CPX_SEP_WRAPPEDKEY);
280 }
281 }
282
283 bool
cpx_is_composite_key(const struct cpx * cpx)284 cpx_is_composite_key(const struct cpx *cpx)
285 {
286 return ISSET(cpx->cpx_flags, CPX_COMPOSITEKEY);
287 }
288
289 void
cpx_set_is_composite_key(struct cpx * cpx,bool v)290 cpx_set_is_composite_key(struct cpx *cpx, bool v)
291 {
292 if (v) {
293 SET(cpx->cpx_flags, CPX_COMPOSITEKEY);
294 } else {
295 CLR(cpx->cpx_flags, CPX_COMPOSITEKEY);
296 }
297 }
298
299 bool
cpx_use_offset_for_iv(const struct cpx * cpx)300 cpx_use_offset_for_iv(const struct cpx *cpx)
301 {
302 return ISSET(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
303 }
304
305 void
cpx_set_use_offset_for_iv(struct cpx * cpx,bool v)306 cpx_set_use_offset_for_iv(struct cpx *cpx, bool v)
307 {
308 if (v) {
309 SET(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
310 } else {
311 CLR(cpx->cpx_flags, CPX_USE_OFFSET_FOR_IV);
312 }
313 }
314
315 bool
cpx_synthetic_offset_for_iv(const struct cpx * cpx)316 cpx_synthetic_offset_for_iv(const struct cpx *cpx)
317 {
318 return ISSET(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
319 }
320
321 void
cpx_set_synthetic_offset_for_iv(struct cpx * cpx,bool v)322 cpx_set_synthetic_offset_for_iv(struct cpx *cpx, bool v)
323 {
324 if (v) {
325 SET(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
326 } else {
327 CLR(cpx->cpx_flags, CPX_SYNTHETIC_OFFSET_FOR_IV);
328 }
329 }
330
331 uint16_t
cpx_max_key_len(const struct cpx * cpx)332 cpx_max_key_len(const struct cpx *cpx)
333 {
334 return cpx->cpx_max_key_len;
335 }
336
337 uint16_t
cpx_key_len(const struct cpx * cpx)338 cpx_key_len(const struct cpx *cpx)
339 {
340 return cpx->cpx_key_len;
341 }
342
343 void
cpx_set_key_len(struct cpx * cpx,uint16_t key_len)344 cpx_set_key_len(struct cpx *cpx, uint16_t key_len)
345 {
346 cpx->cpx_key_len = key_len;
347
348 if (ISSET(cpx->cpx_flags, CPX_IV_AES_CTX_VFS)) {
349 /*
350 * We assume that if the key length is being modified, the key
351 * has changed. As a result, un-set any bits related to the
352 * AES context, if needed. They should be re-generated
353 * on-demand.
354 */
355 CLR(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED | CPX_IV_AES_CTX_VFS);
356 }
357 }
358
359 bool
cpx_has_key(const struct cpx * cpx)360 cpx_has_key(const struct cpx *cpx)
361 {
362 return cpx->cpx_key_len > 0;
363 }
364
365 #pragma clang diagnostic push
366 #pragma clang diagnostic ignored "-Wcast-qual"
367 void *
cpx_key(const struct cpx * cpx)368 cpx_key(const struct cpx *cpx)
369 {
370 return (void *)cpx->cpx_cached_key;
371 }
372 #pragma clang diagnostic pop
373
374 void
cpx_set_aes_iv_key(struct cpx * cpx,void * iv_key)375 cpx_set_aes_iv_key(struct cpx *cpx, void *iv_key)
376 {
377 if (cpx->cpx_iv_aes_ctx_ptr) {
378 aes_encrypt_key128(iv_key, cpx->cpx_iv_aes_ctx_ptr);
379 SET(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED | CPX_USE_OFFSET_FOR_IV);
380 CLR(cpx->cpx_flags, CPX_IV_AES_CTX_VFS);
381 }
382 }
383
384 aes_encrypt_ctx *
cpx_iv_aes_ctx(struct cpx * cpx)385 cpx_iv_aes_ctx(struct cpx *cpx)
386 {
387 if (ISSET(cpx->cpx_flags, CPX_IV_AES_CTX_INITIALIZED)) {
388 return cpx->cpx_iv_aes_ctx_ptr;
389 }
390
391 SHA1_CTX sha1ctxt;
392 uint8_t digest[SHA_DIGEST_LENGTH]; /* Kiv */
393
394 /* First init the cp_cache_iv_key[] */
395 SHA1Init(&sha1ctxt);
396
397 /*
398 * We can only use this when the keys are generated in the AP; As a result
399 * we only use the first 32 bytes of key length in the cache key
400 */
401 SHA1Update(&sha1ctxt, cpx->cpx_cached_key, cpx->cpx_key_len);
402 SHA1Final(digest, &sha1ctxt);
403
404 cpx_set_aes_iv_key(cpx, digest);
405 SET(cpx->cpx_flags, CPX_IV_AES_CTX_VFS);
406
407 return cpx->cpx_iv_aes_ctx_ptr;
408 }
409
410 void
cpx_flush(cpx_t cpx)411 cpx_flush(cpx_t cpx)
412 {
413 bzero(cpx->cpx_cached_key, cpx->cpx_max_key_len);
414 if (cpx->cpx_iv_aes_ctx_ptr) {
415 bzero(cpx->cpx_iv_aes_ctx_ptr, sizeof(aes_encrypt_ctx));
416 }
417 cpx->cpx_flags = 0;
418 cpx->cpx_key_len = 0;
419 }
420
421 bool
cpx_can_copy(const struct cpx * src,const struct cpx * dst)422 cpx_can_copy(const struct cpx *src, const struct cpx *dst)
423 {
424 return src->cpx_key_len <= dst->cpx_max_key_len;
425 }
426
427 void
cpx_copy(const struct cpx * src,cpx_t dst)428 cpx_copy(const struct cpx *src, cpx_t dst)
429 {
430 uint16_t key_len = cpx_key_len(src);
431 cpx_set_key_len(dst, key_len);
432 memcpy(cpx_key(dst), cpx_key(src), key_len);
433 dst->cpx_flags = src->cpx_flags;
434 if (ISSET(dst->cpx_flags, CPX_IV_AES_CTX_INITIALIZED)) {
435 *(dst->cpx_iv_aes_ctx_ptr) = *(src->cpx_iv_aes_ctx_ptr); // deep copy
436 }
437 }
438
439 typedef unsigned char cp_vfs_callback_arg_type_t;
440 enum {
441 CP_TYPE_LOCK_STATE = 0,
442 CP_TYPE_EP_STATE = 1,
443 };
444
445 typedef struct {
446 cp_vfs_callback_arg_type_t type;
447 union {
448 cp_lock_state_t lock_state;
449 cp_ep_state_t ep_state;
450 };
451 int valid_uuid;
452 uuid_t volume_uuid;
453 } cp_vfs_callback_arg;
454
455 static int
cp_vfs_callback(mount_t mp,void * arg)456 cp_vfs_callback(mount_t mp, void *arg)
457 {
458 cp_vfs_callback_arg *callback_arg = (cp_vfs_callback_arg *)arg;
459
460 if (callback_arg->valid_uuid) {
461 struct vfs_attr va;
462 VFSATTR_INIT(&va);
463 VFSATTR_WANTED(&va, f_uuid);
464
465 if (vfs_getattr(mp, &va, vfs_context_current())) {
466 return 0;
467 }
468
469 if (!VFSATTR_IS_SUPPORTED(&va, f_uuid)) {
470 return 0;
471 }
472
473 if (memcmp(va.f_uuid, callback_arg->volume_uuid, sizeof(uuid_t))) {
474 return 0;
475 }
476 }
477
478 switch (callback_arg->type) {
479 case(CP_TYPE_LOCK_STATE):
480 VFS_IOCTL(mp, FIODEVICELOCKED, (void *)(uintptr_t)callback_arg->lock_state, 0, vfs_context_kernel());
481 break;
482 case(CP_TYPE_EP_STATE):
483 VFS_IOCTL(mp, FIODEVICEEPSTATE, (void *)(uintptr_t)callback_arg->ep_state, 0, vfs_context_kernel());
484 break;
485 default:
486 break;
487 }
488 return 0;
489 }
490
491 int
cp_key_store_action(cp_key_store_action_t action)492 cp_key_store_action(cp_key_store_action_t action)
493 {
494 cp_vfs_callback_arg callback_arg;
495
496 switch (action) {
497 case CP_ACTION_LOCKED:
498 case CP_ACTION_UNLOCKED:
499 callback_arg.type = CP_TYPE_LOCK_STATE;
500 callback_arg.lock_state = (action == CP_ACTION_LOCKED ? CP_LOCKED_STATE : CP_UNLOCKED_STATE);
501 memset(callback_arg.volume_uuid, 0, sizeof(uuid_t));
502 callback_arg.valid_uuid = 0;
503 return vfs_iterate(0, cp_vfs_callback, (void *)&callback_arg);
504 case CP_ACTION_EP_INVALIDATED:
505 callback_arg.type = CP_TYPE_EP_STATE;
506 callback_arg.ep_state = CP_EP_INVALIDATED;
507 memset(callback_arg.volume_uuid, 0, sizeof(uuid_t));
508 callback_arg.valid_uuid = 0;
509 return vfs_iterate(0, cp_vfs_callback, (void *)&callback_arg);
510 default:
511 return -1;
512 }
513 }
514
515 int
cp_key_store_action_for_volume(uuid_t volume_uuid,cp_key_store_action_t action)516 cp_key_store_action_for_volume(uuid_t volume_uuid, cp_key_store_action_t action)
517 {
518 cp_vfs_callback_arg callback_arg;
519
520 switch (action) {
521 case CP_ACTION_LOCKED:
522 case CP_ACTION_UNLOCKED:
523 callback_arg.type = CP_TYPE_LOCK_STATE;
524 callback_arg.lock_state = (action == CP_ACTION_LOCKED ? CP_LOCKED_STATE : CP_UNLOCKED_STATE);
525 memcpy(callback_arg.volume_uuid, volume_uuid, sizeof(uuid_t));
526 callback_arg.valid_uuid = 1;
527 return vfs_iterate(0, cp_vfs_callback, (void *)&callback_arg);
528 case CP_ACTION_EP_INVALIDATED:
529 callback_arg.type = CP_TYPE_EP_STATE;
530 callback_arg.ep_state = CP_EP_INVALIDATED;
531 memcpy(callback_arg.volume_uuid, volume_uuid, sizeof(uuid_t));
532 callback_arg.valid_uuid = 1;
533 return vfs_iterate(0, cp_vfs_callback, (void *)&callback_arg);
534 default:
535 return -1;
536 }
537 }
538
539 int
cp_is_valid_class(int isdir,int32_t protectionclass)540 cp_is_valid_class(int isdir, int32_t protectionclass)
541 {
542 /*
543 * The valid protection classes are from 0 -> N
544 * We use a signed argument to detect unassigned values from
545 * directory entry creation time in HFS.
546 */
547 if (isdir) {
548 /* Directories are not allowed to have F, but they can have "NONE" */
549 return (protectionclass >= PROTECTION_CLASS_DIR_NONE) &&
550 (protectionclass <= PROTECTION_CLASS_D);
551 } else {
552 return (protectionclass >= PROTECTION_CLASS_A) &&
553 (protectionclass <= PROTECTION_CLASS_F);
554 }
555 }
556
557 /*
558 * Parses versions of the form 12A316, i.e. <major><minor><revision> and
559 * returns a uint32_t in the form 0xaabbcccc where aa = <major>,
560 * bb = <ASCII char>, cccc = <revision>.
561 */
562 static cp_key_os_version_t
parse_os_version(const char * vers)563 parse_os_version(const char *vers)
564 {
565 const char *p = vers;
566
567 int a = 0;
568 while (*p >= '0' && *p <= '9') {
569 a = a * 10 + *p - '0';
570 ++p;
571 }
572
573 if (!a) {
574 return 0;
575 }
576
577 int b = *p++;
578 if (!b) {
579 return 0;
580 }
581
582 int c = 0;
583 while (*p >= '0' && *p <= '9') {
584 c = c * 10 + *p - '0';
585 ++p;
586 }
587
588 if (!c) {
589 return 0;
590 }
591
592 return (a & 0xff) << 24 | b << 16 | (c & 0xffff);
593 }
594
595 cp_key_os_version_t
cp_os_version(void)596 cp_os_version(void)
597 {
598 static cp_key_os_version_t cp_os_version;
599
600 if (cp_os_version) {
601 return cp_os_version;
602 }
603
604 if (!osversion[0]) {
605 return 0;
606 }
607
608 cp_os_version = parse_os_version(osversion);
609 if (!cp_os_version) {
610 printf("cp_os_version: unable to parse osversion `%s'\n", osversion);
611 cp_os_version = 1;
612 }
613
614 return cp_os_version;
615 }
616