Keystore 2.0: Revise Legacy wrapper error handling

Now using mostly KeyMint error codes and a safe conversion function.

Test: keystore2_km_compat_test_cpp

Change-Id: I43ec848a8ee5544fcc8e79a4af0690e45bc28095
This commit is contained in:
Janis Danisevskis 2021-01-30 22:33:11 -08:00
parent f3caf2698b
commit 926a6c032f
4 changed files with 342 additions and 102 deletions

View file

@ -52,19 +52,23 @@ namespace KMV1 = ::aidl::android::hardware::security::keymint;
// Utility functions
// Converts a V4 error code into a ScopedAStatus
ScopedAStatus convertErrorCode(V4_0_ErrorCode result) {
if (result == V4_0_ErrorCode::OK) {
ScopedAStatus convertErrorCode(KMV1::ErrorCode result) {
if (result == KMV1::ErrorCode::OK) {
return ScopedAStatus::ok();
}
return ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(result));
}
static V4_0_ErrorCode toErrorCode(const ScopedAStatus& status) {
// Converts a V4 error code into a ScopedAStatus
ScopedAStatus convertErrorCode(V4_0_ErrorCode result) {
return convertErrorCode(convert(result));
}
static KMV1::ErrorCode toErrorCode(const ScopedAStatus& status) {
if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
return static_cast<V4_0_ErrorCode>(status.getServiceSpecificError());
return static_cast<KMV1::ErrorCode>(status.getServiceSpecificError());
} else {
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
}
@ -174,25 +178,27 @@ ScopedAStatus KeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* _aidl_return)
_aidl_return->keyMintAuthorName = keymasterAuthorName;
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return ScopedAStatus::ok();
}
ScopedAStatus KeyMintDevice::addRngEntropy(const std::vector<uint8_t>& in_data) {
V4_0_ErrorCode errorCode = mDevice->addRngEntropy(in_data);
return convertErrorCode(errorCode);
auto result = mDevice->addRngEntropy(in_data);
if (!result.isOk()) {
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(result);
}
ScopedAStatus KeyMintDevice::generateKey(const std::vector<KeyParameter>& in_keyParams,
KeyCreationResult* out_creationResult) {
auto legacyKeyParams = convertKeyParametersToLegacy(in_keyParams);
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->generateKey(
legacyKeyParams, [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
const V4_0_KeyCharacteristics& keyCharacteristics) {
errorCode = error;
errorCode = convert(error);
out_creationResult->keyBlob = keyBlob;
out_creationResult->keyCharacteristics =
convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
@ -201,12 +207,12 @@ ScopedAStatus KeyMintDevice::generateKey(const std::vector<KeyParameter>& in_key
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
}
if (errorCode == V4_0_ErrorCode::OK) {
if (errorCode == KMV1::ErrorCode::OK) {
auto cert = getCertificate(in_keyParams, out_creationResult->keyBlob);
if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
auto code = std::get<V4_0_ErrorCode>(cert);
if (std::holds_alternative<KMV1::ErrorCode>(cert)) {
auto code = std::get<KMV1::ErrorCode>(cert);
// We return OK in successful cases that do not generate a certificate.
if (code != V4_0_ErrorCode::OK) {
if (code != KMV1::ErrorCode::OK) {
errorCode = code;
deleteKey(out_creationResult->keyBlob);
}
@ -223,26 +229,25 @@ ScopedAStatus KeyMintDevice::importKey(const std::vector<KeyParameter>& in_inKey
KeyCreationResult* out_creationResult) {
auto legacyKeyParams = convertKeyParametersToLegacy(in_inKeyParams);
auto legacyKeyFormat = convertKeyFormatToLegacy(in_inKeyFormat);
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->importKey(legacyKeyParams, legacyKeyFormat, in_inKeyData,
[&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
const V4_0_KeyCharacteristics& keyCharacteristics) {
errorCode = error;
errorCode = convert(error);
out_creationResult->keyBlob = keyBlob;
out_creationResult->keyCharacteristics =
convertKeyCharacteristicsFromLegacy(
securityLevel_, keyCharacteristics);
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
if (errorCode == V4_0_ErrorCode::OK) {
if (errorCode == KMV1::ErrorCode::OK) {
auto cert = getCertificate(in_inKeyParams, out_creationResult->keyBlob);
if (std::holds_alternative<V4_0_ErrorCode>(cert)) {
auto code = std::get<V4_0_ErrorCode>(cert);
if (std::holds_alternative<KMV1::ErrorCode>(cert)) {
auto code = std::get<KMV1::ErrorCode>(cert);
// We return OK in successful cases that do not generate a certificate.
if (code != V4_0_ErrorCode::OK) {
if (code != KMV1::ErrorCode::OK) {
errorCode = code;
deleteKey(out_creationResult->keyBlob);
}
@ -259,20 +264,19 @@ ScopedAStatus KeyMintDevice::importWrappedKey(
const std::vector<KeyParameter>& in_inUnwrappingParams, int64_t in_inPasswordSid,
int64_t in_inBiometricSid, KeyCreationResult* out_creationResult) {
auto legacyUnwrappingParams = convertKeyParametersToLegacy(in_inUnwrappingParams);
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->importWrappedKey(
in_inWrappedKeyData, in_inWrappingKeyBlob, in_inMaskingKey, legacyUnwrappingParams,
in_inPasswordSid, in_inBiometricSid,
[&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyBlob,
const V4_0_KeyCharacteristics& keyCharacteristics) {
errorCode = error;
errorCode = convert(error);
out_creationResult->keyBlob = keyBlob;
out_creationResult->keyCharacteristics =
convertKeyCharacteristicsFromLegacy(securityLevel_, keyCharacteristics);
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(errorCode);
}
@ -289,20 +293,25 @@ ScopedAStatus KeyMintDevice::upgradeKey(const std::vector<uint8_t>& in_inKeyBlob
*_aidl_return = upgradedKeyBlob;
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(errorCode);
}
ScopedAStatus KeyMintDevice::deleteKey(const std::vector<uint8_t>& in_inKeyBlob) {
V4_0_ErrorCode errorCode = mDevice->deleteKey(in_inKeyBlob);
return convertErrorCode(errorCode);
auto result = mDevice->deleteKey(in_inKeyBlob);
if (!result.isOk()) {
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(result);
}
ScopedAStatus KeyMintDevice::deleteAllKeys() {
V4_0_ErrorCode errorCode = mDevice->deleteAllKeys();
return convertErrorCode(errorCode);
auto result = mDevice->deleteAllKeys();
if (!result.isOk()) {
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(result);
}
// We're not implementing this.
@ -323,24 +332,21 @@ ScopedAStatus KeyMintDevice::begin(KeyPurpose in_inPurpose,
static_cast<::android::hardware::keymaster::V4_0::KeyPurpose>(in_inPurpose);
auto legacyParams = convertKeyParametersToLegacy(in_inParams);
auto legacyAuthToken = convertAuthTokenToLegacy(in_inAuthToken);
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->begin(
legacyPurpose, in_inKeyBlob, legacyParams, legacyAuthToken,
[&](V4_0_ErrorCode error, const hidl_vec<V4_0_KeyParameter>& outParams,
uint64_t operationHandle) {
errorCode = error;
_aidl_return->challenge = operationHandle; // TODO: Is this right?
errorCode = convert(error);
_aidl_return->challenge = operationHandle;
_aidl_return->params = convertKeyParametersFromLegacy(outParams);
_aidl_return->operation = ndk::SharedRefBase::make<KeyMintOperation>(
mDevice, operationHandle, &mOperationSlots, error == V4_0_ErrorCode::OK);
});
if (!result.isOk()) {
// TODO: In this case we're guaranteed that _aidl_return was not initialized, right?
mOperationSlots.freeSlot();
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
if (errorCode != V4_0_ErrorCode::OK) {
if (errorCode != KMV1::ErrorCode::OK) {
mOperationSlots.freeSlot();
}
return convertErrorCode(errorCode);
@ -366,12 +372,12 @@ ScopedAStatus KeyMintOperation::update(const std::optional<KeyParameterArray>& i
if (in_inTimeStampToken.has_value()) {
verificationToken = convertTimestampTokenToLegacy(in_inTimeStampToken.value());
}
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->update(
mOperationHandle, legacyParams, input, authToken, verificationToken,
[&](V4_0_ErrorCode error, uint32_t inputConsumed,
const hidl_vec<V4_0_KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
errorCode = error;
errorCode = convert(error);
out_outParams->emplace();
out_outParams->value().params = convertKeyParametersFromLegacy(outParams);
out_output->emplace();
@ -379,11 +385,9 @@ ScopedAStatus KeyMintOperation::update(const std::optional<KeyParameterArray>& i
*_aidl_return = inputConsumed;
});
if (!result.isOk()) {
mOperationSlot.freeSlot();
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
if (errorCode != V4_0_ErrorCode::OK) {
if (errorCode != KMV1::ErrorCode::OK) {
mOperationSlot.freeSlot();
}
return convertErrorCode(errorCode);
@ -396,7 +400,7 @@ ScopedAStatus KeyMintOperation::finish(const std::optional<KeyParameterArray>& i
const std::optional<TimeStampToken>& in_inTimeStampToken,
std::optional<KeyParameterArray>* out_outParams,
std::vector<uint8_t>* _aidl_return) {
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
std::vector<V4_0_KeyParameter> legacyParams;
if (in_inParams.has_value()) {
legacyParams = convertKeyParametersToLegacy(in_inParams.value().params);
@ -415,23 +419,25 @@ ScopedAStatus KeyMintOperation::finish(const std::optional<KeyParameterArray>& i
mOperationHandle, legacyParams, input, signature, authToken, verificationToken,
[&](V4_0_ErrorCode error, const hidl_vec<V4_0_KeyParameter>& outParams,
const hidl_vec<uint8_t>& output) {
errorCode = error;
errorCode = convert(error);
out_outParams->emplace();
out_outParams->value().params = convertKeyParametersFromLegacy(outParams);
*_aidl_return = output;
});
mOperationSlot.freeSlot();
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
return convertErrorCode(errorCode);
}
ScopedAStatus KeyMintOperation::abort() {
V4_0_ErrorCode errorCode = mDevice->abort(mOperationHandle);
auto result = mDevice->abort(mOperationHandle);
mOperationSlot.freeSlot();
return convertErrorCode(errorCode);
if (!result.isOk()) {
return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
}
return convertErrorCode(result);
}
KeyMintOperation::~KeyMintOperation() {
@ -446,18 +452,17 @@ KeyMintOperation::~KeyMintOperation() {
// SecureClock implementation
ScopedAStatus SecureClock::generateTimeStamp(int64_t in_challenge, TimeStampToken* _aidl_return) {
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->verifyAuthorization(
in_challenge, {}, V4_0_HardwareAuthToken(),
[&](V4_0_ErrorCode error, const V4_0_VerificationToken& token) {
errorCode = error;
errorCode = convert(error);
_aidl_return->challenge = token.challenge;
_aidl_return->timestamp.milliSeconds = token.timestamp;
_aidl_return->mac = token.mac;
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
return convertErrorCode(errorCode);
}
@ -465,17 +470,16 @@ ScopedAStatus SecureClock::generateTimeStamp(int64_t in_challenge, TimeStampToke
// SharedSecret implementation
ScopedAStatus SharedSecret::getSharedSecretParameters(SharedSecretParameters* _aidl_return) {
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto result = mDevice->getHmacSharingParameters(
[&](V4_0_ErrorCode error, const V4_0_HmacSharingParameters& params) {
errorCode = error;
errorCode = convert(error);
_aidl_return->seed = params.seed;
std::copy(params.nonce.data(), params.nonce.data() + params.nonce.elementCount(),
std::back_inserter(_aidl_return->nonce));
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
return convertErrorCode(errorCode);
}
@ -483,16 +487,15 @@ ScopedAStatus SharedSecret::getSharedSecretParameters(SharedSecretParameters* _a
ScopedAStatus
SharedSecret::computeSharedSecret(const std::vector<SharedSecretParameters>& in_params,
std::vector<uint8_t>* _aidl_return) {
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
auto legacyParams = convertSharedSecretParametersToLegacy(in_params);
auto result = mDevice->computeSharedHmac(
legacyParams, [&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& sharingCheck) {
errorCode = error;
errorCode = convert(error);
*_aidl_return = sharingCheck;
});
if (!result.isOk()) {
return ScopedAStatus::fromServiceSpecificError(
static_cast<int32_t>(ResponseCode::SYSTEM_ERROR));
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
return convertErrorCode(errorCode);
}
@ -536,12 +539,12 @@ getMaximum(const std::vector<KeyParameter>& keyParams, T tag,
return *bestSoFar;
}
static std::variant<keystore::X509_Ptr, V4_0_ErrorCode>
static std::variant<keystore::X509_Ptr, KMV1::ErrorCode>
makeCert(::android::sp<Keymaster> mDevice, const std::vector<KeyParameter>& keyParams,
const std::vector<uint8_t>& keyBlob) {
// Start generating the certificate.
// Get public key for makeCert.
V4_0_ErrorCode errorCode;
KMV1::ErrorCode errorCode;
std::vector<uint8_t> key;
static std::vector<uint8_t> empty_vector;
auto unwrapBlob = [&](auto b) -> const std::vector<uint8_t>& {
@ -554,13 +557,13 @@ makeCert(::android::sp<Keymaster> mDevice, const std::vector<KeyParameter>& keyP
V4_0_KeyFormat::X509, keyBlob, unwrapBlob(getParam(keyParams, KMV1::TAG_APPLICATION_ID)),
unwrapBlob(getParam(keyParams, KMV1::TAG_APPLICATION_DATA)),
[&](V4_0_ErrorCode error, const hidl_vec<uint8_t>& keyMaterial) {
errorCode = error;
errorCode = convert(error);
key = keyMaterial;
});
if (!result.isOk()) {
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
if (errorCode != V4_0_ErrorCode::OK) {
if (errorCode != KMV1::ErrorCode::OK) {
return errorCode;
}
// Get pkey for makeCert.
@ -585,12 +588,12 @@ makeCert(::android::sp<Keymaster> mDevice, const std::vector<KeyParameter>& keyP
std::nullopt /* intentionally left blank */, std::nullopt /* intentionally left blank */);
if (std::holds_alternative<keystore::CertUtilsError>(certOrError)) {
LOG(ERROR) << __func__ << ": Failed to make certificate";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
return std::move(std::get<keystore::X509_Ptr>(certOrError));
}
static std::variant<keystore::Algo, V4_0_ErrorCode> getKeystoreAlgorithm(Algorithm algorithm) {
static std::variant<keystore::Algo, KMV1::ErrorCode> getKeystoreAlgorithm(Algorithm algorithm) {
switch (algorithm) {
case Algorithm::RSA:
return keystore::Algo::RSA;
@ -598,11 +601,11 @@ static std::variant<keystore::Algo, V4_0_ErrorCode> getKeystoreAlgorithm(Algorit
return keystore::Algo::ECDSA;
default:
LOG(ERROR) << __func__ << ": This should not be called with symmetric algorithm.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
}
static std::variant<keystore::Padding, V4_0_ErrorCode> getKeystorePadding(PaddingMode padding) {
static std::variant<keystore::Padding, KMV1::ErrorCode> getKeystorePadding(PaddingMode padding) {
switch (padding) {
case PaddingMode::RSA_PKCS1_1_5_SIGN:
return keystore::Padding::PKCS1_5;
@ -613,7 +616,7 @@ static std::variant<keystore::Padding, V4_0_ErrorCode> getKeystorePadding(Paddin
}
}
static std::variant<keystore::Digest, V4_0_ErrorCode> getKeystoreDigest(Digest digest) {
static std::variant<keystore::Digest, KMV1::ErrorCode> getKeystoreDigest(Digest digest) {
switch (digest) {
case Digest::SHA1:
return keystore::Digest::SHA1;
@ -628,36 +631,36 @@ static std::variant<keystore::Digest, V4_0_ErrorCode> getKeystoreDigest(Digest d
return keystore::Digest::SHA512;
default:
LOG(ERROR) << __func__ << ": Unknown digest.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
}
std::optional<V4_0_ErrorCode>
std::optional<KMV1::ErrorCode>
KeyMintDevice::signCertificate(const std::vector<KeyParameter>& keyParams,
const std::vector<uint8_t>& keyBlob, X509* cert) {
auto algorithm = getParam(keyParams, KMV1::TAG_ALGORITHM);
auto algoOrError = getKeystoreAlgorithm(*algorithm);
if (std::holds_alternative<V4_0_ErrorCode>(algoOrError)) {
return std::get<V4_0_ErrorCode>(algoOrError);
if (std::holds_alternative<KMV1::ErrorCode>(algoOrError)) {
return std::get<KMV1::ErrorCode>(algoOrError);
}
auto algo = std::get<keystore::Algo>(algoOrError);
auto origPadding = getMaximum(keyParams, KMV1::TAG_PADDING,
{PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN});
auto paddingOrError = getKeystorePadding(origPadding);
if (std::holds_alternative<V4_0_ErrorCode>(paddingOrError)) {
return std::get<V4_0_ErrorCode>(paddingOrError);
if (std::holds_alternative<KMV1::ErrorCode>(paddingOrError)) {
return std::get<KMV1::ErrorCode>(paddingOrError);
}
auto padding = std::get<keystore::Padding>(paddingOrError);
auto origDigest = getMaximum(
keyParams, KMV1::TAG_DIGEST,
{Digest::SHA_2_256, Digest::SHA_2_512, Digest::SHA_2_384, Digest::SHA_2_224, Digest::SHA1});
auto digestOrError = getKeystoreDigest(origDigest);
if (std::holds_alternative<V4_0_ErrorCode>(digestOrError)) {
return std::get<V4_0_ErrorCode>(digestOrError);
if (std::holds_alternative<KMV1::ErrorCode>(digestOrError)) {
return std::get<KMV1::ErrorCode>(digestOrError);
}
auto digest = std::get<keystore::Digest>(digestOrError);
V4_0_ErrorCode errorCode = V4_0_ErrorCode::OK;
KMV1::ErrorCode errorCode = KMV1::ErrorCode::OK;
auto error = keystore::signCertWith(
&*cert,
[&](const uint8_t* data, size_t len) {
@ -694,40 +697,40 @@ KeyMintDevice::signCertificate(const std::vector<KeyParameter>& keyParams,
if (error) {
LOG(ERROR) << __func__
<< ": signCertWith failed. (Callback diagnosed: " << toString(errorCode) << ")";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
if (errorCode != V4_0_ErrorCode::OK) {
if (errorCode != KMV1::ErrorCode::OK) {
return errorCode;
}
return std::nullopt;
}
std::variant<std::vector<Certificate>, V4_0_ErrorCode>
std::variant<std::vector<Certificate>, KMV1::ErrorCode>
KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
const std::vector<uint8_t>& keyBlob) {
// There are no certificates for symmetric keys.
auto algorithm = getParam(keyParams, KMV1::TAG_ALGORITHM);
if (!algorithm) {
LOG(ERROR) << __func__ << ": Unable to determine key algorithm.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
switch (*algorithm) {
case Algorithm::RSA:
case Algorithm::EC:
break;
default:
return V4_0_ErrorCode::OK;
return KMV1::ErrorCode::OK;
}
// If attestation was requested, call and use attestKey.
if (containsParam(keyParams, KMV1::TAG_ATTESTATION_CHALLENGE)) {
auto legacyParams = convertKeyParametersToLegacy(keyParams);
std::vector<Certificate> certs;
V4_0_ErrorCode errorCode = V4_0_ErrorCode::OK;
KMV1::ErrorCode errorCode = KMV1::ErrorCode::OK;
auto result = mDevice->attestKey(
keyBlob, legacyParams,
[&](V4_0_ErrorCode error, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
errorCode = error;
[&](V4_0::ErrorCode error, const hidl_vec<hidl_vec<uint8_t>>& certChain) {
errorCode = convert(error);
for (const auto& cert : certChain) {
Certificate certificate;
certificate.encodedCertificate = cert;
@ -736,9 +739,9 @@ KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
});
if (!result.isOk()) {
LOG(ERROR) << __func__ << ": Call to attestKey failed.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
if (errorCode != V4_0_ErrorCode::OK) {
if (errorCode != KMV1::ErrorCode::OK) {
return errorCode;
}
return certs;
@ -746,8 +749,8 @@ KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
// makeCert
auto certOrError = makeCert(mDevice, keyParams, keyBlob);
if (std::holds_alternative<V4_0_ErrorCode>(certOrError)) {
return std::get<V4_0_ErrorCode>(certOrError);
if (std::holds_alternative<KMV1::ErrorCode>(certOrError)) {
return std::get<KMV1::ErrorCode>(certOrError);
}
auto cert = std::move(std::get<keystore::X509_Ptr>(certOrError));
@ -755,7 +758,7 @@ KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
auto error = keystore::setIssuer(&*cert, &*cert, false);
if (error) {
LOG(ERROR) << __func__ << ": Set issuer failed.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
// Signing
@ -780,7 +783,7 @@ KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
error = keystore::signCert(&*cert, pkey_ptr);
if (error) {
LOG(ERROR) << __func__ << ": signCert failed.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
}
@ -788,7 +791,7 @@ KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
auto encodedCertOrError = keystore::encodeCert(&*cert);
if (std::holds_alternative<keystore::CertUtilsError>(encodedCertOrError)) {
LOG(ERROR) << __func__ << ": encodeCert failed.";
return V4_0_ErrorCode::UNKNOWN_ERROR;
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
Certificate certificate{.encodedCertificate =

View file

@ -18,6 +18,7 @@
#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <aidl/android/hardware/security/secureclock/BnSecureClock.h>
#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
#include <aidl/android/security/compat/BnKeystoreCompatService.h>
@ -41,6 +42,7 @@ using ::aidl::android::hardware::security::keymint::KeyPurpose;
using KeyMintSecurityLevel = ::aidl::android::hardware::security::keymint::SecurityLevel;
using V4_0_ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode;
using ::aidl::android::hardware::security::keymint::IKeyMintDevice;
using KMV1_ErrorCode = ::aidl::android::hardware::security::keymint::ErrorCode;
using ::aidl::android::hardware::security::secureclock::ISecureClock;
using ::aidl::android::hardware::security::secureclock::TimeStampToken;
using ::aidl::android::hardware::security::sharedsecret::ISharedSecret;
@ -112,13 +114,13 @@ class KeyMintDevice : public aidl::android::hardware::security::keymint::BnKeyMi
// These are public to allow testing code to use them directly.
// This class should not be used publicly anyway.
std::variant<std::vector<Certificate>, V4_0_ErrorCode>
std::variant<std::vector<Certificate>, KMV1_ErrorCode>
getCertificate(const std::vector<KeyParameter>& keyParams, const std::vector<uint8_t>& keyBlob);
void setNumFreeSlots(uint8_t numFreeSlots);
private:
std::optional<V4_0_ErrorCode> signCertificate(const std::vector<KeyParameter>& keyParams,
std::optional<KMV1_ErrorCode> signCertificate(const std::vector<KeyParameter>& keyParams,
const std::vector<uint8_t>& keyBlob, X509* cert);
KeyMintSecurityLevel securityLevel_;
};

View file

@ -16,6 +16,7 @@
#pragma once
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <keymasterV4_1/keymaster_tags.h>
#include <keymint_support/keymint_tags.h>
@ -23,6 +24,159 @@ namespace V4_0 = ::android::hardware::keymaster::V4_0;
namespace V4_1 = ::android::hardware::keymaster::V4_1;
namespace KMV1 = ::aidl::android::hardware::security::keymint;
static KMV1::ErrorCode convert(V4_0::ErrorCode error) {
switch (error) {
case V4_0::ErrorCode::OK:
return KMV1::ErrorCode::OK;
case V4_0::ErrorCode::ROOT_OF_TRUST_ALREADY_SET:
return KMV1::ErrorCode::ROOT_OF_TRUST_ALREADY_SET;
case V4_0::ErrorCode::UNSUPPORTED_PURPOSE:
return KMV1::ErrorCode::UNSUPPORTED_PURPOSE;
case V4_0::ErrorCode::INCOMPATIBLE_PURPOSE:
return KMV1::ErrorCode::INCOMPATIBLE_PURPOSE;
case V4_0::ErrorCode::UNSUPPORTED_ALGORITHM:
return KMV1::ErrorCode::UNSUPPORTED_ALGORITHM;
case V4_0::ErrorCode::INCOMPATIBLE_ALGORITHM:
return KMV1::ErrorCode::INCOMPATIBLE_ALGORITHM;
case V4_0::ErrorCode::UNSUPPORTED_KEY_SIZE:
return KMV1::ErrorCode::UNSUPPORTED_KEY_SIZE;
case V4_0::ErrorCode::UNSUPPORTED_BLOCK_MODE:
return KMV1::ErrorCode::UNSUPPORTED_BLOCK_MODE;
case V4_0::ErrorCode::INCOMPATIBLE_BLOCK_MODE:
return KMV1::ErrorCode::INCOMPATIBLE_BLOCK_MODE;
case V4_0::ErrorCode::UNSUPPORTED_MAC_LENGTH:
return KMV1::ErrorCode::UNSUPPORTED_MAC_LENGTH;
case V4_0::ErrorCode::UNSUPPORTED_PADDING_MODE:
return KMV1::ErrorCode::UNSUPPORTED_PADDING_MODE;
case V4_0::ErrorCode::INCOMPATIBLE_PADDING_MODE:
return KMV1::ErrorCode::INCOMPATIBLE_PADDING_MODE;
case V4_0::ErrorCode::UNSUPPORTED_DIGEST:
return KMV1::ErrorCode::UNSUPPORTED_DIGEST;
case V4_0::ErrorCode::INCOMPATIBLE_DIGEST:
return KMV1::ErrorCode::INCOMPATIBLE_DIGEST;
case V4_0::ErrorCode::INVALID_EXPIRATION_TIME:
return KMV1::ErrorCode::INVALID_EXPIRATION_TIME;
case V4_0::ErrorCode::INVALID_USER_ID:
return KMV1::ErrorCode::INVALID_USER_ID;
case V4_0::ErrorCode::INVALID_AUTHORIZATION_TIMEOUT:
return KMV1::ErrorCode::INVALID_AUTHORIZATION_TIMEOUT;
case V4_0::ErrorCode::UNSUPPORTED_KEY_FORMAT:
return KMV1::ErrorCode::UNSUPPORTED_KEY_FORMAT;
case V4_0::ErrorCode::INCOMPATIBLE_KEY_FORMAT:
return KMV1::ErrorCode::INCOMPATIBLE_KEY_FORMAT;
case V4_0::ErrorCode::UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM:
return KMV1::ErrorCode::UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM;
case V4_0::ErrorCode::UNSUPPORTED_KEY_VERIFICATION_ALGORITHM:
return KMV1::ErrorCode::UNSUPPORTED_KEY_VERIFICATION_ALGORITHM;
case V4_0::ErrorCode::INVALID_INPUT_LENGTH:
return KMV1::ErrorCode::INVALID_INPUT_LENGTH;
case V4_0::ErrorCode::KEY_EXPORT_OPTIONS_INVALID:
return KMV1::ErrorCode::KEY_EXPORT_OPTIONS_INVALID;
case V4_0::ErrorCode::DELEGATION_NOT_ALLOWED:
return KMV1::ErrorCode::DELEGATION_NOT_ALLOWED;
case V4_0::ErrorCode::KEY_NOT_YET_VALID:
return KMV1::ErrorCode::KEY_NOT_YET_VALID;
case V4_0::ErrorCode::KEY_EXPIRED:
return KMV1::ErrorCode::KEY_EXPIRED;
case V4_0::ErrorCode::KEY_USER_NOT_AUTHENTICATED:
return KMV1::ErrorCode::KEY_USER_NOT_AUTHENTICATED;
case V4_0::ErrorCode::OUTPUT_PARAMETER_NULL:
return KMV1::ErrorCode::OUTPUT_PARAMETER_NULL;
case V4_0::ErrorCode::INVALID_OPERATION_HANDLE:
return KMV1::ErrorCode::INVALID_OPERATION_HANDLE;
case V4_0::ErrorCode::INSUFFICIENT_BUFFER_SPACE:
return KMV1::ErrorCode::INSUFFICIENT_BUFFER_SPACE;
case V4_0::ErrorCode::VERIFICATION_FAILED:
return KMV1::ErrorCode::VERIFICATION_FAILED;
case V4_0::ErrorCode::TOO_MANY_OPERATIONS:
return KMV1::ErrorCode::TOO_MANY_OPERATIONS;
case V4_0::ErrorCode::UNEXPECTED_NULL_POINTER:
return KMV1::ErrorCode::UNEXPECTED_NULL_POINTER;
case V4_0::ErrorCode::INVALID_KEY_BLOB:
return KMV1::ErrorCode::INVALID_KEY_BLOB;
case V4_0::ErrorCode::IMPORTED_KEY_NOT_ENCRYPTED:
return KMV1::ErrorCode::IMPORTED_KEY_NOT_ENCRYPTED;
case V4_0::ErrorCode::IMPORTED_KEY_DECRYPTION_FAILED:
return KMV1::ErrorCode::IMPORTED_KEY_DECRYPTION_FAILED;
case V4_0::ErrorCode::IMPORTED_KEY_NOT_SIGNED:
return KMV1::ErrorCode::IMPORTED_KEY_NOT_SIGNED;
case V4_0::ErrorCode::IMPORTED_KEY_VERIFICATION_FAILED:
return KMV1::ErrorCode::IMPORTED_KEY_VERIFICATION_FAILED;
case V4_0::ErrorCode::INVALID_ARGUMENT:
return KMV1::ErrorCode::INVALID_ARGUMENT;
case V4_0::ErrorCode::UNSUPPORTED_TAG:
return KMV1::ErrorCode::UNSUPPORTED_TAG;
case V4_0::ErrorCode::INVALID_TAG:
return KMV1::ErrorCode::INVALID_TAG;
case V4_0::ErrorCode::MEMORY_ALLOCATION_FAILED:
return KMV1::ErrorCode::MEMORY_ALLOCATION_FAILED;
case V4_0::ErrorCode::IMPORT_PARAMETER_MISMATCH:
return KMV1::ErrorCode::IMPORT_PARAMETER_MISMATCH;
case V4_0::ErrorCode::SECURE_HW_ACCESS_DENIED:
return KMV1::ErrorCode::SECURE_HW_ACCESS_DENIED;
case V4_0::ErrorCode::OPERATION_CANCELLED:
return KMV1::ErrorCode::OPERATION_CANCELLED;
case V4_0::ErrorCode::CONCURRENT_ACCESS_CONFLICT:
return KMV1::ErrorCode::CONCURRENT_ACCESS_CONFLICT;
case V4_0::ErrorCode::SECURE_HW_BUSY:
return KMV1::ErrorCode::SECURE_HW_BUSY;
case V4_0::ErrorCode::SECURE_HW_COMMUNICATION_FAILED:
return KMV1::ErrorCode::SECURE_HW_COMMUNICATION_FAILED;
case V4_0::ErrorCode::UNSUPPORTED_EC_FIELD:
return KMV1::ErrorCode::UNSUPPORTED_EC_FIELD;
case V4_0::ErrorCode::MISSING_NONCE:
return KMV1::ErrorCode::MISSING_NONCE;
case V4_0::ErrorCode::INVALID_NONCE:
return KMV1::ErrorCode::INVALID_NONCE;
case V4_0::ErrorCode::MISSING_MAC_LENGTH:
return KMV1::ErrorCode::MISSING_MAC_LENGTH;
case V4_0::ErrorCode::KEY_RATE_LIMIT_EXCEEDED:
return KMV1::ErrorCode::KEY_RATE_LIMIT_EXCEEDED;
case V4_0::ErrorCode::CALLER_NONCE_PROHIBITED:
return KMV1::ErrorCode::CALLER_NONCE_PROHIBITED;
case V4_0::ErrorCode::KEY_MAX_OPS_EXCEEDED:
return KMV1::ErrorCode::KEY_MAX_OPS_EXCEEDED;
case V4_0::ErrorCode::INVALID_MAC_LENGTH:
return KMV1::ErrorCode::INVALID_MAC_LENGTH;
case V4_0::ErrorCode::MISSING_MIN_MAC_LENGTH:
return KMV1::ErrorCode::MISSING_MIN_MAC_LENGTH;
case V4_0::ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH:
return KMV1::ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH;
case V4_0::ErrorCode::UNSUPPORTED_KDF:
return KMV1::ErrorCode::UNSUPPORTED_KDF;
case V4_0::ErrorCode::UNSUPPORTED_EC_CURVE:
return KMV1::ErrorCode::UNSUPPORTED_EC_CURVE;
case V4_0::ErrorCode::KEY_REQUIRES_UPGRADE:
return KMV1::ErrorCode::KEY_REQUIRES_UPGRADE;
case V4_0::ErrorCode::ATTESTATION_CHALLENGE_MISSING:
return KMV1::ErrorCode::ATTESTATION_CHALLENGE_MISSING;
case V4_0::ErrorCode::KEYMASTER_NOT_CONFIGURED:
return KMV1::ErrorCode::KEYMINT_NOT_CONFIGURED;
case V4_0::ErrorCode::ATTESTATION_APPLICATION_ID_MISSING:
return KMV1::ErrorCode::ATTESTATION_APPLICATION_ID_MISSING;
case V4_0::ErrorCode::CANNOT_ATTEST_IDS:
return KMV1::ErrorCode::CANNOT_ATTEST_IDS;
case V4_0::ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE:
return KMV1::ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE;
case V4_0::ErrorCode::HARDWARE_TYPE_UNAVAILABLE:
return KMV1::ErrorCode::HARDWARE_TYPE_UNAVAILABLE;
case V4_0::ErrorCode::PROOF_OF_PRESENCE_REQUIRED:
return KMV1::ErrorCode::PROOF_OF_PRESENCE_REQUIRED;
case V4_0::ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED:
return KMV1::ErrorCode::CONCURRENT_PROOF_OF_PRESENCE_REQUESTED;
case V4_0::ErrorCode::NO_USER_CONFIRMATION:
return KMV1::ErrorCode::NO_USER_CONFIRMATION;
case V4_0::ErrorCode::DEVICE_LOCKED:
return KMV1::ErrorCode::DEVICE_LOCKED;
case V4_0::ErrorCode::UNIMPLEMENTED:
return KMV1::ErrorCode::UNIMPLEMENTED;
case V4_0::ErrorCode::VERSION_MISMATCH:
return KMV1::ErrorCode::VERSION_MISMATCH;
case V4_0::ErrorCode::UNKNOWN_ERROR:
return KMV1::ErrorCode::UNKNOWN_ERROR;
}
}
static std::optional<V4_0::KeyPurpose> convert(KMV1::KeyPurpose p) {
switch (p) {
case KMV1::KeyPurpose::ENCRYPT:

View file

@ -150,3 +150,84 @@ TEST(KmCompatTypeConversionTest, testKeyParameterConversion) {
TEST_KEY_PARAMETER_CONVERSION_V4_0(TAG_USER_SECURE_ID);
TEST_KEY_PARAMETER_CONVERSION_V4_0(TAG_VENDOR_PATCHLEVEL);
}
#define TEST_ERROR_CODE_CONVERSION(variant) \
ASSERT_EQ(KMV1::ErrorCode::variant, convert(V4_0::ErrorCode::variant))
TEST(KmCompatTypeConversionTest, testErrorCodeConversion) {
TEST_ERROR_CODE_CONVERSION(OK);
TEST_ERROR_CODE_CONVERSION(ROOT_OF_TRUST_ALREADY_SET);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_PURPOSE);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_PURPOSE);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_ALGORITHM);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_ALGORITHM);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_KEY_SIZE);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_BLOCK_MODE);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_BLOCK_MODE);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_MAC_LENGTH);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_PADDING_MODE);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_PADDING_MODE);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_DIGEST);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_DIGEST);
TEST_ERROR_CODE_CONVERSION(INVALID_EXPIRATION_TIME);
TEST_ERROR_CODE_CONVERSION(INVALID_USER_ID);
TEST_ERROR_CODE_CONVERSION(INVALID_AUTHORIZATION_TIMEOUT);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_KEY_FORMAT);
TEST_ERROR_CODE_CONVERSION(INCOMPATIBLE_KEY_FORMAT);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_KEY_VERIFICATION_ALGORITHM);
TEST_ERROR_CODE_CONVERSION(INVALID_INPUT_LENGTH);
TEST_ERROR_CODE_CONVERSION(KEY_EXPORT_OPTIONS_INVALID);
TEST_ERROR_CODE_CONVERSION(DELEGATION_NOT_ALLOWED);
TEST_ERROR_CODE_CONVERSION(KEY_NOT_YET_VALID);
TEST_ERROR_CODE_CONVERSION(KEY_EXPIRED);
TEST_ERROR_CODE_CONVERSION(KEY_USER_NOT_AUTHENTICATED);
TEST_ERROR_CODE_CONVERSION(OUTPUT_PARAMETER_NULL);
TEST_ERROR_CODE_CONVERSION(INVALID_OPERATION_HANDLE);
TEST_ERROR_CODE_CONVERSION(INSUFFICIENT_BUFFER_SPACE);
TEST_ERROR_CODE_CONVERSION(VERIFICATION_FAILED);
TEST_ERROR_CODE_CONVERSION(TOO_MANY_OPERATIONS);
TEST_ERROR_CODE_CONVERSION(UNEXPECTED_NULL_POINTER);
TEST_ERROR_CODE_CONVERSION(INVALID_KEY_BLOB);
TEST_ERROR_CODE_CONVERSION(IMPORTED_KEY_NOT_ENCRYPTED);
TEST_ERROR_CODE_CONVERSION(IMPORTED_KEY_DECRYPTION_FAILED);
TEST_ERROR_CODE_CONVERSION(IMPORTED_KEY_NOT_SIGNED);
TEST_ERROR_CODE_CONVERSION(IMPORTED_KEY_VERIFICATION_FAILED);
TEST_ERROR_CODE_CONVERSION(INVALID_ARGUMENT);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_TAG);
TEST_ERROR_CODE_CONVERSION(INVALID_TAG);
TEST_ERROR_CODE_CONVERSION(MEMORY_ALLOCATION_FAILED);
TEST_ERROR_CODE_CONVERSION(IMPORT_PARAMETER_MISMATCH);
TEST_ERROR_CODE_CONVERSION(SECURE_HW_ACCESS_DENIED);
TEST_ERROR_CODE_CONVERSION(OPERATION_CANCELLED);
TEST_ERROR_CODE_CONVERSION(CONCURRENT_ACCESS_CONFLICT);
TEST_ERROR_CODE_CONVERSION(SECURE_HW_BUSY);
TEST_ERROR_CODE_CONVERSION(SECURE_HW_COMMUNICATION_FAILED);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_EC_FIELD);
TEST_ERROR_CODE_CONVERSION(MISSING_NONCE);
TEST_ERROR_CODE_CONVERSION(INVALID_NONCE);
TEST_ERROR_CODE_CONVERSION(MISSING_MAC_LENGTH);
TEST_ERROR_CODE_CONVERSION(KEY_RATE_LIMIT_EXCEEDED);
TEST_ERROR_CODE_CONVERSION(CALLER_NONCE_PROHIBITED);
TEST_ERROR_CODE_CONVERSION(KEY_MAX_OPS_EXCEEDED);
TEST_ERROR_CODE_CONVERSION(INVALID_MAC_LENGTH);
TEST_ERROR_CODE_CONVERSION(MISSING_MIN_MAC_LENGTH);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_MIN_MAC_LENGTH);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_KDF);
TEST_ERROR_CODE_CONVERSION(UNSUPPORTED_EC_CURVE);
TEST_ERROR_CODE_CONVERSION(KEY_REQUIRES_UPGRADE);
TEST_ERROR_CODE_CONVERSION(ATTESTATION_CHALLENGE_MISSING);
ASSERT_EQ(KMV1::ErrorCode::KEYMINT_NOT_CONFIGURED,
convert(V4_0::ErrorCode::KEYMASTER_NOT_CONFIGURED));
TEST_ERROR_CODE_CONVERSION(ATTESTATION_APPLICATION_ID_MISSING);
TEST_ERROR_CODE_CONVERSION(CANNOT_ATTEST_IDS);
TEST_ERROR_CODE_CONVERSION(ROLLBACK_RESISTANCE_UNAVAILABLE);
TEST_ERROR_CODE_CONVERSION(HARDWARE_TYPE_UNAVAILABLE);
TEST_ERROR_CODE_CONVERSION(PROOF_OF_PRESENCE_REQUIRED);
TEST_ERROR_CODE_CONVERSION(CONCURRENT_PROOF_OF_PRESENCE_REQUESTED);
TEST_ERROR_CODE_CONVERSION(NO_USER_CONFIRMATION);
TEST_ERROR_CODE_CONVERSION(DEVICE_LOCKED);
TEST_ERROR_CODE_CONVERSION(UNIMPLEMENTED);
TEST_ERROR_CODE_CONVERSION(VERSION_MISMATCH);
TEST_ERROR_CODE_CONVERSION(UNKNOWN_ERROR);
}