I work on an app which have to accessing keychain items with biometric method( face id or touch id) . We have received an issue that is user installed the app and do registration to insert the data into keychain for later use, then delete and reinstall the app . When user try to do the registration againn, keychain SecItemAdd method failed with error code -25330. The user use iPhone 12(iOS 14.3) and it happen irregularly.
The log:
18:35:44.261389+0800 securityd deleted <genp,acct=,svce=,agrp=XXXXX,sync=0,musr=, |otherAttr,tomb=0,rowid=78066,cdat=2021-04-29 10:35:44 +0000,mdat=2021-04-29 10:35:44 +0000,sha1=823CD54A2E06C44D941F0C349CBAEC06FBEEC1E2,accc=318183300C0C0470726F740C04616B707530730C0361636C316C30070C026F6501010130090C046F64656C01010130560C026F643150304E0C046362696F314630190C057062696F630410186F86E694AB529847803D3747422E2B30290C057062696F680420467A9C1598FB013ECA1030956B7E73C7CF030994BB45BA21268D111593093233,UUID=F07953A7-55A0-46E0-9052-7B98833B5B03,persistref=,clip=0> from <SecDbConnection rw open>
18:35:44.263070+0800 securityd insert failed for item <genp,acct=bio_account_46323731353237383231,svce=bio_service_46323731353237383231,agrp=XXXXX,sync=0,musr=, |otherAttr,tomb=0,cdat=2021-04-29 10:35:44 +0000,mdat=2021-04-29 10:35:44 +0000,labl=636F6D2E656E74696562616E6B2E6170702E7561742E4175746853444B,pdmn=akpu,sha1=BE484AB751AC112E689819E3D83A2FDD45A73D8E,v_Data=<?>,accc=3153300C0C0470726F740C04616B707530430C0361636C313C30070C026F6501010130090C046F64656C01010130260C026F643120301E0C046362696F311630090C057062696F63040030090C057062696F680400,UUID=E76CF22A-67CD-4CEC-B522-1C2700C58FB6,persistref=,clip=0> with Error Domain=NSOSStatusErrorDomain Code=-25330 "(null)" UserInfo={-25330=(
(
{length = 85, bytes = 0x3153300c 0c047072 6f740c04 616b7075 ... 03706279 6f680410 },
""
)
)}
The related code:
ViewController
code for insert into keychain
Has anyone got any ideas why this is happening and how to fix it ? Thanks.
The log:
18:35:44.261389+0800 securityd deleted <genp,acct=,svce=,agrp=XXXXX,sync=0,musr=, |otherAttr,tomb=0,rowid=78066,cdat=2021-04-29 10:35:44 +0000,mdat=2021-04-29 10:35:44 +0000,sha1=823CD54A2E06C44D941F0C349CBAEC06FBEEC1E2,accc=318183300C0C0470726F740C04616B707530730C0361636C316C30070C026F6501010130090C046F64656C01010130560C026F643150304E0C046362696F314630190C057062696F630410186F86E694AB529847803D3747422E2B30290C057062696F680420467A9C1598FB013ECA1030956B7E73C7CF030994BB45BA21268D111593093233,UUID=F07953A7-55A0-46E0-9052-7B98833B5B03,persistref=,clip=0> from <SecDbConnection rw open>
18:35:44.263070+0800 securityd insert failed for item <genp,acct=bio_account_46323731353237383231,svce=bio_service_46323731353237383231,agrp=XXXXX,sync=0,musr=, |otherAttr,tomb=0,cdat=2021-04-29 10:35:44 +0000,mdat=2021-04-29 10:35:44 +0000,labl=636F6D2E656E74696562616E6B2E6170702E7561742E4175746853444B,pdmn=akpu,sha1=BE484AB751AC112E689819E3D83A2FDD45A73D8E,v_Data=<?>,accc=3153300C0C0470726F740C04616B707530430C0361636C313C30070C026F6501010130090C046F64656C01010130260C026F643120301E0C046362696F311630090C057062696F63040030090C057062696F680400,UUID=E76CF22A-67CD-4CEC-B522-1C2700C58FB6,persistref=,clip=0> with Error Domain=NSOSStatusErrorDomain Code=-25330 "(null)" UserInfo={-25330=(
(
{length = 85, bytes = 0x3153300c 0c047072 6f740c04 616b7075 ... 03706279 6f680410 },
""
)
)}
The related code:
ViewController
Code Block objective-c - (IBAction)registerAction:(id)sender { NSString *service = [NSString stringWithFormat:@"bio_service_%@", username]; NSString *account = [NSString stringWithFormat:@"bio_account_%@", username]; BOOL success = [Keychain insertBioAuthDataWithAccount:account service:service generic:nil data:data]; if (success) { // do something } // error handling }
code for insert into keychain
Code Block objective-c + (NSMutableDictionary*) prepareBioAuthDictWithAccount:(NSString *) account service:(NSString*) service generic:(NSString*) generic bioMsg:(NSString*)bioMsg { CFErrorRef *err = nil; SecAccessControlRef sacRef = nil; if (@available(iOS 11.3, *)) { sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlBiometryCurrentSet, err); } else { // Fallback on earlier versions sacRef = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlTouchIDCurrentSet, err); } if(err){ return nil; } NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; if([account isKindOfClass:[NSString class]]){ [dict setObject:account forKey:(__bridge id)kSecAttrAccount]; } if([service isKindOfClass:[NSString class]]){ [dict setObject:service forKey:(__bridge id)kSecAttrService]; } if([generic isKindOfClass:[NSString class]]){ [dict setObject:generic forKey:(__bridge id)kSecAttrGeneric]; } [dict setObject:(__bridge_transfer id)sacRef forKey:(__bridge id)kSecAttrAccessControl]; [dict setObject:bioMsg forKey:(__bridge id)kSecUseOperationPrompt]; [dict setObject:[Keychain queryLabel] forKey:(__bridge id)kSecAttrLabel]; [dict setObject:[Keychain accessGroup] forKey:(__bridge id )kSecAttrAccessGroup]; return dict; } +(BOOL) insertBioAuthDataWithAccount:(NSString*)account service:(NSString*) service generic:(NSString*) generic data:(NSData *)data { NSMutableDictionary * dict = nil; OSStatus status = 0; dict =[[self class] prepareBioAuthDictWithAccount:account service:service generic:generic bioMsg:@""]; if(!dict){ return false; } [dict setObject:data forKey:(__bridge id)kSecValueData]; SecItemDelete((__bridge CFDictionaryRef)dict); status = SecItemAdd((__bridge CFDictionaryRef)dict, NULL); if(errSecSuccess != status) { NSLog(@"Unable add item with key =%@|%@|%@ error:%d",account, service, generic, (int)status); } return (errSecSuccess == status);
Has anyone got any ideas why this is happening and how to fix it ? Thanks.