17bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/*
21917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker * Copyright (C) 2018 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 */
161917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker#define LOG_TAG "hidl_JsonWebKey"
177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include <utils/Log.h>
197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong#include "JsonWebKey.h"
217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
221917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker#include "Base64.h"
231917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker
247bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wongnamespace {
251917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kKeysTag("keys");
261917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kKeyTypeTag("kty");
271917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kSymmetricKeyValue("oct");
281917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kKeyTag("k");
291917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kKeyIdTag("kid");
301917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerconst std::string kBase64Padding("=");
317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
331917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkernamespace android {
341917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkernamespace hardware {
351917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkernamespace drm {
361917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkernamespace V1_1 {
371917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkernamespace clearkey {
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 */
521917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        KeyMap* keys) {
547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
557bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    keys->clear();
561917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker
577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) {
587bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
617bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // mJsonObjects[0] contains the entire JSON Web Key Set, including
627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // all the base64 encoded keys. Each key is also stored separately as
637bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // a JSON object in mJsonObjects[1..n] where n is the total
647bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // number of keys in the set.
657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (!isJsonWebKeySet(mJsonObjects[0])) {
667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
691917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::string encodedKey, encodedKeyId;
701917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::vector<uint8_t> decodedKey, decodedKeyId;
717bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
727bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // mJsonObjects[1] contains the first JSON Web Key in the set
737bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    for (size_t i = 1; i < mJsonObjects.size(); ++i) {
747bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        encodedKeyId.clear();
757bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        encodedKey.clear();
767bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
777bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (!parseJsonObject(mJsonObjects[i], &mTokens))
787bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            return false;
797bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
807bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
811917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            if (encodedKeyId.empty() || encodedKey.empty()) {
827bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                ALOGE("Must have both key id and key in the JsonWebKey set.");
837bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                continue;
847bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            }
857bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
867bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
871917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker                ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
887bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                continue;
897bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            }
907bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
917bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            if (!decodeBase64String(encodedKey, &decodedKey)) {
921917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker                ALOGE("Failed to decode key(%s)", encodedKey.c_str());
937bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                continue;
947bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            }
957bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
961917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            keys->insert(std::pair<std::vector<uint8_t>,
971917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker                    std::vector<uint8_t> >(decodedKeyId, decodedKey));
987bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        }
997bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1007bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
1017bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
1027bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1031917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::decodeBase64String(const std::string& encodedText,
1041917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        std::vector<uint8_t>* decodedText) {
1057bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1067bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    decodedText->clear();
1077bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1087bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // encodedText should not contain padding characters as per EME spec.
1091917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (encodedText.find(kBase64Padding) != std::string::npos) {
1107bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
1117bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1127bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1131917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    // Since decodeBase64() requires padding characters,
1147bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // add them so length of encodedText is exactly a multiple of 4.
1157bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    int remainder = encodedText.length() % 4;
1161917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::string paddedText(encodedText);
1177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (remainder > 0) {
1187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        for (int i = 0; i < 4 - remainder; ++i) {
1197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            paddedText.append(kBase64Padding);
1207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        }
1217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1227bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1231917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    sp<Buffer> buffer = decodeBase64(paddedText);
1241917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (buffer == nullptr) {
1257bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Malformed base64 encoded content found.");
1267bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
1277bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1287bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1291917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    decodedText->insert(decodedText->end(), buffer->base(), buffer->base() + buffer->size());
1307bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
1317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
1327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1331917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::findKey(const std::string& jsonObject, std::string* keyId,
1341917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        std::string* encodedKey) {
1357bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1361917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::string key, value;
1377bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1387bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // Only allow symmetric key, i.e. "kty":"oct" pair.
1391917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (jsonObject.find(kKeyTypeTag) != std::string::npos) {
1407bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        findValue(kKeyTypeTag, &value);
1417bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (0 != value.compare(kSymmetricKeyValue))
1427bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            return false;
1437bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1447bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1451917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (jsonObject.find(kKeyIdTag) != std::string::npos) {
1467bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        findValue(kKeyIdTag, keyId);
1477bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1487bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1491917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (jsonObject.find(kKeyTag) != std::string::npos) {
1507bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        findValue(kKeyTag, encodedKey);
1517bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1527bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
1537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
1547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1551917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkervoid JsonWebKey::findValue(const std::string &key, std::string* value) {
1567bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    value->clear();
1577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    const char* valueToken;
1581917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    for (std::vector<std::string>::const_iterator nextToken = mTokens.begin();
1597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        nextToken != mTokens.end(); ++nextToken) {
1607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (0 == (*nextToken).compare(key)) {
1617bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            if (nextToken + 1 == mTokens.end())
1627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                break;
1631917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            valueToken = (*(nextToken + 1)).c_str();
1641917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            value->assign(valueToken);
1657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            nextToken++;
1667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong            break;
1677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        }
1687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1697bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
1707bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1711917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::isJsonWebKeySet(const std::string& jsonObject) const {
1721917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (jsonObject.find(kKeysTag) == std::string::npos) {
1737bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("JSON Web Key does not contain keys.");
1747bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
1757bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1767bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
1777bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
1787bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1797bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/*
1807bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Parses a JSON objects string and initializes a vector of tokens.
1817bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong *
1827bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * @return Returns false for errors, true for success.
1837bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */
1841917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::parseJsonObject(const std::string& jsonObject,
1851917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        std::vector<std::string>* tokens) {
1867bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_parser parser;
1877bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1887bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_init(&parser);
1897bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    int numTokens = jsmn_parse(&parser,
1901917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        jsonObject.c_str(), jsonObject.size(), nullptr, 0);
1917bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (numTokens < 0) {
1927bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Parser returns error code=%d", numTokens);
1937bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
1947bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
1957bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
1967bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
1977bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    mJsmnTokens.clear();
1981917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    mJsmnTokens.resize(jsmnTokensSize);
1997bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2007bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_init(&parser);
2011917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    int status = jsmn_parse(&parser, jsonObject.c_str(),
2021917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        jsonObject.size(), mJsmnTokens.data(), numTokens);
2037bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (status < 0) {
2047bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Parser returns error code=%d", status);
2057bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
2067bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2077bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2087bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    tokens->clear();
2091917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::string token;
2107bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    const char *pjs;
2117bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    for (int j = 0; j < numTokens; ++j) {
2121917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        pjs = jsonObject.c_str() + mJsmnTokens[j].start;
2137bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (mJsmnTokens[j].type == JSMN_STRING ||
2147bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong                mJsmnTokens[j].type == JSMN_PRIMITIVE) {
2151917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            token.assign(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
2161917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            tokens->push_back(token);
2177bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        }
2187bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2197bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
2207bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
2217bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2227bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong/*
2237bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * Parses JSON Web Key Set string and initializes a vector of JSON objects.
2247bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong *
2257bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong * @return Returns false for errors, true for success.
2267bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong */
2271917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinkerbool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet,
2281917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        std::vector<std::string>* jsonObjects) {
2291917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    if (jsonWebKeySet.empty()) {
2307bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Empty JSON Web Key");
2317bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
2327bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2337bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2347bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // The jsmn parser only supports unicode encoding.
2357bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_parser parser;
2367bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2377bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // Computes number of tokens. A token marks the type, offset in
2387bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    // the original string.
2397bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_init(&parser);
2407bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    int numTokens = jsmn_parse(&parser,
2411917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            jsonWebKeySet.c_str(), jsonWebKeySet.size(), nullptr, 0);
2427bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (numTokens < 0) {
2437bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Parser returns error code=%d", numTokens);
2447bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
2457bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2467bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2477bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
2481917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    mJsmnTokens.resize(jsmnTokensSize);
2497bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2507bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    jsmn_init(&parser);
2511917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
2521917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            jsonWebKeySet.size(), mJsmnTokens.data(), numTokens);
2537bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    if (status < 0) {
2547bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        ALOGE("Parser returns error code=%d", status);
2557bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        return false;
2567bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2577bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2581917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker    std::string token;
2597bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    const char *pjs;
2607bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    for (int i = 0; i < numTokens; ++i) {
2611917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker        pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
2627bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        if (mJsmnTokens[i].type == JSMN_OBJECT) {
2631917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            token.assign(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
2641917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker            jsonObjects->push_back(token);
2657bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong        }
2667bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    }
2677bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong    return true;
2687bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong}
2697bdf28d2b83e527f474e96b0984d6a3f5eb457f7Edwin Wong
2701917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker} // namespace clearkey
2711917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker} // namespace V1_1
2721917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker} // namespace drm
2731917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker} // namespace hardware
2741917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker} // namespace android
2751917fac1e41f57e547df7dcdebf57dd8483e7f61Jeff Tinker
276