]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/SecAKSWrappers.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / utilities / src / SecAKSWrappers.c
1 /*
2 * Copyright (c) 2013-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 // SecAKSWrappers.c
26 // utilities
27 //
28
29 #include <utilities/SecAKSWrappers.h>
30 #include <utilities/SecCFWrappers.h>
31 #include <utilities/SecCFError.h>
32
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
38 #elif TARGET_OS_MAC
39 # include <AppleKeyStoreEvents.h>
40 # define change_notification kAppleKeyStoreLockStatusNotificationID
41 #else
42 # error "unsupported target platform"
43 #endif
44
45 const char * const kUserKeybagStateChangeNotification = change_notification;
46
47 bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action)
48 {
49 #if !TARGET_HAS_KEYSTORE
50 action();
51 return true;
52 #else
53 // Acquire lock assertion, ref count?
54
55 __block kern_return_t status = kIOReturnSuccess;
56 static dispatch_once_t queue_once;
57 static dispatch_queue_t assertion_queue;
58
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;
63 #endif
64 AKSAssertionType_t lockAssertType = kAKSAssertTypeOther;
65
66 dispatch_once(&queue_once, ^{
67 assertion_queue = dispatch_queue_create("AKS Lock Assertion Queue", NULL);
68 });
69
70 static uint32_t count = 0;
71
72 dispatch_sync(assertion_queue, ^{
73 if (count == 0) {
74 uint64_t timeout = 60ull;
75 secnotice("lockassertions", "Requesting lock assertion for %lld seconds", timeout);
76 status = aks_assert_hold(keybagHandle, lockAssertType, timeout);
77 }
78
79 if (status == kIOReturnSuccess)
80 ++count;
81 });
82
83 if (status == kIOReturnSuccess) {
84 action();
85 dispatch_sync(assertion_queue, ^{
86 if (count && (--count == 0)) {
87 secnotice("lockassertions", "Dropping lock assertion");
88 status = aks_assert_drop(keybagHandle, lockAssertType);
89 }
90 });
91 }
92 return SecKernError(status, error, CFSTR("Kern return error"));
93 #endif /* !TARGET_HAS_KEYSTORE */
94 }
95
96 CFDataRef SecAKSCopyBackupBagWithSecret(size_t size, uint8_t *secret, CFErrorRef *error) {
97 #if !TARGET_HAS_KEYSTORE
98 return NULL;
99 #else
100 CFDataRef result = NULL;
101 void *keybagBytes = NULL;
102 int keybagSize = 0;
103
104 keybag_handle_t backupKeybagHandle = -1;
105 kern_return_t ret;
106
107 require_quiet(SecRequirementError(0 <= size && size <= INT_MAX, error, CFSTR("Invalid size: %zu"), size), fail);
108
109 ret = aks_create_bag(secret, (int) size, kAppleKeyStoreAsymmetricBackupBag, &backupKeybagHandle);
110
111 require_quiet(SecKernError(ret, error, CFSTR("bag allocation failed: %d"), ret), fail);
112
113 ret = aks_save_bag(backupKeybagHandle, &keybagBytes, &keybagSize);
114
115 require_quiet(SecKernError(ret, error, CFSTR("save bag failed: %d"), ret), fail);
116
117 ret = aks_unload_bag(backupKeybagHandle);
118
119 if (ret != KERN_SUCCESS) {
120 secerror("unload bag failed: %d", ret);
121 }
122
123 result = CFDataCreate(kCFAllocatorDefault, keybagBytes, keybagSize);
124
125 require_quiet(SecAllocationError(result, error, CFSTR("Bag CFData Allocation Failed")), fail);
126
127 fail:
128 if (keybagBytes)
129 free(keybagBytes);
130 return result;
131 #endif
132 }
133