diff options
author | Tomasz Swierczek <t.swierczek@samsung.com> | 2018-09-26 11:18:43 +0200 |
---|---|---|
committer | Tomasz Swierczek <t.swierczek@samsung.com> | 2018-09-26 16:32:46 +0200 |
commit | 2ff75c9bc6dbaaf7d521edfe393b84a8a1186f45 (patch) | |
tree | d555b57658840a6bab66d5bd1d1abcc720359654 | |
parent | 3cadb98befc315f3e414d38e7cf6d3cfd049b9a7 (diff) | |
download | key-manager-2ff75c9bc6dbaaf7d521edfe393b84a8a1186f45.tar.gz key-manager-2ff75c9bc6dbaaf7d521edfe393b84a8a1186f45.tar.bz2 key-manager-2ff75c9bc6dbaaf7d521edfe393b84a8a1186f45.zip |
Add support for TrustZone backend data storage
Change-Id: Idfd0909d03e40b7e5cd5aeb1116b844be1901cf1
-rw-r--r-- | src/manager/crypto/platform/decider.cpp | 10 | ||||
-rw-r--r-- | src/manager/crypto/tz-backend/internals.cpp | 31 | ||||
-rw-r--r-- | src/manager/crypto/tz-backend/internals.h | 11 | ||||
-rw-r--r-- | src/manager/crypto/tz-backend/store.cpp | 34 | ||||
-rw-r--r-- | src/manager/crypto/tz-backend/tz-context.cpp | 280 | ||||
-rw-r--r-- | src/manager/crypto/tz-backend/tz-context.h | 14 |
6 files changed, 367 insertions, 13 deletions
diff --git a/src/manager/crypto/platform/decider.cpp b/src/manager/crypto/platform/decider.cpp index a2f16e2f..a7e6b32f 100644 --- a/src/manager/crypto/platform/decider.cpp +++ b/src/manager/crypto/platform/decider.cpp @@ -76,13 +76,13 @@ CryptoBackend chooseCryptoBackend(DataType data, if (encrypted) return CryptoBackend::OpenSSL; - // Only software backend allows for key export - if (policy.extractable) + // tz-backend allows only for data binary export + if (policy.extractable && !data.isBinaryData()) return CryptoBackend::OpenSSL; - // Use TrustZone only with symmetric keys until asymmetric - // cryptography is implemented - if (!data.isSKey()) + // Use TrustZone only with symmetric keys or unencrypted binary + // data until asymmetric cryptography is implemented + if (!data.isSKey() && !data.isBinaryData()) return CryptoBackend::OpenSSL; try { diff --git a/src/manager/crypto/tz-backend/internals.cpp b/src/manager/crypto/tz-backend/internals.cpp index d2753bc3..578241dc 100644 --- a/src/manager/crypto/tz-backend/internals.cpp +++ b/src/manager/crypto/tz-backend/internals.cpp @@ -136,6 +136,37 @@ RawBuffer importKey(const Data &data, return result; } + +RawBuffer importData(const Data &data, + const Password &pwd, + const RawBuffer &iv, + RawBuffer &tag) +{ + RawBuffer result; + RawBuffer pwdBuf(pwd.begin(), pwd.end()); + TrustZoneContext::Instance().importData(data.data, + pwdBuf, + iv, + result, + tag); + return result; +} + +RawBuffer getData(const RawBuffer &dataId, + const Pwd &pwd) +{ + RawBuffer result; + TrustZoneContext::Instance().getData(dataId, + pwd, + result); + return result; +} + +void destroyData(const RawBuffer &dataId) +{ + TrustZoneContext::Instance().destroyData(dataId); +} + BufferPair encryptDataAesGcm(const RawBuffer &key, const Pwd &pwd, const RawBuffer &iv, diff --git a/src/manager/crypto/tz-backend/internals.h b/src/manager/crypto/tz-backend/internals.h index c8af8c74..d9748e94 100644 --- a/src/manager/crypto/tz-backend/internals.h +++ b/src/manager/crypto/tz-backend/internals.h @@ -49,6 +49,17 @@ RawBuffer importKey(const Data &key, const Password &pwd, const RawBuffer &iv, RawBuffer &tag); + +RawBuffer importData(const Data &data, + const Password &pwd, + const RawBuffer &iv, + RawBuffer &tag); + +RawBuffer getData(const RawBuffer &dataId, + const Pwd &pwd); + +void destroyData(const RawBuffer &dataId); + void destroyKey(const RawBuffer &key); RawBuffer symmetricEncrypt( diff --git a/src/manager/crypto/tz-backend/store.cpp b/src/manager/crypto/tz-backend/store.cpp index 76cb253c..3d0179b0 100644 --- a/src/manager/crypto/tz-backend/store.cpp +++ b/src/manager/crypto/tz-backend/store.cpp @@ -101,20 +101,22 @@ Store::Store(CryptoBackend backendId) : GObjUPtr Store::getObject(const Token &token, const Password &pass) { int scheme; - RawBuffer data; + RawBuffer id; RawBuffer iv; RawBuffer tag; - unpack(token.data, scheme, data, iv, tag); + unpack(token.data, scheme, id, iv, tag); // TODO AKeys - if (token.dataType == DataType(DataType::KEY_AES)) - return make_unique<SKey>(scheme, data, Pwd(pass, iv, tag), token.dataType); + if (token.dataType.isSKey()) + return make_unique<SKey>(scheme, id, 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); + if (token.dataType.isBinaryData()) { + RawBuffer exported_data = Internals::getData(id, Pwd(pass, iv, tag)); + return make_unique<BData>(scheme, exported_data, Pwd(pass, iv, tag), token.dataType); + } ThrowErr(Exc::Crypto::DataTypeNotSupported, "This type of data is not supported by trustzone backend: ", (int)token.dataType); @@ -142,6 +144,17 @@ Token Store::generateSKey(const CryptoAlgorithm &alg, const Password &pass) Token Store::import(const Data &data, const Password &pass) { + if (data.type.isBinaryData()) { + RawBuffer iv; + RawBuffer tag; + if (!pass.empty()) { + // IV is needed for data encryption with pwd + iv = Internals::generateIV(); + } + RawBuffer dataId = Internals::importData(data, pass, iv, tag); + return Token(m_backendId, data.type, pack(dataId, pass, iv, tag)); + } + if (!data.type.isKey()) ThrowErr(Exc::Crypto::InputParam, "Invalid data provided for import"); @@ -168,8 +181,13 @@ Token Store::importEncrypted(const Data &, const Password &, void Store::destroy(const Token &token) { - RawBuffer data = unpackData(token.data); - Internals::destroyKey(data); + RawBuffer id = unpackData(token.data); + if (token.dataType.isBinaryData()) { + // TODO this should be a generic "destroy persistent memory object" once + // serialization in key-manager-ta is unified + Internals::destroyData(id); + } + Internals::destroyKey(id); } } // namespace TZ diff --git a/src/manager/crypto/tz-backend/tz-context.cpp b/src/manager/crypto/tz-backend/tz-context.cpp index e088163f..60dcd805 100644 --- a/src/manager/crypto/tz-backend/tz-context.cpp +++ b/src/manager/crypto/tz-backend/tz-context.cpp @@ -48,6 +48,21 @@ const uint32_t CIPHER_EXTRA_PADDING_SIZE = 16; // Identifier of our TA const TEEC_UUID KEY_MANAGER_TA_UUID = KM_TA_UUID; +//raw to hex string conversion to print persistent storage data ID +static std::string rawToHexString(const RawBuffer &raw) +{ + std::string dump; + + for (auto &e : raw) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02x", (e & 0xff)); + dump.push_back(buf[0]); + dump.push_back(buf[1]); + } + + return dump; +} + } // anonymous namespace TrustZoneContext::TrustZoneContext() @@ -729,6 +744,271 @@ void TrustZoneContext::executeDestroy(const RawBuffer &keyId) Execute(CMD_DESTROY_KEY, &op); } +void TrustZoneContext::importData(const RawBuffer &data, + const RawBuffer &pwd, + const RawBuffer &iv, + RawBuffer &dataId, + RawBuffer &pwdTag) +{ + // command ID = CMD_IMPORT_DATA + // input: + // [1].memref - reference to serialized buffer: + // KM_BinaryData with binary data + // uint32_t boolean value - true if password is provided + // KM_PwdData with password (optional) + // Output: + // [0].value.a - return code + // [2].memref - reference to serialized buffer: + // KM_BinaryData with data id + // KM_BinaryData with tag id (optional, if password was provided) + KM_BinaryData kmTaData; + uint32_t pwd_flag = pwd.empty() ? 0 : 1; + uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS; + kmTaData.data_size = static_cast<uint32_t>(data.size()); + kmTaData.data = const_cast<unsigned char *>(data.data()); + uint32_t inMemorySize = KM_SizeOfBinaryData(&kmTaData) + KM_SizeOfFlag(); + KM_PwdData kmPwdData; + if (pwd_flag) { + memset(&kmPwdData, 0, sizeof(KM_PwdData)); + kmPwdData.pwd = const_cast<unsigned char *>(pwd.data()); + kmPwdData.pwd_size = pwd.size(); + kmPwdData.iv = const_cast<unsigned char *>(iv.data()); + kmPwdData.iv_size = iv.size(); + kmPwdData.tag = NULL; + kmPwdData.tag_size = 0; + kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS; + kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS; + kmPwdData.tag_len_bits = pwdTagSizeBits; + + inMemorySize += KM_SizeOfPwdData(&kmPwdData); + } + + TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT); + void *inMemoryPtr = inMemory.Get()->buffer; + + int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmTaData); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + if (pwd_flag) { + ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + } + + KM_BinaryData kmDataId; + KM_BinaryData kmTag; + memset(&kmDataId, 0, sizeof(KM_BinaryData)); + memset(&kmTag, 0, sizeof(KM_BinaryData)); + kmDataId.data_size = KM_DATA_ID_SIZE; + uint32_t outMemorySize = KM_SizeOfBinaryData(&kmDataId); + if (pwd_flag) { + kmTag.data_size = pwdTagSizeBits / 8; + outMemorySize += KM_SizeOfBinaryData(&kmTag); + } + + TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT); + void *outMemoryPtr = outMemory.Get()->buffer; + + TEEC_Operation op; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, TEEC_NONE); + 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_IMPORT_DATA, &op); + + ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmDataId); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret); + } + dataId.resize(kmDataId.data_size); + memcpy(dataId.data(), kmDataId.data, kmDataId.data_size); + if (pwd_flag) { + ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmTag); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", ret); + } + pwdTag.resize(kmTag.data_size); + memcpy(pwdTag.data(), kmTag.data, kmTag.data_size); + } + + LogDebug("Imported object ID is (hex): " << rawToHexString(dataId)); +} + +void TrustZoneContext::GetDataSize(const RawBuffer &dataId, uint32_t &dataSize) +{ + // command ID = CMD_GET_DATA_SIZE + // TA will decrypt data with password if provided + // Parameters: + // [1].memref - reference to serialized buffer: + // KM_BinaryData with object ID + // Output: + // [0].value.a - return code + // [0].value.b - size of buffer to be passed from CA + LogDebug("Object ID (passed to CMD_GET_DATA_SIZE) is (hex): " << rawToHexString(dataId)); + KM_BinaryData kmDataId; + kmDataId.data_size = static_cast<uint32_t>(dataId.size()); + kmDataId.data = const_cast<unsigned char *>(dataId.data()); + uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId); + TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT); + void *inMemoryPtr = inMemory.Get()->buffer; + int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to deserialize data, ret: ", 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_GET_DATA_SIZE, &op); + dataSize = op.params[0].value.b; +} + +void TrustZoneContext::getData(const RawBuffer &dataId, + const Pwd &pwd, + RawBuffer &data) +{ + // command ID = CMD_GET_DATA + // TA will decrypt data with password if provided + // Parameters: + // [1].memref - reference to serialized buffer: + // KM_BinaryData with object ID + // uint32_t boolean value - true if password is provided + // KM_PwdData with password (optional) + // Output: + // [0].value.a - return code + // [2].memref - reference to serialized buffer: + // KM_BinaryData with binary data + LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId)); + uint32_t data_size = 0; + GetDataSize(dataId, data_size); + + KM_BinaryData kmDataId; + kmDataId.data_size = static_cast<uint32_t>(dataId.size()); + kmDataId.data = const_cast<unsigned char *>(dataId.data()); + uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId) + KM_SizeOfFlag(); + uint32_t pwd_flag = pwd.getPassword().empty() ? 0 : 1; + uint32_t pwdTagSizeBits = Params::DEFAULT_AES_GCM_TAG_LEN_BITS; + + KM_PwdData kmPwdData; + if (pwd_flag) { + memset(&kmPwdData, 0, sizeof(KM_PwdData)); + kmPwdData.pwd = const_cast<unsigned char *>(pwd.getPassword().data()); + kmPwdData.pwd_size = pwd.getPassword().size(); + kmPwdData.iv = const_cast<unsigned char *>(pwd.getIV().data()); + kmPwdData.iv_size = pwd.getIV().size(); + kmPwdData.tag = const_cast<unsigned char *>(pwd.getTag().data()); + kmPwdData.tag_size = pwd.getTag().size(); + kmPwdData.derive_len_bits = Params::DERIVED_KEY_LENGTH_BITS; + kmPwdData.it_count = Params::DERIVED_KEY_ITERATIONS; + kmPwdData.tag_len_bits = pwdTagSizeBits; + + inMemorySize += KM_SizeOfPwdData(&kmPwdData); + } + + TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT); + void *inMemoryPtr = inMemory.Get()->buffer; + + int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + ret = KM_SerializeFlag(&inMemoryPtr, &inMemorySize, pwd_flag); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + if (pwd_flag) { + ret = KM_SerializePwdData(&inMemoryPtr, &inMemorySize, &kmPwdData); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + } + + KM_BinaryData kmExtractedData; + memset(&kmExtractedData, 0, sizeof(KM_BinaryData)); + kmExtractedData.data_size = data_size; + + uint32_t outMemorySize = KM_SizeOfBinaryData(&kmExtractedData); + uint32_t outMemorySize2 = outMemorySize; + + TrustZoneMemory outMemory(m_Context, outMemorySize, TEEC_MEM_OUTPUT); + void *outMemoryPtr = outMemory.Get()->buffer; + void *outMemoryPtr2 = outMemory.Get()->buffer; + + // requesting size is saved in this buffer + ret = KM_SerializeBinaryData(&outMemoryPtr2, &outMemorySize2, &kmExtractedData); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + + TEEC_Operation op; + op.paramTypes = TEEC_PARAM_TYPES(TEEC_VALUE_INOUT, TEEC_MEMREF_WHOLE, + TEEC_MEMREF_WHOLE, TEEC_NONE); + 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_GET_DATA, &op); + + ret = KM_DeserializeBinaryData(&outMemoryPtr, &outMemorySize, &kmExtractedData); + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", ret); + } + + data.resize(kmExtractedData.data_size); + memcpy(data.data(), kmExtractedData.data, kmExtractedData.data_size); +} + + +void TrustZoneContext::destroyData(const RawBuffer &dataId) +{ + // command ID = CMD_DESTROY_DATA + // TEEC_Operation parameters layout: + // input: + // [1].memref - reference to serialized buffer: + // KM_BinaryData with object ID + // output: + // [0].value.a - return code + LogDebug("Object ID (passed to CMD_GET_DATA) is (hex): " << rawToHexString(dataId)); + KM_BinaryData kmDataId; + kmDataId.data_size = static_cast<uint32_t>(dataId.size()); + kmDataId.data = const_cast<unsigned char *>(dataId.data()); + uint32_t inMemorySize = KM_SizeOfBinaryData(&kmDataId); + TrustZoneMemory inMemory(m_Context, inMemorySize, TEEC_MEM_INPUT); + void *inMemoryPtr = inMemory.Get()->buffer; + + int ret = KM_SerializeBinaryData(&inMemoryPtr, &inMemorySize, &kmDataId); + + if (ret) { + ThrowErr(Exc::Crypto::InternalError, "Failed to serialize data, ret: ", 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_DATA, &op); +} + void TrustZoneContext::Initialize() { TEEC_Operation op; diff --git a/src/manager/crypto/tz-backend/tz-context.h b/src/manager/crypto/tz-backend/tz-context.h index 86fe08bb..2dd2497b 100644 --- a/src/manager/crypto/tz-backend/tz-context.h +++ b/src/manager/crypto/tz-backend/tz-context.h @@ -81,6 +81,18 @@ public: void executeDestroy(const RawBuffer &keyId); + void importData(const RawBuffer &data, + const RawBuffer &pwd, + const RawBuffer &iv, + RawBuffer &dataId, + RawBuffer &pwdTag); + + void getData(const RawBuffer &dataId, + const Pwd &pwd, + RawBuffer &data); + + void destroyData(const RawBuffer &dataId); + private: TrustZoneContext(); ~TrustZoneContext(); @@ -91,6 +103,8 @@ private: void Destroy(); void Reload(); + void GetDataSize(const RawBuffer &dataId, uint32_t &dataSize); + void Execute(tz_command commandID, TEEC_Operation* op); TEEC_Context m_Context; |