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

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

Issue 2721333005: Reauthorize Keychain to Replace Developer ID Certificate (Closed)
Patch Set: Changes per review 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 <vector>
13
14 #include "base/logging.h"
15 #include "base/mac/foundation_util.h"
16 #include "base/mac/mac_logging.h"
17 #include "base/mac/scoped_cftyperef.h"
18 #include "base/metrics/histogram.h"
19 #include "base/metrics/histogram_macros.h"
20 #include "base/scoped_generic.h"
21 #include "components/os_crypt/keychain_password_mac.h"
22 #include "crypto/apple_keychain.h"
23
24 namespace chrome {
25
26 namespace {
27
28 struct VectorScramblerTraits {
29 static std::vector<uint8_t>* InvalidValue() { return nullptr; }
30
31 static void Free(std::vector<uint8_t>* buf) {
32 memset(buf->data(), 0xBA5EBA11, buf->size());
Mark Mentovai 2017/03/02 02:59:32 That’s cute, but you’re really just using 0x11 her
Greg K 2017/03/02 18:54:14 Given that this is pretty important and time sensi
33 delete buf;
34 }
35 };
36
37 typedef base::ScopedGeneric<std::vector<uint8_t>*, VectorScramblerTraits>
38 ScopedVectorScrambler;
39
40 // Reauthorizes the Safe Storage keychain item, which protects the randomly
41 // generated password that encrypts the user's saved passwords. This reads out
42 // the keychain item, deletes it, and re-adds it to the keychain. This works
43 // because the keychain uses an app's designated requirement as the ACL for
44 // reading an item. Chrome will be signed with a designated requirement that
45 // accepts both the old and new certificates.
46 bool KeychainReauthorize() {
47 base::ScopedCFTypeRef<SecKeychainItemRef> storage_item;
48 UInt32 pw_length = 0;
49 void* password_data = nullptr;
50
51 crypto::AppleKeychain keychain;
52 OSStatus error = keychain.FindGenericPassword(
53 nullptr, strlen(KeychainPassword::service_name),
54 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
55 KeychainPassword::account_name, &pw_length, &password_data,
56 storage_item.InitializeInto());
57
58 ScopedVectorScrambler password;
59 if (password_data) {
Mark Mentovai 2017/03/02 02:59:32 I think you should be working off of error here, n
Greg K 2017/03/02 18:54:14 Done.
60 password.reset(new std::vector<uint8_t>(
61 static_cast<uint8_t*>(password_data),
62 static_cast<uint8_t*>(password_data) + pw_length));
63 memset(password_data, 0xBA5EBA11, pw_length);
64 keychain.ItemFreeContent(nullptr, password_data);
65 }
66
67 if (error != noErr) {
68 OSSTATUS_LOG(ERROR, error)
69 << "KeychainReauthorize failed. Cannot retrieve item.";
70 return false;
71 }
72
73 if (password.get() == nullptr) {
Mark Mentovai 2017/03/02 02:59:32 I want to say that this can’t happen and isn’t wor
Greg K 2017/03/02 18:54:14 Done.
74 LOG(ERROR) << "Invalid condition. FindGenericPassword succeeded, password "
75 "is null.";
76 return false;
77 }
78
79 error = keychain.ItemDelete(storage_item);
80 if (error != noErr) {
81 OSSTATUS_LOG(ERROR, error)
82 << "KeychainReauthorize failed. Cannot delete item.";
83 return false;
84 }
85
86 error = keychain.AddGenericPassword(
87 NULL, strlen(KeychainPassword::service_name),
88 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
89 KeychainPassword::account_name, password.get()->size(),
90 password.get()->data(), NULL);
Mark Mentovai 2017/03/02 02:59:32 nullptr
91
92 if (error != noErr) {
93 OSSTATUS_LOG(ERROR, error) << "Failed to re-add storage password.";
94 return false;
95 }
96 return true;
97 }
98
99 } // namespace
100
101 void KeychainReauthorizeIfNeeded(NSString* pref_key, int max_tries) {
102 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
103 int pref_value = [user_defaults integerForKey:pref_key];
104
105 if (pref_value >= max_tries)
106 return;
107
108 NSString* success_pref_key = [pref_key stringByAppendingString:@"Success"];
109 BOOL success_value = [user_defaults boolForKey:success_pref_key];
110 if (success_value)
111 return;
112
113 if (pref_value > 0) {
114 // Logs the number of previous tries that didn't complete.
115 if (base::mac::AmIBundled()) {
116 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeeded", pref_value);
117 } else {
118 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdate",
119 pref_value);
120 }
121 }
122
123 ++pref_value;
124 [user_defaults setInteger:pref_value forKey:pref_key];
125 [user_defaults synchronize];
126
127 bool success = KeychainReauthorize();
128
129 if (!success)
130 return;
131
132 [user_defaults setBool:YES forKey:success_pref_key];
133 [user_defaults synchronize];
134
135 // Logs the try number (1, 2) that succeeded.
136 if (base::mac::AmIBundled()) {
137 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededSuccess", pref_value);
138 } else {
139 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdateSuccess",
140 pref_value);
141 }
142 }
143
144 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698