| 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 |