diff options
17 files changed, 525 insertions, 260 deletions
diff --git a/chrome/browser/password_manager/encryptor_mac.mm b/chrome/browser/password_manager/encryptor_mac.mm index 00116fa..c7f1cd4 100644 --- a/chrome/browser/password_manager/encryptor_mac.mm +++ b/chrome/browser/password_manager/encryptor_mac.mm @@ -10,11 +10,11 @@ #include "base/memory/scoped_ptr.h" #include "base/utf_string_conversions.h" #include "chrome/browser/password_manager/encryptor_password_mac.h" +#include "crypto/apple_keychain.h" #include "crypto/encryptor.h" -#include "crypto/keychain_mac.h" #include "crypto/symmetric_key.h" -using crypto::MacKeychain; +using crypto::AppleKeychain; namespace { @@ -45,7 +45,7 @@ crypto::SymmetricKey* GetEncryptionKey() { if (use_mock_keychain) { password = "mock_password"; } else { - MacKeychain keychain; + AppleKeychain keychain; EncryptorPassword encryptor_password(keychain); password = encryptor_password.GetEncryptorPassword(); } diff --git a/chrome/browser/password_manager/encryptor_password_mac.h b/chrome/browser/password_manager/encryptor_password_mac.h index bd8182d..475ae20 100644 --- a/chrome/browser/password_manager/encryptor_password_mac.h +++ b/chrome/browser/password_manager/encryptor_password_mac.h @@ -10,12 +10,12 @@ #include "base/basictypes.h" namespace crypto { -class MacKeychain; +class AppleKeychain; } // namespace crypto class EncryptorPassword { public: - explicit EncryptorPassword(const crypto::MacKeychain& keychain) + explicit EncryptorPassword(const crypto::AppleKeychain& keychain) : keychain_(keychain) { } @@ -29,7 +29,7 @@ class EncryptorPassword { private: DISALLOW_COPY_AND_ASSIGN(EncryptorPassword); - const crypto::MacKeychain& keychain_; + const crypto::AppleKeychain& keychain_; }; #endif // CHROME_BROWSER_PASSWORD_MANAGER_ENCRYPTOR_PASSWORD_H__ diff --git a/chrome/browser/password_manager/encryptor_password_mac.mm b/chrome/browser/password_manager/encryptor_password_mac.mm index 9b5c23a..d472fad 100644 --- a/chrome/browser/password_manager/encryptor_password_mac.mm +++ b/chrome/browser/password_manager/encryptor_password_mac.mm @@ -9,17 +9,17 @@ #include "base/base64.h" #include "base/mac/mac_logging.h" #include "base/rand_util.h" -#include "crypto/keychain_mac.h" +#include "crypto/apple_keychain.h" #include "ui/base/l10n/l10n_util.h" -using crypto::MacKeychain; +using crypto::AppleKeychain; namespace { // Generates a random password and adds it to the Keychain. The added password // is returned from the function. If an error occurs, an empty password is // returned. -std::string AddRandomPasswordToKeychain(const MacKeychain& keychain, +std::string AddRandomPasswordToKeychain(const AppleKeychain& keychain, const std::string& service_name, const std::string& account_name) { // Generate a password with 128 bits of randomness. diff --git a/chrome/browser/password_manager/encryptor_password_mac_unittest.cc b/chrome/browser/password_manager/encryptor_password_mac_unittest.cc index 284b881..f7b211a 100644 --- a/chrome/browser/password_manager/encryptor_password_mac_unittest.cc +++ b/chrome/browser/password_manager/encryptor_password_mac_unittest.cc @@ -3,17 +3,17 @@ // found in the LICENSE file. #include "chrome/browser/password_manager/encryptor_password_mac.h" -#include "crypto/mock_keychain_mac.h" +#include "crypto/mock_apple_keychain.h" #include "testing/gtest/include/gtest/gtest.h" namespace { -using crypto::MockKeychain; +using crypto::MockAppleKeychain; // Test that if we have an existing password in the Keychain and we are // authorized by the user to read it then we get it back correctly. TEST(EncryptorPasswordTest, FindPasswordSuccess) { - MockKeychain keychain; + MockAppleKeychain keychain; keychain.set_find_generic_result(noErr); EncryptorPassword password(keychain); EXPECT_FALSE(password.GetEncryptorPassword().empty()); @@ -24,7 +24,7 @@ TEST(EncryptorPasswordTest, FindPasswordSuccess) { // Test that if we do not have an existing password in the Keychain then it // gets added successfully and returned. TEST(EncryptorPasswordTest, FindPasswordNotFound) { - MockKeychain keychain; + MockAppleKeychain keychain; keychain.set_find_generic_result(errSecItemNotFound); EncryptorPassword password(keychain); EXPECT_EQ(24U, password.GetEncryptorPassword().length()); @@ -35,7 +35,7 @@ TEST(EncryptorPasswordTest, FindPasswordNotFound) { // Test that if get denied access by the user then we return an empty password. // And we should not try to add one. TEST(EncryptorPasswordTest, FindPasswordNotAuthorized) { - MockKeychain keychain; + MockAppleKeychain keychain; keychain.set_find_generic_result(errSecAuthFailed); EncryptorPassword password(keychain); EXPECT_TRUE(password.GetEncryptorPassword().empty()); @@ -46,7 +46,7 @@ TEST(EncryptorPasswordTest, FindPasswordNotAuthorized) { // Test that if some random other error happens then we return an empty // password, and we should not try to add one. TEST(EncryptorPasswordTest, FindPasswordOtherError) { - MockKeychain keychain; + MockAppleKeychain keychain; keychain.set_find_generic_result(errSecNotAvailable); EncryptorPassword password(keychain); EXPECT_TRUE(password.GetEncryptorPassword().empty()); @@ -56,7 +56,7 @@ TEST(EncryptorPasswordTest, FindPasswordOtherError) { // Test that subsequent additions to the keychain give different passwords. TEST(EncryptorPasswordTest, PasswordsDiffer) { - MockKeychain keychain1; + MockAppleKeychain keychain1; keychain1.set_find_generic_result(errSecItemNotFound); EncryptorPassword encryptor_password1(keychain1); std::string password1 = encryptor_password1.GetEncryptorPassword(); @@ -64,7 +64,7 @@ TEST(EncryptorPasswordTest, PasswordsDiffer) { EXPECT_TRUE(keychain1.called_add_generic()); EXPECT_EQ(0, keychain1.password_data_count()); - MockKeychain keychain2; + MockAppleKeychain keychain2; keychain2.set_find_generic_result(errSecItemNotFound); EncryptorPassword encryptor_password2(keychain2); std::string password2 = encryptor_password2.GetEncryptorPassword(); diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc index b110cb5d..a46d809 100644 --- a/chrome/browser/password_manager/password_store_factory.cc +++ b/chrome/browser/password_manager/password_store_factory.cc @@ -21,8 +21,8 @@ #include "chrome/browser/password_manager/password_store_win.h" #elif defined(OS_MACOSX) #include "chrome/browser/password_manager/password_store_mac.h" -#include "crypto/keychain_mac.h" -#include "crypto/mock_keychain_mac.h" +#include "crypto/apple_keychain.h" +#include "crypto/mock_apple_keychain.h" #elif defined(OS_CHROMEOS) || defined(OS_ANDROID) // Don't do anything. We're going to use the default store. #elif defined(OS_POSIX) @@ -115,9 +115,9 @@ PasswordStoreFactory::BuildServiceInstanceFor(Profile* profile) const { WebDataServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS)); #elif defined(OS_MACOSX) if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseMockKeychain)) { - ps = new PasswordStoreMac(new crypto::MockKeychain(), login_db); + ps = new PasswordStoreMac(new crypto::MockAppleKeychain(), login_db); } else { - ps = new PasswordStoreMac(new crypto::MacKeychain(), login_db); + ps = new PasswordStoreMac(new crypto::AppleKeychain(), login_db); } #elif defined(OS_CHROMEOS) || defined(OS_ANDROID) // For now, we use PasswordStoreDefault. We might want to make a native diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc index 2b23db8..a1cb791 100644 --- a/chrome/browser/password_manager/password_store_mac.cc +++ b/chrome/browser/password_manager/password_store_mac.cc @@ -22,16 +22,16 @@ #include "chrome/browser/password_manager/password_store_change.h" #include "chrome/common/chrome_notification_types.h" #include "content/public/browser/notification_service.h" -#include "crypto/keychain_mac.h" +#include "crypto/apple_keychain.h" -using crypto::MacKeychain; +using crypto::AppleKeychain; using webkit::forms::PasswordForm; // Utility class to handle the details of constructing and running a keychain // search from a set of attributes. class KeychainSearch { public: - explicit KeychainSearch(const MacKeychain& keychain); + explicit KeychainSearch(const AppleKeychain& keychain); ~KeychainSearch(); // Sets up a keycahin search based on an non "null" (NULL for char*, @@ -49,12 +49,12 @@ class KeychainSearch { void FindMatchingItems(std::vector<SecKeychainItemRef>* matches); private: - const MacKeychain* keychain_; + const AppleKeychain* keychain_; SecKeychainAttributeList search_attributes_; SecKeychainSearchRef search_ref_; }; -KeychainSearch::KeychainSearch(const MacKeychain& keychain) +KeychainSearch::KeychainSearch(const AppleKeychain& keychain) : keychain_(&keychain), search_ref_(NULL) { search_attributes_.count = 0; search_attributes_.attr = NULL; @@ -231,7 +231,7 @@ PasswordForm::Scheme SchemeForAuthType(SecAuthenticationType auth_type) { } } -bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain, +bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, const SecKeychainItemRef& keychain_item, PasswordForm* form) { DCHECK(form); @@ -444,7 +444,8 @@ void MergePasswordForms(std::vector<PasswordForm*>* keychain_forms, } std::vector<PasswordForm*> GetPasswordsForForms( - const MacKeychain& keychain, std::vector<PasswordForm*>* database_forms) { + const AppleKeychain& keychain, + std::vector<PasswordForm*>* database_forms) { MacKeychainPasswordFormAdapter keychain_adapter(&keychain); std::vector<PasswordForm*> merged_forms; @@ -469,7 +470,7 @@ std::vector<PasswordForm*> GetPasswordsForForms( #pragma mark - MacKeychainPasswordFormAdapter::MacKeychainPasswordFormAdapter( - const MacKeychain* keychain) + const AppleKeychain* keychain) : keychain_(keychain), finds_only_owned_(false) { } @@ -734,7 +735,7 @@ OSType MacKeychainPasswordFormAdapter::CreatorCodeForSearch() { #pragma mark - -PasswordStoreMac::PasswordStoreMac(MacKeychain* keychain, +PasswordStoreMac::PasswordStoreMac(AppleKeychain* keychain, LoginDatabase* login_db) : keychain_(keychain), login_metadata_db_(login_db) { DCHECK(keychain_.get()); diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h index 36df2ba..3974ecb 100644 --- a/chrome/browser/password_manager/password_store_mac.h +++ b/chrome/browser/password_manager/password_store_mac.h @@ -18,7 +18,7 @@ class NotificationService; } namespace crypto { -class MacKeychain; +class AppleKeychain; } // Implements PasswordStore on top of the OS X Keychain, with an internal @@ -30,7 +30,7 @@ class PasswordStoreMac : public PasswordStore { public: // Takes ownership of |keychain| and |login_db|, both of which must be // non-NULL. - PasswordStoreMac(crypto::MacKeychain* keychain, LoginDatabase* login_db); + PasswordStoreMac(crypto::AppleKeychain* keychain, LoginDatabase* login_db); // Initializes |thread_| and |notification_service_|. virtual bool Init() OVERRIDE; @@ -87,7 +87,7 @@ class PasswordStoreMac : public PasswordStore { // thread. void CreateNotificationService(); - scoped_ptr<crypto::MacKeychain> keychain_; + scoped_ptr<crypto::AppleKeychain> keychain_; scoped_ptr<LoginDatabase> login_metadata_db_; // Thread that the synchronous methods are run on. diff --git a/chrome/browser/password_manager/password_store_mac_internal.h b/chrome/browser/password_manager/password_store_mac_internal.h index d3e8bca..b287557 100644 --- a/chrome/browser/password_manager/password_store_mac_internal.h +++ b/chrome/browser/password_manager/password_store_mac_internal.h @@ -11,18 +11,18 @@ #include <vector> #include "base/time.h" -#include "crypto/keychain_mac.h" +#include "crypto/apple_keychain.h" -using crypto::MacKeychain; +using crypto::AppleKeychain; -// Adapter that wraps a MacKeychain and provides interaction in terms of +// Adapter that wraps a AppleKeychain and provides interaction in terms of // PasswordForms instead of Keychain items. class MacKeychainPasswordFormAdapter { public: // Creates an adapter for |keychain|. This class does not take ownership of // |keychain|, so the caller must make sure that the keychain outlives the // created object. - explicit MacKeychainPasswordFormAdapter(const MacKeychain* keychain); + explicit MacKeychainPasswordFormAdapter(const AppleKeychain* keychain); // Returns PasswordForms for each keychain entry that could be used to fill // |form|. Caller is responsible for deleting the returned forms. @@ -67,20 +67,20 @@ class MacKeychainPasswordFormAdapter { private: // Returns PasswordForms constructed from the given Keychain items, calling - // MacKeychain::Free on all of the keychain items and clearing the vector. + // AppleKeychain::Free on all of the keychain items and clearing the vector. // Caller is responsible for deleting the returned forms. std::vector<webkit::forms::PasswordForm*> ConvertKeychainItemsToForms( std::vector<SecKeychainItemRef>* items); // Searches |keychain| for the specific keychain entry that corresponds to the // given form, and returns it (or NULL if no match is found). The caller is - // responsible for calling MacKeychain::Free on on the returned item. + // responsible for calling AppleKeychain::Free on on the returned item. SecKeychainItemRef KeychainItemForForm( const webkit::forms::PasswordForm& form); // Returns the Keychain items matching the given signon_realm, scheme, and // optionally path and username (either of both can be NULL). - // The caller is responsible for calling MacKeychain::Free on the + // The caller is responsible for calling AppleKeychain::Free on the // returned items. std::vector<SecKeychainItemRef> MatchingKeychainItems( const std::string& signon_realm, @@ -119,7 +119,7 @@ class MacKeychainPasswordFormAdapter { // a search of all items, regardless of creator. OSType CreatorCodeForSearch(); - const MacKeychain* keychain_; + const AppleKeychain* keychain_; // If true, Keychain searches are restricted to items created by Chrome. bool finds_only_owned_; @@ -140,7 +140,7 @@ namespace internal_keychain_helpers { // becomes an issue, the password storage API will need to be refactored to // allow the password to be retrieved later (accessing other fields doesn't // require authorization). -bool FillPasswordFormFromKeychainItem(const MacKeychain& keychain, +bool FillPasswordFormFromKeychainItem(const AppleKeychain& keychain, const SecKeychainItemRef& keychain_item, webkit::forms::PasswordForm* form); @@ -156,7 +156,7 @@ bool FormsMatchForMerge(const webkit::forms::PasswordForm& form_a, // On return, database_forms and keychain_forms will have only unused // entries; for database_forms that means entries for which no corresponding // password can be found (and which aren't blacklist entries), and for -// keychain_forms it's entries that weren't merged into at least one database +// keychain_forms its entries that weren't merged into at least one database // form. void MergePasswordForms( std::vector<webkit::forms::PasswordForm*>* keychain_forms, @@ -167,7 +167,7 @@ void MergePasswordForms( // possible using entries from |keychain| and returns them. On return, // |database_forms| will contain only the forms for which no password was found. std::vector<webkit::forms::PasswordForm*> GetPasswordsForForms( - const MacKeychain& keychain, + const AppleKeychain& keychain, std::vector<webkit::forms::PasswordForm*>* database_forms); } // internal_keychain_helpers diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc index f3fc3cb..be42d3b 100644 --- a/chrome/browser/password_manager/password_store_mac_unittest.cc +++ b/chrome/browser/password_manager/password_store_mac_unittest.cc @@ -17,10 +17,10 @@ #include "chrome/browser/password_manager/password_store_mac_internal.h" #include "chrome/common/chrome_paths.h" #include "content/public/test/test_browser_thread.h" -#include "crypto/mock_keychain_mac.h" +#include "crypto/mock_apple_keychain.h" using content::BrowserThread; -using crypto::MockKeychain; +using crypto::MockAppleKeychain; using webkit::forms::PasswordForm; using testing::_; using testing::DoAll; @@ -51,7 +51,7 @@ ACTION(QuitUIMessageLoop) { class PasswordStoreMacInternalsTest : public testing::Test { public: virtual void SetUp() { - MockKeychain::KeychainTestData test_data[] = { + MockAppleKeychain::KeychainTestData test_data[] = { // Basic HTML form. { kSecAuthenticationTypeHTMLForm, "some.domain.com", kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", @@ -91,7 +91,7 @@ class PasswordStoreMacInternalsTest : public testing::Test { "abc", "123", false }, }; - keychain_ = new MockKeychain(); + keychain_ = new MockAppleKeychain(); for (unsigned int i = 0; i < arraysize(test_data); ++i) { keychain_->AddTestItem(test_data[i]); @@ -120,7 +120,7 @@ class PasswordStoreMacInternalsTest : public testing::Test { EXPECT_TRUE(keychain_->CreatorCodesSetForAddedItems()); } - MockKeychain* keychain_; + MockAppleKeychain* keychain_; }; #pragma mark - @@ -274,7 +274,7 @@ TEST_F(PasswordStoreMacInternalsTest, TestKeychainToFormTranslation) { }; for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(expected); ++i) { - // Create our fake KeychainItemRef; see MockKeychain docs. + // Create our fake KeychainItemRef; see MockAppleKeychain docs. SecKeychainItemRef keychain_item = reinterpret_cast<SecKeychainItemRef>(i + 1); PasswordForm form; @@ -514,7 +514,8 @@ TEST_F(PasswordStoreMacInternalsTest, TestKeychainAdd) { "gobbledygook", NULL, NULL, NULL, NULL, L"anonymous", L"knock-knock", false, false, 0 }, false }, // Test that failing to update a duplicate (forced using the magic failure - // password; see MockKeychain::ItemModifyAttributesAndData) is reported. + // password; see MockAppleKeychain::ItemModifyAttributesAndData) is + // reported. { { PasswordForm::SCHEME_HTML, "http://some.domain.com", "http://some.domain.com/insecure.html", NULL, NULL, NULL, NULL, L"joe_user", L"fail_me", false, false, 0 }, false }, @@ -906,7 +907,7 @@ class PasswordStoreMacTest : public testing::Test { FilePath db_file = db_dir_.path().AppendASCII("login.db"); ASSERT_TRUE(login_db_->Init(db_file)); - keychain_ = new MockKeychain(); + keychain_ = new MockAppleKeychain(); store_ = new PasswordStoreMac(keychain_, login_db_); ASSERT_TRUE(store_->Init()); @@ -922,7 +923,7 @@ class PasswordStoreMacTest : public testing::Test { MessageLoopForUI message_loop_; content::TestBrowserThread ui_thread_; - MockKeychain* keychain_; // Owned by store_. + MockAppleKeychain* keychain_; // Owned by store_. LoginDatabase* login_db_; // Owned by store_. scoped_refptr<PasswordStoreMac> store_; ScopedTempDir db_dir_; @@ -941,14 +942,14 @@ TEST_F(PasswordStoreMacTest, TestStoreUpdate) { }; scoped_ptr<PasswordForm> joint_form(CreatePasswordFormFromData(joint_data)); login_db_->AddLogin(*joint_form); - MockKeychain::KeychainTestData joint_keychain_data = { + MockAppleKeychain::KeychainTestData joint_keychain_data = { kSecAuthenticationTypeHTMLForm, "some.domain.com", kSecProtocolTypeHTTP, "/insecure.html", 0, NULL, "20020601171500Z", "joe_user", "sekrit", false }; keychain_->AddTestItem(joint_keychain_data); // Insert a password into the keychain only. - MockKeychain::KeychainTestData keychain_only_data = { + MockAppleKeychain::KeychainTestData keychain_only_data = { kSecAuthenticationTypeHTMLForm, "keychain.only.com", kSecProtocolTypeHTTP, NULL, 0, NULL, "20020601171500Z", "keychain", "only", false diff --git a/crypto/keychain_mac.h b/crypto/apple_keychain.h index bbcf8b1..840ccee8 100644 --- a/crypto/keychain_mac.h +++ b/crypto/apple_keychain.h @@ -10,6 +10,12 @@ #include "base/basictypes.h" #include "crypto/crypto_export.h" +#if defined (OS_IOS) +typedef void* SecKeychainRef; +typedef void* SecKeychainItemRef; +typedef void SecKeychainAttributeList; +#endif + namespace crypto { // Wraps the KeychainServices API in a very thin layer, to allow it to be @@ -20,11 +26,33 @@ namespace crypto { // SecKeychainFoo). The only exception is Free, which should be used for // anything returned from this class that would normally be freed with // CFRelease (to aid in testing). -class CRYPTO_EXPORT MacKeychain { +class CRYPTO_EXPORT AppleKeychain { public: - MacKeychain(); - virtual ~MacKeychain(); + AppleKeychain(); + virtual ~AppleKeychain(); + + virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const; + + virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const; + + virtual OSStatus AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const; +#if !defined(OS_IOS) virtual OSStatus ItemCopyAttributesAndData( SecKeychainItemRef itemRef, SecKeychainAttributeInfo* info, @@ -67,32 +95,12 @@ class CRYPTO_EXPORT MacKeychain { const void* passwordData, SecKeychainItemRef* itemRef) const; - virtual OSStatus FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const; - - virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const; - - virtual OSStatus AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const; - // Calls CFRelease on the given ref, after checking that |ref| is non-NULL. virtual void Free(CFTypeRef ref) const; +#endif // !defined(OS_IOS) private: - DISALLOW_COPY_AND_ASSIGN(MacKeychain); + DISALLOW_COPY_AND_ASSIGN(AppleKeychain); }; } // namespace crypto diff --git a/crypto/apple_keychain_ios.mm b/crypto/apple_keychain_ios.mm new file mode 100644 index 0000000..1a4c9d5 --- /dev/null +++ b/crypto/apple_keychain_ios.mm @@ -0,0 +1,202 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/apple_keychain.h" + +#import <Foundation/Foundation.h> + +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/memory/scoped_nsobject.h" + +namespace { + +enum KeychainAction { + kKeychainActionCreate, + kKeychainActionUpdate +}; + +// Creates a dictionary that can be used to query the keystore. +// Ownership follows the Create rule. +CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName) { + CFMutableDictionaryRef query = + CFDictionaryCreateMutable(NULL, + 5, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + // Type of element is generic password. + CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword); + + // Set the service name. + scoped_nsobject<NSString> service_name_ns( + [[NSString alloc] initWithBytes:serviceName + length:serviceNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(query, kSecAttrService, + base::mac::NSToCFCast(service_name_ns)); + + // Set the account name. + scoped_nsobject<NSString> account_name_ns( + [[NSString alloc] initWithBytes:accountName + length:accountNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(query, kSecAttrAccount, + base::mac::NSToCFCast(account_name_ns)); + + // Use the proper search constants, return only the data of the first match. + CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne); + CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue); + return query; +} + +// Creates a dictionary conatining the data to save into the keychain. +// Ownership follows the Create rule. +CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + KeychainAction action) { + CFMutableDictionaryRef keychain_data = + CFDictionaryCreateMutable(NULL, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + // Set the password. + NSData* password = [NSData dataWithBytes:passwordData length:passwordLength]; + CFDictionarySetValue(keychain_data, kSecValueData, + base::mac::NSToCFCast(password)); + + // If this is not a creation, no structural information is needed. + if (action != kKeychainActionCreate) + return keychain_data; + + // Set the type of the data. + CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword); + + // Only allow access when the device has been unlocked. + CFDictionarySetValue(keychain_data, + kSecAttrAccessible, + kSecAttrAccessibleWhenUnlocked); + + // Set the service name. + scoped_nsobject<NSString> service_name_ns( + [[NSString alloc] initWithBytes:serviceName + length:serviceNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(keychain_data, kSecAttrService, + base::mac::NSToCFCast(service_name_ns)); + + // Set the account name. + scoped_nsobject<NSString> account_name_ns( + [[NSString alloc] initWithBytes:accountName + length:accountNameLength + encoding:NSUTF8StringEncoding]); + CFDictionarySetValue(keychain_data, kSecAttrAccount, + base::mac::NSToCFCast(account_name_ns)); + + return keychain_data; +} + +} // namespace + +namespace crypto { + +AppleKeychain::AppleKeychain() {} + +AppleKeychain::~AppleKeychain() {} + +OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { + free(data); + return noErr; +} + +OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + base::mac::ScopedCFTypeRef<CFDictionaryRef> query( + CreateGenericPasswordQuery(serviceNameLength, + serviceName, + accountNameLength, + accountName)); + // Check that there is not already a password. + OSStatus status = SecItemCopyMatching(query, NULL); + if (status == errSecItemNotFound) { + // A new entry must be created. + base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data( + CreateKeychainData(serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + kKeychainActionCreate)); + status = SecItemAdd(keychain_data, NULL); + } else if (status == noErr) { + // The entry must be updated. + base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data( + CreateKeychainData(serviceNameLength, + serviceName, + accountNameLength, + accountName, + passwordLength, + passwordData, + kKeychainActionUpdate)); + status = SecItemUpdate(query, keychain_data); + } + + return status; +} + +OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { + DCHECK((passwordData && passwordLength) || + (!passwordData && !passwordLength)); + base::mac::ScopedCFTypeRef<CFDictionaryRef> query( + CreateGenericPasswordQuery(serviceNameLength, + serviceName, + accountNameLength, + accountName)); + + // Get the keychain item containing the password. + CFTypeRef resultRef = NULL; + OSStatus status = SecItemCopyMatching(query, &resultRef); + base::mac::ScopedCFTypeRef<CFTypeRef> result(resultRef); + + if (status != noErr) { + if (passwordData) { + *passwordData = NULL; + *passwordLength = 0; + } + return status; + } + + if (passwordData) { + CFDataRef data = base::mac::CFCast<CFDataRef>(result); + NSUInteger length = CFDataGetLength(data); + *passwordData = malloc(length * sizeof(UInt8)); + CFDataGetBytes(data, CFRangeMake(0, length), (UInt8*)*passwordData); + *passwordLength = length; + } + return status; +} + +} // namespace crypto diff --git a/crypto/keychain_mac.cc b/crypto/apple_keychain_mac.mm index 4d5715b..545be19 100644 --- a/crypto/keychain_mac.cc +++ b/crypto/apple_keychain_mac.mm @@ -2,15 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "crypto/keychain_mac.h" +#include "crypto/apple_keychain.h" + +#import <Foundation/Foundation.h> namespace crypto { -MacKeychain::MacKeychain() {} +AppleKeychain::AppleKeychain() {} -MacKeychain::~MacKeychain() {} +AppleKeychain::~AppleKeychain() {} -OSStatus MacKeychain::ItemCopyAttributesAndData( +OSStatus AppleKeychain::ItemCopyAttributesAndData( SecKeychainItemRef itemRef, SecKeychainAttributeInfo* info, SecItemClass* itemClass, @@ -21,7 +23,7 @@ OSStatus MacKeychain::ItemCopyAttributesAndData( attrList, length, outData); } -OSStatus MacKeychain::ItemModifyAttributesAndData( +OSStatus AppleKeychain::ItemModifyAttributesAndData( SecKeychainItemRef itemRef, const SecKeychainAttributeList* attrList, UInt32 length, @@ -30,17 +32,17 @@ OSStatus MacKeychain::ItemModifyAttributesAndData( data); } -OSStatus MacKeychain::ItemFreeAttributesAndData( +OSStatus AppleKeychain::ItemFreeAttributesAndData( SecKeychainAttributeList* attrList, void* data) const { return SecKeychainItemFreeAttributesAndData(attrList, data); } -OSStatus MacKeychain::ItemDelete(SecKeychainItemRef itemRef) const { +OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { return SecKeychainItemDelete(itemRef); } -OSStatus MacKeychain::SearchCreateFromAttributes( +OSStatus AppleKeychain::SearchCreateFromAttributes( CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList* attrList, @@ -49,12 +51,12 @@ OSStatus MacKeychain::SearchCreateFromAttributes( attrList, searchRef); } -OSStatus MacKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { +OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const { return SecKeychainSearchCopyNext(searchRef, itemRef); } -OSStatus MacKeychain::AddInternetPassword( +OSStatus AppleKeychain::AddInternetPassword( SecKeychainRef keychain, UInt32 serverNameLength, const char* serverName, @@ -80,14 +82,14 @@ OSStatus MacKeychain::AddInternetPassword( itemRef); } -OSStatus MacKeychain::FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const { +OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { return SecKeychainFindGenericPassword(keychainOrArray, serviceNameLength, serviceName, @@ -98,19 +100,19 @@ OSStatus MacKeychain::FindGenericPassword(CFTypeRef keychainOrArray, itemRef); } -OSStatus MacKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const { +OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { return SecKeychainItemFreeContent(attrList, data); } -OSStatus MacKeychain::AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { +OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { return SecKeychainAddGenericPassword(keychain, serviceNameLength, serviceName, @@ -121,7 +123,7 @@ OSStatus MacKeychain::AddGenericPassword(SecKeychainRef keychain, itemRef); } -void MacKeychain::Free(CFTypeRef ref) const { +void AppleKeychain::Free(CFTypeRef ref) const { if (ref) CFRelease(ref); } diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index 40606a7..c9313080 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp @@ -65,6 +65,13 @@ 'symmetric_key_win.cc', ], }], + [ 'OS != "mac" and OS != "ios"', { + 'sources!': [ + 'apple_keychain.h', + 'mock_apple_keychain.cc', + 'mock_apple_keychain.h', + ], + }], [ 'OS == "android"', { 'dependencies': [ '../third_party/openssl/openssl.gyp:openssl', @@ -86,6 +93,12 @@ }, }, ], + [ 'OS == "ios"', { + 'sources!': [ + # This class is stubbed out on iOS. + 'rsa_private_key.cc', + ], + }], [ 'OS == "mac"', { 'link_settings': { 'libraries': [ @@ -156,18 +169,13 @@ ], },], ], - 'target_conditions' : [ - [ 'OS == "ios"', { - 'sources!': [ - # This class is stubbed out on iOS. - 'rsa_private_key.cc', - ], - }], - ], 'sources': [ # NOTE: all transitive dependencies of HMAC on windows need # to be placed in the source list above. '<@(hmac_win64_related_sources)', + 'apple_keychain.h', + 'apple_keychain_ios.mm', + 'apple_keychain_mac.mm', 'capi_util.cc', 'capi_util.h', 'crypto_export.h', @@ -188,12 +196,12 @@ 'encryptor_openssl.cc', 'hmac_nss.cc', 'hmac_openssl.cc', - 'keychain_mac.cc', - 'keychain_mac.h', 'mac_security_services_lock.cc', 'mac_security_services_lock.h', - 'mock_keychain_mac.cc', - 'mock_keychain_mac.h', + 'mock_apple_keychain.cc', + 'mock_apple_keychain.h', + 'mock_apple_keychain_ios.cc', + 'mock_apple_keychain_mac.cc', 'p224_spake.cc', 'p224_spake.h', 'nss_util.cc', diff --git a/crypto/mock_apple_keychain.cc b/crypto/mock_apple_keychain.cc new file mode 100644 index 0000000..bcabab8 --- /dev/null +++ b/crypto/mock_apple_keychain.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "base/time.h" +#include "crypto/mock_apple_keychain.h" + +namespace crypto { + +OSStatus MockAppleKeychain::FindGenericPassword( + CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const { + // When simulating |noErr|, return canned |passwordData| and + // |passwordLength|. Otherwise, just return given code. + if (find_generic_result_ == noErr) { + static const char kPassword[] = "my_password"; + DCHECK(passwordData); + // The function to free this data is mocked so the cast is fine. + *passwordData = const_cast<char*>(kPassword); + DCHECK(passwordLength); + *passwordLength = arraysize(kPassword); + password_data_count_++; + } + + return find_generic_result_; +} + +OSStatus MockAppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const { + // No-op. + password_data_count_--; + return noErr; +} + +OSStatus MockAppleKeychain::AddGenericPassword( + SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const { + called_add_generic_ = true; + + DCHECK_GT(passwordLength, 0U); + DCHECK(passwordData); + add_generic_password_ = + std::string(const_cast<char*>(static_cast<const char*>(passwordData)), + passwordLength); + return noErr; +} + +} // namespace crypto diff --git a/crypto/mock_keychain_mac.h b/crypto/mock_apple_keychain.h index 36bb94f..efbb438 100644 --- a/crypto/mock_keychain_mac.h +++ b/crypto/mock_apple_keychain.h @@ -13,27 +13,47 @@ #include <vector> #include "base/compiler_specific.h" -#include "crypto/keychain_mac.h" +#include "crypto/apple_keychain.h" namespace crypto { -// Type used for the keys in the std::map(s) and MockKeychain items. -typedef uintptr_t MockKeychainItemType; - // Mock Keychain wrapper for testing code that interacts with the OS X // Keychain. Implemented by storing SecKeychainAttributeList and // KeychainPasswordData values in separate mutable containers and // mapping them to integer keys. // // Note that "const" is pretty much meaningless for this class; the const-ness -// of MacKeychain doesn't apply to the actual keychain data, so all of the Mock -// data is mutable; don't assume that it won't change over the life of tests. -class CRYPTO_EXPORT MockKeychain : public MacKeychain { +// of AppleKeychain doesn't apply to the actual keychain data, so all of the +// Mock data is mutable; don't assume that it won't change over the life of +// tests. +class CRYPTO_EXPORT MockAppleKeychain : public AppleKeychain { public: - MockKeychain(); - virtual ~MockKeychain(); + MockAppleKeychain(); + virtual ~MockAppleKeychain(); + + // AppleKeychain implementation. + virtual OSStatus FindGenericPassword( + CFTypeRef keychainOrArray, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32* passwordLength, + void** passwordData, + SecKeychainItemRef* itemRef) const OVERRIDE; + virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, + void* data) const OVERRIDE; + virtual OSStatus AddGenericPassword( + SecKeychainRef keychain, + UInt32 serviceNameLength, + const char* serviceName, + UInt32 accountNameLength, + const char* accountName, + UInt32 passwordLength, + const void* passwordData, + SecKeychainItemRef* itemRef) const OVERRIDE; - // MacKeychain implementation. +#if !defined(OS_IOS) virtual OSStatus ItemCopyAttributesAndData( SecKeychainItemRef itemRef, SecKeychainAttributeInfo* info, @@ -72,26 +92,6 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { UInt32 passwordLength, const void* passwordData, SecKeychainItemRef* itemRef) const OVERRIDE; - virtual OSStatus FindGenericPassword( - CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const OVERRIDE; - virtual OSStatus ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const OVERRIDE; - virtual OSStatus AddGenericPassword( - SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const OVERRIDE; virtual void Free(CFTypeRef ref) const OVERRIDE; // Return the counts of objects returned by Create/Copy functions but never @@ -118,6 +118,7 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { }; // Adds a keychain item with the given info to the test set. void AddTestItem(const KeychainTestData& item_data); +#endif // !defined(OS_IOS) // |FindGenericPassword()| can return different results depending on user // interaction with the system Keychain. For mocking purposes we allow the @@ -139,6 +140,15 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { int password_data_count() const { return password_data_count_; } private: + + // Type used for the keys in the std::map(s) and MockAppleKeychain items. + typedef uintptr_t MockKeychainItemType; + + // Type of the map holding the mock keychain attributes. + typedef std::map<MockKeychainItemType, SecKeychainAttributeList> + MockKeychainAttributesMap; + +#if !defined(OS_IOS) // Returns true if the keychain already contains a password that matches the // attributes provided. bool AlreadyContainsInternetPassword( @@ -178,10 +188,9 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value); void SetTestDataCreator(MockKeychainItemType item, OSType value); // Sets the password data and length for the item-th test item. - void SetTestDataPasswordBytes( - MockKeychainItemType item, - const void* data, - size_t length); + void SetTestDataPasswordBytes(MockKeychainItemType item, + const void* data, + size_t length); // Sets the password for the item-th test item. As with SetTestDataString, // the data will not be null-terminated. void SetTestDataPasswordString(MockKeychainItemType item, const char* value); @@ -199,11 +208,11 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { UInt32 length; } KeychainPasswordData; - // Mutable because the MockKeychain API requires its internal keychain storage - // to be modifiable by users of this class. + // Mutable because the MockAppleKeychain API requires its internal keychain + // storage to be modifiable by users of this class. + mutable MockKeychainAttributesMap keychain_attr_list_; mutable std::map<MockKeychainItemType, - SecKeychainAttributeList> keychain_attr_list_; - mutable std::map<MockKeychainItemType, KeychainPasswordData> keychain_data_; + KeychainPasswordData> keychain_data_; mutable MockKeychainItemType next_item_key_; // Tracks the items that should be returned in subsequent calls to @@ -221,6 +230,7 @@ class CRYPTO_EXPORT MockKeychain : public MacKeychain { // Tracks which items (by key) were added with AddInternetPassword. mutable std::set<MockKeychainItemType> added_via_api_; +#endif // !defined(OS_IOS) // Result code for the |FindGenericPassword()| method. OSStatus find_generic_result_; diff --git a/crypto/mock_apple_keychain_ios.cc b/crypto/mock_apple_keychain_ios.cc new file mode 100644 index 0000000..f94a80d --- /dev/null +++ b/crypto/mock_apple_keychain_ios.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/logging.h" +#include "base/time.h" +#include "crypto/mock_apple_keychain.h" + +namespace crypto { + +MockAppleKeychain::MockAppleKeychain() + : find_generic_result_(noErr), + called_add_generic_(false), + password_data_count_(0) { +} + +MockAppleKeychain::~MockAppleKeychain() { +} + +} // namespace crypto diff --git a/crypto/mock_keychain_mac.cc b/crypto/mock_apple_keychain_mac.cc index f8c6c97..181f108 100644 --- a/crypto/mock_keychain_mac.cc +++ b/crypto/mock_apple_keychain_mac.cc @@ -4,15 +4,15 @@ #include "base/logging.h" #include "base/time.h" -#include "crypto/mock_keychain_mac.h" +#include "crypto/mock_apple_keychain.h" namespace crypto { // static -const SecKeychainSearchRef MockKeychain::kDummySearchRef = +const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef = reinterpret_cast<SecKeychainSearchRef>(1000); -MockKeychain::MockKeychain() +MockAppleKeychain::MockAppleKeychain() : next_item_key_(0), search_copy_count_(0), keychain_item_copy_count_(0), @@ -21,7 +21,7 @@ MockKeychain::MockKeychain() called_add_generic_(false), password_data_count_(0) {} -void MockKeychain::InitializeKeychainData(MockKeychainItemType key) const { +void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const { UInt32 tags[] = { kSecAccountItemAttr, kSecServerItemAttr, kSecPortItemAttr, @@ -64,9 +64,10 @@ void MockKeychain::InitializeKeychainData(MockKeychainItemType key) const { } } -MockKeychain::~MockKeychain() { - for (std::map<MockKeychainItemType, SecKeychainAttributeList>::iterator it = - keychain_attr_list_.begin(); it != keychain_attr_list_.end(); ++it) { +MockAppleKeychain::~MockAppleKeychain() { + for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin(); + it != keychain_attr_list_.end(); + ++it) { for (unsigned int i = 0; i < it->second.count; ++i) { if (it->second.attr[i].data) free(it->second.attr[i].data); @@ -79,7 +80,7 @@ MockKeychain::~MockKeychain() { keychain_data_.clear(); } -SecKeychainAttribute* MockKeychain::AttributeWithTag( +SecKeychainAttribute* MockAppleKeychain::AttributeWithTag( const SecKeychainAttributeList& attribute_list, UInt32 tag) { int attribute_index = -1; @@ -96,10 +97,10 @@ SecKeychainAttribute* MockKeychain::AttributeWithTag( return &(attribute_list.attr[attribute_index]); } -void MockKeychain::SetTestDataBytes(MockKeychainItemType item, - UInt32 tag, - const void* data, - size_t length) { +void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item, + UInt32 tag, + const void* data, + size_t length) { SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], tag); attribute->length = length; @@ -114,31 +115,30 @@ void MockKeychain::SetTestDataBytes(MockKeychainItemType item, } } -void MockKeychain::SetTestDataString( - MockKeychainItemType item, - UInt32 tag, - const char* value) { +void MockAppleKeychain::SetTestDataString(MockKeychainItemType item, + UInt32 tag, + const char* value) { SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); } -void MockKeychain::SetTestDataPort(MockKeychainItemType item, UInt32 value) { +void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item, + UInt32 value) { SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], kSecPortItemAttr); UInt32* data = static_cast<UInt32*>(attribute->data); *data = value; } -void MockKeychain::SetTestDataProtocol(MockKeychainItemType item, - SecProtocolType value) { +void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item, + SecProtocolType value) { SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], kSecProtocolItemAttr); SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data); *data = value; } -void MockKeychain::SetTestDataAuthType( - MockKeychainItemType item, - SecAuthenticationType value) { +void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item, + SecAuthenticationType value) { SecKeychainAttribute* attribute = AttributeWithTag( keychain_attr_list_[item], kSecAuthenticationTypeItemAttr); SecAuthenticationType* data = static_cast<SecAuthenticationType*>( @@ -146,24 +146,25 @@ void MockKeychain::SetTestDataAuthType( *data = value; } -void MockKeychain::SetTestDataNegativeItem(MockKeychainItemType item, - Boolean value) { +void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item, + Boolean value) { SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], kSecNegativeItemAttr); Boolean* data = static_cast<Boolean*>(attribute->data); *data = value; } -void MockKeychain::SetTestDataCreator(MockKeychainItemType item, OSType value) { +void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item, + OSType value) { SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], kSecCreatorItemAttr); OSType* data = static_cast<OSType*>(attribute->data); *data = value; } -void MockKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, - const void* data, - size_t length) { +void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, + const void* data, + size_t length) { keychain_data_[item].length = length; if (length > 0) { if (keychain_data_[item].data) @@ -175,13 +176,12 @@ void MockKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, } } -void MockKeychain::SetTestDataPasswordString( - MockKeychainItemType item, - const char* value) { +void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item, + const char* value) { SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0); } -OSStatus MockKeychain::ItemCopyAttributesAndData( +OSStatus MockAppleKeychain::ItemCopyAttributesAndData( SecKeychainItemRef itemRef, SecKeychainAttributeInfo* info, SecItemClass* itemClass, @@ -207,7 +207,7 @@ OSStatus MockKeychain::ItemCopyAttributesAndData( return noErr; } -OSStatus MockKeychain::ItemModifyAttributesAndData( +OSStatus MockAppleKeychain::ItemModifyAttributesAndData( SecKeychainItemRef itemRef, const SecKeychainAttributeList* attrList, UInt32 length, @@ -224,7 +224,7 @@ OSStatus MockKeychain::ItemModifyAttributesAndData( if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) return errSecInvalidItemRef; - MockKeychain* mutable_this = const_cast<MockKeychain*>(this); + MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this); if (attrList) { for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) { if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) { @@ -240,14 +240,14 @@ OSStatus MockKeychain::ItemModifyAttributesAndData( return noErr; } -OSStatus MockKeychain::ItemFreeAttributesAndData( +OSStatus MockAppleKeychain::ItemFreeAttributesAndData( SecKeychainAttributeList* attrList, void* data) const { --attribute_data_copy_count_; return noErr; } -OSStatus MockKeychain::ItemDelete(SecKeychainItemRef itemRef) const { +OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { MockKeychainItemType key = reinterpret_cast<MockKeychainItemType>(itemRef) - 1; @@ -265,7 +265,7 @@ OSStatus MockKeychain::ItemDelete(SecKeychainItemRef itemRef) const { return noErr; } -OSStatus MockKeychain::SearchCreateFromAttributes( +OSStatus MockAppleKeychain::SearchCreateFromAttributes( CFTypeRef keychainOrArray, SecItemClass itemClass, const SecKeychainAttributeList* attrList, @@ -273,8 +273,8 @@ OSStatus MockKeychain::SearchCreateFromAttributes( // Figure out which of our mock items matches, and set up the array we'll use // to generate results out of SearchCopyNext. remaining_search_results_.clear(); - for (std::map<MockKeychainItemType, SecKeychainAttributeList>::const_iterator - it = keychain_attr_list_.begin(); + for (MockKeychainAttributesMap::const_iterator it = + keychain_attr_list_.begin(); it != keychain_attr_list_.end(); ++it) { bool mock_item_matches = true; @@ -298,7 +298,7 @@ OSStatus MockKeychain::SearchCreateFromAttributes( return noErr; } -bool MockKeychain::AlreadyContainsInternetPassword( +bool MockAppleKeychain::AlreadyContainsInternetPassword( UInt32 serverNameLength, const char* serverName, UInt32 securityDomainLength, @@ -310,8 +310,8 @@ bool MockKeychain::AlreadyContainsInternetPassword( UInt16 port, SecProtocolType protocol, SecAuthenticationType authenticationType) const { - for (std::map<MockKeychainItemType, SecKeychainAttributeList>::const_iterator - it = keychain_attr_list_.begin(); + for (MockKeychainAttributesMap::const_iterator it = + keychain_attr_list_.begin(); it != keychain_attr_list_.end(); ++it) { SecKeychainAttribute* attribute; @@ -374,7 +374,7 @@ bool MockKeychain::AlreadyContainsInternetPassword( return false; } -OSStatus MockKeychain::AddInternetPassword( +OSStatus MockAppleKeychain::AddInternetPassword( SecKeychainRef keychain, UInt32 serverNameLength, const char* serverName, @@ -411,7 +411,7 @@ OSStatus MockKeychain::AddInternetPassword( // Initialize keychain data storage at the target location. InitializeKeychainData(key); - MockKeychain* mutable_this = const_cast<MockKeychain*>(this); + MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this); mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName, serverNameLength); mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr, @@ -441,8 +441,8 @@ OSStatus MockKeychain::AddInternetPassword( return noErr; } -OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { +OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, + SecKeychainItemRef* itemRef) const { if (remaining_search_results_.empty()) return errSecItemNotFound; MockKeychainItemType key = remaining_search_results_.front(); @@ -452,55 +452,7 @@ OSStatus MockKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, return noErr; } -OSStatus MockKeychain::FindGenericPassword(CFTypeRef keychainOrArray, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32* passwordLength, - void** passwordData, - SecKeychainItemRef* itemRef) const { - // When simulating |noErr| we return canned |passwordData| and - // |passwordLenght|. Otherwise, just return given code. - if (find_generic_result_ == noErr) { - static char password[] = "my_password"; - - DCHECK(passwordData); - *passwordData = static_cast<void*>(password); - DCHECK(passwordLength); - *passwordLength = strlen(password); - password_data_count_++; - } - - return find_generic_result_; -} - -OSStatus MockKeychain::ItemFreeContent(SecKeychainAttributeList* attrList, - void* data) const { - // No-op. - password_data_count_--; - return noErr; -} - -OSStatus MockKeychain::AddGenericPassword(SecKeychainRef keychain, - UInt32 serviceNameLength, - const char* serviceName, - UInt32 accountNameLength, - const char* accountName, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - called_add_generic_ = true; - - DCHECK(passwordLength > 0); - DCHECK(passwordData); - add_generic_password_ = - std::string(const_cast<char*>(static_cast<const char*>(passwordData)), - passwordLength); - return noErr; -} - -void MockKeychain::Free(CFTypeRef ref) const { +void MockAppleKeychain::Free(CFTypeRef ref) const { if (!ref) return; @@ -511,19 +463,19 @@ void MockKeychain::Free(CFTypeRef ref) const { } } -int MockKeychain::UnfreedSearchCount() const { +int MockAppleKeychain::UnfreedSearchCount() const { return search_copy_count_; } -int MockKeychain::UnfreedKeychainItemCount() const { +int MockAppleKeychain::UnfreedKeychainItemCount() const { return keychain_item_copy_count_; } -int MockKeychain::UnfreedAttributeDataCount() const { +int MockAppleKeychain::UnfreedAttributeDataCount() const { return attribute_data_copy_count_; } -bool MockKeychain::CreatorCodesSetForAddedItems() const { +bool MockAppleKeychain::CreatorCodesSetForAddedItems() const { for (std::set<MockKeychainItemType>::const_iterator i = added_via_api_.begin(); i != added_via_api_.end(); @@ -537,7 +489,7 @@ bool MockKeychain::CreatorCodesSetForAddedItems() const { return true; } -void MockKeychain::AddTestItem(const KeychainTestData& item_data) { +void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) { MockKeychainItemType key = next_item_key_++; InitializeKeychainData(key); |