]> git.saurik.com Git - apple/security.git/blob - Security/sec/securityd/SecKeybagSupport.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / sec / securityd / SecKeybagSupport.c
1 /*
2 * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * SecKeybagSupport.c - CoreFoundation-based constants and functions for
26 access to Security items (certificates, keys, identities, and
27 passwords.)
28 */
29
30 #include <securityd/SecKeybagSupport.h>
31
32 #include <securityd/SecItemServer.h>
33
34 #if USE_KEYSTORE
35 #include <IOKit/IOKitLib.h>
36 #include <libaks.h>
37 #include <libaks_acl_cf_keys.h>
38 #include <utilities/der_plist.h>
39 #include <corecrypto/ccder.h>
40 #if TARGET_OS_EMBEDDED
41 #include <MobileKeyBag/MobileKeyBag.h>
42 #endif
43 #endif /* USE_KEYSTORE */
44
45
46 /* g_keychain_handle is the keybag handle used for encrypting item in the keychain.
47 For testing purposes, it can be set to something other than the default, with SecItemServerSetKeychainKeybag */
48 #if USE_KEYSTORE
49 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED
50 keybag_handle_t g_keychain_keybag = session_keybag_handle;
51 #else
52 keybag_handle_t g_keychain_keybag = device_keybag_handle;
53 #endif
54 #else /* !USE_KEYSTORE */
55 keybag_handle_t g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */
56 #endif /* USE_KEYSTORE */
57
58 void SecItemServerSetKeychainKeybag(int32_t keybag)
59 {
60 g_keychain_keybag=keybag;
61 }
62
63 void SecItemServerResetKeychainKeybag(void)
64 {
65 #if USE_KEYSTORE
66 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED
67 g_keychain_keybag = session_keybag_handle;
68 #else
69 g_keychain_keybag = device_keybag_handle;
70 #endif
71 #else /* !USE_KEYSTORE */
72 g_keychain_keybag = 0; /* 0 == device_keybag_handle, constant dictated by AKS */
73 #endif /* USE_KEYSTORE */
74 }
75
76 #if USE_KEYSTORE
77
78 static bool hwaes_key_available(void)
79 {
80 keybag_handle_t handle = bad_keybag_handle;
81 keybag_handle_t special_handle = bad_keybag_handle;
82 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED
83 special_handle = session_keybag_handle;
84 #elif TARGET_OS_EMBEDDED
85 special_handle = device_keybag_handle;
86 #endif
87 kern_return_t kr = aks_get_system(special_handle, &handle);
88 if (kr != kIOReturnSuccess) {
89 #if TARGET_OS_EMBEDDED
90 /* TODO: Remove this once the kext runs the daemon on demand if
91 there is no system keybag. */
92 int kb_state = MKBGetDeviceLockState(NULL);
93 asl_log(NULL, NULL, ASL_LEVEL_INFO, "AppleKeyStore lock state: %d", kb_state);
94 #endif
95 }
96 return true;
97 }
98
99 #else /* !USE_KEYSTORE */
100
101 static bool hwaes_key_available(void)
102 {
103 return false;
104 }
105
106 #endif /* USE_KEYSTORE */
107
108 /* Wrap takes a 128 - 256 bit key as input and returns output of
109 inputsize + 64 bits.
110 In bytes this means that a
111 16 byte (128 bit) key returns a 24 byte wrapped key
112 24 byte (192 bit) key returns a 32 byte wrapped key
113 32 byte (256 bit) key returns a 40 byte wrapped key */
114 bool ks_crypt(uint32_t operation, keybag_handle_t keybag,
115 keyclass_t keyclass, uint32_t textLength, const uint8_t *source, keyclass_t *actual_class, CFMutableDataRef dest, CFErrorRef *error) {
116 #if USE_KEYSTORE
117 kern_return_t kernResult = kIOReturnBadArgument;
118
119 int dest_len = (int)CFDataGetLength(dest);
120 if (operation == kSecKsWrap) {
121 kernResult = aks_wrap_key(source, textLength, keyclass, keybag, CFDataGetMutableBytePtr(dest), &dest_len, actual_class);
122 } else if (operation == kSecKsUnwrap) {
123 kernResult = aks_unwrap_key(source, textLength, keyclass, keybag, CFDataGetMutableBytePtr(dest), &dest_len);
124 }
125
126 if (kernResult != KERN_SUCCESS) {
127 if ((kernResult == kIOReturnNotPermitted) || (kernResult == kIOReturnNotPrivileged)) {
128 /* Access to item attempted while keychain is locked. */
129 return SecError(errSecInteractionNotAllowed, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Access to item attempted while keychain is locked."),
130 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
131 } else if (kernResult == kIOReturnError) {
132 /* Item can't be decrypted on this device, ever, so drop the item. */
133 return SecError(errSecDecode, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted on this device, ever, so drop the item."),
134 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
135 } else {
136 return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: %x failed to %s item (class %"PRId32", bag: %"PRId32")"),
137 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
138 }
139 }
140 else
141 CFDataSetLength(dest, dest_len);
142 return true;
143 #else /* !USE_KEYSTORE */
144 uint32_t dest_len = (uint32_t)CFDataGetLength(dest);
145 if (operation == kSecKsWrap) {
146 /* The no encryption case. */
147 if (dest_len >= textLength + 8) {
148 memcpy(CFDataGetMutableBytePtr(dest), source, textLength);
149 memset(CFDataGetMutableBytePtr(dest) + textLength, 8, 8);
150 CFDataSetLength(dest, textLength + 8);
151 *actual_class = keyclass;
152 } else
153 return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to wrap item (class %"PRId32")"), keyclass);
154 } else if (operation == kSecKsUnwrap) {
155 if (dest_len + 8 >= textLength) {
156 memcpy(CFDataGetMutableBytePtr(dest), source, textLength - 8);
157 CFDataSetLength(dest, textLength - 8);
158 } else
159 return SecError(errSecNotAvailable, error, CFSTR("ks_crypt: failed to unwrap item (class %"PRId32")"), keyclass);
160 }
161 return true;
162 #endif /* USE_KEYSTORE */
163 }
164
165 #if USE_KEYSTORE
166 bool ks_crypt_acl(uint32_t operation, keybag_handle_t keybag, keyclass_t keyclass,
167 uint32_t textLength, const uint8_t *source, CFMutableDataRef dest,
168 CFDataRef acl, CFDataRef acm_context, CFDataRef caller_access_groups, CFErrorRef *error) {
169 kern_return_t kernResult = kIOReturnBadArgument;
170 uint8_t *params = NULL, *der = NULL;
171 const uint8_t *access_groups = caller_access_groups?CFDataGetBytePtr(caller_access_groups):NULL;
172 size_t params_len = 0, der_len = 0, access_groups_len = caller_access_groups?CFDataGetLength(caller_access_groups):0;
173
174 if (operation == kSecKsWrap) {
175 aks_operation_optional_params(0, 0, CFDataGetBytePtr(acl), CFDataGetLength(acl), 0, 0, (void**)&params, &params_len);
176 kernResult = aks_encrypt(keybag, keyclass, source, textLength, params, params_len, (void**)&der, &der_len);
177 } else if (operation == kSecKsUnwrap) {
178 aks_operation_optional_params(access_groups, access_groups_len, 0, 0, CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), (void**)&params, &params_len);
179 kernResult = aks_decrypt(keybag, source, textLength, params, params_len, (void**)&der, &der_len);
180 } else if (operation == kSecKsDelete) {
181 aks_operation_optional_params(access_groups, access_groups_len, 0, 0, CFDataGetBytePtr(acm_context), (int)CFDataGetLength(acm_context), (void**)&params, &params_len);
182 kernResult = aks_delete(keybag, source, textLength, params, params_len);
183 }
184
185 bool result = false;
186 if (kernResult != KERN_SUCCESS) {
187 if ((kernResult == kIOReturnNotPermitted) || (kernResult == kIOReturnNotPrivileged)) {
188 /* Access to item attempted while keychain is locked. */
189 result = SecError(errSecInteractionNotAllowed, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Access to item attempted while keychain is locked."),
190 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
191 } else if (kernResult == kIOReturnError) {
192 /* Item can't be decrypted on this device, ever, so drop the item. */
193 result = SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted on this device, ever, so drop the item."),
194 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
195 } else {
196 result = SecError(errSecNotAvailable, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32")"),
197 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag);
198 }
199 }
200 else {
201 if (operation != kSecKsDelete) {
202 const uint8_t *value = der;
203 if (operation == kSecKsUnwrap) {
204 ccder_tag der_tag;
205 size_t der_tag_len;
206 value = ccder_decode_tag(&der_tag, der, der + der_len);
207 value = ccder_decode_len(&der_tag_len, value, der + der_len);
208
209 require_action(der_tag == CCDER_OCTET_STRING, out,
210 SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted due to invalid der tag, so drop the item."),
211 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag));
212 require_action(der_tag_len == (size_t)((der + der_len) - value), out,
213 SecError(errSecDecode, error, CFSTR("ks_crypt_acl: %x failed to %s item (class %"PRId32", bag: %"PRId32") Item can't be decrypted due to invalid der tag length, so drop the item."),
214 kernResult, (operation == kSecKsWrap ? "wrap" : "unwrap"), keyclass, keybag));
215 }
216
217 if(CFDataGetLength(dest) != (der + der_len) - value)
218 CFDataSetLength(dest, (der + der_len) - value);
219
220 memcpy(CFDataGetMutableBytePtr(dest), value, CFDataGetLength(dest));
221 }
222 result = true;
223 }
224
225 out:
226 if(params)
227 free(params);
228 if(der)
229 free(der);
230 return result;
231 }
232 #endif
233
234 bool use_hwaes(void) {
235 static bool use_hwaes;
236 static dispatch_once_t check_once;
237 dispatch_once(&check_once, ^{
238 use_hwaes = hwaes_key_available();
239 if (use_hwaes) {
240 asl_log(NULL, NULL, ASL_LEVEL_INFO, "using hwaes key");
241 } else {
242 asl_log(NULL, NULL, ASL_LEVEL_ERR, "unable to access hwaes key");
243 }
244 });
245 return use_hwaes;
246 }
247
248 bool ks_open_keybag(CFDataRef keybag, CFDataRef password, keybag_handle_t *handle, CFErrorRef *error) {
249 #if USE_KEYSTORE
250 kern_return_t kernResult;
251 kernResult = aks_load_bag(CFDataGetBytePtr(keybag), (int)CFDataGetLength(keybag), handle);
252 if (kernResult)
253 return SecKernError(kernResult, error, CFSTR("aks_load_bag failed: %@"), keybag);
254
255 if (password) {
256 kernResult = aks_unlock_bag(*handle, CFDataGetBytePtr(password), (int)CFDataGetLength(password));
257 if (kernResult) {
258 aks_unload_bag(*handle);
259 return SecKernError(kernResult, error, CFSTR("aks_unlock_bag failed"));
260 }
261 }
262 return true;
263 #else /* !USE_KEYSTORE */
264 *handle = KEYBAG_NONE;
265 return true;
266 #endif /* USE_KEYSTORE */
267 }
268
269 bool ks_close_keybag(keybag_handle_t keybag, CFErrorRef *error) {
270 #if USE_KEYSTORE
271 IOReturn kernResult = aks_unload_bag(keybag);
272 if (kernResult) {
273 return SecKernError(kernResult, error, CFSTR("aks_unload_bag failed"));
274 }
275 #endif /* USE_KEYSTORE */
276 return true;
277 }