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

Side by Side 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, 3 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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
5 #include "crypto/apple_keychain.h"
6
7 #import <Foundation/Foundation.h>
8
9 #include "base/mac/foundation_util.h"
10 #include "base/mac/scoped_cftyperef.h"
11 #include "base/memory/scoped_nsobject.h"
12
13 namespace {
14
15 enum KeychainAction {
16 kKeychainActionCreate,
17 kKeychainActionUpdate
18 };
19
20 // Creates a dictionary that can be used to query the keystore.
21 // Ownership follows the Create rule.
22 CFDictionaryRef CreateGenericPasswordQuery(UInt32 serviceNameLength,
23 const char* serviceName,
24 UInt32 accountNameLength,
25 const char* accountName) {
26 CFMutableDictionaryRef query =
27 CFDictionaryCreateMutable(NULL,
28 5,
29 &kCFTypeDictionaryKeyCallBacks,
30 &kCFTypeDictionaryValueCallBacks);
31 // Type of element is generic password.
32 CFDictionarySetValue(query, kSecClass, kSecClassGenericPassword);
33
34 // Set the service name.
35 scoped_nsobject<NSString> service_name_ns(
36 [[NSString alloc] initWithBytes:serviceName
37 length:serviceNameLength
38 encoding:NSUTF8StringEncoding]);
39 CFDictionarySetValue(query, kSecAttrService, service_name_ns);
40
41 // Set the account name.
42 scoped_nsobject<NSString> account_name_ns(
43 [[NSString alloc] initWithBytes:accountName
44 length:accountNameLength
45 encoding:NSUTF8StringEncoding]);
46 CFDictionarySetValue(query, kSecAttrAccount, account_name_ns);
47
48 // Use the proper search constants, return only the data of the first match.
49 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitOne);
50 CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
51 return query;
52 }
53
54 // Creates a dictionary conatining the data to save into the keychain.
55 // Ownership follows the Create rule.
56 CFDictionaryRef CreateKeychainData(UInt32 serviceNameLength,
57 const char* serviceName,
58 UInt32 accountNameLength,
59 const char* accountName,
60 UInt32 passwordLength,
61 const void* passwordData,
62 KeychainAction action) {
63 CFMutableDictionaryRef keychain_data =
64 CFDictionaryCreateMutable(NULL,
65 0,
66 &kCFTypeDictionaryKeyCallBacks,
67 &kCFTypeDictionaryValueCallBacks);
68
69 // Set the password.
70 NSData* password = [NSData dataWithBytes:passwordData length:passwordLength];
71 CFDictionarySetValue(keychain_data, kSecValueData, password);
72
73 // If this is a creation, the structural information must be defined.
74 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.
75 // Set the type of the data.
76 CFDictionarySetValue(keychain_data, kSecClass, kSecClassGenericPassword);
77
78 // Only allow access when the device has been unlocked.
79 CFDictionarySetValue(keychain_data,
80 kSecAttrAccessible,
81 kSecAttrAccessibleWhenUnlocked);
82
83 // Set the service name.
84 scoped_nsobject<NSString> service_name_ns(
85 [[NSString alloc] initWithBytes:serviceName
86 length:serviceNameLength
87 encoding:NSUTF8StringEncoding]);
88 CFDictionarySetValue(keychain_data, kSecAttrService, service_name_ns);
89
90 // Set the account name.
91 scoped_nsobject<NSString> account_name_ns(
92 [[NSString alloc] initWithBytes:accountName
93 length:accountNameLength
94 encoding:NSUTF8StringEncoding]);
95 CFDictionarySetValue(keychain_data, kSecAttrAccount, account_name_ns);
96 }
97
98 return keychain_data;
99 }
100
101 } // namespace
102
103 namespace crypto {
104
105 AppleKeychain::AppleKeychain() {}
106
107 AppleKeychain::~AppleKeychain() {}
108
109 OSStatus AppleKeychain::ItemFreeContent(SecKeychainAttributeList* attrList,
110 void* data) const {
111 free(data);
112 return noErr;
113 }
114
115 OSStatus AppleKeychain::AddGenericPassword(SecKeychainRef keychain,
116 UInt32 serviceNameLength,
117 const char* serviceName,
118 UInt32 accountNameLength,
119 const char* accountName,
120 UInt32 passwordLength,
121 const void* passwordData,
122 SecKeychainItemRef* itemRef) const {
123 base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
124 CreateGenericPasswordQuery(serviceNameLength,
125 serviceName,
126 accountNameLength,
127 accountName));
128 // Check that there is not already a password.
129 OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, NULL);
130 if (status == errSecItemNotFound) {
131 // A new entry must be created.
132 base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
133 CreateKeychainData(serviceNameLength,
134 serviceName,
135 accountNameLength,
136 accountName,
137 passwordLength,
138 passwordData,
139 kKeychainActionCreate));
140 status = SecItemAdd(keychain_data, NULL);
141 } else if (status == noErr) {
142 // The entry must be updated.
143 base::mac::ScopedCFTypeRef<CFDictionaryRef> keychain_data(
144 CreateKeychainData(serviceNameLength,
145 serviceName,
146 accountNameLength,
147 accountName,
148 passwordLength,
149 passwordData,
150 kKeychainActionUpdate));
151 status = SecItemUpdate(query, keychain_data);
152 }
153
154 return status;
155 }
156
157 OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray,
158 UInt32 serviceNameLength,
159 const char* serviceName,
160 UInt32 accountNameLength,
161 const char* accountName,
162 UInt32* passwordLength,
163 void** passwordData,
164 SecKeychainItemRef* itemRef) const {
165 DCHECK((passwordData && passwordLength) ||
166 (!passwordData && !passwordLength));
167 base::mac::ScopedCFTypeRef<CFDictionaryRef> query(
168 CreateGenericPasswordQuery(serviceNameLength,
169 serviceName,
170 accountNameLength,
171 accountName));
172
173 CFTypeRef result = NULL;
174 OSStatus status = SecItemCopyMatching(query, &result);
175 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.
176 if (passwordData) {
177 NSData* data =
178 base::mac::CFToNSCast(base::mac::CFCast<CFDataRef>(result));
179 NSUInteger length = [data length];
180 *passwordData = malloc(length);
181 [data getBytes:*passwordData length:length];
182 *passwordLength = length;
183 }
184 CFRelease(result);
185 } else {
186 if (passwordData) {
187 *passwordData = NULL;
188 *passwordLength = 0;
189 }
190 }
191 return status;
192 }
193
194 } // namespace crypto
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698