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

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

Issue 2721333005: Reauthorize Keychain to Replace Developer ID Certificate (Closed)
Patch Set: Cleanup the comments, and error handling logic 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(), 0x11, buf->size());
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 if (error != noErr) {
59 OSSTATUS_LOG(ERROR, error)
60 << "KeychainReauthorize failed. Cannot retrieve item.";
61 return false;
62 }
63
64 ScopedVectorScrambler password;
65 password.reset(new std::vector<uint8_t>(
66 static_cast<uint8_t*>(password_data),
67 static_cast<uint8_t*>(password_data) + pw_length));
68 memset(password_data, 0x11, pw_length);
69 keychain.ItemFreeContent(nullptr, password_data);
70
71 error = keychain.ItemDelete(storage_item);
72 if (error != noErr) {
73 OSSTATUS_LOG(ERROR, error)
74 << "KeychainReauthorize failed. Cannot delete item.";
75 return false;
76 }
77
78 error = keychain.AddGenericPassword(
79 NULL, strlen(KeychainPassword::service_name),
80 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
81 KeychainPassword::account_name, password.get()->size(),
82 password.get()->data(), nullptr);
83
84 if (error != noErr) {
85 OSSTATUS_LOG(ERROR, error) << "Failed to re-add storage password.";
86 return false;
87 }
88 return true;
89 }
90
91 } // namespace
92
93 void KeychainReauthorizeIfNeeded(NSString* pref_key, int max_tries) {
Ilya Sherman 2017/03/03 01:36:12 It looks like this function is never called. Is t
Greg K 2017/03/03 18:18:03 Yes, the next CL will add some backup protection a
94 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
95 int pref_value = [user_defaults integerForKey:pref_key];
96
97 if (pref_value >= max_tries)
98 return;
99
100 NSString* success_pref_key = [pref_key stringByAppendingString:@"Success"];
101 BOOL success_value = [user_defaults boolForKey:success_pref_key];
102 if (success_value)
103 return;
104
105 if (pref_value > 0) {
106 // Logs the number of previous tries that didn't complete.
107 if (base::mac::AmIBundled()) {
108 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeeded", pref_value);
Ilya Sherman 2017/03/03 01:36:12 This histogram has an upper bound of 1000000, and
Greg K 2017/03/03 18:18:03 Done.
109 } else {
110 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdate",
111 pref_value);
112 }
113 }
114
115 ++pref_value;
116 [user_defaults setInteger:pref_value forKey:pref_key];
117 [user_defaults synchronize];
118
119 bool success = KeychainReauthorize();
120
121 if (!success)
122 return;
123
124 [user_defaults setBool:YES forKey:success_pref_key];
125 [user_defaults synchronize];
126
127 // Logs the try number (1, 2) that succeeded.
128 if (base::mac::AmIBundled()) {
129 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededSuccess", pref_value);
130 } else {
131 UMA_HISTOGRAM_COUNTS("OSX.KeychainReauthorizeIfNeededAtUpdateSuccess",
132 pref_value);
133 }
134 }
135
136 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698