OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "chrome/browser/extensions/api/cast_channel/cast_auth_util.h" | 5 #include "extensions/browser/api/cast_channel/cast_auth_util.h" |
6 | 6 |
7 #include <cert.h> | 7 #include <cert.h> |
8 #include <cryptohi.h> | 8 #include <cryptohi.h> |
9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
10 #include <seccomon.h> | 10 #include <seccomon.h> |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "chrome/browser/extensions/api/cast_channel/cast_channel.pb.h" | |
15 #include "chrome/browser/extensions/api/cast_channel/cast_message_util.h" | |
16 #include "crypto/nss_util.h" | 14 #include "crypto/nss_util.h" |
17 #include "crypto/scoped_nss_types.h" | 15 #include "crypto/scoped_nss_types.h" |
| 16 #include "extensions/browser/api/cast_channel/cast_channel.pb.h" |
| 17 #include "extensions/browser/api/cast_channel/cast_message_util.h" |
18 #include "net/base/hash_value.h" | 18 #include "net/base/hash_value.h" |
19 #include "net/cert/x509_certificate.h" | 19 #include "net/cert/x509_certificate.h" |
20 | 20 |
| 21 namespace extensions { |
| 22 namespace core_api { |
| 23 namespace cast_channel { |
| 24 |
21 namespace { | 25 namespace { |
22 | 26 |
23 // Fingerprints and public keys of the allowed / trusted ICAs. | 27 // Fingerprints and public keys of the allowed / trusted ICAs. |
24 static const net::SHA1HashValue kFingerprintICA1 = { { | 28 static const net::SHA1HashValue kFingerprintICA1 = { { |
25 0x57,0x16,0xE2,0xAD,0x73,0x2E,0xBE,0xDA,0xEB,0x18, | 29 0x57,0x16,0xE2,0xAD,0x73,0x2E,0xBE,0xDA,0xEB,0x18, |
26 0xE8,0x47,0x15,0xA8,0xDE,0x90,0x3B,0x5E,0x2A,0xF4 | 30 0xE8,0x47,0x15,0xA8,0xDE,0x90,0x3B,0x5E,0x2A,0xF4 |
27 } }; | 31 } }; |
28 static const unsigned char kPublicKeyICA1[] = { | 32 static const unsigned char kPublicKeyICA1[] = { |
29 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xBC,0x22,0x80, | 33 0x30,0x82,0x01,0x0A,0x02,0x82,0x01,0x01,0x00,0xBC,0x22,0x80, |
30 0xBD,0x80,0xF6,0x3A,0x21,0x00,0x3B,0xAE,0x76,0x5E,0x35,0x7F, | 34 0xBD,0x80,0xF6,0x3A,0x21,0x00,0x3B,0xAE,0x76,0x5E,0x35,0x7F, |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 // Returns -1, if no such ICA is found. | 180 // Returns -1, if no such ICA is found. |
177 static int GetICAWithFingerprint(const net::SHA1HashValue& fingerprint) { | 181 static int GetICAWithFingerprint(const net::SHA1HashValue& fingerprint) { |
178 for (size_t i = 0; i < arraysize(kAllowedICAs); ++i) { | 182 for (size_t i = 0; i < arraysize(kAllowedICAs); ++i) { |
179 if (kAllowedICAs[i].fingerprint->Equals(fingerprint)) | 183 if (kAllowedICAs[i].fingerprint->Equals(fingerprint)) |
180 return static_cast<int>(i); | 184 return static_cast<int>(i); |
181 } | 185 } |
182 return -1; | 186 return -1; |
183 } | 187 } |
184 | 188 |
185 // Parses out DeviceAuthMessage from CastMessage | 189 // Parses out DeviceAuthMessage from CastMessage |
186 static bool ParseAuthMessage( | 190 static bool ParseAuthMessage(const CastMessage& challenge_reply, |
187 const extensions::api::cast_channel::CastMessage& challenge_reply, | 191 DeviceAuthMessage* auth_message) { |
188 extensions::api::cast_channel::DeviceAuthMessage* auth_message) { | 192 if (challenge_reply.payload_type() != CastMessage_PayloadType_BINARY) { |
189 if (challenge_reply.payload_type() != | |
190 extensions::api::cast_channel::CastMessage_PayloadType_BINARY) { | |
191 VLOG(1) << "Wrong payload type in challenge reply"; | 193 VLOG(1) << "Wrong payload type in challenge reply"; |
192 return false; | 194 return false; |
193 } | 195 } |
194 if (!challenge_reply.has_payload_binary()) { | 196 if (!challenge_reply.has_payload_binary()) { |
195 VLOG(1) << "Payload type is binary but payload_binary field not set"; | 197 VLOG(1) << "Payload type is binary but payload_binary field not set"; |
196 return false; | 198 return false; |
197 } | 199 } |
198 if (!auth_message->ParseFromString(challenge_reply.payload_binary())) { | 200 if (!auth_message->ParseFromString(challenge_reply.payload_binary())) { |
199 VLOG(1) << "Cannot parse binary payload into DeviceAuthMessage"; | 201 VLOG(1) << "Cannot parse binary payload into DeviceAuthMessage"; |
200 return false; | 202 return false; |
201 } | 203 } |
202 VLOG(1) << "Auth message: " << AuthMessageToString(*auth_message); | 204 VLOG(1) << "Auth message: " << AuthMessageToString(*auth_message); |
203 if (auth_message->has_error()) { | 205 if (auth_message->has_error()) { |
204 VLOG(1) << "Auth message error: " << auth_message->error().error_type(); | 206 VLOG(1) << "Auth message error: " << auth_message->error().error_type(); |
205 return false; | 207 return false; |
206 } | 208 } |
207 if (!auth_message->has_response()) { | 209 if (!auth_message->has_response()) { |
208 VLOG(1) << "Auth message has no response field"; | 210 VLOG(1) << "Auth message has no response field"; |
209 return false; | 211 return false; |
210 } | 212 } |
211 return true; | 213 return true; |
212 } | 214 } |
213 | 215 |
214 // Authenticates the given credentials: | 216 // Authenticates the given credentials: |
215 // 1. |signature| verification of |data| using |certificate|. | 217 // 1. |signature| verification of |data| using |certificate|. |
216 // 2. |certificate| is signed by a trusted CA. | 218 // 2. |certificate| is signed by a trusted CA. |
217 bool VerifyCredentials( | 219 bool VerifyCredentials(const AuthResponse& response, |
218 const extensions::api::cast_channel::AuthResponse& response, | 220 const std::string& data) { |
219 const std::string& data) { | |
220 const std::string& certificate = response.client_auth_certificate(); | 221 const std::string& certificate = response.client_auth_certificate(); |
221 const std::string& signature = response.signature(); | 222 const std::string& signature = response.signature(); |
222 | 223 |
223 const SECItem* trusted_ca_key_der; | 224 const SECItem* trusted_ca_key_der; |
224 | 225 |
225 // If the list of intermediates is empty then use kPublicKeyICA1 as | 226 // If the list of intermediates is empty then use kPublicKeyICA1 as |
226 // the trusted CA (legacy case). | 227 // the trusted CA (legacy case). |
227 // Otherwise, use the first intermediate in the list as long as it | 228 // Otherwise, use the first intermediate in the list as long as it |
228 // is in the allowed list of intermediates. | 229 // is in the allowed list of intermediates. |
229 int num_intermediates = response.intermediate_certificate_size(); | 230 int num_intermediates = response.intermediate_certificate_size(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 if (verified != SECSuccess) { | 296 if (verified != SECSuccess) { |
296 VLOG(1) << "Signed blobs did not match."; | 297 VLOG(1) << "Signed blobs did not match."; |
297 return false; | 298 return false; |
298 } | 299 } |
299 VLOG(1) << "Signature verification succeeded"; | 300 VLOG(1) << "Signature verification succeeded"; |
300 return true; | 301 return true; |
301 } | 302 } |
302 | 303 |
303 } // namespace | 304 } // namespace |
304 | 305 |
305 namespace extensions { | |
306 namespace api { | |
307 namespace cast_channel { | |
308 | |
309 bool AuthenticateChallengeReply(const CastMessage& challenge_reply, | 306 bool AuthenticateChallengeReply(const CastMessage& challenge_reply, |
310 const std::string& peer_cert) { | 307 const std::string& peer_cert) { |
311 if (peer_cert.empty()) | 308 if (peer_cert.empty()) |
312 return false; | 309 return false; |
313 | 310 |
314 VLOG(1) << "Challenge reply: " << CastMessageToString(challenge_reply); | 311 VLOG(1) << "Challenge reply: " << CastMessageToString(challenge_reply); |
315 DeviceAuthMessage auth_message; | 312 DeviceAuthMessage auth_message; |
316 if (!ParseAuthMessage(challenge_reply, &auth_message)) | 313 if (!ParseAuthMessage(challenge_reply, &auth_message)) |
317 return false; | 314 return false; |
318 | 315 |
319 const AuthResponse& response = auth_message.response(); | 316 const AuthResponse& response = auth_message.response(); |
320 return VerifyCredentials(response, peer_cert); | 317 return VerifyCredentials(response, peer_cert); |
321 } | 318 } |
322 | 319 |
323 } // namespace cast_channel | 320 } // namespace cast_channel |
324 } // namespace api | 321 } // namespace core_api |
325 } // namespace extensions | 322 } // namespace extensions |
OLD | NEW |