1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/cdm/json_web_key.h"
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace media {
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class JSONWebKeyTest : public testing::Test {
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  JSONWebKeyTest() {}
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void ExtractJWKKeysAndExpect(const std::string& jwk,
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               bool expected_result,
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                               size_t expected_number_of_keys) {
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(!jwk.empty());
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    KeyIdAndKeyPairs keys;
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    MediaKeys::SessionType session_type;
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(expected_result,
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              ExtractKeysFromJWKSet(jwk, &keys, &session_type));
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EXPECT_EQ(expected_number_of_keys, keys.size());
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void ExtractSessionTypeAndExpect(const std::string& jwk,
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                   bool expected_result,
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                   MediaKeys::SessionType expected_type) {
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    DCHECK(!jwk.empty());
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    KeyIdAndKeyPairs keys;
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    MediaKeys::SessionType session_type;
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(expected_result,
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              ExtractKeysFromJWKSet(jwk, &keys, &session_type));
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (expected_result) {
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      // Only check if successful.
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      EXPECT_EQ(expected_type, session_type);
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void CreateLicenseAndExpect(const uint8* key_id,
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              int key_id_length,
4403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              MediaKeys::SessionType session_type,
4503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                              const std::string& expected_result) {
4603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<uint8> result;
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    CreateLicenseRequest(key_id, key_id_length, session_type, &result);
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::string s(result.begin(), result.end());
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(expected_result, s);
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
5103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  void ExtractKeyFromLicenseAndExpect(const std::string& license,
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      bool expected_result,
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      const uint8* expected_key,
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                      int expected_key_length) {
5603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<uint8> license_vector(license.begin(), license.end());
5703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    std::vector<uint8> key;
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    EXPECT_EQ(expected_result,
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)              ExtractFirstKeyIdFromLicenseRequest(license_vector, &key));
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    if (expected_result) {
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      std::vector<uint8> key_result(expected_key,
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                    expected_key + expected_key_length);
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      EXPECT_EQ(key_result, key);
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
6503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(JSONWebKeyTest, GenerateJWKSet) {
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const uint8 data1[] = { 0x01, 0x02 };
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            GenerateJWKSet(data1, arraysize(data1), data1, arraysize(data1)));
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GenerateJWKSet(data2, arraysize(data2), data2, arraysize(data2)));
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ("{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQIDBA\",\"kty\":\"oct\"}]}",
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            GenerateJWKSet(data1, arraysize(data1), data2, arraysize(data2)));
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ("{\"keys\":[{\"k\":\"AQIDBA\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            GenerateJWKSet(data2, arraysize(data2), data1, arraysize(data1)));
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EXPECT_EQ(
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{\"keys\":[{\"k\":\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kid\":"
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\"AQIDBAUGBwgJCgsMDQ4PEA\",\"kty\":\"oct\"}]}",
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      GenerateJWKSet(data3, arraysize(data3), data3, arraysize(data3)));
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(JSONWebKeyTest, ExtractJWKKeys) {
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a simple JWK key (i.e. not in a set)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwkSimple =
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"kty\": \"oct\","
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwkSimple, false, 0);
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a key list with multiple entries.
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksMultipleEntries =
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    },"
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"JCUmJygpKissLS4vMA\","
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksMultipleEntries, true, 2);
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a key with no spaces and some \n plus additional fields.
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksNoSpaces =
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\",\"foo\":\"bar\"}]}\n\n";
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksNoSpaces, true, 1);
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try some non-ASCII characters.
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "This is not ASCII due to \xff\xfe\xfd in it.", false, 0);
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try some non-ASCII characters in an otherwise valid JWK.
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksInvalidCharacters =
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"\xff\xfe\xfd"
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "\",\"foo\":\"bar\"}]}\n\n";
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksInvalidCharacters, false, 0);
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a badly formatted key. Assume that the JSON parser is fully tested,
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // so we won't try a lot of combinations. However, need a test to ensure
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // that the code doesn't crash if invalid JSON received.
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("This is not a JSON key.", false, 0);
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try passing some valid JSON that is not a dictionary at the top level.
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("40", false, 0);
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try an empty dictionary.
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("{ }", false, 0);
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try an empty 'keys' dictionary.
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("{ \"keys\": [] }", true, 0);
148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try with 'keys' not a dictionary.
150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("{ \"keys\":\"1\" }", false, 0);
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try with 'keys' a list of integers.
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect("{ \"keys\": [ 1, 2, 3 ] }", false, 0);
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try padding(=) at end of 'k' base64 string.
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksWithPaddedKey =
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"AAECAw\","
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksWithPaddedKey, false, 0);
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try padding(=) at end of 'kid' base64 string.
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksWithPaddedKeyId =
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"AAECAw==\","
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksWithPaddedKeyId, false, 0);
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a key with invalid base64 encoding.
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksWithInvalidBase64 =
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"!@#$%^&*()\","
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksWithInvalidBase64, false, 0);
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Empty key id.
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksWithEmptyKeyId =
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"\","
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksWithEmptyKeyId, false, 0);
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Try a list with multiple keys with the same kid.
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const std::string kJwksDuplicateKids =
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "{"
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  \"keys\": ["
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"JCUmJygpKissLS4vMA\","
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    },"
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    {"
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kty\": \"oct\","
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"kid\": \"JCUmJygpKissLS4vMA\","
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "      \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "    }"
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "  ]"
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "}";
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ExtractJWKKeysAndExpect(kJwksDuplicateKids, true, 2);
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
22603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(JSONWebKeyTest, SessionType) {
22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractSessionTypeAndExpect(
22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}]}",
22903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
23003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::TEMPORARY_SESSION);
23103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractSessionTypeAndExpect(
23203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
23303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "\"temporary\"}",
23403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
23503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::TEMPORARY_SESSION);
23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractSessionTypeAndExpect(
23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "\"persistent\"}",
23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::PERSISTENT_SESSION);
24103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractSessionTypeAndExpect(
24203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":"
24303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "\"unknown\"}",
24403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      false,
24503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::TEMPORARY_SESSION);
24603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractSessionTypeAndExpect(
24703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"keys\":[{\"k\":\"AQI\",\"kid\":\"AQI\",\"kty\":\"oct\"}],\"type\":3}",
24803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      false,
24903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::TEMPORARY_SESSION);
25003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
25103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(JSONWebKeyTest, CreateLicense) {
25303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data1[] = { 0x01, 0x02 };
25403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
25503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
25603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
25703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
25803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateLicenseAndExpect(data1,
25903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         arraysize(data1),
26003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         MediaKeys::TEMPORARY_SESSION,
26103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}");
26203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateLicenseAndExpect(data1,
26303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         arraysize(data1),
26403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         MediaKeys::PERSISTENT_SESSION,
26503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         "{\"kids\":[\"AQI\"],\"type\":\"persistent\"}");
26603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateLicenseAndExpect(data2,
26703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         arraysize(data2),
26803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         MediaKeys::TEMPORARY_SESSION,
26903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}");
27003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CreateLicenseAndExpect(
27103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data3,
27203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      arraysize(data3),
27303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      MediaKeys::PERSISTENT_SESSION,
27403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":\"persistent\"}");
27503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
27603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
27703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(JSONWebKeyTest, ExtractLicense) {
27803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data1[] = { 0x01, 0x02 };
27903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data2[] = { 0x01, 0x02, 0x03, 0x04 };
28003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const uint8 data3[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
28103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                          0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 };
28203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
28303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect(
28403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"kids\":[\"AQI\"],\"type\":\"temporary\"}",
28503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
28603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data1,
28703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      arraysize(data1));
28803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect(
28903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"kids\":[\"AQIDBA\"],\"type\":\"temporary\"}",
29003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
29103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data2,
29203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      arraysize(data2));
29303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect(
29403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      "{\"kids\":[\"AQIDBAUGBwgJCgsMDQ4PEA\"],\"type\":\"persistent\"}",
29503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      true,
29603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      data3,
29703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)      arraysize(data3));
29803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Try some incorrect JSON.
30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("", false, NULL, 0);
30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("!@#$%^&*()", false, NULL, 0);
30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
30303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Valid JSON, but not a dictionary.
30403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("6", false, NULL, 0);
30503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("[\"AQI\"]", false, NULL, 0);
30603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
30703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Dictionary, but missing expected tag.
30803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("{\"kid\":[\"AQI\"]}", false, NULL, 0);
30903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
31003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Correct tag, but empty list.
31103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("{\"kids\":[]}", false, NULL, 0);
31203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
31303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Correct tag, but list doesn't contain a string.
31403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("{\"kids\":[[\"AQI\"]]}", false, NULL, 0);
31503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
31603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Correct tag, but invalid base64 encoding.
31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  ExtractKeyFromLicenseAndExpect("{\"kids\":[\"!@#$%^&*()\"]}", false, NULL, 0);
31803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
31903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace media
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
322