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

Side by Side Diff: chrome/browser/mac/keychain_reauthorize.mm

Issue 2721333005: Reauthorize Keychain to Replace Developer ID Certificate (Closed)
Patch Set: Reauthorize Keychain to Replace Developer ID Certificate Created 3 years, 9 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 2017 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 "chrome/browser/mac/keychain_reauthorize.h"
6
7 #import <Foundation/Foundation.h>
8 #include <Security/Security.h>
9
10 #include <string.h>
11
12 #include "base/logging.h"
13 #include "base/mac/foundation_util.h"
14 #include "base/mac/scoped_cftyperef.h"
15 #include "base/metrics/histogram.h"
16 #include "base/metrics/histogram_macros.h"
17 #include "base/scoped_generic.h"
18 #include "components/os_crypt/keychain_password_mac.h"
19 #include "crypto/apple_keychain.h"
20
21 namespace chrome {
22
23 namespace {
24
25 // Reauthorizes the Safe Storage keychain item, which protects the randomly
26 // generated password that encrypts the user's saved passwords. This reads out
27 // the keychain item, deletes it, and re-adds it to the keychain. This works
28 // because the keychain uses an apps designated requirement as the default ACL
Mark Mentovai 2017/03/01 22:00:30 “default ACL for”→“ACL for reading”
Mark Mentovai 2017/03/01 22:00:31 app’s
Greg K 2017/03/02 01:28:27 Done.
Greg K 2017/03/02 01:28:27 Done.
29 // for an item. We are signing Chrome with the current certificate (so it can
Mark Mentovai 2017/03/01 22:00:31 Don’t say “we.” Also, the bit about signing will b
Greg K 2017/03/02 01:28:27 Done.
30 // access the item), but using a designated requirement that accepts the current
31 // and new certificates as valid.
32 bool KeychainReauthorize() {
33 base::ScopedCFTypeRef<SecKeychainItemRef> storage_item;
34 UInt32 pw_length = 0;
35 void* password_data = nullptr;
36
37 crypto::AppleKeychain keychain;
38 OSStatus error = keychain.FindGenericPassword(
39 NULL, strlen(KeychainPassword::service_name),
Mark Mentovai 2017/03/01 22:00:31 Use nullptr now in new code. Hooray for C++11!
Greg K 2017/03/02 01:28:27 Done.
40 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
Mark Mentovai 2017/03/01 22:00:31 If git cl format formatted this, then it’s fine be
Greg K 2017/03/02 01:28:27 Done.
41 KeychainPassword::account_name, &pw_length, &password_data,
42 storage_item.InitializeInto());
43
44 std::string password =
Mark Mentovai 2017/03/01 22:00:30 One of the sanitizers may not like this if !passwo
Greg K 2017/03/02 01:28:27 Done.
45 std::string(static_cast<char*>(password_data), pw_length);
46 if (password_data) {
47 memset(password_data, 0xAA, pw_length);
Mark Mentovai 2017/03/01 22:00:31 This is good. memset_s() would be even better. But
Greg K 2017/03/02 01:28:27 memset_s requires some LIBC extension, but let's d
48 keychain.ItemFreeContent(nullptr, password_data);
49 }
50
51 if (error != noErr)
52 return false;
Mark Mentovai 2017/03/01 22:00:30 Wanna say something about this?
Greg K 2017/03/02 01:28:27 Done.
53
54 if (keychain.ItemDelete(storage_item) != noErr) {
55 LOG(ERROR) << "KeychainReauthorize failed. Cannot delete item.";
Mark Mentovai 2017/03/01 22:00:31 Aha! Whenever you’re logging something about an OS
56 return false;
57 }
58
59 error = keychain.AddGenericPassword(
Mark Mentovai 2017/03/01 22:00:31 I’m pretty sure that the answer is no, but we can’
Greg K 2017/03/02 01:28:27 Definitely good to test, but it failed.
60 NULL, strlen(KeychainPassword::service_name),
61 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
62 KeychainPassword::account_name, password.size(), password.data(), NULL);
63
64 if (error != noErr) {
65 LOG(ERROR) << "Failed to re-add storage password.";
66 return false;
67 }
68 return true;
69 }
70
71 } // namespace
72
73 void KeychainReauthorizeIfNeeded(NSString* pref_key, int max_tries) {
74 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
75 [user_defaults synchronize];
Mark Mentovai 2017/03/01 22:00:31 I don’t believe that this one will do anything, be
Greg K 2017/03/02 01:28:27 Done.
76 int pref_value = [user_defaults integerForKey:pref_key];
77
78 if (pref_value >= max_tries)
79 return;
80
81 BOOL success_value =
82 [user_defaults boolForKey:[pref_key stringByAppendingString:@"Success"]];
83 if (success_value)
84 return;
85
86 if (pref_value > 0) {
87 // Logs the number of previous tries that didn't complete.
88 if (base::mac::AmIBundled()) {
89 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeeded", pref_value);
90 } else {
91 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdate",
92 pref_value);
93 }
94 }
95
96 bool success = KeychainReauthorize();
97
98 ++pref_value;
Mark Mentovai 2017/03/01 22:00:31 The comment in the header was explicit that this w
Greg K 2017/03/02 01:28:27 That makes sense, I didn't think about that.
99 [user_defaults setInteger:pref_value forKey:pref_key];
100 [user_defaults synchronize];
101
102 if (!success)
103 return;
104
105 NSString* success_pref_key = [pref_key stringByAppendingString:@"Success"];
Mark Mentovai 2017/03/01 22:00:31 You already computed this above, on line 82. You s
Greg K 2017/03/02 01:28:27 Done.
106 [user_defaults setBool:YES forKey:success_pref_key];
107 [user_defaults synchronize];
108
109 // Logs the try number (1, 2) that succeeded.
110 if (base::mac::AmIBundled()) {
111 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededSuccess", pref_value);
112 } else {
113 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdateSuccess",
114 pref_value);
115 }
116 }
117
118 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698