//////////////////////////////////////////////////////////////////////////////// // Copyright 2017 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 #include "glog/logging.h" #include "testing/gmock.h" #include "testing/gunit.h" #include "absl/strings/escaping.h" #include "common/rsa_key.h" #include "common/vmp_checker.h" #include "protos/public/errors.pb.h" #include "protos/public/verified_media_pipeline.pb.h" namespace widevine { namespace { const uint32_t kBlessedBinaryFlag = 0x00000001; const char kDevVmpCodeSigningKey[] = "308204a50201000282010100b3a7da87309390688388d614a5a37e7ee73a" "c3b296caf4464bfeccbeedf2e3d802d62d5de2f7b409b1eac2dc578b2bfd" "8b5f20acef13d8ba6a4ccfd406f29a60e1af4151212a062c62c71d894fe6" "d5524e1b28af1d51d2b806aca778f77fd0e4ef278c4fbd5eb756398d646b" "b50d3a13d8687ad304005b0b0a054e5109d70dec9953b2f99768fca8fe51" "957dc4608fd34c999a7b35245bce2795715d8a5957a0872398473eed4860" "29286f51d4118927e88634ad040034e061fd3f58632961761b1fbb8faf45" "391d84f7ffe2bf5e27bd499eee14a17bc8be2fd258331e7a86baa7394706" "424420f6eaba0001bffe74976a5b4cc46380ceef9ce93b3bb73008150203" "01000102820101008befeb1ff28e7ea56a0f63f1a133c08c48c0553efe86" "07cfd9d216d981aef81a81db226b47277a6d32d09207df88e03316247ae7" "39325456a00644bbfacd6dc2990851f047ccdc1226bec21afac9eacfb957" "1e51889cfb6dac853fcdd1bb1593bd5528cdd3cbbb32c69183ef018fd3f5" "3153f097fd3de9aca7998a6f4522e60c5e76ecc717033a2be16c233fe3e2" "94c0ae68179a1ae5d33d51f2c0bcda35cffa21e1814374af1c014c280cfb" "09e294a099f9a6f003d3da026af0f53029cad3d401178b0db53ca97fd166" "a5eddf1384ddd92c55ab31758e0651e41dd7b24f2c438d58de00f55343cc" "a461b94ff6358fc37f404ecbda2365d3e75391566248d3e102818100e4c8" "783343b43fc127f5077fb35b37145ab6ee5f9a802e8100161ce441cbdbdc" "1eb15f50bbef1f5088ba83ff914977862dffc63bd364172c9044e1131dbb" "ff98755daa49670a014163b3c121395d880ad874b9ebdf66ff72a245c2b5" "4f8fe1e233e72fd9cc253cbcd144f52537e9b7ed16b8a6d328de61c41f86" "ea1d9ef326fb02818100c90738b2cf61af785e53393d9e96bc2f4d79358b" "7bd487a242d170b8372af0a26af4980534a099647a4f38efb1a47d9dcdcf" "a4ea6036396ef333e4f1de62ec529c3122f0d3b6abc818918494a52b028b" "2cdf06bf2b450d5b99da7f203ff011318c030a01659c4c56244c2c312528" "e30dd3b7709022d8fd14a2dba23a855da02f0281804f8ebeede4cf5b9449" "d6d582bcd62d73309088984a5be4d00b3da55262e7074fa684bbc69173f8" "09c36248e0a89f49a7297bd66d9b7724efe4436f997c2f92146c4be4199e" "71463a7cf75763bc552027d559d2058a2c810c560db845e0a30243ed14a9" "f92d1a8de2834b5d8c51c33ea87dcc3c8715a12f9249fc5a916e62d3dd02" "8181008f74c7d1528cb35b82748174a7a789c377d5f790025e382c62e273" "3e02a071f875baf681407d1af9c90e9fe2ed322532679cb6634b2566f6f6" "37223a3828ffdc33fa1ca51f704c460ec2498a8a13974d1a484dd83e5898" "9fb5bb66dcecc3b4815719141acb182ea18a659163c0d0dcb7114ee6d4f5" "09441165e6b66e6c9dd3a102818100c449003eee6d9a0b724b66027a791e" "3b86a72b2098ab085c2e69c276627fd6beeee98918de14ce15d17e059906" "a178015d04e205918203ffa6c1324868d5c0a019f6fe82335403743322ee" "14b1159692194ac22d9056c0c39309d249b33abaddb0d08ee87cc053a12a" "83f12d261525e1b37df643c3e55770ef247d5d094816a0"; const char kDevVmpCodeSigningCert[] = "3082056a308203d2a003020102020f112233445566778899aabbccddeeff300d06092a86" "4886f70d01010b050030819c310b30090603550406130255533113301106035504080c0a" "57617368696e67746f6e3111300f06035504070c084b69726b6c616e64310f300d060355" "040a0c06476f6f676c653111300f060355040b0c085769646576696e65311e301c060355" "04030c157769646576696e652d6465762d636f64657369676e3121301f06092a864886f7" "0d010901161274696e736b697040676f6f676c652e636f6d301e170d3137313030393231" "323835385a170d3237313030373231323835385a3081a0310b3009060355040613025553" "3113301106035504080c0a57617368696e67746f6e3111300f06035504070c084b69726b" "6c616e64310f300d060355040a0c06476f6f676c653111300f060355040b0c0857696465" "76696e653122302006035504030c197769646576696e652d6465762d766d702d636f6465" "7369676e3121301f06092a864886f70d010901161274696e736b697040676f6f676c652e" "636f6d30820122300d06092a864886f70d01010105000382010f003082010a0282010100" "b3a7da87309390688388d614a5a37e7ee73ac3b296caf4464bfeccbeedf2e3d802d62d5d" "e2f7b409b1eac2dc578b2bfd8b5f20acef13d8ba6a4ccfd406f29a60e1af4151212a062c" "62c71d894fe6d5524e1b28af1d51d2b806aca778f77fd0e4ef278c4fbd5eb756398d646b" "b50d3a13d8687ad304005b0b0a054e5109d70dec9953b2f99768fca8fe51957dc4608fd3" "4c999a7b35245bce2795715d8a5957a0872398473eed486029286f51d4118927e88634ad" "040034e061fd3f58632961761b1fbb8faf45391d84f7ffe2bf5e27bd499eee14a17bc8be" "2fd258331e7a86baa7394706424420f6eaba0001bffe74976a5b4cc46380ceef9ce93b3b" "b73008150203010001a38201213082011d301d0603551d0e041604147266b4ce84aafd02" "b1159cd2fa04c2553c6c02463081bb0603551d230481b33081b0a181a2a4819f30819c31" "0b30090603550406130255533113301106035504080c0a57617368696e67746f6e311130" "0f06035504070c084b69726b6c616e64310f300d060355040a0c06476f6f676c65311130" "0f060355040b0c085769646576696e65311e301c06035504030c157769646576696e652d" "6465762d636f64657369676e3121301f06092a864886f70d010901161274696e736b6970" "40676f6f676c652e636f6d820900c5f82f038facf15830090603551d1304023000300b06" "03551d0f04040302078030130603551d25040c300a06082b060105050703033011060a2b" "06010401d67904010204030101ff300d06092a864886f70d01010b05000382018100aa23" "6a5c0e23d5bf67c9f80f893d8347ba489541cf7f4ab7dfffda0ca21a3372e8ee8cfea863" "628b9e0795904bc0e7495517246143c7b8555884e82fe1c305f0f4c3575447d4e7ce3243" "4e1e0cf11712d537cd434c11d1328b814c94dbd0bab802e8fed5390da5f0cd719ce0e366" "47620bcf40ed3945c80ab19beb7728080a74d4ff5d62564f47b32c4915c1f14890d379c8" "8060f0bac73301defda06275a2e1a2024f92f0b4700d4e50d2d6f8d033715a362d7ca5ab" "6d2dae20d8cefa2d3fc4f61e1734802984e5078dd6d957719fa75ea10dd02d983f7e383b" "10fa92be7add70238388e63ec2c7ec49a37aa0c8a2566c46e9755cd9ce654c6d42053d1e" "1cd9555f8a3bc5e426857072a8e8b44a756543893b1d29dabf31a2301597df2666612f23" "a442613526e19f2aa9b2ea49f16f14b16794e053967a21b821c7b2495b2e02b01344a339" "9d7e31dd71982cf21a546b1947bbce236381d717070c27096b6a91413abc69c3c0759574" "4b7e91daf24b2a0acfd85924669f00292a4bd0c57b4c"; const char kDevSecureStorageVmpCodeSigningCert[] = "30820571308203d9a0030201020203112233300d06092a864886f70d01010b050030819c" "310b30090603550406130255533113301106035504080c0a57617368696e67746f6e3111" "300f06035504070c084b69726b6c616e64310f300d060355040a0c06476f6f676c653111" "300f060355040b0c085769646576696e65311e301c06035504030c157769646576696e65" "2d6465762d636f64657369676e3121301f06092a864886f70d010901161274696e736b69" "7040676f6f676c652e636f6d301e170d3138303232323231323834395a170d3238303232" "303231323834395a3081a0310b30090603550406130255533113301106035504080c0a57" "617368696e67746f6e3111300f06035504070c084b69726b6c616e64310f300d06035504" "0a0c06476f6f676c653111300f060355040b0c085769646576696e653122302006035504" "030c197769646576696e652d6465762d766d702d636f64657369676e3121301f06092a86" "4886f70d010901161274696e736b697040676f6f676c652e636f6d30820122300d06092a" "864886f70d01010105000382010f003082010a0282010100b3a7da87309390688388d614" "a5a37e7ee73ac3b296caf4464bfeccbeedf2e3d802d62d5de2f7b409b1eac2dc578b2bfd" "8b5f20acef13d8ba6a4ccfd406f29a60e1af4151212a062c62c71d894fe6d5524e1b28af" "1d51d2b806aca778f77fd0e4ef278c4fbd5eb756398d646bb50d3a13d8687ad304005b0b" "0a054e5109d70dec9953b2f99768fca8fe51957dc4608fd34c999a7b35245bce2795715d" "8a5957a0872398473eed486029286f51d4118927e88634ad040034e061fd3f5863296176" "1b1fbb8faf45391d84f7ffe2bf5e27bd499eee14a17bc8be2fd258331e7a86baa7394706" "424420f6eaba0001bffe74976a5b4cc46380ceef9ce93b3bb73008150203010001a38201" "3430820130301d0603551d0e041604147266b4ce84aafd02b1159cd2fa04c2553c6c0246" "3081bb0603551d230481b33081b0a181a2a4819f30819c310b3009060355040613025553" "3113301106035504080c0a57617368696e67746f6e3111300f06035504070c084b69726b" "6c616e64310f300d060355040a0c06476f6f676c653111300f060355040b0c0857696465" "76696e65311e301c06035504030c157769646576696e652d6465762d636f64657369676e" "3121301f06092a864886f70d010901161274696e736b697040676f6f676c652e636f6d82" "0900c5f82f038facf15830090603551d1304023000300b0603551d0f0404030207803013" "0603551d25040c300a06082b060105050703033011060a2b06010401d679040102040301" "01ff3011060a2b06010401d67904010304030101ff300d06092a864886f70d01010b0500" "038201810069482a9bb125b17c76c77f86004e36ca4fc36bbde9c86901481c70d165e3cf" "1c8541264190b3e7106c33ff4920a99bc9f939298091dc72ff898d22f5017b04d213eb60" "626382656fdd66b9cd1830d98ef89d8e405b2d7ce9445db8de2ca365438b848f85d5266b" "c211c8934154bb88ddb9e6f9aaff761814c1c0da90dd499f174507b5f4e89339e8abd157" "8b3238d8f5c9dcb1f76e4d810679c2eca3583144f1ac0ce955b7c6a2cc9fc9f3d6c87069" "28e301ebc3844e53f4905ff60803110dfc3b4f74b50ae1baffd091daad3ea29925f8009e" "adc471a9ae673d9a9a003901d962f58fede85b2f65d9a470725459b19a69b06ae49179a3" "395286b7d7039b32985a6db5b30bcd5cbed975d9a68de44fbcd1dbc8b6fbf67746b87d30" "122c1cd8ed303a8bec7e23d284c0de35cfdccf261c317efe192efa84d2600bba3f9af846" "8f89953a98f92c97b13d320f484627790d5b7b407f29f343c41154efbcf06e98632a3f3d" "7138184a6f40af2435b3d98054ed9f4c3aa9ecf95c5c3014d3aa4d12f2"; const char kSameAsPrevious[] = ""; } // namespace class VmpCheckerTest : public ::testing::Test { public: void SetUp() override { ASSERT_OK(VmpChecker::Instance()->SelectDrmCertificateType( kCertificateTypeTesting)); vmp_data_.Clear(); VmpChecker::Instance()->set_allow_development_vmp(true); signing_key_.reset( RsaPrivateKey::Create(absl::HexStringToBytes(kDevVmpCodeSigningKey))); ASSERT_TRUE(signing_key_); } // Adds a binary to the VMP data to be verified. If |signing_cert| is // |kSameAsPrevious| (empty), then the binary is signed using the same // certificate as the previously added binary. This means that the first // call to this function should not use |kSameAsPrevious|. void AddVmpBinary(const std::string& signing_cert, const std::string& file_name, const std::string& binary_hash, uint32_t flags) { DCHECK(!signing_cert.empty() || !vmp_data_.certificates().empty()); if (!signing_cert.empty()) { *vmp_data_.add_certificates() = absl::HexStringToBytes(signing_cert); } vmp::VmpData::SignedBinaryInfo* new_binary = vmp_data_.add_signed_binary_info(); new_binary->set_file_name(file_name); new_binary->set_certificate_index(vmp_data_.certificates_size() - 1); new_binary->set_binary_hash(binary_hash); new_binary->set_flags(flags); std::string message(binary_hash); message += flags & 0xff; std::string signature; ASSERT_TRUE(signing_key_->GenerateSignature(message, &signature)); new_binary->set_signature(signature); } const std::string GetVmpData() { std::string result; vmp_data_.SerializeToString(&result); return result; } protected: vmp::VmpData vmp_data_; std::unique_ptr signing_key_; }; TEST_F(VmpCheckerTest, Success) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevSecureStorageVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kVerified, result); } TEST_F(VmpCheckerTest, SecureStorageSuccess) { AddVmpBinary(kDevSecureStorageVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevSecureStorageVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kSecureStorageVerified, result); } TEST_F(VmpCheckerTest, FailDevelopmentCert) { VmpChecker::Instance()->set_allow_development_vmp(false); AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); VmpChecker::Result result; EXPECT_EQ(DEVELOPMENT_CERTIFICATE_NOT_ALLOWED, VmpChecker::Instance() ->VerifyVmpData(GetVmpData(), &result) .error_code()); } TEST_F(VmpCheckerTest, FailTwoBlessedBinaries) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); vmp_data_.mutable_signed_binary_info(0)->set_flags(kBlessedBinaryFlag); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kTampered, result); } TEST_F(VmpCheckerTest, FailNoBlessedBinaries) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); vmp_data_.mutable_signed_binary_info(3)->set_flags(0); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kTampered, result); } TEST_F(VmpCheckerTest, FailBadSignature) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); ++((*vmp_data_.mutable_signed_binary_info(2)->mutable_signature())[10]); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kTampered, result); } TEST_F(VmpCheckerTest, FailSignatureVerification) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); ++((*vmp_data_.mutable_signed_binary_info(3)->mutable_binary_hash())[16]); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kTampered, result); } TEST_F(VmpCheckerTest, FailUnsignedBinary) { AddVmpBinary(kDevVmpCodeSigningCert, "binary1.exe", "0123456789abdef0123456789abdef", 0); AddVmpBinary(kSameAsPrevious, "binary2.dll", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0); AddVmpBinary(kDevVmpCodeSigningCert, "binary3.dll", "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 0); AddVmpBinary(kSameAsPrevious, "binary4.dll", "cccccccccccccccccccccccccccccc", kBlessedBinaryFlag); vmp_data_.mutable_signed_binary_info(2)->clear_binary_hash(); VmpChecker::Result result; ASSERT_OK(VmpChecker::Instance()->VerifyVmpData(GetVmpData(), &result)); EXPECT_EQ(VmpChecker::kTampered, result); } } // namespace widevine