2 * Copyright (c) 2013-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@
29 #include <utilities/SecAKSWrappers.h>
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/SecCFError.h>
33 #if TARGET_IPHONE_SIMULATOR
34 # define change_notification "com.apple.will.never.happen"
35 #elif TARGET_OS_IPHONE
36 # include <MobileKeyBag/MobileKeyBag.h>
37 # define change_notification kMobileKeyBagLockStatusNotificationID
39 # include <AppleKeyStoreEvents.h>
40 # define change_notification kAppleKeyStoreLockStatusNotificationID
42 # error "unsupported target platform"
45 const char * const kUserKeybagStateChangeNotification
= change_notification
;
47 bool SecAKSDoWhileUserBagLocked(CFErrorRef
*error
, dispatch_block_t action
)
49 #if !TARGET_HAS_KEYSTORE
53 // Acquire lock assertion, ref count?
55 __block kern_return_t status
= kIOReturnSuccess
;
56 static dispatch_once_t queue_once
;
57 static dispatch_queue_t assertion_queue
;
59 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED // OS X
60 keybag_handle_t keybagHandle
= session_keybag_handle
;
61 #else // iOS, but not simulator
62 keybag_handle_t keybagHandle
= device_keybag_handle
;
64 AKSAssertionType_t lockAssertType
= kAKSAssertTypeOther
;
66 dispatch_once(&queue_once
, ^{
67 assertion_queue
= dispatch_queue_create("AKS Lock Assertion Queue", NULL
);
70 static uint32_t count
= 0;
72 dispatch_sync(assertion_queue
, ^{
74 uint64_t timeout
= 60ull;
75 secnotice("lockassertions", "Requesting lock assertion for %lld seconds", timeout
);
76 status
= aks_assert_hold(keybagHandle
, lockAssertType
, timeout
);
79 if (status
== kIOReturnSuccess
)
83 if (status
== kIOReturnSuccess
) {
85 dispatch_sync(assertion_queue
, ^{
86 if (count
&& (--count
== 0)) {
87 secnotice("lockassertions", "Dropping lock assertion");
88 status
= aks_assert_drop(keybagHandle
, lockAssertType
);
92 return SecKernError(status
, error
, CFSTR("Kern return error"));
93 #endif /* !TARGET_HAS_KEYSTORE */
96 CFDataRef
SecAKSCopyBackupBagWithSecret(size_t size
, uint8_t *secret
, CFErrorRef
*error
) {
97 #if !TARGET_HAS_KEYSTORE
100 CFDataRef result
= NULL
;
101 void *keybagBytes
= NULL
;
104 keybag_handle_t backupKeybagHandle
= -1;
107 require_quiet(SecRequirementError(0 <= size
&& size
<= INT_MAX
, error
, CFSTR("Invalid size: %zu"), size
), fail
);
109 ret
= aks_create_bag(secret
, (int) size
, kAppleKeyStoreAsymmetricBackupBag
, &backupKeybagHandle
);
111 require_quiet(SecKernError(ret
, error
, CFSTR("bag allocation failed: %d"), ret
), fail
);
113 ret
= aks_save_bag(backupKeybagHandle
, &keybagBytes
, &keybagSize
);
115 require_quiet(SecKernError(ret
, error
, CFSTR("save bag failed: %d"), ret
), fail
);
117 ret
= aks_unload_bag(backupKeybagHandle
);
119 if (ret
!= KERN_SUCCESS
) {
120 secerror("unload bag failed: %d", ret
);
123 result
= CFDataCreate(kCFAllocatorDefault
, keybagBytes
, keybagSize
);
125 require_quiet(SecAllocationError(result
, error
, CFSTR("Bag CFData Allocation Failed")), fail
);