Add a few more checks for "key length" and "iv length".
------------- Pad key value when crypto_mode is DVB_CSA, so that the key length is always 16 bytes. ------------- Minor comment and example code update. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=219860612
This commit is contained in:
@@ -60,6 +60,7 @@ static constexpr int kNumBitsUnusedField = 6;
|
||||
static constexpr size_t kKeyIdSizeBytes = 16;
|
||||
static constexpr size_t kKeyDataSizeBytes = 16;
|
||||
static constexpr size_t kWrappedKeyIvSizeBytes = 16;
|
||||
static constexpr size_t kWrappingKeySizeBytes = 32; // entitlement key
|
||||
static constexpr size_t kWrappingKeyIvSizeBytes = 16;
|
||||
|
||||
// BitField constants for the ECM payload
|
||||
@@ -302,21 +303,39 @@ util::Status CasEcm::WrapEntitledKeys(
|
||||
if (entitled_key->wrapped_key_iv.empty()) {
|
||||
CHECK(RandomBytes(kWrappedKeyIvSizeBytes, &entitled_key->wrapped_key_iv));
|
||||
}
|
||||
entitled_key->wrapped_key_value =
|
||||
util::Status status =
|
||||
WrapKey(entitlement_key->key_value, entitled_key->wrapped_key_iv,
|
||||
entitled_key->key_value);
|
||||
entitled_key->key_value, &entitled_key->wrapped_key_value);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
entitlement_key++;
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
std::string CasEcm::WrapKey(const std::string& wrapping_key, const std::string& iv,
|
||||
const std::string& key_value) {
|
||||
if (iv.size() != kWrappingKeyIvSizeBytes) {
|
||||
LOG(WARNING) << "Incorrect iv size for WrapKey(): " << iv.size();
|
||||
util::Status CasEcm::WrapKey(const std::string& wrapping_key,
|
||||
const std::string& wrapping_iv, const std::string& key_value,
|
||||
std::string* wrapped_key) {
|
||||
util::Status status = ValidateKeyValue(wrapping_key, kWrappingKeySizeBytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
status = ValidateIv(wrapping_iv, kWrappingKeyIvSizeBytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
status = ValidateKeyValue(key_value, kKeyDataSizeBytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
// Wrapped key IV is always 16 bytes.
|
||||
return crypto_util::EncryptAesCbcNoPad(wrapping_key, iv, key_value);
|
||||
*wrapped_key =
|
||||
crypto_util::EncryptAesCbcNoPad(wrapping_key, wrapping_iv, key_value);
|
||||
if (wrapped_key->empty()) {
|
||||
return util::Status(util::error::INTERNAL, "Failed to wrap key");
|
||||
}
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
util::Status CasEcm::ValidateKeys(const std::vector<EntitledKeyInfo*>& keys) {
|
||||
@@ -326,6 +345,10 @@ util::Status CasEcm::ValidateKeys(const std::vector<EntitledKeyInfo*>& keys) {
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
status = ValidateKeyValue(key->key_value, kKeyDataSizeBytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
status = ValidateIv(key->content_iv, content_iv_size_);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
@@ -342,7 +365,7 @@ util::Status CasEcm::ValidateWrappedKeys(
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
status = ValidateKeyValue(key->wrapped_key_value);
|
||||
status = ValidateKeyValue(key->wrapped_key_value, kKeyDataSizeBytes);
|
||||
if (!status.ok()) {
|
||||
LOG(ERROR) << "Wrapped key is bad.";
|
||||
return status;
|
||||
@@ -366,9 +389,10 @@ util::Status CasEcm::ValidateKeyId(const std::string& key_id) {
|
||||
return util::OkStatus();
|
||||
}
|
||||
|
||||
util::Status CasEcm::ValidateKeyValue(const std::string& key_value) {
|
||||
if (key_value.size() != kKeyDataSizeBytes) {
|
||||
util::Status(
|
||||
util::Status CasEcm::ValidateKeyValue(const std::string& key_value,
|
||||
size_t key_value_size) {
|
||||
if (key_value.size() != key_value_size) {
|
||||
return util::Status(
|
||||
util::error::INVALID_ARGUMENT,
|
||||
absl::StrCat("Key is wrong size (", key_value.size(), " bytes)."));
|
||||
}
|
||||
@@ -390,6 +414,9 @@ std::string CasEcm::SerializeEcm(const std::vector<EntitledKeyInfo*>& keys) {
|
||||
generation());
|
||||
std::bitset<kNumBitsDecryptModeField> decrypt_mode(
|
||||
static_cast<int>(crypto_mode()));
|
||||
if (decrypt_mode.to_string() == "00") {
|
||||
LOG(FATAL) << "Invalid decrypt mode \"00\"";
|
||||
}
|
||||
std::bitset<kNumBitsRotationEnabledField> rotation_enabled(
|
||||
RotationFieldValue(paired_keys_required()));
|
||||
std::bitset<kNumBitsWrappedKeyIvSizeField> wrapped_key_iv_size(
|
||||
@@ -490,6 +517,10 @@ util::Status CasEcm::ParseEntitlementResponse(const std::string& response_string
|
||||
EntitlementKeyInfo ekey;
|
||||
ekey.key_id = key.key_id();
|
||||
ekey.key_value = key.key();
|
||||
util::Status status = ValidateKeyValue(key.key(), kWrappingKeySizeBytes);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Using only keys with correct KeySlot
|
||||
if (!key.has_key_slot()) {
|
||||
|
||||
@@ -198,17 +198,19 @@ class CasEcm {
|
||||
const std::vector<EntitledKeyInfo*>& keys, const std::string& track_type,
|
||||
std::string* serialized_ecm, uint32_t* generation);
|
||||
|
||||
// Wrap a |key_value| using |wrapping_key| (entitlement key) and |iv|.
|
||||
// Returns the resulting wrapped key.
|
||||
virtual std::string WrapKey(const std::string& wrapping_key, const std::string& iv,
|
||||
const std::string& key_value);
|
||||
// Wrap |key_value| using |wrapping_key| (entitlement key) and |wrapping_iv|.
|
||||
// Returns the resulting wrapped key in |wrapped_key|.
|
||||
// Return a status indicating whether there has been any error.
|
||||
virtual util::Status WrapKey(const std::string& wrapping_key,
|
||||
const std::string& wrapping_iv,
|
||||
const std::string& key_value, std::string* wrapped_key);
|
||||
|
||||
virtual util::Status ValidateKeys(const std::vector<EntitledKeyInfo*>& keys);
|
||||
virtual util::Status ValidateWrappedKeys(
|
||||
const std::vector<EntitledKeyInfo*>& keys);
|
||||
|
||||
util::Status ValidateKeyId(const std::string& key_id);
|
||||
util::Status ValidateKeyValue(const std::string& key_value);
|
||||
util::Status ValidateKeyValue(const std::string& key_value, size_t key_value_size);
|
||||
util::Status ValidateIv(const std::string& iv, size_t size);
|
||||
|
||||
// TODO(user): need unit tests for CreateEntitlementRequest.
|
||||
|
||||
Reference in New Issue
Block a user