security_framework/
access_control.rs1use std::fmt;
4use std::ptr::{self, null};
5use crate::base::{Error, Result};
6use core_foundation::{declare_TCFType, impl_TCFType};
7use core_foundation::base::{kCFAllocatorDefault, CFOptionFlags, TCFType};
8use core_foundation::string::CFString;
9use security_framework_sys::access_control::{
10 kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
11 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAttrAccessibleWhenUnlocked,
12 kSecAttrAccessibleWhenUnlockedThisDeviceOnly, SecAccessControlCreateWithFlags,
13 SecAccessControlGetTypeID,
14};
15use security_framework_sys::base::{errSecParam, SecAccessControlRef};
16
17declare_TCFType! {
18 SecAccessControl, SecAccessControlRef
20}
21impl_TCFType!(
22 SecAccessControl,
23 SecAccessControlRef,
24 SecAccessControlGetTypeID
25);
26
27unsafe impl Sync for SecAccessControl {}
28unsafe impl Send for SecAccessControl {}
29
30pub enum ProtectionMode {
32 AccessibleWhenPasscodeSetThisDeviceOnly,
35 AccessibleWhenUnlockedThisDeviceOnly,
38 AccessibleWhenUnlocked,
41 AccessibleAfterFirstUnlockThisDeviceOnly,
44 AccessibleAfterFirstUnlock,
47}
48
49impl SecAccessControl {
50 pub fn create_with_flags(flags: CFOptionFlags) -> Result<Self> {
52 Self::create_with_protection(None, flags)
53 }
54
55 pub fn create_with_protection(protection: Option<ProtectionMode>, flags: CFOptionFlags) -> Result<Self> {
57 let protection_val = protection.map(|v| {
58 match v {
59 ProtectionMode::AccessibleWhenPasscodeSetThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) },
60 ProtectionMode::AccessibleWhenUnlockedThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlockedThisDeviceOnly) },
61 ProtectionMode::AccessibleWhenUnlocked => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlocked) },
62 ProtectionMode::AccessibleAfterFirstUnlockThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) },
63 ProtectionMode::AccessibleAfterFirstUnlock => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlock) },
64 }
65 });
66 unsafe {
67 let access_control = SecAccessControlCreateWithFlags(
68 kCFAllocatorDefault,
69 protection_val.map(|v| v.as_CFTypeRef()).unwrap_or(null()),
70 flags,
71 ptr::null_mut(),
72 );
73 if access_control.is_null() {
74 Err(Error::from_code(errSecParam))
75 } else {
76 Ok(Self::wrap_under_create_rule(access_control))
77 }
78 }
79 }
80}
81
82impl fmt::Debug for SecAccessControl {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_struct("SecAccessControl").finish_non_exhaustive()
85 }
86}