Exposing the Cast Signing Algorithm

1. Exposing the Cast Signing Algorithm in cdm core.
2. Update core Cast tests to use new core CDM Cast signing API.

Bug: 279671867
Bug: 279672538
Change-Id: Ia73c4b5e6dd61edf790bca97a321881d310e7a99
This commit is contained in:
Kyle Zhang
2023-04-27 19:12:09 +00:00
committed by Robert Shih
parent 0919fb7ea6
commit 5070a7b949
10 changed files with 108 additions and 60 deletions

View File

@@ -114,11 +114,13 @@ TEST_F(CorePIGTest, OfflineHWSecureRequired) {
ASSERT_NO_FATAL_FAILURE(holder.CloseSession());
}
TEST_F(CorePIGTest, CastReceiverProvisioning) {
auto digest = wvutil::a2b_hex( // digest info header
TEST_F(CorePIGTest, CastReceiverProvisioningUsingCdm) {
std::string digest_hex_str =
// digest info header
"3021300906052b0e03021a05000414"
// sha1 of kMessage
"d2662f893aaec72f3ca6decc2aa942f3949e8b21");
"d2662f893aaec72f3ca6decc2aa942f3949e8b21";
auto digest = wvutil::a2b_hex(digest_hex_str);
if (!wvoec::global_features.cast_receiver) {
GTEST_SKIP() << "OEMCrypto does not support CAST Receiver functionality";
@@ -129,56 +131,30 @@ TEST_F(CorePIGTest, CastReceiverProvisioning) {
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));
// cdm_engine_.SignRSA
std::string signature_str;
std::string digest_str(digest.begin(), digest.end());
ASSERT_EQ(NO_ERROR, cdm_engine_.SignRSA(provisioner.wrapped_key(), digest_str,
&signature_str, kSign_PKCS1_Block1));
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));
// Verify the generated signature
std::vector<uint8_t> signature(signature_str.begin(), signature_str.end());
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());
std::unique_ptr<BIO, void (*)(BIO*)> bio(BIO_new(BIO_s_mem()), BIO_free_all);
ASSERT_NE(bio, nullptr);
ASSERT_GT(BIO_puts(bio, cert_str_ptr), 0);
X509* x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
ASSERT_GT(BIO_puts(bio.get(), cert_str_ptr), 0);
std::unique_ptr<X509, void (*)(X509*)> x509(
PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr), X509_free);
ASSERT_NE(x509, nullptr);
EVP_PKEY* pubkey = X509_get_pubkey(x509);
std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY*)> pubkey(
X509_get_pubkey(x509.get()), EVP_PKEY_free);
ASSERT_NE(pubkey, nullptr);
// remove digest info header for verification
@@ -188,27 +164,20 @@ TEST_F(CorePIGTest, CastReceiverProvisioning) {
// 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 */);
std::unique_ptr<EVP_PKEY_CTX, void (*)(EVP_PKEY_CTX*)> ctx(
EVP_PKEY_CTX_new(pubkey.get(), nullptr /* no engine */), EVP_PKEY_CTX_free);
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);
ASSERT_GT(EVP_PKEY_verify_init(ctx.get()), 0);
ASSERT_GT(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING), 0);
ASSERT_GT(EVP_PKEY_CTX_set_signature_md(ctx.get(), 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);
EXPECT_EQ(1, EVP_PKEY_verify(ctx.get(), sig, siglen, md, mdlen));
}
} // namespace wvcdm