I have objc function that return SecIdentityRef
(SecIdentityRef)getSecIdentity {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"cert1" ofType:@"p12"];
NSData *p12Data = [NSData dataWithContentsOfFile:resourcePath];
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[options setObject:@"123456" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import((CFDataRef) p12Data,
(CFDictionaryRef)options, &items);
if (securityError == noErr && CFArrayGetCount(items) > 0) {
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identityApp =
(SecIdentityRef)CFDictionaryGetValue(identityDict,
kSecImportItemIdentity);
CFRelease(items);
return identityApp;
}
CFRelease(items);
return NULL;
}
I import class with this function in bridging header, then use it in swift code
let test = Certificate.getSecIdentity()
let secIdentity = test.takeUnretainedValue()
From Certificate.getSecIdentity()
returns Unmanaged<SecIdentityRef>
with correct (?) SecIdentity inside.
On test.takeUnretainedValue()
(and test.takeRetainedValue()
) I receive
Thread 1: EXC_BAD_ACCESS (code=1, address=0x2d13e474f3e0)
What I do wrong? How can I get SecIdentity?
CodePudding user response:
When you retrieve an element from (i believe) any core foundation collection, the collection functions follows the Get-Rule. It means that you don't own the element until you explicitly retain it. Thus in this part of your code:
SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); CFRelease(items);
You essentially release both items
and identityApp
and return a dangling pointer (a dangling core foundation reference to be precise). Just retain the instance of SecIdentityRef
before your release the items
array like that:
CFRetain(identityApp);
CFRelease(items);
return identityApp;
P.S. since your function may return NULL
, you better make the result nullable
, especially when working with Swift, so it knows the result is an optional value:
(nullable SecIdentityRef)getSecIdentity
P.P.S. you also may want to rewrite you code in Swift directly, since it supports work with SecCertificate