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#ifndef _SECAKSWRAPPERS_H_
26#define _SECAKSWRAPPERS_H_
27
28#include <utilities/SecCFError.h>
29#include <AssertMacros.h>
30#include <dispatch/dispatch.h>
31
32#if TARGET_IPHONE_SIMULATOR
33
34#include <IOKit/IOReturn.h>
35
36// Make the compiler happy so this will compile.
37#define device_keybag_handle 0
38#define session_keybag_handle 0
39
40enum keybag_state {
41    keybag_state_unlocked = 0,
42    keybag_state_locked = 1 << 0,
43    keybag_state_no_pin = 1 << 1,
44    keybag_state_been_unlocked = 1 << 2,
45};
46typedef uint32_t keybag_state_t;
47typedef int32_t keybag_handle_t;
48
49static kern_return_t aks_get_lock_state(keybag_handle_t handle, keybag_state_t *state) {
50    if (state) *state = keybag_state_no_pin & keybag_state_been_unlocked;
51    return kIOReturnSuccess;
52}
53
54#else
55
56#include <libaks.h>
57
58#endif
59
60//
61// MARK: User lock state
62//
63
64enum {
65    user_keybag_handle = TARGET_OS_EMBEDDED ? device_keybag_handle : session_keybag_handle,
66};
67
68extern const char * const kUserKeybagStateChangeNotification;
69
70static inline bool SecAKSGetLockedState(keybag_state_t *state, CFErrorRef* error)
71{
72    kern_return_t status = aks_get_lock_state(user_keybag_handle, state);
73
74    if (kIOReturnSuccess != status) {
75        SecCFCreateError(status, CFSTR("com.apple.kern_return_t"), CFSTR("Kern return error"), NULL, error);
76        return false;
77    }
78
79    return true;
80}
81
82// returns true if any of the bits in bits is set in the current state of the user bag
83static inline bool SecAKSLockedAnyStateBitIsSet(bool* isSet, keybag_state_t bits, CFErrorRef* error)
84{
85    keybag_state_t state;
86    bool success = SecAKSGetLockedState(&state, error);
87
88    require_quiet(success, exit);
89
90    if (isSet)
91        *isSet = (state & bits);
92
93exit:
94    return success;
95
96}
97
98static inline bool SecAKSGetIsLocked(bool* isLocked, CFErrorRef* error)
99{
100    return SecAKSLockedAnyStateBitIsSet(isLocked, keybag_state_locked, error);
101}
102
103static inline bool SecAKSGetIsUnlocked(bool* isUnlocked, CFErrorRef* error)
104{
105    bool isLocked = false;
106    bool success = SecAKSGetIsLocked(&isLocked, error);
107
108    if (success && isUnlocked)
109        *isUnlocked = !isLocked;
110
111    return success;
112}
113
114static inline bool SecAKSGetHasBeenUnlocked(bool* hasBeenUnlocked, CFErrorRef* error)
115{
116    return SecAKSLockedAnyStateBitIsSet(hasBeenUnlocked, keybag_state_been_unlocked, error);
117}
118
119bool SecAKSDoWhileUserBagLocked(CFErrorRef *error, dispatch_block_t action);
120
121#endif
122