diff options
Diffstat (limited to 'KM300/CborConverter.cpp')
-rw-r--r-- | KM300/CborConverter.cpp | 521 |
1 files changed, 0 insertions, 521 deletions
diff --git a/KM300/CborConverter.cpp b/KM300/CborConverter.cpp deleted file mode 100644 index 61bcf8c..0000000 --- a/KM300/CborConverter.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* - ** - ** Copyright 2020, The Android Open Source Project - ** - ** Licensed under the Apache License, Version 2.0 (the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing, software - ** distributed under the License is distributed on an "AS IS" BASIS, - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#include "CborConverter.h" - -#include <map> -#include <string> - -#include <android-base/logging.h> - -#include <KeyMintUtils.h> - -namespace keymint::javacard { -using ::aidl::android::hardware::security::keymint::KeyParameterValue; -using ::aidl::android::hardware::security::keymint::SecurityLevel; -using ::aidl::android::hardware::security::keymint::km_utils::kmParam2Aidl; -using ::aidl::android::hardware::security::keymint::km_utils::legacy_enum_conversion; -using ::aidl::android::hardware::security::keymint::km_utils::typeFromTag; - -constexpr int SB_ENFORCED = 0; -constexpr int TEE_ENFORCED = 1; -constexpr int SW_ENFORCED = 2; - -namespace { - -template <KeyParameterValue::Tag aidl_tag> -std::optional<uint32_t> aidlEnumVal2Uint32(const KeyParameterValue& value) { - return (value.getTag() == aidl_tag) - ? std::optional(static_cast<uint32_t>(value.get<aidl_tag>())) - : std::nullopt; -} - -std::optional<uint32_t> aidlEnumParam2Uint32(const KeyParameter& param) { - auto tag = legacy_enum_conversion(param.tag); - switch (tag) { - case KM_TAG_PURPOSE: - return aidlEnumVal2Uint32<KeyParameterValue::keyPurpose>(param.value); - case KM_TAG_ALGORITHM: - return aidlEnumVal2Uint32<KeyParameterValue::algorithm>(param.value); - case KM_TAG_BLOCK_MODE: - return aidlEnumVal2Uint32<KeyParameterValue::blockMode>(param.value); - case KM_TAG_DIGEST: - case KM_TAG_RSA_OAEP_MGF_DIGEST: - return aidlEnumVal2Uint32<KeyParameterValue::digest>(param.value); - case KM_TAG_PADDING: - return aidlEnumVal2Uint32<KeyParameterValue::paddingMode>(param.value); - case KM_TAG_EC_CURVE: - return aidlEnumVal2Uint32<KeyParameterValue::ecCurve>(param.value); - case KM_TAG_USER_AUTH_TYPE: - return aidlEnumVal2Uint32<KeyParameterValue::hardwareAuthenticatorType>(param.value); - case KM_TAG_ORIGIN: - return aidlEnumVal2Uint32<KeyParameterValue::origin>(param.value); - case KM_TAG_BLOB_USAGE_REQUIREMENTS: - case KM_TAG_KDF: - default: - LOG(FATAL) << "Unknown or unused enum tag: Something is broken"; - return std::nullopt; - } -} - -} // namespace - -bool CborConverter::addAttestationKey(Array& array, - const std::optional<AttestationKey>& attestationKey) { - if (attestationKey.has_value()) { - array.add(Bstr(attestationKey->keyBlob)); - addKeyparameters(array, attestationKey->attestKeyParams); - array.add(Bstr(attestationKey->issuerSubjectName)); - } else { - array.add(std::move(Bstr(vector<uint8_t>(0)))); - array.add(std::move(Map())); - array.add(std::move(Bstr(vector<uint8_t>(0)))); - } - return true; -} - -bool CborConverter::addKeyparameters(Array& array, const vector<KeyParameter>& keyParams) { - Map map; - std::map<uint32_t, vector<uint8_t>> enum_repetition; - std::map<uint32_t, Array> uint_repetition; - for (auto& param : keyParams) { - auto tag = legacy_enum_conversion(param.tag); - switch (typeFromTag(tag)) { - case KM_ENUM: { - auto paramEnum = aidlEnumParam2Uint32(param); - if (paramEnum.has_value()) { - map.add(static_cast<uint32_t>(tag), *paramEnum); - } - break; - } - case KM_UINT: - if (param.value.getTag() == KeyParameterValue::integer) { - uint32_t intVal = param.value.get<KeyParameterValue::integer>(); - map.add(static_cast<uint32_t>(tag), intVal); - } - break; - case KM_UINT_REP: - if (param.value.getTag() == KeyParameterValue::integer) { - uint32_t intVal = param.value.get<KeyParameterValue::integer>(); - uint_repetition[static_cast<uint32_t>(tag)].add(intVal); - } - break; - case KM_ENUM_REP: { - auto paramEnumRep = aidlEnumParam2Uint32(param); - if (paramEnumRep.has_value()) { - enum_repetition[static_cast<uint32_t>(tag)].push_back(*paramEnumRep); - } - break; - } - case KM_ULONG: - if (param.value.getTag() == KeyParameterValue::longInteger) { - uint64_t longVal = param.value.get<KeyParameterValue::longInteger>(); - map.add(static_cast<uint32_t>(tag), longVal); - } - break; - case KM_ULONG_REP: - if (param.value.getTag() == KeyParameterValue::longInteger) { - uint64_t longVal = param.value.get<KeyParameterValue::longInteger>(); - uint_repetition[static_cast<uint32_t>(tag)].add(longVal); - } - break; - case KM_DATE: - if (param.value.getTag() == KeyParameterValue::dateTime) { - uint64_t dateVal = param.value.get<KeyParameterValue::dateTime>(); - map.add(static_cast<uint32_t>(tag), dateVal); - } - break; - case KM_BOOL: - map.add(static_cast<uint32_t>(tag), 1 /* true */); - break; - case KM_BIGNUM: - case KM_BYTES: - if (param.value.getTag() == KeyParameterValue::blob) { - const auto& value = param.value.get<KeyParameterValue::blob>(); - map.add(static_cast<uint32_t>(tag), value); - } - break; - case KM_INVALID: - break; - } - } - - for (auto const& [key, val] : enum_repetition) { - Bstr bstr(val); - map.add(key, std::move(bstr)); - } - - for (auto& [key, val] : uint_repetition) { - map.add(key, std::move(val)); - } - array.add(std::move(map)); - return true; -} - -// Array of three maps -std::optional<vector<KeyCharacteristics>> -CborConverter::getKeyCharacteristics(const unique_ptr<Item>& item, const uint32_t pos) { - vector<KeyCharacteristics> keyCharacteristics; - auto arrayItem = getItemAtPos(item, pos); - if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) { - return std::nullopt; - } - KeyCharacteristics swEnf{SecurityLevel::KEYSTORE, {}}; - KeyCharacteristics teeEnf{SecurityLevel::TRUSTED_ENVIRONMENT, {}}; - KeyCharacteristics sbEnf{SecurityLevel::STRONGBOX, {}}; - - auto optSbEnf = getKeyParameters(arrayItem.value(), SB_ENFORCED); - if (!optSbEnf) { - return std::nullopt; - } - sbEnf.authorizations = std::move(optSbEnf.value()); - auto optTeeEnf = getKeyParameters(arrayItem.value(), TEE_ENFORCED); - if (!optTeeEnf) { - return std::nullopt; - } - teeEnf.authorizations = std::move(optTeeEnf.value()); - auto optSwEnf = getKeyParameters(arrayItem.value(), SW_ENFORCED); - if (!optSwEnf) { - return std::nullopt; - } - swEnf.authorizations = std::move(optSwEnf.value()); - // VTS will fail if the authorizations list is empty. - if (!sbEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(sbEnf)); - if (!teeEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(teeEnf)); - if (!swEnf.authorizations.empty()) keyCharacteristics.push_back(std::move(swEnf)); - return keyCharacteristics; -} - -std::optional<std::vector<KeyParameter>> CborConverter::getKeyParameter( - const std::pair<const std::unique_ptr<Item>&, const std::unique_ptr<Item>&> pair) { - std::vector<KeyParameter> keyParams; - keymaster_tag_t key; - auto optValue = getUint64(pair.first); - if (!optValue) { - return std::nullopt; - } - key = static_cast<keymaster_tag_t>(optValue.value()); - switch (keymaster_tag_get_type(key)) { - case KM_ENUM_REP: { - /* ENUM_REP contains values encoded in a Byte string */ - const Bstr* bstr = pair.second.get()->asBstr(); - if (bstr == nullptr) { - return std::nullopt; - } - for (auto bchar : bstr->value()) { - keymaster_key_param_t keyParam; - keyParam.tag = key; - keyParam.enumerated = bchar; - keyParams.push_back(kmParam2Aidl(keyParam)); - } - return keyParams; - } - case KM_ENUM: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - if (!(optValue = getUint64(pair.second))) { - return std::nullopt; - } - keyParam.enumerated = static_cast<uint32_t>(optValue.value()); - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_UINT: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - if (!(optValue = getUint64(pair.second))) { - return std::nullopt; - } - keyParam.integer = static_cast<uint32_t>(optValue.value()); - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_ULONG: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - if (!(optValue = getUint64(pair.second))) { - return std::nullopt; - } - keyParam.long_integer = optValue.value(); - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_UINT_REP: { - /* UINT_REP contains values encoded in a Array */ - Array* array = const_cast<Array*>(pair.second.get()->asArray()); - if (array == nullptr) return std::nullopt; - for (int i = 0; i < array->size(); i++) { - keymaster_key_param_t keyParam; - keyParam.tag = key; - const std::unique_ptr<Item>& item = array->get(i); - if (!(optValue = getUint64(item))) { - return std::nullopt; - } - keyParam.integer = static_cast<uint32_t>(optValue.value()); - keyParams.push_back(kmParam2Aidl(keyParam)); - } - return keyParams; - } - case KM_ULONG_REP: { - /* ULONG_REP contains values encoded in a Array */ - Array* array = const_cast<Array*>(pair.second.get()->asArray()); - if (array == nullptr) return std::nullopt; - for (int i = 0; i < array->size(); i++) { - keymaster_key_param_t keyParam; - keyParam.tag = key; - const std::unique_ptr<Item>& item = array->get(i); - if (!(optValue = getUint64(item))) { - return std::nullopt; - } - keyParam.long_integer = optValue.value(); - keyParams.push_back(kmParam2Aidl(keyParam)); - } - return keyParams; - } - case KM_DATE: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - if (!(optValue = getUint64(pair.second))) { - return std::nullopt; - } - keyParam.date_time = optValue.value(); - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_BOOL: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - if (!(optValue = getUint64(pair.second))) { - return std::nullopt; - } - // If a tag with this type is present, the value is true. If absent, - // false. - keyParam.boolean = true; - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_BIGNUM: - case KM_BYTES: { - keymaster_key_param_t keyParam; - keyParam.tag = key; - const Bstr* bstr = pair.second.get()->asBstr(); - if (bstr == nullptr) return std::nullopt; - keyParam.blob.data = bstr->value().data(); - keyParam.blob.data_length = bstr->value().size(); - keyParams.push_back(kmParam2Aidl(keyParam)); - return keyParams; - } - case KM_INVALID: - break; - } - return std::nullopt; -} - -// array of a blobs -std::optional<vector<Certificate>> -CborConverter::getCertificateChain(const std::unique_ptr<Item>& item, const uint32_t pos) { - vector<Certificate> certChain; - auto arrayItem = getItemAtPos(item, pos); - if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) return std::nullopt; - - const Array* arr = arrayItem.value().get()->asArray(); - for (int i = 0; i < arr->size(); i++) { - Certificate cert; - auto optTemp = getByteArrayVec(arrayItem.value(), i); - if (!optTemp) return std::nullopt; - cert.encodedCertificate = std::move(optTemp.value()); - certChain.push_back(std::move(cert)); - } - return certChain; -} - -std::optional<string> CborConverter::getTextStr(const unique_ptr<Item>& item, const uint32_t pos) { - auto textStrItem = getItemAtPos(item, pos); - if (!textStrItem || (MajorType::TSTR != getType(textStrItem.value()))) { - return std::nullopt; - } - const Tstr* tstr = textStrItem.value().get()->asTstr(); - return tstr->value(); -} - -std::optional<string> CborConverter::getByteArrayStr(const unique_ptr<Item>& item, - const uint32_t pos) { - auto optTemp = getByteArrayVec(item, pos); - if (!optTemp) { - return std::nullopt; - } - std::string str(optTemp->begin(), optTemp->end()); - return str; -} - -std::optional<std::vector<uint8_t>> CborConverter::getByteArrayVec(const unique_ptr<Item>& item, - const uint32_t pos) { - auto strItem = getItemAtPos(item, pos); - if (!strItem || (MajorType::BSTR != getType(strItem.value()))) { - return std::nullopt; - } - const Bstr* bstr = strItem.value().get()->asBstr(); - return bstr->value(); -} - -std::optional<SharedSecretParameters> -CborConverter::getSharedSecretParameters(const unique_ptr<Item>& item, const uint32_t pos) { - SharedSecretParameters params; - // Array [seed, nonce] - auto arrayItem = getItemAtPos(item, pos); - if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) { - return std::nullopt; - } - auto optSeed = getByteArrayVec(arrayItem.value(), 0); - auto optNonce = getByteArrayVec(arrayItem.value(), 1); - if (!optSeed || !optNonce) { - return std::nullopt; - } - params.seed = std::move(optSeed.value()); - params.nonce = std::move(optNonce.value()); - return params; -} - -bool CborConverter::addSharedSecretParameters(Array& array, - const vector<SharedSecretParameters>& params) { - Array cborParamsVec; - for (auto param : params) { - Array cborParam; - cborParam.add(Bstr(param.seed)); - cborParam.add(Bstr(param.nonce)); - cborParamsVec.add(std::move(cborParam)); - } - array.add(std::move(cborParamsVec)); - return true; -} - -bool CborConverter::addTimeStampToken(Array& array, const TimeStampToken& token) { - Array vToken; - vToken.add(static_cast<uint64_t>(token.challenge)); - vToken.add(static_cast<uint64_t>(token.timestamp.milliSeconds)); - vToken.add((std::vector<uint8_t>(token.mac))); - array.add(std::move(vToken)); - return true; -} - -bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& authToken) { - Array hwAuthToken; - hwAuthToken.add(static_cast<uint64_t>(authToken.challenge)); - hwAuthToken.add(static_cast<uint64_t>(authToken.userId)); - hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorId)); - hwAuthToken.add(static_cast<uint64_t>(authToken.authenticatorType)); - hwAuthToken.add(static_cast<uint64_t>(authToken.timestamp.milliSeconds)); - hwAuthToken.add((std::vector<uint8_t>(authToken.mac))); - array.add(std::move(hwAuthToken)); - return true; -} - -std::optional<TimeStampToken> CborConverter::getTimeStampToken(const unique_ptr<Item>& item, - const uint32_t pos) { - TimeStampToken token; - // {challenge, timestamp, Mac} - auto optChallenge = getUint64(item, pos); - auto optTimestampMillis = getUint64(item, pos + 1); - auto optTemp = getByteArrayVec(item, pos + 2); - if (!optChallenge || !optTimestampMillis || !optTemp) { - return std::nullopt; - } - token.mac = std::move(optTemp.value()); - token.challenge = static_cast<long>(std::move(optChallenge.value())); - token.timestamp.milliSeconds = static_cast<long>(std::move(optTimestampMillis.value())); - return token; -} - -std::optional<Array> CborConverter::getArrayItem(const std::unique_ptr<Item>& item, - const uint32_t pos) { - Array array; - auto arrayItem = getItemAtPos(item, pos); - if (!arrayItem || (MajorType::ARRAY != getType(arrayItem.value()))) { - return std::nullopt; - } - array = std::move(*(arrayItem.value().get()->asArray())); - return array; -} - -std::optional<Map> CborConverter::getMapItem(const std::unique_ptr<Item>& item, - const uint32_t pos) { - Map map; - auto mapItem = getItemAtPos(item, pos); - if (!mapItem || (MajorType::MAP != getType(mapItem.value()))) { - return std::nullopt; - } - map = std::move(*(mapItem.value().get()->asMap())); - return map; -} - -std::optional<vector<KeyParameter>> CborConverter::getKeyParameters(const unique_ptr<Item>& item, - const uint32_t pos) { - vector<KeyParameter> params; - auto mapItem = getItemAtPos(item, pos); - if (!mapItem || (MajorType::MAP != getType(mapItem.value()))) return std::nullopt; - const Map* map = mapItem.value().get()->asMap(); - size_t mapSize = map->size(); - for (int i = 0; i < mapSize; i++) { - auto optKeyParams = getKeyParameter((*map)[i]); - if (optKeyParams) { - params.insert(params.end(), optKeyParams->begin(), optKeyParams->end()); - } else { - return std::nullopt; - } - } - return params; -} - -std::tuple<std::unique_ptr<Item>, keymaster_error_t> -CborConverter::decodeData(const std::vector<uint8_t>& response) { - auto [item, pos, message] = cppbor::parse(response); - if (!item || MajorType::ARRAY != getType(item)) { - return {nullptr, KM_ERROR_UNKNOWN_ERROR}; - } - auto optErrorCode = getErrorCode(item, 0); - if (!optErrorCode) { - return {nullptr, KM_ERROR_UNKNOWN_ERROR}; - } - return {std::move(item), optErrorCode.value()}; -} - -std::optional<keymaster_error_t> -CborConverter::getErrorCode(const std::unique_ptr<cppbor::Item>& item, const uint32_t pos) { - auto optErrorVal = getUint64(item, pos); - if (!optErrorVal) { - return std::nullopt; - } - return static_cast<keymaster_error_t>(0 - optErrorVal.value()); -} - -std::optional<uint64_t> CborConverter::getUint64(const unique_ptr<Item>& item) { - if ((item == nullptr) || (MajorType::UINT != getType(item))) { - return std::nullopt; - } - const Uint* uintVal = item.get()->asUint(); - return uintVal->unsignedValue(); -} - -std::optional<uint64_t> CborConverter::getUint64(const unique_ptr<Item>& item, const uint32_t pos) { - auto intItem = getItemAtPos(item, pos); - if (!intItem) { - return std::nullopt; - } - return getUint64(intItem.value()); -} - -} // namespace keymint::javacard |