tz-backend: Implement symmetric encryption through TA 17/118617/8
authorLukasz Kostyra <l.kostyra@samsung.com>
Tue, 25 Jul 2017 12:59:49 +0000 (14:59 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Tue, 28 Nov 2017 13:27:46 +0000 (14:27 +0100)
Change-Id: Id1b563f099e1671fb5fbcca9ca08757b34b1dfd8

19 files changed:
packaging/key-manager.spec
src/CMakeLists.txt
src/manager/crypto/generic-backend/algo-validation.h
src/manager/crypto/generic-backend/crypto-params.h [new file with mode: 0644]
src/manager/crypto/platform/decider.cpp
src/manager/crypto/sw-backend/internals.cpp
src/manager/crypto/sw-backend/store.cpp
src/manager/crypto/tz-backend/internals.cpp [new file with mode: 0644]
src/manager/crypto/tz-backend/internals.h [new file with mode: 0644]
src/manager/crypto/tz-backend/obj.cpp
src/manager/crypto/tz-backend/obj.h
src/manager/crypto/tz-backend/store.cpp
src/manager/crypto/tz-backend/store.h
src/manager/crypto/tz-backend/tz-context.cpp [new file with mode: 0644]
src/manager/crypto/tz-backend/tz-context.h [new file with mode: 0644]
src/manager/crypto/tz-backend/tz-memory.cpp [new file with mode: 0644]
src/manager/crypto/tz-backend/tz-memory.h [new file with mode: 0644]
tests/CMakeLists.txt
tools/ckm_db_tool/CMakeLists.txt

index cf9518b..d953b27 100644 (file)
@@ -35,8 +35,12 @@ BuildRequires: pkgconfig(argos_watchdog)
 %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
index 9eeaab7..ea04f25 100644 (file)
@@ -20,6 +20,7 @@ PKG_CHECK_MODULES(KEY_MANAGER_DEP
     cynara-creds-socket
     pkgmgr
     vconf
+    tef-libteec
     ${EXTRA_KM_DEPS}
     )
 FIND_PACKAGE(Threads REQUIRED)
@@ -77,6 +78,9 @@ SET(KEY_MANAGER_SOURCES
     ${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}
     )
@@ -112,6 +116,7 @@ TARGET_LINK_LIBRARIES(${TARGET_KEY_MANAGER}
     ${KEY_MANAGER_DEP_LIBRARIES}
     ${TARGET_KEY_MANAGER_COMMON}
     -ldl
+    km_serialization
     )
 
 ################################################################################
index b4621df..dc14966 100644 (file)
@@ -131,7 +131,7 @@ struct DefaultGetter {
 };
 
 template <>
-void DefaultGetter<RawBuffer>::Print(std::ostringstream &os,
+inline void DefaultGetter<RawBuffer>::Print(std::ostringstream &os,
                                                                         const RawBuffer &buffer)
 {
        os << "[" << buffer.size() << "B buffer]";
diff --git a/src/manager/crypto/generic-backend/crypto-params.h b/src/manager/crypto/generic-backend/crypto-params.h
new file mode 100644 (file)
index 0000000..ae23fba
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  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
index c986f4e..98bd69f 100644 (file)
@@ -16,6 +16,7 @@
 /*
  * @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()
index f37d2ef..b519e11 100644 (file)
@@ -40,6 +40,7 @@
 
 #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>
 
@@ -61,9 +62,6 @@ typedef std::unique_ptr<EVP_PKEY, std::function<void(EVP_PKEY *)>> EvpPkeyUPtr;
 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)
 {
@@ -107,7 +105,7 @@ typedef ParamCheck<ParamName::ALGO_TYPE,
 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,
@@ -720,7 +718,7 @@ RawBuffer symmetricEncrypt(const RawBuffer &key,
                                                          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);
@@ -754,7 +752,7 @@ RawBuffer symmetricDecrypt(const RawBuffer &key,
                                                          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);
index ca44df9..d9a7353 100644 (file)
@@ -24,6 +24,7 @@
 #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>
@@ -38,10 +39,6 @@ namespace SW {
 
 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,
@@ -74,7 +71,7 @@ RawBuffer passwordToKey(const Password &password, const RawBuffer &salt,
                                password.size(),
                                salt.data(),
                                salt.size(),
-                               ITERATIONS,
+                               Params::DERIVED_KEY_ITERATIONS,
                                result.size(),
                                result.data()))
                ThrowErr(Exc::InternalError, "PCKS5_PKKDF2_HMAC_SHA1 failed.");
@@ -109,7 +106,7 @@ RawBuffer unpack(const RawBuffer &packed, const Password &pass)
         * - 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;
 
@@ -129,13 +126,13 @@ RawBuffer pack(const RawBuffer &data, const Password &pass)
 
        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");
                }
diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp
new file mode 100644 (file)
index 0000000..bfb78d7
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ *  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
diff --git a/src/manager/crypto/tz-backend/internals.h b/src/manager/crypto/tz-backend/internals.h
new file mode 100644 (file)
index 0000000..c8af8c7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ *  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
index b1109b7..81aabaa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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
index 424563c..f3459c1 100644 (file)
  */
 /*
  * @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
index e878b45..76cb253 100644 (file)
  */
 /*
  * @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
index bb61607..2eddfbe 100644 (file)
@@ -15,7 +15,7 @@
  */
 /*
  * @file       store.h
- * @author     BartÅ‚omiej Grzelewski (b.grzelewski@samsung.com)
+ * @author     Lukasz Kostyra (l.kostyra@samsung.com)
  * @version    1.0
  */
 #pragma once
@@ -34,10 +34,13 @@ public:
        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
diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp
new file mode 100644 (file)
index 0000000..7a59fbe
--- /dev/null
@@ -0,0 +1,810 @@
+/*
+ *  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
diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h
new file mode 100644 (file)
index 0000000..44ad38c
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ *  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
diff --git a/src/manager/crypto/tz-backend/tz-memory.cpp b/src/manager/crypto/tz-backend/tz-memory.cpp
new file mode 100644 (file)
index 0000000..1f76e41
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  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
diff --git a/src/manager/crypto/tz-backend/tz-memory.h b/src/manager/crypto/tz-backend/tz-memory.h
new file mode 100644 (file)
index 0000000..e4f559c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  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
index 5431f8e..e90d8d7 100644 (file)
@@ -79,6 +79,9 @@ SET(TEST_MERGED_SOURCES
     ${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
@@ -109,6 +112,7 @@ TARGET_LINK_LIBRARIES(${TARGET_TEST_MERGED}
     ${KEY_MANAGER_DEP_LIBRARIES}
     ${TARGET_ENCRYPTION_SCHEME_COMMON}
     boost_unit_test_framework
+    teec km_serialization
     -ldl
     )
 
index cd8d413..40de878 100644 (file)
@@ -12,6 +12,7 @@ PKG_CHECK_MODULES(CKM_DB_TOOL_DEP
     cynara-client-async
     cynara-creds-socket
     security-manager
+    tef-libteec
     )
 
 FIND_PACKAGE(Threads REQUIRED)
@@ -38,7 +39,11 @@ SET(CKM_DB_TOOL_SOURCES
     ${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
@@ -82,6 +87,7 @@ TARGET_LINK_LIBRARIES(${CKM_DB_TOOL}
     ${CMAKE_THREAD_LIBS_INIT}
     ${CKM_DB_TOOL_DEP_LIBRARIES}
     ${TARGET_KEY_MANAGER_COMMON}
+    teec km_serialization
     -ldl
     )