No Description

FIRInstanceIDKeyPairStore.m 22KB

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