#include <utilities/SecAKSWrappers.h>
#include <utilities/SecCFWrappers.h>
#if TARGET_IPHONE_SIMULATOR
# define change_notification "com.apple.will.never.happen"
#elif TARGET_OS_IPHONE
# include <MobileKeyBag/MobileKeyBag.h>
# define change_notification kMobileKeyBagLockStatusNotificationID
#elif TARGET_OS_MAC
# include <AppleKeyStoreEvents.h>
# define change_notification kAppleKeyStoreLockStatusNotificationID
#else
# error "unsupported target platform"
#endif
const char * const kUserKeybagStateChangeNotification = change_notification;
bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action)
{
#if TARGET_IPHONE_SIMULATOR
action();
return true;
#else
__block kern_return_t status = kIOReturnSuccess;
static dispatch_once_t queue_once;
static dispatch_queue_t assertion_queue;
#if TARGET_OS_MAC && !TARGET_OS_EMBEDDED // OS X
AKSAssertionType_t lockAssertType = kAKSAssertTypeOther;
keybag_handle_t keybagHandle = session_keybag_handle;
#else // iOS, but not simulator
AKSAssertionType_t lockAssertType = kAKSAssertTypeProfile; keybag_handle_t keybagHandle = device_keybag_handle;
#endif
dispatch_once(&queue_once, ^{
assertion_queue = dispatch_queue_create("AKS Lock Assertion Queue", NULL);
});
static uint32_t count = 0;
dispatch_sync(assertion_queue, ^{
if (count == 0) {
uint64_t timeout = 60ull;
secnotice("lockassertions", "Requesting lock assertion for %lld seconds", timeout);
status = aks_assert_hold(keybagHandle, lockAssertType, timeout);
}
if (status == kIOReturnSuccess)
++count;
});
if (status == kIOReturnSuccess) {
action();
dispatch_sync(assertion_queue, ^{
if (count && (--count == 0)) {
secnotice("lockassertions", "Dropping lock assertion");
status = aks_assert_drop(keybagHandle, lockAssertType);
}
});
}
return SecKernError(status, error, CFSTR("Kern return error"));
#endif
}