Skip key padding better
(This is a merge of http://go/wvgerrit/151112.) The Widevine CDMs have never validated the padding on AES keys. However, the code to ignore the padding was unusual and based on the assumption the keys would always have either 0 or 16 bytes of padding and did not handle other cases correctly. This patch updates the padding-ignoring code to just do the obvious thing: Reject keys that are too small and ignore all extra bytes regardless of count. Bug: 114159862 Test: x86-64 Change-Id: Ic48010477e4cb5f7d2afbde25cf2f098e3470089
This commit is contained in:
committed by
John Bruce
parent
c9c897408a
commit
30a3da1b83
@@ -15,6 +15,7 @@ static const size_t KEY_PAD_SIZE = 16;
|
||||
static const size_t CONTENT_KEY_SIZE = 16;
|
||||
static const size_t SERVICE_KEY_SIZE = 16;
|
||||
static const size_t MAC_KEY_SIZE = 32;
|
||||
static const size_t ENTITLEMENT_KEY_SIZE = 32;
|
||||
static const size_t KEYBOX_KEY_DATA_SIZE = 72;
|
||||
static const size_t SRM_REQUIREMENT_SIZE = 12;
|
||||
|
||||
|
||||
@@ -55,17 +55,19 @@ std::vector<CryptoKey> ExtractEntitlementKeys(const License& license) {
|
||||
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
CryptoKey key;
|
||||
size_t length = 0;
|
||||
switch (license.key(i).type()) {
|
||||
case License_KeyContainer::ENTITLEMENT: {
|
||||
// Strip off PKCS#5 padding - since we know the key is 32 or 48 bytes,
|
||||
// the padding will always be 16 bytes.
|
||||
if (license.key(i).key().size() > 32) {
|
||||
length = license.key(i).key().size() - 16;
|
||||
} else {
|
||||
length = 0;
|
||||
// We always take the first ENTITLEMENT_KEY_SIZE bytes and ignore the
|
||||
// rest in order to ignore any padding.
|
||||
if (license.key(i).key().size() < ENTITLEMENT_KEY_SIZE) {
|
||||
LOGE(
|
||||
"Skipping key %s because it is too small. Expected: %zu vs. "
|
||||
"Actual: %zu",
|
||||
license.key(i).id().c_str(), ENTITLEMENT_KEY_SIZE,
|
||||
license.key(i).key().size());
|
||||
continue;
|
||||
}
|
||||
key.set_key_data(license.key(i).key().substr(0, length));
|
||||
key.set_key_data(license.key(i).key().substr(0, ENTITLEMENT_KEY_SIZE));
|
||||
key.set_key_data_iv(license.key(i).iv());
|
||||
key.set_key_id(license.key(i).id());
|
||||
key.set_track_label(license.key(i).track_label());
|
||||
@@ -111,20 +113,21 @@ std::vector<CryptoKey> ExtractContentKeys(const License& license) {
|
||||
// Extract content key(s)
|
||||
for (int i = 0; i < license.key_size(); ++i) {
|
||||
CryptoKey key;
|
||||
size_t length;
|
||||
switch (license.key(i).type()) {
|
||||
case License_KeyContainer::CONTENT:
|
||||
case License_KeyContainer::OPERATOR_SESSION: {
|
||||
key.set_key_id(license.key(i).id());
|
||||
// Strip off PKCS#5 padding - since we know the key is 16 or 32 bytes,
|
||||
// the padding will always be 16 bytes.
|
||||
// TODO(b/111069024): remove this!
|
||||
if (license.key(i).key().size() > 16) {
|
||||
length = license.key(i).key().size() - 16;
|
||||
} else {
|
||||
length = 0;
|
||||
// We always take the first CONTENT_KEY_SIZE bytes and ignore the rest
|
||||
// in order to ignore any padding.
|
||||
if (license.key(i).key().size() < CONTENT_KEY_SIZE) {
|
||||
LOGE(
|
||||
"Skipping key %s because it is too small. Expected: %zu vs. "
|
||||
"Actual: %zu",
|
||||
license.key(i).id().c_str(), CONTENT_KEY_SIZE,
|
||||
license.key(i).key().size());
|
||||
continue;
|
||||
}
|
||||
key.set_key_data(license.key(i).key().substr(0, length));
|
||||
key.set_key_data(license.key(i).key().substr(0, CONTENT_KEY_SIZE));
|
||||
key.set_key_data_iv(license.key(i).iv());
|
||||
if (license.key(i).has_key_control()) {
|
||||
key.set_key_control(license.key(i).key_control().key_control_block());
|
||||
|
||||
Reference in New Issue
Block a user