password_util.mm 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #import "ios/components/credential_provider_extension/password_util.h"
  5. #import <Security/Security.h>
  6. #import "base/logging.h"
  7. #if !defined(__has_feature) || !__has_feature(objc_arc)
  8. #error "This file requires ARC support."
  9. #endif
  10. namespace credential_provider_extension {
  11. NSString* PasswordWithKeychainIdentifier(NSString* identifier) {
  12. if (!identifier) {
  13. return nil;
  14. }
  15. NSDictionary* query = @{
  16. (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
  17. (__bridge id)kSecAttrAccount : identifier,
  18. (__bridge id)kSecReturnData : @YES
  19. };
  20. // Get the keychain item containing the password.
  21. CFDataRef sec_data_ref = nullptr;
  22. OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query,
  23. (CFTypeRef*)&sec_data_ref);
  24. if (status != errSecSuccess) {
  25. DLOG(ERROR) << "Error retrieving password, OSStatus: " << status;
  26. return nil;
  27. }
  28. // This is safe because SecItemCopyMatching either assign an owned reference
  29. // to sec_data_ref, or leave it unchanged, and bridging maps nullptr to nil.
  30. NSData* data = (__bridge_transfer NSData*)sec_data_ref;
  31. return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  32. }
  33. BOOL StorePasswordInKeychain(NSString* password, NSString* identifier) {
  34. if (!identifier || identifier.length == 0) {
  35. return NO;
  36. }
  37. NSData* passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  38. NSDictionary* query = @{
  39. (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
  40. (__bridge id)
  41. kSecAttrAccessible : (__bridge id)kSecAttrAccessibleWhenUnlocked,
  42. (__bridge id)kSecValueData : passwordData,
  43. (__bridge id)kSecAttrAccount : identifier,
  44. };
  45. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
  46. return status == errSecSuccess;
  47. }
  48. } // namespace credential_provider_extension