Skip to content

Commit

Permalink
Allow creating a SecAccessControl with a protection
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored and kornelski committed Mar 28, 2024
1 parent ee077dc commit ebcc98e
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 2 deletions.
1 change: 1 addition & 0 deletions security-framework-sys/src/access_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ extern "C" {
pub static kSecAttrAccessibleWhenUnlockedThisDeviceOnly: CFStringRef;
pub static kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: CFStringRef;
pub static kSecAttrAccessibleAlwaysThisDeviceOnly: CFStringRef;
pub static kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: CFStringRef;
}

extern "C" {
Expand Down
45 changes: 43 additions & 2 deletions security-framework/src/access_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand All @@ -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> {
Self::create_with_protection(None, flags)
}

/// Create `AccessControl` object from a protection value and flags.
pub fn create_with_protection(protection: Option<ProtectionMode>, flags: CFOptionFlags) -> Result<Self> {
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(),
);
Expand Down

0 comments on commit ebcc98e

Please sign in to comment.