1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <utils/Log.h>
17
18#include "JsonWebKey.h"
19
20#include "gtest/gtest.h"
21#include "Utils.h"
22
23namespace clearkeydrm {
24using android::String8;
25using android::Vector;
26
27class JsonWebKeyTest : public ::testing::Test {
28 protected:
29    JsonWebKey* jwk;
30
31    JsonWebKeyTest() {
32        jwk = new JsonWebKey;
33    }
34
35    virtual ~JsonWebKeyTest() {
36        if (jwk)
37            delete jwk;
38    }
39};
40
41void stringFromVector(const Vector<uint8_t>& input,
42        String8* converted) {
43    converted->clear();
44    if (input.isEmpty()) {
45        return;
46    }
47
48    for (size_t i = 0; i < input.size(); ++i) {
49        converted->appendFormat("%c", input.itemAt(i));
50    }
51}
52
53void verifyKeys(const KeyMap& keys, const String8* clearKeys) {
54    if (keys.isEmpty()) {
55        return;
56    }
57
58    String8 keyString;
59    for (size_t i = 0; i < keys.size(); ++i) {
60        stringFromVector(keys.valueAt(i), &keyString);
61        EXPECT_EQ(keyString, clearKeys[i]);
62    }
63}
64
65TEST_F(JsonWebKeyTest, NoSymmetricKey) {
66    const String8 js(
67            "{"
68                "[{"
69                    "\"kty\":\"rsa\","
70                    "\"alg\":\"A128KW1\","
71                    "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\","
72                    "\"k\":\"1-GawgguFyGrWKav7AX4VKUg\""
73                "}]"
74          "}");
75
76    KeyMap keys;
77    EXPECT_FALSE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
78    EXPECT_TRUE(keys.isEmpty());
79}
80
81TEST_F(JsonWebKeyTest, NoKeysTag) {
82    const String8 js(
83            "{"
84                "[{"
85                    "\"kty\":\"oct\","
86                    "\"alg\":\"A128KW1\","
87                    "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\","
88                    "\"k\":\"1-GawgguFyGrWKav7AX4VKUg\""
89                "},"
90                "{"
91                    "\"kty\":\"oct\","
92                    "\"alg\":\"A128KW2\","
93                    "\"k\":\"R29vZCBkYXkh\","
94                    "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
95                "}]"
96            "}");
97
98    KeyMap keys;
99    EXPECT_FALSE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
100    EXPECT_TRUE(keys.isEmpty());
101}
102
103TEST_F(JsonWebKeyTest, NoKeyId) {
104    const String8 js(
105            "{"
106                "\"keys\":"
107                    "[{"
108                        "\"kty\":\"oct\""
109                        "\"alg\":\"A128KW1\""
110                        "\"k\":\"SGVsbG8gRnJpZW5kISE=\""
111                    "}"
112                    "{"
113                        "\"kty\":\"oct\""
114                        "\"alg\":\"A128KW2\""
115                        "\"k\":\"R29vZCBkYXkh\""
116                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
117                    "}]"
118            "}");
119
120    KeyMap keys;
121    EXPECT_TRUE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
122    EXPECT_TRUE(keys.size() == 1);
123
124    const String8 clearKeys("Good day!");
125    verifyKeys(keys, &clearKeys);
126}
127
128TEST_F(JsonWebKeyTest, NoKey) {
129    const String8 js(
130            "{"
131                "\"keys\":"
132                    "[{"
133                        "\"kty\":\"oct\""
134                        "\"alg\":\"A128KW1\""
135                        "\"kid\":\"`\""
136                    "}"
137                    "{"
138                        "\"kty\":\"oct\""
139                        "\"alg\":\"A128KW2\""
140                        "\"k\":\"R29vZCBkYXkh\""
141                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
142                    "}]"
143            "}");
144
145    KeyMap keys;
146    EXPECT_TRUE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
147    EXPECT_TRUE(keys.size() == 1);
148
149    const String8 clearKeys("Good day!");
150    verifyKeys(keys, &clearKeys);
151}
152
153TEST_F(JsonWebKeyTest, MalformedKey) {
154    const String8 js(
155            "{"
156                "\"keys\":"
157                    "[{"
158                        "\"kty\":\"oct\""
159                        "\"alg\":\"A128KW1\""
160                        "\"k\":\"GawgguFyGrWKav7AX4V???\""
161                        "\"kid\":\"67ef0gd8pvfd0=\""
162                    "}"
163                    "{"
164                        "\"kty\":\"oct\""
165                        "\"alg\":\"A128KW1\""
166                        "\"k\":\"GawgguFyGrWKav7AX4V???\""
167                        "\"kid\":"
168                    "}"
169                    "{"
170                        "\"kty\":\"oct\""
171                        "\"alg\":\"A128KW1\""
172                        ":\"GawgguFyGrWKav7AX4V???\""
173                        "\"kid\":\"67ef0gd8pvfd0=\""
174                    "}"
175                    "{"
176                        "\"kty\":\"oct\""
177                        "\"alg\":\"A128KW3\""
178                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
179                        "\"k\":\"R29vZCBkYXkh\""
180                    "}]"
181            "}");
182
183    KeyMap keys;
184    EXPECT_TRUE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
185    EXPECT_TRUE(keys.size() == 1);
186
187    const String8 clearKeys("Good day!");
188    verifyKeys(keys, &clearKeys);
189}
190
191TEST_F(JsonWebKeyTest, EmptyJsonWebKey) {
192    const String8 js;
193    KeyMap keys;
194    EXPECT_FALSE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
195    EXPECT_TRUE(keys.isEmpty());
196}
197
198TEST_F(JsonWebKeyTest, MalformedJsonWebKey) {
199    // Missing begin array '['
200    const String8 js(
201            "{"
202                "\"keys\":"
203                    "{"
204                        "\"kty\":\"oct\""
205                        "\"alg\":\"A128KW1\""
206                        "\"k\":\"GawgguFyGrWKav7AX4VKUg\""
207                        "\"kid\":\"67ef0gd8pvfd0=\""
208                    "}"
209            "]"
210            "}");
211
212    KeyMap keys;
213    EXPECT_FALSE(jwk->extractKeysFromJsonWebKeySet(js, &keys));
214    EXPECT_TRUE(keys.isEmpty());
215}
216
217TEST_F(JsonWebKeyTest, SameKeyId) {
218    const String8 js(
219            "{"
220                "\"keys\":"
221                    "[{"
222                        "\"kty\":\"oct\""
223                        "\"alg\":\"A128KW1\""
224                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\""
225                        "\"k\":\"SGVsbG8gRnJpZW5kISE\""
226                    "}"
227                    "{"
228                        "\"kty\":\"oct\""
229                        "\"alg\":\"A128KW1\""
230                        "\"k\":\"SGVsbG8gRnJpZW5kIQ\""
231                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\""
232                    "}"
233                    "{"
234                        "\"kty\":\"oct\""
235                        "\"alg\":\"A128KW3\""
236                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
237                        "\"k\":\"R29vZCBkYXkh\""
238                    "}]"
239            "}");
240
241    KeyMap keys;
242    jwk->extractKeysFromJsonWebKeySet(js, &keys);
243    EXPECT_TRUE(keys.size() == 2);
244
245    const String8 clearKeys[] =
246            { String8("Hello Friend!"), String8("Good day!") };
247    verifyKeys(keys, clearKeys);
248}
249
250TEST_F(JsonWebKeyTest, ExtractWellFormedKeys) {
251    const String8 js(
252            "{"
253                "\"keys\":"
254                    "[{"
255                        "\"kty\":\"oct\""
256                        "\"alg\":\"A128KW1\""
257                    "}"
258                    "{"
259                        "\"kty\":\"oct\""
260                        "\"alg\":\"A128KW2\""
261                        "\"k\":\"SGVsbG8gRnJpZW5kIQ\""
262                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
263                    "}"
264                    "{"
265                        "\"kty\":\"oct\""
266                        "\"alg\":\"A128KW3\""
267                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
268                        "\"k\":\"R29vZCBkYXkh\""
269                    "}]"
270            "}");
271
272    KeyMap keys;
273    jwk->extractKeysFromJsonWebKeySet(js, &keys);
274    EXPECT_TRUE(keys.size() == 2);
275
276    const String8 clearKeys[] =
277            { String8("Hello Friend!"), String8("Good day!") };
278    verifyKeys(keys, clearKeys);
279}
280
281TEST_F(JsonWebKeyTest, ExtractKeys) {
282    const String8 js(
283            "{"
284                "\"keys\":"
285                    "[{"
286                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\""
287                        "\"k\":\"SGVsbG8gRnJpZW5kISE\""
288                        "\"kty\":\"oct\""
289                        "\"alg\":\"A128KW1\""
290                    "}"
291                    "{"
292                        "\"kty\":\"oct\""
293                        "\"alg\":\"A128KW2\""
294                        "\"k\":\"SGVsbG8gRnJpZW5kIQ\""
295                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAy\""
296                    "}"
297                    "{"
298                        "\"kty\":\"rsa\""
299                        "\"alg\":\"A128KW-rsa\""
300                        "\"k\":\"R29vZCBkYXkh\""
301                        "\"kid\":\"rsa-67ef0gd8pvfd0=\""
302                    "}"
303                    "{"
304                        "\"alg\":\"A128KW3\""
305                        "\"kid\":\"Y2xlYXJrZXlrZXlpZDAz\""
306                        "\"k\":\"R29vZCBkYXkh\""
307                        "\"kty\":\"oct\""
308                    "}]"
309            "}");
310
311    KeyMap keys;
312    jwk->extractKeysFromJsonWebKeySet(js, &keys);
313    EXPECT_TRUE(keys.size() == 3);
314
315    const String8 clearKeys[] =
316            { String8("Hello Friend!!"), String8("Hello Friend!"),
317              String8("Good day!") };
318    verifyKeys(keys, clearKeys);
319}
320
321}  // namespace clearkeydrm
322