From 4fa979b43d735915e870f69f349f21ac308dd597 Mon Sep 17 00:00:00 2001 From: Matt Feddersen Date: Tue, 16 May 2023 21:26:41 +0000 Subject: [PATCH] Fix CastReceiver unit tests Test: opk_ta, opk_ta_p40 Bug: 259454969 Merged from https://widevine-internal-review.googlesource.com/175370 Change-Id: I6cefe7fb85db539ecb066498b51525a04b8bbd51 --- .../oemcrypto/test/oec_session_util.cpp | 2 +- .../oemcrypto/test/oec_session_util.h | 1 + .../oemcrypto/test/oemcrypto_test.cpp | 112 +++++++++++++----- 3 files changed, 82 insertions(+), 33 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 040472f6..9390c0fc 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -653,7 +653,7 @@ void Provisioning40CastRoundTrip::VerifyRequestSignature( // Creates a prov2 response void Provisioning40CastRoundTrip::CreateDefaultResponse() { - uint32_t algorithm_n = htonl(kSign_RSASSA_PSS); + uint32_t algorithm_n = htonl(allowed_schemes_); memcpy(response_data_.rsa_key, "SIGN", 4); memcpy(response_data_.rsa_key + 4, &algorithm_n, 4); memcpy(response_data_.rsa_key + 8, encoded_rsa_key_.data(), diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 5980be8f..e13bb519 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -391,6 +391,7 @@ class Provisioning40CastRoundTrip // Returned const std::vector& wrapped_drm_key() { return wrapped_drm_key_; } + const std::vector& wrapped_rsa_key() { return wrapped_rsa_key_; } const std::vector& drm_public_key() { return drm_public_key_; } OEMCrypto_PrivateKeyType drm_key_type() { return drm_key_type_; } void set_allowed_schemes(uint32_t allowed_schemes) { diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 6f98ddbf..d3b70aea 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -1916,26 +1916,70 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate { // If force is true, we assert that the key loads successfully. void LoadWithAllowedSchemes(uint32_t schemes, bool force) { - Session s; - ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_); - provisioning_messages.set_allowed_schemes(schemes); - provisioning_messages.PrepareSession(keybox_); - ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest()); - ASSERT_NO_FATAL_FAILURE(provisioning_messages.CreateDefaultResponse()); - ASSERT_NO_FATAL_FAILURE(provisioning_messages.EncryptAndSignResponse()); - OEMCryptoResult sts = provisioning_messages.LoadResponse(); - key_loaded_ = (OEMCrypto_SUCCESS == sts); - if (key_loaded_) { - uint8_t* ptr = provisioning_messages.response_data().rsa_key; - size_t len = provisioning_messages.response_data().rsa_key_length; - encoded_rsa_key_ = std::vector(ptr, ptr + len); - wrapped_drm_key_ = provisioning_messages.wrapped_rsa_key(); - drm_key_type_ = OEMCrypto_RSA_Private_Key; - EXPECT_GT(wrapped_drm_key_.size(), 0u); - EXPECT_EQ(nullptr, find(wrapped_drm_key_, encoded_rsa_key_)); - } - if (force) { - EXPECT_EQ(OEMCrypto_SUCCESS, sts); + // prov 2 or prov 3 + if (global_features.provisioning_method == OEMCrypto_Keybox || + global_features.provisioning_method == OEMCrypto_OEMCertificate) { + Session s; + ProvisioningRoundTrip provisioning_messages(&s, encoded_rsa_key_); + provisioning_messages.set_allowed_schemes(schemes); + provisioning_messages.PrepareSession(keybox_); + ASSERT_NO_FATAL_FAILURE(provisioning_messages.SignAndVerifyRequest()); + ASSERT_NO_FATAL_FAILURE(provisioning_messages.CreateDefaultResponse()); + ASSERT_NO_FATAL_FAILURE(provisioning_messages.EncryptAndSignResponse()); + OEMCryptoResult sts = provisioning_messages.LoadResponse(); + key_loaded_ = (OEMCrypto_SUCCESS == sts); + if (key_loaded_) { + uint8_t* ptr = provisioning_messages.response_data().rsa_key; + size_t len = provisioning_messages.response_data().rsa_key_length; + encoded_rsa_key_ = std::vector(ptr, ptr + len); + wrapped_drm_key_ = provisioning_messages.wrapped_rsa_key(); + drm_key_type_ = OEMCrypto_RSA_Private_Key; + EXPECT_GT(wrapped_drm_key_.size(), 0u); + EXPECT_EQ(nullptr, find(wrapped_drm_key_, encoded_rsa_key_)); + } + if (force) { + EXPECT_EQ(OEMCrypto_SUCCESS, sts); + } + } else if (global_features.provisioning_method == + OEMCrypto_BootCertificateChain) { + Session s1; + ASSERT_NO_FATAL_FAILURE(s1.open()); + ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s1)); + + Session s2; + ASSERT_NO_FATAL_FAILURE(s2.open()); + ASSERT_EQ(OEMCrypto_InstallOemPrivateKey(s2.session_id(), oem_key_type_, + wrapped_oem_key_.data(), + wrapped_oem_key_.size()), + OEMCrypto_SUCCESS); + Provisioning40CastRoundTrip prov_cast(&s2, encoded_rsa_key_); + prov_cast.set_allowed_schemes(schemes); + ASSERT_NO_FATAL_FAILURE(prov_cast.PrepareSession()); + ASSERT_NO_FATAL_FAILURE(prov_cast.LoadDRMPrivateKey()); + + ASSERT_NO_FATAL_FAILURE(s2.SetPublicKeyFromSubjectPublicKey( + prov_cast.drm_key_type(), prov_cast.drm_public_key().data(), + prov_cast.drm_public_key().size())); + ASSERT_NO_FATAL_FAILURE(prov_cast.SignAndVerifyRequest()); + ASSERT_NO_FATAL_FAILURE(s2.GenerateDerivedKeysFromSessionKey()); + ASSERT_NO_FATAL_FAILURE(prov_cast.CreateDefaultResponse()); + ASSERT_NO_FATAL_FAILURE(prov_cast.EncryptAndSignResponse()); + OEMCryptoResult sts = prov_cast.LoadResponse(); + key_loaded_ = (OEMCrypto_SUCCESS == sts); + if (key_loaded_) { + uint8_t* ptr = prov_cast.response_data().rsa_key; + size_t len = prov_cast.response_data().rsa_key_length; + encoded_rsa_key_ = std::vector(ptr, ptr + len); + wrapped_drm_key_ = prov_cast.wrapped_rsa_key(); + drm_key_type_ = OEMCrypto_RSA_Private_Key; + EXPECT_GT(wrapped_drm_key_.size(), 0u); + EXPECT_EQ(nullptr, find(wrapped_drm_key_, encoded_rsa_key_)); + } + if (force) { + EXPECT_EQ(OEMCrypto_SUCCESS, sts); + } + } else { + FAIL() << "Unsupported provisioning method"; } } @@ -1945,7 +1989,8 @@ class OEMCryptoLoadsCertificateAlternates : public OEMCryptoLoadsCertificate { // The alternate padding is only required for cast receivers, but all devices // should forbid the alternate padding for regular certificates. TEST_F(OEMCryptoLoadsCertificateAlternates, DisallowForbiddenPaddingAPI09) { - LoadWithAllowedSchemes(kSign_RSASSA_PSS, true); // Use default padding scheme + LoadWithAllowedSchemes(kSign_RSASSA_PSS, + true); // Use default padding scheme DisallowForbiddenPadding(kSign_PKCS1_Block1, 50); } @@ -2103,9 +2148,11 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates { // Header of rsa key is constant. encoded_rsa_key_ = wvutil::a2b_hex( - // 0x02 0x01 0x00 == integer, size 1 byte, value = 0 (field=version) + // 0x02 0x01 0x00 == integer, size 1 byte, value = 0 + // (field=version) "020100" - // 0x30, sequence, size = d = 13 (field=pkeyalg) AlgorithmIdentifier + // 0x30, sequence, size = d = 13 (field=pkeyalg) + // AlgorithmIdentifier "300d" // 0x06 = object identifier. length = 9 // (this should be 1.2.840.113549.1.1.1) (field=algorithm) @@ -2159,7 +2206,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates { vector digest = wvutil::a2b_hex("3021300906052b0e03021a05000414"); digest.insert(digest.end(), hash, hash + SHA_DIGEST_LENGTH); - // OEMCrypto will apply the padding, and encrypt to generate the signature. + // OEMCrypto will apply the padding, and encrypt to generate the + // signature. size_t signature_length = 0; sts = OEMCrypto_GenerateRSASignature(s.session_id(), digest.data(), digest.size(), nullptr, @@ -2184,8 +2232,8 @@ class OEMCryptoCastReceiverTest : public OEMCryptoLoadsCertificateAlternates { signature.resize(signature_length); ASSERT_EQ(correct_signature, signature); - // Also verify that our verification algorithm agrees. This is not needed - // to test OEMCrypto, but it does verify that this test is valid. + // Also verify that our verification algorithm agrees. This is not + // needed to test OEMCrypto, but it does verify that this test is valid. ASSERT_NO_FATAL_FAILURE(s.VerifyRsaSignature(digest, signature.data(), signature_length, scheme)); ASSERT_NO_FATAL_FAILURE(s.VerifyRsaSignature( @@ -3376,7 +3424,8 @@ class OEMCryptoGenericCryptoKeyIdLengthTest .timer_limits.total_playback_duration_seconds = kDuration; ASSERT_NO_FATAL_FAILURE(license_messages_.CreateDefaultResponse()); SetUniformKeyIdLength(16); // Start with all key ids being 16 bytes. - // But, we are testing that the key ids do not have to have the same length. + // But, we are testing that the key ids do not have to have the same + // length. // 12 bytes (common key id length). license_messages_.SetKeyId(0, "123456789012"); license_messages_.SetKeyId(1, "12345"); // short key id. @@ -3402,11 +3451,10 @@ class OEMCryptoGenericCryptoKeyIdLengthTest ASSERT_LT(key_index, license_messages_.num_keys()); EncryptAndLoadKeys(); vector encrypted; - // To make sure OEMCrypto is not expecting the key_id to be zero padded, we - // will create a buffer that is padded with 'Z'. - // Then, we use fill the buffer with the longer of the three keys. If - // OEMCrypto is paying attention to the key id length, it should pick out - // the correct key. + // To make sure OEMCrypto is not expecting the key_id to be zero padded, + // we will create a buffer that is padded with 'Z'. Then, we use fill + // the buffer with the longer of the three keys. If OEMCrypto is paying + // attention to the key id length, it should pick out the correct key. vector key_id_buffer( session_.license().keys[kLongKeyId].key_id_length + 5, 'Z'); // Fill a bigger buffer with letter 'Z'.