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

Side by Side Diff: components/gcm_driver/crypto/gcm_encryption_provider.cc

Issue 1707513002: Add various UMA histograms for measuring GCM crypto performance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@gcm-remove-info
Patch Set: android fix Created 4 years, 10 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/gcm_driver/crypto/gcm_encryption_provider.h" 5 #include "components/gcm_driver/crypto/gcm_encryption_provider.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 11 matching lines...) Expand all
22 22
23 const char kEncryptionProperty[] = "encryption"; 23 const char kEncryptionProperty[] = "encryption";
24 const char kCryptoKeyProperty[] = "crypto-key"; 24 const char kCryptoKeyProperty[] = "crypto-key";
25 25
26 // Directory in the GCM Store in which the encryption database will be stored. 26 // Directory in the GCM Store in which the encryption database will be stored.
27 const base::FilePath::CharType kEncryptionDirectoryName[] = 27 const base::FilePath::CharType kEncryptionDirectoryName[] =
28 FILE_PATH_LITERAL("Encryption"); 28 FILE_PATH_LITERAL("Encryption");
29 29
30 } // namespace 30 } // namespace
31 31
32 std::string GCMEncryptionProvider::ToDecryptionFailureDetailsString( 32 std::string GCMEncryptionProvider::ToDecryptionResultDetailsString(
33 DecryptionFailure reason) { 33 DecryptionResult result) {
34 switch(reason) { 34 switch(result) {
35 case DECRYPTION_FAILURE_UNKNOWN: 35 case DECRYPTION_RESULT_UNENCRYPTED:
36 return "Unknown failure"; 36 return "Message was not encrypted";
37 case DECRYPTION_FAILURE_INVALID_ENCRYPTION_HEADER: 37 case DECRYPTION_RESULT_DECRYPTED:
38 return "Message decrypted";
39 case DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER:
38 return "Invalid format for the Encryption header"; 40 return "Invalid format for the Encryption header";
39 case DECRYPTION_FAILURE_INVALID_CRYPTO_KEY_HEADER: 41 case DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER:
40 return "Invalid format for the Crypto-Key header"; 42 return "Invalid format for the Crypto-Key header";
41 case DECRYPTION_FAILURE_NO_KEYS: 43 case DECRYPTION_RESULT_NO_KEYS:
42 return "There are no associated keys with the subscription"; 44 return "There are no associated keys with the subscription";
43 case DECRYPTION_FAILURE_INVALID_PUBLIC_KEY: 45 case DECRYPTION_RESULT_INVALID_SHARED_SECRET:
44 return "The public key in the Crypto-Key header is invalid"; 46 return "The shared secret cannot be derived from the keying material";
45 case DECRYPTION_FAILURE_INVALID_PAYLOAD: 47 case DECRYPTION_RESULT_INVALID_PAYLOAD:
46 return "AES-GCM decryption failed"; 48 return "AES-GCM decryption failed";
47 } 49 }
48 50
49 NOTREACHED(); 51 NOTREACHED();
50 return "(invalid reason)"; 52 return "(invalid result)";
51 } 53 }
52 54
53 GCMEncryptionProvider::GCMEncryptionProvider() 55 GCMEncryptionProvider::GCMEncryptionProvider()
54 : weak_ptr_factory_(this) { 56 : weak_ptr_factory_(this) {
55 } 57 }
56 58
57 GCMEncryptionProvider::~GCMEncryptionProvider() { 59 GCMEncryptionProvider::~GCMEncryptionProvider() {
58 } 60 }
59 61
60 void GCMEncryptionProvider::Init( 62 void GCMEncryptionProvider::Init(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 if (message.data.find(kEncryptionProperty) == message.data.end() || 98 if (message.data.find(kEncryptionProperty) == message.data.end() ||
97 message.data.find(kCryptoKeyProperty) == message.data.end()) 99 message.data.find(kCryptoKeyProperty) == message.data.end())
98 return false; 100 return false;
99 101
100 return message.raw_data.size() > 0; 102 return message.raw_data.size() > 0;
101 } 103 }
102 104
103 void GCMEncryptionProvider::DecryptMessage( 105 void GCMEncryptionProvider::DecryptMessage(
104 const std::string& app_id, 106 const std::string& app_id,
105 const IncomingMessage& message, 107 const IncomingMessage& message,
106 const MessageDecryptedCallback& success_callback, 108 const MessageCallback& callback) {
107 const DecryptionFailedCallback& failure_callback) {
108 DCHECK(key_store_); 109 DCHECK(key_store_);
110 if (!IsEncryptedMessage(message)) {
111 callback.Run(DECRYPTION_RESULT_UNENCRYPTED, message);
112 return;
113 }
109 114
115 // IsEncryptedMessage() verifies that both the Encryption and Crypto-Key HTTP
116 // headers have been provided for the |message|.
110 const auto& encryption_header = message.data.find(kEncryptionProperty); 117 const auto& encryption_header = message.data.find(kEncryptionProperty);
111 const auto& crypto_key_header = message.data.find(kCryptoKeyProperty); 118 const auto& crypto_key_header = message.data.find(kCryptoKeyProperty);
112 119
113 // Callers are expected to call IsEncryptedMessage() prior to this method.
114 DCHECK(encryption_header != message.data.end()); 120 DCHECK(encryption_header != message.data.end());
115 DCHECK(crypto_key_header != message.data.end()); 121 DCHECK(crypto_key_header != message.data.end());
116 122
117 std::vector<EncryptionHeaderValues> encryption_header_values; 123 std::vector<EncryptionHeaderValues> encryption_header_values;
118 if (!ParseEncryptionHeader(encryption_header->second, 124 if (!ParseEncryptionHeader(encryption_header->second,
119 &encryption_header_values)) { 125 &encryption_header_values)) {
120 DLOG(ERROR) << "Unable to parse the value of the Encryption header"; 126 DLOG(ERROR) << "Unable to parse the value of the Encryption header";
121 failure_callback.Run(DECRYPTION_FAILURE_INVALID_ENCRYPTION_HEADER); 127 callback.Run(DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
128 IncomingMessage());
122 return; 129 return;
123 } 130 }
124 131
125 if (encryption_header_values.size() != 1u || 132 if (encryption_header_values.size() != 1u ||
126 encryption_header_values[0].salt.size() != 133 encryption_header_values[0].salt.size() !=
127 GCMMessageCryptographer::kSaltSize) { 134 GCMMessageCryptographer::kSaltSize) {
128 DLOG(ERROR) << "Invalid values supplied in the Encryption header"; 135 DLOG(ERROR) << "Invalid values supplied in the Encryption header";
129 failure_callback.Run(DECRYPTION_FAILURE_INVALID_ENCRYPTION_HEADER); 136 callback.Run(DECRYPTION_RESULT_INVALID_ENCRYPTION_HEADER,
137 IncomingMessage());
130 return; 138 return;
131 } 139 }
132 140
133 std::vector<CryptoKeyHeaderValues> crypto_key_header_values; 141 std::vector<CryptoKeyHeaderValues> crypto_key_header_values;
134 if (!ParseCryptoKeyHeader(crypto_key_header->second, 142 if (!ParseCryptoKeyHeader(crypto_key_header->second,
135 &crypto_key_header_values)) { 143 &crypto_key_header_values)) {
136 DLOG(ERROR) << "Unable to parse the value of the Crypto-Key header"; 144 DLOG(ERROR) << "Unable to parse the value of the Crypto-Key header";
137 failure_callback.Run(DECRYPTION_FAILURE_INVALID_CRYPTO_KEY_HEADER); 145 callback.Run(DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
146 IncomingMessage());
138 return; 147 return;
139 } 148 }
140 149
141 if (crypto_key_header_values.size() != 1u || 150 if (crypto_key_header_values.size() != 1u ||
142 !crypto_key_header_values[0].dh.size()) { 151 !crypto_key_header_values[0].dh.size()) {
143 DLOG(ERROR) << "Invalid values supplied in the Crypto-Key header"; 152 DLOG(ERROR) << "Invalid values supplied in the Crypto-Key header";
144 failure_callback.Run(DECRYPTION_FAILURE_INVALID_CRYPTO_KEY_HEADER); 153 callback.Run(DECRYPTION_RESULT_INVALID_CRYPTO_KEY_HEADER,
154 IncomingMessage());
145 return; 155 return;
146 } 156 }
147 157
148 key_store_->GetKeys( 158 key_store_->GetKeys(
149 app_id, base::Bind(&GCMEncryptionProvider::DecryptMessageWithKey, 159 app_id, base::Bind(&GCMEncryptionProvider::DecryptMessageWithKey,
150 weak_ptr_factory_.GetWeakPtr(), message, 160 weak_ptr_factory_.GetWeakPtr(), message,
151 success_callback, failure_callback, 161 callback, encryption_header_values[0].salt,
152 encryption_header_values[0].salt,
153 crypto_key_header_values[0].dh, 162 crypto_key_header_values[0].dh,
154 encryption_header_values[0].rs)); 163 encryption_header_values[0].rs));
155 } 164 }
156 165
157 void GCMEncryptionProvider::DidGetEncryptionInfo( 166 void GCMEncryptionProvider::DidGetEncryptionInfo(
158 const std::string& app_id, 167 const std::string& app_id,
159 const EncryptionInfoCallback& callback, 168 const EncryptionInfoCallback& callback,
160 const KeyPair& pair, 169 const KeyPair& pair,
161 const std::string& auth_secret) { 170 const std::string& auth_secret) {
162 if (!pair.IsInitialized()) { 171 if (!pair.IsInitialized()) {
(...skipping 16 matching lines...) Expand all
179 std::string() /* auth_secret */); 188 std::string() /* auth_secret */);
180 return; 189 return;
181 } 190 }
182 191
183 DCHECK_EQ(KeyPair::ECDH_P256, pair.type()); 192 DCHECK_EQ(KeyPair::ECDH_P256, pair.type());
184 callback.Run(pair.public_key(), auth_secret); 193 callback.Run(pair.public_key(), auth_secret);
185 } 194 }
186 195
187 void GCMEncryptionProvider::DecryptMessageWithKey( 196 void GCMEncryptionProvider::DecryptMessageWithKey(
188 const IncomingMessage& message, 197 const IncomingMessage& message,
189 const MessageDecryptedCallback& success_callback, 198 const MessageCallback& callback,
190 const DecryptionFailedCallback& failure_callback,
191 const std::string& salt, 199 const std::string& salt,
192 const std::string& dh, 200 const std::string& dh,
193 uint64_t rs, 201 uint64_t rs,
194 const KeyPair& pair, 202 const KeyPair& pair,
195 const std::string& auth_secret) { 203 const std::string& auth_secret) {
196 if (!pair.IsInitialized()) { 204 if (!pair.IsInitialized()) {
197 DLOG(ERROR) << "Unable to retrieve the keys for the incoming message."; 205 DLOG(ERROR) << "Unable to retrieve the keys for the incoming message.";
198 failure_callback.Run(DECRYPTION_FAILURE_NO_KEYS); 206 callback.Run(DECRYPTION_RESULT_NO_KEYS, IncomingMessage());
199 return; 207 return;
200 } 208 }
201 209
202 DCHECK_EQ(KeyPair::ECDH_P256, pair.type()); 210 DCHECK_EQ(KeyPair::ECDH_P256, pair.type());
203 211
204 std::string shared_secret; 212 std::string shared_secret;
205 if (!ComputeSharedP256Secret(pair.private_key(), pair.public_key_x509(), dh, 213 if (!ComputeSharedP256Secret(pair.private_key(), pair.public_key_x509(), dh,
206 &shared_secret)) { 214 &shared_secret)) {
207 DLOG(ERROR) << "Unable to calculate the shared secret."; 215 DLOG(ERROR) << "Unable to calculate the shared secret.";
208 failure_callback.Run(DECRYPTION_FAILURE_INVALID_PUBLIC_KEY); 216 callback.Run(DECRYPTION_RESULT_INVALID_SHARED_SECRET, IncomingMessage());
209 return; 217 return;
210 } 218 }
211 219
212 std::string plaintext; 220 std::string plaintext;
213 221
214 GCMMessageCryptographer cryptographer(GCMMessageCryptographer::Label::P256, 222 GCMMessageCryptographer cryptographer(GCMMessageCryptographer::Label::P256,
215 pair.public_key(), dh, auth_secret); 223 pair.public_key(), dh, auth_secret);
216 if (!cryptographer.Decrypt(message.raw_data, shared_secret, salt, rs, 224 if (!cryptographer.Decrypt(message.raw_data, shared_secret, salt, rs,
217 &plaintext)) { 225 &plaintext)) {
218 DLOG(ERROR) << "Unable to decrypt the incoming data."; 226 DLOG(ERROR) << "Unable to decrypt the incoming data.";
219 failure_callback.Run(DECRYPTION_FAILURE_INVALID_PAYLOAD); 227 callback.Run(DECRYPTION_RESULT_INVALID_PAYLOAD, IncomingMessage());
220 return; 228 return;
221 } 229 }
222 230
223 IncomingMessage decrypted_message; 231 IncomingMessage decrypted_message;
224 decrypted_message.collapse_key = message.collapse_key; 232 decrypted_message.collapse_key = message.collapse_key;
225 decrypted_message.sender_id = message.sender_id; 233 decrypted_message.sender_id = message.sender_id;
226 decrypted_message.raw_data.swap(plaintext); 234 decrypted_message.raw_data.swap(plaintext);
227 decrypted_message.decrypted = true; 235 decrypted_message.decrypted = true;
228 236
229 // There must be no data associated with the decrypted message at this point, 237 // There must be no data associated with the decrypted message at this point,
230 // to make sure that we don't end up in an infinite decryption loop. 238 // to make sure that we don't end up in an infinite decryption loop.
231 DCHECK_EQ(0u, decrypted_message.data.size()); 239 DCHECK_EQ(0u, decrypted_message.data.size());
232 240
233 success_callback.Run(decrypted_message); 241 callback.Run(DECRYPTION_RESULT_DECRYPTED, decrypted_message);
234 } 242 }
235 243
236 } // namespace gcm 244 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698