Home | History | Annotate | Download | only in cdm
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "media/cdm/json_web_key.h"
      6 
      7 #include "base/logging.h"
      8 #include "testing/gtest/include/gtest/gtest.h"
      9 
     10 namespace media {
     11 
     12 class JSONWebKeyTest : public testing::Test {
     13  public:
     14   JSONWebKeyTest() {}
     15 
     16  protected:
     17   void ExtractJWKKeysAndExpect(const std::string& jwk,
     18                                bool expected_result,
     19                                size_t expected_number_of_keys) {
     20     DCHECK(!jwk.empty());
     21     KeyIdAndKeyPairs keys;
     22     EXPECT_EQ(expected_result, ExtractKeysFromJWKSet(jwk, &keys));
     23     EXPECT_EQ(expected_number_of_keys, keys.size());
     24   }
     25 };
     26 
     27 TEST_F(JSONWebKeyTest, GenerateJWKSet) {
     28   const uint8 data1[] = { 0x01, 0x02 };
     29   const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
     30   const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
     31                           0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
     32 
     33   EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
     34             GenerateJWKSet(data1, arraysize(data1), data1, arraysize(data1)));
     35   EXPECT_EQ(
     36       "{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
     37       GenerateJWKSet(data2, arraysize(data2), data2, arraysize(data2)));
     38   EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
     39             GenerateJWKSet(data1, arraysize(data1), data2, arraysize(data2)));
     40   EXPECT_EQ("{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
     41             GenerateJWKSet(data2, arraysize(data2), data1, arraysize(data1)));
     42   EXPECT_EQ(
     43       "{\"keys\":[{\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":"
     44       "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}",
     45       GenerateJWKSet(data3, arraysize(data3), data3, arraysize(data3)));
     46 }
     47 
     48 TEST_F(JSONWebKeyTest, ExtractJWKKeys) {
     49   // Try a simple JWK key (i.e. not in a set)
     50   const std::string kJwkSimple =
     51       "{"
     52       "  \"kty\": \"oct\","
     53       "  \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
     54       "  \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
     55       "}";
     56   ExtractJWKKeysAndExpect(kJwkSimple, false, 0);
     57 
     58   // Try a key list with multiple entries.
     59   const std::string kJwksMultipleEntries =
     60       "{"
     61       "  \"keys\": ["
     62       "    {"
     63       "      \"kty\": \"oct\","
     64       "      \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
     65       "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
     66       "    },"
     67       "    {"
     68       "      \"kty\": \"oct\","
     69       "      \"kid\": \"JCUmJygpKissLS4vMA\","
     70       "      \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
     71       "    }"
     72       "  ]"
     73       "}";
     74   ExtractJWKKeysAndExpect(kJwksMultipleEntries, true, 2);
     75 
     76   // Try a key with no spaces and some \n plus additional fields.
     77   const std::string kJwksNoSpaces =
     78       "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
     79       "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
     80       "\",\"foo\":\"bar\"}]}\n\n";
     81   ExtractJWKKeysAndExpect(kJwksNoSpaces, true, 1);
     82 
     83   // Try some non-ASCII characters.
     84   ExtractJWKKeysAndExpect(
     85       "This is not ASCII due to \xff\xfe\xfd in it.", false, 0);
     86 
     87   // Try some non-ASCII characters in an otherwise valid JWK.
     88   const std::string kJwksInvalidCharacters =
     89       "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
     90       "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd"
     91       "\",\"foo\":\"bar\"}]}\n\n";
     92   ExtractJWKKeysAndExpect(kJwksInvalidCharacters, false, 0);
     93 
     94   // Try a badly formatted key. Assume that the JSON parser is fully tested,
     95   // so we won't try a lot of combinations. However, need a test to ensure
     96   // that the code doesn't crash if invalid JSON received.
     97   ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0);
     98 
     99   // Try passing some valid JSON that is not a dictionary at the top level.
    100   ExtractJWKKeysAndExpect("40", false, 0);
    101 
    102   // Try an empty dictionary.
    103   ExtractJWKKeysAndExpect("{ }", false, 0);
    104 
    105   // Try an empty 'keys' dictionary.
    106   ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0);
    107 
    108   // Try with 'keys' not a dictionary.
    109   ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0);
    110 
    111   // Try with 'keys' a list of integers.
    112   ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0);
    113 
    114   // Try padding(=) at end of 'k' base64 string.
    115   const std::string kJwksWithPaddedKey =
    116       "{"
    117       "  \"keys\": ["
    118       "    {"
    119       "      \"kty\": \"oct\","
    120       "      \"kid\": \"AAECAw\","
    121       "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
    122       "    }"
    123       "  ]"
    124       "}";
    125   ExtractJWKKeysAndExpect(kJwksWithPaddedKey, false, 0);
    126 
    127   // Try padding(=) at end of 'kid' base64 string.
    128   const std::string kJwksWithPaddedKeyId =
    129       "{"
    130       "  \"keys\": ["
    131       "    {"
    132       "      \"kty\": \"oct\","
    133       "      \"kid\": \"AAECAw==\","
    134       "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
    135       "    }"
    136       "  ]"
    137       "}";
    138   ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId, false, 0);
    139 
    140   // Try a key with invalid base64 encoding.
    141   const std::string kJwksWithInvalidBase64 =
    142       "{"
    143       "  \"keys\": ["
    144       "    {"
    145       "      \"kty\": \"oct\","
    146       "      \"kid\": \"!@#$%^&*()\","
    147       "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
    148       "    }"
    149       "  ]"
    150       "}";
    151   ExtractJWKKeysAndExpect(kJwksWithInvalidBase64, false, 0);
    152 
    153   // Empty key id.
    154   const std::string kJwksWithEmptyKeyId =
    155       "{"
    156       "  \"keys\": ["
    157       "    {"
    158       "      \"kty\": \"oct\","
    159       "      \"kid\": \"\","
    160       "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
    161       "    }"
    162       "  ]"
    163       "}";
    164   ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId, false, 0);
    165 
    166   // Try a list with multiple keys with the same kid.
    167   const std::string kJwksDuplicateKids =
    168       "{"
    169       "  \"keys\": ["
    170       "    {"
    171       "      \"kty\": \"oct\","
    172       "      \"kid\": \"JCUmJygpKissLS4vMA\","
    173       "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
    174       "    },"
    175       "    {"
    176       "      \"kty\": \"oct\","
    177       "      \"kid\": \"JCUmJygpKissLS4vMA\","
    178       "      \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
    179       "    }"
    180       "  ]"
    181       "}";
    182   ExtractJWKKeysAndExpect(kJwksDuplicateKids, true, 2);
    183 }
    184 
    185 }  // namespace media
    186 
    187