Implement digest and asymmetric operations 35/141235/3
authorLukasz Kostyra <l.kostyra@samsung.com>
Fri, 28 Jul 2017 13:40:23 +0000 (15:40 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Tue, 7 Nov 2017 16:05:01 +0000 (17:05 +0100)
Change-Id: Iaee5d63bea67887665f5c171230c73c89cf010a3

12 files changed:
CMakeLists.txt
ta/include/cmd_exec.h
ta/include/crypto_asymmetric.h [new file with mode: 0644]
ta/include/crypto_digest.h [new file with mode: 0644]
ta/include/internal.h
ta/include/km_ta_defines.h
ta/src/cmd_exec.c
ta/src/crypto_asymmetric.c [new file with mode: 0644]
ta/src/crypto_digest.c [new file with mode: 0644]
ta/src/crypto_symmetric.c
ta/src/internal.c
ta/src/km_ta.c

index c7110ebf01c0a2274bec3596b7f8858d488a49bc..a4ab16c51fe11c931d6569915a2c4270367bf14b 100644 (file)
@@ -33,8 +33,10 @@ SET(KEY_MANAGER_TA_SERIALIZATION_PATH ${KEY_MANAGER_TA_ROOT_PATH}/serialization)
 
 SET(KEY_MANAGER_TA_SOURCES
     ${KEY_MANAGER_TA_PATH}/src/cmd_exec.c
+    ${KEY_MANAGER_TA_PATH}/src/crypto_asymmetric.c
     ${KEY_MANAGER_TA_PATH}/src/crypto_auth.c
     ${KEY_MANAGER_TA_PATH}/src/crypto_derive.c
+    ${KEY_MANAGER_TA_PATH}/src/crypto_digest.c
     ${KEY_MANAGER_TA_PATH}/src/crypto_symmetric.c
     ${KEY_MANAGER_TA_PATH}/src/internal.c
     ${KEY_MANAGER_TA_PATH}/src/log.c
index 7c97ac952324a4b7822de21cc9133f7a855e1232..eac2058801cbdf8a85e36f1174201eb3fb6a1ebc 100644 (file)
@@ -34,4 +34,8 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4]);
 
 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]);
+
 #endif // __CMD_EXEC_H__
\ No newline at end of file
diff --git a/ta/include/crypto_asymmetric.h b/ta/include/crypto_asymmetric.h
new file mode 100644 (file)
index 0000000..fff8e8d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file        crypto_asymmetric.h
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (asymmetric operations)
+ */
+
+#ifndef __CRYPTO_ASYMMETRIC_H__
+#define __CRYPTO_ASYMMETRIC_H__
+
+#include <tee_internal_api.h>
+
+TEE_Result KM_AsymmetricEncrypt(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                                               void *output, uint32_t *output_size);
+
+TEE_Result KM_AsymmetricDecrypt(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                                               void *output, uint32_t *output_size);
+
+TEE_Result KM_AsymmetricSign(TEE_OperationHandle hndl, void *digest, uint32_t digest_size,
+                                                       void *signature, uint32_t *sig_size);
+
+TEE_Result KM_AsymmetricVerify(TEE_OperationHandle hndl, void *digest, uint32_t digest_size,
+                                                               void *signature, uint32_t sig_size);
+
+#endif // __CRYPTO_ASYMMETRIC_H__
diff --git a/ta/include/crypto_digest.h b/ta/include/crypto_digest.h
new file mode 100644 (file)
index 0000000..3e15cd0
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file        crypto_digest.h
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (digest operations)
+ */
+
+#ifndef __CRYPTO_DIGEST_H__
+#define __CRYPTO_DIGEST_H__
+
+#include <tee_internal_api.h>
+
+TEE_Result KM_Digest(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                       void *output, uint32_t *output_size);
+
+#endif // __CRYPTO_DIGEST_H__
index fa237adb1c8c2ef35438c76da79b98830688c047..dc71a1bdaea98c408aead3811d040297a28497ac 100644 (file)
@@ -41,6 +41,8 @@ TEE_Result KM_CreateOperationWithKey(void *key, uint32_t key_size, uint32_t type
 TEE_Result KM_CreateOperationWithKeyId(void *key_id, uint32_t key_id_size, uint32_t mode,
                                                                                uint32_t algo, TEE_OperationHandle *oper_hndl);
 
+TEE_Result KM_CreateDigestOperation(uint32_t algo, TEE_OperationHandle *oper_hndl);
+
 // saves the key inside persistent object
 TEE_Result KM_SaveKey(void *data, size_t data_size, TEE_ObjectHandle key, void *objId,
                                                size_t objId_size);
index c36fe2e3040d1acea47c2ba84b60beccdbc8471f..be48875560bf91cb885086bdb27ee4c571cb1f2e 100644 (file)
@@ -43,14 +43,22 @@ typedef enum {
        ALGO_AES_GCM,
        ALGO_AES_CFB,
        ALGO_RSA,
-       ALGO_DSA,
-       ALGO_ECDSA,
        ALGO_AES_GEN,
        ALGO_RSA_GEN,
        ALGO_DSA_GEN,
        ALGO_ECDSA_GEN,
+       ALGO_RSA_SV,
+       ALGO_DSA_SV,
+       ALGO_ECDSA_SV,
 } tz_algo_type;
 
+typedef enum {
+       HASH_SHA1,
+       HASH_SHA256,
+       HASH_SHA384,
+       HASH_SHA512,
+} tz_hash_type;
+
 // TODO this must be somehow confronted with TEE_OBJECT_ID_MAX_LEN
 #define KM_KEY_ID_SIZE 64
 
@@ -58,6 +66,7 @@ typedef enum {
 #define KM_TA_SUCCESS 0
 #define KM_TA_ERROR_GENERIC 1
 #define KM_TA_ERROR_AUTH_FAILED 2
+#define KM_TA_ERROR_SIGNATURE 3
 
 // UUID
 #define KM_TA_UUID { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x66, 0x66, 0x66, 0x55, 0x55, 0x55} }
index 0c5a7906ca9c72bfc643b022ef7cdf73d5ec557f..6ac1cf3c47b2ba130976ae39893b57f4f25c64e6 100644 (file)
 #include <tee_internal_api.h>
 #include <km_ta_defines.h>
 #include <internal.h>
+#include <crypto_asymmetric.h>
 #include <crypto_symmetric.h>
 #include <crypto_auth.h>
 #include <crypto_derive.h>
+#include <crypto_digest.h>
 #include <km_serialization.h>
 #include <cmd_exec.h>
 #include <log.h>
@@ -39,6 +41,7 @@
 #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
 
 
 static uint32_t KM_AlgoType2TeeType(int algo)
@@ -159,6 +162,55 @@ static TEE_Result KM_DeserializeInput(void* buffer, uint32_t buffer_size, Symmet
        return TEE_SUCCESS;
 }
 
+static uint32_t KM_Hash2TeeAlgo(int hash)
+{
+       switch (hash) {
+       case HASH_SHA1: return TEE_ALG_SHA1;
+       case HASH_SHA256: return TEE_ALG_SHA256;
+       case HASH_SHA384: return TEE_ALG_SHA384;
+       case HASH_SHA512: return TEE_ALG_SHA512;
+       default: return 0;
+       }
+}
+
+static uint32_t KM_DigestSizeFromHash(int hash)
+{
+       // returned in bytes
+       switch (hash) {
+       case HASH_SHA1: return 20;
+       case HASH_SHA256: return 32;
+       case HASH_SHA384: return 48;
+       case HASH_SHA512: return 64;
+       default: return 0;
+       }
+}
+
+static uint32_t KM_AlgoHash2SignVerifyAlgo(int algo, int hash)
+{
+       switch (algo) {
+       case ALGO_RSA_SV: {
+               switch (hash) {
+               case HASH_SHA1: return TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1;
+               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
+               }
+       }
+       case ALGO_DSA_SV: {
+               switch (hash) {
+               case HASH_SHA1: return TEE_ALG_DSA_SHA1;
+               default: return 0; // TODO more SV algs unsupported
+               }
+       }
+       case ALGO_ECDSA_SV: {
+               // TODO unsupported
+               return 0;
+       }
+       default: return 0;
+       }
+}
+
 TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
 {
        TEE_Result ret = TEE_SUCCESS;
@@ -167,20 +219,27 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
 
        uint32_t type = KM_AlgoType2TeeType(param[0].value.a);
        uint32_t key_bits_size = param[0].value.b;
-
        uint32_t objId_size = KM_KEY_ID_SIZE;
        uint32_t *objId = (uint32_t*)malloc(objId_size);
+
        if (objId == NULL) {
                LOG("Failed to allocate object ID buffer");
                ret = TEE_ERROR_OUT_OF_MEMORY;
                goto clean;
        }
 
+       if (type == 0) {
+               LOG("Unsupported key type provided: %u", type);
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
        ret = KM_CreateRandomKey(type, key_bits_size, &hndl);
        if (TEE_SUCCESS != ret) {
                LOG("Failed to randomize new key");
                goto clean;
        }
+
        ret = KM_SaveKey(NULL, 0, hndl, objId, objId_size);
        if (TEE_SUCCESS != ret) {
                LOG("Failed to save generated key");
@@ -385,6 +444,11 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4])
                return TEE_ERROR_BAD_PARAMETERS;
        }
 
+       if (algo == 0) {
+               LOG("Unsupported algorithm provided: %u", algo);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
        ret = KM_DeserializeInput(param[1].memref.buffer, param[1].memref.size,
                                                        &input, &input_data, &iv_data, &key_id_data,
                                                        &key_data, &ae_data, &tag_data);
@@ -470,16 +534,11 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
        TEE_OperationHandle operation = TEE_HANDLE_NULL;
        SymmetricInput *input = NULL;
        InputData *input_data = NULL;
-       IVData *iv_data = NULL;
        KeyId *key_id_data = NULL;
        Key *key_data = NULL;
-       char ownIVFlag = 0;
 
-       uint32_t *iv = NULL;
-       uint32_t iv_size = 0;
        void *out = NULL;
-       uint32_t out_size = 0;
-       uint32_t out_size_pad = 0;
+       uint32_t out_size = RSA_BLOCK_SIZE;
 
        uint32_t type = 0;
        uint32_t algo = KM_Algo2TeeAlgo(param[0].value.a);
@@ -491,15 +550,25 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
        }
 
        ret = KM_DeserializeInput(param[1].memref.buffer, param[1].memref.size,
-                                                       &input, &input_data, &iv_data, &key_id_data,
+                                                       &input, &input_data, NULL, &key_id_data,
                                                        &key_data, NULL, NULL);
        if (ret != TEE_SUCCESS) {
                LOG("Failed to deserialize data from input buffer");
                return TEE_ERROR_BAD_PARAMETERS;
        }
 
-       out_size_pad = AES_BLOCK_SIZE - (input_data->data_size % AES_BLOCK_SIZE);
-       out_size = input_data->data_size + out_size_pad;
+       if (key_id_data) {
+               ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size, mode, algo,
+                                                                                       &operation);
+       } else if (key_data) {
+               type = KM_AlgoType2TeeType(param[0].value.a);
+               ret = KM_CreateOperationWithKey(key_data->key.data, key_data->key.data_size, type, mode,
+                                                                               algo, key_data->key_bits_size, &operation);
+       }
+       if (TEE_SUCCESS != ret) {
+               return ret;
+       }
+
        out = malloc(out_size);
        if (out == NULL) {
                LOG("Failed to allocate output buffer");
@@ -507,47 +576,113 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
                goto clean;
        }
 
-       if (iv_data) {
-               iv = iv_data->data;
-               iv_size = iv_data->data_size;
-       } else {
-               // create empty (zeroed) IV based on AES block size
-               ownIVFlag = 1;
-               iv_size = AES_BLOCK_SIZE;
-               iv = malloc(iv_size);
-               if (iv == NULL) {
-                       LOG("Failed to allocate IV buffer");
-                       ret = TEE_ERROR_OUT_OF_MEMORY;
-                       goto clean;
-               }
-               memset(iv, 0x00, iv_size);
+       if (commandID == CMD_ENCRYPT)
+               ret = KM_AsymmetricEncrypt(operation, input_data->data, input_data->data_size,
+                                                                       out, &out_size);
+       else
+               ret = KM_AsymmetricDecrypt(operation, input_data->data, input_data->data_size,
+                                                                       out, &out_size);
+
+       if (TEE_SUCCESS != ret) {
+               goto clean;
        }
 
-       if (algo == KM_TA_ALG_AES_CFB) {
-               ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode, iv, iv_size,
-                                                                               input_data->data, input_data->data_size, out, &out_size);
-       } else {
-               if (key_id_data) {
-                       ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size, mode, algo, &operation);
-               } else if (key_data) {
-                       type = KM_AlgoType2TeeType(param[0].value.a);
-                       ret = KM_CreateOperationWithKey(key_data->key.data, key_data->key.data_size, type, mode,
-                                                                                       algo, key_data->key_bits_size, &operation);
-               }
+       if (0 != KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size, &input)
+               || 0 != KM_ParamsSerializeOutData(input, out, out_size)) {
+               ret = TEE_ERROR_BAD_PARAMETERS;
+       }
 
-               if (TEE_SUCCESS != ret) {
-                       goto clean;
-               }
+clean:
+       free(out);
+       if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
+       return ret;
+}
 
-               ret = KM_SymmetricCrypt(operation, iv, iv_size, input_data->data, input_data->data_size,
-                                                               out, &out_size);
+TEE_Result KM_ExecCmdSign(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_SUCCESS;
+       TEE_OperationHandle digestOperation = TEE_HANDLE_NULL;
+       TEE_OperationHandle operation = TEE_HANDLE_NULL;
+       SymmetricInput *input = NULL;
+       InputData *input_data = NULL;
+       KeyId *key_id_data = NULL;
+       Key *key_data = 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 type = 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;
        }
 
+       if (0 != KM_ParamsDeserializationInit(param[1].memref.buffer, param[1].memref.size, &input)
+               || 0 != KM_ParamsDeserializeInputData(input, &input_data)
+               || 0 != KM_ParamsDeserializeKeyId(input, &key_id_data)
+               || 0 != KM_ParamsDeserializeKey(input, &key_data)) {
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       KM_ParamsDump(input, input_data, NULL, key_data, key_id_data, NULL, NULL, NULL);
+
+       if (!input_data) {
+               LOG("There needs to be InputData!");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if ((NULL != key_data && NULL != key_id_data) || (NULL == key_data && NULL == key_id_data)) {
+               LOG("You need to specify key or keyId. At least one and only one.");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if (key_id_data) {
+               ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size,
+                                                                                       TEE_MODE_SIGN, algo, &operation);
+       } else if (key_data) {
+               type = KM_AlgoType2TeeType(param[0].value.a);
+               ret = KM_CreateOperationWithKey(key_data->key.data, key_data->key.data_size, type,
+                                                                               TEE_MODE_SIGN, algo, key_data->key_bits_size, &operation);
+       }
+
+       ret = KM_CreateDigestOperation(KM_Hash2TeeAlgo(param[0].value.b), &digestOperation);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to create digest operation");
+               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;
+               goto clean;
+       }
+
+       out_size_pad = RSA_BLOCK_SIZE;
+       out_size = input_data->data_size + out_size_pad;
+       out = malloc(out_size);
+       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;
        }
 
-       LOG("LKDEBUG out_size = %u", out_size);
+       ret = KM_AsymmetricSign(operation, digest, digest_size, out, &out_size);
+       if (TEE_SUCCESS != ret) {
+               goto clean;
+       }
 
        if (0 != KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size, &input)
                || 0 != KM_ParamsSerializeOutData(input, out, out_size)) {
@@ -556,7 +691,89 @@ TEE_Result KM_ExecCmdAsymmetric(uint32_t commandID, TEE_Param param[4])
 
 clean:
        free(out);
-       if (ownIVFlag) free(iv);
+       free(digest);
+       if (digestOperation != TEE_HANDLE_NULL) TEE_FreeOperation(digestOperation);
+       if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
+       return ret;
+}
+
+TEE_Result KM_ExecCmdVerify(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
+       TEE_OperationHandle digestOperation = TEE_HANDLE_NULL;
+       TEE_OperationHandle operation = TEE_HANDLE_NULL;
+       SymmetricInput *input = NULL;
+       InputData *input_data = NULL;
+       IVData *iv_data = NULL;
+       KeyId *key_id_data = NULL;
+       Key *key_data = NULL;
+
+       void* digest = NULL;
+       uint32_t digest_size = 0;
+
+       uint32_t type = 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;
+       }
+
+       if (0 != KM_ParamsDeserializationInit(param[1].memref.buffer, param[1].memref.size, &input)
+               || 0 != KM_ParamsDeserializeInputData(input, &input_data)
+               || 0 != KM_ParamsDeserializeIVData(input, &iv_data)
+               || 0 != KM_ParamsDeserializeKeyId(input, &key_id_data)
+               || 0 != KM_ParamsDeserializeKey(input, &key_data)) {
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       KM_ParamsDump(input, input_data, iv_data, key_data, key_id_data, NULL, NULL, NULL);
+
+       if (!input_data) {
+               LOG("There needs to be InputData!");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       if ((NULL != key_data && NULL != key_id_data) || (NULL == key_data && NULL == key_id_data)) {
+               LOG("You need to specify key or keyId. At least one and only one.");
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
+       ret = KM_CreateDigestOperation(KM_Hash2TeeAlgo(param[0].value.b), &digestOperation);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to create digest operation");
+               goto clean;
+       }
+
+       if (key_id_data) {
+               ret = KM_CreateOperationWithKeyId(key_id_data->data, key_id_data->data_size,
+                                                                                       TEE_MODE_VERIFY, algo, &operation);
+       } else if (key_data) {
+               type = KM_AlgoType2TeeType(param[0].value.a);
+               ret = KM_CreateOperationWithKey(key_data->key.data, key_data->key.data_size, type,
+                                                                               TEE_MODE_VERIFY, algo, key_data->key_bits_size, &operation);
+       }
+
+       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;
+               goto clean;
+       }
+
+       ret = KM_Digest(digestOperation, input_data->data, input_data->data_size,
+                                       digest, &digest_size);
+       if (TEE_SUCCESS != ret) {
+               goto clean;
+       }
+
+       ret = KM_AsymmetricVerify(operation, digest, digest_size,
+                                                       iv_data->data, iv_data->data_size);
+
+clean:
+       free(digest);
+       if (digestOperation != TEE_HANDLE_NULL) TEE_FreeOperation(digestOperation);
        if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
        return ret;
 }
diff --git a/ta/src/crypto_asymmetric.c b/ta/src/crypto_asymmetric.c
new file mode 100644 (file)
index 0000000..0cdae6e
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file        crypto_asymmetric.c
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (asymmetric operations)
+ */
+
+#include "crypto_asymmetric.h"
+#include "log.h"
+
+TEE_Result KM_AsymmetricEncrypt(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                                               void *output, uint32_t *output_size)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       LOG("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("Asym encrypt done");
+       return ret;
+}
+
+TEE_Result KM_AsymmetricDecrypt(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                                               void *output, uint32_t *output_size)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       LOG("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("Asym encrypt done");
+       return ret;
+}
+
+TEE_Result KM_AsymmetricSign(TEE_OperationHandle hndl, void *digest, uint32_t digest_size,
+                                                       void *signature, uint32_t *sig_size)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       LOG("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("Asym sign done");
+       return ret;
+}
+
+TEE_Result KM_AsymmetricVerify(TEE_OperationHandle hndl, void *digest, uint32_t digest_size,
+                                                               void *signature, uint32_t sig_size)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       LOG("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("Asym verify done");
+       return ret;
+}
\ No newline at end of file
diff --git a/ta/src/crypto_digest.c b/ta/src/crypto_digest.c
new file mode 100644 (file)
index 0000000..22fb01e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/*
+ * @file        crypto_digest.c
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (digest operations)
+ */
+
+#include "crypto_digest.h"
+#include "log.h"
+
+
+TEE_Result KM_Digest(TEE_OperationHandle hndl, void *input, uint32_t input_size,
+                                       void *output, uint32_t *output_size)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       LOG("Digest");
+       ret = TEE_DigestDoFinal(hndl, input, input_size, output, output_size);
+       if (ret != TEE_SUCCESS) {
+               LOG("TEE_DigestDoFinal has failed with=%x.", ret);
+               return ret;
+       }
+
+       LOG("Digest done");
+       return ret;
+}
\ No newline at end of file
index 3b71cd1f1feea8f5785e9c6e44114d7fb409e00d..dc558623287daca756e69a4e788a88a76eb7298c 100644 (file)
@@ -16,6 +16,7 @@
 /*
  * @file        crypto_symmetric.c
  * @author      RafaƂ Tyminski (r.tyminski@partner.samsung.com)
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
  * @version     1.0
  * @brief       Implementation of Global Platform Internal API usage (symmetric encryption)
  */
index 0146a6a1511de55fdbe70a938e9b8ce7c0b5a1c7..07010a73eeb1849f58067f9699439f33ba3d95c1 100644 (file)
@@ -170,6 +170,18 @@ TEE_Result KM_CreateOperationWithKeyId(void *key_id, uint32_t key_id_size, uint3
        return ret;
 }
 
+TEE_Result KM_CreateDigestOperation(uint32_t algo, TEE_OperationHandle *oper_hndl)
+{
+       TEE_Result ret = TEE_SUCCESS;
+
+       ret = TEE_AllocateOperation(oper_hndl, algo, TEE_MODE_DIGEST, 0);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to allocate digest operation: %x", ret);
+       }
+
+       return ret;
+}
+
 TEE_Result KM_SaveKey(void *data, size_t data_size, TEE_ObjectHandle key, void *objId,
                                                size_t objId_size)
 {
index 3c4c3db035468ca75babd2aafbe1320cd0a2ec81..91c7445763679ca4557c123bad19e24baf52dff9 100644 (file)
@@ -62,21 +62,25 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
        S_VAR_NOT_USED(param_types);
 
        switch (commandID) {
-       case CMD_GENERATE_KEY:
+       case CMD_GENERATE_KEY: {
                LOGD("!!! Generate key !!!");
                ret = KM_ExecCmdGenerateKey(param);
                break;
-       case CMD_GENERATE_IV:
+       }
+       case CMD_GENERATE_IV: {
                LOGD("!!! Generate IV !!!");
                KM_GenerateIV(param[1].memref.buffer, param[1].memref.size);
                break;
-       case CMD_GENERATE_KEY_PWD:
-               LOGD("!!! Generate PWD !!!");
+       }
+       case CMD_GENERATE_KEY_PWD: {
+               LOGD("!!! Generate Key from PWD !!!");
                ret = KM_ExecCmdGenerateKeyPwd(param);
                break;
+       }
        case CMD_ENCRYPT:
-       case CMD_DECRYPT:
+       case CMD_DECRYPT: {
                LOGD("!!! %scrypt !!!", (commandID == CMD_ENCRYPT) ? "En" : "De");
+
                if (ALGO_AES_CTR != param[0].value.a &&
                        ALGO_AES_CBC != param[0].value.a &&
                        ALGO_AES_GCM != param[0].value.a &&
@@ -86,6 +90,7 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
                        ret = TEE_ERROR_BAD_PARAMETERS;
                        break;
                }
+
                if (ALGO_AES_GCM == param[0].value.a) {
                        ret = KM_ExecCmdAuth(commandID, param);
                } else if (ALGO_RSA == param[0].value.a) {
@@ -93,11 +98,42 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
                } else {
                        ret = KM_ExecCmdSymmetric(commandID, param);
                }
+
+               break;
+       }
+       case CMD_SIGN: {
+               LOGD("!!! Sign !!!");
+
+               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_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;
-       default:
+       }
+       default: {
                LOG("Unknown commandID=%d.", commandID);
                ret = TEE_ERROR_BAD_PARAMETERS;
        }
+       }
 
        // inform about successful operation, or about an error in authorization
        // TEEC API has less return codes than TEE, so about some exceptional
@@ -106,18 +142,25 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
        param[0].value.a = KM_TA_SUCCESS;
        if (ret != TEE_SUCCESS) {
                switch (ret) {
-               case TEE_ERROR_MAC_INVALID:
+               case TEE_ERROR_MAC_INVALID: {
                        // error during auth cipher - revert return to success because
                        // TEE Client API does not support this error code and inform
                        // about it thorugh our own TA-specific return value
                        ret = TEE_SUCCESS;
                        param[0].value.a = KM_TA_ERROR_AUTH_FAILED;
                        break;
-               default:
+               }
+               case TEE_ERROR_SIGNATURE_INVALID: {
+                       // error during signature verification - same as above
+                       ret = TEE_SUCCESS;
+                       param[0].value.a = KM_TA_ERROR_SIGNATURE;
+               }
+               default: {
                        // other errors can be added here as we need
                        param[0].value.a = KM_TA_ERROR_GENERIC;
                        break;
                }
+               }
        }
 
        return ret;