%endif
BuildRequires: boost-devel
BuildRequires: ca-certificates-devel
+BuildRequires: key-manager-ta-devel
+BuildRequires: key-manager-ta-serialization-devel
+BuildRequires: pkgconfig(tef-libteec)
#Requires(pre): tizen-platform-config-tools
Requires: libkey-manager-common = %{version}-%{release}
+
%{?systemd_requires}
%global user_name key-manager
cynara-creds-socket
pkgmgr
vconf
+ tef-libteec
${EXTRA_KM_DEPS}
)
FIND_PACKAGE(Threads REQUIRED)
${KEY_MANAGER_PATH}/crypto/platform/decider.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/obj.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/store.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/internals.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-context.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-memory.cpp
${SECURITY_MANAGER_WRAPPER_PATH}
${CYNARA_WRAPPER_PATH}
)
${KEY_MANAGER_DEP_LIBRARIES}
${TARGET_KEY_MANAGER_COMMON}
-ldl
+ km_serialization
)
################################################################################
};
template <>
-void DefaultGetter<RawBuffer>::Print(std::ostringstream &os,
+inline void DefaultGetter<RawBuffer>::Print(std::ostringstream &os,
const RawBuffer &buffer)
{
os << "[" << buffer.size() << "B buffer]";
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file crypto-params.h
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ */
+ #pragma once
+
+namespace CKM {
+namespace Crypto {
+
+class Params
+{
+public:
+ static const size_t DEFAULT_AES_IV_LEN = 16; // max acceptable size of IV
+ static const int DEFAULT_AES_GCM_TAG_LEN_BYTES = 16; // length of AES GCM tag
+ static const int DEFAULT_AES_GCM_TAG_LEN_BITS = DEFAULT_AES_GCM_TAG_LEN_BYTES * 8;
+ static const int DERIVED_KEY_LENGTH = 16; // length of AES key derived from password in bytes
+ static const int DERIVED_KEY_LENGTH_BITS = DERIVED_KEY_LENGTH * 8; // as above, in bits
+ static const int DERIVED_KEY_ITERATIONS = 1024; // iteration count used to derive key
+};
+
+} // namespace Crypto
+} // namespace CKM
/*
* @file decider.cpp
* @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
#include <dpl/log/log.h>
#include <sw-backend/store.h>
#include <tz-backend/store.h>
+#include <tee_client_api.h>
+#include <km_ta_defines.h>
+
+#include <sstream>
+#include <fstream>
+#include <iomanip>
+
namespace CKM {
namespace Crypto {
namespace {
-CryptoBackend chooseCryptoBackend(DataType dataType, bool exportable,
+
+const std::string TA_STORE_PATH = "/usr/lib/tastore";
+
+template <typename T>
+std::string ValueToString(const T& value)
+{
+ std::stringstream str;
+ // we need to re-cast because otherwise stringstream
+ // will write our value incorrectly
+ str << std::setfill('0') << std::setw(2 * sizeof(T)) << std::hex
+ << static_cast<uint64_t>(value);
+ return str.str();
+}
+
+std::string convertTeecUUIDToString(TEEC_UUID uuid)
+{
+ std::string uuidStr;
+ uuidStr += ValueToString(uuid.timeLow);
+ uuidStr += ValueToString(uuid.timeMid);
+ uuidStr += ValueToString(uuid.timeHiAndVersion);
+ for (auto& c: uuid.clockSeqAndNode)
+ uuidStr += ValueToString(c);
+
+ return uuidStr;
+}
+
+CryptoBackend chooseCryptoBackend(DataType data, bool exportable,
bool encrypted)
{
- // Only software backend supports device encyption key
+ // For now only software backend supports device encyption key
+ // TODO tz-backend could support the master key, but it would require
+ // hardcoding a known key ID and querying TA whether the key is
+ // reachable
if (encrypted)
return CryptoBackend::OpenSSL;
- // The list of items that MUST be support by OpenSSL
- if (dataType.isCertificate())
+ // Only software backend allows for key export
+ if (exportable)
return CryptoBackend::OpenSSL;
- if (dataType.isBinaryData())
+ // Use TrustZone only with symmetric keys until asymmetric
+ // cryptography is implemented
+ if (!data.isSKey())
return CryptoBackend::OpenSSL;
- if (exportable)
- return CryptoBackend::OpenSSL;
+ // Check if key-manager TA exists
+ std::string taUUIDStr = convertTeecUUIDToString(KM_TA_UUID);
- // This is the place where we can use trust zone backend
- // Examples:
- //
- // if (dataType.isKeyPrivate())
- // return CryptoBackend::TrustZone;
+ LogDebug("Checking for " << TA_STORE_PATH << "/" << taUUIDStr);
+ std::ifstream taFile(TA_STORE_PATH + "/" + taUUIDStr);
+ if (taFile)
+ return CryptoBackend::TrustZone;
- // This item does not met Trust Zone requirements. Let's use software backend
+ // no TA available - fallback to OpenSSL
return CryptoBackend::OpenSSL;
}
+
} // namespace
Decider::Decider()
#include <generic-backend/exception.h>
#include <generic-backend/algo-validation.h>
+#include <generic-backend/crypto-params.h>
#include <sw-backend/internals.h>
#include <sw-backend/crypto.h>
typedef std::unique_ptr<BIO, std::function<void(BIO *)>> BioUniquePtr;
typedef int(*I2D_CONV)(BIO *, EVP_PKEY *);
-const size_t DEFAULT_AES_GCM_TAG_LEN =
- 128; // tag length in bits according to W3C Crypto API
-const size_t DEFAULT_AES_IV_LEN = 16; // default iv size in bytes for AES
RawBuffer i2d(I2D_CONV fun, EVP_PKEY *pkey)
{
typedef ParamCheck<ParamName::ED_IV,
RawBuffer,
true,
- Type<size_t>::Equals<DEFAULT_AES_IV_LEN>,
+ Type<size_t>::Equals<Params::DEFAULT_AES_IV_LEN>,
BufferSizeGetter> IvSizeCheck;
typedef ParamCheck<ParamName::ED_CTR_LEN,
ParamName::ED_IV));
case AlgoType::AES_GCM: {
- int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
+ int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
RawBuffer aad;
alg.getParam(ParamName::ED_AAD, aad);
ParamName::ED_IV));
case AlgoType::AES_GCM: {
- int tagLenBits = DEFAULT_AES_GCM_TAG_LEN;
+ int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
RawBuffer aad;
alg.getParam(ParamName::ED_AAD, aad);
#include <openssl/evp.h>
#include <generic-backend/exception.h>
+#include <generic-backend/crypto-params.h>
#include <sw-backend/obj.h>
#include <sw-backend/store.h>
#include <sw-backend/internals.h>
namespace {
-const int ITERATIONS = 1024;
-const int KEY_LENGTH = 16; // length of AES key derived from password
-const int STORE_AES_GCM_TAG_SIZE = 16; // length of AES GCM tag
-
// internal SW encryption scheme flags
enum EncryptionScheme {
NONE = 0,
password.size(),
salt.data(),
salt.size(),
- ITERATIONS,
+ Params::DERIVED_KEY_ITERATIONS,
result.size(),
result.data()))
ThrowErr(Exc::InternalError, "PCKS5_PKKDF2_HMAC_SHA1 failed.");
* - password is empty when it shouldn't be
* - password is not empty when it should be
*/
- RawBuffer key = passwordToKey(pass, iv, KEY_LENGTH);
+ RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH);
RawBuffer ret;
if (!pass.empty()) {
RawBuffer iv = generateRandIV();
- RawBuffer key = passwordToKey(pass, iv, KEY_LENGTH);
+ RawBuffer key = passwordToKey(pass, iv, Params::DERIVED_KEY_LENGTH);
std::pair<RawBuffer, RawBuffer> ret;
try {
ret = Crypto::SW::Internals::encryptDataAesGcm(key, data, iv,
- STORE_AES_GCM_TAG_SIZE);
+ Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
} catch (const Exc::Crypto::InternalError &e) {
ThrowErr(Exc::AuthenticationFailed, "Encryption with custom password failed");
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file internals.h
+ * @author Krzysztof Dynowski (k.dynowski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ */
+
+#include <generic-backend/exception.h>
+#include <generic-backend/algo-validation.h>
+#include <generic-backend/crypto-params.h>
+#include <dpl/log/log.h>
+
+#include <tz-backend/internals.h>
+#include <tz-backend/tz-context.h>
+#include <km_ta_defines.h>
+
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+tz_algo_type getGenKeyType(AlgoType type)
+{
+ switch (type)
+ {
+ case AlgoType::AES_GEN: return ALGO_AES_GEN;
+ default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+ }
+}
+
+tz_algo_type getAlgType(AlgoType type)
+{
+ switch (type)
+ {
+ case AlgoType::AES_CBC: return ALGO_AES_CBC;
+ case AlgoType::AES_CTR: return ALGO_AES_CTR;
+ case AlgoType::AES_CFB: return ALGO_AES_CFB;
+ case AlgoType::AES_GCM: return ALGO_AES_GCM;
+ default: ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+ };
+}
+
+tz_algo_type getAlgType(KeyType keyType)
+{
+ switch (keyType)
+ {
+ case KeyType::KEY_AES:
+ return ALGO_AES_GEN;
+ case KeyType::KEY_RSA_PUBLIC:
+ case KeyType::KEY_RSA_PRIVATE:
+ return ALGO_RSA_GEN;
+ default:
+ ThrowErr(Exc::Crypto::OperationNotSupported, "Requested algorithm is not supported");
+ };
+}
+
+RawBuffer generateIV()
+{
+ RawBuffer result;
+ TrustZoneContext::Instance().generateIV(Params::DEFAULT_AES_IV_LEN, result);
+ return result;
+}
+
+Data generateSKey(const CryptoAlgorithm &alg,
+ const Password &pwd,
+ const RawBuffer &iv,
+ RawBuffer &tag)
+{
+ AlgoType keyType = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ int keyBits = unpack<int>(alg, ParamName::GEN_KEY_LEN);
+
+ Data keyData;
+ keyData.type = DataType(keyType);
+
+ if (!pwd.empty()) {
+ if (iv.empty()) {
+ ThrowErr(Exc::InputParam, "Key generation with password encryption requires an IV");
+ }
+
+ RawBuffer pwdBuf(pwd.begin(), pwd.end());
+ TrustZoneContext::Instance().generateSKeyPwd(getGenKeyType(keyType),
+ pwdBuf, iv, keyBits,
+ Params::DEFAULT_AES_GCM_TAG_LEN_BITS,
+ keyData.data, tag);
+ } else {
+ TrustZoneContext::Instance().generateSKey(getGenKeyType(keyType), keyBits,
+ keyData.data);
+ }
+
+ return keyData;
+}
+
+DataPair generateAKey(const CryptoAlgorithm &,
+ const Password &,
+ const RawBuffer &)
+{
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "AKeys are not yet implemented in TrustZone backend");
+}
+
+void destroyKey(const RawBuffer &key)
+{
+ TrustZoneContext::Instance().executeDestroy(key);
+}
+
+RawBuffer importKey(const Data &data,
+ const Password &pwd,
+ const RawBuffer &iv,
+ RawBuffer &tag)
+{
+ tz_algo_type algo = getAlgType(data.type);
+ RawBuffer result;
+
+ RawBuffer pwdBuf(pwd.begin(), pwd.end());
+ uint32_t keySizeBits = data.data.size() * 8;
+ TrustZoneContext::Instance().importKey(algo,
+ data.data,
+ pwdBuf,
+ iv,
+ keySizeBits,
+ Params::DERIVED_KEY_LENGTH_BITS,
+ result,
+ tag);
+ return result;
+}
+
+BufferPair encryptDataAesGcm(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSize,
+ const RawBuffer &data,
+ const RawBuffer &aad)
+{
+ RawBuffer result;
+ RawBuffer tag;
+
+ TrustZoneContext::Instance().executeEncryptAE(key, pwd, iv, tagSize,
+ aad, data, result, tag);
+
+ return std::make_pair(result, tag);
+}
+
+RawBuffer encryptDataAesGcmPacked(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSize,
+ const RawBuffer &data,
+ const RawBuffer &aad)
+{
+ auto pair = encryptDataAesGcm(key, pwd, iv, tagSize, data, aad);
+ std::copy(pair.second.begin(), pair.second.end(),
+ std::back_inserter(pair.first));
+ return pair.first;
+}
+
+RawBuffer decryptDataAesGcm(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &tag,
+ const RawBuffer &data,
+ const RawBuffer &aad)
+{
+ RawBuffer result;
+
+ TrustZoneContext::Instance().executeDecryptAE(key, pwd, iv, tagSizeBits,
+ tag, aad, data, result);
+
+ return result;
+}
+
+RawBuffer decryptDataAesGcmPacked(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &data,
+ const RawBuffer &aad)
+{
+ int tagSizeBytes = tagSizeBits / 8;
+ if (tagSizeBytes > static_cast<int>(data.size()))
+ ThrowErr(Exc::Crypto::InputParam, "Wrong size of tag");
+
+ auto tagPos = data.data() + data.size() - tagSizeBytes;
+ return decryptDataAesGcm(key,
+ pwd,
+ iv,
+ tagSizeBits,
+ RawBuffer(tagPos, data.data() + data.size()),
+ RawBuffer(data.data(), tagPos),
+ aad);
+}
+
+
+RawBuffer symmetricEncrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
+{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ uint64_t ctrLen = 0;
+
+ switch (algo) {
+ case AlgoType::AES_CTR: {
+ ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
+ // counter length is in bits
+ if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
+ LogError("CTR length invalid: " << std::to_string(ctrLen));
+ ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
+ }
+ // no break here, we still need to slide down to executeCrypt
+ }
+ case AlgoType::AES_CBC:
+ case AlgoType::AES_CFB: {
+ RawBuffer result;
+ TrustZoneContext::Instance().executeCrypt(CMD_ENCRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ data,
+ result);
+ return result;
+ }
+ case AlgoType::AES_GCM: {
+ int tagLenBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
+ alg.getParam(ParamName::ED_TAG_LEN, tagLenBits);
+ RawBuffer aad;
+ alg.getParam(ParamName::ED_AAD, aad);
+ return encryptDataAesGcmPacked(key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ tagLenBits,
+ data,
+ aad);
+ }
+ default:
+ break;
+ }
+
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Incorrect algorithm provided for symmetric crypto operation");
+}
+
+RawBuffer symmetricDecrypt(const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data)
+{
+ AlgoType algo = unpack<AlgoType>(alg, ParamName::ALGO_TYPE);
+ uint64_t ctrLen = 0;
+
+ switch (algo) {
+ case AlgoType::AES_CTR: {
+ ctrLen = unpack<uint64_t>(alg, ParamName::ED_CTR_LEN);
+ // counter length is in bits
+ if (ctrLen != Params::DEFAULT_AES_IV_LEN * 8) {
+ LogError("CTR length invalid: " << std::to_string(ctrLen));
+ ThrowErr(Exc::Crypto::InputParam, "Invalid CTR length");
+ }
+ // no break here, we still need to slide down to executeCrypt
+ }
+ case AlgoType::AES_CBC:
+ case AlgoType::AES_CFB: {
+ RawBuffer result;
+ TrustZoneContext::Instance().executeCrypt(CMD_DECRYPT,
+ getAlgType(algo),
+ key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ data,
+ result);
+ return result;
+ }
+ case AlgoType::AES_GCM: {
+ int tagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS;
+ alg.getParam(ParamName::ED_TAG_LEN, tagSizeBits);
+ RawBuffer aad;
+ alg.getParam(ParamName::ED_AAD, aad);
+ return decryptDataAesGcmPacked(key,
+ pwd,
+ unpack<RawBuffer>(alg, ParamName::ED_IV),
+ tagSizeBits,
+ data,
+ aad);
+ }
+ default:
+ break;
+ }
+
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Incorrect algorithm provided for symmetric crypto operation");
+}
+
+RawBuffer asymmetricEncrypt(const RawBuffer &,
+ const Pwd &,
+ const CryptoAlgorithm &,
+ const RawBuffer &)
+{
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Asymmetric encryption is not yet supported on TrustZone backend");
+}
+
+RawBuffer asymmetricDecrypt(const RawBuffer &,
+ const Pwd &,
+ const CryptoAlgorithm &,
+ const RawBuffer &)
+{
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Asymmetric encryption is not yet supported on TrustZone backend");
+}
+
+RawBuffer sign(const RawBuffer &,
+ const Pwd &,
+ const CryptoAlgorithm &,
+ const RawBuffer &)
+{
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Certificate signing is not yet supported on TrustZone backend");
+}
+
+int verify(const RawBuffer &,
+ const Pwd &,
+ const CryptoAlgorithm &,
+ const RawBuffer &,
+ const RawBuffer &)
+{
+ ThrowErr(Exc::Crypto::OperationNotSupported,
+ "Certificate signing is not yet supported on TrustZone backend");
+}
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file internals.h
+ * @author Krzysztof Dynowski (k.dynowski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ */
+#pragma once
+
+#include <ckm/ckm-type.h>
+#include <data-type.h>
+#include <tz-backend/obj.h>
+#include <generic-backend/gstore.h>
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+using DataPair = std::pair<Data, Data>;
+using BufferPair = std::pair<RawBuffer, RawBuffer>;
+
+// encryption schema + buffer pair
+using KeyIdPair = std::pair<int, RawBuffer>;
+
+RawBuffer generateIV();
+DataPair generateAKey(const CryptoAlgorithm &alg,
+ const Password &pwd,
+ const RawBuffer &iv);
+Data generateSKey(const CryptoAlgorithm &alg,
+ const Password &pwd,
+ const RawBuffer &iv,
+ RawBuffer &tag);
+RawBuffer importKey(const Data &key,
+ const Password &pwd,
+ const RawBuffer &iv,
+ RawBuffer &tag);
+void destroyKey(const RawBuffer &key);
+
+RawBuffer symmetricEncrypt(
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data);
+RawBuffer symmetricDecrypt(
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &cipher);
+
+RawBuffer asymmetricEncrypt(
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &data);
+RawBuffer asymmetricDecrypt(
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &cipher);
+
+BufferPair encryptDataAesGcm(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSize,
+ const RawBuffer &data,
+ const RawBuffer &aad = RawBuffer());
+
+RawBuffer decryptDataAesGcm(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ const RawBuffer &tag,
+ const RawBuffer &data,
+ const RawBuffer &aad = RawBuffer());
+
+RawBuffer sign(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message);
+
+int verify(const RawBuffer &pkey,
+ const Pwd &pwd,
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message,
+ const RawBuffer &signature);
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
/*
* @file obj.cpp
- * @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
+#include <generic-backend/exception.h>
+#include <tz-backend/obj.h>
+#include <tz-backend/internals.h>
+
namespace CKM {
namespace Crypto {
namespace TZ {
+namespace {
+AlgoType key2algo(DataType type)
+{
+ switch (static_cast<int>(type)) {
+ case DataType::Type::KEY_RSA_PRIVATE:
+ case DataType::Type::KEY_RSA_PUBLIC:
+ return AlgoType::RSA_SV;
+
+ case DataType::Type::KEY_DSA_PRIVATE:
+ case DataType::Type::KEY_DSA_PUBLIC:
+ return AlgoType::DSA_SV;
+
+ case DataType::Type::KEY_ECDSA_PRIVATE:
+ case DataType::Type::KEY_ECDSA_PUBLIC:
+ return AlgoType::ECDSA_SV;
+
+ default:
+ ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", type);
+ }
+}
+} // namespace anonymous
+
+RawBuffer SKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
+{
+ return Internals::symmetricEncrypt(getBinary(), getPassword(), alg, data);
+}
+
+RawBuffer SKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
+{
+ return Internals::symmetricDecrypt(getBinary(), getPassword(), alg, cipher);
+}
+
+RawBuffer AKey::encrypt(const CryptoAlgorithm &alg, const RawBuffer &data)
+{
+ return Internals::asymmetricEncrypt(getBinary(), getPassword(), alg, data);
+}
+
+RawBuffer AKey::decrypt(const CryptoAlgorithm &alg, const RawBuffer &cipher)
+{
+ return Internals::asymmetricDecrypt(getBinary(), getPassword(), alg, cipher);
+}
+
+RawBuffer AKey::sign(
+ const CryptoAlgorithm &alg,
+ const RawBuffer &message)
+{
+ CryptoAlgorithm algWithType(alg);
+ algWithType.setParam(ParamName::ALGO_TYPE, key2algo(m_type));
+ return Internals::sign(getBinary(), getPassword(), algWithType, message);
+}
+
+int AKey::verify(const CryptoAlgorithm &alg, const RawBuffer &message,
+ const RawBuffer &sign)
+{
+ CryptoAlgorithm algWithType(alg);
+ AlgoType type;
+
+ // setup algorithm type basing on key type if it doesn't exist
+ if (!algWithType.getParam(ParamName::ALGO_TYPE, type)) {
+ ThrowErr(Exc::Crypto::InputParam, "Invalid key type: ", "not given");
+ }
+
+ return Internals::verify(getBinary(), getPassword(), algWithType, message, sign);
+}
+
+
} // namespace TZ
} // namespace Crypto
} // namespace CKM
*/
/*
* @file obj.h
- * @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
#pragma once
#include <generic-backend/gobj.h>
+#include <data-type.h>
namespace CKM {
namespace Crypto {
namespace TZ {
-class SKey : public GObj {
+class Pwd {
public:
- SKey() {}
- virtual ~SKey() {}
+ Pwd(Password pwd, RawBuffer iv, RawBuffer tag)
+ : m_password(pwd.begin(), pwd.end())
+ , m_iv(std::move(iv))
+ , m_tag(std::move(tag))
+ {}
+
+ const RawBuffer& getPassword() const
+ {
+ return m_password;
+ }
+
+ const RawBuffer& getIV() const
+ {
+ return m_iv;
+ }
+
+ const RawBuffer& getTag() const
+ {
+ return m_tag;
+ }
+
+
+private:
+ RawBuffer m_password;
+ RawBuffer m_iv;
+ RawBuffer m_tag;
+};
+
+class BData : public GObj {
+public:
+ BData(int scheme, RawBuffer buffer, Pwd pwd, DataType keyType):
+ m_scheme(scheme), m_raw(std::move(buffer)), m_password(std::move(pwd)),
+ m_type(keyType) {}
+
+ virtual RawBuffer getBinary() const override
+ {
+ return m_raw;
+ }
+
+ virtual int getScheme() const
+ {
+ return m_scheme;
+ }
+
+ virtual Pwd getPassword() const
+ {
+ return m_password;
+ }
protected:
+ int m_scheme;
+ RawBuffer m_raw;
+ Pwd m_password;
+ DataType m_type;
+};
+
+class SKey : public BData {
+public:
+ SKey(int scheme, RawBuffer buffer, Pwd pwd, DataType keyType) :
+ BData(scheme, std::move(buffer), std::move(pwd), keyType) {}
+
+ virtual RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &);
+ virtual RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &);
};
-class AKey : public GObj {
+class AKey : public BData {
public:
- AKey() {}
+ AKey(int scheme, RawBuffer buffer, Pwd pwd, DataType dataType) :
+ BData(scheme, std::move(buffer), std::move(pwd), dataType) {}
+
+ virtual RawBuffer sign(const CryptoAlgorithm &alg, const RawBuffer &message);
+ virtual int verify(const CryptoAlgorithm &alg, const RawBuffer &message,
+ const RawBuffer &sign);
+ virtual RawBuffer encrypt(const CryptoAlgorithm &, const RawBuffer &);
+ virtual RawBuffer decrypt(const CryptoAlgorithm &, const RawBuffer &);
virtual ~AKey() {}
+};
-protected:
+class Cert : public AKey {
+public:
+ Cert(int scheme, RawBuffer buffer, Pwd pwd, DataType dataType) :
+ AKey(scheme, std::move(buffer), std::move(pwd), dataType) {}
+
+ virtual ~Cert() {}
};
} // namespace TZ
*/
/*
* @file store.cpp
- * @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
+
#include <generic-backend/exception.h>
+#include <generic-backend/crypto-params.h>
#include <tz-backend/obj.h>
#include <tz-backend/store.h>
+#include <tz-backend/internals.h>
+
+#include <dpl/log/log.h>
+#include <message-buffer.h>
namespace CKM {
namespace Crypto {
namespace TZ {
+namespace {
+
+template <typename T, typename ...Args>
+std::unique_ptr<T> make_unique(Args &&...args)
+{
+ return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
+}
+
+// internal SW encryption scheme flags
+enum EncryptionScheme {
+ NONE = 0,
+ PASSWORD = 1 << 0
+};
+
+void unpack(const RawBuffer &packed,
+ int &scheme,
+ RawBuffer &data,
+ RawBuffer &iv,
+ RawBuffer &tag)
+{
+ MessageBuffer buffer;
+ buffer.Push(packed);
+
+ buffer.Deserialize(scheme);
+
+ if (scheme == EncryptionScheme::PASSWORD) {
+ buffer.Deserialize(data, iv, tag);
+ } else {
+ buffer.Deserialize(data);
+ }
+}
+
+RawBuffer unpackData(const RawBuffer &packed)
+{
+ MessageBuffer buffer;
+ buffer.Push(packed);
+
+ int scheme;
+ buffer.Deserialize(scheme);
+
+ RawBuffer data;
+ buffer.Deserialize(data);
+ return data;
+}
+
+RawBuffer pack(const RawBuffer &keyId, const Password &pwd,
+ const RawBuffer &iv, const RawBuffer &tag)
+{
+ // determine whether the key is password protected and store schema info
+ // we don't need to additionally encrypt key ID
+ int scheme = pwd.empty() ? EncryptionScheme::NONE : EncryptionScheme::PASSWORD;
+
+ if (scheme == EncryptionScheme::PASSWORD) {
+ return MessageBuffer::Serialize(scheme, keyId, iv, tag).Pop();
+ } else {
+ return MessageBuffer::Serialize(scheme, keyId).Pop();
+ }
+}
+
+} // namespace
+
Store::Store(CryptoBackend backendId) :
GStore(backendId)
{
}
-GObjUPtr Store::getObject(const Token &, const Password &)
+GObjUPtr Store::getObject(const Token &token, const Password &pass)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Trust zone backend is not implemented!");
+ int scheme;
+ RawBuffer data;
+ RawBuffer iv;
+ RawBuffer tag;
+ unpack(token.data, scheme, data, iv, tag);
+
+ // TODO AKeys
+
+ if (token.dataType == DataType(DataType::KEY_AES))
+ return make_unique<SKey>(scheme, data, Pwd(pass, iv, tag), token.dataType);
+
+ // TODO certificate/chaincert
+
+ if (token.dataType.isBinaryData())
+ return make_unique<BData>(scheme, data, Pwd(pass, iv, tag), token.dataType);
+
+ ThrowErr(Exc::Crypto::DataTypeNotSupported,
+ "This type of data is not supported by trustzone backend: ", (int)token.dataType);
}
TokenPair Store::generateAKey(const CryptoAlgorithm &, const Password &,
const Password &)
{
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Trust zone backend is not implemented!");
+ "AKey operations are not implemented on TrustZone backend!");
}
-Token Store::import(const Data &, const Password &)
+Token Store::generateSKey(const CryptoAlgorithm &alg, const Password &pass)
{
- ThrowErr(Exc::Crypto::OperationNotSupported,
- "Trust zone backend is not implemented!");
+ RawBuffer iv;
+ RawBuffer tag;
+ if (!pass.empty()) {
+ // IV is needed for key encryption
+ iv = Internals::generateIV();
+ }
+
+ Data ret = Internals::generateSKey(alg, pass, iv, tag);
+ return Token(m_backendId, ret.type, pack(ret.data, pass, iv, tag));
+}
+
+Token Store::import(const Data &data, const Password &pass)
+{
+ if (!data.type.isKey())
+ ThrowErr(Exc::Crypto::InputParam, "Invalid data provided for import");
+
+ if (!data.type.isSKey())
+ ThrowErr(Exc::Crypto::DataTypeNotSupported, "Asymmetric keys are not supported");
+
+ RawBuffer iv;
+ RawBuffer tag;
+ if (!pass.empty()) {
+ // IV is needed for key encryption
+ iv = Internals::generateIV();
+ }
+
+ RawBuffer keyId = Internals::importKey(data, pass, iv, tag);
+ return Token(m_backendId, data.type, pack(keyId, pass, iv, tag));
}
Token Store::importEncrypted(const Data &, const Password &,
const DataEncryption &)
{
ThrowErr(Exc::Crypto::OperationNotSupported,
- "Trust zone backend is not implemented!");
+ "Encrypted import is not yet supported on TrustZone backend!");
+}
+
+void Store::destroy(const Token &token)
+{
+ RawBuffer data = unpackData(token.data);
+ Internals::destroyKey(data);
}
} // namespace TZ
*/
/*
* @file store.h
- * @author Bartłomiej Grzelewski (b.grzelewski@samsung.com)
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
* @version 1.0
*/
#pragma once
virtual GObjUPtr getObject(const Token &, const Password &);
virtual TokenPair generateAKey(const CryptoAlgorithm &, const Password &,
const Password &);
- virtual Token import(const Data &data, const Password &);
+ virtual Token generateSKey(const CryptoAlgorithm &, const Password &);
+ virtual Token import(const Data &, const Password &);
virtual Token importEncrypted(const Data &, const Password &,
const DataEncryption &);
- virtual void destroy(const Token &) {}
+ virtual void destroy(const Token &);
+
+ // TODO device key ID is needed here to support importEncrypted
};
} // namespace TZ
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file tz-context.cpp
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ */
+
+#include <tz-backend/tz-context.h>
+#include <tz-backend/tz-memory.h>
+#include <generic-backend/exception.h>
+#include <generic-backend/crypto-params.h>
+#include <dpl/log/log.h>
+
+#include <km_serialization.h>
+#include <km_ta_defines.h>
+
+#include <cstdint>
+#include <cstring>
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+namespace {
+
+// A little bit of extra memory to add to output buffers.
+//
+// We need this extra memory to output for padding purposes - after encryption
+// we can resize the result memory back to its proper size according to
+// whatever TA will return us.
+const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16;
+
+// Identifier of our TA
+const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID;
+
+} // anonymous namespace
+
+TrustZoneContext::TrustZoneContext()
+ : m_ContextInitialized(false)
+ , m_SessionInitialized(false)
+{
+ Initialize();
+}
+
+TrustZoneContext::~TrustZoneContext()
+{
+ Destroy();
+}
+
+TrustZoneContext& TrustZoneContext::Instance()
+{
+ static TrustZoneContext instance;
+ return instance;
+}
+
+void TrustZoneContext::generateIV(uint32_t ivSize, RawBuffer& iv)
+{
+ // command ID = CMD_GENERATE_IV
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [1].memref.buffer - output
+ // [1].memref.size - output size
+ // output:
+ // [0].value.a - return code
+
+ // IV generation is a simple call - no need to serialize data
+ // just provide the output buffer with size equal to iv.
+ TrustZoneMemory ivMemory(m_Context, ivSize, TEEC_MEM_OUTPUT);
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[1].memref.parent = ivMemory.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = ivMemory.Get()->size;
+ Execute(CMD_GENERATE_IV, &op);
+
+ iv.resize(ivSize);
+ memcpy(iv.data(), ivMemory.Get()->buffer, ivMemory.Get()->size);
+}
+
+void TrustZoneContext::generateSKey(tz_algo_type algo,
+ uint32_t keySizeBits,
+ RawBuffer &keyId)
+{
+ // command ID = CMD_GENERATE_KEY
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - key type
+ // [0].value.b - key bit size
+ // output:
+ // [0].value.a - return code
+ // [1].memref - serialized key reference
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = KM_KEY_ID_SIZE;
+ uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory keyMemory(m_Context, keyMemorySize, TEEC_MEM_OUTPUT);
+
+ 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 = keySizeBits;
+ op.params[1].memref.parent = keyMemory.Get();
+ op.params[1].memref.offset = 0;
+ 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);
+}
+
+void TrustZoneContext::generateSKeyPwd(tz_algo_type algo,
+ const RawBuffer &pwd,
+ const RawBuffer &iv,
+ const uint32_t keySizeBits,
+ const uint32_t pwdTagSizeBits,
+ RawBuffer &keyId,
+ RawBuffer &pwdTag)
+{
+ // command ID = CMD_GENERATE_KEY_PWD
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - key type
+ // [0].value.b - key size in bits
+ // [1].memref - input (seralized pwd/iv for pbkdf2)
+ // output:
+ // [0].value.a - return code
+ // [2].memref - serialized key reference ID
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.with_pwd_data = true;
+ bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
+ bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = KM_KEY_ID_SIZE;
+ bufSize.tag_size = pwdTagSizeBits / 8;
+ uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory keyMemory(m_Context, keyMemorySize, 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 crypto operations");
+ }
+
+ ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
+ nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
+ Params::DERIVED_KEY_ITERATIONS, pwdTagSizeBits);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize password data for TZ crypto 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 = 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 = keyMemory.Get();
+ op.params[2].memref.offset = 0;
+ op.params[2].memref.size = keyMemory.Get()->size;
+ Execute(CMD_GENERATE_KEY_PWD, &op);
+
+ KM_SymmetricInput* output = nullptr;
+ 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");
+ }
+
+ KM_TagData* tagData = nullptr;
+ ret = KM_ParamsDeserializeTagData(output, &tagData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize key's tag");
+ }
+
+ if (outData == nullptr || outData->data_size != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key ID");
+ }
+
+ if (tagData == nullptr || tagData->data_size != Params::DEFAULT_AES_GCM_TAG_LEN_BYTES) {
+ ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
+ }
+
+ keyId.resize(KM_KEY_ID_SIZE);
+ memcpy(keyId.data(), outData->data, KM_KEY_ID_SIZE);
+
+ pwdTag.resize(Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
+ memcpy(pwdTag.data(), tagData->data, Params::DEFAULT_AES_GCM_TAG_LEN_BYTES);
+}
+
+
+void TrustZoneContext::importKey(tz_algo_type algo,
+ const RawBuffer &key,
+ const RawBuffer &pwd,
+ const RawBuffer &iv,
+ const uint32_t keySizeBits,
+ const uint32_t pwdTagSizeBits,
+ RawBuffer &keyId,
+ RawBuffer &pwdTag)
+{
+ // command ID = CMD_IMPORT_KEY
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - key type
+ // [0].value.b - key size in bits
+ // [1].memref - seralized key & password data
+ // output:
+ // [0].value.a - return code
+ // [2].memref - serialized key reference ID
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(key.size());
+ if (!pwd.empty()) {
+ bufSize.with_pwd_data = true;
+ bufSize.pwd_size = static_cast<uint32_t>(pwd.size());
+ bufSize.pwd_iv_size = static_cast<uint32_t>(iv.size());
+ }
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = KM_KEY_ID_SIZE;
+ bufSize.tag_size = pwdTagSizeBits / 8;
+ uint32_t keyMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory keyMemory(m_Context, keyMemorySize, 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 key import: ", ret);
+ }
+
+ ret = KM_ParamsSerializeInputData(input, key.data(), key.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key to import: ", ret);
+ }
+
+ if (!pwd.empty()) {
+ ret = KM_ParamsSerializePwdData(input, pwd.data(), pwd.size(), iv.data(), iv.size(),
+ nullptr, 0, Params::DERIVED_KEY_LENGTH_BITS,
+ Params::DERIVED_KEY_ITERATIONS, pwdTagSizeBits);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key data for import: ", 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 = 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 = keyMemory.Get();
+ op.params[2].memref.offset = 0;
+ op.params[2].memref.size = keyMemory.Get()->size;
+ Execute(CMD_IMPORT_KEY, &op);
+
+ KM_SymmetricInput* output = nullptr;
+ ret = KM_ParamsDeserializationInit(keyMemory.Get()->buffer, keyMemory.Get()->size, &output);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize deserialization for imported key ID");
+ }
+
+ KM_OutData* outData = nullptr;
+ ret = KM_ParamsDeserializeOutData(output, &outData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported 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);
+
+ if (!pwd.empty()) {
+ KM_TagData* tagData = nullptr;
+ uint32_t pwdTagSizeBytes = pwdTagSizeBits / 8;
+
+ ret = KM_ParamsDeserializeTagData(output, &tagData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize imported key's tag");
+ }
+
+ if (tagData == nullptr || tagData->data_size != pwdTagSizeBytes) {
+ ThrowErr(Exc::Crypto::InternalError, "Deserialized incorrect key tag");
+ }
+
+ pwdTag.resize(pwdTagSizeBytes);
+ memcpy(pwdTag.data(), tagData->data, pwdTagSizeBytes);
+ }
+}
+
+void TrustZoneContext::executeCrypt(tz_command cmd,
+ tz_algo_type algo,
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ const RawBuffer &data,
+ RawBuffer &out)
+{
+ // command IDs = CMD_ENCRYPT, CMD_DECRYPT (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - keyid
+ // [0].value.b - algo
+ // [1].memref - input data (serialized key/input)
+ // returned:
+ // [0].value.a - return code
+ // [2].memref - serialized output buffer
+
+ if (key.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer (size = "
+ + std::to_string(key.size()) + ")");
+ }
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(data.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.iv_size = static_cast<uint32_t>(iv.size());
+ bufSize.key_id_size = static_cast<uint32_t>(key.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());
+ 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 crypto operations");
+ }
+
+ ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto 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 crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto 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[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, &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);
+ }
+
+ // data_size should contain how much memory we actually took for our cipher operation
+ out.resize(outData->data_size);
+ memcpy(out.data(), outData->data, outData->data_size);
+}
+
+void TrustZoneContext::executeEncryptAE(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &aad,
+ const RawBuffer &data,
+ RawBuffer &out,
+ RawBuffer &tag)
+{
+ // command ID = CMD_ENCRYPT (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - keyid
+ // [0].value.b - algo
+ // [1].memref - input data (serialized key/input/iv/aad)
+ // returned:
+ // [0].value.a - return code
+ // [2].memref - output
+
+ if (key.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
+ }
+
+ uint32_t tagSizeBytes = (tagSizeBits + 7) / 8;
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(data.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.iv_size = static_cast<uint32_t>(iv.size());
+ bufSize.key_id_size = static_cast<uint32_t>(key.size());
+ bufSize.with_ae_data = true;
+ bufSize.aad_size = static_cast<uint32_t>(aad.size());
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = static_cast<uint32_t>(data.size() + CIPHER_EXTRA_PADDING_SIZE);
+ bufSize.tag_size = static_cast<uint32_t>(tagSizeBytes);
+ 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 crypto operations");
+ }
+
+ ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto 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 crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto 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_AES_GCM;
+ 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_ENCRYPT, &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);
+ }
+
+ KM_TagData* tagData = nullptr;
+ ret = KM_ParamsDeserializeTagData(output, &tagData);
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize tag data: ", ret);
+ }
+
+ out.resize(outData->data_size);
+ memcpy(out.data(), outData->data, outData->data_size);
+
+ if (tagData->data_size) {
+ tag.resize(tagData->data_size);
+ memcpy(tag.data(), tagData->data, tagData->data_size);
+ }
+}
+
+void TrustZoneContext::executeDecryptAE(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &tag,
+ const RawBuffer &aad,
+ const RawBuffer &data,
+ RawBuffer &out)
+{
+ // command ID = CMD_DECRYPT (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // params:
+ // [0].value.a - keyid
+ // [0].value.b - algo
+ // [1].memref - input data (serialized key/input/iv/tag/aad)
+ // returned:
+ // [0].value.a - output size
+ // [2].memref - output (decrypted data)
+
+ if (key.size() != KM_KEY_ID_SIZE) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ Backend received incorrect key buffer");
+ }
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.input_size = static_cast<uint32_t>(data.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.iv_size = static_cast<uint32_t>(iv.size());
+ bufSize.key_id_size = static_cast<uint32_t>(key.size());
+ bufSize.with_ae_data = true;
+ bufSize.aad_size = static_cast<uint32_t>(aad.size());
+ bufSize.tag_size = static_cast<uint32_t>(tag.size());
+ uint32_t inMemorySize = KM_CalcBufferSize(bufSize);
+ TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT);
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.out_size = static_cast<uint32_t>(data.size());
+ 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 crypto operations");
+ }
+
+ ret = KM_ParamsSerializeInputData(input, data.data(), data.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize input data for TZ crypto 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 crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeIVData(input, iv.data(), iv.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize IV data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeKeyId(input, key.data(), key.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key id data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeAEData(input, tagSizeBits, 0, aad.data(), aad.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize auth data for TZ crypto operation: ", ret);
+ }
+
+ ret = KM_ParamsSerializeTagData(input, tag.data(), tag.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize tag data for TZ crypto 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_AES_GCM;
+ 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_DECRYPT, &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);
+ }
+
+ out.resize(outData->data_size);
+ memcpy(out.data(), outData->data, outData->data_size);
+}
+
+void TrustZoneContext::executeDestroy(const RawBuffer &keyId)
+{
+ // command ID = CMD_DESTROY_KEY (from km_ta_defines.h)
+ //
+ // TEEC_Operation layout:
+ // input params:
+ // [1].memref - input data (serialized 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");
+ }
+
+ KM_BufferSizeDesc bufSize;
+
+ memset(&bufSize, 0, sizeof(KM_BufferSizeDesc));
+ bufSize.key_id_size = static_cast<uint32_t>(keyId.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: ", ret);
+ }
+
+ ret = KM_ParamsSerializeInputData(input, keyId.data(), keyId.size());
+ if (ret) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to serialize key ID to destroy: ", ret);
+ }
+
+ TEEC_Operation op;
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_OUTPUT, TEEC_MEMREF_WHOLE,
+ TEEC_NONE, TEEC_NONE);
+ op.params[1].memref.parent = inMemory.Get();
+ op.params[1].memref.offset = 0;
+ op.params[1].memref.size = inMemory.Get()->size;
+ Execute(CMD_DESTROY_KEY, &op);
+}
+
+void TrustZoneContext::Initialize()
+{
+ TEEC_Operation op;
+ TEEC_Result result;
+ uint32_t retOrigin;
+
+ op.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_NONE, TEEC_NONE);
+
+ result = TEEC_InitializeContext(nullptr, &m_Context);
+ if (result != TEEC_SUCCESS) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to initialize TEE context: ", result);
+ }
+ m_ContextInitialized = true;
+
+ result = TEEC_OpenSession(&m_Context, &m_Session, &KEY_MANAGER_TA_UUID, 0, nullptr, &op, &retOrigin);
+ if (result != TEEC_SUCCESS) {
+ ThrowErr(Exc::Crypto::InternalError, "Failed to open session to Key Manager TA: ", result);
+ }
+ m_SessionInitialized = true;
+}
+
+void TrustZoneContext::Destroy()
+{
+ if (m_SessionInitialized) {
+ TEEC_CloseSession(&m_Session);
+ m_SessionInitialized = false;
+ }
+
+ if (m_ContextInitialized) {
+ TEEC_FinalizeContext(&m_Context);
+ m_ContextInitialized = false;
+ }
+}
+
+void TrustZoneContext::Reload()
+{
+ Destroy();
+ Initialize();
+}
+
+void TrustZoneContext::Execute(tz_command commandID, TEEC_Operation* op)
+{
+ LogDebug("Executing TZ operation " << commandID);
+
+ TEEC_Result result = TEEC_InvokeCommand(&m_Session, static_cast<unsigned int>(commandID), op, NULL);
+ if (result != TEEC_SUCCESS) {
+ switch (result) {
+ case TEEC_ERROR_TARGET_DEAD:
+ Reload();
+ ThrowErr(Exc::Crypto::InternalError, "TA panicked while executing command ",
+ static_cast<unsigned int>(commandID));
+ case TEEC_ERROR_BAD_PARAMETERS:
+ ThrowErr(Exc::Crypto::InputParam, "Incorrect parameters provided to TA");
+ default:
+ ThrowErr(Exc::Crypto::InternalError, "TA failed to invoke command ",
+ static_cast<unsigned int>(commandID), " with error: ", std::hex,
+ static_cast<unsigned int>(result));
+ }
+ }
+
+ 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);
+ }
+ }
+}
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file tz-context.h
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ */
+#pragma once
+
+#include <tee_client_api.h>
+#include <ckm/ckm-raw-buffer.h>
+#include <data-type.h>
+#include <km_ta_defines.h>
+#include <memory>
+#include <tz-backend/obj.h>
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+class TrustZoneContext final
+{
+public:
+ static TrustZoneContext& Instance();
+
+ void generateIV(uint32_t ivSize, RawBuffer &iv);
+ void generateSKey(tz_algo_type algo,
+ uint32_t keySizeBits,
+ RawBuffer &keyId);
+ void generateSKeyPwd(tz_algo_type algo,
+ const RawBuffer &pwd,
+ const RawBuffer &iv,
+ const uint32_t pwdKeySizeBits,
+ const uint32_t pwdTagSizeBits,
+ RawBuffer &keyId,
+ RawBuffer &pwdTag);
+ void importKey(tz_algo_type algo,
+ const RawBuffer &key,
+ const RawBuffer &pwd,
+ const RawBuffer &iv,
+ const uint32_t keySizeBits,
+ const uint32_t pwdTagSizeBits,
+ RawBuffer &keyId,
+ RawBuffer &pwdTag);
+
+ void executeCrypt(tz_command cmd,
+ tz_algo_type algo,
+ const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ const RawBuffer &data,
+ RawBuffer &out);
+
+ void executeEncryptAE(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &aad,
+ const RawBuffer &data,
+ RawBuffer &out,
+ RawBuffer &tag);
+ void executeDecryptAE(const RawBuffer &key,
+ const Pwd &pwd,
+ const RawBuffer &iv,
+ int tagSizeBits,
+ const RawBuffer &tag,
+ const RawBuffer &aad,
+ const RawBuffer &data,
+ RawBuffer &out);
+
+ void executeDestroy(const RawBuffer &keyId);
+
+private:
+ TrustZoneContext();
+ ~TrustZoneContext();
+ TrustZoneContext(const TrustZoneContext &other) = delete;
+ TrustZoneContext(TrustZoneContext &&other) = delete;
+
+ void Initialize();
+ void Destroy();
+ void Reload();
+
+ void Execute(tz_command commandID, TEEC_Operation* op);
+
+ TEEC_Context m_Context;
+ TEEC_Session m_Session;
+
+ bool m_ContextInitialized;
+ bool m_SessionInitialized;
+};
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file tz-memory.cpp
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ * @brief TrustZone Shared Memory wrapper definitions
+ */
+
+#include <tz-backend/tz-memory.h>
+#include <generic-backend/exception.h>
+#include <dpl/log/log.h>
+
+#include <cstring>
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+TrustZoneMemory::TrustZoneMemory(TEEC_Context context, const size_t size, const uint32_t flags)
+{
+ Allocate(context, size, flags);
+}
+
+TrustZoneMemory::~TrustZoneMemory()
+{
+ Release();
+}
+
+void TrustZoneMemory::Allocate(TEEC_Context context, const size_t size, const uint32_t flags)
+{
+ m_SharedMemory.size = size;
+ m_SharedMemory.flags = flags;
+
+ LogDebug("Allocating " << size << " bytes of shared TZ memory, flags: " << flags);
+ TEEC_Result result = TEEC_AllocateSharedMemory(&context, &m_SharedMemory);
+ if (result != TEEC_SUCCESS) {
+ ThrowErr(Exc::Crypto::InternalError, "TZ failed to register memory: ",
+ static_cast<uint32_t>(result));
+ }
+
+ memset(m_SharedMemory.buffer, 0, m_SharedMemory.size);
+}
+
+TEEC_SharedMemory* TrustZoneMemory::Get() const
+{
+ return &m_SharedMemory;
+}
+
+void TrustZoneMemory::Release()
+{
+ TEEC_ReleaseSharedMemory(&m_SharedMemory);
+}
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
--- /dev/null
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file tz-memory.h
+ * @author Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version 1.0
+ * @brief TrustZone Shared Memory wrapper declaration
+ */
+
+#pragma once
+
+#include <tee_client_api.h>
+
+namespace CKM {
+namespace Crypto {
+namespace TZ {
+namespace Internals {
+
+class TrustZoneMemory final
+{
+public:
+ TrustZoneMemory(TEEC_Context context, const size_t size, const uint32_t flags);
+ TrustZoneMemory(const TrustZoneMemory&) = delete;
+ TrustZoneMemory(TrustZoneMemory &&) = delete;
+ TrustZoneMemory& operator=(const TrustZoneMemory&) = delete;
+ TrustZoneMemory& operator=(TrustZoneMemory &&) = delete;
+ ~TrustZoneMemory();
+
+ TEEC_SharedMemory* Get() const;
+
+private:
+ void Allocate(TEEC_Context context, const size_t size, const uint32_t flags);
+ void Release();
+
+ mutable TEEC_SharedMemory m_SharedMemory;
+};
+
+} // namespace Internals
+} // namespace TZ
+} // namespace Crypto
+} // namespace CKM
${KEY_MANAGER_PATH}/crypto/sw-backend/store.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/obj.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/store.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/internals.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-context.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-memory.cpp
${KEY_MANAGER_PATH}/dpl/core/src/assert.cpp
${KEY_MANAGER_PATH}/dpl/core/src/colors.cpp
${KEY_MANAGER_PATH}/dpl/core/src/errno_string.cpp
${KEY_MANAGER_DEP_LIBRARIES}
${TARGET_ENCRYPTION_SCHEME_COMMON}
boost_unit_test_framework
+ teec km_serialization
-ldl
)
cynara-client-async
cynara-creds-socket
security-manager
+ tef-libteec
)
FIND_PACKAGE(Threads REQUIRED)
${KEY_MANAGER_PATH}/crypto/sw-backend/internals.cpp
${KEY_MANAGER_PATH}/crypto/sw-backend/obj.cpp
${KEY_MANAGER_PATH}/crypto/sw-backend/store.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/internals.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/obj.cpp
${KEY_MANAGER_PATH}/crypto/tz-backend/store.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-context.cpp
+ ${KEY_MANAGER_PATH}/crypto/tz-backend/tz-memory.cpp
${KEY_MANAGER_PATH}/dpl/core/src/assert.cpp
${KEY_MANAGER_PATH}/dpl/db/src/naive_synchronization_object.cpp
${KEY_MANAGER_PATH}/dpl/db/src/sql_connection.cpp
${CMAKE_THREAD_LIBS_INIT}
${CKM_DB_TOOL_DEP_LIBRARIES}
${TARGET_KEY_MANAGER_COMMON}
+ teec km_serialization
-ldl
)