Merge "Correct request_license_test failures"
This commit is contained in:
@@ -10,7 +10,9 @@ class ContentKeySession : public KeySession {
|
|||||||
public:
|
public:
|
||||||
ContentKeySession(CryptoSessionId oec_session_id,
|
ContentKeySession(CryptoSessionId oec_session_id,
|
||||||
metrics::CryptoMetrics* metrics)
|
metrics::CryptoMetrics* metrics)
|
||||||
: KeySession(metrics), oec_session_id_(oec_session_id) {}
|
: KeySession(metrics),
|
||||||
|
oec_session_id_(oec_session_id),
|
||||||
|
cipher_mode_(kCipherModeCtr) {}
|
||||||
virtual ~ContentKeySession() {}
|
virtual ~ContentKeySession() {}
|
||||||
|
|
||||||
KeySessionType Type() { return kDefault; }
|
KeySessionType Type() { return kDefault; }
|
||||||
@@ -32,7 +34,7 @@ class ContentKeySession : public KeySession {
|
|||||||
CdmCipherMode* cipher_mode,
|
CdmCipherMode* cipher_mode,
|
||||||
const std::string& srm_requirement);
|
const std::string& srm_requirement);
|
||||||
|
|
||||||
OEMCryptoResult LoadEntitledContentKeys(const std::vector<CryptoKey>& keys) {
|
OEMCryptoResult LoadEntitledContentKeys(const std::vector<CryptoKey>&) {
|
||||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +58,7 @@ class ContentKeySession : public KeySession {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
KeyId cached_key_id_;
|
KeyId cached_key_id_;
|
||||||
|
CdmCipherMode cipher_mode_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ void GenerateMacContext(const std::string& input_context,
|
|||||||
void GenerateEncryptContext(const std::string& input_context,
|
void GenerateEncryptContext(const std::string& input_context,
|
||||||
std::string* deriv_context);
|
std::string* deriv_context);
|
||||||
size_t GetOffset(std::string message, std::string field);
|
size_t GetOffset(std::string message, std::string field);
|
||||||
|
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode);
|
||||||
|
|
||||||
class CryptoSession {
|
class CryptoSession {
|
||||||
public:
|
public:
|
||||||
@@ -272,8 +273,6 @@ class CryptoSession {
|
|||||||
bool is_destination_buffer_type_valid_;
|
bool is_destination_buffer_type_valid_;
|
||||||
SecurityLevel requested_security_level_;
|
SecurityLevel requested_security_level_;
|
||||||
|
|
||||||
KeyId cached_key_id_;
|
|
||||||
|
|
||||||
bool is_usage_support_type_valid_;
|
bool is_usage_support_type_valid_;
|
||||||
CdmUsageSupportType usage_support_type_;
|
CdmUsageSupportType usage_support_type_;
|
||||||
UsageTableHeader* usage_table_header_;
|
UsageTableHeader* usage_table_header_;
|
||||||
@@ -284,6 +283,7 @@ class CryptoSession {
|
|||||||
static uint64_t request_id_index_;
|
static uint64_t request_id_index_;
|
||||||
|
|
||||||
CdmCipherMode cipher_mode_;
|
CdmCipherMode cipher_mode_;
|
||||||
|
uint32_t api_version_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,12 +74,14 @@ OEMCryptoResult ContentKeySession::LoadKeys(
|
|||||||
OEMCryptoResult ContentKeySession::SelectKey(const std::string& key_id,
|
OEMCryptoResult ContentKeySession::SelectKey(const std::string& key_id,
|
||||||
CdmCipherMode cipher_mode) {
|
CdmCipherMode cipher_mode) {
|
||||||
// Crypto session lock already locked.
|
// Crypto session lock already locked.
|
||||||
if (!cached_key_id_.empty() && cached_key_id_ == key_id) {
|
if (!cached_key_id_.empty() && cached_key_id_ == key_id &&
|
||||||
// Already using the desired key.
|
cipher_mode_ == cipher_mode) {
|
||||||
|
// Already using the desired key and cipher mode.
|
||||||
return OEMCrypto_SUCCESS;
|
return OEMCrypto_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_key_id_ = key_id;
|
cached_key_id_ = key_id;
|
||||||
|
cipher_mode_ = cipher_mode;
|
||||||
|
|
||||||
const uint8_t* key_id_string =
|
const uint8_t* key_id_string =
|
||||||
reinterpret_cast<const uint8_t*>(cached_key_id_.data());
|
reinterpret_cast<const uint8_t*>(cached_key_id_.data());
|
||||||
@@ -87,7 +89,7 @@ OEMCryptoResult ContentKeySession::SelectKey(const std::string& key_id,
|
|||||||
OEMCryptoResult sts;
|
OEMCryptoResult sts;
|
||||||
M_TIME(sts = OEMCrypto_SelectKey(
|
M_TIME(sts = OEMCrypto_SelectKey(
|
||||||
oec_session_id_, key_id_string, cached_key_id_.size(),
|
oec_session_id_, key_id_string, cached_key_id_.size(),
|
||||||
static_cast<OEMCryptoCipherMode>(cipher_mode)),
|
ToOEMCryptoCipherMode(cipher_mode)),
|
||||||
metrics_, oemcrypto_select_key_, sts);
|
metrics_, oemcrypto_select_key_, sts);
|
||||||
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
@@ -120,16 +122,17 @@ OEMCryptoResult ContentKeySession::LoadKeys(
|
|||||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||||
const uint8_t* enc_mac_key = NULL;
|
const uint8_t* enc_mac_key = NULL;
|
||||||
const uint8_t* enc_mac_key_iv = NULL;
|
const uint8_t* enc_mac_key_iv = NULL;
|
||||||
|
cached_key_id_.clear();
|
||||||
if (mac_key.size() >= MAC_KEY_SIZE && mac_key_iv.size() >= KEY_IV_SIZE) {
|
if (mac_key.size() >= MAC_KEY_SIZE && mac_key_iv.size() >= KEY_IV_SIZE) {
|
||||||
enc_mac_key = msg + GetOffset(message, mac_key);
|
enc_mac_key = msg + GetOffset(message, mac_key);
|
||||||
enc_mac_key_iv = msg + GetOffset(message, mac_key_iv);
|
enc_mac_key_iv = msg + GetOffset(message, mac_key_iv);
|
||||||
} else {
|
} else {
|
||||||
LOGV("ContentKeySession::LoadKeys: enc_mac_key not set");
|
LOGV("ContentKeySession::LoadKeys: enc_mac_key not set");
|
||||||
}
|
}
|
||||||
std::vector<OEMCrypto_KeyObject> load_keys(keys.size());
|
std::vector<OEMCrypto_KeyObject_V13> load_keys(keys.size());
|
||||||
for (size_t i = 0; i < keys.size(); ++i) {
|
for (size_t i = 0; i < keys.size(); ++i) {
|
||||||
const CryptoKey* ki = &keys[i];
|
const CryptoKey* ki = &keys[i];
|
||||||
OEMCrypto_KeyObject* ko = &load_keys[i];
|
OEMCrypto_KeyObject_V13* ko = &load_keys[i];
|
||||||
ko->key_id = msg + GetOffset(message, ki->key_id());
|
ko->key_id = msg + GetOffset(message, ki->key_id());
|
||||||
ko->key_id_length = ki->key_id().length();
|
ko->key_id_length = ki->key_id().length();
|
||||||
ko->key_data_iv = msg + GetOffset(message, ki->key_data_iv());
|
ko->key_data_iv = msg + GetOffset(message, ki->key_data_iv());
|
||||||
@@ -144,6 +147,8 @@ OEMCryptoResult ContentKeySession::LoadKeys(
|
|||||||
ko->key_control_iv = NULL;
|
ko->key_control_iv = NULL;
|
||||||
ko->key_control = NULL;
|
ko->key_control = NULL;
|
||||||
}
|
}
|
||||||
|
ko->cipher_mode = ToOEMCryptoCipherMode(ki->cipher_mode());
|
||||||
|
|
||||||
// TODO(jfore): Is returning the cipher needed. If not drop this.
|
// TODO(jfore): Is returning the cipher needed. If not drop this.
|
||||||
*cipher_mode = ki->cipher_mode();
|
*cipher_mode = ki->cipher_mode();
|
||||||
}
|
}
|
||||||
@@ -162,7 +167,7 @@ OEMCryptoResult ContentKeySession::LoadKeys(
|
|||||||
LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_);
|
LOGV("LoadKeys: id=%ld", (uint32_t)oec_session_id_);
|
||||||
OEMCryptoResult sts;
|
OEMCryptoResult sts;
|
||||||
M_TIME(
|
M_TIME(
|
||||||
sts = OEMCrypto_LoadKeys(
|
sts = ::OEMCrypto_LoadKeys_Back_Compat(
|
||||||
oec_session_id_, msg, message.size(),
|
oec_session_id_, msg, message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
|
reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
|
||||||
enc_mac_key_iv, enc_mac_key, keys.size(), &load_keys[0], pst,
|
enc_mac_key_iv, enc_mac_key, keys.size(), &load_keys[0], pst,
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ const uint32_t kRsaSignatureLength = 256;
|
|||||||
const size_t kMaximumChunkSize = 100 * 1024; // 100 KiB
|
const size_t kMaximumChunkSize = 100 * 1024; // 100 KiB
|
||||||
const size_t kEstimatedInitialUsageTableHeader = 40;
|
const size_t kEstimatedInitialUsageTableHeader = 40;
|
||||||
const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13;
|
const size_t kOemCryptoApiVersionSupportsBigUsageTables = 13;
|
||||||
|
// Ability to switch cipher modes in SelectKey() was introduced in this
|
||||||
|
// OEMCrypto version
|
||||||
|
const size_t kOemCryptoApiVersionSupportsSwitchingCipherMode = 14;
|
||||||
|
|
||||||
// Constants and utility objects relating to OEM Certificates
|
// Constants and utility objects relating to OEM Certificates
|
||||||
const int kExtensionOidSize = 64;
|
const int kExtensionOidSize = 64;
|
||||||
@@ -126,6 +129,11 @@ OEMCrypto_LicenseType OEMCryptoLicenseType(CdmLicenseKeyType cdm_license_type) {
|
|||||||
: OEMCrypto_EntitlementLicense;
|
: OEMCrypto_EntitlementLicense;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode) {
|
||||||
|
return cipher_mode == kCipherModeCtr
|
||||||
|
? OEMCrypto_CipherMode_CTR : OEMCrypto_CipherMode_CBC;
|
||||||
|
}
|
||||||
|
|
||||||
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
||||||
: metrics_(metrics),
|
: metrics_(metrics),
|
||||||
system_id_(-1),
|
system_id_(-1),
|
||||||
@@ -137,7 +145,8 @@ CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
|
|||||||
usage_support_type_(kUnknownUsageSupport),
|
usage_support_type_(kUnknownUsageSupport),
|
||||||
usage_table_header_(NULL),
|
usage_table_header_(NULL),
|
||||||
request_id_base_(0),
|
request_id_base_(0),
|
||||||
cipher_mode_(kCipherModeCtr) {
|
cipher_mode_(kCipherModeCtr),
|
||||||
|
api_version_(0) {
|
||||||
assert(metrics);
|
assert(metrics);
|
||||||
Init();
|
Init();
|
||||||
life_span_.Start();
|
life_span_.Start();
|
||||||
@@ -664,6 +673,11 @@ CdmResponseType CryptoSession::Open(SecurityLevel requested_security_level) {
|
|||||||
metrics_->oemcrypto_get_random_.Increment(random_sts);
|
metrics_->oemcrypto_get_random_.Increment(random_sts);
|
||||||
++request_id_index_;
|
++request_id_index_;
|
||||||
|
|
||||||
|
if (!GetApiVersion(&api_version_)) {
|
||||||
|
LOGE("CryptoSession::Open: GetApiVersion failed");
|
||||||
|
return USAGE_SUPPORT_GET_API_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
CdmUsageSupportType usage_support_type;
|
CdmUsageSupportType usage_support_type;
|
||||||
CdmResponseType result = GetUsageSupportType(&usage_support_type);
|
CdmResponseType result = GetUsageSupportType(&usage_support_type);
|
||||||
if (result == NO_ERROR) {
|
if (result == NO_ERROR) {
|
||||||
@@ -1071,8 +1085,10 @@ CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) {
|
|||||||
sts = CopyBufferInChunks(params, buffer_descriptor);
|
sts = CopyBufferInChunks(params, buffer_descriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params.is_encrypted && params.cipher_mode != cipher_mode_) {
|
if (api_version_ < kOemCryptoApiVersionSupportsSwitchingCipherMode) {
|
||||||
return INCORRECT_CRYPTO_MODE;
|
if (params.is_encrypted && params.cipher_mode != cipher_mode_) {
|
||||||
|
return INCORRECT_CRYPTO_MODE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (params.is_encrypted || sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
if (params.is_encrypted || sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||||
OEMCrypto_CENCEncryptPatternDesc pattern_descriptor;
|
OEMCrypto_CENCEncryptPatternDesc pattern_descriptor;
|
||||||
@@ -1928,14 +1944,8 @@ CdmResponseType CryptoSession::GetUsageSupportType(
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t api_version = 0;
|
|
||||||
if (!GetApiVersion(&api_version)) {
|
|
||||||
LOGE("GetUsageSupportType: GetApiVersion failed");
|
|
||||||
return USAGE_SUPPORT_GET_API_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
*usage_support_type = usage_support_type_ =
|
*usage_support_type = usage_support_type_ =
|
||||||
(api_version >= kOemCryptoApiVersionSupportsBigUsageTables)
|
(api_version_ >= kOemCryptoApiVersionSupportsBigUsageTables)
|
||||||
? kUsageEntrySupport
|
? kUsageEntrySupport
|
||||||
: kUsageTableSupport;
|
: kUsageTableSupport;
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
|
|||||||
@@ -955,6 +955,8 @@ bool CdmLicense::RestoreLicenseForRelease(
|
|||||||
if (!crypto_session_->GenerateDerivedKeys(key_request_,
|
if (!crypto_session_->GenerateDerivedKeys(key_request_,
|
||||||
signed_response.session_key()))
|
signed_response.session_key()))
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
return KEY_ADDED == HandleKeyResponse(license_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (license.policy().has_renewal_server_url())
|
if (license.policy().has_renewal_server_url())
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ OEMCryptoResult SubLicenseKeySession::SelectKey(const std::string& key_id,
|
|||||||
it->second,
|
it->second,
|
||||||
reinterpret_cast<const uint8_t*>(keys_[i].key_id().data()),
|
reinterpret_cast<const uint8_t*>(keys_[i].key_id().data()),
|
||||||
keys_[i].key_id().size(),
|
keys_[i].key_id().size(),
|
||||||
static_cast<OEMCryptoCipherMode>(cipher_mode)),
|
ToOEMCryptoCipherMode(cipher_mode)),
|
||||||
metrics_, oemcrypto_select_key_, status);
|
metrics_, oemcrypto_select_key_, status);
|
||||||
if (OEMCrypto_SUCCESS != status) {
|
if (OEMCrypto_SUCCESS != status) {
|
||||||
return status;
|
return status;
|
||||||
@@ -184,7 +184,7 @@ OEMCryptoResult SubLicenseKeySession::DoLoadKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < keys.size(); i++) {
|
for (size_t i = 0; i < keys.size(); i++) {
|
||||||
OEMCrypto_KeyObject key_object;
|
OEMCrypto_KeyObject_V13 key_object;
|
||||||
const CryptoKey& key_data = keys[i];
|
const CryptoKey& key_data = keys[i];
|
||||||
key_object.key_id = msg + GetOffset(message, key_data.key_id());
|
key_object.key_id = msg + GetOffset(message, key_data.key_id());
|
||||||
key_object.key_id_length = key_data.key_id().length();
|
key_object.key_id_length = key_data.key_id().length();
|
||||||
@@ -201,6 +201,8 @@ OEMCryptoResult SubLicenseKeySession::DoLoadKeys(
|
|||||||
key_object.key_control_iv = NULL;
|
key_object.key_control_iv = NULL;
|
||||||
key_object.key_control = NULL;
|
key_object.key_control = NULL;
|
||||||
}
|
}
|
||||||
|
key_object.cipher_mode = ToOEMCryptoCipherMode(key_data.cipher_mode());
|
||||||
|
|
||||||
// TODO(jfore): Does returning the cipher mode serve any purpose?
|
// TODO(jfore): Does returning the cipher mode serve any purpose?
|
||||||
// If not drop.
|
// If not drop.
|
||||||
*cipher_mode = key_data.cipher_mode();
|
*cipher_mode = key_data.cipher_mode();
|
||||||
@@ -215,7 +217,7 @@ OEMCryptoResult SubLicenseKeySession::DoLoadKeys(
|
|||||||
|
|
||||||
OEMCryptoResult sts;
|
OEMCryptoResult sts;
|
||||||
M_TIME(
|
M_TIME(
|
||||||
sts = OEMCrypto_LoadKeys(
|
sts = OEMCrypto_LoadKeys_Back_Compat(
|
||||||
oec_session_id->second, msg, message.size(),
|
oec_session_id->second, msg, message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
signature.size(), enc_mac_key_iv, enc_mac_key, 1, &key_object, pst,
|
signature.size(), enc_mac_key_iv, enc_mac_key, 1, &key_object, pst,
|
||||||
@@ -230,7 +232,7 @@ OEMCryptoResult SubLicenseKeySession::DoLoadKeys(
|
|||||||
oec_session_id->second,
|
oec_session_id->second,
|
||||||
reinterpret_cast<const uint8_t*>(key_data.key_id().data()),
|
reinterpret_cast<const uint8_t*>(key_data.key_id().data()),
|
||||||
key_data.key_id().size(),
|
key_data.key_id().size(),
|
||||||
static_cast<OEMCryptoCipherMode>(key_data.cipher_mode())),
|
ToOEMCryptoCipherMode(key_data.cipher_mode())),
|
||||||
metrics_, oemcrypto_select_key_, sts);
|
metrics_, oemcrypto_select_key_, sts);
|
||||||
|
|
||||||
if (sts != OEMCrypto_SUCCESS) {
|
if (sts != OEMCrypto_SUCCESS) {
|
||||||
@@ -312,7 +314,7 @@ OEMCryptoResult SubLicenseKeySession::DoSubLicenseLoadKeys(
|
|||||||
return sts;
|
return sts;
|
||||||
}
|
}
|
||||||
|
|
||||||
OEMCrypto_KeyObject key_object;
|
OEMCrypto_KeyObject_V13 key_object;
|
||||||
key_object.key_id = msg + GetOffset(message, keys_[key_index].key_id());
|
key_object.key_id = msg + GetOffset(message, keys_[key_index].key_id());
|
||||||
key_object.key_id_length = keys_[key_index].key_id().length();
|
key_object.key_id_length = keys_[key_index].key_id().length();
|
||||||
key_object.key_data_iv =
|
key_object.key_data_iv =
|
||||||
@@ -325,9 +327,11 @@ OEMCryptoResult SubLicenseKeySession::DoSubLicenseLoadKeys(
|
|||||||
key_object.key_control =
|
key_object.key_control =
|
||||||
msg + GetOffset(message, keys_[key_index].key_control());
|
msg + GetOffset(message, keys_[key_index].key_control());
|
||||||
}
|
}
|
||||||
|
key_object.cipher_mode =
|
||||||
|
ToOEMCryptoCipherMode(keys_[key_index].cipher_mode());
|
||||||
|
|
||||||
M_TIME(
|
M_TIME(
|
||||||
sts = OEMCrypto_LoadKeys(
|
sts = OEMCrypto_LoadKeys_Back_Compat(
|
||||||
it->second, msg, message.size(),
|
it->second, msg, message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
|
reinterpret_cast<const uint8_t*>(signature.data()), signature.size(),
|
||||||
enc_mac_key_iv, enc_mac_key, 1, &key_object, pst,
|
enc_mac_key_iv, enc_mac_key, 1, &key_object, pst,
|
||||||
@@ -342,7 +346,7 @@ OEMCryptoResult SubLicenseKeySession::DoSubLicenseLoadKeys(
|
|||||||
it->second,
|
it->second,
|
||||||
reinterpret_cast<const uint8_t*>(keys_[key_index].key_id().data()),
|
reinterpret_cast<const uint8_t*>(keys_[key_index].key_id().data()),
|
||||||
keys_[key_index].key_id().size(),
|
keys_[key_index].key_id().size(),
|
||||||
static_cast<OEMCryptoCipherMode>(keys_[key_index].cipher_mode())),
|
ToOEMCryptoCipherMode(keys_[key_index].cipher_mode())),
|
||||||
metrics_, oemcrypto_select_key_, sts);
|
metrics_, oemcrypto_select_key_, sts);
|
||||||
|
|
||||||
return sts;
|
return sts;
|
||||||
|
|||||||
@@ -871,6 +871,165 @@ HlsDecryptionInfo kHlsFourCCBackwardCompatibilityTestVectors[] = {
|
|||||||
{true, 1, &kSampleAes160ByteSegmentInfo[0], kHlsPsshSampleAesFourCC},
|
{true, 1, &kSampleAes160ByteSegmentInfo[0], kHlsPsshSampleAesFourCC},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::string kFullCencPssh = wvcdm::a2bs_hex(
|
||||||
|
"00000044" // blob size
|
||||||
|
"70737368" // "pssh"
|
||||||
|
"00000000" // flags
|
||||||
|
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
|
||||||
|
"00000024" // pssh data size
|
||||||
|
"08011201321a0d7769646576696e655f" // pssh data
|
||||||
|
"74657374220a323031355f7465617273"
|
||||||
|
"2a024844");
|
||||||
|
|
||||||
|
const std::string kFullCbc1Pssh = wvcdm::a2bs_hex(
|
||||||
|
"00000053" // blob size
|
||||||
|
"70737368" // "pssh"
|
||||||
|
"00000000" // flags
|
||||||
|
"edef8ba979d64acea3c827dcd51d21ed" // Widevine system id
|
||||||
|
"00000033" // pssh data size
|
||||||
|
"12103030303030303030303030303030" // pssh data
|
||||||
|
"30321a0d7769646576696e655f746573"
|
||||||
|
"74220a323031355f746561727348b1c6"
|
||||||
|
"899b06");
|
||||||
|
|
||||||
|
struct Cenc30SampleInfo {
|
||||||
|
bool is_encrypted;
|
||||||
|
wvcdm::KeyId key_id;
|
||||||
|
std::string iv;
|
||||||
|
std::string clear_data;
|
||||||
|
std::string encrypted_data;
|
||||||
|
uint8_t subsample_flags;
|
||||||
|
wvcdm::CdmCipherMode cipher_mode;
|
||||||
|
};
|
||||||
|
|
||||||
|
Cenc30SampleInfo kCenc30CencKey33Sample = {
|
||||||
|
true, wvcdm::a2bs_hex("30303030303030303030303030303033"),
|
||||||
|
wvcdm::a2bs_hex("9FBE45DD47DA7EBA09A3E24CBA95C9AF"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"011E88387D58EBB8E5CDCC38D431EEF4B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC868701CB8BE038"
|
||||||
|
"15BBFFB95FD3A86F142127720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"E7C566D86E98C36D2DCA54A966E7B469B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC8687B3A4AD15AD"
|
||||||
|
"A2ABBB84D8E3CBEC3E8771720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample,
|
||||||
|
wvcdm::kCipherModeCtr,
|
||||||
|
};
|
||||||
|
|
||||||
|
Cenc30SampleInfo kCenc30CencKey32Sample = {
|
||||||
|
true, wvcdm::a2bs_hex("30303030303030303030303030303032"),
|
||||||
|
wvcdm::a2bs_hex("9FBE45DD47DA7EBA09A3E24CBA95C9AF"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"1B605E32B31D6245BCCC01C4E7720725B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC8687DBFDF7F684"
|
||||||
|
"3A552DCB7C38E461EDF5F3720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"E7C566D86E98C36D2DCA54A966E7B469B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC8687B3A4AD15AD"
|
||||||
|
"A2ABBB84D8E3CBEC3E8771720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample,
|
||||||
|
wvcdm::kCipherModeCtr,
|
||||||
|
};
|
||||||
|
|
||||||
|
Cenc30SampleInfo kCenc30Cbc1Key33Sample = {
|
||||||
|
true, wvcdm::a2bs_hex("30303030303030303030303030303033"),
|
||||||
|
wvcdm::a2bs_hex("9FBE45DD47DA7EBA09A3E24CBA95C9AF"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"E300F37FEB0CDD9F276E67B971FF423003F3BF21DCF6100BA453A473A4522A19A8"
|
||||||
|
"2E098AA25511011D386FC7092FE3B407DF2BEB3AD57D5E1178F041E3FCABE25193"
|
||||||
|
"3F5EE35670CEB96BA3DAF922484F9A37773EF75D4B17FACC80B475004A6229AB4C"
|
||||||
|
"DFFA426468E578DE6A0285D942CDE476E06FF907D03F382552C2E14399C3FC2D21"
|
||||||
|
"9A59819FFF837EBC88A9F83A42D37F48ED8564EB40AC3BA8A6D2634A81F04FC2F1"
|
||||||
|
"379A45869036FD72B39C88222646AB7486A8416D78AB75951EB87ED1E16DF69209"
|
||||||
|
"A6966AC93C7BB65B85E429357A732CBC75F6EFB1781859FB771D60D11EB381D9CA"
|
||||||
|
"63F793507B02207810773FCABED0240E5BEEAD30116014E481"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"E7C566D86E98C36D2DCA54A966E7B469B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC8687B3A4AD15AD"
|
||||||
|
"A2ABBB84D8E3CBEC3E8771720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample,
|
||||||
|
wvcdm::kCipherModeCbc,
|
||||||
|
};
|
||||||
|
|
||||||
|
Cenc30SampleInfo kCenc30Cbc1Key32Sample = {
|
||||||
|
true, wvcdm::a2bs_hex("30303030303030303030303030303032"),
|
||||||
|
wvcdm::a2bs_hex("9FBE45DD47DA7EBA09A3E24CBA95C9AF"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"4392E38BAE263267ED15394DE349AD1577F37B7D906C3A61536EE5A288F66F22F2"
|
||||||
|
"F5098964B7F2860A848C3C4FD30E538B3BCD2E700DC3FBC1657A6E9EAE44DE97C4"
|
||||||
|
"6F27C82A49198EE185D92931F093C3342FDBF6CF8203E18CCDC4B88E79C95EC052"
|
||||||
|
"3FD10F9409945349169FAA8F6A37179D2BEDC04A158A09BCBF742DA05245428788"
|
||||||
|
"E972B9B465FED5849AEDDB74B8919673C0C8829B5B062A38B3146CB8D497F03A4D"
|
||||||
|
"5C0A1D463504C1F116A811EF32503695B8FF78D9E93CDF7B2F7493E8043D4DE110"
|
||||||
|
"FE1D342D1C0175BF1466A544FC0D02DD0E314098256DD65B48098323C3AED9B7E0"
|
||||||
|
"CF260DBC5A0F09A46E39AE5E26A66ABFA52CBA26FBA83975E4"),
|
||||||
|
wvcdm::a2bs_hex(
|
||||||
|
"E7C566D86E98C36D2DCA54A966E7B469B6094B9201F200932F8EB5E1A94FB0B977"
|
||||||
|
"FAB8DFDAD57C677E279615F4EAFA872CA8EFF83179E4DE2AB78E6B41A860C42203"
|
||||||
|
"4B875AC282406E03AC01F2E407A55DE38C6C35707F34B3319646FA016A01CE9056"
|
||||||
|
"E55D28C48ED72F10FA6625656ED62B758CBADA757DDC52533C9CBD54FC1A46F827"
|
||||||
|
"CC7B69BA66AE19A15D725FCBB972B23C83F95C0F00F481A7C9AC8687B3A4AD15AD"
|
||||||
|
"A2ABBB84D8E3CBEC3E8771720A35234070799173B37219127141922CBA8CB2DC48"
|
||||||
|
"EC2477832D1AE477942DCDA93C0886AF72D71E56DA3D7737E49670B024639A195B"
|
||||||
|
"7377C7F45A797C6E5DBB1BB2843DA3FC76043E33687BEF3172"),
|
||||||
|
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample,
|
||||||
|
wvcdm::kCipherModeCbc,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cenc30SwitchCipherInfo {
|
||||||
|
const std::string pssh;
|
||||||
|
Cenc30SampleInfo sample_info[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
Cenc30SwitchCipherInfo kCenc30SwitchCipherData[8] = {
|
||||||
|
// Switch between cipher modes
|
||||||
|
{ kFullCencPssh, { kCenc30CencKey33Sample, kCenc30Cbc1Key33Sample,
|
||||||
|
kCenc30CencKey33Sample, kCenc30Cbc1Key33Sample, } },
|
||||||
|
{ kFullCbc1Pssh, { kCenc30Cbc1Key33Sample, kCenc30CencKey33Sample,
|
||||||
|
kCenc30Cbc1Key33Sample, kCenc30CencKey33Sample, } },
|
||||||
|
// Switch between cipher modes, but the first sample has a cipher mode
|
||||||
|
// that differs with the protection scheme in the pssh
|
||||||
|
{ kFullCencPssh, { kCenc30Cbc1Key33Sample, kCenc30CencKey33Sample,
|
||||||
|
kCenc30Cbc1Key33Sample, kCenc30CencKey33Sample, } },
|
||||||
|
{ kFullCbc1Pssh, { kCenc30CencKey33Sample, kCenc30Cbc1Key33Sample,
|
||||||
|
kCenc30CencKey33Sample, kCenc30Cbc1Key33Sample, } },
|
||||||
|
// Switch between cipher modes and keys
|
||||||
|
{ kFullCencPssh, { kCenc30CencKey33Sample, kCenc30CencKey32Sample,
|
||||||
|
kCenc30Cbc1Key33Sample, kCenc30Cbc1Key32Sample, } },
|
||||||
|
{ kFullCencPssh, { kCenc30Cbc1Key33Sample, kCenc30Cbc1Key32Sample,
|
||||||
|
kCenc30CencKey33Sample, kCenc30CencKey32Sample, } },
|
||||||
|
{ kFullCbc1Pssh, { kCenc30Cbc1Key33Sample, kCenc30Cbc1Key32Sample,
|
||||||
|
kCenc30CencKey33Sample, kCenc30CencKey32Sample, } },
|
||||||
|
{ kFullCbc1Pssh, { kCenc30CencKey33Sample, kCenc30CencKey32Sample,
|
||||||
|
kCenc30Cbc1Key33Sample, kCenc30Cbc1Key32Sample, } },
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -1055,7 +1214,6 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
|||||||
// when appropriate.
|
// when appropriate.
|
||||||
std::string init_data;
|
std::string init_data;
|
||||||
wvcdm::CdmAppParameterMap app_parameters;
|
wvcdm::CdmAppParameterMap app_parameters;
|
||||||
wvcdm::CdmKeyRequestType key_request_type;
|
|
||||||
CdmKeyRequest key_request;
|
CdmKeyRequest key_request;
|
||||||
EXPECT_EQ(wvcdm::KEY_MESSAGE,
|
EXPECT_EQ(wvcdm::KEY_MESSAGE,
|
||||||
decryptor_.GenerateKeyRequest(
|
decryptor_.GenerateKeyRequest(
|
||||||
@@ -2496,7 +2654,6 @@ TEST_P(WvCdmUsageTest, WithClientId) {
|
|||||||
decrypt_buffer.begin()));
|
decrypt_buffer.begin()));
|
||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
|
|
||||||
uint32_t num_usage_info = 0;
|
|
||||||
CdmUsageInfo usage_info;
|
CdmUsageInfo usage_info;
|
||||||
CdmUsageInfoReleaseMessage release_msg;
|
CdmUsageInfoReleaseMessage release_msg;
|
||||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||||
@@ -2582,7 +2739,6 @@ TEST_F(WvCdmRequestLicenseTest, UsageInfoRetryTest) {
|
|||||||
decrypt_buffer.begin()));
|
decrypt_buffer.begin()));
|
||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
|
|
||||||
uint32_t num_usage_info = 0;
|
|
||||||
CdmUsageInfo usage_info;
|
CdmUsageInfo usage_info;
|
||||||
CdmUsageInfoReleaseMessage release_msg;
|
CdmUsageInfoReleaseMessage release_msg;
|
||||||
CdmResponseType status = decryptor_.GetUsageInfo(
|
CdmResponseType status = decryptor_.GetUsageInfo(
|
||||||
@@ -2680,7 +2836,6 @@ TEST_P(WvCdmUsageInfoTest, UsageInfo) {
|
|||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t num_usage_info = 0;
|
|
||||||
CdmUsageInfo usage_info;
|
CdmUsageInfo usage_info;
|
||||||
CdmUsageInfoReleaseMessage release_msg;
|
CdmUsageInfoReleaseMessage release_msg;
|
||||||
CdmResponseType status =
|
CdmResponseType status =
|
||||||
@@ -3705,6 +3860,73 @@ INSTANTIATE_TEST_CASE_P(
|
|||||||
::testing::Range(&kHlsFourCCBackwardCompatibilityTestVectors[0],
|
::testing::Range(&kHlsFourCCBackwardCompatibilityTestVectors[0],
|
||||||
&kHlsFourCCBackwardCompatibilityTestVectors[4]));
|
&kHlsFourCCBackwardCompatibilityTestVectors[4]));
|
||||||
|
|
||||||
|
class WvCenc30SwitchCipherModeTest
|
||||||
|
: public WvCdmRequestLicenseTest,
|
||||||
|
public ::testing::WithParamInterface<Cenc30SwitchCipherInfo*> {};
|
||||||
|
|
||||||
|
TEST_P(WvCenc30SwitchCipherModeTest, DecryptionTest) {
|
||||||
|
Provision(kLevel3);
|
||||||
|
TestWvCdmClientPropertySet client_property_set;
|
||||||
|
client_property_set.set_security_level(QUERY_VALUE_SECURITY_LEVEL_L3);
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
EXPECT_EQ(wvcdm::NO_ERROR,
|
||||||
|
decryptor_.QueryStatus(
|
||||||
|
kLevel3, wvcdm::QUERY_KEY_OEMCRYPTO_API_VERSION, &value));
|
||||||
|
std::istringstream ss(value);
|
||||||
|
uint32_t api_version;
|
||||||
|
ss >> api_version;
|
||||||
|
ASSERT_FALSE(ss.fail());
|
||||||
|
EXPECT_TRUE(ss.eof());
|
||||||
|
|
||||||
|
// Ability to switch between cipher modes without re-requesting a license
|
||||||
|
// was introduced in OEMCrypto v14
|
||||||
|
if (api_version < 14)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Cenc30SwitchCipherInfo* info = GetParam();
|
||||||
|
|
||||||
|
TestWvCdmHlsEventListener listener;
|
||||||
|
decryptor_.OpenSession(g_key_system, &client_property_set,
|
||||||
|
kDefaultCdmIdentifier, &listener, &session_id_);
|
||||||
|
CdmAppParameterMap app_parameters;
|
||||||
|
GenerateKeyRequest(info->pssh, app_parameters,
|
||||||
|
kLicenseTypeStreaming, NULL);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth);
|
||||||
|
CdmKeyStatusMap key_status_map = listener.GetKeyStatusMap();
|
||||||
|
EXPECT_EQ(8u, key_status_map.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N_ELEM(info->sample_info); ++i) {
|
||||||
|
Cenc30SampleInfo* data = &info->sample_info[i];
|
||||||
|
std::vector<uint8_t> output_buffer(data->encrypted_data.size(), 0);
|
||||||
|
std::vector<uint8_t> iv(data->iv.begin(), data->iv.end());
|
||||||
|
CdmDecryptionParameters decryption_parameters(
|
||||||
|
&data->key_id,
|
||||||
|
reinterpret_cast<const uint8_t*>(data->encrypted_data.c_str()),
|
||||||
|
data->encrypted_data.size(), &iv, 0, &output_buffer[0]);
|
||||||
|
decryption_parameters.is_encrypted = data->is_encrypted;
|
||||||
|
decryption_parameters.is_secure = false;
|
||||||
|
decryption_parameters.cipher_mode = data->cipher_mode;
|
||||||
|
if (data->cipher_mode == kCipherModeCtr) {
|
||||||
|
decryption_parameters.pattern_descriptor.encrypt_blocks = 1;
|
||||||
|
decryption_parameters.pattern_descriptor.skip_blocks = 9;
|
||||||
|
}
|
||||||
|
decryption_parameters.subsample_flags = data->subsample_flags;
|
||||||
|
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, false,
|
||||||
|
decryption_parameters));
|
||||||
|
EXPECT_EQ(data->clear_data,
|
||||||
|
std::string(reinterpret_cast<const char*>(&output_buffer[0]),
|
||||||
|
output_buffer.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptor_.CloseSession(session_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(
|
||||||
|
Cdm, WvCenc30SwitchCipherModeTest,
|
||||||
|
::testing::Range(&kCenc30SwitchCipherData[0],
|
||||||
|
&kCenc30SwitchCipherData[8]));
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
void show_menu(char* prog_name) {
|
void show_menu(char* prog_name) {
|
||||||
|
|||||||
Reference in New Issue
Block a user