diff --git a/security-framework-sys/src/access_control.rs b/security-framework-sys/src/access_control.rs index 9089ab64..e5e18d6f 100644 --- a/security-framework-sys/src/access_control.rs +++ b/security-framework-sys/src/access_control.rs @@ -31,6 +31,7 @@ extern "C" { pub static kSecAttrAccessibleWhenUnlockedThisDeviceOnly: CFStringRef; pub static kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: CFStringRef; pub static kSecAttrAccessibleAlwaysThisDeviceOnly: CFStringRef; + pub static kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: CFStringRef; } extern "C" { diff --git a/security-framework/src/access_control.rs b/security-framework/src/access_control.rs index 15a6d700..dfaa4541 100644 --- a/security-framework/src/access_control.rs +++ b/security-framework/src/access_control.rs @@ -2,8 +2,16 @@ use std::ptr::{self, null}; +use core_foundation::string::CFString; use core_foundation::base::{TCFType, CFOptionFlags, kCFAllocatorDefault}; -use security_framework_sys::access_control::{SecAccessControlGetTypeID, SecAccessControlCreateWithFlags}; +use security_framework_sys::access_control::{ + SecAccessControlGetTypeID, SecAccessControlCreateWithFlags, + kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + kSecAttrAccessibleWhenUnlocked, + kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, + kSecAttrAccessibleAfterFirstUnlock +}; use security_framework_sys::base::{SecAccessControlRef, errSecParam}; use crate::base::{Error, Result}; @@ -20,13 +28,46 @@ impl_TCFType!( unsafe impl Sync for SecAccessControl {} unsafe impl Send for SecAccessControl {} +/// Specify when an item is available. +pub enum ProtectionMode { + /// The data in the keychain can only be accessed when the device is + /// unlocked. Only available if a passcode is set on the device. + AccessibleWhenPasscodeSetThisDeviceOnly, + ///The data in the keychain item can be accessed only while the device is + /// unlocked by the user. + AccessibleWhenUnlockedThisDeviceOnly, + /// The data in the keychain item can be accessed only while the device is + /// unlocked by the user. + AccessibleWhenUnlocked, + /// The data in the keychain item cannot be accessed after a restart until + /// the device has been unlocked once by the user. + AccessibleAfterFirstUnlockThisDeviceOnly, + /// The data in the keychain item cannot be accessed after a restart until + /// the device has been unlocked once by the user. + AccessibleAfterFirstUnlock, +} + impl SecAccessControl { /// Create `AccessControl` object from flags pub fn create_with_flags(flags: CFOptionFlags) -> Result { + Self::create_with_protection(None, flags) + } + + /// Create `AccessControl` object from a protection value and flags. + pub fn create_with_protection(protection: Option, flags: CFOptionFlags) -> Result { + let protection_val = protection.map(|v| { + match v { + ProtectionMode::AccessibleWhenPasscodeSetThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly) }, + ProtectionMode::AccessibleWhenUnlockedThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlockedThisDeviceOnly) }, + ProtectionMode::AccessibleWhenUnlocked => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleWhenUnlocked) }, + ProtectionMode::AccessibleAfterFirstUnlockThisDeviceOnly => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly) }, + ProtectionMode::AccessibleAfterFirstUnlock => unsafe { CFString::wrap_under_get_rule(kSecAttrAccessibleAfterFirstUnlock) }, + } + }); unsafe { let access_control = SecAccessControlCreateWithFlags( kCFAllocatorDefault, - null(), + protection_val.map(|v| v.as_CFTypeRef()).unwrap_or(null()), flags, ptr::null_mut(), );