Posts

Post marked as solved
6 Replies
4.5k Views
Hello,I'm running a regression tests agains iOS 13b4 and i have found an issue with the SecItemCopyMatching API.In iOS 12 the following class can generate a key-pair, and later on retrieve and query for the existance of a key given an alias:@interface PKIUtils : NSObject + (BOOL)generateKeyPair:(NSString* _Nonnull)alias error:(NSError* _Nullable* _Nullable)error; + (BOOL)hasKeyPair:(NSString* _Nonnull)alias; + (SecKeyRef) privateKeyForAlias:(NSString* _Nonnull) alias error:(NSError * _Nullable* _Nullable) error; @end @implementation PKIUtils + (BOOL)generateKeyPair:(NSString* _Nonnull)alias error:(NSError* _Nullable* _Nullable)error { if (!alias || alias.length <= 0) { NSLog(@"Alias cannot be empty"); return NO; } if ([self hasKeyPair:alias]) { NSLog(@"key already exists"); return NO; } NSDictionary* attributes = [self buildAttributes:alias error:error]; if (!attributes) { return NO; } CFErrorRef errorRef = nil; SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &errorRef); if (!privateKey) { if (error) *error = (__bridge NSError*)errorRef; return NO; } // release the private key reference as soon as it is not longer needed. CFRelease(privateKey); // everything went fine :) return YES; } + (NSDictionary*)buildAttributes:(NSString*)alias error:(NSError**)error { CFErrorRef errorRef = nil; UInt32 accessControlFlags = kSecAccessControlPrivateKeyUsage; SecAccessControlRef access = SecAccessControlCreateWithFlags(NULL, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, accessControlFlags, &errorRef); if (!access) { // unable to create the access Control reference if (error) *error = (__bridge NSError*)errorRef; return nil; } NSDictionary* attributes = @{ (__bridge NSString*)kSecAttrKeyType : (id)kSecAttrKeyTypeECSECPrimeRandom, (__bridge NSString*)kSecAttrKeySizeInBits : @256, (__bridge NSString*)kSecPrivateKeyAttrs : @{ (__bridge NSString*)kSecAttrIsPermanent : @YES, (__bridge NSString*)kSecAttrApplicationTag : [alias dataUsingEncoding:NSUTF8StringEncoding], (__bridge NSString*)kSecAttrAccessControl : (__bridge id)access, } }; // release the access control reference as soon as it is not longer needed. CFRelease(access); return attributes; } + (BOOL)hasKeyPair:(NSString* _Nonnull)alias { SecKeyRef privateKeyRef = [self privateKeyForAlias:alias error:nil]; return privateKeyRef != nil; } + (SecKeyRef) privateKeyForAlias:(NSString* _Nonnull) alias error:(NSError * _Nullable* _Nullable) error { NSDictionary* keyQuery = @{ (__bridge NSString*)kSecClass : (id)kSecClassKey, (__bridge NSString*)kSecAttrApplicationTag : [alias dataUsingEncoding:NSUTF8StringEncoding], (__bridge NSString*)kSecReturnRef : @YES }; SecKeyRef privateKeyRef = nil; OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)keyQuery, (CFTypeRef*)&privateKeyRef); if (status != noErr) { NSLog(@"Error retrieving key-pair from the storage (%@)", @(status)); return nil; } return privateKeyRef; } @endCalled from an app delegate as:NSError* error; NSString* alias = @"some alias" BOOL result = [PKIUtils generateKeyPair:alias error:&error]; if(result){ if([PKIUtils hasKeyPair:alias]){ NSLog(@"Hooray"); } else { NSLog(@"Oh no!"); } }However, in iOS 13b4, it can generate the key-pair, i can perform operations over the private key reference (export public key, sign, verify) but whenever i attempt to query for the same private key, it cannot be found. The OSStatus code returned is -25300 (item not found).Am i missing something?NOTES:- The code has only been tested on the simulator.- Moving to CrytoKit is not a viable option- I have attempted multiple combinations of parameters, all the same result.
Posted Last updated
.