This commit adds support for asymmetric key operations. Implemented changes are:
Asymmetric key generation, RSA OAEP encryption/decryption, RSA/DSA signing and
verification operations.
Note that this commit introduces support for RSA/DSA algorithms only. Moreover,
DSA is supported only with SHA1 digest. TA is supposed to run on GP API 1.0
version, which does not support Elliptic Curve algorithms, or other digest types
for DSA.
Change-Id: I4631ffe34597931c60d1c6fa5d66edb192d7712b
BuildRequires: cmake
BuildRequires: unified-ta-devkit
+BuildRequires: openssl
%description
Key Manager Trusted Application working in the ARMĀ® TrustZoneĀ® environment.
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
LOG("Invalid usage of deserialization.");
return -1;
}
+ data->data = NULL;
+ data->data_size = 0;
return KM_Deserialize(buffer, size_guard, &(data->data), &(data->data_size));
}
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4]);
+TEE_Result KM_ExecCmdGenerateRSAKey(TEE_Param param[4]);
+
+TEE_Result KM_ExecCmdGenerateDSAKey(TEE_Param param[4]);
+
TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4]);
TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4]);
TEE_Result KM_ExecCmdSign(TEE_Param param[4]);
+TEE_Result KM_ExecCmdVerify(TEE_Param param[4]);
+
TEE_Result KM_ExecCmdDestroyKey(TEE_Param param[4]);
TEE_Result KM_ExecCmdSaveData(TEE_Param param[4]);
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
#define TEE_ALG_AES_CTR TEE_ALG_AES_CTR_NOPAD
#endif // TEF_BUILD_SIMULATOR
+const uint32_t AES_BLOCK_SIZE;
+
int KM_CheckAuthAESMode(uint32_t algo, uint32_t tagLen);
TEE_Result KM_CreateKey(uint32_t tee_key_type, uint32_t key_bits_size, void *key,
TEE_ObjectHandle *hndl);
-TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size, TEE_ObjectHandle *hndl);
+TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size,
+ const TEE_Attribute *params, size_t paramsCount,
+ TEE_ObjectHandle *hndl);
+
+TEE_Result KM_CreateKeyFromKey(uint32_t tee_key_type, uint32_t key_bits_size,
+ TEE_ObjectHandle srcHndl, TEE_ObjectHandle *dstHndl);
-TEE_Result KM_EncryptDataWithPwd(KM_PwdData *pwd, void *in, size_t in_size,
+TEE_Result KM_EncryptDataWithPwd(const KM_PwdData *pwd, void *in, size_t in_size,
void *out, uint32_t *out_size, void *tag, uint32_t *tag_size);
TEE_Result KM_EncryptKey(TEE_ObjectHandle keyHndl, KM_PwdData *pwd, TEE_ObjectHandle *encKeyHndl,
void *tag, uint32_t *tag_size);
+TEE_Result KM_EncryptAsymKey(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
+ KM_BinaryData *encKey, KM_BinaryData *tag);
+
TEE_Result KM_DecryptImportedData(KM_BinaryData *iv, KM_BinaryData *tag,
KM_BinaryData *input, KM_BinaryData *output);
-TEE_Result KM_DecryptDataWithPwd(KM_PwdData* pwd, void *in, size_t in_size,
+TEE_Result KM_DecryptDataWithPwd(const KM_PwdData* pwd, void *in, size_t in_size,
void *out, uint32_t *out_size);
TEE_Result KM_DecryptKey(void *id, size_t id_size, KM_PwdData* pwd, TEE_ObjectHandle *decKeyHndl);
+TEE_Result KM_DecryptAsymKey(const KM_KeyId *id, KM_PwdData *pwd,
+ TEE_ObjectHandle *decKeyHndl);
+
TEE_Result KM_CreateOperation(TEE_ObjectHandle op_key_hndl, uint32_t algo,
uint32_t mode, TEE_OperationHandle *hndl);
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
*/
typedef enum {
CMD_NOP = 0,
- CMD_GENERATE_KEY, ///< Generate random key.
+ CMD_GENERATE_KEY, ///< Generate random symmetric key.
///< Parameters:
///< [0].value.a - algorithm type (tz_algo_type)
///< [0].value.b - key size in bits
///< KM_ParamsSerializeInputData with data to encrypt
///< KM_ParamsSerializeIVData with iv of key
///< KM_ParamsSerializePwdData with password to key
- ///< necessary if key is encryted
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///<
///< For ALGO_RSA:
///< KM_ParamsSerializeInputData with data to encrypt
+ ///< KM_ParamsSerializePwdData with password to key
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///<
///< For other algorithms:
///< KM_ParamsSerializeInputData with data to encrypt
///< KM_ParamsSerializeIVData with iv of key
///< KM_ParamsSerializePwdData with password to key
- ///< necessary if key is encryted
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///<
///< Output:
///< KM_ParamsSerializeInputData with data to decrypt
///< KM_ParamsSerializeIVData with iv of key
///< KM_ParamsSerializePwdData with password to key
- ///< necessary if key is encryted
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///< KM_ParamsSerializeTagData with tag from encryption
///<
///< For ALGO_RSA:
///< KM_ParamsSerializeInputData with data to encrypt
+ ///< KM_ParamsSerializePwdData with password to key
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///<
///< For other algorithms (symmetric):
///< KM_ParamsSerializeInputData with data to encrypt
///< KM_ParamsSerializeIVData with iv of key
///< KM_ParamsSerializePwdData with password to key
- ///< necessary if key is encryted
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///<
///< Output:
///<
CMD_SIGN, ///< TA sign data
- ///< Only for ALGO_RSA_SV|ALGO_DSA_SV|ALGO_ECDSA_SV
+ ///< Only for ALGO_RSA_SV|ALGO_DSA_SV
///< Parameters:
///< [0].value.a - algorithm type (tz_algo_type)
///< [0].value.b - hash type (tz_hash_type)
///< [1].memref - reference to serialized buffer:
///< KM_ParamsSerializeInputData with data to sign
+ ///< KM_ParamsSerializePwdData with password to key
+ ///< necessary if key is encrypted
///< KM_ParamsSerializeKeyId with key id
///< Output:
///< [0].value.a - return code
///< KM_ParamsSerializeOutData with signed data
CMD_VERIFY, ///< TA verify signature
- ///<
- ///< Not implemented
+ ///< Only for ALGO_RSA_SV|ALGO_DSA_SV
+ ///< Parameters:
+ ///< [0].value.a - algorithm type (tz_algo_type)
+ ///< [0].value.b - hash type (tz_hash_type)
+ ///< [1].memref - reference to serialized buffer:
+ ///< KM_ParamsSerializeInputData with verify data (signature hidden in Tag data)
+ ///< KM_ParamsSerializePwdData with password to key
+ ///< necessary if key is encrypted
+ ///< KM_ParamsSerializeKeyId with key id
+ ///< Output:
+ ///< [0].value.a - return code
CMD_GENERATE_IV, ///< TA generate random IV
///< No parameters necessary.
///< [0].value.a - return code
///< [0].value.b - size of buffer to be passed from CA
- CMD_DESTROY_DATA ///< Key Manager binary data removal from persistent storage
+ CMD_DESTROY_DATA, ///< Key Manager binary data removal from persistent storage
///< Parameters:
///< [1].memref - reference to serialized buffer:
///< KM_BinaryData with object ID
///< Output:
///< [0].value.a - return code
+
+ CMD_GENERATE_RSA_KEYPAIR, ///< Generate random RSA key pair.
+ ///< Parameters:
+ ///< [0].value.a - algorithm type (tz_algo_type)
+ ///< [0].value.b - key size in bits
+ ///< [1].memref - reference to serialized buffer:
+ ///< flag marking the public key password presence
+ ///< public key password data if the flag above is not 0
+ ///< flag marking the private key password presence
+ ///< public key private data if the flag above is not 0
+ ///< Output:
+ ///< [0].value.a - return code
+ ///< [2].memref - reference to serialized buffer:
+ ///< Public key ID
+ ///< public key tag if password was present
+ ///< Private key ID
+ ///< private key tag if password was present
+
+ CMD_GENERATE_DSA_KEYPAIR, ///< Generate random DSA key pair.
+ ///< Parameters:
+ ///< [0].value.a - algorithm type (tz_algo_type)
+ ///< [0].value.b - key size in bits
+ ///< [1].memref - reference to serialized buffer:
+ ///< prime, subprime, base
+ ///< flag marking the public key password presence
+ ///< public key password data if the flag above is not 0
+ ///< flag marking the private key password presence
+ ///< public key private data if the flag above is not 0
+ ///< Output:
+ ///< [0].value.a - return code
+ ///< [2].memref - reference to serialized buffer:
+ ///< Public key ID
+ ///< public key tag if password was present
+ ///< Private key ID
+ ///< private key tag if password was present
} tz_command;
/** \enum tz_algo_type
HASH_SHA512,
} tz_hash_type;
+/** \enum tz_data_type
+ * \brief tz_data_type contains definitions of supported data types
+ *
+ * Each enum corresponds to type of data which can be stored on TA side.
+ */
typedef enum {
TYPE_GENERIC_SECRET,
TYPE_SKEY,
+ TYPE_AKEY_PRIVATE,
+ TYPE_AKEY_PUBLIC,
} tz_data_type;
// TODO these must be somehow confronted with TEE_OBJECT_ID_MAX_LEN
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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 ta_km.c
* @author RafaÅ Tyminski (r.tyminski@partner.samsung.com)
* @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
* @version 2.0
* @brief
*/
#include <stdlib.h>
+#include <malloc.h>
#include <tee_internal_api.h>
#include <km_ta_defines.h>
#include <internal.h>
// random value to mark unsupported algorithm
#define KM_TA_ALG_AES_CFB 0x50005050
-const uint32_t AES_BLOCK_SIZE = 16; // in bytes
const uint32_t RSA_BLOCK_SIZE = 512; // in bytes, assumes max RSA key size 4096 bits
const uint32_t PBKDF2_ITERATIONS = 1024;
const PaddingMode PADDING_MODE = KM_PADDING_PKCS7;
}
}
+static uint32_t KM_IsAsymCryptoKeyCorrect(uint32_t commandID, TEE_ObjectHandle key)
+{
+ TEE_ObjectInfo info;
+ TEE_GetObjectInfo(key, &info);
+
+ if (commandID == CMD_ENCRYPT && info.objectType == TEE_TYPE_RSA_PUBLIC_KEY) {
+ return 1;
+ } else if (commandID == CMD_DECRYPT && info.objectType == TEE_TYPE_RSA_KEYPAIR) {
+ return 1;
+ }
+
+ LOGD("Invalid key type provided for given command");
+ return 0;
+}
+
+static uint32_t KM_IsAsymSVKeyCorrect(uint32_t commandID, TEE_ObjectHandle key)
+{
+ TEE_ObjectInfo info;
+ TEE_GetObjectInfo(key, &info);
+
+ if (commandID == CMD_SIGN) {
+ switch (info.objectType) {
+ case TEE_TYPE_RSA_KEYPAIR:
+ case TEE_TYPE_DSA_KEYPAIR:
+ return 1;
+ default: break;
+ };
+ } else if (commandID == CMD_VERIFY) {
+ switch (info.objectType) {
+ case TEE_TYPE_RSA_PUBLIC_KEY:
+ case TEE_TYPE_DSA_PUBLIC_KEY:
+ return 1;
+ default: break;
+ };
+ }
+
+ LOGD("Invalid key type provided for given command");
+ return 0;
+}
+
static TEE_Result KM_DeserializeInput(void* buffer, uint32_t buffer_size, KM_SymmetricInput **input,
KM_InputData **input_data, KM_PwdData **pwd_data, KM_IVData **iv_data,
KM_KeyId **key_id_data, KM_AEData **ae_data, KM_TagData **tag_data)
}
}
+static uint32_t KM_SignatureSizeFromKey(TEE_ObjectHandle key)
+{
+ TEE_ObjectInfo info;
+ TEE_GetObjectInfo(key, &info);
+
+ return (info.objectSize + 7) >> 3;
+}
+
static uint32_t KM_CheckAlgoKeySize(uint32_t type, uint32_t key_size)
{
switch (type) {
case HASH_SHA256: return TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256;
case HASH_SHA384: return TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384;
case HASH_SHA512: return TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512;
- default: return 0; // TODO more SV algs unsupported
+ default: return 0;
}
}
case ALGO_DSA_SV: {
switch (hash) {
+ // TODO more SV algs are unsupported in GP API 1.0
case HASH_SHA1: return TEE_ALG_DSA_SHA1;
- default: return 0; // TODO more SV algs unsupported
+ default: return 0;
}
}
case ALGO_ECDSA_SV: {
- // TODO unsupported
+ // TODO unsupported in GP API 1.0
return 0;
}
default: return 0;
}
}
+static TEE_Result KM_DeserializeFlagAndPw(void **bufferPtr,
+ uint32_t *bufferSizeGuard,
+ uint32_t *hasPwd,
+ KM_PwdData *pwd)
+{
+ if (KM_DeserializeFlag(bufferPtr, bufferSizeGuard, hasPwd)) {
+ LOG("Failed to deserialize pwd flag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (*hasPwd) {
+ if (KM_DeserializePwdData(bufferPtr, bufferSizeGuard, pwd)) {
+ LOG("Failed to deserialize pub pwd data");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result KM_SerializeObjInfo(void **bufferPtr,
+ uint32_t *bufferSizeGuard,
+ const KM_BinaryData *objId,
+ uint32_t hasTag,
+ const KM_BinaryData *tag)
+{
+ if (KM_SerializeBinaryData(bufferPtr, bufferSizeGuard, objId) != 0) {
+ LOG("Failed to serialize object ID");
+ return TEE_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (hasTag) {
+ if (KM_SerializeBinaryData(bufferPtr, bufferSizeGuard, tag) != 0) {
+ LOG("Failed to serialize key tag");
+ return TEE_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ return TEE_SUCCESS;
+}
+
+static TEE_Result KM_SaveKeyGeneric(uint32_t isEncrypted,
+ const KM_BinaryData *encryptedObj,
+ TEE_ObjectHandle plainObjHandle,
+ const KM_BinaryData *objId)
+{
+ TEE_Result ret;
+
+ if (isEncrypted) {
+ ret = KM_SaveData(encryptedObj->data, encryptedObj->data_size, objId->data, objId->data_size);
+ } else {
+ ret = KM_SaveKey(NULL, 0, plainObjHandle, objId->data, objId->data_size);
+ }
+
+ if (TEE_SUCCESS != ret)
+ LOG("Failed to save key");
+
+ return ret;
+}
+
+static TEE_Result KM_AllocateObjId(KM_BinaryData *objId)
+{
+ if (objId == NULL) {
+ LOG("objId is NULL");
+ return TEE_ERROR_GENERIC;
+ }
+
+ objId->data_size = KM_KEY_ID_SIZE;
+ objId->data = malloc(objId->data_size);
+
+ if (objId->data == NULL) {
+ LOG("Failed to allocate object ID buffer");
+ return TEE_ERROR_OUT_OF_MEMORY;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result KM_AllocateRandomObjId(KM_BinaryData *objId)
+{
+ TEE_Result ret = KM_AllocateObjId(objId);
+ if (ret != TEE_SUCCESS)
+ return ret;
+
+ TEE_GenerateRandom(objId->data, objId->data_size);
+ return TEE_SUCCESS;
+}
+
+static TEE_Result KM_GenerateAsymKey(void *bufferPtr,
+ uint32_t bufferSizeGuard,
+ void *outBufferPtr,
+ uint32_t outBufferSizeGuard,
+ uint32_t privType,
+ uint32_t pubType,
+ uint32_t keyBitsSize,
+ const TEE_Attribute *params,
+ uint32_t paramsCount)
+{
+ TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectHandle privHndl = TEE_HANDLE_NULL;
+ TEE_ObjectHandle pubHndl = TEE_HANDLE_NULL;
+
+ uint32_t hasPubPwd = 0, hasPrivPwd = 0;
+ KM_BinaryData pubKeyTag, privKeyTag;
+ KM_BinaryData pubEncKey, privEncKey;
+ KM_PwdData pubKeyPwd, privKeyPwd;
+ KM_BinaryData pubObjId, privObjId;
+
+ // initialize
+ pubKeyTag.data = NULL;
+ pubKeyTag.data_size = 0;
+ privKeyTag.data = NULL;
+ privKeyTag.data_size = 0;
+ pubEncKey.data = NULL;
+ pubEncKey.data_size = 0;
+ privEncKey.data = NULL;
+ privEncKey.data_size = 0;
+ pubObjId.data = NULL;
+ pubObjId.data_size = 0;
+ privObjId.data = NULL;
+ privObjId.data_size = 0;
+
+ // check key size
+ if (!KM_CheckAlgoKeySize(privType, keyBitsSize)) {
+ LOG("Unsupported key size provided: %u", keyBitsSize);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeFlagAndPw(&bufferPtr, &bufferSizeGuard, &hasPubPwd, &pubKeyPwd);
+ if (ret != TEE_SUCCESS)
+ return ret;
+
+ ret = KM_DeserializeFlagAndPw(&bufferPtr, &bufferSizeGuard, &hasPrivPwd, &privKeyPwd);
+ if (ret != TEE_SUCCESS)
+ return ret;
+
+ // generate private key
+ ret = KM_CreateRandomKey(privType, keyBitsSize, params, paramsCount, &privHndl);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to randomize new key");
+ goto clean;
+ }
+
+ // copy public key from private
+ ret = KM_CreateKeyFromKey(pubType, keyBitsSize, privHndl, &pubHndl);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to create public key from private");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ // encrypt both keys if needed
+ if (hasPrivPwd) {
+ ret = KM_EncryptAsymKey(privHndl, &privKeyPwd, &privEncKey, &privKeyTag);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+ }
+
+ if (hasPubPwd) {
+ ret = KM_EncryptAsymKey(pubHndl, &pubKeyPwd, &pubEncKey, &pubKeyTag);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+ }
+
+ // generate object IDs
+ ret = KM_AllocateRandomObjId(&pubObjId);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ ret = KM_AllocateRandomObjId(&privObjId);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ // serialize output
+ ret = KM_SerializeObjInfo(&outBufferPtr, &outBufferSizeGuard, &pubObjId, hasPubPwd, &pubKeyTag);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ ret = KM_SerializeObjInfo(&outBufferPtr, &outBufferSizeGuard, &privObjId, hasPrivPwd, &privKeyTag);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ // save keys to persistent storage
+ ret = KM_SaveKeyGeneric(hasPubPwd, &pubEncKey, pubHndl, &pubObjId);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ ret = KM_SaveKeyGeneric(hasPrivPwd, &privEncKey, privHndl, &privObjId);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+clean:
+ if (ret != TEE_SUCCESS) {
+ KM_DestroyKey(pubObjId.data, pubObjId.data_size);
+ KM_DestroyKey(privObjId.data, privObjId.data_size);
+ }
+ TEE_FreeTransientObject(privHndl);
+ TEE_FreeTransientObject(pubHndl);
+
+ free(pubObjId.data);
+ free(privObjId.data);
+ free(pubEncKey.data);
+ free(privEncKey.data);
+ free(pubKeyTag.data);
+ free(privKeyTag.data);
+
+ return ret;
+}
+
+static TEE_Result KM_DeserializeAndGetAsymKey(TEE_Param param,
+ TEE_ObjectHandle *key,
+ KM_SymmetricInput **input,
+ KM_InputData **inputData,
+ KM_TagData **tagData)
+{
+ TEE_Result ret;
+ KM_PwdData *pwdData = NULL;
+ KM_KeyId *keyIdData = NULL;
+
+ ret = KM_DeserializeInput(param.memref.buffer, param.memref.size,
+ input, inputData, &pwdData, NULL,
+ &keyIdData, NULL, tagData);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to deserialize data from input buffer");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (!*inputData) {
+ LOG("There needs to be input data!");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (!keyIdData) {
+ LOG("There needs to be key id!");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // open key and (if needed) decrypt it
+ if (pwdData != NULL) {
+ ret = KM_DecryptAsymKey(keyIdData, pwdData, key);
+ } else {
+ ret = KM_OpenKey(keyIdData->data, keyIdData->data_size, NULL, key);
+ }
+
+ if (TEE_SUCCESS != ret)
+ LOG("Failed to get key, ret %x", ret);
+
+ return ret;
+}
+
+static TEE_Result KM_InputDataDigest(uint32_t hash,
+ const KM_InputData *inputData,
+ void **digest,
+ uint32_t *digestSize)
+{
+ TEE_Result ret;
+ TEE_OperationHandle digestOperation = TEE_HANDLE_NULL;
+ void* tmpDigest = NULL;
+ uint32_t tmpDigestSize = 0;
+
+ // create digest operation
+ ret = KM_CreateDigestOperation(KM_Hash2TeeAlgo(hash), &digestOperation);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to create digest operation");
+ return ret;
+ }
+
+ // allocate memory
+ tmpDigestSize = KM_DigestSizeFromHash(hash);
+ tmpDigest = malloc(tmpDigestSize);
+ if (tmpDigest == NULL) {
+ LOG("Failed to allocate buffer for digest");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ // calculate message digest
+ ret = KM_Digest(digestOperation, inputData->data, inputData->data_size,
+ tmpDigest, &tmpDigestSize);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to digest message");
+ goto clean;
+ }
+
+ *digest = tmpDigest;
+ *digestSize = tmpDigestSize;
+
+clean:
+ if (ret != TEE_SUCCESS)
+ free(tmpDigest);
+ TEE_FreeOperation(digestOperation);
+ return ret;
+}
+
TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
{
TEE_Result ret = TEE_SUCCESS;
KM_SymmetricInput *input = NULL;
uint32_t type = KM_AlgoType2TeeType(param[0].value.a);
- uint32_t key_bits_size = param[0].value.b;
+ uint32_t keyBitsSize = param[0].value.b;
uint32_t objId_size = KM_KEY_ID_SIZE;
uint32_t *objId = (uint32_t*)malloc(objId_size);
goto clean;
}
- if (!KM_CheckAlgoKeySize(type, key_bits_size)) {
- LOG("Unsupported key size provided: %u", key_bits_size);
+ if (!KM_CheckAlgoKeySize(type, keyBitsSize)) {
+ LOG("Unsupported key size provided: %u", keyBitsSize);
ret = TEE_ERROR_BAD_PARAMETERS;
goto clean;
}
- ret = KM_CreateRandomKey(type, key_bits_size, &hndl);
+ ret = KM_CreateRandomKey(type, keyBitsSize, NULL, 0, &hndl);
if (TEE_SUCCESS != ret) {
LOG("Failed to randomize new key");
goto clean;
goto clean;
}
- ret = KM_CreateRandomKey(type, key_bits_size, &key);
+ ret = KM_CreateRandomKey(type, key_bits_size, NULL, 0, &key);
if (TEE_SUCCESS != ret) {
LOG("Failed to randomize new key");
goto clean;
return ret;
}
+TEE_Result KM_ExecCmdGenerateRSAKey(TEE_Param param[4])
+{
+ return KM_GenerateAsymKey(param[1].memref.buffer,
+ param[1].memref.size,
+ param[2].memref.buffer,
+ param[2].memref.size,
+ TEE_TYPE_RSA_KEYPAIR,
+ TEE_TYPE_RSA_PUBLIC_KEY,
+ param[0].value.b,
+ NULL,
+ 0);
+}
+
+TEE_Result KM_ExecCmdGenerateDSAKey(TEE_Param param[4])
+{
+ TEE_Attribute dsaParams[3];
+ int ret;
+
+ void *bufferPtr = NULL;
+ uint32_t bufferSizeGuard = 0;
+ KM_BinaryData primeBuf, subprimeBuf, baseBuf;
+
+ // deserialize input data
+ bufferPtr = param[1].memref.buffer;
+ bufferSizeGuard = param[1].memref.size;
+
+ ret = KM_DeserializeBinaryData(&bufferPtr, &bufferSizeGuard, &primeBuf);
+ if (ret) {
+ LOG("Failed to deserialize DSA prime, ret = %x", ret);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeBinaryData(&bufferPtr, &bufferSizeGuard, &subprimeBuf);
+ if (ret) {
+ LOG("Failed to deserialize DSA subprime, ret = %x", ret);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeBinaryData(&bufferPtr, &bufferSizeGuard, &baseBuf);
+ if (ret) {
+ LOG("Failed to deserialize DSA base, ret = %x", ret);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // generate private key
+ TEE_InitRefAttribute(&dsaParams[0], TEE_ATTR_DSA_PRIME, primeBuf.data, primeBuf.data_size);
+ TEE_InitRefAttribute(&dsaParams[1], TEE_ATTR_DSA_SUBPRIME, subprimeBuf.data, subprimeBuf.data_size);
+ TEE_InitRefAttribute(&dsaParams[2], TEE_ATTR_DSA_BASE, baseBuf.data, baseBuf.data_size);
+
+ return KM_GenerateAsymKey(bufferPtr,
+ bufferSizeGuard,
+ param[2].memref.buffer,
+ param[2].memref.size,
+ TEE_TYPE_DSA_KEYPAIR,
+ TEE_TYPE_DSA_PUBLIC_KEY,
+ param[0].value.b,
+ dsaParams,
+ sizeof(dsaParams) / sizeof(*dsaParams));
+}
+
TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
{
TEE_Result ret = TEE_SUCCESS;
TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
{
TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
TEE_OperationHandle operation = TEE_HANDLE_NULL;
KM_SymmetricInput *input = NULL;
KM_InputData *input_data = NULL;
- KM_KeyId *key_id_data = NULL;
void *out = NULL;
uint32_t out_size = RSA_BLOCK_SIZE;
return TEE_ERROR_BAD_PARAMETERS;
}
- ret = KM_DeserializeInput(param[1].memref.buffer, param[1].memref.size,
- &input, &input_data, NULL, NULL,
- &key_id_data, NULL, NULL);
- if (ret != TEE_SUCCESS) {
- LOG("Failed to deserialize data from input buffer");
- return TEE_ERROR_BAD_PARAMETERS;
- }
-
- ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size,
- mode, algo, &operation);
- if (TEE_SUCCESS != ret) {
+ ret = KM_DeserializeAndGetAsymKey(param[1], &key, &input, &input_data, NULL);
+ if (ret != TEE_SUCCESS)
return ret;
+
+ // ensure key is correct
+ if (KM_IsAsymCryptoKeyCorrect(commandID, key) == 0) {
+ LOG("Provided key for asymmetric crypto operation is invalid");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
}
+ // memory for output
out = malloc(out_size);
if (out == NULL) {
LOG("Failed to allocate output buffer");
goto clean;
}
+ ret = KM_CreateOperation(key, algo, mode, &operation);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to allocate operation, ret %x", ret);
+ goto clean;
+ }
+
if (commandID == CMD_ENCRYPT)
ret = KM_AsymmetricEncrypt(operation, input_data->data, input_data->data_size,
out, &out_size);
out, &out_size);
if (TEE_SUCCESS != ret) {
+ LOG("Failed to perform asymmetric crypto operation: %x", ret);
goto clean;
}
if (0 != KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size, &input)
|| 0 != KM_ParamsSerializeOutData(input, out, out_size)) {
+ LOG("Failed to serialize encryption output");
ret = TEE_ERROR_BAD_PARAMETERS;
}
clean:
+ TEE_CloseObject(key);
+ TEE_FreeOperation(operation);
+
free(out);
- if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
+
return ret;
}
TEE_Result KM_ExecCmdSign(TEE_Param param[4])
{
TEE_Result ret = TEE_SUCCESS;
- TEE_OperationHandle digestOperation = TEE_HANDLE_NULL;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
TEE_OperationHandle operation = TEE_HANDLE_NULL;
KM_SymmetricInput *input = NULL;
- KM_InputData *input_data = NULL;
- KM_KeyId *key_id_data = NULL;
+ KM_InputData *inputData = NULL;
- void *digest = NULL;
- uint32_t digest_size = 0;
void *out = NULL;
- uint32_t out_size = 0;
- uint32_t out_size_pad = 0;
+ uint32_t outSize = 0;
+ void *digest = NULL;
+ uint32_t digestSize = 0;
uint32_t algo = KM_AlgoHash2SignVerifyAlgo(param[0].value.a, param[0].value.b);
return TEE_ERROR_BAD_PARAMETERS;
}
- ret = KM_DeserializeInput(param[1].memref.buffer, param[1].memref.size,
- &input, &input_data, NULL, NULL,
- &key_id_data, NULL, NULL);
- if (ret != TEE_SUCCESS) {
- LOG("Failed to deserialize data from input buffer");
- return TEE_ERROR_BAD_PARAMETERS;
- }
+ ret = KM_DeserializeAndGetAsymKey(param[1], &key, &input, &inputData, NULL);
+ if (ret != TEE_SUCCESS)
+ return ret;
- if (!input_data) {
- LOG("There needs to be InputData!");
- return TEE_ERROR_BAD_PARAMETERS;
+ // ensure key is correct
+ if (KM_IsAsymSVKeyCorrect(CMD_SIGN, key) == 0) {
+ LOG("Provided key for asymmetric crypto operation is invalid");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
}
- ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size,
- TEE_MODE_SIGN, algo, &operation);
-
- ret = KM_CreateDigestOperation(KM_Hash2TeeAlgo(param[0].value.b), &digestOperation);
- if (TEE_SUCCESS != ret) {
- LOG("Failed to create digest operation");
+ // calculate digest
+ ret = KM_InputDataDigest(param[0].value.b, inputData, &digest, &digestSize);
+ if (ret != TEE_SUCCESS)
goto clean;
- }
- digest_size = KM_DigestSizeFromHash(param[0].value.b);
- digest = malloc(digest_size);
- if (digest == NULL) {
- LOG("Failed to allocate buffer for digest");
- ret = TEE_ERROR_OUT_OF_MEMORY;
+ // create sign operation
+ ret = KM_CreateOperation(key, algo, TEE_MODE_SIGN, &operation);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to allocate operation, ret %x", ret);
goto clean;
}
- out_size_pad = RSA_BLOCK_SIZE;
- out_size = input_data->data_size + out_size_pad;
- out = malloc(out_size);
+ outSize = KM_SignatureSizeFromKey(key);
+ out = malloc(outSize);
if (out == NULL) {
LOG("Failed to allocate output buffer");
ret = TEE_ERROR_OUT_OF_MEMORY;
goto clean;
}
- ret = KM_Digest(digestOperation, input_data->data, input_data->data_size,
- digest, &digest_size);
- if (TEE_SUCCESS != ret) {
- goto clean;
- }
-
- ret = KM_AsymmetricSign(operation, digest, digest_size, out, &out_size);
+ // create signature
+ ret = KM_AsymmetricSign(operation, digest, digestSize, out, &outSize);
if (TEE_SUCCESS != ret) {
+ LOG("Failed to sign digested message");
goto clean;
}
if (0 != KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size, &input)
- || 0 != KM_ParamsSerializeOutData(input, out, out_size)) {
+ || 0 != KM_ParamsSerializeOutData(input, out, outSize)) {
+ LOG("Failed to serialize signature");
ret = TEE_ERROR_BAD_PARAMETERS;
}
clean:
free(out);
free(digest);
- if (digestOperation != TEE_HANDLE_NULL) TEE_FreeOperation(digestOperation);
- if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
+ TEE_FreeOperation(operation);
+ return ret;
+}
+
+TEE_Result KM_ExecCmdVerify(TEE_Param param[4])
+{
+ TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectHandle key = TEE_HANDLE_NULL;
+ TEE_OperationHandle operation = TEE_HANDLE_NULL;
+ KM_SymmetricInput *input = NULL;
+ KM_InputData *inputData = NULL;
+ KM_TagData *signatureData = NULL;
+
+ void *digest = NULL;
+ uint32_t digestSize = 0;
+
+ uint32_t algo = KM_AlgoHash2SignVerifyAlgo(param[0].value.a, param[0].value.b);
+
+ if (algo == 0) {
+ LOG("Unsupported algorithm provided: %u", algo);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DeserializeAndGetAsymKey(param[1], &key, &input, &inputData, &signatureData);
+ if (ret != TEE_SUCCESS)
+ return ret;
+
+ // ensure key is correct
+ if (KM_IsAsymSVKeyCorrect(CMD_VERIFY, key) == 0) {
+ LOG("Provided key for asymmetric crypto operation is invalid");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto clean;
+ }
+
+ // calculate digest
+ ret = KM_InputDataDigest(param[0].value.b, inputData, &digest, &digestSize);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ // create verify operation
+ ret = KM_CreateOperation(key, algo, TEE_MODE_VERIFY, &operation);
+ if (TEE_SUCCESS != ret) {
+ LOG("Failed to allocate operation, ret %x", ret);
+ goto clean;
+ }
+
+ // no check over here - return anything that TEE_AsymmetricVerifyDigest gives us
+ // return code will contain information whether the signature was correct or not
+ ret = KM_AsymmetricVerify(operation, digest, digestSize, signatureData->data, signatureData->data_size);
+
+clean:
+ free(digest);
+ TEE_FreeOperation(operation);
return ret;
}
LOG("Failed to save generated key");
goto clean;
}
+ } else if (dataTypeFlag == TYPE_AKEY_PRIVATE || dataTypeFlag == TYPE_AKEY_PUBLIC) {
+ LOG("Importing asymmetric keys is not yet implemented!");
+ ret = TEE_ERROR_NOT_IMPLEMENTED;
+ goto clean;
} else {
LOG("This data type(tz_algo_type=%u) is not supported by import methods.\n", dataTypeFlag);
ret = TEE_ERROR_BAD_PARAMETERS;
{
TEE_Result ret = TEE_SUCCESS;
- LOG("LKDEBUG Asym encrypt");
ret = TEE_AsymmetricEncrypt(hndl, NULL, 0, input, input_size, output, output_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricEncrypt has failed with=%x.", ret);
return ret;
}
- LOG("LKDEBUG Asym encrypt done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("LKDEBUG Asym decrypt");
ret = TEE_AsymmetricDecrypt(hndl, NULL, 0, input, input_size, output, output_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricEncrypt has failed with=%x.", ret);
return ret;
}
- LOG("LKDEBUG Asym decrypt done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("LKDEBUG Asym sign");
ret = TEE_AsymmetricSignDigest(hndl, NULL, 0, digest, digest_size, signature, sig_size);
if (TEE_SUCCESS != ret) {
LOG("TEE_AsymmetricSignDigest has failed with=%x.", ret);
return ret;
}
- LOG("LKDEBUG Asym sign done");
return ret;
}
{
TEE_Result ret = TEE_SUCCESS;
- LOG("LKDEBUG Asym verify");
ret = TEE_AsymmetricVerifyDigest(hndl, NULL, 0, digest, digest_size, signature, sig_size);
if (TEE_SUCCESS != ret && TEE_ERROR_SIGNATURE_INVALID != ret) {
LOG("TEE_AsymmetricVerifyDigest has failed with=%x.", ret);
return ret;
}
- LOG("LKDEBUG Asym verify done");
return ret;
}
\ No newline at end of file
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
#include <stdlib.h>
#include <string.h>
-extern const uint32_t AES_BLOCK_SIZE;
-
-
TEE_Result KM_SymmetricCrypt_AES_CFB(TEE_ObjectHandle key, uint32_t mode,
void *iv, uint32_t iv_size, void *input, uint32_t input_size,
void *output, uint32_t *output_size)
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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 internal.c
* @author RafaÅ Tyminski (r.tyminski@partner.samsung.com)
* @author Tomasz Swierczek (t.swierczek@samsung.com)
+ * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
* @version 2.0
* @brief
*/
#include <log.h>
#include <stdlib.h>
+#include <malloc.h>
#include <crypto_padding.h>
#include <crypto_derive.h>
#include <crypto_symmetric.h>
#define TEE_DATA_FLAG_OVERWRITE TEE_DATA_FLAG_EXCLUSIVE
#endif
+
+// below *_ATTRIBUTES arrays are used in KM_EncryptAsymKey to determine
+// which transient object attributes we want to encrypt. They are all listed
+// in GP API specification under TEE_PopulateTransientObject function
+// description and are all required for given type of object to exist.
+
+const uint32_t RSA_PRIVATE_ATTRIBUTES[] = {
+ TEE_ATTR_RSA_MODULUS,
+ TEE_ATTR_RSA_PUBLIC_EXPONENT,
+ TEE_ATTR_RSA_PRIVATE_EXPONENT,
+ // CRT attributes are ignored - tef-simulator doesn't fill them on TEE_GenerateKey call
+};
+const uint32_t RSA_PRIVATE_ATTRIBUTES_SIZE = sizeof(RSA_PRIVATE_ATTRIBUTES) / sizeof(RSA_PRIVATE_ATTRIBUTES[0]);
+
+const uint32_t RSA_PUBLIC_ATTRIBUTES[] = {
+ TEE_ATTR_RSA_MODULUS,
+ TEE_ATTR_RSA_PUBLIC_EXPONENT,
+};
+const uint32_t RSA_PUBLIC_ATTRIBUTES_SIZE = sizeof(RSA_PUBLIC_ATTRIBUTES) / sizeof(RSA_PUBLIC_ATTRIBUTES[0]);
+
+const uint32_t DSA_PRIVATE_ATTRIBUTES[] = {
+ TEE_ATTR_DSA_PRIME,
+ TEE_ATTR_DSA_SUBPRIME,
+ TEE_ATTR_DSA_BASE,
+ TEE_ATTR_DSA_PUBLIC_VALUE,
+ TEE_ATTR_DSA_PRIVATE_VALUE,
+};
+const uint32_t DSA_PRIVATE_ATTRIBUTES_SIZE = sizeof(DSA_PRIVATE_ATTRIBUTES) / sizeof(DSA_PRIVATE_ATTRIBUTES[0]);
+
+const uint32_t DSA_PUBLIC_ATTRIBUTES[] = {
+ TEE_ATTR_DSA_PRIME,
+ TEE_ATTR_DSA_SUBPRIME,
+ TEE_ATTR_DSA_BASE,
+ TEE_ATTR_DSA_PUBLIC_VALUE,
+};
+const uint32_t DSA_PUBLIC_ATTRIBUTES_SIZE = sizeof(DSA_PUBLIC_ATTRIBUTES) / sizeof(DSA_PUBLIC_ATTRIBUTES[0]);
+
+const uint32_t AES_BLOCK_SIZE = 16; // in bytes
+
int KM_CheckAuthAESMode(uint32_t algo, uint32_t tagLen)
{
LOGD("Auth aes tag len: %d for algo %x", tagLen, algo);
return ret;
}
-TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size, TEE_ObjectHandle *hndl)
+TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size,
+ const TEE_Attribute *params, size_t paramsCount,
+ TEE_ObjectHandle *hndl)
{
TEE_Result ret = TEE_SUCCESS;
return ret;
}
- ret = TEE_GenerateKey(*hndl, key_bits_size, NULL, 0);
+ ret = TEE_GenerateKey(*hndl, key_bits_size, params, paramsCount);
if (TEE_SUCCESS != ret) {
LOG("TEE_GenerateKey has failed with=%x.", ret);
TEE_FreeTransientObject(*hndl);
return ret;
}
-TEE_Result KM_EncryptDataWithPwd(KM_PwdData *pwd, void *in, size_t in_size,
+TEE_Result KM_CreateKeyFromKey(uint32_t tee_key_type, uint32_t key_bits_size,
+ TEE_ObjectHandle srcHndl, TEE_ObjectHandle *dstHndl)
+{
+ TEE_Result ret = TEE_SUCCESS;
+
+ ret = TEE_AllocateTransientObject(tee_key_type, key_bits_size, dstHndl);
+ if (TEE_SUCCESS != ret) {
+ LOG("TEE_AllocateTransientObject has failed with=%x. Arguments=(tee_key_type=%X, "
+ "key_bits_size=%d.", ret, tee_key_type, key_bits_size);
+ return ret;
+ }
+
+ TEE_CopyObjectAttributes(*dstHndl, srcHndl);
+ return ret;
+}
+
+TEE_Result KM_EncryptDataWithPwd(const KM_PwdData *pwd, void *in, size_t in_size,
void *out, uint32_t *out_size, void *tag, uint32_t *tag_size)
{
TEE_Result ret = TEE_SUCCESS;
out:
free(encKeyBuf);
free(keyBuf);
+
+ return ret;
+}
+
+static TEE_Result KM_GetAttribute(TEE_ObjectHandle keyHndl, uint32_t attrId, KM_BinaryData *attr)
+{
+ TEE_ObjectInfo objInfo;
+ TEE_Result ret;
+
+ if (attr == NULL) {
+ LOG("Attribute buffer is NULL");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ /*
+ * TODO current key size is used as maximum attribute size because prompting the size with NULL
+ * buffer in TEE_GetObjectBufferAttribute doesn't work in simulator.
+ */
+ TEE_GetObjectInfo(keyHndl, &objInfo);
+ if (((objInfo.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) ||
+ (objInfo.objectSize == 0)) {
+ LOG("Key provided for encryption is not initialized");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ attr->data_size = (objInfo.objectSize + 7) >> 3;
+ attr->data = malloc(attr->data_size);
+ if (attr->data == NULL) {
+ LOG("Failed to allocate memory for key attribute.");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ ret = TEE_GetObjectBufferAttribute(keyHndl, attrId, attr->data, &attr->data_size);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to get object buffer attribute info, ret = %x", ret);
+ }
+
+clean:
+ if (ret != TEE_SUCCESS) {
+ free(attr->data);
+ attr->data = NULL;
+ attr->data_size = 0;
+ }
+ return ret;
+}
+
+static TEE_Result KM_EncryptAsymKeyInternal(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
+ const uint32_t *attrIds, const uint32_t attrsCount,
+ KM_BinaryData *encKey, KM_BinaryData *tag)
+{
+ TEE_Result ret = TEE_SUCCESS;
+ TEE_ObjectInfo objInfo;
+ void* keyDataBuffer = NULL;
+ void* keyDataBufferPtr = NULL;
+ uint32_t keyDataBufferGuard = 0;
+ uint32_t i = 0;
+ uint32_t totalSize = 0;
+ KM_BinaryData attributes[attrsCount];
+ KM_BinaryData tmpEncKey;
+ KM_BinaryData tmpTag;
+
+ if (encKey == NULL) {
+ LOG("There's no buffer for encrypted key");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (tag == NULL) {
+ LOG("There's no buffer for encryption tag");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // initialize
+ for (i = 0; i < attrsCount; i++) {
+ attributes[i].data = NULL;
+ attributes[i].data_size = 0;
+ }
+
+ tmpEncKey.data = NULL;
+ tmpEncKey.data_size = 0;
+ tmpTag.data = NULL;
+ tmpTag.data_size = 0;
+
+ TEE_GetObjectInfo(keyHndl, &objInfo);
+ if (((objInfo.handleFlags & TEE_HANDLE_FLAG_INITIALIZED) == 0) ||
+ (objInfo.maxObjectSize == 0)) {
+ LOG("Key provided for encryption is not initialized");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ // get attributes and calculate required size for key data buffer
+ totalSize = 2 * KM_SizeOfFlag();
+ for (i = 0; i < attrsCount; ++i) {
+ ret = KM_GetAttribute(keyHndl, attrIds[i], &attributes[i]);
+ if (ret != TEE_SUCCESS)
+ goto clean;
+
+ totalSize += KM_SizeOfBinaryData(&attributes[i]);
+ }
+
+ // allocate key data buffer
+ keyDataBuffer = malloc(totalSize);
+ if (keyDataBuffer == NULL) {
+ LOG("Failed to allocate memory for key data");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ keyDataBufferGuard = totalSize;
+ keyDataBufferPtr = keyDataBuffer;
+
+ // serialize key type and object size
+ if (KM_SerializeFlag(&keyDataBufferPtr, &keyDataBufferGuard, objInfo.objectType)) {
+ LOG("Failed to serialize object type");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ if (KM_SerializeFlag(&keyDataBufferPtr, &keyDataBufferGuard, objInfo.maxObjectSize)) {
+ LOG("Failed to serialize object max size");
+ ret = TEE_ERROR_GENERIC;
+ goto clean;
+ }
+
+ for (i = 0; i < attrsCount; i++) {
+ if (KM_SerializeBinaryData(&keyDataBufferPtr, &keyDataBufferGuard, &attributes[i])) {
+ LOG("Failed to serialize binary data for encryption, attr %d", i);
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+ }
+
+ // allocate buffer for encrypted key
+ tmpEncKey.data_size = totalSize;
+ tmpEncKey.data = malloc(tmpEncKey.data_size);
+ if (tmpEncKey.data == NULL) {
+ LOG("Failed to allocate memory for encrypted key");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ // allocate buffer for tag
+ tmpTag.data_size = (pwd->tag_len_bits + 7) >> 3;
+ tmpTag.data = malloc(tmpTag.data_size);
+ if (tmpTag.data == NULL) {
+ LOG("Failed to allocate memory for key tag");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto clean;
+ }
+
+ // encrypt key data
+ ret = KM_EncryptDataWithPwd(pwd,
+ keyDataBuffer, totalSize,
+ tmpEncKey.data, &tmpEncKey.data_size,
+ tmpTag.data, &tmpTag.data_size);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to encrypt key: %x", ret);
+ goto clean;
+ }
+
+ encKey->data = tmpEncKey.data;
+ encKey->data_size = tmpEncKey.data_size;
+ tag->data = tmpTag.data;
+ tag->data_size = tmpTag.data_size;
+
+clean:
+ if (ret != TEE_SUCCESS) {
+ free(tmpEncKey.data);
+ free(tmpTag.data);
+ }
+
+ for (i = 0; i < attrsCount; i++) {
+ free(attributes[i].data);
+ }
+ free(keyDataBuffer);
+
return ret;
}
+static TEE_Result KM_CreateDecryptedAsymKey(void *data, uint32_t dataSize, uint32_t keyType,
+ const uint32_t *attrIDs,
+ const uint32_t attrsCount,
+ TEE_ObjectHandle *hndl)
+{
+ KM_BinaryData readAttr[attrsCount];
+ TEE_Attribute attributes[attrsCount];
+ TEE_Result ret = 0;
+ uint32_t i = 0;
+ uint32_t maxObjectSize = 0;
+
+ if (KM_DeserializeFlag(&data, &dataSize, &maxObjectSize)) {
+ LOG("Failed to deserialize object size");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ for (i = 0; i < attrsCount; ++i) {
+ if (KM_DeserializeBinaryData(&data, &dataSize, &readAttr[i])) {
+ LOG("Failed to deserialize attribute %d", i);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ TEE_InitRefAttribute(&attributes[i], attrIDs[i],
+ readAttr[i].data, readAttr[i].data_size);
+ }
+
+ ret = TEE_AllocateTransientObject(keyType, maxObjectSize, hndl);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to allocate transient object for new key, ret %x", ret);
+ return ret;
+ }
+
+ ret = TEE_PopulateTransientObject(*hndl, attributes, attrsCount);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to populate transient object for new key, ret %x", ret);
+ TEE_FreeTransientObject(*hndl);
+ *hndl = TEE_HANDLE_NULL;
+ return ret;
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result KM_DecryptAsymKeyData(const KM_KeyId *id,
+ const KM_PwdData *pwd,
+ KM_BinaryData *decKeyBuf)
+{
+ TEE_Result ret;
+ TEE_ObjectHandle hndl;
+ TEE_ObjectInfo info;
+ KM_BinaryData keyBuf, tmpDecKeyBuf;
+ uint32_t read;
+
+ // Read encrypted key from persistent storage
+ ret = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, id->data, id->data_size,
+ TEE_DATA_FLAG_ACCESS_READ, &hndl);
+ if (TEE_SUCCESS != ret) {
+ LOG("TEE_OpenPersistentObject has failed with=%x.", ret);
+ return ret;
+ }
+
+ TEE_GetObjectInfo(hndl, &info);
+
+ keyBuf.data_size = info.dataSize;
+ keyBuf.data = malloc(keyBuf.data_size);
+ if (keyBuf.data == NULL) {
+ LOG("Failed to allocate memory for encrypted key read");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ ret = TEE_ReadObjectData(hndl, keyBuf.data, keyBuf.data_size, &read);
+ if (TEE_SUCCESS != ret) {
+ LOG("TEE_ReadObjectData has failed with=%x.", ret);
+ goto out;
+ }
+ keyBuf.data_size = read;
+
+ // allocate memory for result
+ tmpDecKeyBuf.data_size = keyBuf.data_size;
+ tmpDecKeyBuf.data = malloc(tmpDecKeyBuf.data_size);
+ if (tmpDecKeyBuf.data == NULL) {
+ LOG("Failed to allocate memory for key decryption");
+ ret = TEE_ERROR_OUT_OF_MEMORY;
+ goto out;
+ }
+
+ // decrypt data
+ read = tmpDecKeyBuf.data_size;
+ ret = KM_DecryptDataWithPwd(pwd, keyBuf.data, keyBuf.data_size, tmpDecKeyBuf.data, &read);
+ if (ret != TEE_SUCCESS) {
+ LOG("Failed to decrypt key: %x", ret);
+ goto out;
+ }
+
+ decKeyBuf->data = tmpDecKeyBuf.data;
+ decKeyBuf->data_size = read;
+ tmpDecKeyBuf.data = NULL;
+ tmpDecKeyBuf.data_size = 0;
+
+out:
+ TEE_CloseObject(hndl);
+ free(keyBuf.data);
+ free(tmpDecKeyBuf.data);
+ return ret;
+}
+
+TEE_Result KM_EncryptAsymKey(TEE_ObjectHandle keyHndl, const KM_PwdData *pwd,
+ KM_BinaryData *encKey, KM_BinaryData *tag)
+{
+ TEE_ObjectInfo objInfo;
+
+ TEE_GetObjectInfo(keyHndl, &objInfo);
+
+ LOGD("Encrypt asym key object type %x", objInfo.objectType);
+
+ switch (objInfo.objectType) {
+ case TEE_TYPE_RSA_KEYPAIR:
+ return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+ RSA_PRIVATE_ATTRIBUTES, RSA_PRIVATE_ATTRIBUTES_SIZE,
+ encKey, tag);
+ break;
+ case TEE_TYPE_RSA_PUBLIC_KEY:
+ return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+ RSA_PUBLIC_ATTRIBUTES, RSA_PUBLIC_ATTRIBUTES_SIZE,
+ encKey, tag);
+ case TEE_TYPE_DSA_KEYPAIR:
+ return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+ DSA_PRIVATE_ATTRIBUTES, DSA_PRIVATE_ATTRIBUTES_SIZE,
+ encKey, tag);
+ case TEE_TYPE_DSA_PUBLIC_KEY:
+ return KM_EncryptAsymKeyInternal(keyHndl, pwd,
+ DSA_PUBLIC_ATTRIBUTES, DSA_PUBLIC_ATTRIBUTES_SIZE,
+ encKey, tag);
+ default:
+ LOG("Invalid object type provided for asymmetric key encryption");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
+
#ifdef SECRET_KEY_ENABLE
TEE_Result KM_DecryptImportedData(
KM_BinaryData *iv,
}
#endif
-TEE_Result KM_DecryptDataWithPwd(KM_PwdData* pwd, void *in, size_t in_size,
+TEE_Result KM_DecryptDataWithPwd(const KM_PwdData* pwd, void *in, size_t in_size,
void *out, uint32_t *out_size)
{
TEE_Result ret = TEE_SUCCESS;
return ret;
}
+TEE_Result KM_DecryptAsymKey(const KM_KeyId *id, KM_PwdData* pwd, TEE_ObjectHandle *decKeyHndl)
+{
+ TEE_Result ret = TEE_SUCCESS;
+ KM_BinaryData decKeyBuf;
+ uint32_t keyType = 0;
+ void *bufferPtr = NULL;
+ uint32_t bufferSizeGuard = 0;
+
+ decKeyBuf.data = NULL;
+ decKeyBuf.data_size = 0;
+
+ if (decKeyHndl == NULL) {
+ LOG("Output key handle not valid");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ ret = KM_DecryptAsymKeyData(id, pwd, &decKeyBuf);
+ if (ret != TEE_SUCCESS)
+ return ret;
+
+ // deserialize key type
+ bufferPtr = decKeyBuf.data;
+ bufferSizeGuard = decKeyBuf.data_size;
+
+ if (KM_DeserializeFlag(&bufferPtr, &bufferSizeGuard, &keyType)) {
+ LOG("Failed to get key type");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ goto out;
+ }
+
+ // deserialize rest of key and create a handle
+ switch (keyType) {
+ case TEE_TYPE_RSA_KEYPAIR:
+ ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+ RSA_PRIVATE_ATTRIBUTES, RSA_PRIVATE_ATTRIBUTES_SIZE, decKeyHndl);
+ break;
+ case TEE_TYPE_RSA_PUBLIC_KEY:
+ ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+ RSA_PUBLIC_ATTRIBUTES, RSA_PUBLIC_ATTRIBUTES_SIZE, decKeyHndl);
+ break;
+ case TEE_TYPE_DSA_KEYPAIR:
+ ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+ DSA_PRIVATE_ATTRIBUTES, DSA_PRIVATE_ATTRIBUTES_SIZE, decKeyHndl);
+ break;
+ case TEE_TYPE_DSA_PUBLIC_KEY:
+ ret = KM_CreateDecryptedAsymKey(bufferPtr, bufferSizeGuard, keyType,
+ DSA_PUBLIC_ATTRIBUTES, DSA_PUBLIC_ATTRIBUTES_SIZE, decKeyHndl);
+ break;
+ default:
+ LOG("Invalid object type provided for decrypted key creation");
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ break;
+ }
+
+out:
+ free(decKeyBuf.data);
+ return ret;
+}
+
TEE_Result KM_CreateOperation(TEE_ObjectHandle op_key_hndl, uint32_t algo,
uint32_t mode, TEE_OperationHandle *hndl)
{
TEE_GetObjectInfo(op_key_hndl, &info);
- LOGD("Operation key size: %d", info.objectSize);
+ LOGD("Operation key size: %d alg: %x", info.objectSize, algo);
ret = TEE_AllocateOperation(hndl, algo, mode, info.objectSize);
if (TEE_SUCCESS != ret) {
LOG("TEE_AllocateOperation has failed with=%x.", ret);
/*
- * Copyright (c) 2017 - 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2019 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.
#include <cmd_exec.h>
#include <log.h>
#include <internal.h>
+#include <openssl/evp.h>
TEE_Result TA_CreateEntryPoint(void)
{
ret = KM_ExecCmdSign(param);
break;
}
+ case CMD_VERIFY: {
+ LOGD("!!! Verify !!!");
+
+ if (ALGO_RSA_SV != param[0].value.a &&
+ ALGO_DSA_SV != param[0].value.a &&
+ ALGO_ECDSA_SV != param[0].value.a) {
+ LOG("Invalid key type=%d for command=%d.", param[0].value.a, commandID);
+ ret = TEE_ERROR_BAD_PARAMETERS;
+ break;
+ }
+
+ ret = KM_ExecCmdVerify(param);
+ break;
+ }
case CMD_DESTROY_KEY: {
LOGD("!!! Destroy !!!");
ret = KM_ExecCmdDestroyKey(param);
ret = KM_ExecCmdDestroyData(param);
break;
}
+ case CMD_GENERATE_RSA_KEYPAIR: {
+ LOGD("!!! Generating RSA key pair !!!");
+ ret = KM_ExecCmdGenerateRSAKey(param);
+ break;
+ }
+ case CMD_GENERATE_DSA_KEYPAIR: {
+ LOGD("!!! Generating DSA key pair !!!");
+ ret = KM_ExecCmdGenerateDSAKey(param);
+ break;
+ }
default: {
LOG("Unknown commandID=%d.", commandID);
ret = TEE_ERROR_BAD_PARAMETERS;