SecItemCopyMatching returns -25300 - ios

I have the following codesnippet in my app.
CFTypeRef result = nil;
OSStatus userPresenceStatus = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
SecItemCopyMatching returns -25300. It happens on some iPhone 6 devices but not on every device. What does this code mean ? What can be the cause ?
Thanks for your advice
Frank

Error 25300 is errSecItemNotFound, which means that there is no such item in your key chain.
And you can find a list of potential result codes for Keychain Services here.
I'm guessing the keychain item you are trying to match against doesn't exist on that particular device.

Faced one more condition which can return an error -25300. Make sure that the data passed to kSecMatchIssuers or kSecMatchSearchList is of the same type. Loop through all filters and for each call SecItemCopyMatching
This is how you find the problematic element!

Related

sqlite3_prepare_v2 exc_bad_access in iOS 10

I have use sqlite in my iOS project for database. In iOS 9 all things are working perfectly. Now i have update new Xcode. But app is crashes many times at 'sqlite3_prepare_v2'.
Also, i am not closing database overtime. And open it only once.
I have added DB open in below code b'acs in debug i got DB close. But still got crash.
crash
Can anyone help me ?
Thanks in advance
I think issue is in line 2592.
Do not treat key as string when passing it to sqlite3_key(...)
Not sure how you generate key but if first byte is set '\0' then strlen return 0
(which may happen pretty often if you use some autogenerated helper based on NSData random bytes)
sqlite3_key definition:
SQLITE_API int SQLITE_STDCALL sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
It expects nKey bytes where "\0" is allowed too
Instead try:
NSData *passBytes = [g_sqlite_key dataUsingEncoding:NSUTF8StringEncoding];
int status = sqlite3_key(contactDB, passBytes.bytes, passBytes.length);
if (status != SQLITE_OK) {
// handle error and return
}
// continue...

H.264 : VTDecompressionSessionDecodeFrame fails with code 12909

I'm displaying RTSP streams from IP cameras. I want to replace this method avcodec_decode_video2 with VideoToolbox framework. I'm kinda new with video data processing so I'm a little lost...
I've tested both solutions from here and here, but I end up with a failure for this method VTDecompressionSessionDecodeFrame.
Error Domain=NSOSStatusErrorDomain Code=-12909 "The operation couldn’t be completed. (OSStatus error -12909.)" - -12909
I suspect this is coming from the session because if I call this VTDecompressionSessionCanAcceptFormatDescription right after creating the session, the result is NO.
Here is how is created my session :
VTDecompressionOutputCallbackRecord callback;
callback.decompressionOutputCallback = decompressionSessionDecodeFrameCallback;
callback.decompressionOutputRefCon = (__bridge void *)self;
NSDictionary *destinationImageBufferAttributes =[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],(id)kCVPixelBufferOpenGLESCompatibilityKey,[NSNumber numberWithInt:kCVPixelFormatType_32RGBA],(id)kCVPixelBufferPixelFormatTypeKey,nil];
OSStatus status = VTDecompressionSessionCreate(kCFAllocatorDefault, _formatDesc, NULL,
(__bridge CFDictionaryRef)destinationImageBufferAttributes,
&callback, &_decompressionSession);
I'm also not sure about the data to use. I have a choice between AVPacket.data, AVCodecContext.extradata, AVPacket.buf->data. Can anyone tell me which one should I use (maybe there is another one) ?
Thx in advance,
PS.: This is my first post ; let me know if it is not correctly presented/explained.
I've succeeded to get one successful status for this method. Turns out that I had indexes issues and the code I pasted had some bugs (at least, it wasn't adapted for my situation, specially for managing NALU types 1 and 5).
I have another issues because all the other calls returns a failure but I think I must post another question.

SecItemCopyMatching with kSecMatchItemList fails

I'm having trouble getting this call to work for IOS. I've tried a number of approaches but nothing seems to work: I always get a status of errSecParam. Can anyone tell me what I'm doing wrong?
I started out using this to get a list of attributes for a certificate I hydrated from bytes. That didn't work so I reduced it to this and received the same error. I've tested on the simulator and an iPhone6 and get the same results.
First I get an array of certificates and then I pass the array back to SecItemCopyMatching. I've tried this where I queried for attributes only and get the same error.
I'm new to IOS so I don't doubt it's something I've missed.
Thanks.
// Call SecItemCopyMatching twice: the first time fetch an array of certificates
// and the second time use the array with kSecMatchItemList.
- (void) SecItemCopyMatchingTest2 {
// Now read them from the keychain.
NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassCertificate,(__bridge id)kSecClass,
(__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnRef,
(__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit,
nil];
CFTypeRef result;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
NSArray *rgRefs = CFBridgingRelease(result);
if (status == noErr){
// this works
}
// Use the array we received from our previous call
[query setObject:rgRefs forKey:(__bridge id)kSecMatchItemList];
CFTypeRef result2;
// Results in status = errSecParam
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result2);
if (status == errSecParam){
// the cal fails.
}
}
Quote from the header file documentation:
#constant kSecMatchItemList OS X only. Specifies a dictionary key whose value is a CFArray of SecKeychainItemRef items. If provided, returned items will be limited to the subset which are contained in this list.
I know that the __OSX_AVAILABLE_STARTING claims it exists for iOS but that is a lie, on the mailing list an Apple developer claimed it has never been implemented for iOS.
Try setting the same array with kSecUseItemList. This wasn't implemented for iOS either at that time according to mailing list, but if Apple is going to implement either one for iOS (or has already done so), it's rather kSecUseItemList.
There are a lot of strange keychain API differences between macOS and iOS and some of these are only found in documentation or just in the header files. Here's another example from the SecItemDelete() delete documentation:
To delete an item identified by a transient reference, on iOS, specify kSecValueRef with a item reference. On OS X, give a kSecMatchItemList containing an item reference.
Trying to use kSecMatchItemList for that on iOS will fail, just like using kSecValueRef on macOS seems to fail. These API differences don't make any sense to me, but either you can do it with kSecUseItemList or you are out of luck and it's simply not possible on iOS.

OSStatus error code -34018

I am using SecItemCopyMatching to access the iOS keychain. About 1 in a hundred times I get a -34018 result code right after relaunching the app from the background. The documentation states:
The assigned error space for Keychain Services is discontinuous:
–25240 through –25279 and –25290 through –25329. Keychain Item
Services may also return noErr (0) or paramErr (–50), or CSSM result
codes
So it seems that -34018 is a 'CSSM result code'. I have followed the suggested link but could not find result codes.
What it the -34018 result code? How can I get more reliable keychain access?
- (NSData *)getKeychainData:(NSString *)key
{
NSDictionary *query = #{
(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService:SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount:key,
(__bridge id)kSecReturnData:#YES
};
CFDataRef result = nil;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:#"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
After some research, I found this: http://opensource.apple.com/source/Security/Security-55471/sec/Security/SecBasePriv.h
So -34018 is errSecMissingEntitlement and the comment says
Internal error when a required entitlement isn't present.
Do you experience this error while running your unit tests? If so, this might help: https://stackoverflow.com/a/22305193/171933
This issue on github says that it only seems to happen while debugging from Xcode: https://github.com/soffes/sskeychain/issues/97 (also see https://stackoverflow.com/a/28256591/171933)
Hopefully some of this will help!
I've been just researching the same error.
The gist of it is that the security service apple uses in order to communicate with the key chain, in rare cases, when the user's device is low on memory, crashes and taking away the app ability to talk to the keychain which results the dreadful -34018.
This is not happening only while running through Xcode like some may claim.
This is the most recent data regarding the issue taken from the Apple developer forums by one of the Apple staff:
UPDATE: We have finally been able to reproduce the -34018 error on iOS
8.3. This is the first step in identifying the root cause and then coming up with a fix.
As usual, we can't commit to a release timeframe, but this has
affected many developers and we really want to get this resolved.
Earlier I suggested adding a small delay in
application:didFinishLaunchingWithOptions and
applicationDidBecomeActive: before accessing the keychain as a
workaround. However, that doesn't actually appear to help. That means
that there's no known workaround at this time other than relaunching
the app.
The issue appears to be related to memory pressure, so perhaps being
more aggressive in handling memory warnings may alleviate the problem.
From Another Apple staff member:
Keychain engineering is well aware of how important this issue is.
The primary problem has been reproducing the failure here at Apple.
We're now able to do that (largely thanks to the work you guys have put in filing and following up on your bug reports).
From Another Apple staff member on Mar 22, 2016:
OK, here’s the latest. This is a complex problem with multiple
possible causes: Some instances of the problem are caused by incorrect
app signing. You can easily distinguish this case because the problem
is 100% reproducible. Some instances of the problem are caused by a
bug in how iOS supports app development (r. 23,991,853). Debugging
this was complicated by the fact that another bug in the OS (r.
23,770,418) masked its effect, meaning the problem only cropped up
when the device was under memory pressure. We believe these problems
were resolved in iOS 9.3. We suspect that there may be yet more causes
of this problem. So, if you see this problem on a user device (one
that hasn’t been talked to by Xcode) that’s running iOS 9.3 or later,
please do file a bug report about it. Try to include the device
system log in your bug report (I realise that can be tricky when
dealing with customer devices; one option is to ask the customer to
install Apple Configurator, which lets them view the system log). And
if you do file a bug, please post your bug number, just for the
record. On behalf of Apple I’d like to thank everyone for their
efforts in helping to track down this rather horrid issue. Share and
Enjoy
Unfortunately there are no known workarounds and the issue is still not fixed in 9.3.2 Beta 1 (13F51a)
This code works for me:
static const UInt8 kKeychainItemIdentifier[] = "com.apple.dts.KeychainUI\0";
- (NSData *)getKeychainData:(NSString *)key
{
NSData *keychainItemID = [NSData dataWithBytes:kKeychainItemIdentifier length:strlen((const char *)kKeychainItemIdentifier)];
NSDictionary *query = #{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: SEC_ATTR_SERVICE,
(__bridge id)kSecAttrAccount: key,
(__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrGeneric: keychainItemID
};
CFDataRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
if(status == errSecItemNotFound) {
return nil;
}
if(status == noErr) {
return CFBridgingRelease(result);
} else {
[self logError:[NSString stringWithFormat:#"SecItemCopyMatching status %d", (int)status] :nil];
return nil;
}
}
The main difference with OP's code is the addition of a Generic Attribute to the query. The Keychain Item Identifier is the default from apple. The reason behind this comes to differentiate possible different keychain items from each other. This is one way to make a more the keychain items access more reliable. Basically, in other words, this makes sure you access apple's default keychain.
After trying many of the fixes in stack overflow, things still didn't work for me.
What worked was switching the Keychain Sharing Capability in Xcode. Built and run and it worked right away.

How to update an already added SecIdentityRef to iOS app's keychain?

I have a PKCS12 file in my app's document folder that contains one certificate and one private key.
I am able to open this .p12 file, extract the identity object and display some information thanks to Apple's documentation (https://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html#//apple_ref/doc/uid/TP40001358-CH208-DontLinkElementID_10)
What I'm trying to do now is to store this Identity to the keychain so I can use it later. I've read a lot of different stuff on iOS Keychain and I'm having a hard time figuring out how it really works.
Apple's code seems to use a persistent_ref to retrieve the Identity stored in Keychain. But I don't really understand what this is... Is it a simple reference like a memory ref ? If that is the case what happens when the device reboots ?
Unable to find a lot more information about this I tried to do it differently by using the kSecAttr attributes.
The current code works fine to add Identity to keychain :
NSMutableDictionary * dictionary = [[[NSMutableDictionary alloc] init] autorelease];
[dictionary setObject:#"LABEL" forKey:kSecAttrLabel];
[dictionary setObject:(id)newIdentity forKey:(id)kSecValueRef];
OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
But if I try to add it a second time I'm receiving a -25299 error which is "fine" since it already exists. I tried handling it by an update like this :
NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease];
[searchDictionary setObject:#"LABEL" forKey:kSecAttrLabel];
[searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
[searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
[updateDictionary setObject:(id)newIdentity forKey:(id)kSecValueRef];
OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,(CFDictionaryRef)updateDictionary);
With this code I get a -50 status error apparently because I have invalid parameters... Which one ? Why ? What can I do to update my keychain correctly ?
EDIT: As suggested I tried to delete the existing element prior to adding it but I'm stuck with the same status code (-50). Below is the code I tried:
NSMutableDictionary *searchDictionary = [self setupSearchDirectoryForIdentifier:identifier];
OSStatus status = SecItemDelete((CFDictionaryRef)searchDictionary);
NSAssert(status == noErr, #"Problem deleting current keychain item." );
setupSearchDirectoryForIdentifier simply create a NSDictionnary with the label of my item:
- (NSMutableDictionary *)setupSearchDirectoryForIdentifier:(NSString *)identifier {
// Setup dictionary to access keychain.
NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease];
[searchDictionary setObject:identifier forKey:kSecAttrLabel];
return searchDictionary;
}
Thank you
PS : I'm developing on Xcode 4.2 / iPad 5.1.1
Even if this is an old post, as I came up with similar issues very recently when working with identities in keychains (to be used for SSL client authentication), I am providing my own experience (with XCode 5.0.1) as support for this seems to be still very confusing.
SecItemAdd must indeed be used with very few keys. kSecValueRef (with the identity) is of course mandatory and optionally kSecAttrLabel. Using several other keys (e.g. kSecClass) resulted in silent failures, i.e. no error reported but the identity wasn't added. This was very confusing.
I didn't succeed either to use SecItemUpdate with such an identity. All my attempts resulted in a -50 error.
To be able to update an existing identity I deleted the existing identity using SecItemDelete and then added it with SecItemAdd. What was again confusing is that although the call to SecItemDelete returned a -25300 error back (errSecItemNotFound), it could be ignored as the identity was indeed deleted as it was possible to add it afterwards (using SecItemAdd) without an error.
SecIdentityRefs, SecKeyRefs and similar Sec...Ref values are ephemeral representations of keychain items. They become invalid when the application exits or when their retain count reaches zero. They cannot be directly saved in persistent storage.
On the other hand, a persistent reference is a piece of CFDataRef that you can use to retrieve a particular keychain item later. You can store it in a file, in NSUserDefaults, or anywhere else you fancy. It will not become invalid when the application exits or when the device is rebooted. (However, a persistent reference may become invalid when the keychain itself is removed (i.e., when device is restored), when the item it refers to is deleted or when one of the item's identifying attributes is modified.)
Apple's sample code uses SecItemAdd's second argument to retrieve persistent references to the items it adds to the keychain. This is then presumably stored in NSUserDefaults. Given the persistent reference, the app can later use SecItemCopyMatching to convert it to an SecIdentityRef that it can use.
Note that you don't have to use persistent references if you don't want to; if you wish, you can also choose to retrieve keychain items based on their label, or any other identifying attribute.
SecItemUpdate probably fails because a SecIdentityRef isn't a real keychain item. It is but a pseudo-item that is constructed when a public key and its associated private key are both on the keychain. As such, it doesn't make much sense to update it -- it doesn't own any attributes. All its properties are inherited from its associated SecCertificateRef (the certificate) and SecKeyRef (the private key). Updating these items instead of the identity should work. (But it is easier to simply create the item correctly: you can initialize any attribute by adding it and its value to SecItemAdd's first parameter.) Alternatively, you could try simply deleting the identity (SecItemDelete) before re-adding it to the keychain.

Resources