Minimal implementation of Widevine MediaCAS ECMG.
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=226515998
This commit is contained in:
@@ -113,99 +113,99 @@ void RemoteAttestationVerifier::EnableTestDrmCertificates(bool enable) {
|
||||
ca_.reset();
|
||||
}
|
||||
|
||||
util::Status RemoteAttestationVerifier::VerifyRemoteAttestation(
|
||||
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 (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-certificate-missing"));
|
||||
return (Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-certificate-missing"));
|
||||
}
|
||||
if (!remote_attestation.has_salt()) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-salt-missing"));
|
||||
return (Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-salt-missing"));
|
||||
}
|
||||
if (!remote_attestation.has_signature()) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-signature-missing"));
|
||||
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;
|
||||
util::Status status = DrmServiceCertificate::DecryptClientIdentification(
|
||||
Status status = DrmServiceCertificate::DecryptClientIdentification(
|
||||
remote_attestation.certificate(), &client_id);
|
||||
if (!status.ok()) return status;
|
||||
|
||||
if (client_id.type() !=
|
||||
ClientIdentification::REMOTE_ATTESTATION_CERTIFICATE) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
std::string("remote-attestation-invalid-client-id-type (") +
|
||||
absl::StrCat(client_id.type()) + ")"));
|
||||
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);
|
||||
}
|
||||
|
||||
util::Status RemoteAttestationVerifier::VerifyRemoteAttestation(
|
||||
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 (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-certificate-missing"));
|
||||
return (Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-certificate-missing"));
|
||||
}
|
||||
if (!remote_attestation.has_salt()) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-salt-missing"));
|
||||
return (Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-salt-missing"));
|
||||
}
|
||||
if (!remote_attestation.has_signature()) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-signature-missing"));
|
||||
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;
|
||||
util::Status status = DecryptEncryptedClientIdentification(
|
||||
Status status = DecryptEncryptedClientIdentification(
|
||||
remote_attestation.certificate(), privacy_key, &client_id);
|
||||
if (!status.ok()) return status;
|
||||
|
||||
if (client_id.type() !=
|
||||
ClientIdentification::REMOTE_ATTESTATION_CERTIFICATE) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
std::string("remote-attestation-invalid-client-id-type (") +
|
||||
absl::StrCat(client_id.type()) + ")"));
|
||||
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);
|
||||
}
|
||||
|
||||
util::Status RemoteAttestationVerifier::VerifyRemoteAttestation(
|
||||
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 (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-token-missing"));
|
||||
return (Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-token-missing"));
|
||||
}
|
||||
// Load and verify the certificate chain.
|
||||
std::unique_ptr<X509CertChain> cert_chain(new X509CertChain);
|
||||
util::Status status = cert_chain->LoadPem(client_id.token());
|
||||
Status status = cert_chain->LoadPem(client_id.token());
|
||||
if (!status.ok()) return status;
|
||||
|
||||
if (cert_chain->GetNumCerts() < 1) {
|
||||
return (util::Status(error_space, INVALID_MESSAGE,
|
||||
"remote-attestation-empty-certificate-chain"));
|
||||
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 (util::Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
std::string("remote-attestation-device-not-verified (") +
|
||||
device_mode_string + " / " + kDeviceModeFieldName +
|
||||
")"));
|
||||
return (Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
std::string("remote-attestation-device-not-verified (") +
|
||||
device_mode_string + " / " + kDeviceModeFieldName +
|
||||
")"));
|
||||
}
|
||||
ca_mutex_.ReaderLock();
|
||||
if (ca_ == NULL) {
|
||||
@@ -217,10 +217,9 @@ util::Status RemoteAttestationVerifier::VerifyRemoteAttestation(
|
||||
status = ca_->VerifyCertChain(*cert_chain);
|
||||
ca_mutex_.ReaderUnlock();
|
||||
if (!status.ok()) {
|
||||
return (util::Status(
|
||||
error_space, REMOTE_ATTESTATION_FAILED,
|
||||
std::string("remote-attestation-cert-chain-validation-failed: ") +
|
||||
status.error_message()));
|
||||
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;
|
||||
@@ -232,30 +231,30 @@ util::Status RemoteAttestationVerifier::VerifyRemoteAttestation(
|
||||
}
|
||||
}
|
||||
if (!leaf_key) {
|
||||
return util::Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
"remote-attestation-cert-chain-no-leaf");
|
||||
return Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
"remote-attestation-cert-chain-no-leaf");
|
||||
}
|
||||
|
||||
if (!leaf_key->VerifySignatureSha256Pkcs7(message_with_salt,
|
||||
remote_attestation.signature())) {
|
||||
return (util::Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
"remote-attestation-signature-verification-failed: "));
|
||||
return (Status(error_space, REMOTE_ATTESTATION_FAILED,
|
||||
"remote-attestation-signature-verification-failed: "));
|
||||
}
|
||||
|
||||
*remote_attestation_cert_sn = cert_chain->GetCert(0)->GetSerialNumber();
|
||||
return util::OkStatus();
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
util::Status RemoteAttestationVerifier::LoadCa() {
|
||||
Status RemoteAttestationVerifier::LoadCa() {
|
||||
absl::WriterMutexLock lock(&ca_mutex_);
|
||||
std::unique_ptr<X509Cert> ca_cert(new X509Cert);
|
||||
util::Status status = ca_cert->LoadDer(absl::HexStringToBytes(
|
||||
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 util::OkStatus();
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
Reference in New Issue
Block a user