//////////////////////////////////////////////////////////////////////////////// // 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 "common/client_cert.h" #include #include #include #include #include "glog/logging.h" #include "testing/gmock.h" #include "testing/gunit.h" #include "absl/strings/escaping.h" #include "absl/strings/str_cat.h" #include "absl/synchronization/mutex.h" #include "absl/time/clock.h" #include "absl/time/time.h" #include "common/drm_root_certificate.h" #include "common/error_space.h" #include "common/rsa_test_keys.h" #include "common/sha_util.h" #include "common/test_drm_certificates.h" #include "common/wvm_test_keys.h" #include "protos/public/drm_certificate.pb.h" #include "protos/public/errors.pb.h" #include "protos/public/signed_drm_certificate.pb.h" // TODO(user): Change these tests to use on-the-fly generated intermediate // and device certificates based on RsaTestKeys. // TODO(user): Add testcase(s) CreateSignature, // and GenerateSigningKey. namespace widevine { using ::testing::_; using ::testing::Return; class ClientCertTest : public ::testing::Test { public: void SetUp() override { if (!setup_preprov_keys_) { KeyboxClientCert::SetPreProvisioningKeys( wvm_test_keys::GetPreprovKeyMultimap()); setup_preprov_keys_ = true; } ASSERT_OK( DrmRootCertificate::CreateByType(kCertificateTypeTesting, &root_cert_)); } protected: // Simple container struct for test value and expected keys. class TestTokenAndKeys { public: const std::string token_; uint32_t expected_system_id_; const std::string expected_serial_number_; const std::string expected_device_key_; TestTokenAndKeys(const std::string& token, uint32_t expected_system_id, const std::string& expected_serial_number, const std::string& expected_device_key) : token_(token), expected_system_id_(expected_system_id), expected_serial_number_(expected_serial_number), expected_device_key_(expected_device_key) {} }; class TestCertificateAndData { public: const std::string certificate_; const std::string expected_serial_number_; uint32_t expected_system_id_; Status expected_status_; TestCertificateAndData(const std::string& certificate, const std::string& expected_serial_number, uint32_t expected_system_id, Status expected_status) : certificate_(certificate), expected_serial_number_(expected_serial_number), expected_system_id_(expected_system_id), expected_status_(std::move(expected_status)) {} }; void TestBasicValidation(const TestTokenAndKeys& expectation, const bool expect_success, const bool compare_device_key); void TestBasicValidationDrmCertificate( const TestCertificateAndData& expectation, const bool compare_data); void GenerateSignature(const std::string& message, const std::string& private_key, std::string* signature); SignedDrmCertificate* SignCertificate(const DrmCertificate& certificate, SignedDrmCertificate* signer, const std::string& private_key); DrmCertificate* GenerateProvisionerCertificate(uint32_t system_id, const std::string& serial_number, const std::string& provider_id); SignedDrmCertificate* GenerateSignedProvisionerCertificate( uint32_t system_id, const std::string& serial_number, const std::string& service_id); DrmCertificate* GenerateIntermediateCertificate(uint32_t system_id, const std::string& serial_number); SignedDrmCertificate* GenerateSignedIntermediateCertificate( SignedDrmCertificate* signer, uint32_t system_id, const std::string& serial_number); DrmCertificate* GenerateDrmCertificate(uint32_t system_id, const std::string& serial_number); SignedDrmCertificate* GenerateSignedDrmCertificate( SignedDrmCertificate* signer, uint32_t system_id, const std::string& serial_number); RsaTestKeys test_rsa_keys_; TestDrmCertificates test_drm_certs_; std::unique_ptr root_cert_; static bool setup_preprov_keys_; }; bool ClientCertTest::setup_preprov_keys_(false); void ClientCertTest::TestBasicValidation(const TestTokenAndKeys& expectation, const bool expect_success, const bool compare_device_key) { // Test validation of a valid request. Status status; ClientCert* client_cert_ptr = nullptr; // Two ways to create a client cert object, test both. for (int i = 0; i < 2; i++) { if (i == 0) { status = ClientCert::Create(root_cert_.get(), ClientIdentification::KEYBOX, expectation.token_, &client_cert_ptr); } else { status = ClientCert::CreateWithKeybox(expectation.token_, &client_cert_ptr); } std::unique_ptr keybox_cert(client_cert_ptr); if (expect_success) { ASSERT_EQ(OkStatus(), status); ASSERT_TRUE(keybox_cert.get()); EXPECT_EQ(expectation.expected_system_id_, keybox_cert->system_id()); EXPECT_EQ(expectation.expected_serial_number_, keybox_cert->serial_number()); if (compare_device_key) { EXPECT_EQ(expectation.expected_device_key_, keybox_cert->key()); } } else { EXPECT_NE(OkStatus(), status); EXPECT_FALSE(keybox_cert); } } } void ClientCertTest::TestBasicValidationDrmCertificate( const TestCertificateAndData& expectation, const bool compare_data) { // Reset DRM certificate signature cache since some certificates get // re-generated. ASSERT_OK( DrmRootCertificate::CreateByType(kCertificateTypeTesting, &root_cert_)); // Test validation of a valid request. Status status; ClientCert* client_cert_ptr = nullptr; status = ClientCert::Create(root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, expectation.certificate_, &client_cert_ptr); std::unique_ptr drm_certificate_cert(client_cert_ptr); ASSERT_EQ(expectation.expected_status_, status); if (expectation.expected_status_.ok()) { ASSERT_TRUE(drm_certificate_cert.get()); if (compare_data) { ASSERT_EQ(expectation.expected_serial_number_, drm_certificate_cert->signer_serial_number()); ASSERT_EQ(expectation.expected_system_id_, drm_certificate_cert->system_id()); } } else { ASSERT_FALSE(drm_certificate_cert.get()); } } void ClientCertTest::GenerateSignature(const std::string& message, const std::string& private_key, std::string* signature) { std::unique_ptr rsa_private_key( RsaPrivateKey::Create(private_key)); ASSERT_TRUE(rsa_private_key != nullptr); rsa_private_key->GenerateSignature(message, signature); } // The caller relinquishes ownership of |signer|, which may also be nullptr. SignedDrmCertificate* ClientCertTest::SignCertificate( const DrmCertificate& certificate, SignedDrmCertificate* signer, const std::string& private_key) { std::unique_ptr signed_certificate( new SignedDrmCertificate); signed_certificate->set_drm_certificate(certificate.SerializeAsString()); GenerateSignature(signed_certificate->drm_certificate(), private_key, signed_certificate->mutable_signature()); if (signer != nullptr) { signed_certificate->set_allocated_signer(signer); } return signed_certificate.release(); } DrmCertificate* ClientCertTest::GenerateIntermediateCertificate( uint32_t system_id, const std::string& serial_number) { std::unique_ptr intermediate_certificate(new DrmCertificate); intermediate_certificate->set_type(DrmCertificate::DEVICE_MODEL); intermediate_certificate->set_serial_number(serial_number); intermediate_certificate->set_public_key( test_rsa_keys_.public_test_key_2_2048_bits()); intermediate_certificate->set_system_id(system_id); intermediate_certificate->set_creation_time_seconds(1234); return intermediate_certificate.release(); } SignedDrmCertificate* ClientCertTest::GenerateSignedIntermediateCertificate( SignedDrmCertificate* signer, uint32_t system_id, const std::string& serial_number) { std::unique_ptr intermediate_certificate( GenerateIntermediateCertificate(system_id, serial_number)); return SignCertificate(*intermediate_certificate, signer, test_rsa_keys_.private_test_key_1_3072_bits()); } DrmCertificate* ClientCertTest::GenerateDrmCertificate( uint32_t system_id, const std::string& serial_number) { std::unique_ptr drm_certificate(new DrmCertificate); drm_certificate->set_type(DrmCertificate::DEVICE); drm_certificate->set_serial_number(serial_number); drm_certificate->set_system_id(system_id); drm_certificate->set_public_key(test_rsa_keys_.public_test_key_3_2048_bits()); drm_certificate->set_creation_time_seconds(4321); return drm_certificate.release(); } SignedDrmCertificate* ClientCertTest::GenerateSignedDrmCertificate( SignedDrmCertificate* signer, uint32_t system_id, const std::string& serial_number) { std::unique_ptr drm_certificate( GenerateDrmCertificate(system_id, serial_number)); std::unique_ptr signed_drm_certificate(SignCertificate( *drm_certificate, signer, test_rsa_keys_.private_test_key_2_2048_bits())); return signed_drm_certificate.release(); } DrmCertificate* ClientCertTest::GenerateProvisionerCertificate( uint32_t system_id, const std::string& serial_number, const std::string& provider_id) { std::unique_ptr provisioner_certificate(new DrmCertificate); provisioner_certificate->set_type(DrmCertificate::PROVISIONER); provisioner_certificate->set_serial_number(serial_number); // TODO(user): Need to generate 3072 bit test for provisioner certificates. provisioner_certificate->set_public_key( test_rsa_keys_.public_test_key_1_3072_bits()); provisioner_certificate->set_system_id(system_id); provisioner_certificate->set_provider_id(provider_id); provisioner_certificate->set_creation_time_seconds(1234); return provisioner_certificate.release(); } SignedDrmCertificate* ClientCertTest::GenerateSignedProvisionerCertificate( uint32_t system_id, const std::string& serial_number, const std::string& service_id) { std::unique_ptr provisioner_certificate( GenerateProvisionerCertificate(system_id, serial_number, service_id)); return SignCertificate(*provisioner_certificate, nullptr, test_rsa_keys_.private_test_key_1_3072_bits()); } TEST_F(ClientCertTest, BasicValidation) { const TestTokenAndKeys kValidTokenAndExpectedKeys[] = { TestTokenAndKeys( absl::HexStringToBytes( "00000002000001128e1ebfe037828096ca6538b4f6f4bcb51c2b7191cf037e98" "beaa24924907e128f9ff49b54a165cd9c33e6547537eb4d29fb7e8df3c2c1cd9" "2517a12f4922953e"), 274, absl::HexStringToBytes("8e1ebfe037828096ca6538b4f6f4bcb5"), absl::HexStringToBytes("4071197f1f8910d9bf10c6bc4c987638")), TestTokenAndKeys( absl::HexStringToBytes( "0000000200000112d906feebe1750c5886ff77c2dfa31bb40e002f3adbc0fa5b" "eb2486cf5f419549cdaa23230e5165ac2ffab56d53b692b7ba0c1857400c6add" "3af3ff3d5cb24985"), 274, absl::HexStringToBytes("d906feebe1750c5886ff77c2dfa31bb4"), absl::HexStringToBytes("42cfb1765201042302a404d1e0fac8ed"))}; for (size_t i = 0; i < ABSL_ARRAYSIZE(kValidTokenAndExpectedKeys); ++i) { SCOPED_TRACE("Test data: " + absl::StrCat(i)); TestBasicValidation(kValidTokenAndExpectedKeys[i], true, true); } EXPECT_EQ( wvm_test_keys::kTestSystemId, KeyboxClientCert::GetSystemId(kValidTokenAndExpectedKeys[0].token_)); } TEST_F(ClientCertTest, BasicCertValidation) { const uint32_t system_id = 1234; const std::string serial_number("serial_number"); std::unique_ptr signed_cert( GenerateSignedDrmCertificate(GenerateSignedIntermediateCertificate( nullptr, system_id, serial_number), system_id, serial_number + "-device")); const TestCertificateAndData kValidCertificateAndExpectedData( signed_cert->SerializeAsString(), serial_number, system_id, OkStatus()); const bool compare_data = true; TestBasicValidationDrmCertificate(kValidCertificateAndExpectedData, compare_data); } TEST_F(ClientCertTest, InvalidKeybox) { const TestTokenAndKeys kInvalidTokenAndExpectedKeys[] = { // This tests a malformed, but appropriately sized keybox. TestTokenAndKeys( absl::HexStringToBytes( "00000002000001129e1ebfe037828096ca6538b4f6f4bcb51c2b7191cf037e98" "beaa24924907e128f9ff49b54a165cd9c33e6547537eb4d29fb7e8df3c2c1cd9" "2517a12f4922953e"), 0, absl::HexStringToBytes(""), absl::HexStringToBytes("")), // This has a length and system_id, but nothing else. TestTokenAndKeys(absl::HexStringToBytes("0000000200000112"), 0, absl::HexStringToBytes(""), absl::HexStringToBytes("")), // This has only a byte. TestTokenAndKeys(absl::HexStringToBytes(""), 0, absl::HexStringToBytes(""), absl::HexStringToBytes("")), // This has an emptry std::string for the keybox. TestTokenAndKeys(absl::HexStringToBytes(""), 0, absl::HexStringToBytes(""), absl::HexStringToBytes(""))}; for (size_t i = 0; i < ABSL_ARRAYSIZE(kInvalidTokenAndExpectedKeys); ++i) { SCOPED_TRACE("Test data: " + absl::StrCat(i)); TestBasicValidation(kInvalidTokenAndExpectedKeys[i], false, false); } } TEST_F(ClientCertTest, InvalidCertificate) { const uint32_t system_id(1234); const std::string device_sn("device-serial-number"); const std::string signer_sn("signer-serial-number"); std::unique_ptr dev_cert; std::unique_ptr signer_cert; std::unique_ptr signed_signer; // Invalid serialized device certificate. std::unique_ptr invalid_drm_cert( new SignedDrmCertificate); invalid_drm_cert->set_drm_certificate("bad-serialized-cert"); GenerateSignature(invalid_drm_cert->drm_certificate(), test_rsa_keys_.private_test_key_2_2048_bits(), invalid_drm_cert->mutable_signature()); invalid_drm_cert->set_allocated_signer( GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn)); // Invalid device public key. dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); dev_cert->set_public_key("bad-device-public-key"); std::unique_ptr bad_device_public_key(SignCertificate( *dev_cert, GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn), test_rsa_keys_.private_test_key_2_2048_bits())); // Invalid serialized intermediate certificate. signed_signer.reset( GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn)); signed_signer->set_drm_certificate("bad-serialized-cert"); GenerateSignature(signed_signer->drm_certificate(), test_rsa_keys_.private_test_key_1_3072_bits(), signed_signer->mutable_signature()); dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); std::unique_ptr invalid_signer( SignCertificate(*dev_cert, signed_signer.release(), test_rsa_keys_.private_test_key_2_2048_bits())); // Invalid signer public key. dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); signer_cert.reset(GenerateIntermediateCertificate(system_id, signer_sn)); signer_cert->set_public_key("bad-signer-public-key"); std::unique_ptr bad_signer_public_key(SignCertificate( *dev_cert, SignCertificate(*signer_cert, nullptr, test_rsa_keys_.private_test_key_1_3072_bits()), test_rsa_keys_.private_test_key_2_2048_bits())); // Invalid device certificate signature. std::unique_ptr bad_device_signature( GenerateSignedDrmCertificate( GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn), system_id, device_sn)); bad_device_signature->set_signature("bad-signature"); // Missing model system ID. dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); signer_cert.reset(GenerateIntermediateCertificate(system_id, signer_sn)); signer_cert->clear_system_id(); std::unique_ptr missing_model_sn(SignCertificate( *dev_cert, SignCertificate(*signer_cert, nullptr, test_rsa_keys_.private_test_key_1_3072_bits()), test_rsa_keys_.private_test_key_2_2048_bits())); // Missing signer serial number. dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); signer_cert.reset(GenerateIntermediateCertificate(system_id, signer_sn)); signer_cert->clear_serial_number(); std::unique_ptr missing_signer_sn(SignCertificate( *dev_cert, SignCertificate(*signer_cert, nullptr, test_rsa_keys_.private_test_key_1_3072_bits()), test_rsa_keys_.private_test_key_2_2048_bits())); // Invalid serialized intermediate certificate. dev_cert.reset(GenerateDrmCertificate(system_id, device_sn)); signed_signer.reset( GenerateSignedIntermediateCertificate(nullptr, system_id, signer_sn)); signed_signer->set_signature("bad-signature"); std::unique_ptr bad_signer_signature( SignCertificate(*dev_cert, signed_signer.release(), test_rsa_keys_.private_test_key_2_2048_bits())); const TestCertificateAndData kInvalidCertificate[] = { TestCertificateAndData("f", "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "invalid-signed-drm-certificate")), TestCertificateAndData(invalid_drm_cert->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "invalid-drm-certificate")), TestCertificateAndData(bad_device_public_key->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "drm-certificate-public-key-failed")), TestCertificateAndData(invalid_signer->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "invalid-signer-certificate")), TestCertificateAndData(bad_signer_public_key->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "invalid-leaf-signer-public-key")), TestCertificateAndData(bad_device_signature->SerializeAsString(), "", 0, Status(error_space, INVALID_SIGNATURE, "cache-miss-invalid-signature")), TestCertificateAndData(missing_model_sn->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "model-certificate-missing-system-id")), TestCertificateAndData(missing_signer_sn->SerializeAsString(), "", 0, Status(error_space, INVALID_DRM_CERTIFICATE, "missing-signer-serial-number")), TestCertificateAndData(bad_signer_signature->SerializeAsString(), "", 0, Status(error_space, INVALID_SIGNATURE, "cache-miss-invalid-signature")), }; for (size_t i = 0; i < ABSL_ARRAYSIZE(kInvalidCertificate); ++i) { TestBasicValidationDrmCertificate(kInvalidCertificate[i], false); } } TEST_F(ClientCertTest, MissingPreProvKey) { // system ID in token is 0x01234567 const std::string token(absl::HexStringToBytes( "00000002012345678e1ebfe037828096ca6538b4f6f4bcb51c2b7191cf037e98" "beaa24924907e128f9ff49b54a165cd9c33e6547537eb4d29fb7e8df3c2c1cd9" "2517a12f4922953e")); ClientCert* client_cert_ptr = nullptr; Status status = ClientCert::CreateWithKeybox(token, &client_cert_ptr); ASSERT_EQ(MISSING_PRE_PROV_KEY, status.error_code()); } TEST_F(ClientCertTest, ValidProvisionerDeviceCert) { const uint32_t system_id = 5000; const std::string service_id("widevine_test.com"); const std::string device_serial_number("device-serial-number"); const std::string intermediate_serial_number("intermediate-serial-number"); const std::string provisioner_serial_number("provisioner-serial-number"); std::unique_ptr signed_provisioner_cert( GenerateSignedProvisionerCertificate(system_id, provisioner_serial_number, service_id)); std::unique_ptr signed_intermediate_cert( GenerateSignedIntermediateCertificate(signed_provisioner_cert.release(), system_id, intermediate_serial_number)); std::unique_ptr signed_device_cert( GenerateSignedDrmCertificate(signed_intermediate_cert.release(), system_id, device_serial_number)); std::string serialized_cert; signed_device_cert->SerializeToString(&serialized_cert); ClientCert* client_cert_ptr = nullptr; EXPECT_OK(ClientCert::Create(root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, serialized_cert, &client_cert_ptr)); ASSERT_TRUE(client_cert_ptr != nullptr); std::unique_ptr drm_cert(client_cert_ptr); EXPECT_EQ(service_id, drm_cert->service_id()); EXPECT_EQ(device_serial_number, drm_cert->serial_number()); EXPECT_EQ(intermediate_serial_number, drm_cert->signer_serial_number()); EXPECT_EQ(system_id, drm_cert->system_id()); } TEST_F(ClientCertTest, InvalidProvisionerDeviceCertEmptyServiceId) { const uint32_t system_id = 4890; const std::string service_id(""); const std::string device_serial_number("device-serial-number"); const std::string intermediate_serial_number("intermediate-serial-number"); const std::string provisioner_serial_number("provisioner-serial-number"); std::unique_ptr signed_provisioner_cert( GenerateSignedProvisionerCertificate(system_id, provisioner_serial_number, service_id)); std::unique_ptr signed_intermediate_cert( GenerateSignedIntermediateCertificate(signed_provisioner_cert.release(), system_id, intermediate_serial_number)); std::unique_ptr signed_device_cert( GenerateSignedDrmCertificate(signed_intermediate_cert.release(), system_id, device_serial_number)); std::string serialized_cert; signed_device_cert->SerializeToString(&serialized_cert); ClientCert* client_cert_ptr = nullptr; EXPECT_EQ("missing-provisioning-service-id", ClientCert::Create(root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, serialized_cert, &client_cert_ptr) .error_message()); EXPECT_FALSE(client_cert_ptr); } TEST_F(ClientCertTest, InvalidProvisionerDeviceCertChain) { const uint32_t system_id = 4890; const uint32_t system_id2 = 4892; const std::string service_id("widevine_test.com"); const std::string device_serial_number("device-serial-number"); const std::string intermediate_serial_number("intermediate-serial-number"); const std::string intermediate_serial_number2("intermediate-serial-number-2"); std::unique_ptr signed_intermediate_cert2( GenerateSignedIntermediateCertificate(nullptr, system_id2, intermediate_serial_number2)); // Instead of using a provisioner certificate to sign this intermediate // certificate, use another intermediate certificate. This is an invalid // chain and should generate an error when trying to create a client // certificate. std::unique_ptr signed_intermediate_cert( GenerateSignedIntermediateCertificate(signed_intermediate_cert2.release(), system_id, intermediate_serial_number)); std::unique_ptr signed_device_cert( GenerateSignedDrmCertificate(signed_intermediate_cert.release(), system_id, device_serial_number)); std::string serialized_cert; signed_device_cert->SerializeToString(&serialized_cert); ClientCert* client_cert_ptr = nullptr; // TODO(user): Fix this test. It is failing for the right reasons, but the // certificate chain is broken (intermediate signature does not match signer). ASSERT_EQ("cache-miss-invalid-signature", ClientCert::Create(root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, serialized_cert, &client_cert_ptr) .error_message()); EXPECT_FALSE(client_cert_ptr); } TEST_F(ClientCertTest, Protocol21WithDrmCert) { const char message[] = "A weekend wasted is a weekend well spent."; ClientCert* client_cert_ptr = nullptr; ASSERT_OK(ClientCert::Create( root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, test_drm_certs_.test_user_device_certificate(), &client_cert_ptr)); std::unique_ptr client_cert(client_cert_ptr); std::unique_ptr private_key( RsaPrivateKey::Create(test_rsa_keys_.private_test_key_3_2048_bits())); ASSERT_TRUE(private_key); // Success std::string signature; ASSERT_TRUE(private_key->GenerateSignature(message, &signature)); EXPECT_OK(client_cert->VerifySignature(message, signature, VERSION_2_1)); // Failure ASSERT_EQ(256, signature.size()); ++signature[127]; EXPECT_FALSE( client_cert->VerifySignature(message, signature, VERSION_2_1).ok()); } TEST_F(ClientCertTest, Protocol22WithDrmCert) { const char message[] = "There is nothing permanent except change."; const std::string message_hash(Sha512_Hash(message)); ClientCert* client_cert_ptr = nullptr; ASSERT_OK(ClientCert::Create( root_cert_.get(), ClientIdentification::DRM_DEVICE_CERTIFICATE, test_drm_certs_.test_user_device_certificate(), &client_cert_ptr)); std::unique_ptr client_cert(client_cert_ptr); std::unique_ptr private_key( RsaPrivateKey::Create(test_rsa_keys_.private_test_key_3_2048_bits())); ASSERT_TRUE(private_key); // Success std::string signature; ASSERT_TRUE(private_key->GenerateSignature(message_hash, &signature)); EXPECT_OK(client_cert->VerifySignature(message, signature, VERSION_2_2)); // Failure ASSERT_EQ(256, signature.size()); ++signature[127]; EXPECT_FALSE( client_cert->VerifySignature(message, signature, VERSION_2_2).ok()); } } // namespace widevine