FIRInstallationsKeychainUtils.m 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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 "FIRInstallationsKeychainUtils.h"
  17. #import "FIRInstallationsErrorUtil.h"
  18. @implementation FIRInstallationsKeychainUtils
  19. + (nullable NSData *)getItemWithQuery:(NSDictionary *)query
  20. error:(NSError *_Nullable *_Nullable)outError {
  21. NSMutableDictionary *mutableQuery = [query mutableCopy];
  22. mutableQuery[(__bridge id)kSecReturnData] = @YES;
  23. mutableQuery[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
  24. CFDataRef result = NULL;
  25. OSStatus status =
  26. SecItemCopyMatching((__bridge CFDictionaryRef)mutableQuery, (CFTypeRef *)&result);
  27. if (status == errSecSuccess && result != NULL) {
  28. if (outError) {
  29. *outError = nil;
  30. }
  31. return (__bridge_transfer NSData *)result;
  32. }
  33. if (status == errSecItemNotFound) {
  34. if (outError) {
  35. *outError = nil;
  36. }
  37. } else {
  38. if (outError) {
  39. *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemCopyMatching"
  40. status:status];
  41. }
  42. }
  43. return nil;
  44. }
  45. + (BOOL)setItem:(NSData *)item
  46. withQuery:(NSDictionary *)query
  47. error:(NSError *_Nullable *_Nullable)outError {
  48. NSData *existingItem = [self getItemWithQuery:query error:outError];
  49. if (outError && *outError) {
  50. return NO;
  51. }
  52. NSMutableDictionary *mutableQuery = [query mutableCopy];
  53. mutableQuery[(__bridge id)kSecAttrAccessible] =
  54. (__bridge id)kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;
  55. OSStatus status;
  56. if (!existingItem) {
  57. mutableQuery[(__bridge id)kSecValueData] = item;
  58. status = SecItemAdd((__bridge CFDictionaryRef)mutableQuery, NULL);
  59. } else {
  60. NSDictionary *attributes = @{(__bridge id)kSecValueData : item};
  61. status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)attributes);
  62. }
  63. if (status == noErr) {
  64. if (outError) {
  65. *outError = nil;
  66. }
  67. return YES;
  68. }
  69. NSString *function = existingItem ? @"SecItemUpdate" : @"SecItemAdd";
  70. if (outError) {
  71. *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:function status:status];
  72. }
  73. return NO;
  74. }
  75. + (BOOL)removeItemWithQuery:(NSDictionary *)query error:(NSError *_Nullable *_Nullable)outError {
  76. OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
  77. if (status == noErr || status == errSecItemNotFound) {
  78. if (outError) {
  79. *outError = nil;
  80. }
  81. return YES;
  82. }
  83. if (outError) {
  84. *outError = [FIRInstallationsErrorUtil keychainErrorWithFunction:@"SecItemDelete"
  85. status:status];
  86. }
  87. return NO;
  88. }
  89. @end