//////////////////////////////////////////////////////////////////////////////// // 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 #include #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 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 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 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