2 * Copyright (c) 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
37 #define PTR_ADD(type, base, offset) (type)((uintptr_t)(base) + (offset))
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
48 typedef uint32_t cpx_flags_t
;
50 CPX_SEP_WRAPPEDKEY
= 0x01,
51 CPX_IV_AES_CTX_INITIALIZED
= 0x02,
52 CPX_USE_OFFSET_FOR_IV
= 0x04,
54 // Using AES IV context generated from key
55 CPX_IV_AES_CTX_VFS
= 0x08,
56 CPX_SYNTHETIC_OFFSET_FOR_IV
= 0x10,
63 cpx_flags_t cpx_flags
;
64 uint16_t cpx_max_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
));
70 // -- cpx_t accessors --
72 size_t cpx_size(size_t key_size
)
74 size_t size
= sizeof(struct cpx
) + key_size
;
77 size
+= 4; // Extra for magic
83 size_t cpx_sizex(const struct cpx
*cpx
)
85 return cpx_size(cpx
->cpx_max_key_len
);
88 cpx_t
cpx_alloc(size_t key_len
)
92 MALLOC(cpx
, cpx_t
, cpx_size(key_len
), M_TEMP
, M_WAITOK
);
94 cpx_init(cpx
, key_len
);
100 static const uint32_t cpx_magic1
= 0x7b787063; // cpx{
101 static const uint32_t cpx_magic2
= 0x7870637d; // }cpx
104 void cpx_free(cpx_t cpx
)
107 assert(cpx
->cpx_magic1
== cpx_magic1
);
108 assert(*PTR_ADD(uint32_t *, cpx
, cpx_sizex(cpx
) - 4) == cpx_magic2
);
110 bzero(cpx
->cpx_cached_key
, cpx
->cpx_max_key_len
);
114 void cpx_init(cpx_t cpx
, size_t key_len
)
117 cpx
->cpx_magic1
= cpx_magic1
;
118 *PTR_ADD(uint32_t *, cpx
, cpx_size(key_len
) - 4) = cpx_magic2
;
121 cpx
->cpx_key_len
= 0;
122 cpx
->cpx_max_key_len
= key_len
;
125 bool cpx_is_sep_wrapped_key(const struct cpx
*cpx
)
127 return ISSET(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
130 void cpx_set_is_sep_wrapped_key(struct cpx
*cpx
, bool v
)
133 SET(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
135 CLR(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
138 bool cpx_use_offset_for_iv(const struct cpx
*cpx
)
140 return ISSET(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
143 void cpx_set_use_offset_for_iv(struct cpx
*cpx
, bool v
)
146 SET(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
148 CLR(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
151 bool cpx_synthetic_offset_for_iv(const struct cpx
*cpx
)
153 return ISSET(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
156 void cpx_set_synthetic_offset_for_iv(struct cpx
*cpx
, bool v
)
159 SET(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
161 CLR(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
164 uint16_t cpx_max_key_len(const struct cpx
*cpx
)
166 return cpx
->cpx_max_key_len
;
169 uint16_t cpx_key_len(const struct cpx
*cpx
)
171 return cpx
->cpx_key_len
;
174 void cpx_set_key_len(struct cpx
*cpx
, uint16_t key_len
)
176 cpx
->cpx_key_len
= key_len
;
178 if (ISSET(cpx
->cpx_flags
, CPX_IV_AES_CTX_VFS
)) {
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
185 CLR(cpx
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
| CPX_IV_AES_CTX_VFS
);
189 bool cpx_has_key(const struct cpx
*cpx
)
191 return cpx
->cpx_key_len
> 0;
194 #pragma clang diagnostic push
195 #pragma clang diagnostic ignored "-Wcast-qual"
196 void *cpx_key(const struct cpx
*cpx
)
198 return (void *)cpx
->cpx_cached_key
;
200 #pragma clang diagnostic pop
202 void cpx_set_aes_iv_key(struct cpx
*cpx
, void *iv_key
)
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
);
209 aes_encrypt_ctx
*cpx_iv_aes_ctx(struct cpx
*cpx
)
211 if (ISSET(cpx
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
))
212 return &cpx
->cpx_iv_aes_ctx
;
215 uint8_t digest
[SHA_DIGEST_LENGTH
]; /* Kiv */
217 /* First init the cp_cache_iv_key[] */
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
224 SHA1Update(&sha1ctxt
, cpx
->cpx_cached_key
, cpx
->cpx_key_len
);
225 SHA1Final(digest
, &sha1ctxt
);
227 cpx_set_aes_iv_key(cpx
, digest
);
228 SET(cpx
->cpx_flags
, CPX_IV_AES_CTX_VFS
);
230 return &cpx
->cpx_iv_aes_ctx
;
233 void cpx_flush(cpx_t cpx
)
235 bzero(cpx
->cpx_cached_key
, cpx
->cpx_max_key_len
);
236 bzero(&cpx
->cpx_iv_aes_ctx
, sizeof(cpx
->cpx_iv_aes_ctx
));
238 cpx
->cpx_key_len
= 0;
241 bool cpx_can_copy(const struct cpx
*src
, const struct cpx
*dst
)
243 return src
->cpx_key_len
<= dst
->cpx_max_key_len
;
246 void cpx_copy(const struct cpx
*src
, cpx_t dst
)
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
;
256 static struct cp_wrap_func g_cp_wrap_func
= {};
259 cp_lock_vfs_callback(mount_t mp
, void *arg
)
261 VFS_IOCTL(mp
, FIODEVICELOCKED
, arg
, 0, vfs_context_kernel());
267 cp_key_store_action(cp_key_store_action_t 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
);
281 cp_register_wraps(cp_wrap_func_t key_store_func
)
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
;
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
)
297 if (!g_cp_wrap_func
.rewrapper
)
299 return g_cp_wrap_func
.rewrapper(access
, dp_class
, wrapped_key_in
,
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
)
306 if (!g_cp_wrap_func
.new_key
)
308 return g_cp_wrap_func
.new_key(access
, dp_class
, key_out
, wrapped_key_out
);
311 int cp_unwrap_key(cp_cred_t access
, const cp_wrapped_key_t wrapped_key_in
,
312 cp_raw_key_t key_out
)
314 if (!g_cp_wrap_func
.unwrapper
)
316 return g_cp_wrap_func
.unwrapper(access
, wrapped_key_in
, key_out
);
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
)
322 if (!g_cp_wrap_func
.backup_key
)
324 return g_cp_wrap_func
.backup_key(access
, wrapped_key_in
, wrapped_key_out
);
328 cp_is_valid_class(int isdir
, int32_t protectionclass
)
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.
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
));
341 return ((protectionclass
>= PROTECTION_CLASS_A
) &&
342 (protectionclass
<= PROTECTION_CLASS_F
));
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>.
351 static cp_key_os_version_t
352 parse_os_version(const char *vers
)
354 const char *p
= vers
;
357 while (*p
>= '0' && *p
<= '9') {
358 a
= a
* 10 + *p
- '0';
370 while (*p
>= '0' && *p
<= '9') {
371 c
= c
* 10 + *p
- '0';
378 return (a
& 0xff) << 24 | b
<< 16 | (c
& 0xffff);
384 static cp_key_os_version_t cp_os_version
;
387 return cp_os_version
;
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
);
398 return cp_os_version
;