]>
Commit | Line | Data |
---|---|---|
3e170ce0 A |
1 | /* |
2 | * Copyright (c) 2009-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 | #ifndef HFS_CPROTECT_H_ | |
30 | #define HFS_CPROTECT_H_ | |
31 | ||
32 | #if KERNEL_PRIVATE | |
33 | ||
34 | #include <sys/cprotect.h> | |
35 | ||
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> | |
41 | ||
42 | #include "hfs.h" | |
43 | #include "hfs_fsctl.h" | |
44 | ||
45 | __BEGIN_DECLS | |
46 | ||
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 */ | |
50 | ||
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 */ | |
54 | ||
55 | #define CP_LOCKED_KEYCHAIN 0 | |
56 | #define CP_UNLOCKED_KEYCHAIN 1 | |
57 | ||
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 | |
68 | ||
69 | /* the class occupies the lowest 5 bits, so there are 32 values (0-31) */ | |
70 | #define CP_EFFECTIVE_CLASSMASK 0x0000001f | |
71 | ||
72 | typedef uint32_t cp_key_class_t; | |
73 | typedef uint32_t cp_key_os_version_t; | |
74 | ||
75 | /* macros for quick access/typing to mask out the classmask */ | |
76 | #define CP_CLASS(x) ((cp_key_class_t)(CP_EFFECTIVE_CLASSMASK & (x))) | |
77 | ||
78 | #define CP_CRYPTO_G1 0x00000020 | |
79 | ||
80 | typedef struct cp_xattr *cp_xattr_t; | |
81 | typedef struct cnode * cnode_ptr_t; | |
82 | //forward declare the struct. | |
83 | struct hfsmount; | |
84 | ||
85 | /* | |
86 | * Flags for Key Generation Behavior | |
87 | * | |
88 | * These are passed to cp_generate_keys() and cp_new() in the | |
89 | * flags arguments | |
90 | */ | |
91 | #define CP_KEYWRAP_DIFFCLASS 0x00000001 /* wrapping with a different class bag is OK */ | |
92 | ||
93 | /* | |
94 | * off_rsrc_t: this structure represents an offset and whether or not it's | |
95 | * the resource fork. It's done this way so that we can easily do comparisons | |
96 | * i.e. | |
97 | * | |
98 | * { 0, data-fork } < { 100, rsrc-fork } | |
99 | */ | |
100 | ||
101 | enum { | |
102 | OFF_RSRC_BIT = 0x4000000000000000, | |
103 | }; | |
104 | ||
105 | typedef int64_t off_rsrc_t; | |
106 | ||
107 | static inline bool off_rsrc_is_rsrc(off_rsrc_t off_rsrc) | |
108 | { | |
109 | return off_rsrc & OFF_RSRC_BIT; | |
110 | } | |
111 | ||
112 | static inline off_t off_rsrc_get_off(off_rsrc_t off_rsrc) | |
113 | { | |
114 | return off_rsrc & (OFF_RSRC_BIT - 1); | |
115 | } | |
116 | ||
117 | static inline off_rsrc_t off_rsrc_make(off_t offset, bool is_rsrc) | |
118 | { | |
119 | return offset | (is_rsrc ? OFF_RSRC_BIT : 0); | |
120 | } | |
121 | ||
122 | // -- struct cpx -- | |
123 | ||
124 | /* | |
125 | * This structure contains the unwrapped key and is passed to the lower layers. | |
126 | * It is private so users must use the accessors declared in sys/cprotect.h | |
127 | * to read/write it. | |
128 | */ | |
129 | ||
130 | // cpx_flags | |
131 | typedef uint32_t cpx_flags_t; | |
132 | enum { | |
133 | CPX_SEP_WRAPPEDKEY = 0x01, | |
134 | CPX_IV_AES_CTX_INITIALIZED = 0x02, | |
135 | CPX_USE_OFFSET_FOR_IV = 0x04, | |
136 | ||
137 | // Using AES IV context generated from key | |
138 | CPX_IV_AES_CTX_HFS = 0x08, | |
139 | }; | |
140 | ||
141 | struct cpx { | |
142 | #if DEBUG | |
143 | uint32_t cpx_magic1; | |
144 | #endif | |
145 | cpx_flags_t cpx_flags; | |
146 | uint16_t cpx_max_key_len; | |
147 | uint16_t cpx_key_len; | |
148 | aes_encrypt_ctx cpx_iv_aes_ctx; // Context used for generating the IV | |
149 | uint8_t cpx_cached_key[]; | |
150 | } __attribute__((packed)); | |
151 | ||
152 | // -- struct cp_key_pair -- | |
153 | ||
154 | /* | |
155 | * This structure maintains the pair of keys; the persistent, wrapped key that | |
156 | * is written to disk, and the unwrapped key (cpx_t) that we pass to lower | |
157 | * layers. | |
158 | */ | |
159 | ||
160 | typedef struct cp_key_pair { | |
161 | uint16_t cpkp_max_pers_key_len; | |
162 | uint16_t cpkp_pers_key_len; | |
163 | struct cpx cpkp_cpx; | |
164 | ||
165 | // cpkp_cpx is variable length so the location of the persistent key varies | |
166 | // uint8_t cpkp_persistent_key[]; | |
167 | } cp_key_pair_t; | |
168 | ||
169 | // -- struct cprotect -- | |
170 | ||
171 | /* | |
172 | * Runtime-only structure containing the content protection status for | |
173 | * the given file. This is referenced by the cnode. It has the | |
174 | * variable length key pair at the end. | |
175 | */ | |
176 | ||
177 | typedef uint32_t cp_flags_t; | |
178 | enum { | |
179 | CP_NO_XATTR = 0x01, /* Key info has not been saved as EA to the FS */ | |
180 | CP_RELOCATION_INFLIGHT = 0x02, /* File with offset IVs is in the process of being relocated. */ | |
181 | ||
182 | CP_HAS_A_KEY = 0x08, /* File has a non-zero length key */ | |
183 | }; | |
184 | ||
185 | struct cprotect { | |
186 | #if DEBUG | |
187 | uint32_t cp_magic1; | |
188 | #endif | |
189 | cp_flags_t cp_flags; | |
190 | cp_key_class_t cp_pclass; /* persistent class stored on-disk */ | |
191 | void* cp_backing_cnode; | |
192 | cp_key_os_version_t cp_key_os_version; | |
193 | cp_key_revision_t cp_key_revision; | |
194 | uint16_t cp_raw_open_count; | |
195 | cp_key_pair_t cp_keys; // Variable length | |
196 | }; | |
197 | ||
198 | // -- On-Disk Structures -- | |
199 | ||
200 | typedef uint32_t cp_xattr_flags_t; | |
201 | enum { | |
202 | /* | |
203 | * Be careful about using flags 0x02 to 0x20. Older code used to write | |
204 | * flags that were used for in-memory purposes to disk and therefore | |
205 | * they might be used in V4 structures. Here's what they were: | |
206 | * | |
207 | * CP_KEY_FLUSHED 0x02 Should never have made it to disk | |
208 | * CP_NO_XATTR 0x04 Should never have made it to disk | |
209 | * CP_OFF_IV_ENABLED 0x08 Probably made it to disk | |
210 | * CP_RELOCATION_INFLIGHT 0x10 Should never have made it to disk | |
211 | * CP_SEP_WRAPPEDKEY 0x20 Probably made it to disk | |
212 | * | |
213 | */ | |
214 | ||
215 | CP_XAF_NEEDS_KEYS = 0x0001, /* V4 only: file needs persistent keys */ | |
216 | ||
217 | }; | |
218 | ||
219 | /* | |
220 | * V2 structure written as the per-file EA payload | |
221 | * All on-disk multi-byte fields for the CP XATTR must be stored | |
222 | * little-endian on-disk. This means they must be endian swapped to | |
223 | * L.E on getxattr() and converted to LE on setxattr(). | |
224 | * | |
225 | * This structure is a fixed length and is tightly packed. | |
226 | * 56 bytes total. | |
227 | */ | |
228 | struct cp_xattr_v2 { | |
229 | u_int16_t xattr_major_version; | |
230 | u_int16_t xattr_minor_version; | |
231 | cp_xattr_flags_t flags; | |
232 | u_int32_t persistent_class; | |
233 | u_int32_t key_size; | |
234 | uint8_t persistent_key[CP_V2_WRAPPEDKEYSIZE]; | |
235 | } __attribute__((aligned(2), packed)); | |
236 | ||
237 | ||
238 | /* | |
239 | * V4 Content Protection EA On-Disk Layout. | |
240 | * | |
241 | * This structure must be tightly packed, but the *size can vary* | |
242 | * depending on the length of the key. At MOST, the key length will be | |
243 | * CP_MAX_WRAPPEDKEYSIZE, but the length is defined by the key_size field. | |
244 | * | |
245 | * Either way, the packing must be applied to ensure that the key data is | |
246 | * retrievable in the right location relative to the start of the struct. | |
247 | * | |
248 | * Fully packed, this structure can range from : | |
249 | * MIN: 36 bytes (no key -- used with directories) | |
250 | * MAX: 164 bytes (with 128 byte key) | |
251 | * | |
252 | * During runtime we always allocate with the full 128 byte key, but only | |
253 | * use as much of the key buffer as needed. It must be tightly packed, though. | |
254 | */ | |
255 | ||
256 | struct cp_xattr_v4 { | |
257 | u_int16_t xattr_major_version; | |
258 | u_int16_t xattr_minor_version; | |
259 | cp_xattr_flags_t flags; | |
260 | cp_key_class_t persistent_class; | |
261 | u_int32_t key_size; | |
262 | // This field will be zero on older systems | |
263 | cp_key_os_version_t key_os_version; | |
264 | /* CP V4 Reserved Bytes == 16 */ | |
265 | u_int8_t reserved[CP_V4_RESERVEDBYTES]; | |
266 | /* All above fields are fixed regardless of key length (36 bytes) */ | |
267 | /* Max Wrapped Size == 128 */ | |
268 | uint8_t persistent_key[CP_MAX_WRAPPEDKEYSIZE]; | |
269 | } __attribute__((aligned(2), packed)); | |
270 | ||
271 | // -- Version 5 -- | |
272 | ||
273 | ||
274 | struct cp_xattr_v5 { | |
275 | uint16_t xattr_major_version; | |
276 | uint16_t xattr_minor_version; | |
277 | cp_xattr_flags_t flags; | |
278 | cp_key_class_t persistent_class; | |
279 | cp_key_os_version_t key_os_version; | |
280 | cp_key_revision_t key_revision; | |
281 | uint16_t key_len; | |
282 | ||
283 | // 20 bytes to here | |
284 | ||
285 | // Variable length from here | |
286 | uint8_t persistent_key[CP_MAX_WRAPPEDKEYSIZE]; | |
287 | ||
288 | ||
289 | // Wouldn't be necessary if xattr routines returned just what we ask for | |
290 | uint8_t spare[512]; | |
291 | } __attribute__((aligned(2), packed)); | |
292 | ||
293 | enum { | |
294 | CP_XATTR_MIN_LEN = 20, // Minimum length for all versions | |
295 | }; | |
296 | ||
297 | /* | |
298 | * The Root Directory's EA (fileid 1) is special; it defines information about | |
299 | * what capabilities the filesystem is using. | |
300 | * | |
301 | * The data is still stored little endian. | |
302 | */ | |
303 | struct cp_root_xattr { | |
304 | u_int16_t major_version; | |
305 | u_int16_t minor_version; | |
306 | u_int64_t flags; | |
307 | } __attribute__((aligned(2), packed)); | |
308 | ||
309 | enum { | |
310 | CP_ROOT_XATTR_MIN_LEN = 12, | |
311 | }; | |
312 | ||
313 | ||
314 | // -- Function Prototypes -- | |
315 | ||
316 | int cp_entry_init(cnode_ptr_t, struct mount *); | |
317 | int cpx_gentempkeys(cpx_t *pcpx, struct hfsmount *hfsmp); | |
318 | void cp_entry_destroy(struct hfsmount *hfsmp, struct cprotect *entry_ptr); | |
319 | void cp_replace_entry (struct hfsmount *hfsmp, struct cnode *cp, struct cprotect *newentry); | |
320 | cnode_ptr_t cp_get_protected_cnode(vnode_t); | |
321 | int cp_fs_protected (mount_t); | |
322 | int cp_getrootxattr (struct hfsmount *hfsmp, struct cp_root_xattr *outxattr); | |
323 | int cp_setrootxattr (struct hfsmount *hfsmp, struct cp_root_xattr *newxattr); | |
324 | int cp_generate_keys (struct hfsmount *hfsmp, struct cnode *cp, | |
325 | cp_key_class_t targetclass, uint32_t flags, | |
326 | struct cprotect **newentry); | |
327 | int cp_setup_newentry (struct hfsmount *hfsmp, struct cnode *dcp, | |
328 | cp_key_class_t suppliedclass, mode_t cmode, | |
329 | struct cprotect **tmpentry); | |
330 | int cp_is_valid_class (int isdir, int32_t protectionclass); | |
331 | int cp_set_trimmed(struct hfsmount*); | |
332 | int cp_set_rewrapped(struct hfsmount *); | |
333 | int cp_flop_generation (struct hfsmount*); | |
334 | bool cp_is_supported_version(uint16_t version); | |
335 | ||
336 | ||
337 | typedef struct cp_io_params { | |
338 | // The key to use | |
339 | cpx_t cpx; | |
340 | ||
341 | /* | |
342 | * The physical offset for this I/O or -1 if unknown (i.e. caller must | |
343 | * do a regular look up). | |
344 | */ | |
345 | off_t phys_offset; | |
346 | ||
347 | // The maximum length allowed for this I/O | |
348 | off_t max_len; | |
349 | } cp_io_params_t; | |
350 | ||
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); | |
354 | ||
355 | int cp_setxattr(struct cnode *cp, struct cprotect *entry, struct hfsmount *hfsmp, | |
356 | uint32_t fileid, int xattr_opts); | |
357 | ||
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); | |
361 | ||
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); | |
366 | ||
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); | |
370 | ||
371 | cprotect_t cp_entry_alloc(cprotect_t old, uint16_t pers_keylen, | |
372 | uint16_t cached_key_len, cp_key_pair_t **pcpkp); | |
373 | ||
374 | cp_key_os_version_t cp_os_version(void); | |
375 | ||
376 | cp_key_revision_t cp_next_key_revision(cp_key_revision_t rev); | |
377 | ||
378 | typedef uint32_t cp_getxattr_options_t; | |
379 | enum { | |
380 | // Return just basic information (not the key) | |
381 | CP_GET_XATTR_BASIC_INFO = 1, | |
382 | }; | |
383 | ||
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); | |
386 | ||
387 | ||
388 | errno_t cp_handle_strategy(buf_t bp); | |
389 | ||
390 | // -- cp_key_pair_t functions -- | |
391 | ||
392 | size_t cpkp_size(uint16_t pers_key_len, uint16_t cached_key_len); | |
393 | size_t cpkp_sizex(const cp_key_pair_t *cpkp); | |
394 | void cpkp_init(cp_key_pair_t *cpkp, uint16_t max_pers_key_len, | |
395 | uint16_t max_cached_key_len); | |
396 | void cpkp_flush(cp_key_pair_t *cpkp); | |
397 | void cpkp_copy(const cp_key_pair_t *src, cp_key_pair_t *dst); | |
398 | uint16_t cpkp_max_pers_key_len(const cp_key_pair_t *cpkp); | |
399 | uint16_t cpkp_pers_key_len(const cp_key_pair_t *cpkp); | |
400 | bool cpkp_can_copy(const cp_key_pair_t *src, const cp_key_pair_t *dst); | |
401 | ||
402 | // -- Private cpx functions -- | |
403 | ||
404 | void cpx_init(cpx_t, size_t key_len); | |
405 | bool cpx_has_key(const struct cpx *cpx); | |
406 | uint16_t cpx_max_key_len(const struct cpx *cpx); | |
407 | cpx_t cpkp_cpx(const cp_key_pair_t *cpkp); | |
408 | void cpx_copy(const struct cpx *src, cpx_t dst); | |
409 | ||
410 | // -- Helper Functions -- | |
411 | ||
412 | static inline int cp_get_crypto_generation (cp_key_class_t protclass) { | |
413 | if (protclass & CP_CRYPTO_G1) { | |
414 | return 1; | |
415 | } | |
416 | else return 0; | |
417 | } | |
418 | ||
419 | __END_DECLS | |
420 | ||
421 | #endif /* KERNEL_PRIVATE */ | |
422 | ||
423 | #endif /* !HFS_CPROTECT_H_ */ |