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 23 namespace clearkeydrm { 24 using android::String8; 25 using android::Vector; 26 27 class 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 41 void 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 53 void 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 65 TEST_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 81 TEST_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 103 TEST_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 128 TEST_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 153 TEST_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 191 TEST_F(JsonWebKeyTest, EmptyJsonWebKey) { 192 const String8 js; 193 KeyMap keys; 194 EXPECT_FALSE(jwk->extractKeysFromJsonWebKeySet(js, &keys)); 195 EXPECT_TRUE(keys.isEmpty()); 196 } 197 198 TEST_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 217 TEST_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 250 TEST_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 281 TEST_F(JsonWebKeyTest, ExtractKeys) { 282 const String8 js( 283 "{" 284 "\"keys\":" 285 "[{" 286 "\"kid\":\"Y2xlYXJrZXlrZXlpZDAx\"" 287 "\"k\":\"SGVsbG8gRnJpZW5kICE-Pw\"" 288 "\"kty\":\"oct\"" 289 "\"alg\":\"A128KW1\"" 290 "}" 291 "{" 292 "\"kty\":\"oct\"" 293 "\"alg\":\"A128KW2\"" 294 "\"k\":\"SGVsbG8gRnJpZW5kICE_\"" 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\":\"SGVsbG8gPz4-IEZyaWVuZCA_Pg\"" 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("Hello ?>> Friend ?>") }; 318 verifyKeys(keys, clearKeys); 319 } 320 321 } // namespace clearkeydrm 322