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

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

Issue 2721333005: Reauthorize Keychain to Replace Developer ID Certificate (Closed)
Patch Set: Updates 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
« no previous file with comments | « chrome/browser/mac/keychain_reauthorize.h ('k') | chrome/installer/mac/sign_app.sh.in » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
Ilya Sherman 2017/03/03 18:19:55 nit: It doesn't look like this #include is needed.
Greg K 2017/03/03 18:25:36 Done.
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) {
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_SPARSE_SLOWLY("OSX.KeychainReauthorizeIfNeeded",
109 pref_value);
110 } else {
111 UMA_HISTOGRAM_SPARSE_SLOWLY("OSX.KeychainReauthorizeIfNeededAtUpdate",
112 pref_value);
113 }
114 }
115
116 ++pref_value;
117 [user_defaults setInteger:pref_value forKey:pref_key];
118 [user_defaults synchronize];
119
120 bool success = KeychainReauthorize();
121
122 if (!success)
123 return;
124
125 [user_defaults setBool:YES forKey:success_pref_key];
126 [user_defaults synchronize];
127
128 // Logs the try number (1, 2) that succeeded.
129 if (base::mac::AmIBundled()) {
130 UMA_HISTOGRAM_SPARSE_SLOWLY("OSX.KeychainReauthorizeIfNeededSuccess",
131 pref_value);
132 } else {
133 UMA_HISTOGRAM_SPARSE_SLOWLY(
134 "OSX.KeychainReauthorizeIfNeededAtUpdateSuccess", pref_value);
135 }
136 }
137
138 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/mac/keychain_reauthorize.h ('k') | chrome/installer/mac/sign_app.sh.in » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698