FIRInstanceIDKeyPairStore.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "FIRInstanceIDKeyPairStore.h"
  17. #import "FIRInstanceIDBackupExcludedPlist.h"
  18. #import "FIRInstanceIDConstants.h"
  19. #import "FIRInstanceIDDefines.h"
  20. #import "FIRInstanceIDKeyPair.h"
  21. #import "FIRInstanceIDKeyPairUtilities.h"
  22. #import "FIRInstanceIDKeychain.h"
  23. #import "FIRInstanceIDLogger.h"
  24. #import "FIRInstanceIDUtilities.h"
  25. #import "NSError+FIRInstanceID.h"
  26. // NOTE: These values should be in sync with what InstanceID saves in as.
  27. static NSString *const kFIRInstanceIDKeyPairStoreFileName = @"com.google.iid-keypair";
  28. static NSString *const kFIRInstanceIDStoreKeyGenerationTime = @"cre";
  29. static NSString *const kFIRInstanceIDStoreKeyPrefix = @"com.google.iid-";
  30. static NSString *const kFIRInstanceIDStoreKeyPublic = @"|P|";
  31. static NSString *const kFIRInstanceIDStoreKeyPrivate = @"|K|";
  32. static NSString *const kFIRInstanceIDStoreKeySubtype = @"|S|";
  33. static NSString *const kFIRInstanceIDKeyPairPublicTagPrefix = @"com.google.iid.keypair.public-";
  34. static NSString *const kFIRInstanceIDKeyPairPrivateTagPrefix = @"com.google.iid.keypair.private-";
  35. static const int kMaxMissingEntitlementErrorCount = 3;
  36. NSString *const kFIRInstanceIDKeyPairSubType = @"";
  37. // Query the key with NSData format
  38. NSData *FIRInstanceIDKeyDataWithTag(NSString *tag) {
  39. _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified");
  40. if (![tag length]) {
  41. return NULL;
  42. }
  43. NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, YES);
  44. CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey];
  45. if (!result) {
  46. return NULL;
  47. }
  48. return (__bridge NSData *)result;
  49. }
  50. // Query the key given a tag
  51. SecKeyRef FIRInstanceIDCachedKeyRefWithTag(NSString *tag) {
  52. _FIRInstanceIDDevAssert([tag length], @"Invalid tag for keychain specified");
  53. if (!tag.length) {
  54. return NULL;
  55. }
  56. NSDictionary *queryKey = FIRInstanceIDKeyPairQuery(tag, YES, NO);
  57. CFTypeRef result = [[FIRInstanceIDKeychain sharedInstance] itemWithQuery:queryKey];
  58. return (SecKeyRef)result;
  59. }
  60. // Check if keypair has been migrated from the legacy to the new version
  61. BOOL FIRInstanceIDHasMigratedKeyPair(NSString *legacyPublicKeyTag, NSString *newPublicKeyTag) {
  62. NSData *oldPublicKeyData = FIRInstanceIDKeyDataWithTag(legacyPublicKeyTag);
  63. NSData *newPublicKeyData = FIRInstanceIDKeyDataWithTag(newPublicKeyTag);
  64. return [oldPublicKeyData isEqualToData:newPublicKeyData];
  65. }
  66. // The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain
  67. // environments.
  68. NSString *FIRInstanceIDLegacyPublicTagWithSubtype(NSString *subtype) {
  69. NSString *prefix = kFIRInstanceIDStoreKeyPrefix;
  70. return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPublic];
  71. }
  72. // The legacy value is hardcoded to be the same key. This is a potential problem in shared keychain
  73. // environments.
  74. NSString *FIRInstanceIDLegacyPrivateTagWithSubtype(NSString *subtype) {
  75. NSString *prefix = kFIRInstanceIDStoreKeyPrefix;
  76. return [NSString stringWithFormat:@"%@%@%@", prefix, subtype, kFIRInstanceIDStoreKeyPrivate];
  77. }
  78. NSString *FIRInstanceIDPublicTagWithSubtype(NSString *subtype) {
  79. static NSString *publicTag;
  80. static dispatch_once_t onceToken;
  81. dispatch_once(&onceToken, ^{
  82. NSString *mainAppBundleID = FIRInstanceIDAppIdentifier();
  83. publicTag =
  84. [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPublicTagPrefix, mainAppBundleID];
  85. });
  86. return publicTag;
  87. }
  88. NSString *FIRInstanceIDPrivateTagWithSubtype(NSString *subtype) {
  89. static NSString *privateTag;
  90. static dispatch_once_t onceToken;
  91. dispatch_once(&onceToken, ^{
  92. NSString *mainAppBundleID = FIRInstanceIDAppIdentifier();
  93. privateTag =
  94. [NSString stringWithFormat:@"%@%@", kFIRInstanceIDKeyPairPrivateTagPrefix, mainAppBundleID];
  95. });
  96. return privateTag;
  97. }
  98. NSString *FIRInstanceIDCreationTimeKeyWithSubtype(NSString *subtype) {
  99. return [NSString stringWithFormat:@"%@%@%@", subtype, kFIRInstanceIDStoreKeySubtype,
  100. kFIRInstanceIDStoreKeyGenerationTime];
  101. }
  102. @interface FIRInstanceIDKeyPairStore ()
  103. @property(nonatomic, readwrite, strong) FIRInstanceIDBackupExcludedPlist *plist;
  104. @property(atomic, readwrite, strong) FIRInstanceIDKeyPair *keyPair;
  105. @property(nonatomic, readwrite, assign) NSInteger keychainEntitlementsErrorCount;
  106. @end
  107. @implementation FIRInstanceIDKeyPairStore
  108. - (instancetype)init {
  109. self = [super init];
  110. if (self) {
  111. NSString *fileName = [[self class] keyStoreFileName];
  112. _plist =
  113. [[FIRInstanceIDBackupExcludedPlist alloc] initWithFileName:fileName
  114. subDirectory:kFIRInstanceIDSubDirectoryName];
  115. }
  116. return self;
  117. }
  118. - (BOOL)invalidateKeyPairsIfNeeded {
  119. // Currently keypairs are always invalidated if self.plist is missing. This normally indicates
  120. // a fresh install (or an uninstall/reinstall). In those situations the key pairs should be
  121. // deleted.
  122. // NOTE: Although this class refers to multiple key pairs, with different subtypes, in practice
  123. // only a single subtype is currently supported. (b/64906549)
  124. if (![self.plist doesFileExist]) {
  125. // A fresh install, clear all the key pairs in the key chain. Do not perform migration as all
  126. // key pairs are gone.
  127. [self deleteSavedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType handler:nil];
  128. return YES;
  129. }
  130. // Not a fresh install, perform migration at early state.
  131. [self migrateKeyPairCacheIfNeededWithHandler:nil];
  132. return NO;
  133. }
  134. - (BOOL)hasCachedKeyPairs {
  135. NSError *error;
  136. if ([self cachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:&error] == nil) {
  137. if (error) {
  138. FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore000,
  139. @"Failed to get the cached keyPair %@", error);
  140. }
  141. error = nil;
  142. [self removeKeyPairCreationTimePlistWithError:&error];
  143. if (error) {
  144. FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore001,
  145. @"Failed to remove keyPair creationTime plist %@", error);
  146. }
  147. return NO;
  148. }
  149. return YES;
  150. }
  151. - (NSString *)appIdentityWithError:(NSError *__autoreleasing *)error {
  152. // Load the keyPair from Keychain (or generate a key pair, if this is the first run of the app).
  153. FIRInstanceIDKeyPair *keyPair = [self loadKeyPairWithError:error];
  154. if (!keyPair) {
  155. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStoreCouldNotLoadKeyPair,
  156. @"Keypair could not be loaded from Keychain. Error: %@", (*error));
  157. return nil;
  158. }
  159. if (error) {
  160. *error = nil;
  161. }
  162. NSString *appIdentity = FIRInstanceIDAppIdentity(keyPair);
  163. if (!appIdentity.length) {
  164. if (error) {
  165. *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeUnknown];
  166. }
  167. }
  168. return appIdentity;
  169. }
  170. - (FIRInstanceIDKeyPair *)loadKeyPairWithError:(NSError **)error {
  171. // In case we call this from different threads we don't want to generate or fetch the
  172. // keyPair multiple times. Once we have a keyPair in the cache it would mostly be used
  173. // from there.
  174. @synchronized(self) {
  175. if ([self.keyPair isValid]) {
  176. return self.keyPair;
  177. }
  178. if (self.keychainEntitlementsErrorCount >= kMaxMissingEntitlementErrorCount) {
  179. FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairStore002,
  180. @"Keychain not accessible, Entitlements missing error (-34018). "
  181. @"Will not check token in cache.");
  182. return nil;
  183. }
  184. if (!self.keyPair) {
  185. self.keyPair = [self validCachedKeyPairWithSubtype:kFIRInstanceIDKeyPairSubType error:error];
  186. }
  187. if ((*error).code == kFIRInstanceIDSecMissingEntitlementErrorCode) {
  188. self.keychainEntitlementsErrorCount++;
  189. }
  190. if (!self.keyPair) {
  191. self.keyPair = [self generateAndSaveKeyWithSubtype:kFIRInstanceIDKeyPairSubType
  192. creationTime:FIRInstanceIDCurrentTimestampInSeconds()
  193. error:error];
  194. }
  195. }
  196. return self.keyPair;
  197. }
  198. // TODO(chliangGoogle: Remove subtype support, as it's not being used.
  199. - (FIRInstanceIDKeyPair *)generateAndSaveKeyWithSubtype:(NSString *)subtype
  200. creationTime:(int64_t)creationTime
  201. error:(NSError **)error {
  202. NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
  203. NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
  204. FIRInstanceIDKeyPair *keyPair =
  205. [[FIRInstanceIDKeychain sharedInstance] generateKeyPairWithPrivateTag:privateKeyTag
  206. publicTag:publicKeyTag];
  207. if (![keyPair isValid]) {
  208. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore003,
  209. @"Unable to generate keypair.");
  210. return nil;
  211. }
  212. NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
  213. NSDictionary *keyPairData = @{creationTimeKey : @(creationTime)};
  214. if (error) {
  215. *error = nil;
  216. }
  217. NSMutableDictionary *allKeyPairs = [[self.plist contentAsDictionary] mutableCopy];
  218. if (allKeyPairs.count) {
  219. [allKeyPairs addEntriesFromDictionary:keyPairData];
  220. } else {
  221. allKeyPairs = [keyPairData mutableCopy];
  222. }
  223. if (![self.plist writeDictionary:allKeyPairs error:error]) {
  224. [FIRInstanceIDKeyPairStore deleteKeyPairWithPrivateTag:privateKeyTag
  225. publicTag:publicKeyTag
  226. handler:nil];
  227. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore004,
  228. @"Failed to save keypair data to plist %@", error ? *error : @"");
  229. return nil;
  230. }
  231. return keyPair;
  232. }
  233. - (FIRInstanceIDKeyPair *)validCachedKeyPairWithSubtype:(NSString *)subtype
  234. error:(NSError **)error {
  235. // On a new install (or if the ID was deleted), the plist will be missing, which should trigger
  236. // a reset of the key pairs in Keychain (if they exist).
  237. NSDictionary *allKeyPairs = [self.plist contentAsDictionary];
  238. NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
  239. if (allKeyPairs[creationTimeKey] > 0) {
  240. return [self cachedKeyPairWithSubtype:subtype error:error];
  241. } else {
  242. // There is no need to reset keypair again here as FIRInstanceID init call is always
  243. // going to be ahead of this call, which already trigger keypair reset if it's new install
  244. FIRInstanceIDErrorCode code = kFIRInstanceIDErrorCodeInvalidKeyPairCreationTime;
  245. if (error) {
  246. *error = [NSError errorWithFIRInstanceIDErrorCode:code];
  247. }
  248. return nil;
  249. }
  250. }
  251. - (FIRInstanceIDKeyPair *)cachedKeyPairWithSubtype:(NSString *)subtype
  252. error:(NSError *__autoreleasing *)error {
  253. // base64 encoded keys
  254. NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
  255. NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
  256. return [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:privateKeyTag
  257. publicKeyTag:publicKeyTag
  258. error:error];
  259. }
  260. + (FIRInstanceIDKeyPair *)keyPairForPrivateKeyTag:(NSString *)privateKeyTag
  261. publicKeyTag:(NSString *)publicKeyTag
  262. error:(NSError *__autoreleasing *)error {
  263. _FIRInstanceIDDevAssert([privateKeyTag length] && [publicKeyTag length],
  264. @"Invalid tags for keypair");
  265. if (![privateKeyTag length] || ![publicKeyTag length]) {
  266. if (error) {
  267. *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeInvalidKeyPairTags];
  268. }
  269. return nil;
  270. }
  271. SecKeyRef privateKeyRef = FIRInstanceIDCachedKeyRefWithTag(privateKeyTag);
  272. SecKeyRef publicKeyRef = FIRInstanceIDCachedKeyRefWithTag(publicKeyTag);
  273. if (!privateKeyRef || !publicKeyRef) {
  274. if (error) {
  275. *error = [NSError errorWithFIRInstanceIDErrorCode:kFIRInstanceIDErrorCodeMissingKeyPair];
  276. }
  277. FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPair000,
  278. @"No keypair info is found with tag %@", privateKeyTag);
  279. return nil;
  280. }
  281. NSData *publicKeyData = FIRInstanceIDKeyDataWithTag(publicKeyTag);
  282. NSData *privateKeyData = FIRInstanceIDKeyDataWithTag(privateKeyTag);
  283. FIRInstanceIDKeyPair *keyPair = [[FIRInstanceIDKeyPair alloc] initWithPrivateKey:privateKeyRef
  284. publicKey:publicKeyRef
  285. publicKeyData:publicKeyData
  286. privateKeyData:privateKeyData];
  287. return keyPair;
  288. }
  289. // Migrates from keypair saved under legacy keys (hardcoded value) to dynamic keys (stable, but
  290. // unique for the app's bundle id
  291. - (void)migrateKeyPairCacheIfNeededWithHandler:(void (^)(NSError *error))handler {
  292. // Attempt to load keypair using legacy keys
  293. NSString *legacyPublicKeyTag =
  294. FIRInstanceIDLegacyPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType);
  295. NSString *legacyPrivateKeyTag =
  296. FIRInstanceIDLegacyPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType);
  297. NSError *error;
  298. FIRInstanceIDKeyPair *keyPair =
  299. [FIRInstanceIDKeyPairStore keyPairForPrivateKeyTag:legacyPrivateKeyTag
  300. publicKeyTag:legacyPublicKeyTag
  301. error:&error];
  302. if (![keyPair isValid]) {
  303. FIRInstanceIDLoggerDebug(kFIRInstanceIDMessageCodeKeyPairNoLegacyKeyPair,
  304. @"There's no legacy keypair so no need to do migration.");
  305. if (handler) {
  306. handler(nil);
  307. }
  308. return;
  309. }
  310. // Check whether migration already done.
  311. NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(kFIRInstanceIDKeyPairSubType);
  312. if (FIRInstanceIDHasMigratedKeyPair(legacyPublicKeyTag, publicKeyTag)) {
  313. if (handler) {
  314. handler(nil);
  315. }
  316. return;
  317. }
  318. // Also cache locally since we are sure to use the migrated key pair.
  319. self.keyPair = keyPair;
  320. // Either new key pair doesn't exist or it's different than legacy key pair, start the migration.
  321. __block NSError *updateKeyRefError;
  322. NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(kFIRInstanceIDKeyPairSubType);
  323. [self updateKeyRef:keyPair.publicKey
  324. withTag:publicKeyTag
  325. handler:^(NSError *error) {
  326. if (error) {
  327. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError,
  328. @"Unable to migrate key pair from legacy ones.");
  329. updateKeyRefError = error;
  330. }
  331. }];
  332. [self updateKeyRef:keyPair.privateKey
  333. withTag:privateKeyTag
  334. handler:^(NSError *error) {
  335. if (error) {
  336. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairMigrationError,
  337. @"Unable to migrate key pair from legacy ones.");
  338. updateKeyRefError = error;
  339. }
  340. if (handler) {
  341. handler(updateKeyRefError);
  342. }
  343. }];
  344. }
  345. // Used for migrating from legacy tags to updated tags. The legacy keychain is not deleted for
  346. // backward compatibility.
  347. // TODO(chliangGoogle) Delete the legacy keychain when GCM is fully deprecated.
  348. - (void)updateKeyRef:(SecKeyRef)keyRef
  349. withTag:(NSString *)tag
  350. handler:(void (^)(NSError *error))handler {
  351. NSData *updatedTagData = [tag dataUsingEncoding:NSUTF8StringEncoding];
  352. __block NSError *keychainError;
  353. // Always delete the old keychain before adding a new one to avoid conflicts.
  354. NSDictionary *deleteQuery = @{
  355. (__bridge id)kSecAttrApplicationTag : updatedTagData,
  356. (__bridge id)kSecClass : (__bridge id)kSecClassKey,
  357. (__bridge id)kSecAttrKeyType : (__bridge id)kSecAttrKeyTypeRSA,
  358. (__bridge id)kSecReturnRef : @(YES),
  359. };
  360. [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:deleteQuery
  361. handler:^(NSError *error) {
  362. if (error) {
  363. keychainError = error;
  364. }
  365. }];
  366. NSDictionary *addQuery = @{
  367. (__bridge id)kSecAttrApplicationTag : updatedTagData,
  368. (__bridge id)kSecClass : (__bridge id)kSecClassKey,
  369. (__bridge id)kSecValueRef : (__bridge id)keyRef,
  370. (__bridge id)kSecAttrAccessible : (__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly,
  371. };
  372. [[FIRInstanceIDKeychain sharedInstance] addItemWithQuery:addQuery
  373. handler:^(NSError *addError) {
  374. if (addError) {
  375. keychainError = addError;
  376. }
  377. if (handler) {
  378. handler(keychainError);
  379. }
  380. }];
  381. }
  382. - (void)deleteSavedKeyPairWithSubtype:(NSString *)subtype
  383. handler:(void (^)(NSError *error))handler {
  384. NSDictionary *allKeyPairs = [self.plist contentAsDictionary];
  385. NSString *publicKeyTag = FIRInstanceIDPublicTagWithSubtype(subtype);
  386. NSString *privateKeyTag = FIRInstanceIDPrivateTagWithSubtype(subtype);
  387. NSString *creationTimeKey = FIRInstanceIDCreationTimeKeyWithSubtype(subtype);
  388. // remove the creation time
  389. if (allKeyPairs[creationTimeKey] > 0) {
  390. NSMutableDictionary *newKeyPairs = [NSMutableDictionary dictionaryWithDictionary:allKeyPairs];
  391. [newKeyPairs removeObjectForKey:creationTimeKey];
  392. NSError *plistError;
  393. if (![self.plist writeDictionary:newKeyPairs error:&plistError]) {
  394. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore006,
  395. @"Unable to remove keypair creation time from plist %@", plistError);
  396. }
  397. }
  398. self.keyPair = nil;
  399. [FIRInstanceIDKeyPairStore
  400. deleteKeyPairWithPrivateTag:privateKeyTag
  401. publicTag:publicKeyTag
  402. handler:^(NSError *error) {
  403. // Delete legacy key pairs from GCM/FCM If they exist. All key pairs
  404. // should be deleted when app is newly installed.
  405. NSString *legacyPublicKeyTag =
  406. FIRInstanceIDLegacyPublicTagWithSubtype(subtype);
  407. NSString *legacyPrivateKeyTag =
  408. FIRInstanceIDLegacyPrivateTagWithSubtype(subtype);
  409. [FIRInstanceIDKeyPairStore
  410. deleteKeyPairWithPrivateTag:legacyPrivateKeyTag
  411. publicTag:legacyPublicKeyTag
  412. handler:nil];
  413. if (error) {
  414. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore007,
  415. @"Unable to remove RSA keypair, error: %@",
  416. error);
  417. if (handler) {
  418. handler(error);
  419. }
  420. } else {
  421. if (handler) {
  422. handler(nil);
  423. }
  424. }
  425. }];
  426. }
  427. + (void)deleteKeyPairWithPrivateTag:(NSString *)privateTag
  428. publicTag:(NSString *)publicTag
  429. handler:(void (^)(NSError *))handler {
  430. NSDictionary *queryPublicKey = FIRInstanceIDKeyPairQuery(publicTag, NO, NO);
  431. NSDictionary *queryPrivateKey = FIRInstanceIDKeyPairQuery(privateTag, NO, NO);
  432. __block NSError *keychainError;
  433. // Always remove public key first because it is the key we generate IID.
  434. [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPublicKey
  435. handler:^(NSError *error) {
  436. if (error) {
  437. keychainError = error;
  438. }
  439. }];
  440. [[FIRInstanceIDKeychain sharedInstance] removeItemWithQuery:queryPrivateKey
  441. handler:^(NSError *error) {
  442. if (error) {
  443. keychainError = error;
  444. }
  445. if (handler) {
  446. handler(keychainError);
  447. }
  448. }];
  449. }
  450. - (BOOL)removeKeyPairCreationTimePlistWithError:(NSError *__autoreleasing *)error {
  451. if (![self.plist deleteFile:error]) {
  452. FIRInstanceIDLoggerError(kFIRInstanceIDMessageCodeKeyPairStore008,
  453. @"Unable to delete keypair creation times plist");
  454. return NO;
  455. }
  456. return YES;
  457. }
  458. + (NSString *)keyStoreFileName {
  459. return kFIRInstanceIDKeyPairStoreFileName;
  460. }
  461. @end