2 * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * SecKeybagSupport.c - CoreFoundation-based constants and functions for
26 access to Security items (certificates, keys, identities, and
30 #include <securityd/SecKeybagSupport.h>
32 #include <securityd/SecItemServer.h>
35 #include <IOKit/IOKitLib.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>
43 #endif /* USE_KEYSTORE */
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 */
49 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED
50 keybag_handle_t g_keychain_keybag
= session_keybag_handle
;
52 keybag_handle_t g_keychain_keybag
= device_keybag_handle
;
54 #else /* !USE_KEYSTORE */
55 keybag_handle_t g_keychain_keybag
= 0; /* 0 == device_keybag_handle, constant dictated by AKS */
56 #endif /* USE_KEYSTORE */
58 void SecItemServerSetKeychainKeybag(int32_t keybag
)
60 g_keychain_keybag
=keybag
;
63 void SecItemServerResetKeychainKeybag(void)
66 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED
67 g_keychain_keybag
= session_keybag_handle
;
69 g_keychain_keybag
= device_keybag_handle
;
71 #else /* !USE_KEYSTORE */
72 g_keychain_keybag
= 0; /* 0 == device_keybag_handle, constant dictated by AKS */
73 #endif /* USE_KEYSTORE */
78 static bool hwaes_key_available(void)
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
;
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
);
99 #else /* !USE_KEYSTORE */
101 static bool hwaes_key_available(void)
106 #endif /* USE_KEYSTORE */
108 /* Wrap takes a 128 - 256 bit key as input and returns output of
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
) {
117 kern_return_t kernResult
= kIOReturnBadArgument
;
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
);
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
);
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
);
141 CFDataSetLength(dest
, dest_len
);
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
;
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);
159 return SecError(errSecNotAvailable
, error
, CFSTR("ks_crypt: failed to unwrap item (class %"PRId32
")"), keyclass
);
162 #endif /* 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;
174 if (operation
== kSecKsWrap
) {
175 aks_operation_optional_params(0, 0, CFDataGetBytePtr(acl
), CFDataGetLength(acl
), 0, 0, (void**)¶ms
, ¶ms_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**)¶ms
, ¶ms_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**)¶ms
, ¶ms_len
);
182 kernResult
= aks_delete(keybag
, source
, textLength
, params
, params_len
);
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
);
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
);
201 if (operation
!= kSecKsDelete
) {
202 const uint8_t *value
= der
;
203 if (operation
== kSecKsUnwrap
) {
206 value
= ccder_decode_tag(&der_tag
, der
, der
+ der_len
);
207 value
= ccder_decode_len(&der_tag_len
, value
, der
+ der_len
);
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
));
217 if(CFDataGetLength(dest
) != (der
+ der_len
) - value
)
218 CFDataSetLength(dest
, (der
+ der_len
) - value
);
220 memcpy(CFDataGetMutableBytePtr(dest
), value
, CFDataGetLength(dest
));
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();
240 asl_log(NULL
, NULL
, ASL_LEVEL_INFO
, "using hwaes key");
242 asl_log(NULL
, NULL
, ASL_LEVEL_ERR
, "unable to access hwaes key");
248 bool ks_open_keybag(CFDataRef keybag
, CFDataRef password
, keybag_handle_t
*handle
, CFErrorRef
*error
) {
250 kern_return_t kernResult
;
251 kernResult
= aks_load_bag(CFDataGetBytePtr(keybag
), (int)CFDataGetLength(keybag
), handle
);
253 return SecKernError(kernResult
, error
, CFSTR("aks_load_bag failed: %@"), keybag
);
256 kernResult
= aks_unlock_bag(*handle
, CFDataGetBytePtr(password
), (int)CFDataGetLength(password
));
258 aks_unload_bag(*handle
);
259 return SecKernError(kernResult
, error
, CFSTR("aks_unlock_bag failed"));
263 #else /* !USE_KEYSTORE */
264 *handle
= KEYBAG_NONE
;
266 #endif /* USE_KEYSTORE */
269 bool ks_close_keybag(keybag_handle_t keybag
, CFErrorRef
*error
) {
271 IOReturn kernResult
= aks_unload_bag(keybag
);
273 return SecKernError(kernResult
, error
, CFSTR("aks_unload_bag failed"));
275 #endif /* USE_KEYSTORE */