Commit 5287c3c5 authored by xhwang's avatar xhwang Committed by Commit bot

Encrypted Media: Check "alg":"A128KW" in AesDecryptor.

BUG=444713
TEST=Add tests to cover this case.
R=jrummell@chromium.org

Review URL: https://codereview.chromium.org/798583003

Cr-Commit-Position: refs/heads/master@{#309543}
parent fd59a531
......@@ -293,21 +293,21 @@ void AesDecryptor::UpdateSession(const std::string& web_session_id,
SessionType session_type = MediaKeys::TEMPORARY_SESSION;
if (!ExtractKeysFromJWKSet(key_string, &keys, &session_type)) {
promise->reject(
INVALID_ACCESS_ERROR, 0, "response is not a valid JSON Web Key Set.");
INVALID_ACCESS_ERROR, 0, "Response is not a valid JSON Web Key Set.");
return;
}
// Make sure that at least one key was extracted.
if (keys.empty()) {
promise->reject(
INVALID_ACCESS_ERROR, 0, "response does not contain any keys.");
INVALID_ACCESS_ERROR, 0, "Response does not contain any keys.");
return;
}
for (KeyIdAndKeyPairs::iterator it = keys.begin(); it != keys.end(); ++it) {
if (it->second.length() !=
static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) {
DVLOG(1) << "Invalid key length: " << key_string.length();
DVLOG(1) << "Invalid key length: " << it->second.length();
promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid key length.");
return;
}
......
......@@ -55,6 +55,7 @@ const char kKeyAsJWK[] =
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
......@@ -68,6 +69,7 @@ const char kKeyAlternateAsJWK[] =
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw\","
" \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" }"
......@@ -79,6 +81,7 @@ const char kWrongKeyAsJWK[] =
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw\","
" \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
" }"
......@@ -90,6 +93,7 @@ const char kWrongSizedKeyAsJWK[] =
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw\","
" \"k\": \"AAECAw\""
" }"
......@@ -136,6 +140,7 @@ const char kKey2AsJWK[] =
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
" \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" }"
......@@ -713,6 +718,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
const std::string kJwkSimple =
"{"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
" \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
"}";
......@@ -724,11 +730,13 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
" \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" },"
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"JCUmJygpKissLS4vMA\","
" \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
" }"
......@@ -773,6 +781,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
" }"
......@@ -786,6 +795,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"AAECAw==\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
......@@ -799,6 +809,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"!@#$%^&*()\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
......@@ -814,6 +825,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"Kiss\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
......@@ -827,6 +839,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"keys\": ["
" {"
" \"kty\": \"oct\","
" \"alg\": \"A128KW\","
" \"kid\": \"\","
" \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
......
......@@ -17,7 +17,9 @@ namespace media {
const char kKeysTag[] = "keys";
const char kKeyTypeTag[] = "kty";
const char kSymmetricKeyValue[] = "oct";
const char kKeyTypeOct[] = "oct"; // Octet sequence.
const char kAlgTag[] = "alg";
const char kAlgA128KW[] = "A128KW"; // AES key wrap using a 128-bit key.
const char kKeyTag[] = "k";
const char kKeyIdTag[] = "kid";
const char kKeyIdsTag[] = "kids";
......@@ -44,8 +46,10 @@ static std::string EncodeBase64(const uint8* input, int input_length) {
// Decodes an unpadded base64 string. Returns empty string on error.
static std::string DecodeBase64(const std::string& encoded_text) {
// EME spec doesn't allow padding characters.
if (encoded_text.find_first_of(kBase64Padding) != std::string::npos)
if (encoded_text.find_first_of(kBase64Padding) != std::string::npos) {
DVLOG(1) << "Padding characters not allowed: " << encoded_text;
return std::string();
}
// Since base::Base64Decode() requires padding characters, add them so length
// of |encoded_text| is exactly a multiple of 4.
......@@ -55,8 +59,10 @@ static std::string DecodeBase64(const std::string& encoded_text) {
modified_text.append(4 - num_last_grouping_chars, kBase64Padding);
std::string decoded_text;
if (!base::Base64Decode(modified_text, &decoded_text))
if (!base::Base64Decode(modified_text, &decoded_text)) {
DVLOG(1) << "Base64 decoding failed on: " << modified_text;
return std::string();
}
return decoded_text;
}
......@@ -69,7 +75,8 @@ std::string GenerateJWKSet(const uint8* key, int key_length,
// Create the JWK, and wrap it into a JWK Set.
scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue());
jwk->SetString(kKeyTypeTag, kSymmetricKeyValue);
jwk->SetString(kKeyTypeTag, kKeyTypeOct);
jwk->SetString(kAlgTag, kAlgA128KW);
jwk->SetString(kKeyTag, key_base64);
jwk->SetString(kKeyIdTag, key_id_base64);
scoped_ptr<base::ListValue> list(new base::ListValue());
......@@ -88,10 +95,15 @@ std::string GenerateJWKSet(const uint8* key, int key_length,
// to the id/value pair and returns true on success.
static bool ConvertJwkToKeyPair(const base::DictionaryValue& jwk,
KeyIdAndKeyPair* jwk_key) {
// Have found a JWK, start by checking that it is a symmetric key.
std::string type;
if (!jwk.GetString(kKeyTypeTag, &type) || type != kSymmetricKeyValue) {
DVLOG(1) << "JWK is not a symmetric key";
if (!jwk.GetString(kKeyTypeTag, &type) || type != kKeyTypeOct) {
DVLOG(1) << "Missing or invalid '" << kKeyTypeTag << "': " << type;
return false;
}
std::string alg;
if (!jwk.GetString(kAlgTag, &alg) || alg != kAlgA128KW) {
DVLOG(1) << "Missing or invalid '" << kAlgTag << "': " << alg;
return false;
}
......@@ -128,12 +140,16 @@ static bool ConvertJwkToKeyPair(const base::DictionaryValue& jwk,
bool ExtractKeysFromJWKSet(const std::string& jwk_set,
KeyIdAndKeyPairs* keys,
MediaKeys::SessionType* session_type) {
if (!base::IsStringASCII(jwk_set))
if (!base::IsStringASCII(jwk_set)) {
DVLOG(1) << "Non ASCII JWK Set: " << jwk_set;
return false;
}
scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(jwk_set));
if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY)
if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) {
DVLOG(1) << "Not valid JSON: " << jwk_set << ", root: " << root.get();
return false;
}
// Locate the set from the dictionary.
base::DictionaryValue* dictionary =
......@@ -221,12 +237,16 @@ bool ExtractFirstKeyIdFromLicenseRequest(const std::vector<uint8>& license,
const std::string license_as_str(
reinterpret_cast<const char*>(!license.empty() ? &license[0] : NULL),
license.size());
if (!base::IsStringASCII(license_as_str))
if (!base::IsStringASCII(license_as_str)) {
DVLOG(1) << "Non ASCII license: " << license_as_str;
return false;
}
scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(license_as_str));
if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY)
if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) {
DVLOG(1) << "Not valid JSON: " << license_as_str;
return false;
}
// Locate the set from the dictionary.
base::DictionaryValue* dictionary =
......
This diff is collapsed.
......@@ -56,7 +56,7 @@ Utils.createJWKData = function(keyId, key) {
// Creates a JWK from raw key ID and key.
function createJWK(keyId, key) {
var jwk = '{"kty":"oct","kid":"';
var jwk = '{"kty":"oct","alg":"A128KW","kid":"';
jwk += base64Encode(keyId);
jwk += '","k":"';
jwk += base64Encode(key);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment