nsKeychainMigrationUtils.mm (2589B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "nsKeychainMigrationUtils.h" 6 7 #include <Security/Security.h> 8 9 #include "mozilla/Logging.h" 10 11 #include "nsCocoaUtils.h" 12 #include "nsString.h" 13 14 using namespace mozilla; 15 16 LazyLogModule gKeychainUtilsLog("keychainmigrationutils"); 17 18 NS_IMPL_ISUPPORTS(nsKeychainMigrationUtils, nsIKeychainMigrationUtils) 19 20 NS_IMETHODIMP 21 nsKeychainMigrationUtils::GetGenericPassword(const nsACString& aServiceName, 22 const nsACString& aAccountName, 23 nsACString& aKey) { 24 // To retrieve a secret, we create a CFDictionary of the form: 25 // { class: generic password, 26 // service: the given service name 27 // account: the given account name, 28 // match limit: match one, 29 // return attributes: true, 30 // return data: true } 31 // This searches for and returns the attributes and data for the secret 32 // matching the given service and account names. We then extract the data 33 // (i.e. the secret) and return it. 34 NSDictionary* searchDictionary = @{ 35 (__bridge NSString*) 36 kSecClass : (__bridge NSString*)kSecClassGenericPassword, 37 (__bridge NSString*) 38 kSecAttrService : nsCocoaUtils::ToNSString(aServiceName), 39 (__bridge NSString*) 40 kSecAttrAccount : nsCocoaUtils::ToNSString(aAccountName), 41 (__bridge NSString*)kSecMatchLimit : (__bridge NSString*)kSecMatchLimitOne, 42 (__bridge NSString*)kSecReturnAttributes : @YES, 43 (__bridge NSString*)kSecReturnData : @YES 44 }; 45 46 CFTypeRef item; 47 // https://developer.apple.com/documentation/security/1398306-secitemcopymatching 48 OSStatus rv = 49 SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &item); 50 if (rv != errSecSuccess) { 51 MOZ_LOG(gKeychainUtilsLog, LogLevel::Debug, 52 ("SecItemCopyMatching failed: %d", rv)); 53 return NS_ERROR_FAILURE; 54 } 55 NSDictionary* resultDict = [(__bridge NSDictionary*)item autorelease]; 56 NSData* secret = [resultDict objectForKey:(__bridge NSString*)kSecValueData]; 57 if (!secret) { 58 MOZ_LOG(gKeychainUtilsLog, LogLevel::Debug, ("objectForKey failed")); 59 return NS_ERROR_FAILURE; 60 } 61 if ([secret length] != 0) { 62 // We assume that the data is UTF-8 encoded since that seems to be common 63 // and Keychain Access shows it with that encoding. 64 aKey.Assign(reinterpret_cast<const char*>([secret bytes]), [secret length]); 65 } 66 67 return NS_OK; 68 }