#include <generic-backend/algo-validation.h>
#include <generic-backend/crypto-params.h>
#include <dpl/log/log.h>
+#include <openssl/evp.h>
+#include <openssl/dsa.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
#include <tz-backend/internals.h>
#include <tz-backend/tz-context.h>
+#include <openssl-error-handler.h>
#include <km_ta_defines.h>
+#include <functional>
+
+namespace {
+
+using DSAPtr = std::unique_ptr<DSA, std::function<void(DSA*)>>;
+
+CKM::RawBuffer extractBignumData(BIGNUM* bn)
+{
+ size_t size = static_cast<size_t>(BN_num_bytes(bn));
+
+ CKM::RawBuffer result(size);
+ int ret = BN_bn2bin(bn, result.data());
+ if (ret != static_cast<int>(size)) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Error while converting bignums - expected "
+ + std::to_string(size) + " bytes of data, got " + std::to_string(ret));
+ }
+
+ return result;
+}
+
+void generateDSAParams(const int sizeBits, CKM::RawBuffer &prime,
+ CKM::RawBuffer &subprime, CKM::RawBuffer &base)
+{
+ DSAPtr dsa(DSA_new(), DSA_free);
+ if (!dsa) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Failed to create DSA context for parameter gen");
+ }
+
+ if (DSA_generate_parameters_ex(dsa.get(), sizeBits, NULL, 0, NULL, NULL, NULL) == 0) {
+ ThrowErr(CKM::Exc::Crypto::InternalError,
+ "Failed to generate DSA params, err = " + std::to_string(ERR_get_error()));
+ }
+
+ // at this stage dsa->p, dsa->q & dsa->r should contain our params
+ // extract them into buffers
+ prime = extractBignumData(dsa->p);
+ subprime = extractBignumData(dsa->q);
+ base = extractBignumData(dsa->g);
+}
+
+} // namespace
namespace CKM {
namespace Crypto {
namespace TZ {
namespace Internals {
-tz_algo_type getGenKeyType(AlgoType type)
+tz_algo_type getGenSKeyType(AlgoType type)
{
switch (type)
{
case AlgoType::AES_CTR: return ALGO_AES_CTR;
case AlgoType::AES_CFB: return ALGO_AES_CFB;
case AlgoType::AES_GCM: return ALGO_AES_GCM;
+ case AlgoType::RSA_OAEP: return ALGO_RSA;
+ case AlgoType::RSA_SV: return ALGO_RSA_SV;
+ case AlgoType::DSA_SV: return ALGO_DSA_SV;
+ case AlgoType::ECDSA_SV: return ALGO_ECDSA_SV;
default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
};
}
case KeyType::KEY_RSA_PUBLIC:
case KeyType::KEY_RSA_PRIVATE:
return ALGO_RSA_GEN;
+ case KeyType::KEY_DSA_PUBLIC:
+ case KeyType::KEY_DSA_PRIVATE:
+ return ALGO_DSA_GEN;
+ case KeyType::KEY_ECDSA_PUBLIC:
+ case KeyType::KEY_ECDSA_PRIVATE:
+ return ALGO_ECDSA_GEN;
default:
ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
};
}
+tz_hash_type getHashType(HashAlgorithm hash)
+{
+ switch (hash)
+ {
+ case HashAlgorithm::SHA1: return HASH_SHA1;
+ case HashAlgorithm::SHA256: return HASH_SHA256;
+ case HashAlgorithm::SHA384: return HASH_SHA384;
+ case HashAlgorithm::SHA512: return HASH_SHA512;
+ default:
+ ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+ }
+}
+
RawBuffer generateIV()
{
RawBuffer result;
}
RawBuffer pwdBuf(pwd.begin(), pwd.end());
- TrustZoneContext::Instance().generateSKeyPwd(getGenKeyType(keyType),
+ TrustZoneContext::Instance().generateSKeyPwd(getGenSKeyType(keyType),
pwdBuf, iv, keyBits,
keyData.data, tag);
} else {
- TrustZoneContext::Instance().generateSKey(getGenKeyType(keyType), keyBits,
+ TrustZoneContext::Instance().generateSKey(getGenSKeyType(keyType), keyBits,
keyData.data);
}
return keyData;
}
-DataPair generateAKey(const CryptoAlgorithm &,
- const Password &,
- const RawBuffer &)
+DataPair generateAKey(const CryptoAlgorithm &alg,
+ const Password &pubPwd,
+ const Password &privPwd,
+ const RawBuffer &pubPwdIv,
+ const RawBuffer &privPwdIv,
+ RawBuffer &pubTag,
+ RawBuffer &privTag)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "AKeys are not yet implemented in TrustZone backend");
+ AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
+
+ Data pubKeyData;
+ Data privKeyData;
+
+ RawBuffer pubPwdBuf;
+ if (!pubPwd.empty())
+ pubPwdBuf.assign(pubPwd.begin(), pubPwd.end());
+
+ RawBuffer privPwdBuf;
+ if (!privPwd.empty())
+ privPwdBuf.assign(privPwd.begin(), privPwd.end());
+
+ switch (keyType) {
+ case AlgoType::RSA_GEN: {
+ pubKeyData.type = DataType(KeyType::KEY_RSA_PUBLIC);
+ privKeyData.type = DataType(KeyType::KEY_RSA_PRIVATE);
+
+ TrustZoneContext::Instance().generateRSAKey(keyBits,
+ pubPwdBuf,
+ pubPwdIv,
+ privPwdBuf,
+ privPwdIv,
+ pubKeyData.data,
+ pubTag,
+ privKeyData.data,
+ privTag);
+ break;
+ }
+ case AlgoType::DSA_GEN: {
+ pubKeyData.type = DataType(KeyType::KEY_DSA_PUBLIC);
+ privKeyData.type = DataType(KeyType::KEY_DSA_PRIVATE);
+
+ RawBuffer prime;
+ RawBuffer subprime;
+ RawBuffer base;
+ generateDSAParams(keyBits, prime, subprime, base);
+ TrustZoneContext::Instance().generateDSAKey(keyBits,
+ prime,
+ subprime,
+ base,
+ pubPwdBuf,
+ pubPwdIv,
+ privPwdBuf,
+ privPwdIv,
+ pubKeyData.data,
+ pubTag,
+ privKeyData.data,
+ privTag);
+ break;
+ }
+ default: {
+ ThrowErr(Exc::Crypto::InputParam,
+ "Invalid algo type provided for generateAKey function");
+ }
+ }
+
+ return DataPair(pubKeyData, privKeyData);
}
void destroyKey(const RawBuffer &key)
dataType = TYPE_SKEY;
} else if (data.type.isBinaryData()) {
dataType = TYPE_GENERIC_SECRET;
+ } else if (data.type.isKeyPrivate()) {
+ dataType = TYPE_AKEY_PRIVATE;
+ } else if (data.type.isKeyPublic()) {
+ dataType = TYPE_AKEY_PUBLIC;
} else {
ThrowErr(Exc::Crypto::DataTypeNotSupported,
"Data type could not be impoted by tz-backend");
"Incorrect algorithm provided for symmetric crypto operation");
}
-RawBuffer asymmetricEncrypt(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer asymmetricEncrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ RawBuffer result;
+
+ switch (algo)
+ {
+ case AlgoType::RSA_OAEP: {
+ TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ data,
+ result);
+ return result;
+ }
+ default:
+ break;
+ }
+
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Asymmetric encryption is not yet supported on TrustZone backend");
+ "Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer asymmetricDecrypt(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer asymmetricDecrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &cipher)
{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ RawBuffer result;
+
+ switch (algo)
+ {
+ case AlgoType::RSA_OAEP: {
+ TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ cipher,
+ result);
+ return result;
+ }
+ default:
+ break;
+ }
+
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Asymmetric encryption is not yet supported on TrustZone backend");
+ "Incorrect algorithm provided for asymmetric crypto operation");
}
-RawBuffer sign(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &)
+RawBuffer sign(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Certificate signing is not yet supported on TrustZone backend");
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+ RawBuffer signature;
+ TrustZoneContext::Instance().executeSign(getAlgType(algo),
+ getHashType(hash),
+ pkey,
+ pwd,
+ message,
+ signature);
+ return signature;
}
-int verify(const RawBuffer &,
- const Pwd &,
- const CryptoAlgorithm &,
- const RawBuffer &,
- const RawBuffer &)
+int verify(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message,
+ const RawBuffer &signature)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Certificate signing is not yet supported on TrustZone backend");
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+ return TrustZoneContext::Instance().executeVerify(getAlgType(algo),
+ getHashType(hash),
+ pkey,
+ pwd,
+ message,
+ signature);
}
} // namespace Internals
#include <tz-backend/tz-context.h>
#include <tz-backend/tz-memory.h>
-#include <tz-backend/tz-serializer.h>
#include <generic-backend/exception.h>
#include <generic-backend/crypto-params.h>
#include <generic-backend/encryption-params.h>
#include <cstdint>
#include <cstring>
+#include <cassert>
+#include <iomanip>
+#include <sstream>
+#include <unordered_map>
namespace CKM {
namespace Crypto {
return dump;
}
+/*
+ * Maximum size for given key type in bytes according to key-manager-ta implementation.
+ * Note that they are greater than TEE Internal Core API v1.1.2.50 (Table 5-9) values.
+ */
+const std::unordered_map<tz_algo_type, size_t> MAX_KEY_SIZE = {
+ { ALGO_RSA, 4096 / 8 },
+ { ALGO_RSA_SV, 4096 / 8 },
+ { ALGO_DSA_SV, 4096 / 8 }
+};
+
+void DeserializeKeyID(TrustZoneMemory &mem, RawBuffer &id)
+{
+ LogDebug("Deserializing key ID");
+
+ KM_SymmetricInput* output = nullptr;
+ int ret = KM_ParamsDeserializationInit(mem.Get()->buffer, mem.Get()->size, &output);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize key ID data deserialization: ", ret);
+ }
+
+ KM_OutData* outData = nullptr;
+ ret = KM_ParamsDeserializeOutData(output, &outData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key ID data: ", ret);
+ }
+
+ if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "Deserialized invalid key ID");
+ }
+
+ // data_size should contain how much memory we actually took for our cipher operation
+ id.resize(outData->data_size);
+ memcpy(id.data(), outData->data, outData->data_size);
+}
+
} // anonymous namespace
TrustZoneContext::TrustZoneContext()
op.params[1].memref.size = keyMemorySize;
Execute(CMD_GENERATE_KEY, &op);
- KM_SymmetricInput* output = nullptr;
- int ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
- if (ret) {
- ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for generated key ID");
- }
-
- KM_OutData* outData = nullptr;
- ret = KM_ParamsDeserializeOutData(output, &outData);
- if (ret) {
- ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize generated key ID");
- }
-
- if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
- ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
- }
-
- keyId.resize(KM_KEY_ID_SIZE);
- memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
+ DeserializeKeyID(keyMemory, keyId);
}
void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
op.params[2].memref.size = keyMemory.Get()->size;
Execute(CMD_GENERATE_KEY_PWD, &op);
+ DeserializeKeyID(keyMemory, keyId);
+
KM_SymmetricInput* output = nullptr;
ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
if (ret) {
memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
}
+void TrustZoneContext::GenerateAKey(tz_command commandId,
+ TZSerializer &sIn,
+ uint32_t keySizeBits,
+ const RawBuffer &pubPwd,
+ const RawBuffer &pubPwdIv,
+ const RawBuffer &privPwd,
+ const RawBuffer &privPwdIv,
+ RawBuffer &pubKeyId,
+ RawBuffer &pubKeyTag,
+ RawBuffer &privKeyId,
+ RawBuffer &privKeyTag)
+{
+ uint32_t pubTagSize = 0;
+ uint32_t privTagSize = 0;
+
+ uint32_t pubPwdExists = pubPwd.empty() ? 0 : 1;
+ sIn.Push(new TZSerializableFlag(pubPwdExists));
+ if (pubPwdExists) {
+ sIn.Push(new TZSerializablePwdData(pubPwd, pubPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+ pubTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
+ }
+ uint32_t privPwdExists = privPwd.empty() ? 0 : 1;
+ sIn.Push(new TZSerializableFlag(privPwdExists));
+ if (privPwdExists) {
+ sIn.Push(new TZSerializablePwdData(privPwd, privPwdIv, Params::DEFAULT_AES_GCM_TAG_LEN_BITS));
+ privTagSize = (Params::DEFAULT_AES_GCM_TAG_LEN_BITS + 7) >> 3;
+ }
+
+ TrustZoneMemory inMemory(m_Context, sIn.GetSize(), TEEC_MEM_INPUT);
+ sIn.Serialize(inMemory);
+
+ TZSerializer sOut;
+ sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
+ sOut.Push(new TZSerializableBinary(pubTagSize));
+ sOut.Push(new TZSerializableBinary(KM_KEY_ID_SIZE));
+ sOut.Push(new TZSerializableBinary(privTagSize));
+
+ TrustZoneMemory outMemory(m_Context, sOut.GetSize(), TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+ TEEC_MEMREF_WHOLE, TEEC_NONE);
+ op.params[0].value.b = keySizeBits;
+ op.params[1].memref.parent = inMemory.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = inMemory.Get()->size;
+ op.params[2].memref.parent = outMemory.Get();
+ op.params[2].memref.offset = 0;
+ op.params[2].memref.size = outMemory.Get()->size;
+ Execute(commandId, &op);
+
+ sOut.Deserialize(outMemory);
+
+ sOut.Pull(pubKeyId);
+ if (pubKeyId.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize public key ID");
+ }
+
+ if (pubPwdExists) {
+ sOut.Pull(pubKeyTag);
+ }
+
+ sOut.Pull(privKeyId);
+ if (privKeyId.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize private key ID");
+ }
+
+ if (privPwdExists) {
+ sOut.Pull(privKeyTag);
+ }
+}
+
+void TrustZoneContext::generateRSAKey(uint32_t keySizeBits,
+ const RawBuffer &pubPwd,
+ const RawBuffer &pubPwdIv,
+ const RawBuffer &privPwd,
+ const RawBuffer &privPwdIv,
+ RawBuffer &pubKeyId,
+ RawBuffer &pubKeyTag,
+ RawBuffer &privKeyId,
+ RawBuffer &privKeyTag)
+{
+ // command ID = CMD_GENERATE_RSA_KEYPAIR
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.b - key bit size
+ // [1].memref - reference to serialized buffer:
+ // flag marking the public key password presence,
+ // public key password data if the flag above is not 0,
+ // flag marking the private key password presence,
+ // public key private data if the flag above is not 0,
+ // output:
+ // [0].value.a - return code
+ // [2].memref
+ // Public key ID,
+ // public key tag if password was present,
+ // Private key ID,
+ // private key tag if password was present,
+
+ TZSerializer sIn;
+
+ GenerateAKey(CMD_GENERATE_RSA_KEYPAIR,
+ sIn,
+ keySizeBits,
+ pubPwd,
+ pubPwdIv,
+ privPwd,
+ privPwdIv,
+ pubKeyId,
+ pubKeyTag,
+ privKeyId,
+ privKeyTag);
+}
+
+void TrustZoneContext::generateDSAKey(uint32_t keySizeBits,
+ const RawBuffer &prime,
+ const RawBuffer &subprime,
+ const RawBuffer &base,
+ const RawBuffer &pubPwd,
+ const RawBuffer &pubPwdIv,
+ const RawBuffer &privPwd,
+ const RawBuffer &privPwdIv,
+ RawBuffer &pubKeyId,
+ RawBuffer &pubKeyTag,
+ RawBuffer &privKeyId,
+ RawBuffer &privKeyTag)
+{
+ // command ID = CMD_GENERATE_DSA_KEYPAIR
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.b - key bit size
+ // [1].memref - reference to serialized buffer:
+ // prime, subprime, base,
+ // flag marking the public key password presence,
+ // public key password data if the flag above is not 0,
+ // flag marking the private key password presence,
+ // public key private data if the flag above is not 0,
+ // output:
+ // [0].value.a - return code
+ // [2].memref
+ // Public key ID,
+ // public key tag if password was present,
+ // Private key ID,
+ // private key tag if password was present,
+
+ TZSerializer sIn;
+ sIn.Push(new TZSerializableBinary(prime));
+ sIn.Push(new TZSerializableBinary(subprime));
+ sIn.Push(new TZSerializableBinary(base));
+
+ GenerateAKey(CMD_GENERATE_DSA_KEYPAIR,
+ sIn,
+ keySizeBits,
+ pubPwd,
+ pubPwdIv,
+ privPwd,
+ privPwdIv,
+ pubKeyId,
+ pubKeyTag,
+ privKeyId,
+ privKeyTag);
+}
+
void TrustZoneContext::executeCrypt(tz_command cmd,
tz_algo_type algo,
- const RawBuffer &key,
+ const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
const RawBuffer &data,
// [0].value.a - return code
// [2].memref - serialized output buffer
- if (key.size() != KM_KEY_ID_SIZE) {
+ if (keyId.size() != KM_KEY_ID_SIZE) {
ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
- + std::to_string(key.size()) + ")");
+ + std::to_string(keyId.size()) + ")");
}
KM_BufferSizeDesc bufSize;
bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
bufSize.iv_size = static_cast<uint32_t>(iv.size());
- bufSize.key_id_size = static_cast<uint32_t>(key.size());
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
- // decrypt operation does not require padding
memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
- bufSize.out_size = static_cast<uint32_t>((cmd == CMD_ENCRYPT) ?
- data.size() + CIPHER_EXTRA_PADDING_SIZE :
- data.size());
+
+ // decrypt operation does not require padding
+ bufSize.out_size = static_cast<uint32_t>(data.size());
+ if (cmd == CMD_ENCRYPT) {
+ if (algo == ALGO_RSA) {
+ // We don't know the key length
+ bufSize.out_size = MAX_KEY_SIZE.at(ALGO_RSA);
+ } else {
+ bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
+ }
+ }
uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
}
- ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
if (ret) {
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
}
memcpy(out.data(), outData->data, outData->data_size);
}
-void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
+void TrustZoneContext::executeEncryptAE(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSizeBits,
// [0].value.a - return code
// [2].memref - output
- if (key.size() != KM_KEY_ID_SIZE) {
+ if (keyId.size() != KM_KEY_ID_SIZE) {
ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
}
bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
bufSize.iv_size = static_cast<uint32_t>(iv.size());
- bufSize.key_id_size = static_cast<uint32_t>(key.size());
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
bufSize.with_ae_data = true;
bufSize.aad_size = static_cast<uint32_t>(aad.size());
uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
}
- ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
if (ret) {
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
}
}
}
-void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
+void TrustZoneContext::executeDecryptAE(const RawBuffer &keyId,
const Pwd &pwd,
const RawBuffer &iv,
int tagSizeBits,
// [0].value.a - output size
// [2].memref - output (decrypted data)
- if (key.size() != KM_KEY_ID_SIZE) {
+ if (keyId.size() != KM_KEY_ID_SIZE) {
ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
}
bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
bufSize.iv_size = static_cast<uint32_t>(iv.size());
- bufSize.key_id_size = static_cast<uint32_t>(key.size());
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
bufSize.with_ae_data = true;
bufSize.aad_size = static_cast<uint32_t>(aad.size());
bufSize.tag_size = static_cast<uint32_t>(tag.size());
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
}
- ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
if (ret) {
ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
}
memcpy(out.data(), outData->data, outData->data_size);
}
+void TrustZoneContext::executeSign(tz_algo_type algo,
+ tz_hash_type hash,
+ const RawBuffer &keyId,
+ const Pwd &pwd,
+ const RawBuffer &message,
+ RawBuffer &signature)
+{
+ // command ID = CMD_SIGN (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // input params:
+ // [0].value.a - algorithm type (tz_algo_type)
+ // [0].value.b - hash type (tz_hash_type)
+ // [1].memref - reference to serialized buffer:
+ // KM_ParamsSerializeInputData with data to sign
+ // KM_ParamsSerializeKeyId with key id
+ // output params:
+ // [0].value.a - return code
+ // [2].memref - reference to serialized buffer:
+ // KM_ParamsSerializeOutData with signature data
+
+ if (keyId.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+ + std::to_string(keyId.size()) + ")");
+ }
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(message.size());
+ bufSize.with_pwd_data = true;
+ bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
+ bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
+ bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = MAX_KEY_SIZE.at(algo);
+ uint32_t outMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT);
+
+ KM_SymmetricInput* input = nullptr;
+ int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
+ }
+
+ ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
+ }
+
+ uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
+ ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
+ pwd.getIV().data(), pwd.getIV().size(),
+ pwd.getTag().data(), pwd.getTag().size(),
+ Params::DERIVED_KEY_LENGTH_BITS,
+ Params::DERIVED_KEY_ITERATIONS,
+ pwdTagSizeBits);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
+ }
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+ TEEC_MEMREF_WHOLE, TEEC_NONE);
+ op.params[0].value.a = algo;
+ op.params[0].value.b = hash;
+ op.params[1].memref.parent = inMemory.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = inMemory.Get()->size;
+ op.params[2].memref.parent = outMemory.Get();
+ op.params[2].memref.offset = 0;
+ op.params[2].memref.size = outMemory.Get()->size;
+ Execute(CMD_SIGN, &op);
+
+ KM_SymmetricInput* output = nullptr;
+ ret = KM_ParamsDeserializationInit(outMemory.Get()->buffer, outMemory.Get()->size, &output);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize output data deserialization: ", ret);
+ }
+
+ KM_OutData* outData = nullptr;
+ ret = KM_ParamsDeserializeOutData(output, &outData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize output data: ", ret);
+ }
+
+ signature.resize(outData->data_size);
+ memcpy(signature.data(), outData->data, outData->data_size);
+}
+
+int TrustZoneContext::executeVerify(tz_algo_type algo,
+ tz_hash_type hash,
+ const RawBuffer &keyId,
+ const Pwd &pwd,
+ const RawBuffer &message,
+ const RawBuffer &signature)
+{
+ // command ID = CMD_VERIFY (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // input params:
+ // [0].value.a - algorithm type (tz_algo_type)
+ // [0].value.b - hash type (tz_hash_type)
+ // [1].memref - reference to serialized buffer:
+ // KM_ParamsSerializeInputData with verify data (signature hidden in Tag data)
+ // KM_ParamsSerializeKeyId with key id
+ // output params:
+ // [0].value.a - return code
+
+ if (keyId.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+ + std::to_string(keyId.size()) + ")");
+ }
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(message.size());
+ bufSize.with_pwd_data = true;
+ bufSize.pwd_size = static_cast<uint32_t>(pwd.getPassword().size());
+ bufSize.pwd_iv_size = static_cast<uint32_t>(pwd.getIV().size());
+ bufSize.pwd_tag_size = static_cast<uint32_t>(pwd.getTag().size());
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.size());
+ bufSize.tag_size = static_cast<uint32_t>(signature.size());
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ KM_SymmetricInput* input = nullptr;
+ int ret = KM_ParamsSerializationInit(inMemory.Get()->buffer, inMemory.Get()->size, &input);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize data serialization for TZ sign operations");
+ }
+
+ ret = KM_ParamsSerializeInputData(input, message.data(), message.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ sign operation: ", ret);
+ }
+
+ uint32_t pwdTagSizeBits = pwd.getTag().size() * 8;
+ ret = KM_ParamsSerializePwdData(input, pwd.getPassword().data(), pwd.getPassword().size(),
+ pwd.getIV().data(), pwd.getIV().size(),
+ pwd.getTag().data(), pwd.getTag().size(),
+ Params::DERIVED_KEY_LENGTH_BITS,
+ Params::DERIVED_KEY_ITERATIONS,
+ pwdTagSizeBits);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ sign operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeKeyId(input, keyId.data(), keyId.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ sign operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeTagData(input, signature.data(), signature.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize signature data for TZ sign operation: ", ret);
+ }
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[0].value.a = algo;
+ op.params[0].value.b = hash;
+ op.params[1].memref.parent = inMemory.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = inMemory.Get()->size;
+ Execute(CMD_VERIFY, &op);
+
+ int opRet = op.params[0].value.a;
+ switch (opRet) {
+ case KM_TA_SUCCESS:
+ return CKM_API_SUCCESS;
+ case KM_TA_ERROR_SIGNATURE:
+ LogWarning("Signature verification failed");
+ return CKM_API_ERROR_VERIFICATION_FAILED;
+ default:
+ assert(false); // This condition should be checked inside Execute() function
+ ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", opRet);
+ }
+}
+
void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
{
// command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
}
int ta_ret = op->params[0].value.a;
- if (ta_ret != KM_TA_SUCCESS) {
- switch (ta_ret) {
- case KM_TA_ERROR_AUTH_FAILED:
- // Authentication cipher failed - notify with proper exception
- ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
- default:
- ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
- }
+ switch (ta_ret) {
+ case KM_TA_SUCCESS:
+ case KM_TA_ERROR_SIGNATURE:
+ break;
+ case KM_TA_ERROR_AUTH_FAILED:
+ // Authentication cipher failed - notify with proper exception
+ ThrowErr(Exc::AuthenticationFailed, "Crypto operation authentication failed");
+ default:
+ ThrowErr(Exc::Crypto::InternalError, "Unknown TA error during operation: ", ta_ret);
}
}