|
|
|
|
@@ -20,438 +20,285 @@
|
|
|
|
|
#include "oemcrypto_session_tests_helper.h"
|
|
|
|
|
#include "oemcrypto_types.h"
|
|
|
|
|
#include "properties.h"
|
|
|
|
|
#include "scoped_ptr.h"
|
|
|
|
|
#include "string_conversions.h"
|
|
|
|
|
#include "test_base.h"
|
|
|
|
|
#include "test_printers.h"
|
|
|
|
|
#include "url_request.h"
|
|
|
|
|
#include "wv_cdm_constants.h"
|
|
|
|
|
#include "wv_cdm_types.h"
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const std::string kKeySystem = "com.widevine.alpha";
|
|
|
|
|
|
|
|
|
|
std::string g_provisioning_server;
|
|
|
|
|
std::string g_license_service_certificate;
|
|
|
|
|
std::string g_provisioning_service_certificate;
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
namespace wvcdm {
|
|
|
|
|
|
|
|
|
|
class WvGenericOperationsTest : public testing::Test,
|
|
|
|
|
public wvoec::SessionUtil {
|
|
|
|
|
class WvGenericOperationsTest : public WvCdmTestBase {
|
|
|
|
|
public:
|
|
|
|
|
WvGenericOperationsTest() : crypto_session_(NULL) {}
|
|
|
|
|
WvGenericOperationsTest()
|
|
|
|
|
: cdm_engine_(&file_system_), holder_(&cdm_engine_) {}
|
|
|
|
|
|
|
|
|
|
virtual void SetUp() {
|
|
|
|
|
::testing::Test::SetUp();
|
|
|
|
|
WvCdmTestBase::SetUp();
|
|
|
|
|
EnsureProvisioned();
|
|
|
|
|
holder_.OpenSession(config_.key_system());
|
|
|
|
|
holder_.GenerateKeyRequest(binary_key_id(), ISO_BMFF_VIDEO_MIME_TYPE);
|
|
|
|
|
holder_.CreateDefaultLicense();
|
|
|
|
|
|
|
|
|
|
ConfigTestEnv config(kContentProtectionStagingLicense);
|
|
|
|
|
Properties::set_provisioning_messages_are_binary(false);
|
|
|
|
|
ency_id_ = "ency";
|
|
|
|
|
StripeBuffer(&ency_key_, KEY_SIZE, 'e');
|
|
|
|
|
AddOneKey(ency_id_, ency_key_, wvoec::kControlAllowEncrypt);
|
|
|
|
|
dency_id_ = "dency";
|
|
|
|
|
StripeBuffer(&dency_key_, KEY_SIZE, 'd');
|
|
|
|
|
AddOneKey(dency_id_, dency_key_, wvoec::kControlAllowDecrypt);
|
|
|
|
|
siggy_id_ = "siggy";
|
|
|
|
|
StripeBuffer(&siggy_key_, MAC_KEY_SIZE, 's');
|
|
|
|
|
AddOneKey(siggy_id_, siggy_key_, wvoec::kControlAllowSign);
|
|
|
|
|
vou_id_ = "vou";
|
|
|
|
|
StripeBuffer(&vou_key_, MAC_KEY_SIZE, 'v');
|
|
|
|
|
AddOneKey(vou_id_, vou_key_, wvoec::kControlAllowVerify);
|
|
|
|
|
|
|
|
|
|
g_provisioning_service_certificate.assign(
|
|
|
|
|
config.provisioning_service_certificate());
|
|
|
|
|
g_license_service_certificate.assign(config.license_service_certificate());
|
|
|
|
|
g_provisioning_server.assign(config.provisioning_server());
|
|
|
|
|
StripeBuffer(&in_vector_, KEY_SIZE * 15, '1');
|
|
|
|
|
in_buffer_ = std::string(in_vector_.begin(), in_vector_.end());
|
|
|
|
|
|
|
|
|
|
// Ensure that OEMCrypto has a test keybox if needed.
|
|
|
|
|
EnsureTestKeys();
|
|
|
|
|
|
|
|
|
|
// Perform CdmEngine setup
|
|
|
|
|
cdm_engine_.reset(new CdmEngine(&file_system_));
|
|
|
|
|
|
|
|
|
|
Provision();
|
|
|
|
|
|
|
|
|
|
CdmResponseType status =
|
|
|
|
|
cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_);
|
|
|
|
|
if (status == NEED_PROVISIONING) {
|
|
|
|
|
Provision();
|
|
|
|
|
status = cdm_engine_->OpenSession(kKeySystem, NULL, NULL, &session_id_);
|
|
|
|
|
}
|
|
|
|
|
ASSERT_EQ(NO_ERROR, status);
|
|
|
|
|
ASSERT_NE("", session_id_) << "Could not open CDM session.";
|
|
|
|
|
ASSERT_TRUE(cdm_engine_->IsOpenSession(session_id_));
|
|
|
|
|
|
|
|
|
|
// Get OEMCrypto session ID from the CDM
|
|
|
|
|
CdmQueryMap query;
|
|
|
|
|
cdm_engine_->QueryOemCryptoSessionId(session_id_, &query);
|
|
|
|
|
std::istringstream parse_int;
|
|
|
|
|
parse_int.str(query[QUERY_KEY_OEMCRYPTO_SESSION_ID]);
|
|
|
|
|
parse_int >> oec_session_id_;
|
|
|
|
|
|
|
|
|
|
// Construct and install keys into the CDM's OEMCrypto session.
|
|
|
|
|
OecSessionSetup(oec_session_id_);
|
|
|
|
|
EncryptAndLoadKeys();
|
|
|
|
|
StripeBuffer(&iv_vector_, KEY_SIZE, 'a');
|
|
|
|
|
iv_ = std::string(iv_vector_.begin(), iv_vector_.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void TearDown() {
|
|
|
|
|
oec_util_session_.close();
|
|
|
|
|
if (cdm_engine_.get() != NULL) {
|
|
|
|
|
cdm_engine_->CloseSession(session_id_);
|
|
|
|
|
}
|
|
|
|
|
// OEMCrypto_Terminate() will be performed during the test class's
|
|
|
|
|
// destruction (specifically by the CryptoSession destructor)
|
|
|
|
|
}
|
|
|
|
|
virtual void TearDown() { holder_.CloseSession(); }
|
|
|
|
|
|
|
|
|
|
void OecSessionSetup(uint32_t oec_session_id) {
|
|
|
|
|
buffer_size_ = 160;
|
|
|
|
|
oec_util_session_.SetSessionId(oec_session_id);
|
|
|
|
|
// TODO(fredgc or gmorgan): This should be updated for provisioning 3.0
|
|
|
|
|
oec_util_session_.GenerateDerivedKeysFromKeybox();
|
|
|
|
|
MakeFourKeys();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum GenericKeyType {
|
|
|
|
|
kGenericEncrypt = 0,
|
|
|
|
|
kGenericDecrypt = 1,
|
|
|
|
|
kGenericSign = 2,
|
|
|
|
|
kGenericVerify = 3
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
virtual void MakeFourKeys(
|
|
|
|
|
uint32_t duration = wvoec::kDuration, uint32_t control = 0,
|
|
|
|
|
uint32_t nonce = 0, const std::string& pst = "") {
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
|
|
|
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
|
|
|
|
|
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowEncrypt);
|
|
|
|
|
oec_util_session_.license().keys[kGenericDecrypt].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowDecrypt);
|
|
|
|
|
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowSign);
|
|
|
|
|
oec_util_session_.license().keys[kGenericVerify].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowVerify);
|
|
|
|
|
|
|
|
|
|
oec_util_session_.license().keys[kGenericSign].key_data_length =
|
|
|
|
|
wvcdm::MAC_KEY_SIZE;
|
|
|
|
|
oec_util_session_.license().keys[kGenericVerify].key_data_length =
|
|
|
|
|
wvcdm::MAC_KEY_SIZE;
|
|
|
|
|
|
|
|
|
|
clear_buffer_.assign(buffer_size_, 0);
|
|
|
|
|
for (size_t i = 0; i < clear_buffer_.size(); i++) {
|
|
|
|
|
clear_buffer_[i] = 1 + i % 250;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < wvcdm::KEY_IV_SIZE; i++) {
|
|
|
|
|
iv_[i] = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GetKeyId(GenericKeyType type) {
|
|
|
|
|
std::string key_id;
|
|
|
|
|
size_t key_id_length = oec_util_session_.license().keys[0].key_id_length;
|
|
|
|
|
key_id.assign(
|
|
|
|
|
&(oec_util_session_.license().keys[type].key_id[0]),
|
|
|
|
|
&(oec_util_session_.license().keys[type].key_id[key_id_length]));
|
|
|
|
|
return key_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GetClearBuffer() {
|
|
|
|
|
std::string buffer;
|
|
|
|
|
size_t buffer_length = clear_buffer_.size();
|
|
|
|
|
buffer.assign(&clear_buffer_[0], &clear_buffer_[buffer_length]);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GetEncryptedBuffer() {
|
|
|
|
|
std::string buffer;
|
|
|
|
|
size_t buffer_length = encrypted_buffer_.size();
|
|
|
|
|
buffer.assign(&encrypted_buffer_[0], &encrypted_buffer_[buffer_length]);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GetIvBlock() {
|
|
|
|
|
std::string buffer;
|
|
|
|
|
size_t buffer_length = wvcdm::KEY_IV_SIZE;
|
|
|
|
|
buffer.assign(&iv_[0], &iv_[buffer_length]);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string GetSignatureBuffer() {
|
|
|
|
|
std::string buffer;
|
|
|
|
|
buffer.resize(SHA256_DIGEST_LENGTH);
|
|
|
|
|
return buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EncryptAndLoadKeys() {
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(oec_util_session_.EncryptAndSign());
|
|
|
|
|
oec_util_session_.LoadTestKeys();
|
|
|
|
|
// Create a single key, and add it to the license.
|
|
|
|
|
void AddOneKey(const KeyId& key_id, const std::vector<uint8_t>& key_data,
|
|
|
|
|
uint32_t key_control_block) {
|
|
|
|
|
wvoec::KeyControlBlock block = {};
|
|
|
|
|
block.control_bits = htonl(key_control_block);
|
|
|
|
|
holder_.AddKey(key_id, key_data, block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
virtual void Provision() {
|
|
|
|
|
LOGE("WvGenericOperationsTest::Provision: url=%s",
|
|
|
|
|
g_provisioning_server.c_str());
|
|
|
|
|
CdmProvisioningRequest prov_request;
|
|
|
|
|
std::string provisioning_server_url;
|
|
|
|
|
CdmCertificateType cert_type = kCertificateWidevine;
|
|
|
|
|
std::string cert_authority;
|
|
|
|
|
std::string cert, wrapped_key;
|
|
|
|
|
ASSERT_EQ(NO_ERROR, cdm_engine_->SetServiceCertificate(
|
|
|
|
|
g_provisioning_service_certificate));
|
|
|
|
|
ASSERT_EQ(NO_ERROR, cdm_engine_->GetProvisioningRequest(
|
|
|
|
|
cert_type, cert_authority, &prov_request,
|
|
|
|
|
&provisioning_server_url));
|
|
|
|
|
|
|
|
|
|
LOGV("WvGenericOperationsTest::Provision: req=%s", prov_request.c_str());
|
|
|
|
|
|
|
|
|
|
// Ignore URL provided by CdmEngine. Use ours, as configured
|
|
|
|
|
// for test vs. production server.
|
|
|
|
|
provisioning_server_url.assign(g_provisioning_server);
|
|
|
|
|
UrlRequest url_request(provisioning_server_url);
|
|
|
|
|
EXPECT_TRUE(url_request.is_connected());
|
|
|
|
|
url_request.PostCertRequestInQueryString(prov_request);
|
|
|
|
|
std::string http_message;
|
|
|
|
|
bool ok = url_request.GetResponse(&http_message);
|
|
|
|
|
EXPECT_TRUE(ok);
|
|
|
|
|
|
|
|
|
|
LOGV("WvGenericOperationsTest::Provision: http_message: \n%s\n",
|
|
|
|
|
http_message.c_str());
|
|
|
|
|
|
|
|
|
|
ASSERT_EQ(NO_ERROR,
|
|
|
|
|
cdm_engine_->HandleProvisioningResponse(http_message,
|
|
|
|
|
&cert, &wrapped_key));
|
|
|
|
|
ASSERT_EQ(NO_ERROR,
|
|
|
|
|
cdm_engine_->SetServiceCertificate(g_license_service_certificate));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This CryptoSession object handles Initialization and Termination
|
|
|
|
|
// calls on OEMCrypto for the duration of the test. CryptoSessions
|
|
|
|
|
// created by the CDM will share the OEMCrypto state of this CryptoSession,
|
|
|
|
|
// including, for example, a test keybox.
|
|
|
|
|
CryptoSession crypto_session_;
|
|
|
|
|
|
|
|
|
|
FileSystem file_system_;
|
|
|
|
|
std::unique_ptr<CdmEngine> cdm_engine_;
|
|
|
|
|
std::string key_msg_;
|
|
|
|
|
std::string session_id_;
|
|
|
|
|
std::string server_url_;
|
|
|
|
|
uint32_t oec_session_id_;
|
|
|
|
|
wvoec::Session oec_util_session_;
|
|
|
|
|
size_t buffer_size_;
|
|
|
|
|
vector<uint8_t> clear_buffer_;
|
|
|
|
|
vector<uint8_t> encrypted_buffer_;
|
|
|
|
|
uint8_t iv_[wvcdm::KEY_IV_SIZE];
|
|
|
|
|
CdmEngine cdm_engine_;
|
|
|
|
|
TestLicenseHolder holder_;
|
|
|
|
|
|
|
|
|
|
KeyId ency_id_;
|
|
|
|
|
KeyId dency_id_;
|
|
|
|
|
KeyId siggy_id_;
|
|
|
|
|
KeyId vou_id_;
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> ency_key_;
|
|
|
|
|
std::vector<uint8_t> dency_key_;
|
|
|
|
|
std::vector<uint8_t> siggy_key_;
|
|
|
|
|
std::vector<uint8_t> vou_key_;
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> in_vector_;
|
|
|
|
|
std::vector<uint8_t> iv_vector_;
|
|
|
|
|
std::string in_buffer_;
|
|
|
|
|
std::string iv_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, NormalSessionOpenClose) {
|
|
|
|
|
wvoec::Session s;
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(s.close());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenerateSessionKeys) {
|
|
|
|
|
wvoec::Session s;
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(s.open());
|
|
|
|
|
// TODO(fredgc or gmorgan): This should be updated for provisioning 3.0
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(s.GenerateDerivedKeysFromKeybox());
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(s.close());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptNoKey) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string out_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
|
|
|
|
|
// No key
|
|
|
|
|
KeyId key_id("xyz");
|
|
|
|
|
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_CONTENT_KEY_3, cdm_sts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptKeyNotAllowed) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string out_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
|
|
|
|
|
// Wrong key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericDecrypt);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&out_buffer);
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
TEST_F(WvGenericOperationsTest, LoadSpecialKeys) {
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptGood) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string out_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
std::string encrypted = Aes128CbcEncrypt(ency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
|
|
|
|
|
// Good key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericEncrypt);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericEncrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, ency_id_, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericEncrypt(session_id_, in_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(encrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericDecryptKeyNotAllowed) {
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptNoKey) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string out_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
std::string encrypted = Aes128CbcEncrypt(ency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
KeyId key_id("no_key");
|
|
|
|
|
|
|
|
|
|
// Wrong key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericEncrypt);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericEncrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_CONTENT_KEY_3, cdm_sts);
|
|
|
|
|
EXPECT_NE(encrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericDecrypt(session_id_, in_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&out_buffer);
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptKeyNotAllowed) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
// Trying to use Decrypt key to encrypt, which is not allowed.
|
|
|
|
|
KeyId key_id = dency_id_;
|
|
|
|
|
std::string encrypted = Aes128CbcEncrypt(dency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericEncrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_NE(encrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericDecryptGood) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string out_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
std::string decrypted = Aes128CbcDecrypt(dency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
|
|
|
|
|
// Good key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericDecrypt);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericDecrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, dency_id_, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericDecrypt(session_id_, in_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(decrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericDecryptNoKey) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string decrypted = Aes128CbcDecrypt(dency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
KeyId key_id = "no_key";
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericDecrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_CONTENT_KEY_3, cdm_sts);
|
|
|
|
|
EXPECT_NE(decrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericDecryptKeyNotAllowed) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
// Trying to use Encrypt key to decrypt, which is not allowed.
|
|
|
|
|
KeyId key_id = ency_id_;
|
|
|
|
|
std::string decrypted = Aes128CbcDecrypt(ency_key_, in_vector_, iv_vector_);
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericDecrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_NE(decrypted, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericSignKeyNotAllowed) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string signature_buffer;
|
|
|
|
|
|
|
|
|
|
// Wrong key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericVerify);
|
|
|
|
|
std::string key_id = vou_id_;
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
std::string signature = SignHMAC(in_buffer_, siggy_key_);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
&signature_buffer);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts =
|
|
|
|
|
cdm_engine_.GenericSign(holder_.session_id(), in_buffer_, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256, &out_buffer);
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_NE(signature, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericSignGood) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string signature_buffer;
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
std::string signature = SignHMAC(in_buffer_, siggy_key_);
|
|
|
|
|
|
|
|
|
|
// Good key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericSign);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
&signature_buffer);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts =
|
|
|
|
|
cdm_engine_.GenericSign(holder_.session_id(), in_buffer_, siggy_id_,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256, &out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(signature, out_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericVerifyKeyNotAllowed) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string signature_buffer = GetSignatureBuffer();
|
|
|
|
|
|
|
|
|
|
// Wrong key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericSign);
|
|
|
|
|
std::string key_id = siggy_id_;
|
|
|
|
|
std::string signature = SignHMAC(in_buffer_, siggy_key_);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericVerify(holder_.session_id(), in_buffer_, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
signature_buffer);
|
|
|
|
|
signature);
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericVerifyBadSignautre) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string signature(MAC_KEY_SIZE, 's');
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts = cdm_engine_.GenericVerify(
|
|
|
|
|
holder_.session_id(), in_buffer_, vou_id_,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256, signature);
|
|
|
|
|
// OEMCrypto error is OEMCrypto_ERROR_SIGNATURE_FAILURE
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericVerifyGood) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string signature_buffer = GetSignatureBuffer();
|
|
|
|
|
std::string signature = SignHMAC(in_buffer_, vou_key_);
|
|
|
|
|
|
|
|
|
|
// Good key - signature not set.
|
|
|
|
|
std::string key_id = GetKeyId(kGenericVerify);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
signature_buffer);
|
|
|
|
|
// OEMCrypto error is OEMCrypto_ERROR_SIGNATURE_FAILURE
|
|
|
|
|
EXPECT_EQ(UNKNOWN_ERROR, cdm_sts);
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
cdm_sts =
|
|
|
|
|
cdm_engine_.GenericVerify(holder_.session_id(), in_buffer_, vou_id_,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256, signature);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class WvGenericOperationsDataTest : public WvGenericOperationsTest {
|
|
|
|
|
public:
|
|
|
|
|
// Construct keys for encrypt/decrypt and for sign/verify
|
|
|
|
|
virtual void MakeFourKeys(
|
|
|
|
|
uint32_t duration = wvoec::kDuration, uint32_t control = 0,
|
|
|
|
|
uint32_t nonce = 0, const std::string& pst = "") {
|
|
|
|
|
ASSERT_NO_FATAL_FAILURE(
|
|
|
|
|
oec_util_session_.FillSimpleMessage(duration, control, nonce, pst));
|
|
|
|
|
oec_util_session_.license().keys[kGenericEncrypt].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowEncrypt |
|
|
|
|
|
wvoec::kControlAllowDecrypt);
|
|
|
|
|
oec_util_session_.license().keys[kGenericSign].control.control_bits |=
|
|
|
|
|
htonl(wvoec::kControlAllowSign | wvoec::kControlAllowVerify);
|
|
|
|
|
|
|
|
|
|
oec_util_session_.license().keys[kGenericSign].key_data_length =
|
|
|
|
|
wvcdm::MAC_KEY_SIZE;
|
|
|
|
|
|
|
|
|
|
clear_buffer_.assign(buffer_size_, 0);
|
|
|
|
|
for (size_t i = 0; i < clear_buffer_.size(); i++) {
|
|
|
|
|
clear_buffer_[i] = 1 + i % 250;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < wvcdm::KEY_IV_SIZE; i++) {
|
|
|
|
|
iv_[i] = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsDataTest, GenericEncryptDecrypt) {
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericEncryptDecrypt) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string encrypted_buffer = GetEncryptedBuffer();
|
|
|
|
|
std::string iv = GetIvBlock();
|
|
|
|
|
std::string out_buffer;
|
|
|
|
|
std::string clear_buffer;
|
|
|
|
|
|
|
|
|
|
// Encrypt
|
|
|
|
|
std::string key_id = GetKeyId(kGenericEncrypt);
|
|
|
|
|
KeyId key_id = "enc and dec";
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericEncrypt(
|
|
|
|
|
session_id_, in_buffer, key_id, iv, wvcdm::kEncryptionAlgorithmAesCbc128,
|
|
|
|
|
&encrypted_buffer);
|
|
|
|
|
std::vector<uint8_t> key_data;
|
|
|
|
|
StripeBuffer(&key_data, KEY_SIZE, '3');
|
|
|
|
|
AddOneKey(key_id, key_data,
|
|
|
|
|
wvoec::kControlAllowEncrypt | wvoec::kControlAllowDecrypt);
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_.GenericEncrypt(
|
|
|
|
|
holder_.session_id(), in_buffer_, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &out_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
|
|
|
|
|
// Decrypt, use same key as encrypt.
|
|
|
|
|
key_id = GetKeyId(kGenericEncrypt);
|
|
|
|
|
|
|
|
|
|
std::string final_buffer;
|
|
|
|
|
final_buffer.resize(in_buffer.size());
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_->GenericDecrypt(
|
|
|
|
|
session_id_, encrypted_buffer, key_id, iv,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &final_buffer);
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_.GenericDecrypt(
|
|
|
|
|
holder_.session_id(), out_buffer, key_id, iv_,
|
|
|
|
|
wvcdm::kEncryptionAlgorithmAesCbc128, &clear_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(0, in_buffer.compare(final_buffer));
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(in_buffer_, clear_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(WvGenericOperationsDataTest, GenericSignVerify) {
|
|
|
|
|
TEST_F(WvGenericOperationsTest, GenericSignVerify) {
|
|
|
|
|
CdmResponseType cdm_sts;
|
|
|
|
|
std::string in_buffer = GetClearBuffer();
|
|
|
|
|
std::string signature_buffer = GetSignatureBuffer();
|
|
|
|
|
std::string signature_buffer;
|
|
|
|
|
|
|
|
|
|
// Signing key
|
|
|
|
|
std::string key_id = GetKeyId(kGenericSign);
|
|
|
|
|
cdm_sts = cdm_engine_->GenericSign(session_id_, in_buffer, key_id,
|
|
|
|
|
KeyId key_id = "sign and ver";
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> key_data;
|
|
|
|
|
StripeBuffer(&key_data, MAC_KEY_SIZE, '4');
|
|
|
|
|
AddOneKey(key_id, key_data,
|
|
|
|
|
wvoec::kControlAllowSign | wvoec::kControlAllowVerify);
|
|
|
|
|
std::string signature = SignHMAC(in_buffer_, key_data);
|
|
|
|
|
|
|
|
|
|
holder_.SignAndLoadLicense();
|
|
|
|
|
|
|
|
|
|
cdm_sts = cdm_engine_.GenericSign(holder_.session_id(), in_buffer_, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
&signature_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(MAC_KEY_SIZE, signature_buffer.size());
|
|
|
|
|
|
|
|
|
|
// Verify signature, use same key as sign.
|
|
|
|
|
key_id = GetKeyId(kGenericSign);
|
|
|
|
|
cdm_sts = cdm_engine_->GenericVerify(session_id_, in_buffer, key_id,
|
|
|
|
|
cdm_sts = cdm_engine_.GenericVerify(holder_.session_id(), in_buffer_, key_id,
|
|
|
|
|
wvcdm::kSigningAlgorithmHmacSha256,
|
|
|
|
|
signature_buffer);
|
|
|
|
|
EXPECT_EQ(NO_ERROR, cdm_sts);
|
|
|
|
|
EXPECT_EQ(signature, signature_buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace wvcdm
|
|
|
|
|
|