am eb4b7cdc: Merge "Catch null pst in OEMCrypto" into lmp-dev

* commit 'eb4b7cdc473ef8fe00f246c4e56f5ab8af0f2f1b':
  Catch null pst in OEMCrypto
This commit is contained in:
Fred Gylys-Colwell
2014-09-04 00:15:59 +00:00
committed by Android Git Automerger
5 changed files with 95 additions and 12 deletions

View File

@@ -344,6 +344,13 @@ bool SessionContext::CheckNonceOrEntry(const KeyControlBlock& key_control_block,
switch (key_control_block.control_bits() & kControlReplayMask) {
case kControlNonceRequired: // Online license. Nonce always required.
if (!CheckNonce(key_control_block.nonce())) return false;
if (pst.size() == 0) {
LOGE("KCB: PST null for kControlNonceRequired.");
return false;
}
if (!(key_control_block.control_bits() & kControlNonceEnabled)) {
LOGE("KCB: Server provided Nonce_Required but Nonce_Enabled = 0.");
}
if (!usage_entry_) {
if (ce_->usage_table()->FindEntry(pst)) {
LOGE("KCB: Cannot create duplicate entries in usage table.");
@@ -353,6 +360,13 @@ bool SessionContext::CheckNonceOrEntry(const KeyControlBlock& key_control_block,
}
break; // Offline license. Nonce required on first use.
case kControlNonceOrEntry:
if (key_control_block.control_bits() & kControlNonceEnabled) {
LOGE("KCB: Server provided NonceOrEntry but Nonce_Enabled = 1.");
}
if (pst.size() == 0) {
LOGE("KCB: PST null for kControlNonceOrEntry.");
return false;
}
if (!usage_entry_) {
usage_entry_ = ce_->usage_table()->FindEntry(pst);
if (usage_entry_) {
@@ -405,7 +419,8 @@ OEMCryptoResult SessionContext::LoadKeys(
std::vector<uint8_t> key_data_iv;
std::vector<uint8_t> key_control;
std::vector<uint8_t> key_control_iv;
std::vector<uint8_t> pstv(pst, pst + pst_length);
std::vector<uint8_t> pstv;
if (pst_length > 0) pstv.assign(pst, pst + pst_length);
for (unsigned int i = 0; i < num_keys; i++) {
key_id.assign(key_array[i].key_id,
key_array[i].key_id + key_array[i].key_id_length);

View File

@@ -318,14 +318,21 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// Later on, we use pst_length to verify the the pst is valid. This makes
// sure that we aren't given a null string but told it has postiive length.
if ((pst == NULL && pst_length > 0) || (pst != NULL && pst_length == 0)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_ONCTEXT - null pst.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
// Range check
if (!RangeCheck(message, message_length, enc_mac_keys,
2 * wvcdm::MAC_KEY_SIZE, true) ||
!RangeCheck(message, message_length, enc_mac_key_iv, wvcdm::KEY_IV_SIZE,
true) ||
!RangeCheck(message, message_length, pst, pst_length, true)) {
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE - range check.]");
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT - range check.]");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
for (unsigned int i = 0; i < num_keys; i++) {

View File

@@ -4525,9 +4525,7 @@ class DISABLED_UsageTableTest : public DISABLED_GenericDRMTest,
void LoadOfflineLicense(Session& s, const std::string& pst) {
s.open();
s.GenerateDerivedKeys();
s.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry,
s.get_nonce(), pst);
s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry, s.get_nonce(), pst);
s.EncryptAndSign();
s.LoadTestKeys(pst, new_mac_keys_);
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
@@ -4613,6 +4611,27 @@ TEST_P(DISABLED_UsageTableTest, RepeatOnlineLicense) {
}
}
// A license with non-zero replay control bits needs a valid pst..
TEST_P(DISABLED_UsageTableTest, OnlineEmptyPST) {
if (OEMCrypto_SupportsUsageTable()) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
Session s;
s.open();
s.GenerateDerivedKeys();
s.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceRequired,
s.get_nonce());
s.EncryptAndSign();
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0],
s.signature().size(), s.encrypted_license().mac_key_iv,
s.encrypted_license().mac_keys, kNumKeys, s.key_array(),
NULL, 0);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
}
}
TEST_P(DISABLED_UsageTableTest, EmptyTable) {
if (OEMCrypto_SupportsUsageTable()) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
@@ -5178,9 +5197,8 @@ TEST_P(DISABLED_UsageTableTest, BadReloadOfflineLicense) {
Session s2;
s2.open();
s2.GenerateDerivedKeys();
s2.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry,
s2.get_nonce(), pst);
s2.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry,
s2.get_nonce(), pst);
s2.EncryptAndSign();
uint8_t* pst_ptr = s2.encrypted_license().pst;
ASSERT_NE(OEMCrypto_SUCCESS,
@@ -5201,6 +5219,50 @@ TEST_P(DISABLED_UsageTableTest, BadReloadOfflineLicense) {
}
}
// An offline license should not load on the first call if the nonce is bad.
TEST_P(DISABLED_UsageTableTest, OfflineBadNonce) {
if (OEMCrypto_SupportsUsageTable()) {
std::string pst = "my_pst";
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
Session s;
s.open();
s.GenerateDerivedKeys();
s.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry,
42, pst);
s.EncryptAndSign();
uint8_t* pst_ptr = s.encrypted_license().pst;
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0],
s.signature().size(), s.encrypted_license().mac_key_iv,
s.encrypted_license().mac_keys, kNumKeys, s.key_array(),
pst_ptr, pst.length());
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
}
}
// An offline license needs a valid pst.
TEST_P(DISABLED_UsageTableTest, OfflineEmptyPST) {
if (OEMCrypto_SupportsUsageTable()) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_UpdateUsageTable());
Session s;
s.open();
s.GenerateDerivedKeys();
s.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry,
s.get_nonce());
s.EncryptAndSign();
OEMCryptoResult sts = OEMCrypto_LoadKeys(
s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0],
s.signature().size(), s.encrypted_license().mac_key_iv,
s.encrypted_license().mac_keys, kNumKeys, s.key_array(),
NULL, 0);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
s.close();
}
}
TEST_P(DISABLED_UsageTableTest, DeactivateOfflineLicense) {
if (OEMCrypto_SupportsUsageTable()) {
std::string pst = "my_pst";
@@ -5248,9 +5310,8 @@ TEST_P(DISABLED_UsageTableTest, BadRange) {
Session s;
s.open();
s.GenerateDerivedKeys();
s.FillSimpleMessage(
0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry,
s.get_nonce(), pst);
s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry,
s.get_nonce(), pst);
s.EncryptAndSign();
uint8_t* pst_ptr = s.license().pst; // Bad: not in encrypted_license.
ASSERT_NE(