Cast Receiver integration test
Merge from Widevine repo of http://go/wvgerrit/169471 Remove the test in android tests and add it to the core tests. Bug: 276464340 Test: GTEST_FILTER="CorePIGTest.CastReceiverProvisioning*" jenkins/run_fake_l1_tests Change-Id: Icd280b532ddae274f66b2fab3e65520e96adb7cb
This commit is contained in:
committed by
Kyle Zhang
parent
836b1a30a6
commit
d211195f92
@@ -6,6 +6,9 @@
|
||||
// would do. They verify that policies specified on UAT are honored on the
|
||||
// device.
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -16,9 +19,9 @@
|
||||
#include "license_holder.h"
|
||||
#include "log.h"
|
||||
#include "oec_device_features.h"
|
||||
#include "provisioning_holder.h"
|
||||
#include "test_base.h"
|
||||
#include "test_printers.h"
|
||||
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -111,4 +114,101 @@ TEST_F(CorePIGTest, OfflineHWSecureRequired) {
|
||||
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
|
||||
}
|
||||
|
||||
TEST_F(CorePIGTest, CastReceiverProvisioning) {
|
||||
auto digest = wvutil::a2b_hex( // digest info header
|
||||
"3021300906052b0e03021a05000414"
|
||||
// sha1 of kMessage
|
||||
"d2662f893aaec72f3ca6decc2aa942f3949e8b21");
|
||||
|
||||
if (!wvoec::global_features.cast_receiver) {
|
||||
GTEST_SKIP() << "OEMCrypto does not support CAST Receiver functionality";
|
||||
}
|
||||
|
||||
// Provision x509 cert for CAST Receiver.
|
||||
ProvisioningHolder provisioner(&cdm_engine_, config_.provisioning_server(),
|
||||
config_.provisioning_service_certificate());
|
||||
provisioner.Provision(kCertificateX509, binary_provisioning_);
|
||||
|
||||
// cdm_engine_.OpenSession here is to load test keybox
|
||||
// in order to successfully OEMCrypto_LoadDRMPrivateKey
|
||||
std::string session_id;
|
||||
CdmResponseType status = cdm_engine_.OpenSession(
|
||||
config_.key_system(), nullptr, nullptr, &session_id);
|
||||
ASSERT_EQ(NO_ERROR, status);
|
||||
ASSERT_TRUE(cdm_engine_.IsOpenSession(session_id));
|
||||
|
||||
std::string wrapped_key_str = provisioner.wrapped_key();
|
||||
std::vector<uint8_t> wrapped_key(wrapped_key_str.begin(),
|
||||
wrapped_key_str.end());
|
||||
OEMCrypto_SESSION oemcrypto_session;
|
||||
OEMCryptoResult sts =
|
||||
OEMCrypto_OpenSession(&oemcrypto_session, kLevelDefault);
|
||||
if (sts != OEMCrypto_SUCCESS) {
|
||||
LOGE("Fail in OEMCrypto_OpenSession");
|
||||
}
|
||||
|
||||
// Stop test when OEMCrypto_LoadDRMPrivateKey fails.
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadDRMPrivateKey(
|
||||
oemcrypto_session, OEMCrypto_RSA_Private_Key,
|
||||
wrapped_key.data(), wrapped_key.size()));
|
||||
|
||||
// Generate signature for the digest
|
||||
size_t signatureSize = 0;
|
||||
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
||||
OEMCrypto_GenerateRSASignature(oemcrypto_session, digest.data(),
|
||||
digest.size(), nullptr,
|
||||
&signatureSize, kSign_PKCS1_Block1));
|
||||
std::vector<uint8_t> signature;
|
||||
signature.resize(signatureSize);
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS,
|
||||
OEMCrypto_GenerateRSASignature(oemcrypto_session, digest.data(),
|
||||
digest.size(), signature.data(),
|
||||
&signatureSize, kSign_PKCS1_Block1));
|
||||
LOGI("digest.size(): %zu, signature.size(): %zu", digest.size(),
|
||||
signature.size());
|
||||
|
||||
// Verify the generated signature
|
||||
std::string cert = provisioner.certificate();
|
||||
const char* cert_str_ptr = cert.c_str();
|
||||
LOGI("cert: %s", cert_str_ptr);
|
||||
|
||||
// Extract the public key from the x509 cert chain
|
||||
BIO* bio = BIO_new(BIO_s_mem());
|
||||
ASSERT_NE(bio, nullptr);
|
||||
ASSERT_GT(BIO_puts(bio, cert_str_ptr), 0);
|
||||
X509* x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
||||
ASSERT_NE(x509, nullptr);
|
||||
EVP_PKEY* pubkey = X509_get_pubkey(x509);
|
||||
ASSERT_NE(pubkey, nullptr);
|
||||
|
||||
// remove digest info header for verification
|
||||
// SHA1 is 20 bytes long
|
||||
digest.erase(digest.begin(), digest.begin() + digest.size() - 20);
|
||||
|
||||
// Modified from openssl example
|
||||
// https://www.openssl.org/docs/man3.0/man3/EVP_PKEY_verify_init.html
|
||||
// Set RSA padding as RSA_PKCS1_PADDING and digest algo to SHA1.
|
||||
EVP_PKEY_CTX* ctx;
|
||||
unsigned char* md = digest.data();
|
||||
unsigned char* sig = signature.data();
|
||||
size_t mdlen = digest.size();
|
||||
size_t siglen = signature.size();
|
||||
|
||||
ctx = EVP_PKEY_CTX_new(pubkey, nullptr /* no engine */);
|
||||
ASSERT_NE(ctx, nullptr);
|
||||
ASSERT_GT(EVP_PKEY_verify_init(ctx), 0);
|
||||
ASSERT_GT(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), 0);
|
||||
ASSERT_GT(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha1()), 0);
|
||||
|
||||
/* Perform operation */
|
||||
EXPECT_EQ(1, EVP_PKEY_verify(ctx, sig, siglen, md, mdlen));
|
||||
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(pubkey);
|
||||
BIO_free(bio);
|
||||
X509_free(x509);
|
||||
|
||||
OEMCrypto_CloseSession(oemcrypto_session);
|
||||
cdm_engine_.CloseSession(session_id);
|
||||
}
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -20,6 +20,8 @@ class ProvisioningHolder {
|
||||
provisioning_server_url_(provisioning_server_url),
|
||||
provisioning_service_certificate_(provisioning_service_certificate) {}
|
||||
void Provision(CdmCertificateType cert_type, bool binary_provisioning);
|
||||
std::string certificate() const { return certificate_; }
|
||||
std::string wrapped_key() const { return wrapped_key_; }
|
||||
|
||||
protected:
|
||||
TestCdmEngine* cdm_engine_;
|
||||
|
||||
@@ -88,6 +88,7 @@ class TestCdmEngine : public CdmEngine {
|
||||
TestCdmEngine(wvutil::FileSystem* file_system,
|
||||
std::shared_ptr<metrics::EngineMetrics> metrics)
|
||||
: CdmEngine(file_system, metrics) {}
|
||||
const CdmSession* GetCdmSession(std::string sessionId) const;
|
||||
};
|
||||
|
||||
class WvCdmTestBaseWithEngine : public WvCdmTestBase {
|
||||
|
||||
@@ -2534,33 +2534,6 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningInterspersedRetryTest) {
|
||||
decryptor_->CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, DISABLED_X509ProvisioningTest) {
|
||||
decryptor_->OpenSession(config_.key_system(), nullptr, kDefaultCdmIdentifier,
|
||||
nullptr, &session_id_);
|
||||
std::string provisioning_server;
|
||||
CdmCertificateType cert_type = kCertificateX509;
|
||||
// TODO(rfrias): insert appropriate CA here
|
||||
std::string cert_authority = "cast.google.com";
|
||||
std::string cert, wrapped_key;
|
||||
|
||||
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||
decryptor_->GetProvisioningRequest(
|
||||
cert_type, cert_authority, kDefaultCdmIdentifier,
|
||||
kEmptyServiceCertificate, kLevelDefault, &key_msg_,
|
||||
&provisioning_server));
|
||||
EXPECT_THAT(provisioning_server,
|
||||
IsSimilarUrlTo(kDefaultProvisioningServerUrl));
|
||||
|
||||
std::string response = GetCertRequestResponse(config_.provisioning_server());
|
||||
EXPECT_NE(0, static_cast<int>(response.size()));
|
||||
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->HandleProvisioningResponse(
|
||||
kDefaultCdmIdentifier, response, kLevelDefault,
|
||||
&cert, &wrapped_key));
|
||||
EXPECT_NE(0, static_cast<int>(cert.size()));
|
||||
EXPECT_NE(0, static_cast<int>(wrapped_key.size()));
|
||||
decryptor_->CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, ProvisioningSpoidTest) {
|
||||
CdmProvisioningResponse provisioning_response;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user