objc2 icon indicating copy to clipboard operation
objc2 copied to clipboard

Add examples for security framework

Open zemse opened this issue 3 months ago • 1 comments

I'm trying to migrate to objc2, coming from kornelski/rust-security-framework.

I was able to use the Objc2's local authentication framework in my codebase and it's working great, thanks!

However in case of security framework, I'm running into some type check errors that I'm not able to make sense of, would be really nice if I can get some pointers.

let query = CFMutableDictionary::new(
    kCFAllocatorDefault,
    1,
    &kCFTypeDictionaryKeyCallBacks,
    &kCFTypeDictionaryValueCallBacks,
)
.unwrap();

// Error on `add`: the trait bound `objc2_core_foundation::opaque::Opaque: objc2_core_foundation::Type` is not satisfied
query.add(kSecClass, kSecClassGenericPassword);
query.add(kSecMatchLimit, kSecMatchLimit);
query.add(kSecReturnData, kCFBooleanTrue);

let mut out: MaybeUninit<*const CFType> = MaybeUninit::uninit(); // Not sure if this is even correct
let result = SecItemCopyMatching(&query, out.as_mut_ptr());

Also would you be open for contributions into the examples of this repo?

zemse avatar Sep 16 '25 02:09 zemse

The issue here is that CFMutableDictionary::new is auto-generated and made non-generic (I'd like to fix that, but it's a breaking change, so haven't done so yet), whereas .add only works with correctly generic types.

I'd suggest you instead use the CFMutableDictionary::with_capacity wrapper to get the right type to begin with, and then remove the type information later on when calling SecItemCopyMatching. Something like the following:

let query = CFMutableDictionary::<CFString, CFString>::with_capacity(3);

query.add(kSecClass, kSecClassGenericPassword);
query.add(kSecMatchLimit, kSecMatchLimit);
query.add(kSecReturnData, kCFBooleanTrue);

let mut result: *const CFType = ptr::null();
// SAFETY: The query has the correct types, and `result` is a valid pointer.
let status = unsafe { SecItemCopyMatching(&query.as_opaque(), &mut result) };
if status != errSecSuccess {
    return Err(status);
}
// SAFETY: `SecItemCopyMatching` has "create" semantics, so we take
// ownership of the retain count here.
let result = unsafe { NonNull::new(result).map(|ptr| CFRetained::from_raw(ptr)) };

(I also cleaned up your result handling, I think this is roughly how it should be).

Also would you be open for contributions into the examples of this repo?

Very!

madsmtm avatar Sep 16 '25 05:09 madsmtm