]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/src/SecAKSWrappers.c
Security-58286.270.3.0.1.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 #if TARGET_OS_MAC && !TARGET_OS_EMBEDDED && TARGET_HAS_KEYSTORE
46 // OS X
47 const keybag_handle_t keybagHandle = session_keybag_handle;
48 #elif TARGET_HAS_KEYSTORE // iOS, but not simulator
49 const keybag_handle_t keybagHandle = device_keybag_handle;
50 #endif
51
52 #if TARGET_HAS_KEYSTORE
53 const AKSAssertionType_t lockAssertType = kAKSAssertTypeOther;
54 #endif
55
56 CFGiblisGetSingleton(dispatch_queue_t, GetKeybagAssertionQueue, sUserKeyBagAssertionLockQueue, ^{
57 *sUserKeyBagAssertionLockQueue = dispatch_queue_create("AKS Lock Assertion Queue", NULL);
58 })
59
60 #if TARGET_HAS_KEYSTORE
61 static uint32_t count = 0;
62 #endif
63 const char * const kUserKeybagStateChangeNotification = change_notification;
64
65 bool SecAKSLockUserKeybag(uint64_t timeout, CFErrorRef *error){
66 #if !TARGET_HAS_KEYSTORE
67 return true;
68 #else
69 __block kern_return_t status = kIOReturnSuccess;
70
71 dispatch_sync(GetKeybagAssertionQueue(), ^{
72 if (count == 0) {
73 secnotice("lockassertions", "Requesting lock assertion for %lld seconds", timeout);
74 status = aks_assert_hold(keybagHandle, lockAssertType, timeout);
75 }
76
77 if (status == kIOReturnSuccess)
78 ++count;
79 });
80 return SecKernError(status, error, CFSTR("Kern return error"));
81 #endif /* !TARGET_HAS_KEYSTORE */
82 }
83
84 bool SecAKSUnLockUserKeybag(CFErrorRef *error){
85 #if !TARGET_HAS_KEYSTORE
86 return true;
87 #else
88 __block kern_return_t status = kIOReturnSuccess;
89
90 dispatch_sync(GetKeybagAssertionQueue(), ^{
91 if (count && (--count == 0)) {
92 secnotice("lockassertions", "Dropping lock assertion");
93 status = aks_assert_drop(keybagHandle, lockAssertType);
94 }
95 });
96
97 return SecKernError(status, error, CFSTR("Kern return error"));
98 #endif /* !TARGET_HAS_KEYSTORE */
99 }
100
101
102 bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action)
103 {
104 #if !TARGET_HAS_KEYSTORE
105 action();
106 return true;
107 #else
108 // Acquire lock assertion, ref count?
109
110 bool status = false;
111 uint64_t timeout = 60ull;
112 if (SecAKSLockUserKeybag(timeout, error)) {
113 action();
114 status = SecAKSUnLockUserKeybag(error);
115 }
116 return status;
117 #endif /* !TARGET_HAS_KEYSTORE */
118 }
119 CFDataRef SecAKSCopyBackupBagWithSecret(size_t size, uint8_t *secret, CFErrorRef *error) {
120 #if !TARGET_HAS_KEYSTORE
121 return NULL;
122 #else
123 CFDataRef result = NULL;
124 void *keybagBytes = NULL;
125 int keybagSize = 0;
126
127 keybag_handle_t backupKeybagHandle = -1;
128 kern_return_t ret;
129
130 require_quiet(SecRequirementError(0 <= size && size <= INT_MAX, error, CFSTR("Invalid size: %zu"), size), fail);
131
132 ret = aks_create_bag(secret, (int) size, kAppleKeyStoreAsymmetricBackupBag, &backupKeybagHandle);
133
134 require_quiet(SecKernError(ret, error, CFSTR("bag allocation failed: %d"), ret), fail);
135
136 ret = aks_save_bag(backupKeybagHandle, &keybagBytes, &keybagSize);
137
138 require_quiet(SecKernError(ret, error, CFSTR("save bag failed: %d"), ret), fail);
139
140 ret = aks_unload_bag(backupKeybagHandle);
141
142 if (ret != KERN_SUCCESS) {
143 secerror("unload bag failed: %d", ret);
144 }
145
146 result = CFDataCreate(kCFAllocatorDefault, keybagBytes, keybagSize);
147
148 require_quiet(SecAllocationError(result, error, CFSTR("Bag CFData Allocation Failed")), fail);
149
150 fail:
151 if (keybagBytes)
152 free(keybagBytes);
153 return result;
154 #endif
155 }
156