summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Swierczek <t.swierczek@samsung.com>2018-09-26 11:18:43 +0200
committerTomasz Swierczek <t.swierczek@samsung.com>2018-09-26 16:32:46 +0200
commit2ff75c9bc6dbaaf7d521edfe393b84a8a1186f45 (patch)
treed555b57658840a6bab66d5bd1d1abcc720359654
parent3cadb98befc315f3e414d38e7cf6d3cfd049b9a7 (diff)
downloadkey-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.cpp10
-rw-r--r--src/manager/crypto/tz-backend/internals.cpp31
-rw-r--r--src/manager/crypto/tz-backend/internals.h11
-rw-r--r--src/manager/crypto/tz-backend/store.cpp34
-rw-r--r--src/manager/crypto/tz-backend/tz-context.cpp280
-rw-r--r--src/manager/crypto/tz-backend/tz-context.h14
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;