diff --git a/HAL/keymaster/4.1/CborConverter.cpp b/HAL/keymaster/4.1/CborConverter.cpp index 4d7041fd..96bf78c5 100644 --- a/HAL/keymaster/4.1/CborConverter.cpp +++ b/HAL/keymaster/4.1/CborConverter.cpp @@ -15,300 +15,314 @@ ** limitations under the License. */ -#include +#include "CborConverter.h" + #include +#include "CommonUtils.h" + +using namespace ::keymaster::V4_1::javacard; +using namespace cppbor; + +constexpr int SW_ENFORCED = 0; +constexpr int HW_ENFORCED = 1; + + +std::optional CborConverter::getUint64(const std::unique_ptr& item) { + if ((item == nullptr) || (MajorType::UINT != getType(item))) { + return std::nullopt; + } + const Uint *uintVal = item.get()->asUint(); + return uintVal->value(); +} + +std::optional CborConverter::getUint64(const std::unique_ptr& item, const uint32_t pos) { + auto uintItem = getItemAtPos(item, pos); + if (!uintItem) { + return std::nullopt; + } + return getUint64(*uintItem); +} + bool CborConverter::addKeyparameters(Array& array, const android::hardware::hidl_vec& keyParams) { Map map; std::map> enum_repetition; std::map uint_repetition; - for(size_t i = 0; i < keyParams.size(); i++) { - KeyParameter param = keyParams[i]; - TagType tagType = static_cast(param.tag & (0xF << 28)); + for (size_t i = 0; i < keyParams.size(); i++) { + keymaster_tag_type_t tagType = typeFromTag(legacy_enum_conversion(keyParams[i].tag)); switch(tagType) { - case TagType::ENUM: - case TagType::UINT: - map.add(static_cast(param.tag), param.f.integer); + case KM_ENUM: + case KM_UINT: + map.add(static_cast(keyParams[i].tag), keyParams[i].f.integer); break; - case TagType::UINT_REP: - uint_repetition[static_cast(param.tag)].add(param.f.integer); + case KM_UINT_REP: + uint_repetition[static_cast(keyParams[i].tag)] + .add(keyParams[i].f.integer); break; - case TagType::ENUM_REP: - enum_repetition[static_cast(param.tag)].push_back(static_cast(param.f.integer)); + case KM_ENUM_REP: + enum_repetition[static_cast(keyParams[i].tag)] + .push_back(static_cast(keyParams[i].f.integer)); break; - case TagType::ULONG: - map.add(static_cast(param.tag), param.f.longInteger); + case KM_ULONG: + map.add(static_cast(keyParams[i].tag), keyParams[i].f.longInteger); break; - case TagType::ULONG_REP: - uint_repetition[static_cast(param.tag)].add(param.f.longInteger); + case KM_ULONG_REP: + uint_repetition[static_cast(keyParams[i].tag)] + .add(keyParams[i].f.longInteger); break; - case TagType::DATE: - map.add(static_cast(param.tag), param.f.dateTime); + case KM_DATE: + map.add(static_cast(keyParams[i].tag), keyParams[i].f.dateTime); break; - case TagType::BOOL: - map.add(static_cast(param.tag), static_cast(param.f.boolValue)); + case KM_BOOL: + map.add(static_cast(keyParams[i].tag), + static_cast(keyParams[i].f.boolValue)); break; - case TagType::BIGNUM: - case TagType::BYTES: - map.add(static_cast(param.tag), (std::vector(param.blob))); + case KM_BIGNUM: + case KM_BYTES: + map.add(static_cast(keyParams[i].tag), + (std::vector(keyParams[i].blob))); break; - default: - /* Invalid skip */ + case KM_INVALID: break; } } - if(0 < enum_repetition.size()) { - for( auto const& [key, val] : enum_repetition ) { - Bstr bstr(val); - map.add(key, std::move(bstr)); - } + for (auto const& [key, val] : enum_repetition ) { + Bstr bstr(val); + map.add(key, std::move(bstr)); } - if(0 < uint_repetition.size()) { - for( auto & [key, val] : uint_repetition ) { - map.add(key, std::move(val)); - } + for (auto & [key, val] : uint_repetition ) { + map.add(key, std::move(val)); } array.add(std::move(map)); return true; } -bool CborConverter::getKeyCharacteristics(const std::unique_ptr &item, const uint32_t pos, - KeyCharacteristics& keyCharacteristics) { - bool ret = false; - std::unique_ptr arrayItem(nullptr); - getItemAtPos(item, pos, arrayItem); - if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) - return ret; +std::optional +CborConverter::getKeyCharacteristics(const std::unique_ptr &item, const uint32_t pos) { + KeyCharacteristics keyCharacteristics; + auto arrayItem = getItemAtPos(item, pos); + if (!arrayItem || (MajorType::ARRAY != getType(*arrayItem))) + return std::nullopt; - if (!getKeyParameters(arrayItem, 0, keyCharacteristics.softwareEnforced)) { - return ret; + auto optSwEnf = getKeyParameters(*arrayItem, SW_ENFORCED); + if (!optSwEnf) { + return std::nullopt; } + keyCharacteristics.softwareEnforced = std::move(*optSwEnf); - if (!getKeyParameters(arrayItem, 1, keyCharacteristics.hardwareEnforced)) { - return ret; + auto optHwEnf = getKeyParameters(*arrayItem, HW_ENFORCED); + if (!optHwEnf) { + return std::nullopt; } - //success - ret = true; - return ret; + keyCharacteristics.hardwareEnforced = std::move(*optHwEnf); + return keyCharacteristics; + } -bool CborConverter::getKeyParameter(const std::pair&, - const std::unique_ptr&> pair, std::vector& keyParams) { - bool ret = false; - uint64_t key; - uint64_t value; +std::optional> +CborConverter::getKeyParameter(const std::pair&, + const std::unique_ptr&> pair) { + std::vector keyParams; + Tag key; - if(!getUint64(pair.first, key)) { - return ret; + auto optKey = getUint64(pair.first); + if (!optKey) { + return std::nullopt; } + key = static_cast(optKey.value()); /* Get the TagType from the Tag */ - TagType tagType = static_cast(key & (0xF << 28)); + keymaster_tag_type_t tagType = typeFromTag(legacy_enum_conversion(key)); switch(tagType) { - case TagType::ENUM_REP: + case KM_ENUM_REP: { - /* ENUM_REP contains values encoded in a Binary string */ + /* ENUM_REP contains values encoded in a Byte string */ const Bstr* bstr = pair.second.get()->asBstr(); - if(bstr == nullptr) return ret; + if(bstr == nullptr) return std::nullopt; for (auto bchar : bstr->value()) { KeyParameter keyParam; - keyParam.tag = static_cast(key); + keyParam.tag = key; keyParam.f.integer = bchar; keyParams.push_back(std::move(keyParam)); } - return true; + return keyParams; } break; - case TagType::ENUM: - case TagType::UINT: + case KM_ENUM: + case KM_UINT: { KeyParameter keyParam; - keyParam.tag = static_cast(key); - if(!getUint64(pair.second, value)) { - return ret; + keyParam.tag = key; + auto optVal = getUint64(pair.second); + if(!optVal) { + return std::nullopt; } - keyParam.f.integer = static_cast(value); + keyParam.f.integer = static_cast(optVal.value()); keyParams.push_back(std::move(keyParam)); - return true; + return keyParams; } break; - case TagType::ULONG: + case KM_ULONG: { KeyParameter keyParam; - keyParam.tag = static_cast(key); - if(!getUint64(pair.second, value)) { - return ret; + keyParam.tag = key; + auto optVal = getUint64(pair.second); + if(!optVal) { + return std::nullopt; } - keyParam.f.longInteger = value; + keyParam.f.longInteger = optVal.value(); keyParams.push_back(std::move(keyParam)); - return true; + return keyParams; } break; - case TagType::UINT_REP: + case KM_UINT_REP: { /* UINT_REP contains values encoded in a Array */ Array* array = const_cast(pair.second.get()->asArray()); - if(array == nullptr) return ret; + if(array == nullptr) return std::nullopt; for(int i = 0; i < array->size(); i++) { KeyParameter keyParam; - keyParam.tag = static_cast(key); - std::unique_ptr item = std::move((*array)[i]); - if(!getUint64(item, value)) { - return ret; + keyParam.tag = key; + const std::unique_ptr& item = array->get(i); + auto optVal = getUint64(item); + if(!optVal) { + return std::nullopt; } - keyParam.f.integer = static_cast(value); + keyParam.f.integer = static_cast(optVal.value()); keyParams.push_back(std::move(keyParam)); } - return true; + return keyParams; } break; - case TagType::ULONG_REP: + case KM_ULONG_REP: { /* ULONG_REP contains values encoded in a Array */ Array* array = const_cast(pair.second.get()->asArray()); - if(array == nullptr) return ret; + if(array == nullptr) return std::nullopt; for(int i = 0; i < array->size(); i++) { KeyParameter keyParam; - keyParam.tag = static_cast(key); - std::unique_ptr item = std::move((*array)[i]); - if(!getUint64(item, keyParam.f.longInteger)) { - return ret; + keyParam.tag = key; + const std::unique_ptr& item = array->get(i); + auto optVal = getUint64(item); + if(!optVal) { + return std::nullopt; } + keyParam.f.longInteger = optVal.value(); keyParams.push_back(std::move(keyParam)); } - return true; + return keyParams; } break; - case TagType::DATE: + case KM_DATE: { KeyParameter keyParam; - keyParam.tag = static_cast(key); - if(!getUint64(pair.second, value)) { - return ret; + keyParam.tag = key; + auto optVal = getUint64(pair.second); + if(!optVal) { + return std::nullopt; } - keyParam.f.dateTime = value; + keyParam.f.dateTime = optVal.value(); keyParams.push_back(std::move(keyParam)); - return true; + return keyParams; } break; - case TagType::BOOL: + case KM_BOOL: { KeyParameter keyParam; - keyParam.tag = static_cast(key); - if(!getUint64(pair.second, value)) { - return ret; + keyParam.tag = key; + auto optVal = getUint64(pair.second); + if(!optVal) { + return std::nullopt; } - keyParam.f.boolValue = static_cast(value); + keyParam.f.boolValue = static_cast(optVal.value()); keyParams.push_back(std::move(keyParam)); - return true; + return keyParams; } break; - case TagType::BYTES: + case KM_BYTES: { KeyParameter keyParam; - keyParam.tag = static_cast(key); + keyParam.tag = key; const Bstr* bstr = pair.second.get()->asBstr(); - if(bstr == nullptr) return ret; + if(bstr == nullptr) return std::nullopt; keyParam.blob = bstr->value(); keyParams.push_back(std::move(keyParam)); - return true; + return keyParams; } break; - default: - /* Invalid skip */ + case KM_INVALID: + case KM_BIGNUM: break; } - return ret; + return std::nullopt; } - -bool CborConverter::getMultiBinaryArray(const std::unique_ptr& item, const uint32_t pos, - std::vector>& data) { - bool ret = false; - std::unique_ptr arrayItem(nullptr); - - getItemAtPos(item, pos, arrayItem); - if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) - return ret; - const Array* arr = arrayItem.get()->asArray(); - size_t arrSize = arr->size(); +std::optional>> +CborConverter::getCertChain(const std::unique_ptr& item, const uint32_t pos) { + std::vector> data; + auto arrayItem = getItemAtPos(item, pos); + if (!arrayItem || (MajorType::ARRAY != getType(*arrayItem))) { + return std::nullopt; + } + size_t arrSize = arrayItem->get()->asArray()->size(); for (int i = 0; i < arrSize; i++) { - std::vector temp; - if (!getBinaryArray(arrayItem, i, temp)) - return ret; - data.push_back(std::move(temp)); + auto optTemp = getByteArrayVec(*arrayItem, i); + if (!optTemp) { + return std::nullopt; + } + data.push_back(std::move(*optTemp)); } - ret = true; // success - return ret; + return data; } -bool CborConverter::getBinaryArray(const std::unique_ptr& item, const uint32_t pos, - ::android::hardware::hidl_vec& value) { - bool ret = false; - std::unique_ptr strItem(nullptr); - getItemAtPos(item, pos, strItem); - if ((strItem == nullptr) || (MajorType::BSTR != getType(strItem))) - return ret; - - const Bstr* bstr = strItem.get()->asBstr(); - value = bstr->value(); - ret = true; - return ret; +std::optional<::android::hardware::hidl_vec> +CborConverter::getByteArrayHidlVec(const std::unique_ptr& item, const uint32_t pos) { + auto strItem = getItemAtPos(item, pos); + if (!strItem || (MajorType::BSTR != getType(*strItem))) + return std::nullopt; + + return strItem->get()->asBstr()->value(); } -bool CborConverter::getBinaryArray(const std::unique_ptr& item, const uint32_t pos, - ::android::hardware::hidl_string& value) { - std::vector vec; - std::string str; - if(!getBinaryArray(item, pos, vec)) { - return false; - } - for(auto ch : vec) { - str += ch; +std::optional<::android::hardware::hidl_string> +CborConverter::getByteArrayHidlStr(const std::unique_ptr& item, const uint32_t pos) { + auto vec = getByteArrayVec(item, pos); + if(!vec) { + return std::nullopt; } - value = str; - return true; + std::string str(vec->begin(), vec->end()); + return str; } -bool CborConverter::getBinaryArray(const std::unique_ptr& item, const uint32_t pos, std::vector& value) { - bool ret = false; - std::unique_ptr strItem(nullptr); - getItemAtPos(item, pos, strItem); - if ((strItem == nullptr) || (MajorType::BSTR != getType(strItem))) - return ret; +std::optional> +CborConverter::getByteArrayVec(const std::unique_ptr& item, const uint32_t pos) { + auto strItem = getItemAtPos(item, pos); + if (!strItem || (MajorType::BSTR != getType(*strItem))) + return std::nullopt; - const Bstr* bstr = strItem.get()->asBstr(); - for (auto bchar : bstr->value()) { - value.push_back(bchar); - } - ret = true; - return ret; + return strItem->get()->asBstr()->value(); } -bool CborConverter::getHmacSharingParameters(const std::unique_ptr& item, const uint32_t pos, HmacSharingParameters& params) { +std::optional +CborConverter::getHmacSharingParameters(const std::unique_ptr& item, const uint32_t pos) { std::vector paramValue; - bool ret = false; - std::unique_ptr arrayItem(nullptr); - + HmacSharingParameters params; //1. Get ArrayItem + auto arrayItem = getItemAtPos(item, pos); //2. First item in the array seed; second item in the array is nonce. + if (!arrayItem || (MajorType::ARRAY != getType(*arrayItem))) + return std::nullopt; - getItemAtPos(item, pos, arrayItem); - if ((arrayItem == nullptr) || (MajorType::ARRAY != getType(arrayItem))) - return ret; - - //Seed - if (!getBinaryArray(arrayItem, 0, params.seed)) - return ret; - - //nonce - if (!getBinaryArray(arrayItem, 1, paramValue)) - return ret; - memcpy(params.nonce.data(), paramValue.data(), paramValue.size()); - ret = true; - return ret; + auto optSeed = getByteArrayHidlVec(*arrayItem, 0); + auto optNonce = getByteArrayVec(*arrayItem, 1); + if (!optSeed || !optNonce) { + return std::nullopt; + } + params.seed = std::move(*optSeed); + memcpy(params.nonce.data(), optNonce->data(), optNonce->size()); + return params; } bool CborConverter::addVerificationToken(Array& array, const VerificationToken& @@ -336,77 +350,75 @@ bool CborConverter::addHardwareAuthToken(Array& array, const HardwareAuthToken& return true; } -bool CborConverter::getHardwareAuthToken(const std::unique_ptr& item, const uint32_t pos, HardwareAuthToken& token) { - bool ret = false; - //challenge - if (!getUint64(item, pos, token.challenge)) - return ret; - //userId - if (!getUint64(item, pos+1, token.userId)) - return ret; - //AuthenticatorId - if (!getUint64(item, pos+2, token.authenticatorId)) - return ret; - //AuthType - uint64_t authType; - if (!getUint64(item, pos+3, authType)) - return ret; - token.authenticatorType = static_cast(authType); - //Timestamp - if (!getUint64(item, pos+4, token.timestamp)) - return ret; - //MAC - if (!getBinaryArray(item, pos+5, token.mac)) - return ret; - ret = true; - return ret; +std::optional> +CborConverter::getKeyParameters(const std::unique_ptr& item, const uint32_t pos) { + android::hardware::hidl_vec hidlVecParams; + std::vector params; + auto mapItem = getItemAtPos(item, pos); + if (!mapItem || (MajorType::MAP != getType(*mapItem))) + return std::nullopt; + + const Map* map = mapItem->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; + } + } + hidlVecParams.resize(params.size()); + hidlVecParams = params; + return hidlVecParams; } -bool CborConverter::getVerificationToken(const std::unique_ptr& item, const uint32_t pos, VerificationToken& - token) { - bool ret = false; - //challenge - if (!getUint64(item, pos, token.challenge)) - return ret; - - //timestamp - if (!getUint64(item, pos+1, token.timestamp)) - return ret; - - //List of KeyParameters - if (!getKeyParameters(item, pos+2, token.parametersVerified)) - return ret; - - //AuthenticatorId - uint64_t val; - if (!getUint64(item, pos+3, val)) - return ret; - token.securityLevel = static_cast(val); - - //MAC - if (!getBinaryArray(item, pos+4, token.mac)) - return ret; - ret = true; - return ret; +std::tuple, ErrorCode> +CborConverter::decodeData(const std::vector &response, bool hasErrorCode) { + const uint8_t *pos; + std::unique_ptr item(nullptr); + std::string message; + ErrorCode errorCode = ErrorCode::OK; + + std::tie(item, pos, message) = cppbor::parse(response); + + if (item != nullptr && hasErrorCode) { + if (cppbor::MajorType::ARRAY == getType(item)) { + auto optErr = getErrorCode(item, 0); + if (!optErr) { + item = nullptr; + } else { + errorCode = optErr.value(); + } + + } else if (cppbor::MajorType::UINT == getType(item)) { + auto optErr = getUint64(item); + if (optErr) { + errorCode = static_cast(optErr.value()); + } + item = nullptr; /*Already read the errorCode. So no need of sending item to client */ + } + } + return {std::move(item), errorCode}; +} +std::optional> +CborConverter::getItemAtPos(const std::unique_ptr &item, const uint32_t pos) { + if (cppbor::MajorType::ARRAY != getType(item)) { + return std::nullopt; + } + Array *arr = item.get()->asArray(); + if (arr->size() < (pos + 1)) { + return std::nullopt; + } + return std::move(arr->get(pos)); } -bool CborConverter::getKeyParameters(const std::unique_ptr& item, const uint32_t pos, android::hardware::hidl_vec& keyParams) { - bool ret = false; - std::unique_ptr mapItem(nullptr); - std::vector params; - getItemAtPos(item, pos, mapItem); - if ((mapItem == nullptr) || (MajorType::MAP != getType(mapItem))) - return ret; - const Map* map = mapItem.get()->asMap(); - size_t mapSize = map->size(); - for (int i = 0; i < mapSize; i++) { - if (!getKeyParameter((*map)[i], params)) { - return ret; - } +std::optional +CborConverter::getErrorCode(const std::unique_ptr &item, const uint32_t pos) { + auto optErrorVal = getUint64(item, pos); + if (!optErrorVal) { + return std::nullopt; } - keyParams.resize(params.size()); - keyParams = params; - ret = true; - return ret; + return static_cast(*optErrorVal); } diff --git a/HAL/keymaster/4.1/CommonUtils.cpp b/HAL/keymaster/4.1/CommonUtils.cpp index 476fe68e..28bd5ae7 100644 --- a/HAL/keymaster/4.1/CommonUtils.cpp +++ b/HAL/keymaster/4.1/CommonUtils.cpp @@ -15,21 +15,23 @@ ** limitations under the License. */ -#include -#include +#include "CommonUtils.h" + #include + +#include #include -#include -#include -#include + #include +#include +#include #include -#include +#include + +#include #include #include #include -#include -#include #define TAG_SEQUENCE 0x30 #define LENGTH_MASK 0x80 @@ -160,21 +162,22 @@ ErrorCode getEcCurve(const EC_GROUP *group, EcCurve& ecCurve) { ErrorCode ecRawKeyFromPKCS8(const std::vector& pkcs8Blob, std::vector& secret, std::vector& publicKey, EcCurve& ecCurve) { ErrorCode errorCode = ErrorCode::INVALID_KEY_BLOB; - EVP_PKEY *pkey = nullptr; const uint8_t *data = pkcs8Blob.data(); - d2i_PrivateKey(EVP_PKEY_EC, &pkey, &data, pkcs8Blob.size()); - if(!pkey) { + EVP_PKEY* evpKey = d2i_PrivateKey(EVP_PKEY_EC, nullptr /* pkey */, &data, + pkcs8Blob.size()); + if (!evpKey) { return legacy_enum_conversion(TranslateLastOpenSslError()); } + UniquePtr pkey(evpKey); - UniquePtr ec_key(EVP_PKEY_get1_EC_KEY(pkey)); + UniquePtr ec_key(EVP_PKEY_get1_EC_KEY(pkey.get())); if(!ec_key.get()) return legacy_enum_conversion(TranslateLastOpenSslError()); //Get EC Group const EC_GROUP *group = EC_KEY_get0_group(ec_key.get()); - if(group == NULL) + if(group == nullptr) return errorCode; if(ErrorCode::OK != (errorCode = getEcCurve(group, ecCurve))) { @@ -183,57 +186,83 @@ publicKey, EcCurve& ecCurve) { //Extract private key. const BIGNUM *privBn = EC_KEY_get0_private_key(ec_key.get()); - int privKeyLen = BN_num_bytes(privBn); - std::unique_ptr privKey(new uint8_t[privKeyLen]); - BN_bn2bin(privBn, privKey.get()); - secret.insert(secret.begin(), privKey.get(), privKey.get()+privKeyLen); + if (privBn == nullptr) { + return errorCode; + } + // Note that this may return fewer than 32 bytes so pad with zeroes since we + // want to always return 32 bytes. + size_t numBytes = BN_num_bytes(privBn); + if (numBytes > 32) { + LOG(ERROR) << "Size is " << numBytes << ", expected this to be 32 or less"; + return errorCode; + } + secret.resize(32); + for (size_t n = 0; n < 32 - numBytes; n++) { + secret[n] = 0x00; + } + BN_bn2bin(privBn, secret.data() + 32 - numBytes); //Extract public key. const EC_POINT *point = EC_KEY_get0_public_key(ec_key.get()); - int pubKeyLen=0; - pubKeyLen = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); - std::unique_ptr pubKey(new uint8_t[pubKeyLen]); - EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, pubKey.get(), pubKeyLen, NULL); - publicKey.insert(publicKey.begin(), pubKey.get(), pubKey.get()+pubKeyLen); + int size = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0, + nullptr); + if (size == 0) { + LOG(ERROR) << "Error generating public key encoding"; + return errorCode; + } + + publicKey.resize(size); + EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(), + publicKey.size(), nullptr); - EVP_PKEY_free(pkey); return ErrorCode::OK; } ErrorCode rsaRawKeyFromPKCS8(const std::vector& pkcs8Blob, std::vector& privateExp, std::vector& pubModulus) { ErrorCode errorCode = ErrorCode::INVALID_KEY_BLOB; - const BIGNUM *n=NULL, *e=NULL, *d=NULL; - EVP_PKEY *pkey = nullptr; + const BIGNUM *n = nullptr, *d = nullptr; const uint8_t *data = pkcs8Blob.data(); - d2i_PrivateKey(EVP_PKEY_RSA, &pkey, &data, pkcs8Blob.size()); - if(!pkey) { + EVP_PKEY* evpKey = d2i_PrivateKey(EVP_PKEY_RSA, nullptr /* pkey */, &data, + pkcs8Blob.size()); + if (!evpKey) { return legacy_enum_conversion(TranslateLastOpenSslError()); } + UniquePtr pkey(evpKey); - UniquePtr rsa_key(EVP_PKEY_get1_RSA(pkey)); + UniquePtr rsa_key(EVP_PKEY_get1_RSA(pkey.get())); if(!rsa_key.get()) { return legacy_enum_conversion(TranslateLastOpenSslError()); } - RSA_get0_key(rsa_key.get(), &n, &e, &d); - if(d != NULL && n != NULL) { + RSA_get0_key(rsa_key.get(), &n, nullptr, &d); + if(d != nullptr && n != nullptr) { /*private exponent */ int privExpLen = BN_num_bytes(d); - std::unique_ptr privExp(new uint8_t[privExpLen]); - BN_bn2bin(d, privExp.get()); + if (privExpLen > 256) { + LOG(ERROR) << "Size is " << privExpLen << ", expected this to be 256 or less"; + return errorCode; + } + privateExp.resize(256); + for (size_t n = 0; n < 256 - privExpLen; n++) { + privateExp[n] = 0x00; + } + BN_bn2bin(d, privateExp.data() + 256 - privExpLen); /* public modulus */ int pubModLen = BN_num_bytes(n); - std::unique_ptr pubMod(new uint8_t[pubModLen]); - BN_bn2bin(n, pubMod.get()); - - privateExp.insert(privateExp.begin(), privExp.get(), privExp.get()+privExpLen); - pubModulus.insert(pubModulus.begin(), pubMod.get(), pubMod.get()+pubModLen); + if (pubModLen > 256) { + LOG(ERROR) << "Size is " << pubModLen << ", expected this to be 256 or less"; + return errorCode; + } + pubModulus.resize(256); + for (size_t n = 0; n < 256 - pubModLen; n++) { + pubModulus[n] = 0x00; + } + BN_bn2bin(n, pubModulus.data() + 256 - pubModLen); } else { return errorCode; } - EVP_PKEY_free(pkey); return ErrorCode::OK; } diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index a222f93f..5f63d448 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -15,26 +15,27 @@ ** limitations under the License. */ -#include +#include "JavacardKeymaster4Device.h" + #include -#include -#include -#include + +#include + +#include +#include + #include -#include +#include #include #include #include -#include +#include + +#include "CborConverter.h" +#include "CommonUtils.h" +#include "JavacardSoftKeymasterContext.h" +#include "Transport.h" -#include -#include -#include -#include -#include -#include -#include -#include #define JAVACARD_KEYMASTER_NAME "JavacardKeymaster4.1Device v1.0" #define JAVACARD_KEYMASTER_AUTHOR "Android Open Source Project" @@ -52,9 +53,9 @@ #define SB_KM_OPR 1UL #define SE_POWER_RESET_STATUS_FLAG ( 1 << 30) -namespace keymaster { -namespace V4_1 { -namespace javacard { +namespace keymaster::V4_1::javacard { + +using namespace cppbor; static std::unique_ptr pTransportFactory = nullptr; constexpr size_t kOperationTableSize = 4; @@ -125,9 +126,8 @@ static inline bool getTag(const hidl_vec& params, Tag tag, KeyPara return false; } -template -static T translateExtendedErrorsToHalErrors(T& errorCode) { - T err; +static ErrorCode translateExtendedErrorsToHalErrors(ErrorCode& errorCode) { + ErrorCode err; switch(static_cast(errorCode)) { case SW_CONDITIONS_NOT_SATISFIED: case UNSUPPORTED_CLA: @@ -138,18 +138,18 @@ static T translateExtendedErrorsToHalErrors(T& errorCode) { case CRYPTO_INVALID_INIT: case CRYPTO_UNINITIALIZED_KEY: case GENERIC_UNKNOWN_ERROR: - err = T::UNKNOWN_ERROR; + err = ErrorCode::UNKNOWN_ERROR; break; case CRYPTO_NO_SUCH_ALGORITHM: - err = T::UNSUPPORTED_ALGORITHM; + err = ErrorCode::UNSUPPORTED_ALGORITHM; break; case UNSUPPORTED_INSTRUCTION: case CMD_NOT_ALLOWED: case SW_WRONG_LENGTH: - err = T::UNIMPLEMENTED; + err = ErrorCode::UNIMPLEMENTED; break; default: - err = static_cast(errorCode); + err = errorCode; break; } return err; @@ -211,22 +211,21 @@ static uint32_t handleErrorCode(const std::unique_ptr& oprCtx, return errorCode; } -template -static std::tuple, T> decodeData(CborConverter& cb, const std::vector& response, bool +static std::tuple, ErrorCode> decodeData(CborConverter& cb, const std::vector& response, bool hasErrorCode, const std::unique_ptr& oprCtx) { std::unique_ptr item(nullptr); - T errorCode = T::OK; - std::tie(item, errorCode) = cb.decodeData(response, hasErrorCode); + ErrorCode errorCode = ErrorCode::OK; + std::tie(item, errorCode) = cb.decodeData(response, hasErrorCode); uint32_t tempErrCode = handleErrorCode(oprCtx, static_cast(errorCode)); // SE sends errocode as unsigned value so convert the unsigned value // into a signed value of same magnitude and copy back to errorCode. - errorCode = static_cast(get2sCompliment(tempErrCode)); + errorCode = static_cast(get2sCompliment(tempErrCode)); - if (T::OK != errorCode) { + if (ErrorCode::OK != errorCode) { LOG(ERROR) << "error in decodeData: " << (int32_t) errorCode; - errorCode = translateExtendedErrorsToHalErrors(errorCode); + errorCode = translateExtendedErrorsToHalErrors(errorCode); } LOG(DEBUG) << "decodeData status: " << (int32_t) errorCode; return {std::move(item), errorCode}; @@ -464,13 +463,17 @@ Return JavacardKeymaster4Device::getHardwareInfo(getHardwareInfo_cb _hidl_ false, oprCtx_); if (item != nullptr) { std::vector temp; - if(!cborConverter_.getUint64(item, 0, securityLevel) || - !cborConverter_.getBinaryArray(item, 1, jcKeymasterName) || - !cborConverter_.getBinaryArray(item, 2, jcKeymasterAuthor)) { + auto optSecurityLevel = cborConverter_.getUint64(item, 0); + auto optKeymasterName = cborConverter_.getByteArrayHidlStr(item, 1); + auto optKeymasterAuthor = cborConverter_.getByteArrayHidlStr(item, 2); + if (!optSecurityLevel || !optKeymasterName || !optKeymasterAuthor) { LOG(ERROR) << "Failed to convert cbor data of INS_GET_HW_INFO_CMD"; - _hidl_cb(static_cast(securityLevel), jcKeymasterName, jcKeymasterAuthor); + _hidl_cb(SecurityLevel::STRONGBOX, JAVACARD_KEYMASTER_NAME, JAVACARD_KEYMASTER_AUTHOR); return Void(); } + securityLevel = optSecurityLevel.value(); + jcKeymasterName = std::move(*optKeymasterName); + jcKeymasterAuthor = std::move(*optKeymasterAuthor); } _hidl_cb(static_cast(securityLevel), jcKeymasterName, jcKeymasterAuthor); return Void(); @@ -495,12 +498,15 @@ Return JavacardKeymaster4Device::getHmacSharingParameters(getHmacSharingPa std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborData.begin(), cborData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getHmacSharingParameters(item, 1, hmacSharingParameters)) { + auto optHmacSharingParams = cborConverter_.getHmacSharingParameters(item, 1); + if(!optHmacSharingParams) { LOG(ERROR) << "javacard strongbox : Failed to convert cbor data of INS_GET_HMAC_SHARING_PARAM_CMD"; errorCode = ErrorCode::UNKNOWN_ERROR; + } else { + LOG(DEBUG) << "javacard strongbox : received getHmacSharingParameter from Javacard - successful"; + hmacSharingParameters = std::move(*optHmacSharingParams); } } - LOG(DEBUG) << "javacard strongbox : received getHmacSharingParameter from Javacard - successful"; // Send earlyBootEnded if there is any pending earlybootEnded event. handleSendEarlyBootEndedEvent(); } @@ -556,18 +562,16 @@ Return JavacardKeymaster4Device::computeSharedHmac(const hidl_vec(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - std::vector bstr; - if(!cborConverter_.getBinaryArray(item, 1, bstr)) { + auto optHidlVec = cborConverter_.getByteArrayHidlVec(item, 1); + if(!optHidlVec) { LOG(ERROR) << "INS_COMPUTE_SHARED_HMAC_CMD: failed to convert cbor sharing check value"; errorCode = ErrorCode::UNKNOWN_ERROR; } else { - sharingCheck = bstr; + LOG(ERROR) << "javacard strongbox : computeSharedHmac - sending sharingCheckToKeystore"; + sharingCheck = std::move(*optHidlVec); } } } - - LOG(ERROR) << "javacard strongbox : computeSharedHmac - sending sharingCheckToKeystore"; - _hidl_cb(errorCode, sharingCheck); return Void(); } @@ -627,14 +631,18 @@ Return JavacardKeymaster4Device::generateKey(const hidl_vec& std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getBinaryArray(item, 1, keyBlob) || - !cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) { + auto optKeyBlob = cborConverter_.getByteArrayHidlVec(item, 1); + auto optKeyCharacteristics = cborConverter_.getKeyCharacteristics(item, 2); + if (!optKeyBlob || !optKeyCharacteristics) { //Clear the buffer. keyBlob.setToExternal(nullptr, 0); keyCharacteristics.softwareEnforced.setToExternal(nullptr, 0); keyCharacteristics.hardwareEnforced.setToExternal(nullptr, 0); errorCode = ErrorCode::UNKNOWN_ERROR; LOG(ERROR) << "INS_GENERATE_KEY_CMD: error while converting cbor data: " << (int32_t) errorCode; + } else { + keyBlob = std::move(*optKeyBlob); + keyCharacteristics = std::move(*optKeyCharacteristics); } } } @@ -680,14 +688,18 @@ Return JavacardKeymaster4Device::importKey(const hidl_vec& k std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getBinaryArray(item, 1, keyBlob) || - !cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) { + auto optKeyBlob = cborConverter_.getByteArrayHidlVec(item, 1); + auto optKeyCharacteristics = cborConverter_.getKeyCharacteristics(item, 2); + if (!optKeyBlob || !optKeyCharacteristics) { //Clear the buffer. keyBlob.setToExternal(nullptr, 0); keyCharacteristics.softwareEnforced.setToExternal(nullptr, 0); keyCharacteristics.hardwareEnforced.setToExternal(nullptr, 0); errorCode = ErrorCode::UNKNOWN_ERROR; - LOG(ERROR) << "INS_IMPORT_KEY_CMD: error while converting cbor data, status: " << (int32_t) errorCode; + LOG(ERROR) << "INS_IMPORT_KEY_CMD: error while converting cbor data: " << (int32_t) errorCode; + } else { + keyBlob = std::move(*optKeyBlob); + keyCharacteristics = std::move(*optKeyCharacteristics); } } } @@ -747,14 +759,18 @@ Return JavacardKeymaster4Device::importWrappedKey(const hidl_vec& std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getBinaryArray(item, 1, keyBlob) || - !cborConverter_.getKeyCharacteristics(item, 2, keyCharacteristics)) { + auto optKeyBlob = cborConverter_.getByteArrayHidlVec(item, 1); + auto optKeyCharacteristics = cborConverter_.getKeyCharacteristics(item, 2); + if (!optKeyBlob || !optKeyCharacteristics) { //Clear the buffer. keyBlob.setToExternal(nullptr, 0); keyCharacteristics.softwareEnforced.setToExternal(nullptr, 0); keyCharacteristics.hardwareEnforced.setToExternal(nullptr, 0); errorCode = ErrorCode::UNKNOWN_ERROR; - LOG(ERROR) << "INS_IMPORT_WRAPPED_KEY_CMD: error while converting cbor data, status: " << (int32_t) errorCode; + LOG(ERROR) << "INS_IMPORT_WRAPPED_KEY_CMD: error while converting cbor data: " << (int32_t) errorCode; + } else { + keyBlob = std::move(*optKeyBlob); + keyCharacteristics = std::move(*optKeyCharacteristics); } } } @@ -780,11 +796,14 @@ Return JavacardKeymaster4Device::getKeyCharacteristics(const hidl_vec(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getKeyCharacteristics(item, 1, keyCharacteristics)) { + auto optKeyCharacteristics = cborConverter_.getKeyCharacteristics(item, 1); + if (!optKeyCharacteristics) { keyCharacteristics.softwareEnforced.setToExternal(nullptr, 0); keyCharacteristics.hardwareEnforced.setToExternal(nullptr, 0); errorCode = ErrorCode::UNKNOWN_ERROR; LOG(ERROR) << "INS_GET_KEY_CHARACTERISTICS_CMD: error while converting cbor data, status: " << (int32_t) errorCode; + } else { + keyCharacteristics = std::move(*optKeyCharacteristics); } } } @@ -829,7 +848,29 @@ Return JavacardKeymaster4Device::exportKey(KeyFormat exportFormat, const h return Void(); } - +ErrorCode JavacardKeymaster4Device::getFactoryAttestCertChain(std::vector>& certChain) { + std::vector cborData; + std::vector cborOutData; + std::unique_ptr item; + ErrorCode errorCode = sendData(Instruction::INS_GET_CERT_CHAIN_CMD, cborData, cborOutData); + if (errorCode == ErrorCode::OK) { + // Skip last 2 bytes in cborData, it contains status. + std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end() - 2), + true, oprCtx_); + if (item != nullptr) { + std::vector asn1CertChain; + auto optChain = cborConverter_.getByteArrayVec(item, 1); + if (!optChain) { + errorCode = ErrorCode::UNKNOWN_ERROR; + LOG(ERROR) << "INS_GET_CERT_CHAIN_CMD: errorn in converting cbor data, status: " << (int32_t)errorCode; + } else { + asn1CertChain = std::move(*optChain); + errorCode = getCertificateChain(asn1CertChain, certChain); + } + } + } + return errorCode; +} Return JavacardKeymaster4Device::attestKey(const hidl_vec& keyToAttest, const hidl_vec& attestParams, attestKey_cb _hidl_cb) { cppbor::Array array; @@ -851,33 +892,18 @@ Return JavacardKeymaster4Device::attestKey(const hidl_vec& keyToA std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getMultiBinaryArray(item, 1, temp)) { + auto optTemp = cborConverter_.getCertChain(item, 1); + if (!optTemp) { errorCode = ErrorCode::UNKNOWN_ERROR; LOG(ERROR) << "INS_ATTEST_KEY_CMD: error in converting cbor data, status: " << (int32_t) errorCode; } else { - cborData.clear(); - cborOutData.clear(); - errorCode = sendData(Instruction::INS_GET_CERT_CHAIN_CMD, cborData, cborOutData); - if(errorCode == ErrorCode::OK) { - //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), - cborOutData.end()-2), - true, oprCtx_); - if (item != nullptr) { - std::vector chain; - if(!cborConverter_.getBinaryArray(item, 1, chain)) { - errorCode = ErrorCode::UNKNOWN_ERROR; - LOG(ERROR) << "attestkey INS_GET_CERT_CHAIN_CMD: errorn in converting cbor data, status: " << (int32_t) errorCode; - } else { - if(ErrorCode::OK == (errorCode = getCertificateChain(chain, temp))) { - certChain.resize(temp.size()); - for(int i = 0; i < temp.size(); i++) { - certChain[i] = temp[i]; - } - } else { - LOG(ERROR) << "Error in attestkey getCertificateChain: " << (int32_t) errorCode; - } - } + temp = std::move(*optTemp); + // Request the factory attest certificate chain from SE. + errorCode = getFactoryAttestCertChain(temp); + if (ErrorCode::OK == errorCode) { + certChain.resize(temp.size()); + for (int i = 0; i < temp.size(); i++) { + certChain[i] = temp[i]; } } } @@ -905,9 +931,12 @@ Return JavacardKeymaster4Device::upgradeKey(const hidl_vec& keyBl std::tie(item, errorCode) = decodeData(cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); if (item != nullptr) { - if(!cborConverter_.getBinaryArray(item, 1, upgradedKeyBlob)) { + auto optKeyBlob = cborConverter_.getByteArrayHidlVec(item, 1); + if (!optKeyBlob) { errorCode = ErrorCode::UNKNOWN_ERROR; LOG(ERROR) << "INS_UPGRADE_KEY_CMD: error in converting cbor data, status: " << (int32_t) errorCode; + } else { + upgradedKeyBlob = std::move(*optKeyBlob); } } } @@ -1093,8 +1122,9 @@ ErrorCode JavacardKeymaster4Device::handleBeginPrivateKeyOperation( std::vector(cborOutData.begin(), cborOutData.end() - 2), true, oprCtx_); if (item != nullptr) { - if (!cborConverter_.getKeyParameters(item, 1, outParams) || - !cborConverter_.getUint64(item, 2, operationHandle)) { + auto optOutParams = cborConverter_.getKeyParameters(item, 1); + auto optOperationHandle = cborConverter_.getUint64(item, 2); + if (!optOperationHandle || !optOutParams) { errorCode = ErrorCode::UNKNOWN_ERROR; outParams.setToExternal(nullptr, 0); operationHandle = 0; @@ -1102,6 +1132,8 @@ ErrorCode JavacardKeymaster4Device::handleBeginPrivateKeyOperation( "data, status: " << (int32_t)errorCode; } else { + outParams = std::move(*optOutParams); + operationHandle = optOperationHandle.value(); /* Store the operationInfo */ oprCtx_->setOperationInfo(operationHandle, purpose, param.f.algorithm, inParams); @@ -1235,18 +1267,22 @@ JavacardKeymaster4Device::update(uint64_t operationHandle, const hidl_vec). - if ((outParams.size() == 0 && - !cborConverter_.getKeyParameters(item, 2, outParams)) || - !cborConverter_.getBinaryArray(item, 3, tempOut)) { - outParams.setToExternal(nullptr, 0); - tempOut.clear(); + auto optOutParams = cborConverter_.getKeyParameters(item, 2); + auto optTempOut = cborConverter_.getByteArrayVec(item, 3); + if (!optOutParams || !optTempOut) { errorCode = ErrorCode::UNKNOWN_ERROR; - LOG(ERROR) << "sendDataCallback: INS_UPDATE_OPERATION_CMD: error while " + tempOut.clear(); + LOG(ERROR) << "sendDataCallback: INS_UPDATE_OPERATION_CMD: error while " "converting cbor data, status: " << (int32_t)errorCode; + return errorCode; + } + if (outParams.size() == 0) { + outParams = std::move(*optOutParams); } + tempOut.insert(tempOut.end(), optTempOut->begin(), optTempOut->end()); } } return errorCode; @@ -1390,18 +1426,22 @@ JavacardKeymaster4Device::finish(uint64_t operationHandle, const hidl_vec). - if ((outParams.size() == 0 && - !cborConverter_.getKeyParameters(item, keyParamPos, outParams)) || - !cborConverter_.getBinaryArray(item, outputPos, tempOut)) { - outParams.setToExternal(nullptr, 0); - tempOut.clear(); + auto optOutParams = cborConverter_.getKeyParameters(item, keyParamPos); + auto optTempOut = cborConverter_.getByteArrayVec(item, outputPos); + if (!optOutParams || !optTempOut) { errorCode = ErrorCode::UNKNOWN_ERROR; - LOG(ERROR) - << "sendDataCallback: error while converting cbor data in operation: " - << (int32_t)ins << " decodeData, status: " << (int32_t)errorCode; + tempOut.clear(); + LOG(ERROR) << "sendDataCallback: INS_FINISH_OPERATION_CMD: error while " + "converting cbor data, status: " + << (int32_t)errorCode; + return errorCode; } + if (outParams.size() == 0) { + outParams = std::move(*optOutParams); + } + tempOut.insert(tempOut.end(), optTempOut->begin(), optTempOut->end()); } } return errorCode; @@ -1509,8 +1549,10 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device if(errorCode == V41ErrorCode::OK) { //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = decodeData( + ErrorCode err; + std::tie(item, err) = decodeData( cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); + errorCode = static_cast(err); } return errorCode; } @@ -1526,8 +1568,10 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device if(errorCode == V41ErrorCode::OK) { //Skip last 2 bytes in cborData, it contains status. - std::tie(item, errorCode) = decodeData( + ErrorCode err; + std::tie(item, err) = decodeData( cborConverter_, std::vector(cborOutData.begin(), cborOutData.end()-2), true, oprCtx_); + errorCode = static_cast(err); } else { // Incase of failure cache the event and send in the next immediate request to Applet. isEarlyBootEventPending = true; @@ -1535,6 +1579,4 @@ Return<::android::hardware::keymaster::V4_1::ErrorCode> JavacardKeymaster4Device return errorCode; } -} // javacard -} // namespace V4_1 -} // namespace keymaster +} diff --git a/HAL/keymaster/4.1/JavacardOperationContext.cpp b/HAL/keymaster/4.1/JavacardOperationContext.cpp index 64c13c71..1a065123 100644 --- a/HAL/keymaster/4.1/JavacardOperationContext.cpp +++ b/HAL/keymaster/4.1/JavacardOperationContext.cpp @@ -15,7 +15,8 @@ ** limitations under the License. */ -#include +#include "JavacardOperationContext.h" + #include #define MAX_ALLOWED_INPUT_SIZE 256 @@ -25,9 +26,7 @@ #define EC_INPUT_MSG_LEN 32 #define MAX_EC_BUFFER_SIZE 32 -namespace keymaster { -namespace V4_1 { -namespace javacard { +namespace keymaster::V4_1::javacard { enum class Operation { Update = 0, @@ -378,6 +377,4 @@ ErrorCode OperationContext::handleInternalUpdate(uint64_t operHandle, std::vecto } -} // namespace javacard -} // namespace V4_1 -} // namespace keymaster +} diff --git a/HAL/keymaster/4.1/JavacardSoftKeymasterContext.cpp b/HAL/keymaster/4.1/JavacardSoftKeymasterContext.cpp index 99097662..0c04d502 100644 --- a/HAL/keymaster/4.1/JavacardSoftKeymasterContext.cpp +++ b/HAL/keymaster/4.1/JavacardSoftKeymasterContext.cpp @@ -14,23 +14,28 @@ * limitations under the License. */ -#include -#include -#include +#include "JavacardSoftKeymasterContext.h" + +#include + #include +#include +#include #include -#include +#include + #include -#include -#include #include +#include +#include #include -#include -#include -#include + +#include "CborConverter.h" +#include "CommonUtils.h" using std::unique_ptr; using ::keymaster::V4_1::javacard::KmParamSet; +using namespace cppbor; namespace keymaster { @@ -190,7 +195,10 @@ keymaster_error_t JavaCardSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyB uint64_t version = 0; int pubKeyOffset; int keyCharsOffset; - cc.getUint64(item, 0, version); + auto optVersion = cc.getUint64(item, 0); + if (optVersion) { + version = optVersion.value(); + } switch (version) { case 0: pubKeyOffset = 4; @@ -203,13 +211,15 @@ keymaster_error_t JavaCardSoftKeymasterContext::ParseKeyBlob(const KeymasterKeyB default: return KM_ERROR_INVALID_KEY_BLOB; } - std::vector temp(0); - if(cc.getBinaryArray(item, pubKeyOffset, temp)) { - key_material = {temp.data(), temp.size()}; - temp.clear(); + auto optTemp = cc.getByteArrayVec(item, pubKeyOffset); + if (optTemp) { + key_material = {optTemp->data(), optTemp->size()}; } KeyCharacteristics keyCharacteristics; - cc.getKeyCharacteristics(item, keyCharsOffset, keyCharacteristics); + auto optKeyChars = cc.getKeyCharacteristics(item, keyCharsOffset); + if (optKeyChars) { + keyCharacteristics = optKeyChars.value(); + } sw_enforced.Reinitialize(KmParamSet(keyCharacteristics.softwareEnforced)); hw_enforced.Reinitialize(KmParamSet(keyCharacteristics.hardwareEnforced)); diff --git a/HAL/keymaster/4.1/OmapiTransport.cpp b/HAL/keymaster/4.1/OmapiTransport.cpp index cb363254..68e3deef 100644 --- a/HAL/keymaster/4.1/OmapiTransport.cpp +++ b/HAL/keymaster/4.1/OmapiTransport.cpp @@ -14,15 +14,17 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ + +#include "Transport.h" + #include -#include #include +#include + #include #include -#include "Transport.h" - namespace se_transport { constexpr const char kEseReaderPrefix[] = "eSE"; diff --git a/HAL/keymaster/4.1/SocketTransport.cpp b/HAL/keymaster/4.1/SocketTransport.cpp index e060262f..6c2f094a 100644 --- a/HAL/keymaster/4.1/SocketTransport.cpp +++ b/HAL/keymaster/4.1/SocketTransport.cpp @@ -14,16 +14,19 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -#include -#include -#include -#include + #include "Transport.h" + +#include #include +#include + +#include + +#include #define PORT 8080 -#define IPADDR "192.168.0.29" -//#define IPADDR "192.168.0.5" +#define IPADDR "192.168.0.5" #define MAX_RECV_BUFFER_SIZE 2500 namespace se_transport { diff --git a/HAL/keymaster/4.1/service.cpp b/HAL/keymaster/4.1/service.cpp index cd7653d0..f87216b9 100644 --- a/HAL/keymaster/4.1/service.cpp +++ b/HAL/keymaster/4.1/service.cpp @@ -16,9 +16,11 @@ */ #include + #include #include -#include + +#include "JavacardKeymaster4Device.h" int main() { ::android::hardware::configureRpcThreadpool(1, true); diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp index 33f255f6..852b92ca 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -38,7 +38,7 @@ cc_binary { "libhardware", "libhidlbase", "libsoftkeymasterdevice", - "libsoft_attestation_cert", + "libsoft_attestation_cert", "libkeymaster_messages", "libkeymaster_portable", "libcppbor_external", @@ -76,14 +76,14 @@ cc_library { "libhardware", "libhidlbase", "libsoftkeymasterdevice", - "libsoft_attestation_cert", + "libsoft_attestation_cert", "libkeymaster_messages", "libkeymaster_portable", "libcppbor_external", "android.hardware.keymaster@4.1", "android.hardware.keymaster@4.0", "libjc_transport", - "libcrypto", + "libcrypto", "libbinder_ndk", "android.se.omapi-V1-ndk", ], @@ -130,10 +130,10 @@ cc_library { "libutils", "libhardware", "libhidlbase", - "libsoftkeymasterdevice", - "libsoft_attestation_cert", + "libsoftkeymasterdevice", + "libsoft_attestation_cert", "libkeymaster_messages", - "libkeymaster_portable", + "libkeymaster_portable", "libcppbor_external", "android.hardware.keymaster@4.1", "android.hardware.keymaster@4.0", diff --git a/HAL/keymaster/include/CborConverter.h b/HAL/keymaster/include/CborConverter.h index 45855244..14b8d5e4 100644 --- a/HAL/keymaster/include/CborConverter.h +++ b/HAL/keymaster/include/CborConverter.h @@ -15,17 +15,16 @@ ** limitations under the License. */ -#ifndef __CBOR_CONVERTER_H_ -#define __CBOR_CONVERTER_H_ +#pragma once #include #include -#include -#include -#include + #include +#include -using namespace cppbor; +#include +#include using ::android::hardware::hidl_vec; using ::android::hardware::keymaster::V4_0::ErrorCode; @@ -48,184 +47,93 @@ class CborConverter /** * Parses the input data which is in CBOR format and returns a Tuple of Item pointer and the first element in the item pointer. */ - template - std::tuple, T> decodeData(const std::vector& response, bool - hasErrorCode) { - const uint8_t* pos; - std::unique_ptr item(nullptr); - std::string message; - T errorCode = T::OK; - - std::tie(item, pos, message) = parse(response); - - if(item != nullptr && hasErrorCode) { - if(MajorType::ARRAY == getType(item)) { - if(!getErrorCode(item, 0, errorCode)) - item = nullptr; - } else if (MajorType::UINT == getType(item)) { - uint64_t err; - if(getUint64(item, err)) { - errorCode = static_cast(err); - } - item = nullptr; /*Already read the errorCode. So no need of sending item to client */ - } - } - return {std::move(item), errorCode}; - } + std::tuple, ErrorCode> decodeData(const std::vector& response, + bool hasErrorCode); /** - * Get the signed/unsigned integer value at a given position from the item pointer. + * Get the unsigned integer value from the item pointer. */ - template - bool getUint64(const std::unique_ptr& item, const uint32_t pos, T& value); + std::optional getUint64(const std::unique_ptr &item); /** - * Get the signed/unsigned integer value from the item pointer. + * Get the unsigned integer value at a given position from the item pointer. */ - template - bool getUint64(const std::unique_ptr& item, T& value); + std::optional getUint64(const std::unique_ptr& item, const uint32_t pos); /** * Get the HmacSharingParameters structure value at the given position from the item pointer. */ - bool getHmacSharingParameters(const std::unique_ptr& item, const uint32_t pos, HmacSharingParameters& params); + std::optional getHmacSharingParameters(const std::unique_ptr& item, const uint32_t pos); /** * Get the Binary string at the given position from the item pointer. */ - bool getBinaryArray(const std::unique_ptr& item, const uint32_t pos, ::android::hardware::hidl_string& value); + std::optional<::android::hardware::hidl_string> getByteArrayHidlStr(const std::unique_ptr& item, const uint32_t pos); /** * Get the Binary string at the given position from the item pointer. */ - bool getBinaryArray(const std::unique_ptr& item, const uint32_t pos, std::vector& value); + std::optional> getByteArrayVec(const std::unique_ptr& item, const uint32_t pos); /** * Get the Binary string at the given position from the item pointer. */ - bool getBinaryArray(const std::unique_ptr& item, const uint32_t pos, - ::android::hardware::hidl_vec& value); - /** - * Get the HardwareAuthToken value at the given position from the item pointer. - */ - bool getHardwareAuthToken(const std::unique_ptr& item, const uint32_t pos, HardwareAuthToken& authType); + std::optional<::android::hardware::hidl_vec> getByteArrayHidlVec(const std::unique_ptr& item, const uint32_t pos); /** * Get the list of KeyParameters value at the given position from the item pointer. */ - bool getKeyParameters(const std::unique_ptr& item, const uint32_t pos, android::hardware::hidl_vec& keyParams); + std::optional> getKeyParameters(const std::unique_ptr& item, const uint32_t pos); /** * Adds the the list of KeyParameters values to the Array item. */ - bool addKeyparameters(Array& array, const android::hardware::hidl_vec& + bool addKeyparameters(cppbor::Array& array, const android::hardware::hidl_vec& keyParams); /** * Add HardwareAuthToken value to the Array item. */ - bool addHardwareAuthToken(Array& array, const HardwareAuthToken& + bool addHardwareAuthToken(cppbor::Array& array, const HardwareAuthToken& authToken); - /** - * Get the VerificationToken value at the given position from the item pointer. - */ - bool getVerificationToken(const std::unique_ptr& item, const uint32_t pos, VerificationToken& - token); /** * Get the KeyCharacteristics value at the given position from the item pointer. */ - bool getKeyCharacteristics(const std::unique_ptr &item, const uint32_t pos, - KeyCharacteristics& keyCharacteristics); + std::optional getKeyCharacteristics(const std::unique_ptr &item, const uint32_t pos); /** * Get the list of binary arrays at the given position from the item pointer. */ - bool getMultiBinaryArray(const std::unique_ptr& item, const uint32_t pos, - std::vector>& data); + std::optional>> getCertChain(const std::unique_ptr& item, const uint32_t pos); /** * Add VerificationToken value to the Array item. */ - bool addVerificationToken(Array& array, const VerificationToken& + bool addVerificationToken(cppbor::Array& array, const VerificationToken& verificationToken, std::vector& encodedParamsVerified); /** * Get the ErrorCode value at the give position from the item pointer. */ - template) || - (std::is_same_v)>> - inline bool getErrorCode(const std::unique_ptr& item, const uint32_t pos, T& errorCode) { - bool ret = false; - uint64_t errorVal; - if (!getUint64(item, pos, errorVal)) { - return ret; - } - errorCode = static_cast(errorVal); - - ret = true; - return ret; - } + std::optional getErrorCode(const std::unique_ptr &item, const uint32_t pos); private: /** * Get the type of the Item pointer. */ - inline MajorType getType(const std::unique_ptr &item) { return item.get()->type(); } + inline cppbor::MajorType getType(const std::unique_ptr &item) { return item.get()->type(); } /** * Construct Keyparameter structure from the pair of key and value. If TagType is ENUM_REP the value contains * binary string. If TagType is UINT_REP or ULONG_REP the value contains Array of unsigned integers. */ - bool getKeyParameter(const std::pair&, - const std::unique_ptr&> pair, std::vector& keyParam); + std::optional> getKeyParameter(const std::pair&, + const std::unique_ptr&> pair); - /** - * Get the sub item pointer from the root item pointer at the given position. + /** + * Checks if the item is of type Array and the pos is not out of range. */ - inline void getItemAtPos(const std::unique_ptr& item, const uint32_t pos, std::unique_ptr& subItem) { - Array* arr = nullptr; - - if (MajorType::ARRAY != getType(item)) { - return; - } - arr = const_cast(item.get()->asArray()); - if (arr->size() < (pos + 1)) { - return; - } - subItem = std::move((*arr)[pos]); - } + std::optional> getItemAtPos(const std::unique_ptr &item, const uint32_t pos); }; - -template -bool CborConverter::getUint64(const std::unique_ptr& item, T& value) { - bool ret = false; - if ((item == nullptr) || - (std::is_unsigned::value && (MajorType::UINT != getType(item))) || - ((std::is_signed::value && (MajorType::NINT != getType(item))))) { - return ret; - } - - if (std::is_unsigned::value) { - const Uint* uintVal = item.get()->asUint(); - value = uintVal->value(); - } - else { - const Nint* nintVal = item.get()->asNint(); - value = nintVal->value(); - } - ret = true; - return ret; //success -} - -template -bool CborConverter::getUint64(const std::unique_ptr& item, const uint32_t pos, T& value) { - std::unique_ptr intItem(nullptr); - getItemAtPos(item, pos, intItem); - return getUint64(intItem, value); -} - - - -#endif diff --git a/HAL/keymaster/include/CommonUtils.h b/HAL/keymaster/include/CommonUtils.h index 8fd247f7..be7694fd 100644 --- a/HAL/keymaster/include/CommonUtils.h +++ b/HAL/keymaster/include/CommonUtils.h @@ -15,17 +15,13 @@ ** limitations under the License. */ - -#ifndef KEYMASTER_V4_1_JAVACARD_COMMONUTILS_H_ -#define KEYMASTER_V4_1_JAVACARD_COMMONUTILS_H_ +#pragma once #include -#include #include +#include -namespace keymaster { -namespace V4_1 { -namespace javacard { +namespace keymaster::V4_1::javacard { using ::android::hardware::hidl_vec; using ::android::hardware::keymaster::V4_0::ErrorCode; using ::android::hardware::keymaster::V4_0::Tag; @@ -98,7 +94,4 @@ class KmParamSet : public keymaster_key_param_set_t { ~KmParamSet() { delete[] params; } }; -} // namespace javacard -} // namespace V4_1 -} // namespace keymaster -#endif //KEYMASTER_V4_1_JAVACARD_COMMONUTILS_H_ +} // namespace javacard::V4_1::keymaster diff --git a/HAL/keymaster/include/JavacardKeymaster4Device.h b/HAL/keymaster/include/JavacardKeymaster4Device.h index 617457b1..b3aeec07 100644 --- a/HAL/keymaster/include/JavacardKeymaster4Device.h +++ b/HAL/keymaster/include/JavacardKeymaster4Device.h @@ -15,25 +15,25 @@ ** limitations under the License. */ -#ifndef KEYMASTER_V4_1_JAVACARD_JAVACARDKEYMASTER4DEVICE_H_ -#define KEYMASTER_V4_1_JAVACARD_JAVACARDKEYMASTER4DEVICE_H_ +#pragma once #include #include #include -#include -#include "CborConverter.h" -#include "TransportFactory.h" + #include #include + #include #include #include -#include -namespace keymaster { -namespace V4_1 { -namespace javacard { +#include "CborConverter.h" +#include "JavacardOperationContext.h" +#include "TransportFactory.h" + +namespace keymaster::V4_1::javacard { + #define INS_BEGIN_KM_CMD 0x00 #define INS_END_KM_PROVISION_CMD 0x20 #define INS_END_KM_CMD 0x7F @@ -144,6 +144,8 @@ class JavacardKeymaster4Device : public IKeymasterDevice { hidl_vec& outParams, uint64_t& operationHandle, OperationType& operType); + ErrorCode getFactoryAttestCertChain(std::vector>& certChain); + ErrorCode abortOperation(uint64_t operationHandle, OperationType operType); ErrorCode abortPublicKeyOperation(uint64_t operationHandle); @@ -161,8 +163,4 @@ class JavacardKeymaster4Device : public IKeymasterDevice { CborConverter cborConverter_; }; -} // namespace javacard -} // namespace V4_1 -} // namespace keymaster - -#endif // KEYMASTER_V4_1_JAVACARD_JAVACARDKEYMASTER4DEVICE_H_ +} // namespace javacard::V4_1::keymaster diff --git a/HAL/keymaster/include/JavacardOperationContext.h b/HAL/keymaster/include/JavacardOperationContext.h index 0d452c67..66a72f62 100644 --- a/HAL/keymaster/include/JavacardOperationContext.h +++ b/HAL/keymaster/include/JavacardOperationContext.h @@ -15,17 +15,15 @@ ** limitations under the License. */ -#ifndef KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ -#define KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ +#pragma once #include + #include #define MAX_BUF_SIZE 256 -namespace keymaster { -namespace V4_1 { -namespace javacard { +namespace keymaster::V4_1::javacard { using ::android::hardware::hidl_vec; using ::android::hardware::keymaster::V4_0::ErrorCode; @@ -148,8 +146,4 @@ class OperationContext { }; -} // namespace javacard -} // namespace V4_1 -} // namespace keymaster - -#endif // KEYMASTER_V4_1_JAVACARD_OPERATIONCONTEXT_H_ +} // namespace javacard::V4_1::keymaster diff --git a/HAL/keymaster/include/JavacardSoftKeymasterContext.h b/HAL/keymaster/include/JavacardSoftKeymasterContext.h index 8cdeab92..9f9caf90 100644 --- a/HAL/keymaster/include/JavacardSoftKeymasterContext.h +++ b/HAL/keymaster/include/JavacardSoftKeymasterContext.h @@ -14,11 +14,11 @@ * limitations under the License. */ -#ifndef SYSTEM_KEYMASTER_JAVA_CARD_SOFT_KEYMASTER_CONTEXT_H_ -#define SYSTEM_KEYMASTER_JAVA_CARD_SOFT_KEYMASTER_CONTEXT_H_ +#pragma once #include #include + namespace keymaster { class SoftKeymasterKeyRegistrations; @@ -48,4 +48,3 @@ class JavaCardSoftKeymasterContext : public keymaster::PureSoftKeymasterContext } // namespace keymaster -#endif // SYSTEM_KEYMASTER_PURE_SOFT_KEYMASTER_CONTEXT_H_ diff --git a/HAL/keymaster/include/Transport.h b/HAL/keymaster/include/Transport.h index f525479c..c389b5f2 100644 --- a/HAL/keymaster/include/Transport.h +++ b/HAL/keymaster/include/Transport.h @@ -14,8 +14,9 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -#ifndef __SE_TRANSPORT__ -#define __SE_TRANSPORT__ +#pragma once + +#include #include #include @@ -23,9 +24,9 @@ #include #include #include + #include -#include namespace se_transport { @@ -131,4 +132,3 @@ class SocketTransport : public ITransport { }; } -#endif /* __SE_TRANSPORT__ */ diff --git a/HAL/keymaster/include/TransportFactory.h b/HAL/keymaster/include/TransportFactory.h index b09e3ba9..303c22a7 100644 --- a/HAL/keymaster/include/TransportFactory.h +++ b/HAL/keymaster/include/TransportFactory.h @@ -14,8 +14,7 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -#ifndef __SE_TRANSPORT_FACTORY__ -#define __SE_TRANSPORT_FACTORY__ +#pragma once #include "Transport.h" @@ -73,4 +72,3 @@ class TransportFactory { }; } -#endif /* __SE_TRANSPORT_FACTORY__ */