2 * Copyright (c) 2009-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 #ifndef HFS_CPROTECT_H_
30 #define HFS_CPROTECT_H_
34 #include <sys/cprotect.h>
36 #include <sys/cdefs.h>
37 #include <sys/content_protection.h>
38 #include <sys/kernel_types.h>
39 #include <crypto/aes.h>
40 #include <sys/kdebug.h>
43 #include "hfs_fsctl.h"
47 #define CP_IV_KEYSIZE 16 /* 16x8 = 128 */
48 #define CP_MAX_KEYSIZE 32 /* 8x4 = 32, 32x8 = 256 */
49 #define CP_MAX_CACHEBUFLEN 64 /* Maximum size of cp cache buffer/array */
51 #define CP_INITIAL_WRAPPEDKEYSIZE 40
52 #define CP_V2_WRAPPEDKEYSIZE 40 /* Size of the wrapped key in a v2 EA */
53 #define CP_V4_RESERVEDBYTES 16 /* Number of reserved bytes in EA still present */
55 #define CP_LOCKED_KEYCHAIN 0
56 #define CP_UNLOCKED_KEYCHAIN 1
58 #define CONTENT_PROTECTION_XATTR_NAME "com.apple.system.cprotect"
59 #define CONTENT_PROTECTION_XATTR_NAME_CHARS \
60 { 'c', 'o', 'm', '.', 'a', 'p', 'p', 'l', 'e', \
61 '.', 's', 'y', 's', 't', 'e', 'm', \
62 '.', 'c', 'p', 'r', 'o', 't', 'e', 'c', 't' }
63 #define CP_CURRENT_VERS CP_VERS_5
64 #define CP_VERS_5 5 // iOS 8.1
65 #define CP_VERS_4 4 // iOS 5
66 #define CP_VERS_2 2 // iOS 4
67 #define CP_MINOR_VERS 0
69 /* the class occupies the lowest 5 bits, so there are 32 values (0-31) */
70 #define CP_EFFECTIVE_CLASSMASK 0x0000001f
72 /* macros for quick access/typing to mask out the classmask */
73 #define CP_CLASS(x) ((cp_key_class_t)(CP_EFFECTIVE_CLASSMASK & (x)))
75 #define CP_CRYPTO_G1 0x00000020
77 typedef struct cp_xattr
*cp_xattr_t
;
78 typedef struct cnode
* cnode_ptr_t
;
79 //forward declare the struct.
83 * Flags for Key Generation Behavior
85 * These are passed to cp_generate_keys() and cp_new() in the
88 #define CP_KEYWRAP_DIFFCLASS 0x00000001 /* wrapping with a different class bag is OK */
91 * off_rsrc_t: this structure represents an offset and whether or not it's
92 * the resource fork. It's done this way so that we can easily do comparisons
95 * { 0, data-fork } < { 100, rsrc-fork }
99 OFF_RSRC_BIT
= 0x4000000000000000,
102 typedef int64_t off_rsrc_t
;
104 static inline bool off_rsrc_is_rsrc(off_rsrc_t off_rsrc
)
106 return off_rsrc
& OFF_RSRC_BIT
;
109 static inline off_t
off_rsrc_get_off(off_rsrc_t off_rsrc
)
111 return off_rsrc
& (OFF_RSRC_BIT
- 1);
114 static inline off_rsrc_t
off_rsrc_make(off_t offset
, bool is_rsrc
)
116 return offset
| (is_rsrc
? OFF_RSRC_BIT
: 0);
119 // -- struct cp_key_pair --
122 * This structure maintains the pair of keys; the persistent, wrapped key that
123 * is written to disk, and the unwrapped key (cpx_t) that we pass to lower
127 typedef struct cp_key_pair
{
128 uint16_t cpkp_max_pers_key_len
;
129 uint16_t cpkp_pers_key_len
;
132 // cpkp_cpx is variable length so the location of the persistent key varies
133 // uint8_t cpkp_persistent_key[];
136 // -- struct cprotect --
139 * Runtime-only structure containing the content protection status for
140 * the given file. This is referenced by the cnode. It has the
141 * variable length key pair at the end.
144 typedef uint32_t cp_flags_t
;
146 CP_NO_XATTR
= 0x01, /* Key info has not been saved as EA to the FS */
147 CP_RELOCATION_INFLIGHT
= 0x02, /* File with offset IVs is in the process of being relocated. */
149 #if HFS_CONFIG_KEY_ROLL
150 // These flags are only set if you ask for basic info from read_xattr_v5
151 CP_KEY_IS_ROLLING
= 0x04, /* File is in the middle of key rolling */
153 CP_HAS_A_KEY
= 0x08, /* File has a non-zero length key */
156 typedef struct cprotect
{
161 cp_key_class_t cp_pclass
; /* persistent class stored on-disk */
162 void* cp_backing_cnode
;
163 cp_key_os_version_t cp_key_os_version
;
164 cp_key_revision_t cp_key_revision
;
165 uint16_t cp_raw_open_count
;
166 #if HFS_CONFIG_KEY_ROLL
167 struct hfs_cp_key_roll_ctx
*cp_key_roll_ctx
;
169 cp_key_pair_t cp_keys
; // Variable length
172 // -- On-Disk Structures --
174 typedef uint32_t cp_xattr_flags_t
;
177 * Be careful about using flags 0x02 to 0x20. Older code used to write
178 * flags that were used for in-memory purposes to disk and therefore
179 * they might be used in V4 structures. Here's what they were:
181 * CP_KEY_FLUSHED 0x02 Should never have made it to disk
182 * CP_NO_XATTR 0x04 Should never have made it to disk
183 * CP_OFF_IV_ENABLED 0x08 Probably made it to disk
184 * CP_RELOCATION_INFLIGHT 0x10 Should never have made it to disk
185 * CP_SEP_WRAPPEDKEY 0x20 Probably made it to disk
189 CP_XAF_NEEDS_KEYS
= 0x0001, /* V4 only: file needs persistent keys */
194 * V2 structure written as the per-file EA payload
195 * All on-disk multi-byte fields for the CP XATTR must be stored
196 * little-endian on-disk. This means they must be endian swapped to
197 * L.E on getxattr() and converted to LE on setxattr().
199 * This structure is a fixed length and is tightly packed.
203 u_int16_t xattr_major_version
;
204 u_int16_t xattr_minor_version
;
205 cp_xattr_flags_t flags
;
206 u_int32_t persistent_class
;
208 uint8_t persistent_key
[CP_V2_WRAPPEDKEYSIZE
];
209 } __attribute__((aligned(2), packed
));
213 * V4 Content Protection EA On-Disk Layout.
215 * This structure must be tightly packed, but the *size can vary*
216 * depending on the length of the key. At MOST, the key length will be
217 * CP_MAX_WRAPPEDKEYSIZE, but the length is defined by the key_size field.
219 * Either way, the packing must be applied to ensure that the key data is
220 * retrievable in the right location relative to the start of the struct.
222 * Fully packed, this structure can range from :
223 * MIN: 36 bytes (no key -- used with directories)
224 * MAX: 164 bytes (with 128 byte key)
226 * During runtime we always allocate with the full 128 byte key, but only
227 * use as much of the key buffer as needed. It must be tightly packed, though.
231 u_int16_t xattr_major_version
;
232 u_int16_t xattr_minor_version
;
233 cp_xattr_flags_t flags
;
234 cp_key_class_t persistent_class
;
236 // This field will be zero on older systems
237 cp_key_os_version_t key_os_version
;
238 /* CP V4 Reserved Bytes == 16 */
239 u_int8_t reserved
[CP_V4_RESERVEDBYTES
];
240 /* All above fields are fixed regardless of key length (36 bytes) */
241 /* Max Wrapped Size == 128 */
242 uint8_t persistent_key
[CP_MAX_WRAPPEDKEYSIZE
];
243 } __attribute__((aligned(2), packed
));
247 #if HFS_CONFIG_KEY_ROLL
248 struct cp_roll_info
{
251 uint8_t key
[CP_MAX_WRAPPEDKEYSIZE
];
252 } __attribute__((aligned(2), packed
));
256 uint16_t xattr_major_version
;
257 uint16_t xattr_minor_version
;
258 cp_xattr_flags_t flags
;
259 cp_key_class_t persistent_class
;
260 cp_key_os_version_t key_os_version
;
261 cp_key_revision_t key_revision
;
266 // Variable length from here
267 uint8_t persistent_key
[CP_MAX_WRAPPEDKEYSIZE
];
269 #if HFS_CONFIG_KEY_ROLL
270 // NOTE: data not necessarily here because preceding is variable
271 uint8_t roll_key_
[sizeof(struct cp_roll_info
)];
274 // Wouldn't be necessary if xattr routines returned just what we ask for
276 } __attribute__((aligned(2), packed
));
279 CP_XATTR_MIN_LEN
= 20, // Minimum length for all versions
283 * The Root Directory's EA (fileid 1) is special; it defines information about
284 * what capabilities the filesystem is using.
286 * The data is still stored little endian.
288 struct cp_root_xattr
{
289 u_int16_t major_version
;
290 u_int16_t minor_version
;
292 #if HFS_CONFIG_KEY_ROLL
293 cp_key_os_version_t auto_roll_min_version
;
294 cp_key_os_version_t auto_roll_max_version
;
296 } __attribute__((aligned(2), packed
));
299 CP_ROOT_XATTR_MIN_LEN
= 12,
303 // -- Function Prototypes --
305 int cp_entry_init(cnode_ptr_t
, struct mount
*);
306 int cpx_gentempkeys(cpx_t
*pcpx
, struct hfsmount
*hfsmp
);
307 void cp_entry_destroy(struct hfsmount
*hfsmp
, struct cprotect
*entry_ptr
);
308 void cp_replace_entry (struct hfsmount
*hfsmp
, struct cnode
*cp
, struct cprotect
*newentry
);
309 cnode_ptr_t
cp_get_protected_cnode(vnode_t
);
310 int cp_fs_protected (mount_t
);
311 int cp_getrootxattr (struct hfsmount
*hfsmp
, struct cp_root_xattr
*outxattr
);
312 int cp_setrootxattr (struct hfsmount
*hfsmp
, struct cp_root_xattr
*newxattr
);
313 int cp_generate_keys (struct hfsmount
*hfsmp
, struct cnode
*cp
,
314 cp_key_class_t targetclass
, uint32_t flags
,
315 struct cprotect
**newentry
);
316 int cp_setup_newentry (struct hfsmount
*hfsmp
, struct cnode
*dcp
,
317 cp_key_class_t suppliedclass
, mode_t cmode
,
318 struct cprotect
**tmpentry
);
319 int cp_is_valid_class (int isdir
, int32_t protectionclass
);
320 int cp_set_trimmed(struct hfsmount
*);
321 int cp_set_rewrapped(struct hfsmount
*);
322 int cp_flop_generation (struct hfsmount
*);
323 bool cp_is_supported_version(uint16_t version
);
324 int cp_vnode_getclass(struct vnode
*vp
, cp_key_class_t
*class);
325 int cp_vnode_setclass(struct vnode
*vp
, cp_key_class_t newclass
);
326 int cp_get_root_major_vers(vnode_t vp
, uint32_t *level
);
327 int cp_vnode_transcode(vnode_t vp
, cp_key_t
*k
);
328 int cp_get_default_level (struct vnode
*vp
, uint32_t *level
);
329 void cp_device_locked_callback(mount_t mp
, cp_lock_state_t state
);
331 #if HFS_CONFIG_KEY_ROLL
332 bool cp_should_auto_roll(struct hfsmount
*hfsmp
, cprotect_t cpr
);
333 errno_t
cp_set_auto_roll(struct hfsmount
*hfsmp
,
334 const hfs_key_auto_roll_args_t
*args
);
337 typedef struct cp_io_params
{
342 * The physical offset for this I/O or -1 if unknown (i.e. caller must
343 * do a regular look up).
347 // The maximum length allowed for this I/O
351 // Return the I/O parameters for this I/O
352 void cp_io_params(struct hfsmount
*hfsmp
, cprotect_t cpr
, off_rsrc_t off_rsrc
,
353 int direction
, cp_io_params_t
*io_params
);
355 int cp_setxattr(struct cnode
*cp
, struct cprotect
*entry
, struct hfsmount
*hfsmp
,
356 uint32_t fileid
, int xattr_opts
);
358 typedef void * (* cp_new_alloc_fn
)(const void *old
, uint16_t pers_key_len
,
359 uint16_t cached_key_len
,
360 cp_key_pair_t
**pcpkp
);
362 int cp_new(cp_key_class_t
*newclass_eff
, struct hfsmount
*hfsmp
,
363 struct cnode
*cp
, mode_t cmode
, int32_t keyflags
,
364 cp_key_revision_t key_revision
,
365 cp_new_alloc_fn alloc_fn
, void **pholder
);
367 int cp_rewrap(struct cnode
*cp
, __unused
struct hfsmount
*hfsmp
,
368 cp_key_class_t
*newclass
, cp_key_pair_t
*cpkp
, const void *old_holder
,
369 cp_new_alloc_fn alloc_fn
, void **pholder
);
371 cprotect_t
cp_entry_alloc(cprotect_t old
, uint16_t pers_keylen
,
372 uint16_t cached_key_len
, cp_key_pair_t
**pcpkp
);
374 cp_key_os_version_t
cp_os_version(void);
376 cp_key_revision_t
cp_next_key_revision(cp_key_revision_t rev
);
378 typedef uint32_t cp_getxattr_options_t
;
380 // Return just basic information (not the key)
381 CP_GET_XATTR_BASIC_INFO
= 1,
384 int cp_read_xattr_v5(struct hfsmount
*hfsmp
, struct cp_xattr_v5
*xattr
,
385 size_t xattr_len
, cprotect_t
*pcpr
, cp_getxattr_options_t options
);
388 errno_t
cp_handle_strategy(buf_t bp
);
391 CP_READ_ACCESS
= 0x1,
392 CP_WRITE_ACCESS
= 0x2
395 int cp_handle_open(struct vnode
*vp
, int mode
);
396 int cp_handle_vnop(struct vnode
*vp
, int mode
, int ioflag
);
398 // -- cp_key_pair_t functions --
400 size_t cpkp_size(uint16_t pers_key_len
, uint16_t cached_key_len
);
401 size_t cpkp_sizex(const cp_key_pair_t
*cpkp
);
402 void cpkp_init(cp_key_pair_t
*cpkp
, uint16_t max_pers_key_len
,
403 uint16_t max_cached_key_len
);
404 void cpkp_flush(cp_key_pair_t
*cpkp
);
405 void cpkp_copy(const cp_key_pair_t
*src
, cp_key_pair_t
*dst
);
406 uint16_t cpkp_max_pers_key_len(const cp_key_pair_t
*cpkp
);
407 uint16_t cpkp_pers_key_len(const cp_key_pair_t
*cpkp
);
408 bool cpkp_can_copy(const cp_key_pair_t
*src
, const cp_key_pair_t
*dst
);
409 cpx_t
cpkp_cpx(const cp_key_pair_t
*cpkp
) __attribute__((pure
));
411 // -- Helper Functions --
413 static inline int cp_get_crypto_generation (cp_key_class_t protclass
) {
414 if (protclass
& CP_CRYPTO_G1
) {
422 #endif // CONFIG_PROTECT
424 #endif /* !HFS_CPROTECT_H_ */