| Index: extensions/browser/api/cast_channel/cast_auth_util.cc
|
| diff --git a/extensions/browser/api/cast_channel/cast_auth_util.cc b/extensions/browser/api/cast_channel/cast_auth_util.cc
|
| index 68cb9f321fccacae26cb9724966405155d1c8735..1e71685586460efd7a6b6575ee653efe408aa7c4 100644
|
| --- a/extensions/browser/api/cast_channel/cast_auth_util.cc
|
| +++ b/extensions/browser/api/cast_channel/cast_auth_util.cc
|
| @@ -4,11 +4,14 @@
|
|
|
| #include "extensions/browser/api/cast_channel/cast_auth_util.h"
|
|
|
| +#include <vector>
|
| +
|
| #include "base/logging.h"
|
| #include "base/strings/string_number_conversions.h"
|
| #include "base/strings/stringprintf.h"
|
| #include "extensions/browser/api/cast_channel/cast_message_util.h"
|
| #include "extensions/common/api/cast_channel/cast_channel.pb.h"
|
| +#include "extensions/common/cast/cast_cert_validator.h"
|
|
|
| namespace extensions {
|
| namespace core_api {
|
| @@ -17,6 +20,8 @@ namespace {
|
|
|
| const char* const kParseErrorPrefix = "Failed to parse auth message: ";
|
|
|
| +namespace cast_crypto = ::extensions::core_api::cast_crypto;
|
| +
|
| // Extracts an embedded DeviceAuthMessage payload from an auth challenge reply
|
| // message.
|
| AuthResult ParseAuthMessage(const CastMessage& challenge_reply,
|
| @@ -52,6 +57,27 @@ AuthResult ParseAuthMessage(const CastMessage& challenge_reply,
|
| return AuthResult();
|
| }
|
|
|
| +AuthResult TranslateVerificationError(cast_crypto::VerificationResult error) {
|
| + static AuthResult::ErrorType error_type_map[] = {
|
| + AuthResult::ERROR_NONE,
|
| + AuthResult::ERROR_CERT_PARSING_FAILED,
|
| + AuthResult::ERROR_CERT_NOT_SIGNED_BY_TRUSTED_CA,
|
| + AuthResult::ERROR_CANNOT_EXTRACT_PUBLIC_KEY,
|
| + AuthResult::ERROR_SIGNED_BLOBS_MISMATCH,
|
| + AuthResult::ERROR_UNEXPECTED_AUTH_LIBRARY_RESULT};
|
| +
|
| + AuthResult result;
|
| + result.error_message = error.error_message;
|
| +
|
| + int idx = static_cast<int>(error.error_type);
|
| + result.error_type =
|
| + (idx < 0 || idx > cast_crypto::VerificationResult::ERROR_TYPE_MAX)
|
| + ? AuthResult::ERROR_UNEXPECTED_AUTH_LIBRARY_RESULT
|
| + : error_type_map[idx];
|
| +
|
| + return result;
|
| +}
|
| +
|
| } // namespace
|
|
|
| AuthResult::AuthResult() : error_type(ERROR_NONE), nss_error_code(0) {
|
| @@ -104,6 +130,33 @@ AuthResult AuthenticateChallengeReply(const CastMessage& challenge_reply,
|
| return AuthResult();
|
| }
|
|
|
| +// This function does the following
|
| +// * Verifies that the trusted CA |response.intermediate_certificate| is
|
| +// whitelisted for use.
|
| +// * Verifies that |response.client_auth_certificate| is signed
|
| +// by the trusted CA certificate.
|
| +// * Verifies that |response.signature| matches the signature
|
| +// of |peer_cert| by |response.client_auth_certificate|'s public
|
| +// key.
|
| +AuthResult VerifyCredentials(const AuthResponse& response,
|
| + const std::string& peer_cert) {
|
| + // Verify the certificate
|
| + cast_crypto::CertVerificationContext* verification_context = NULL;
|
| + cast_crypto::VerificationResult ret = cast_crypto::VerifyCert(
|
| + response.client_auth_certificate(),
|
| + std::vector<std::string>(response.intermediate_certificate().begin(),
|
| + response.intermediate_certificate().end()),
|
| + &verification_context);
|
| +
|
| + if (ret.Success()) {
|
| + ret = verification_context->VerifySignatureOverData(response.signature(),
|
| + peer_cert);
|
| + }
|
| +
|
| + delete verification_context;
|
| + return TranslateVerificationError(ret);
|
| +}
|
| +
|
| } // namespace cast_channel
|
| } // namespace core_api
|
| } // namespace extensions
|
|
|