Add support for asymmetric operations 13/200313/2
authorLukasz Kostyra <l.kostyra@samsung.com>
Wed, 20 Feb 2019 11:22:09 +0000 (12:22 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Mon, 18 Mar 2019 14:15:04 +0000 (15:15 +0100)
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

packaging/key-manager-ta.spec
serialization/src/km_serialization.c
ta/include/cmd_exec.h
ta/include/internal.h
ta/include/km_ta_defines.h
ta/src/cmd_exec.c
ta/src/crypto_asymmetric.c
ta/src/crypto_symmetric.c
ta/src/internal.c
ta/src/km_ta.c

index 17320cdcc4cbafc8be4eaf39f549dc76b102d436..af7011fd57f14b92c9fc6e958e6613ddec487ea1 100644 (file)
@@ -38,6 +38,7 @@ Provides:   %{name}
 
 BuildRequires: cmake
 BuildRequires: unified-ta-devkit
+BuildRequires: openssl
 
 %description
 Key Manager Trusted Application working in the ARMĀ® TrustZoneĀ® environment.
index 621463dce3d4cf555500f9e3d4939c9214f204c0..d1046df92ec4a2f3c7010894974c18292eac0fcf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -683,6 +683,8 @@ int KM_DeserializeBinaryData(void **buffer, uint32_t *size_guard, KM_BinaryData
                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));
 }
 
index abb5672a13d871b8100d563b0ac41d40bb1f9e1f..c4171d7ef8647c26e2a06c22fd7f6e71878b60a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -28,6 +28,10 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4]);
 
 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]);
@@ -36,6 +40,8 @@ TEE_Result KM_ExecCmdAsymmetric(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]);
index 34f217f1ba8c669d85c5f96e643c5794d8d890c2..19c5d29f078f3b9f0fea17bd42919e9a53153c4f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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);
 
index 23202c6dfd6c79e8eb8ad2adf3799cd22112b85f..a5d495e8b93358996a46244f44bd13af40321787 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -32,7 +32,7 @@
  */
 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
@@ -54,18 +54,20 @@ typedef enum {
                             ///<        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:
@@ -85,19 +87,21 @@ typedef enum {
                             ///<        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:
@@ -107,12 +111,14 @@ typedef enum {
                             ///<
 
        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
@@ -120,8 +126,17 @@ typedef enum {
                             ///<        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.
@@ -190,12 +205,47 @@ typedef enum {
                             ///<    [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
@@ -234,9 +284,16 @@ typedef enum {
        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
index ae731838c10ec04487dfd509d515e7d04125a18b..1803ce751fee124e00ad4f72fa910fa2b21f631f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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>
@@ -38,7 +40,6 @@
 // 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;
@@ -75,6 +76,46 @@ static uint32_t KM_Algo2TeeAlgo(int algo)
        }
 }
 
+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)
@@ -162,6 +203,14 @@ static uint32_t KM_DigestSizeFromHash(int hash)
        }
 }
 
+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) {
@@ -202,23 +251,316 @@ static uint32_t KM_AlgoHash2SignVerifyAlgo(int algo, int hash)
                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;
@@ -226,7 +568,7 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
        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);
 
@@ -236,13 +578,13 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
                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;
@@ -312,7 +654,7 @@ TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4])
                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;
@@ -347,6 +689,66 @@ 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;
@@ -604,10 +1006,10 @@ clean:
 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;
@@ -620,20 +1022,18 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
                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");
@@ -641,6 +1041,12 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
                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);
@@ -649,34 +1055,37 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
                                                                        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);
 
@@ -685,66 +1094,106 @@ TEE_Result KM_ExecCmdSign(TEE_Param param[4])
                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;
 }
 
@@ -968,6 +1417,10 @@ TEE_Result KM_ExecCmdSaveData(TEE_Param param[4])
                        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;
index dad2f6a216786902bd8f91f16d52f01bed0a5ca2..1ed2fe28b134638f195e1fe62ce4d521990dd920 100644 (file)
@@ -28,14 +28,12 @@ TEE_Result KM_AsymmetricEncrypt(TEE_OperationHandle hndl, void *input, uint32_t
 {
        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;
 }
 
@@ -44,14 +42,12 @@ TEE_Result KM_AsymmetricDecrypt(TEE_OperationHandle hndl, void *input, uint32_t
 {
        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;
 }
 
@@ -60,14 +56,12 @@ TEE_Result KM_AsymmetricSign(TEE_OperationHandle hndl, void *digest, uint32_t di
 {
        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;
 }
 
@@ -76,13 +70,11 @@ TEE_Result KM_AsymmetricVerify(TEE_OperationHandle hndl, void *digest, uint32_t
 {
        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
index 4e346c5e87eb27f7bf504b7ec63145f17805d2f9..42a041e731bfabedc2ea11ef4e40856689b31af5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -28,9 +28,6 @@
 #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)
index b5f10cdbd4fcf6d7002c0670a6abb349e3b95ba4..11528d3491d28ee5d0c5cac7483ceb6be6691a23 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -17,6 +17,7 @@
  * @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
  */
@@ -25,6 +26,7 @@
 #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);
@@ -98,7 +139,9 @@ TEE_Result KM_CreateKey(uint32_t tee_key_type, uint32_t key_bits_size, void *key
        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;
 
@@ -109,7 +152,7 @@ TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size, TEE
                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);
@@ -119,7 +162,23 @@ TEE_Result KM_CreateRandomKey(uint32_t tee_key_type, uint32_t key_bits_size, TEE
        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;
@@ -220,9 +279,325 @@ TEE_Result KM_EncryptKey(TEE_ObjectHandle keyHndl, KM_PwdData *pwd,
 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,
@@ -297,7 +672,7 @@ TEE_Result KM_DecryptImportedData(
 }
 #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;
@@ -399,6 +774,65 @@ out:
        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)
 {
@@ -407,7 +841,7 @@ TEE_Result KM_CreateOperation(TEE_ObjectHandle op_key_hndl, uint32_t algo,
 
        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);
index 4748a53df6c7c0216ae0de036c5c7f37a61b3ae5..82d75e2d999eb131336c9a770c51815032b0083a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  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.
@@ -25,6 +25,7 @@
 #include <cmd_exec.h>
 #include <log.h>
 #include <internal.h>
+#include <openssl/evp.h>
 
 TEE_Result TA_CreateEntryPoint(void)
 {
@@ -119,6 +120,20 @@ TEE_Result TA_InvokeCommandEntryPoint(
                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);
@@ -144,6 +159,16 @@ TEE_Result TA_InvokeCommandEntryPoint(
                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;