Files
media_cas_packager_sdk_source/common/remote_attestation_verifier.cc
2020-01-27 16:05:15 -08:00

263 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Copyright 2013 Google LLC.
//
// This software is licensed under the terms defined in the Widevine Master
// License Agreement. For a copy of this agreement, please contact
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
#include "common/remote_attestation_verifier.h"
#include <stddef.h>
#include <memory>
#include "glog/logging.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "common/client_id_util.h"
#include "common/drm_service_certificate.h"
#include "common/error_space.h"
#include "common/rsa_key.h"
#include "protos/public/client_identification.pb.h"
#include "protos/public/errors.pb.h"
namespace widevine {
const char kTestRootCaDerCert[] =
"30820403308202eba003020102020900a24f94af7ae6831f300d06092a86"
"4886f70d0101050500308197310b30090603550406130255533113301106"
"035504080c0a57617368696e67746f6e3111300f06035504070c084b6972"
"6b6c616e6431133011060355040a0c0a476f6f676c6520496e633111300f"
"060355040b0c085769646576696e653115301306035504030c0c54657374"
"20526f6f742043413121301f06092a864886f70d010901161274696e736b"
"697040676f6f676c652e636f6d301e170d3133303831363030353731305a"
"170d3333303831353030353731305a308197310b30090603550406130255"
"533113301106035504080c0a57617368696e67746f6e3111300f06035504"
"070c084b69726b6c616e6431133011060355040a0c0a476f6f676c652049"
"6e633111300f060355040b0c085769646576696e65311530130603550403"
"0c0c5465737420526f6f742043413121301f06092a864886f70d01090116"
"1274696e736b697040676f6f676c652e636f6d30820122300d06092a8648"
"86f70d01010105000382010f003082010a0282010100c6eee629d99f7736"
"2db5545ed1d6dfb3616c742c617d5fd48f2fbfcb3f2ec40a080bd04d551c"
"e519471a8bb4ec5c2c75bf8a2d2caf3f85d90e9e39391dfbdaae68051319"
"0da71b1b2ae4829a15c44bc1b19b17134844b94c6f06d9216333236574f3"
"f11b0d10c3c621410e42630c57ce9e901057eda5c3c2203ee2ad805a0d93"
"52fa91da45a6f4875b4524c193c42fd9048a10204e5b2c8203402ba760e7"
"e1b4126c3e2ab4258f2bf28cd3170de8c738a6a1f4cfcc0649fa95f1414f"
"d9d09dd4f511bc0a9bf3a5844a334d9e0a4b9525d2789be6abafe2d0cc20"
"79dcf030ffa9be8ae3fe2cab4ebdfa494d48aa8c63264d31e2208a9c28f7"
"3e0103ce164683bf0203010001a350304e301d0603551d0e041604144d30"
"ff181ac4f10da99e6a12c01e02accadf840a301f0603551d230418301680"
"144d30ff181ac4f10da99e6a12c01e02accadf840a300c0603551d130405"
"30030101ff300d06092a864886f70d01010505000382010100779e9b98d3"
"ec066f29862903a00e9c98259d987c04b9e6a2e6c3381ee59ec1dd0d7dee"
"79da612e4dfaa3465c8916993ed7adebb27340de20ca101067f8342b2124"
"ec0d5db531277b4653c3bc72b2a8daeae120e5348e1a338f6e68e7129436"
"026e78024f04d766b132252ec152402dcec28174346aa0ba997d7f1af140"
"ff025bec841f8039ba10d7cc098cf24554f8cbb2aa31875205c67df2f053"
"0d8784faf63c4f945e62da374cad6155e6ae44f597bcff4566ea2aac4258"
"e4ae81569c0eddd1df6929532b4538bd204b2ff5847cb46ac7383c96fe82"
"d22de9a13c5092c92c297021c51a2a0a5250cf26c271ff262f25a7738ae4"
"c270d87191c13aefdd177b";
const char kProdRootCaDerCert[] =
"30820408308202f0a003020102020101300d06092a864886f70d01010505"
"00307d311830160603550403130f5072697661637920434120526f6f7431"
"123010060355040b13094368726f6d65204f5331133011060355040a130a"
"476f6f676c6520496e63311630140603550407130d4d6f756e7461696e20"
"56696577311330110603550408130a43616c69666f726e6961310b300906"
"0355040613025553301e170d3133303231383130313334325a170d333330"
"3231333130313334325a307d311830160603550403130f50726976616379"
"20434120526f6f7431123010060355040b13094368726f6d65204f533113"
"3011060355040a130a476f6f676c6520496e63311630140603550407130d"
"4d6f756e7461696e2056696577311330110603550408130a43616c69666f"
"726e6961310b300906035504061302555330820122300d06092a864886f7"
"0d01010105000382010f003082010a0282010100e10ea6819d3d066b421d"
"d7612de3eef9599f5d9a2a24bfd09caab543511cf22f615e29f989425a65"
"7396bf33603747719cfb0b4240cd682c7c558fec0176b4793be440752246"
"83648f5b12d02a838a2a8e55a4b645ed0a4a52b19252a23d34bf64a17ac7"
"11fe93a889086d943211b17d670f96442c9f367d38026000da79664e600e"
"e9259348f4fd74108e973d561e624e9f5eda77a085a6eb15fadb2cc7787c"
"7f30ef3b196f2a416a76fa9eb30d65753f5039d97bea70e82431d2962396"
"a34864f33b74d60707fea794c03c82e547abc2407fa7bad67bd09cdab49b"
"26e68754994d12a3845dbeceffe18de0d51fc6fa78676d89ea1e0fcff931"
"59bfb809519b0203010001a3819230818f30290603551d0e042204204b1d"
"148aa5380938812ed6a763f5dc2c318610d5fa9604d609cb2e0d8cec3289"
"302b0603551d230424302280204b1d148aa5380938812ed6a763f5dc2c31"
"8610d5fa9604d609cb2e0d8cec3289300e0603551d0f0101ff0404030201"
"06300f0603551d130101ff040530030101ff30140603551d200101ff040a"
"300830060604551d2000300d06092a864886f70d01010505000382010100"
"c40d84bc8d609b1b68b3caa7e841021838d7e392557d40debab3e0685e72"
"80541092dc913b0aa6150228d8fe5ab08cceefbac56952fa00ba614294d1"
"ba4fa170c86b27f9bf58666c46940f740c4be2795501b25e40b9702af07c"
"884926bd8beed036c503e5e42a223ff36271404ca4360a93dec92a02fd8d"
"ae8f756fc68aaa647e2159f0a7a95d1446e92362bd512f59daec02c5d152"
"c301b9807db998ba70c616364762a0a497aaa92eb7d92f3635169d3f74c6"
"40c738941759a8ab43677b80329d015bdcf8922b779a80f85f1e4a677659"
"c60de80152e8c526a7de46cac143a75af58f0806de81e15c97f616e1bffa"
"1c1c6b0d2438543bdfb2a21bd9bc7ae4";
const char kServiceIdFieldName[] = "OU";
const char kDeviceModeFieldName[] = "O";
const char kExpectedDeviceMode[] = "Chrome Device Content Protection";
RemoteAttestationVerifier& RemoteAttestationVerifier::get() {
static RemoteAttestationVerifier instance;
return instance;
}
void RemoteAttestationVerifier::EnableTestDrmCertificates(bool enable) {
absl::WriterMutexLock lock(&ca_mutex_);
enable_test_certificates_ = enable;
ca_.reset();
}
Status RemoteAttestationVerifier::VerifyRemoteAttestation(
const std::string& message, const RemoteAttestation& remote_attestation,
std::string* remote_attestation_cert_sn) {
DCHECK(remote_attestation_cert_sn);
// Sanity check RemoteAttestation.
if (!remote_attestation.has_certificate()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-certificate-missing"));
}
if (!remote_attestation.has_salt()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-salt-missing"));
}
if (!remote_attestation.has_signature()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-signature-missing"));
}
// Decrypt ClientIdentification containing remote attestation certificate.
// A service cert would be looked up first, then that cert will be used
// to decrypt the ClientIdentification.
ClientIdentification client_id;
Status status = DrmServiceCertificate::DecryptClientIdentification(
remote_attestation.certificate(), &client_id);
if (!status.ok()) return status;
if (client_id.type() !=
ClientIdentification::REMOTE_ATTESTATION_CERTIFICATE) {
return (Status(error_space, INVALID_MESSAGE,
std::string("remote-attestation-invalid-client-id-type (") +
absl::StrCat(client_id.type()) + ")"));
}
return VerifyRemoteAttestation(message, remote_attestation, client_id,
remote_attestation_cert_sn);
}
Status RemoteAttestationVerifier::VerifyRemoteAttestation(
const std::string& message, const RemoteAttestation& remote_attestation,
const std::string& privacy_key) {
// Sanity check RemoteAttestation.
if (!remote_attestation.has_certificate()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-certificate-missing"));
}
if (!remote_attestation.has_salt()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-salt-missing"));
}
if (!remote_attestation.has_signature()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-signature-missing"));
}
// Decrypt ClientIdentification containing remote attestation certificate,
// directly using an explicitly provided key |privacy_key|.
ClientIdentification client_id;
Status status = DecryptEncryptedClientIdentification(
remote_attestation.certificate(), privacy_key, &client_id);
if (!status.ok()) return status;
if (client_id.type() !=
ClientIdentification::REMOTE_ATTESTATION_CERTIFICATE) {
return (Status(error_space, INVALID_MESSAGE,
std::string("remote-attestation-invalid-client-id-type (") +
absl::StrCat(client_id.type()) + ")"));
}
std::string remote_attestation_cert_sn;
return VerifyRemoteAttestation(message, remote_attestation, client_id,
&remote_attestation_cert_sn);
}
Status RemoteAttestationVerifier::VerifyRemoteAttestation(
const std::string& message, const RemoteAttestation& remote_attestation,
const ClientIdentification& client_id,
std::string* remote_attestation_cert_sn) {
if (!client_id.has_token()) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-token-missing"));
}
// Load and verify the certificate chain.
std::unique_ptr<X509CertChain> cert_chain(new X509CertChain);
Status status = cert_chain->LoadPem(client_id.token());
if (!status.ok()) return status;
if (cert_chain->GetNumCerts() < 1) {
return (Status(error_space, INVALID_MESSAGE,
"remote-attestation-empty-certificate-chain"));
}
std::string device_mode_string =
cert_chain->GetCert(0)->GetSubjectNameField(kDeviceModeFieldName);
if (device_mode_string != kExpectedDeviceMode) {
return (Status(error_space, REMOTE_ATTESTATION_FAILED,
std::string("remote-attestation-device-not-verified (") +
device_mode_string + " / " + kDeviceModeFieldName +
")"));
}
ca_mutex_.ReaderLock();
if (ca_ == NULL) {
ca_mutex_.ReaderUnlock();
status = LoadCa();
if (!status.ok()) return status;
ca_mutex_.ReaderLock();
}
status = ca_->VerifyCertChain(*cert_chain);
ca_mutex_.ReaderUnlock();
if (!status.ok()) {
return (Status(
error_space, REMOTE_ATTESTATION_FAILED,
std::string("remote-attestation-cert-chain-validation-failed: ") +
status.error_message()));
}
// Verify the remote attestation signature.
std::unique_ptr<RsaPublicKey> leaf_key;
std::string message_with_salt = message + remote_attestation.salt();
for (size_t idx = 0; idx < cert_chain->GetNumCerts(); ++idx) {
if (!cert_chain->GetCert(idx)->IsCaCertificate()) {
leaf_key = cert_chain->GetCert(idx)->GetRsaPublicKey();
break;
}
}
if (!leaf_key) {
return Status(error_space, REMOTE_ATTESTATION_FAILED,
"remote-attestation-cert-chain-no-leaf");
}
if (!leaf_key->VerifySignatureSha256Pkcs7(message_with_salt,
remote_attestation.signature())) {
return (Status(error_space, REMOTE_ATTESTATION_FAILED,
"remote-attestation-signature-verification-failed: "));
}
*remote_attestation_cert_sn = cert_chain->GetCert(0)->GetSerialNumber();
return OkStatus();
}
Status RemoteAttestationVerifier::LoadCa() {
absl::WriterMutexLock lock(&ca_mutex_);
std::unique_ptr<X509Cert> ca_cert(new X509Cert);
Status status = ca_cert->LoadDer(absl::HexStringToBytes(
enable_test_certificates_ ? kTestRootCaDerCert : kProdRootCaDerCert));
if (!status.ok()) {
return status;
}
ca_.reset(new X509CA(ca_cert.release()));
return OkStatus();
}
} // namespace widevine