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: chrome/browser/mac/keychain_reauthorize.mm

Issue 2721333005: Reauthorize Keychain to Replace Developer ID Certificate (Closed)
Patch Set: Remove histogram.h include 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_macros.h"
19 #include "base/scoped_generic.h"
20 #include "components/os_crypt/keychain_password_mac.h"
21 #include "crypto/apple_keychain.h"
22
23 namespace chrome {
24
25 namespace {
26
27 struct VectorScramblerTraits {
28 static std::vector<uint8_t>* InvalidValue() { return nullptr; }
29
30 static void Free(std::vector<uint8_t>* buf) {
31 memset(buf->data(), 0x11, buf->size());
32 delete buf;
33 }
34 };
35
36 typedef base::ScopedGeneric<std::vector<uint8_t>*, VectorScramblerTraits>
37 ScopedVectorScrambler;
38
39 // Reauthorizes the Safe Storage keychain item, which protects the randomly
40 // generated password that encrypts the user's saved passwords. This reads out
41 // the keychain item, deletes it, and re-adds it to the keychain. This works
42 // because the keychain uses an app's designated requirement as the ACL for
43 // reading an item. Chrome will be signed with a designated requirement that
44 // accepts both the old and new certificates.
45 bool KeychainReauthorize() {
46 base::ScopedCFTypeRef<SecKeychainItemRef> storage_item;
47 UInt32 pw_length = 0;
48 void* password_data = nullptr;
49
50 crypto::AppleKeychain keychain;
51 OSStatus error = keychain.FindGenericPassword(
52 nullptr, strlen(KeychainPassword::service_name),
53 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
54 KeychainPassword::account_name, &pw_length, &password_data,
55 storage_item.InitializeInto());
56
57 if (error != noErr) {
58 OSSTATUS_LOG(ERROR, error)
59 << "KeychainReauthorize failed. Cannot retrieve item.";
60 return false;
61 }
62
63 ScopedVectorScrambler password;
64 password.reset(new std::vector<uint8_t>(
65 static_cast<uint8_t*>(password_data),
66 static_cast<uint8_t*>(password_data) + pw_length));
67 memset(password_data, 0x11, pw_length);
68 keychain.ItemFreeContent(nullptr, password_data);
69
70 error = keychain.ItemDelete(storage_item);
71 if (error != noErr) {
72 OSSTATUS_LOG(ERROR, error)
73 << "KeychainReauthorize failed. Cannot delete item.";
74 return false;
75 }
76
77 error = keychain.AddGenericPassword(
78 NULL, strlen(KeychainPassword::service_name),
79 KeychainPassword::service_name, strlen(KeychainPassword::account_name),
80 KeychainPassword::account_name, password.get()->size(),
81 password.get()->data(), nullptr);
82
83 if (error != noErr) {
84 OSSTATUS_LOG(ERROR, error) << "Failed to re-add storage password.";
85 return false;
86 }
87 return true;
88 }
89
90 } // namespace
91
92 void KeychainReauthorizeIfNeeded(NSString* pref_key, int max_tries) {
93 NSUserDefaults* user_defaults = [NSUserDefaults standardUserDefaults];
94 int pref_value = [user_defaults integerForKey:pref_key];
95
96 if (pref_value >= max_tries)
97 return;
98
99 NSString* success_pref_key = [pref_key stringByAppendingString:@"Success"];
100 BOOL success_value = [user_defaults boolForKey:success_pref_key];
101 if (success_value)
102 return;
103
104 if (pref_value > 0) {
105 // Logs the number of previous tries that didn't complete.
106 if (base::mac::AmIBundled()) {
107 UMA_HISTOGRAM_SPARSE_SLOWLY("OSX.KeychainReauthorizeIfNeeded",
108 pref_value);
109 } else {
110 UMA_HISTOGRAM_SPARSE_SLOWLY("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_SPARSE_SLOWLY("OSX.KeychainReauthorizeIfNeededSuccess",
130 pref_value);
131 } else {
132 UMA_HISTOGRAM_SPARSE_SLOWLY(
133 "OSX.KeychainReauthorizeIfNeededAtUpdateSuccess", pref_value);
134 }
135 }
136
137 } // 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