17bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/* 27bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Copyright (C) 2014 The Android Open Source Project 37bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 47bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Licensed under the Apache License, Version 2.0 (the "License"); 57bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * you may not use this file except in compliance with the License. 67bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * You may obtain a copy of the License at 77bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 87bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * http://www.apache.org/licenses/LICENSE-2.0 97bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 107bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Unless required by applicable law or agreed to in writing, software 117bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * distributed under the License is distributed on an "AS IS" BASIS, 127bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * See the License for the specific language governing permissions and 147bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * limitations under the License. 157bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */ 167bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#define LOG_TAG "JsonWebKey" 177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include <media/stagefright/foundation/ABuffer.h> 197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include <media/stagefright/foundation/AString.h> 207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include <media/stagefright/foundation/base64.h> 217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include <utils/Log.h> 227bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 237bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include "JsonWebKey.h" 247bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 257bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongnamespace { 267bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kKeysTag("keys"); 277bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kKeyTypeTag("kty"); 287bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kSymmetricKeyValue("oct"); 297bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kKeyTag("k"); 307bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kKeyIdTag("kid"); 317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongconst android::String8 kBase64Padding("="); 327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 337bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 347bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongnamespace clearkeydrm { 357bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 367bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongusing android::ABuffer; 377bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongusing android::AString; 387bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 397bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin WongJsonWebKey::JsonWebKey() { 407bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 417bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 427bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin WongJsonWebKey::~JsonWebKey() { 437bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 447bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 457bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/* 467bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Parses a JSON Web Key Set string, initializes a KeyMap with key id:key 477bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * pairs from the JSON Web Key Set. Both key ids and keys are base64url 487bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * encoded. The KeyMap contains base64url decoded key id:key pairs. 497bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 507bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * @return Returns false for errors, true for success. 517bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */ 527bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::extractKeysFromJsonWebKeySet(const String8& jsonWebKeySet, 537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong KeyMap* keys) { 547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 557bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong keys->clear(); 567bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) { 577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 587bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // mJsonObjects[0] contains the entire JSON Web Key Set, including 617bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // all the base64 encoded keys. Each key is also stored separately as 627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // a JSON object in mJsonObjects[1..n] where n is the total 637bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // number of keys in the set. 647bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (!isJsonWebKeySet(mJsonObjects[0])) { 657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8 encodedKey, encodedKeyId; 697bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong Vector<uint8_t> decodedKey, decodedKeyId; 707bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 717bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // mJsonObjects[1] contains the first JSON Web Key in the set 727bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong for (size_t i = 1; i < mJsonObjects.size(); ++i) { 737bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong encodedKeyId.clear(); 747bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong encodedKey.clear(); 757bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 767bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (!parseJsonObject(mJsonObjects[i], &mTokens)) 777bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 787bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 797bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) { 807bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (encodedKeyId.isEmpty() || encodedKey.isEmpty()) { 817bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Must have both key id and key in the JsonWebKey set."); 827bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong continue; 837bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 847bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 857bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (!decodeBase64String(encodedKeyId, &decodedKeyId)) { 867bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Failed to decode key id(%s)", encodedKeyId.string()); 877bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong continue; 887bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 897bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 907bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (!decodeBase64String(encodedKey, &decodedKey)) { 917bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Failed to decode key(%s)", encodedKey.string()); 927bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong continue; 937bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 947bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 957bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong keys->add(decodedKeyId, decodedKey); 967bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 977bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 987bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 997bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 1007bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1017bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::decodeBase64String(const String8& encodedText, 1027bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong Vector<uint8_t>* decodedText) { 1037bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1047bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong decodedText->clear(); 1057bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1067bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // encodedText should not contain padding characters as per EME spec. 1077bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (encodedText.find(kBase64Padding) != -1) { 1087bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 1097bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1107bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1117bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // Since android::decodeBase64() requires padding characters, 1127bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // add them so length of encodedText is exactly a multiple of 4. 1137bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong int remainder = encodedText.length() % 4; 1147bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8 paddedText(encodedText); 1157bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (remainder > 0) { 1167bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong for (int i = 0; i < 4 - remainder; ++i) { 1177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong paddedText.append(kBase64Padding); 1187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong android::sp<ABuffer> buffer = 1227bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong android::decodeBase64(AString(paddedText.string())); 1237bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (buffer == NULL) { 1247bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Malformed base64 encoded content found."); 1257bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 1267bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1277bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1287bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong decodedText->appendArray(buffer->base(), buffer->size()); 1297bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 1307bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 1317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::findKey(const String8& jsonObject, String8* keyId, 1337bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8* encodedKey) { 1347bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1357bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8 key, value; 1367bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1377bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // Only allow symmetric key, i.e. "kty":"oct" pair. 1387bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (jsonObject.find(kKeyTypeTag) >= 0) { 1397bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong findValue(kKeyTypeTag, &value); 1407bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (0 != value.compare(kSymmetricKeyValue)) 1417bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 1427bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1437bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1447bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (jsonObject.find(kKeyIdTag) >= 0) { 1457bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong findValue(kKeyIdTag, keyId); 1467bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1477bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1487bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (jsonObject.find(kKeyTag) >= 0) { 1497bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong findValue(kKeyTag, encodedKey); 1507bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1517bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 1527bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 1537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongvoid JsonWebKey::findValue(const String8 &key, String8* value) { 1557bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong value->clear(); 1567bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong const char* valueToken; 1577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong for (Vector<String8>::const_iterator nextToken = mTokens.begin(); 1587bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong nextToken != mTokens.end(); ++nextToken) { 1597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (0 == (*nextToken).compare(key)) { 1607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (nextToken + 1 == mTokens.end()) 1617bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong break; 1627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong valueToken = (*(nextToken + 1)).string(); 1637bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong value->setTo(valueToken); 1647bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong nextToken++; 1657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong break; 1667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 1697bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1707bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::isJsonWebKeySet(const String8& jsonObject) const { 1717bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (jsonObject.find(kKeysTag) == -1) { 1727bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("JSON Web Key does not contain keys."); 1737bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 1747bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1757bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 1767bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 1777bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1787bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/* 1797bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Parses a JSON objects string and initializes a vector of tokens. 1807bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 1817bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * @return Returns false for errors, true for success. 1827bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */ 1837bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::parseJsonObject(const String8& jsonObject, 1847bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong Vector<String8>* tokens) { 1857bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_parser parser; 1867bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1877bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_init(&parser); 1887bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong int numTokens = jsmn_parse(&parser, 1897bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsonObject.string(), jsonObject.size(), NULL, 0); 1907bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (numTokens < 0) { 1917bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Parser returns error code=%d", numTokens); 1927bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 1937bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 1947bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1957bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t); 1967bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong mJsmnTokens.clear(); 1977bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong mJsmnTokens.setCapacity(jsmnTokensSize); 1987bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 1997bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_init(&parser); 2007bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong int status = jsmn_parse(&parser, jsonObject.string(), 2017bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsonObject.size(), mJsmnTokens.editArray(), numTokens); 2027bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (status < 0) { 2037bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Parser returns error code=%d", status); 2047bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 2057bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2067bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2077bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong tokens->clear(); 2087bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8 token; 2097bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong const char *pjs; 2107bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong for (int j = 0; j < numTokens; ++j) { 2117bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong pjs = jsonObject.string() + mJsmnTokens[j].start; 2127bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (mJsmnTokens[j].type == JSMN_STRING || 2137bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong mJsmnTokens[j].type == JSMN_PRIMITIVE) { 2147bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong token.setTo(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start); 2157bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong tokens->add(token); 2167bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 2197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 2207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/* 2227bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Parses JSON Web Key Set string and initializes a vector of JSON objects. 2237bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * 2247bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * @return Returns false for errors, true for success. 2257bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */ 2267bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongbool JsonWebKey::parseJsonWebKeySet(const String8& jsonWebKeySet, 2277bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong Vector<String8>* jsonObjects) { 2287bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (jsonWebKeySet.isEmpty()) { 2297bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Empty JSON Web Key"); 2307bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 2317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2337bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // The jsmn parser only supports unicode encoding. 2347bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_parser parser; 2357bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2367bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // Computes number of tokens. A token marks the type, offset in 2377bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong // the original string. 2387bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_init(&parser); 2397bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong int numTokens = jsmn_parse(&parser, 2407bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsonWebKeySet.string(), jsonWebKeySet.size(), NULL, 0); 2417bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (numTokens < 0) { 2427bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Parser returns error code=%d", numTokens); 2437bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 2447bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2457bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2467bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t); 2477bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong mJsmnTokens.setCapacity(jsmnTokensSize); 2487bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2497bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsmn_init(&parser); 2507bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong int status = jsmn_parse(&parser, jsonWebKeySet.string(), 2517bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsonWebKeySet.size(), mJsmnTokens.editArray(), numTokens); 2527bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (status < 0) { 2537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong ALOGE("Parser returns error code=%d", status); 2547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return false; 2557bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2567bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong String8 token; 2587bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong const char *pjs; 2597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong for (int i = 0; i < numTokens; ++i) { 2607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong pjs = jsonWebKeySet.string() + mJsmnTokens[i].start; 2617bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong if (mJsmnTokens[i].type == JSMN_OBJECT) { 2627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong token.setTo(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start); 2637bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong jsonObjects->add(token); 2647bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong } 2667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong return true; 2677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} 2687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong 2697bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong} // clearkeydrm 270