| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/components/credential_provider_extension/password_util.h" |
| |
| #import <Security/Security.h> |
| |
| #import "base/logging.h" |
| |
| namespace credential_provider_extension { |
| |
| NSString* PasswordWithKeychainIdentifier(NSString* identifier) { |
| if (!identifier) { |
| return nil; |
| } |
| NSDictionary* query = @{ |
| (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, |
| (__bridge id)kSecAttrAccount : identifier, |
| (__bridge id)kSecReturnData : @YES |
| }; |
| |
| // Get the keychain item containing the password. |
| CFDataRef sec_data_ref = nullptr; |
| OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, |
| (CFTypeRef*)&sec_data_ref); |
| |
| if (status != errSecSuccess) { |
| DLOG(ERROR) << "Error retrieving password, OSStatus: " << status; |
| return nil; |
| } |
| |
| // This is safe because SecItemCopyMatching either assign an owned reference |
| // to sec_data_ref, or leave it unchanged, and bridging maps nullptr to nil. |
| NSData* data = (__bridge_transfer NSData*)sec_data_ref; |
| return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; |
| } |
| |
| BOOL StorePasswordInKeychain(NSString* password, NSString* identifier) { |
| if (!identifier || identifier.length == 0) { |
| return NO; |
| } |
| |
| NSData* passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; |
| |
| NSDictionary* query = @{ |
| (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, |
| (__bridge id) |
| kSecAttrAccessible : (__bridge id)kSecAttrAccessibleWhenUnlocked, |
| (__bridge id)kSecValueData : passwordData, |
| (__bridge id)kSecAttrAccount : identifier, |
| }; |
| |
| OSStatus status = SecItemAdd((__bridge CFDictionaryRef)query, NULL); |
| return status == errSecSuccess; |
| } |
| |
| } // namespace credential_provider_extension |