Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2774)

Unified Diff: crypto/apple_keychain_ios.mm

Issue 10875029: Rename MacKeychain to AppleKeychain (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address code review. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: crypto/apple_keychain_ios.mm
diff --git a/crypto/apple_keychain_ios.mm b/crypto/apple_keychain_ios.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f3c25435827d25dc920627d4fbce59f3adcf0761
--- /dev/null
+++ b/crypto/apple_keychain_ios.mm
@@ -0,0 +1,194 @@
+// 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, service_name_ns);
+
+ // Set the account name.
+ scoped_nsobject<NSString> account_name_ns(
+ [[NSString alloc] initWithBytes:accountName
+ length:accountNameLength
+ encoding:NSUTF8StringEncoding]);
+ CFDictionarySetValue(query, kSecAttrAccount, 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, password);
+
+ // If this is a creation, the structural information must be defined.
+ if (action == kKeychainActionCreate) {
Ryan Sleevi 2012/08/29 01:18:38 Can you short-circuit early here? if (action != k
msarda 2012/08/29 11:58:27 Done.
+ // 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, 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, 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((CFDictionaryRef)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));
+
+ CFTypeRef result = NULL;
+ OSStatus status = SecItemCopyMatching(query, &result);
+ if (status == noErr) {
Ryan Sleevi 2012/08/29 01:18:38 nit: Perhaps re-order the error handling here so t
msarda 2012/08/29 11:58:27 Done.
+ if (passwordData) {
+ NSData* data =
+ base::mac::CFToNSCast(base::mac::CFCast<CFDataRef>(result));
+ NSUInteger length = [data length];
+ *passwordData = malloc(length);
+ [data getBytes:*passwordData length:length];
+ *passwordLength = length;
+ }
+ CFRelease(result);
+ } else {
+ if (passwordData) {
+ *passwordData = NULL;
+ *passwordLength = 0;
+ }
+ }
+ return status;
+}
+
+} // namespace crypto

Powered by Google App Engine
This is Rietveld 408576698