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,
57 CPX_COMPOSITEKEY
= 0x20
64 aes_encrypt_ctx cpx_iv_aes_ctx
; // Context used for generating the IV
65 cpx_flags_t cpx_flags
;
66 uint16_t cpx_max_key_len
;
68 uint8_t cpx_cached_key
[];
71 // -- cpx_t accessors --
73 size_t cpx_size(size_t key_size
)
75 size_t size
= sizeof(struct cpx
) + key_size
;
78 size
+= 4; // Extra for magic
84 size_t cpx_sizex(const struct cpx
*cpx
)
86 return cpx_size(cpx
->cpx_max_key_len
);
89 cpx_t
cpx_alloc(size_t key_len
)
93 MALLOC(cpx
, cpx_t
, cpx_size(key_len
), M_TEMP
, M_WAITOK
);
95 cpx_init(cpx
, key_len
);
101 static const uint32_t cpx_magic1
= 0x7b787063; // cpx{
102 static const uint32_t cpx_magic2
= 0x7870637d; // }cpx
105 void cpx_free(cpx_t cpx
)
108 assert(cpx
->cpx_magic1
== cpx_magic1
);
109 assert(*PTR_ADD(uint32_t *, cpx
, cpx_sizex(cpx
) - 4) == cpx_magic2
);
111 bzero(cpx
->cpx_cached_key
, cpx
->cpx_max_key_len
);
115 void cpx_init(cpx_t cpx
, size_t key_len
)
118 cpx
->cpx_magic1
= cpx_magic1
;
119 *PTR_ADD(uint32_t *, cpx
, cpx_size(key_len
) - 4) = cpx_magic2
;
122 cpx
->cpx_key_len
= 0;
123 cpx
->cpx_max_key_len
= key_len
;
126 bool cpx_is_sep_wrapped_key(const struct cpx
*cpx
)
128 return ISSET(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
131 void cpx_set_is_sep_wrapped_key(struct cpx
*cpx
, bool v
)
134 SET(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
136 CLR(cpx
->cpx_flags
, CPX_SEP_WRAPPEDKEY
);
139 bool cpx_is_composite_key(const struct cpx
*cpx
)
141 return ISSET(cpx
->cpx_flags
, CPX_COMPOSITEKEY
);
144 void cpx_set_is_composite_key(struct cpx
*cpx
, bool v
)
147 SET(cpx
->cpx_flags
, CPX_COMPOSITEKEY
);
149 CLR(cpx
->cpx_flags
, CPX_COMPOSITEKEY
);
152 bool cpx_use_offset_for_iv(const struct cpx
*cpx
)
154 return ISSET(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
157 void cpx_set_use_offset_for_iv(struct cpx
*cpx
, bool v
)
160 SET(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
162 CLR(cpx
->cpx_flags
, CPX_USE_OFFSET_FOR_IV
);
165 bool cpx_synthetic_offset_for_iv(const struct cpx
*cpx
)
167 return ISSET(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
170 void cpx_set_synthetic_offset_for_iv(struct cpx
*cpx
, bool v
)
173 SET(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
175 CLR(cpx
->cpx_flags
, CPX_SYNTHETIC_OFFSET_FOR_IV
);
178 uint16_t cpx_max_key_len(const struct cpx
*cpx
)
180 return cpx
->cpx_max_key_len
;
183 uint16_t cpx_key_len(const struct cpx
*cpx
)
185 return cpx
->cpx_key_len
;
188 void cpx_set_key_len(struct cpx
*cpx
, uint16_t key_len
)
190 cpx
->cpx_key_len
= key_len
;
192 if (ISSET(cpx
->cpx_flags
, CPX_IV_AES_CTX_VFS
)) {
194 * We assume that if the key length is being modified, the key
195 * has changed. As a result, un-set any bits related to the
196 * AES context, if needed. They should be re-generated
199 CLR(cpx
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
| CPX_IV_AES_CTX_VFS
);
203 bool cpx_has_key(const struct cpx
*cpx
)
205 return cpx
->cpx_key_len
> 0;
208 #pragma clang diagnostic push
209 #pragma clang diagnostic ignored "-Wcast-qual"
210 void *cpx_key(const struct cpx
*cpx
)
212 return (void *)cpx
->cpx_cached_key
;
214 #pragma clang diagnostic pop
216 void cpx_set_aes_iv_key(struct cpx
*cpx
, void *iv_key
)
218 aes_encrypt_key128(iv_key
, &cpx
->cpx_iv_aes_ctx
);
219 SET(cpx
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
| CPX_USE_OFFSET_FOR_IV
);
220 CLR(cpx
->cpx_flags
, CPX_IV_AES_CTX_VFS
);
223 aes_encrypt_ctx
*cpx_iv_aes_ctx(struct cpx
*cpx
)
225 if (ISSET(cpx
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
))
226 return &cpx
->cpx_iv_aes_ctx
;
229 uint8_t digest
[SHA_DIGEST_LENGTH
]; /* Kiv */
231 /* First init the cp_cache_iv_key[] */
235 * We can only use this when the keys are generated in the AP; As a result
236 * we only use the first 32 bytes of key length in the cache key
238 SHA1Update(&sha1ctxt
, cpx
->cpx_cached_key
, cpx
->cpx_key_len
);
239 SHA1Final(digest
, &sha1ctxt
);
241 cpx_set_aes_iv_key(cpx
, digest
);
242 SET(cpx
->cpx_flags
, CPX_IV_AES_CTX_VFS
);
244 return &cpx
->cpx_iv_aes_ctx
;
247 void cpx_flush(cpx_t cpx
)
249 bzero(cpx
->cpx_cached_key
, cpx
->cpx_max_key_len
);
250 bzero(&cpx
->cpx_iv_aes_ctx
, sizeof(cpx
->cpx_iv_aes_ctx
));
252 cpx
->cpx_key_len
= 0;
255 bool cpx_can_copy(const struct cpx
*src
, const struct cpx
*dst
)
257 return src
->cpx_key_len
<= dst
->cpx_max_key_len
;
260 void cpx_copy(const struct cpx
*src
, cpx_t dst
)
262 uint16_t key_len
= cpx_key_len(src
);
263 cpx_set_key_len(dst
, key_len
);
264 memcpy(cpx_key(dst
), cpx_key(src
), key_len
);
265 dst
->cpx_flags
= src
->cpx_flags
;
266 if (ISSET(dst
->cpx_flags
, CPX_IV_AES_CTX_INITIALIZED
))
267 dst
->cpx_iv_aes_ctx
= src
->cpx_iv_aes_ctx
;
271 cp_lock_state_t state
;
274 } cp_lock_vfs_callback_arg
;
277 cp_lock_vfs_callback(mount_t mp
, void *arg
)
279 cp_lock_vfs_callback_arg
*callback_arg
= (cp_lock_vfs_callback_arg
*)arg
;
281 if (callback_arg
->valid_uuid
) {
284 VFSATTR_WANTED(&va
, f_uuid
);
286 if (vfs_getattr(mp
, &va
, vfs_context_current()))
289 if (!VFSATTR_IS_SUPPORTED(&va
, f_uuid
))
292 if(memcmp(va
.f_uuid
, callback_arg
->volume_uuid
, sizeof(uuid_t
)))
296 VFS_IOCTL(mp
, FIODEVICELOCKED
, (void *)(uintptr_t)callback_arg
->state
, 0, vfs_context_kernel());
301 cp_key_store_action(cp_key_store_action_t action
)
303 cp_lock_vfs_callback_arg callback_arg
;
306 case CP_ACTION_LOCKED
:
307 case CP_ACTION_UNLOCKED
:
308 callback_arg
.state
= (action
== CP_ACTION_LOCKED
? CP_LOCKED_STATE
: CP_UNLOCKED_STATE
);
309 memset(callback_arg
.volume_uuid
, 0, sizeof(uuid_t
));
310 callback_arg
.valid_uuid
= 0;
311 return vfs_iterate(0, cp_lock_vfs_callback
, (void *)&callback_arg
);
318 cp_key_store_action_for_volume(uuid_t volume_uuid
, cp_key_store_action_t action
)
320 cp_lock_vfs_callback_arg callback_arg
;
323 case CP_ACTION_LOCKED
:
324 case CP_ACTION_UNLOCKED
:
325 callback_arg
.state
= (action
== CP_ACTION_LOCKED
? CP_LOCKED_STATE
: CP_UNLOCKED_STATE
);
326 memcpy(callback_arg
.volume_uuid
, volume_uuid
, sizeof(uuid_t
));
327 callback_arg
.valid_uuid
= 1;
328 return vfs_iterate(0, cp_lock_vfs_callback
, (void *)&callback_arg
);
335 cp_is_valid_class(int isdir
, int32_t protectionclass
)
338 * The valid protection classes are from 0 -> N
339 * We use a signed argument to detect unassigned values from
340 * directory entry creation time in HFS.
343 /* Directories are not allowed to have F, but they can have "NONE" */
344 return ((protectionclass
>= PROTECTION_CLASS_DIR_NONE
) &&
345 (protectionclass
<= PROTECTION_CLASS_D
));
348 return ((protectionclass
>= PROTECTION_CLASS_A
) &&
349 (protectionclass
<= PROTECTION_CLASS_F
));
354 * Parses versions of the form 12A316, i.e. <major><minor><revision> and
355 * returns a uint32_t in the form 0xaabbcccc where aa = <major>,
356 * bb = <ASCII char>, cccc = <revision>.
358 static cp_key_os_version_t
359 parse_os_version(const char *vers
)
361 const char *p
= vers
;
364 while (*p
>= '0' && *p
<= '9') {
365 a
= a
* 10 + *p
- '0';
377 while (*p
>= '0' && *p
<= '9') {
378 c
= c
* 10 + *p
- '0';
385 return (a
& 0xff) << 24 | b
<< 16 | (c
& 0xffff);
391 static cp_key_os_version_t cp_os_version
;
394 return cp_os_version
;
399 cp_os_version
= parse_os_version(osversion
);
400 if (!cp_os_version
) {
401 printf("cp_os_version: unable to parse osversion `%s'\n", osversion
);
405 return cp_os_version
;