security_framework/
access_control.rs1use crate::base::{Error, Result};
4use core_foundation::base::{kCFAllocatorDefault, CFOptionFlags, TCFType};
5use core_foundation::string::CFString;
6use core_foundation::{declare_TCFType, impl_TCFType};
7use security_framework_sys::access_control::{
8 kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
9 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAttrAccessibleWhenUnlocked,
10 kSecAttrAccessibleWhenUnlockedThisDeviceOnly, SecAccessControlCreateWithFlags,
11 SecAccessControlGetTypeID,
12};
13use security_framework_sys::base::{errSecParam, SecAccessControlRef};
14use std::fmt;
15use std::ptr;
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 }).unwrap_or_else(|| {
66 unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlocked) }
67 });
68 unsafe {
69 let access_control = SecAccessControlCreateWithFlags(
70 kCFAllocatorDefault,
71 protection_val.as_CFTypeRef(),
72 flags,
73 ptr::null_mut(),
74 );
75 if access_control.is_null() {
76 Err(Error::from_code(errSecParam))
77 } else {
78 Ok(Self::wrap_under_create_rule(access_control))
79 }
80 }
81 }
82}
83
84impl fmt::Debug for SecAccessControl {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.debug_struct("SecAccessControl").finish_non_exhaustive()
87 }
88}