Implement PKCS7 and zero padding 28/149928/6
authorLukasz Kostyra <l.kostyra@samsung.com>
Mon, 4 Sep 2017 13:13:01 +0000 (15:13 +0200)
committerLukasz Kostyra <l.kostyra@samsung.com>
Mon, 13 Nov 2017 14:49:37 +0000 (15:49 +0100)
PKCS7 padding is used in symmetric cipher operations, as GP API does not
support it natively.

Zero padding is used with PBKDF2 to allow passwords having less than 10
bytes.

Some minor bugs were also squashed to make the code fully working.

Change-Id: Ibec339af3e1adf2ff69d08a83baf07429ef567c3

15 files changed:
CMakeLists.txt
packaging/key-manager-ta.spec
serialization/include/km_serialization.h
serialization/src/km_serialization.c
ta/include/cmd_exec.h
ta/include/crypto_auth.h
ta/include/crypto_padding.h [new file with mode: 0644]
ta/src/cmd_exec.c
ta/src/crypto_asymmetric.c
ta/src/crypto_auth.c
ta/src/crypto_derive.c
ta/src/crypto_padding.c [new file with mode: 0644]
ta/src/crypto_symmetric.c
ta/src/internal.c
ta/src/km_ta.c

index 44bf2865df03984c82b3aab1631d87a4630d914f..d683fd0557485b0a002f5464fb61a3fcfe2237fc 100644 (file)
@@ -29,6 +29,10 @@ SET(KEY_MANAGER_TA_ROOT_PATH ${PROJECT_SOURCE_DIR})
 SET(KEY_MANAGER_TA_PATH ${KEY_MANAGER_TA_ROOT_PATH}/ta)
 SET(KEY_MANAGER_TA_SERIALIZATION_PATH ${KEY_MANAGER_TA_ROOT_PATH}/serialization)
 
+IF(${CMAKE_BUILD_TYPE} MATCHES "DEBUG")
+    ADD_DEFINITIONS("-DDEBUG")
+ENDIF(${CMAKE_BUILD_TYPE} MATCHES "DEBUG")
+
 ############# TA #############
 
 SET(KEY_MANAGER_TA_SOURCES
@@ -37,6 +41,7 @@ SET(KEY_MANAGER_TA_SOURCES
     ${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_padding.c
     ${KEY_MANAGER_TA_PATH}/src/crypto_symmetric.c
     ${KEY_MANAGER_TA_PATH}/src/internal.c
     ${KEY_MANAGER_TA_PATH}/src/log.c
index c07c6407c62d730a09dd3cb7aad917e583d4a9b5..ac8e28cb61c66a097c2686738fbae1ba6bd47ec4 100644 (file)
@@ -69,6 +69,7 @@ cp -a %{SOURCE2} .
 mkdir -p build
 cd build
 %cmake .. \
+    -DCMAKE_BUILD_TYPE=%{?build_type:%build_type}%{!?build_type:RELEASE} \
     -DTEF_BUILD_TYPE=%{tef_build_type} \
     -DTASTORE_DIR=%{tastore_dir} \
     -DINCLUDE_DIR=%{include_dir} \
index 322a573f78c04d9558f6542c5ea7f57edd0d2a60..884592f006fd7f614f16f106580690127ad8e40c 100644 (file)
@@ -59,7 +59,6 @@ typedef struct Data_ TagData;
 typedef struct AEData_ {
        Data aad;
        uint32_t tagLen;
-       uint32_t AADLen;
        uint32_t payloadLen;
 } AEData;
 
@@ -98,12 +97,12 @@ int KM_ParamsDeserializeTagData(SymmetricInput *self, TagData **out);
 int KM_ParamsDeserializeKey(SymmetricInput *self, Key **out);
 int KM_ParamsDeserializeKeyId(SymmetricInput *self, KeyId **out);
 
-int KM_ParamsSerializationInit(void *buffer, size_t buffer_size, SymmetricInput **out);
-int KM_ParamsSerializeInputData(SymmetricInput *self, const void *data, size_t data_size);
-int KM_ParamsSerializeIVData(SymmetricInput *self, const void *data, size_t data_size);
-int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t AADLen,
-                                                       uint32_t payloadLen, const void *aad, size_t aad_size);
-int KM_ParamsSerializeOutData(SymmetricInput *self, const void *data, size_t data_size);
+int KM_ParamsSerializationInit(void *buffer, uint32_t buffer_size, SymmetricInput **out);
+int KM_ParamsSerializeInputData(SymmetricInput *self, const void *data, uint32_t data_size);
+int KM_ParamsSerializeIVData(SymmetricInput *self, const void *data, uint32_t data_size);
+int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t payloadLen,
+                                                       const void *aad, uint32_t aad_size);
+int KM_ParamsSerializeOutData(SymmetricInput *self, const void *data, uint32_t data_size);
 
 int KM_ParamsSerializeTagData(SymmetricInput *self, const void *data, size_t data_size);
 
index 1f9eeb92622164d2535f12ce7b4c9587edad6d07..166e94c6a9aa27b19a804b78e4d350d1bee9c1a7 100644 (file)
@@ -131,8 +131,8 @@ void KM_ParamsDump(SymmetricInput *input, InputData *input_data, IVData *iv_data
                LOG("Input=%p, input_size=%d", input_data->data, input_data->data_size);
        }
        if (ae_data) {
-               LOG("aad.data=%p, aad.size=%d, tagLen=%d, AADLen=%d, payloadLen=%d", ae_data->aad.data,
-                               ae_data->aad.data_size, ae_data->tagLen, ae_data->AADLen, ae_data->payloadLen);
+               LOG("aad.data=%p, aad.size=%d, tagLen=%d, payloadLen=%d", ae_data->aad.data,
+                               ae_data->aad.data_size, ae_data->tagLen, ae_data->payloadLen);
        }
        if (out_data) {
                LOG("Out=%p, out_size=%d", out_data->data, out_data->data_size);
@@ -165,7 +165,7 @@ uint32_t KM_PrecalculateBufferSize(uint32_t input_size, uint32_t iv_size, uint32
                size += sizeof(IVData) + addAlignment(iv_size);
 
        if (with_ae_data > 0)
-               size += sizeof(AEData) + addAlignment(aad_size);
+               size += sizeof(AEData) + sizeof(Data) + addAlignment(aad_size);
 
        if (out_size > 0)
                size += sizeof(OutData) + addAlignment(out_size);
@@ -318,8 +318,8 @@ int KM_ParamsSerializeIVData(SymmetricInput *self, const void *data, size_t data
        return 0;
 }
 
-int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t AADLen,
-                                                       uint32_t payloadLen, const void *aad, size_t aad_size)
+int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t payloadLen,
+                                                       const void *aad, uint32_t aad_size)
 {
        AEData *ptr = NULL;
        uint32_t ret = 0;
@@ -334,7 +334,6 @@ int KM_ParamsSerializeAEData(SymmetricInput *self, uint32_t tagLen, uint32_t AAD
        }
 
        ptr->tagLen = tagLen;
-       ptr->AADLen = AADLen;
        ptr->payloadLen = payloadLen;
 
        self->ae_data_offset = self->global_offset;
index eac2058801cbdf8a85e36f1174201eb3fb6a1ebc..343ca8b124c56e7c2482f85af4a6ab33caf7e0ca 100644 (file)
@@ -28,6 +28,8 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4]);
 
 TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4]);
 
+TEE_Result KM_ExecCmdImportKey(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]);
index 8ee1faa5546757a4d84038926562ebbbee313e27..fa9efef74b14cb63f42b66739c2050a49d97072e 100644 (file)
 #include <tee_internal_api.h>
 
 TEE_Result KM_AuthEncrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
-                                                       uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
-                                                       void *out, uint32_t *out_size, void *tag, uint32_t *tag_size);
+                                               uint32_t payloadLen, void *data, uint32_t data_size,
+                                               void *aad, uint32_t aad_size, void *out, uint32_t *out_size,
+                                               void *tag, uint32_t *tag_size);
 
 TEE_Result KM_AuthDecrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
-                                                       uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
-                                                       void *tag, uint32_t tag_size, void *out, uint32_t *out_size);
-
+                                               uint32_t payloadLen, void *data, uint32_t data_size,
+                                               void *aad, uint32_t aad_size, void *tag, uint32_t tag_size,
+                                               void *out, uint32_t *out_size);
 #endif // __CRYPTO_AUTH_H__
diff --git a/ta/include/crypto_padding.h b/ta/include/crypto_padding.h
new file mode 100644 (file)
index 0000000..74fa3c8
--- /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_padding.c
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (padding)
+ */
+
+#ifndef _CRYPTO_PADDING_H_
+#define _CRYPTO_PADDING_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef enum
+{
+       KM_PADDING_ZERO = 1, // not reversable - should be used only for hashes/keys, not for data
+       KM_PADDING_PKCS7,
+} PaddingMode;
+
+uint32_t KM_CalculatePaddedSize(PaddingMode padding, uint32_t block_size, uint32_t data_size);
+int KM_PadBuffer(PaddingMode padding, uint32_t block_size, void *in, uint32_t in_size,
+                               void *out, uint32_t *out_size);
+int KM_UnpadBuffer(PaddingMode padding, void *buffer, uint32_t *buffer_size);
+
+#endif // _CRYPTO_PADDING_H_
\ No newline at end of file
index e719198b9f88fbcba7e93212110bc6d1bd433d03..a8e19c25d9ed4bc3782e7acae909c365dc497808 100644 (file)
@@ -29,6 +29,7 @@
 #include <crypto_auth.h>
 #include <crypto_derive.h>
 #include <crypto_digest.h>
+#include <crypto_padding.h>
 #include <km_serialization.h>
 #include <cmd_exec.h>
 #include <log.h>
@@ -43,6 +44,8 @@
 const uint32_t AES_BLOCK_SIZE = 16; // in bytes
 const uint32_t RSA_BLOCK_SIZE = 512; // in bytes, assumes max RSA key size 4096 bits
 const uint32_t PBKDF2_ITERATIONS = 1024;
+const PaddingMode PADDING_MODE = KM_PADDING_PKCS7;
+
 
 static uint32_t KM_AlgoType2TeeType(int algo)
 {
@@ -57,14 +60,10 @@ static uint32_t KM_AlgoType2TeeType(int algo)
 static uint32_t KM_Cmd2TeeMode(int cmd)
 {
        switch (cmd) {
-       case CMD_ENCRYPT:
-               return TEE_MODE_ENCRYPT;
-       case CMD_DECRYPT:
-               return TEE_MODE_DECRYPT;
-       default:
-               return 0;
+       case CMD_ENCRYPT: return TEE_MODE_ENCRYPT;
+       case CMD_DECRYPT: return TEE_MODE_DECRYPT;
+       default: return 0;
        }
-       return 0;
 }
 
 static uint32_t KM_Algo2TeeAlgo(int algo)
@@ -74,7 +73,7 @@ static uint32_t KM_Algo2TeeAlgo(int algo)
        case ALGO_AES_CBC: return TEE_ALG_AES_CBC_NOPAD;
        case ALGO_AES_CFB: return KM_TA_ALG_AES_CFB;
        case ALGO_AES_GCM: return TEE_ALG_AES_GCM;
-       case ALGO_RSA: return TEE_ALG_RSA_NOPAD;
+       case ALGO_RSA: return TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1;
        default: return 0;
        }
 }
@@ -144,8 +143,6 @@ static TEE_Result KM_DeserializeInput(void* buffer, uint32_t buffer_size, Symmet
                }
        }
 
-       KM_ParamsDump(*input, *input_data, *iv_data, *key_data, *key_id_data, *ae_data, NULL, *tag_data);
-
        if (*input_data == NULL) {
                LOG("No InputData in input buffer");
                return TEE_ERROR_BAD_PARAMETERS;
@@ -185,6 +182,37 @@ static uint32_t KM_DigestSizeFromHash(int hash)
        }
 }
 
+static uint32_t KM_CheckAESKeySize(uint32_t type, uint32_t key_size)
+{
+       switch (type) {
+       case TEE_TYPE_AES:
+               switch (key_size) {
+               case 128:
+               case 192:
+               case 256:
+                       return 1;
+               default:
+                       return 0;
+               }
+       case TEE_TYPE_RSA_KEYPAIR:
+       case TEE_TYPE_DSA_KEYPAIR: {
+               switch (key_size) {
+               case 512:
+               case 1024:
+               case 2048:
+               case 3072:
+               case 4096:
+                       return 1;
+               default:
+                       return 0;
+               }
+       }
+       default:
+               LOG("Invalid key type provided: %x", type);
+               return 0;
+       }
+}
+
 static uint32_t KM_AlgoHash2SignVerifyAlgo(int algo, int hash)
 {
        switch (algo) {
@@ -228,8 +256,8 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
                goto clean;
        }
 
-       if (type == 0) {
-               LOG("Unsupported key type provided: %u", type);
+       if (!KM_CheckAESKeySize(type, key_bits_size)) {
+               LOG("Unsupported key size provided: %u", key_bits_size);
                ret = TEE_ERROR_BAD_PARAMETERS;
                goto clean;
        }
@@ -240,16 +268,20 @@ TEE_Result KM_ExecCmdGenerateKey(TEE_Param param[4])
                goto clean;
        }
 
-       ret = KM_SaveKey(NULL, 0, hndl, objId, objId_size);
-       if (TEE_SUCCESS != ret) {
-               LOG("Failed to save generated key");
-               goto clean;
-       }
+       // ObjectID generation
+       TEE_GenerateRandom(objId, objId_size);
 
        if (0 != KM_ParamsSerializationInit(param[1].memref.buffer, param[1].memref.size,
-                       &input) || 0 != KM_ParamsSerializeKeyId(input, objId, objId_size)) {
+               &input) || 0 != KM_ParamsSerializeKeyId(input, objId, objId_size)) {
                LOG("Failed to serialize key to output buffer");
                ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
+       }
+
+       ret = KM_SaveKey(NULL, 0, hndl, objId, objId_size);
+       if (TEE_SUCCESS != ret) {
+               LOG("Failed to save generated key");
+               goto clean;
        }
 
 clean:
@@ -279,7 +311,8 @@ TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4])
                                                        &input, &input_data, &iv_data, NULL, NULL, NULL, NULL);
        if (ret != TEE_SUCCESS) {
                LOG("Failed to deserialize data from input buffer");
-               return TEE_ERROR_BAD_PARAMETERS;
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
        }
 
 
@@ -290,11 +323,14 @@ TEE_Result KM_ExecCmdGenerateKeyPwd(TEE_Param param[4])
                goto clean;
        }
 
+       // ObjectID generation
+       TEE_GenerateRandom(objId, objId_size);
+
        if (KM_ParamsSerializationInit(param[2].memref.buffer, param[2].memref.size,
-                                                                       &input != 0) ||
-               KM_ParamsSerializeKeyId(input, objId, objId_size) != 0) {
+               &input) != 0 || KM_ParamsSerializeKeyId(input, objId, objId_size) != 0) {
                LOG("Failed to serialize output data");
                ret = TEE_ERROR_BAD_PARAMETERS;
+               goto clean;
        }
 
        ret = KM_SaveKey(NULL, 0, derivedKey, objId, objId_size);
@@ -309,6 +345,13 @@ clean:
        return ret;
 }
 
+TEE_Result KM_ExecCmdImportKey(TEE_Param param[4])
+{
+       TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
+
+       return ret;
+}
+
 TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
 {
        TEE_Result ret = TEE_SUCCESS;
@@ -318,13 +361,11 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
        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 *in_padded = NULL;
+       uint32_t in_padded_size = 0;
        void *out = NULL;
        uint32_t out_size = 0;
-       uint32_t out_size_pad = 0;
 
        uint32_t type = 0;
        uint32_t algo = KM_Algo2TeeAlgo(param[0].value.a);
@@ -343,8 +384,7 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
                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;
+       out_size = KM_CalculatePaddedSize(KM_PADDING_PKCS7, AES_BLOCK_SIZE, input_data->data_size);
        out = malloc(out_size);
        if (out == NULL) {
                LOG("Failed to allocate output buffer");
@@ -352,25 +392,35 @@ TEE_Result KM_ExecCmdSymmetric(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 = (uint32_t*)malloc(iv_size);
-               if (iv == NULL) {
-                       LOG("Failed to allocate IV buffer");
+       // GCM and CTR modes does not need to be padded
+       if (CMD_ENCRYPT == commandID &&
+               TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+               in_padded_size = out_size;
+               in_padded = malloc(in_padded_size);
+               if (in_padded == NULL) {
+                       LOG("Failed to allocate input buffer for padded data");
                        ret = TEE_ERROR_OUT_OF_MEMORY;
                        goto clean;
                }
-               memset(iv, 0x00, iv_size);
+
+               if (KM_PadBuffer(PADDING_MODE, AES_BLOCK_SIZE, input_data->data, input_data->data_size,
+                                               in_padded, &in_padded_size)) {
+                       LOG("Error during padding operation");
+                       ret = TEE_ERROR_GENERIC;
+                       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);
+               if (CMD_ENCRYPT == commandID) {
+                       ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode,
+                                                                                       iv_data->data, iv_data->data_size,
+                                                                                       in_padded, in_padded_size, out, &out_size);
+               } else {
+                       ret = KM_SymmetricCrypt_AES_CFB(key_id_data->data, key_id_data->data_size, mode,
+                                                                                       iv_data->data, iv_data->data_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);
@@ -384,22 +434,35 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
                        goto clean;
                }
 
-               ret = KM_SymmetricCrypt(operation, iv, iv_size, input_data->data, input_data->data_size,
-                                                               out, &out_size);
+               if (CMD_ENCRYPT == commandID && TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+                       ret = KM_SymmetricCrypt(operation, iv_data->data, iv_data->data_size,
+                                                                       in_padded, in_padded_size, out, &out_size);
+               } else {
+                       ret = KM_SymmetricCrypt(operation, iv_data->data, iv_data->data_size,
+                                                                       input_data->data, input_data->data_size, out, &out_size);
+               }
        }
 
        if (TEE_SUCCESS != ret) {
                goto clean;
        }
 
+       if (CMD_DECRYPT == commandID && TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR_NOPAD != algo) {
+               if (KM_UnpadBuffer(PADDING_MODE, out, &out_size)) {
+                       LOG("Error during unpadding operation");
+                       ret = TEE_ERROR_GENERIC;
+                       goto clean;
+               }
+       }
+
        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;
        }
 
 clean:
+       free(in_padded);
        free(out);
-       if (ownIVFlag) free(iv);
        if (operation != TEE_HANDLE_NULL) TEE_FreeOperation(operation);
        return ret;
 }
@@ -425,7 +488,7 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4])
        uint32_t algo = KM_Algo2TeeAlgo(param[0].value.a);
        uint32_t mode = KM_Cmd2TeeMode(commandID);
 
-       if (ALGO_AES_GCM != param[0].value.a) {
+       if (param[0].value.a != ALGO_AES_GCM) {
                LOG("Invalid key type: %d.", param[0].value.a);
                return TEE_ERROR_BAD_PARAMETERS;
        }
@@ -448,7 +511,7 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4])
                return TEE_ERROR_BAD_PARAMETERS;
        }
 
-       if (KM_CheckAESMode(algo, ae_data->tagLen)) {
+       if (!KM_CheckAESMode(algo, ae_data->tagLen)) {
                LOG("Tag has invalid length. (tagLen=%d)", ae_data->tagLen);
                return TEE_ERROR_BAD_PARAMETERS;
        }
@@ -462,16 +525,11 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4])
                                                                                algo, key_data->key_bits_size, &hndl);
        }
        if (TEE_SUCCESS != ret) {
-               return ret;
+               goto clean;
        }
 
-       out_size = input_data->data_size + AES_BLOCK_SIZE;
+       out_size = KM_CalculatePaddedSize(KM_PADDING_PKCS7, AES_BLOCK_SIZE, input_data->data_size);
        out = malloc(out_size);
-       if (out == NULL) {
-               LOG("Failed to allocate output buffer");
-               ret = TEE_ERROR_OUT_OF_MEMORY;
-               goto clean;
-       }
 
        if (CMD_ENCRYPT == commandID) {
                tag_size = ae_data->tagLen / 8; // convert tag size to bytes
@@ -482,12 +540,14 @@ TEE_Result KM_ExecCmdAuth(uint32_t commandID, TEE_Param param[4])
                        goto clean;
                }
                ret = KM_AuthEncrypt(hndl, iv_data->data, iv_data->data_size, ae_data->tagLen,
-                                                       ae_data->AADLen, ae_data->payloadLen, input_data->data,
-                                                       input_data->data_size, out, &out_size, tag, &tag_size);
+                                                       ae_data->payloadLen, input_data->data,
+                                                       input_data->data_size, ae_data->aad.data,
+                                                       ae_data->aad.data_size, out, &out_size, tag, &tag_size);
        } else {
                ret = KM_AuthDecrypt(hndl, iv_data->data, iv_data->data_size, ae_data->tagLen,
-                                                       ae_data->AADLen, ae_data->payloadLen, input_data->data,
-                                                       input_data->data_size, tag_data->data, tag_data->data_size,
+                                                       ae_data->payloadLen, input_data->data,
+                                                       input_data->data_size, ae_data->aad.data,
+                                                       ae_data->aad.data_size, tag_data->data, tag_data->data_size,
                                                        out, &out_size);
        }
 
index 0cdae6e85433e1ce63fc55688a8e4abfd3be6f2d..dad2f6a216786902bd8f91f16d52f01bed0a5ca2 100644 (file)
@@ -28,14 +28,14 @@ TEE_Result KM_AsymmetricEncrypt(TEE_OperationHandle hndl, void *input, uint32_t
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       LOG("Asym encrypt");
+       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("Asym encrypt done");
+       LOG("LKDEBUG Asym encrypt done");
        return ret;
 }
 
@@ -44,14 +44,14 @@ TEE_Result KM_AsymmetricDecrypt(TEE_OperationHandle hndl, void *input, uint32_t
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       LOG("Asym decrypt");
+       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("Asym encrypt done");
+       LOG("LKDEBUG Asym decrypt done");
        return ret;
 }
 
@@ -60,14 +60,14 @@ TEE_Result KM_AsymmetricSign(TEE_OperationHandle hndl, void *digest, uint32_t di
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       LOG("Asym sign");
+       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("Asym sign done");
+       LOG("LKDEBUG Asym sign done");
        return ret;
 }
 
@@ -76,13 +76,13 @@ TEE_Result KM_AsymmetricVerify(TEE_OperationHandle hndl, void *digest, uint32_t
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       LOG("Asym verify");
+       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("Asym verify done");
+       LOG("LKDEBUG Asym verify done");
        return ret;
 }
\ No newline at end of file
index 2ed44d9ee95bca0ababb555b5f78a2b22d6693d4..6d100a221d49de4a9523b361b5d3791863ab061f 100644 (file)
 #include <log.h>
 
 TEE_Result KM_AuthEncrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
-                                                       uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
-                                                       void *out, uint32_t *out_size, void *tag, uint32_t *tag_size)
+                                                       uint32_t payloadLen, void *data, uint32_t data_size,
+                                                       void *aad, uint32_t aad_size, void *out, uint32_t *out_size,
+                                                       void *tag, uint32_t *tag_size)
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, AADLen, payloadLen);
+       if (iv == NULL || iv_size < 12) {
+               LOG("Provided IV is not big enough (%d bytes)", iv_size);
+               return TEE_ERROR_NOT_SUPPORTED;
+       }
+
+       ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, aad_size, payloadLen);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AEInit failed with error=%x.", ret);
                return ret;
        }
 
+       // AAD is not obligatory, so no error returned here if we don't have it
+       if (aad != NULL && aad_size > 0) {
+               TEE_AEUpdateAAD(hndl, aad, aad_size);
+       }
+
        ret = TEE_AEEncryptFinal(hndl, data, data_size, out, out_size, tag, tag_size);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AEEncryptFinal failed with error=%x.", ret);
@@ -44,16 +55,22 @@ TEE_Result KM_AuthEncrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size,
 }
 
 TEE_Result KM_AuthDecrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_size, uint32_t tagLen,
-                                                       uint32_t AADLen, uint32_t payloadLen, void *data, uint32_t data_size,
-                                                       void *tag, uint32_t tag_size, void *out, uint32_t *out_size)
+                                                       uint32_t payloadLen, void *data, uint32_t data_size,
+                                                       void *aad, uint32_t aad_size, void *tag, uint32_t tag_size,
+                                                       void *out, uint32_t *out_size)
 {
        TEE_Result ret = TEE_SUCCESS;
 
-       ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, AADLen, payloadLen);
+       ret = TEE_AEInit(hndl, iv, (size_t) iv_size, tagLen, aad_size, payloadLen);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AEInit failed with error=%x.", ret);
                return ret;
        }
+
+       if (aad != NULL && aad_size > 0) {
+               TEE_AEUpdateAAD(hndl, aad, aad_size);
+       }
+
        ret = TEE_AEDecryptFinal(hndl, data, data_size, out, out_size, tag, tag_size);
        if (TEE_SUCCESS != ret) {
                LOG("TEE_AEDecryptFinal failed with error=%x.", ret);
index b48a332e1e4e4cdf45fd20283e2e0c0f145b9f0d..14a8e94bedf0a4ad2493875ee2172bc5cf541c71 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include <crypto_derive.h>
+#include <crypto_padding.h>
 #include <internal.h>
 #include <log.h>
 #include <stdlib.h>
@@ -74,28 +75,40 @@ TEE_Result KM_DeriveKey(void *pwd, uint32_t pwd_size, void *salt, uint32_t salt_
        uint32_t b = 0, i = 0, j = 0, b_be = 0;
        uint32_t currentKeyBlock = 0;
        uint32_t bytesToCopy = 0;
+       char *hmacKeyBuffer = NULL;
        char *hmacInBuffer = NULL; // temporary to keep HMAC result
        char *blockBuffer = NULL; // actual buffer to keep the result of HMAC iterations
        char *keyBuffer = NULL; // buffer for derived key data
        char hmacOutBuffer[SHA1_SIZE_BYTES]; // temporary to keep HMAC output
+       size_t hmacKeySize = pwd_size;
        size_t hmacInBufferSize = salt_size + 4; // max buffer size for hmac's input
        size_t hmacOutBufferSize = SHA1_SIZE_BYTES;
        size_t blockBufferSize = SHA1_SIZE_BYTES;
        uint32_t keyBytesSize = key_bits_size / 8;
-       char *pwdptr = (char*)pwd;
 
-       if (pwd_size < 10 || pwd_size > 64) {
-               LOG("Unsupported password size - cannot derive");
+       if (hmacKeySize > 64) {
+               LOG("Too long password (%d bytes) - cannot derive", hmacKeySize);
                return TEE_ERROR_NOT_SUPPORTED;
        }
 
+       if (hmacKeySize < 10) {
+               hmacKeySize = 10;
+       }
+       hmacKeyBuffer = (char*)malloc(hmacKeySize);
+       if (pwd_size < 10) {
+               KM_PadBuffer(KM_PADDING_ZERO, 10, pwd, pwd_size, hmacKeyBuffer, &hmacKeySize);
+       } else {
+               memcpy(hmacKeyBuffer, pwd, pwd_size);
+       }
+
        if (out_key == NULL) {
                LOG("Incorrect key handle provided");
-               return TEE_ERROR_BAD_PARAMETERS;
+               ret = TEE_ERROR_BAD_PARAMETERS;
+               goto end;
        }
 
-       ret = KM_CreateOperationWithKey(pwd, pwd_size, TEE_TYPE_HMAC_SHA1, TEE_MODE_MAC,
-                                                                       TEE_ALG_HMAC_SHA1, pwd_size * 8, &hmacOp);
+       ret = KM_CreateOperationWithKey(hmacKeyBuffer, hmacKeySize, TEE_TYPE_HMAC_SHA1, TEE_MODE_MAC,
+                                                                       TEE_ALG_HMAC_SHA1, hmacKeySize * 8, &hmacOp);
        if (ret != TEE_SUCCESS) {
                LOG("Failed to create HMAC operation: %x", ret);
                goto end;
@@ -177,6 +190,7 @@ TEE_Result KM_DeriveKey(void *pwd, uint32_t pwd_size, void *salt, uint32_t salt_
        *out_key = keyHandle;
 
 end:
+       free(hmacKeyBuffer);
        free(hmacInBuffer);
        free(blockBuffer);
        free(keyBuffer);
diff --git a/ta/src/crypto_padding.c b/ta/src/crypto_padding.c
new file mode 100644 (file)
index 0000000..f4355be
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  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_padding.c
+ * @author      Lukasz Kostyra (l.kostyra@samsung.com)
+ * @version     1.0
+ * @brief       Implementation of Global Platform Internal API usage (padding)
+ */
+
+#include "crypto_padding.h"
+#include "log.h"
+
+
+uint32_t KM_CalculatePaddedSize(PaddingMode padding, uint32_t block_size, uint32_t data_size)
+{
+       uint32_t toPad = 0;
+
+       switch (padding) {
+       case KM_PADDING_ZERO: {
+               toPad = block_size - (data_size % block_size);
+               return data_size + toPad;
+       }
+       case KM_PADDING_PKCS7: {
+               toPad = block_size - (data_size % block_size);
+               if (toPad == 0) toPad = block_size;
+               return data_size + toPad;
+       }
+       default: {
+               LOG("Unsupported padding type %d", padding);
+               return 0;
+       }
+       }
+}
+
+void KM_PadBuffer_Zero(void *in, uint32_t in_size, void *out, unsigned char to_pad)
+{
+       memcpy(out, in, in_size);
+       memset(&((unsigned char*)out)[in_size], 0x0, to_pad);
+}
+
+void KM_PadBuffer_PKCS7(void *in, uint32_t in_size, void *out, unsigned char to_pad)
+{
+       memcpy(out, in, in_size);
+       memset(&((unsigned char*)out)[in_size], to_pad, to_pad);
+}
+
+int KM_PadBuffer(PaddingMode padding, uint32_t block_size, void *in, uint32_t in_size,
+                               void *out, uint32_t *out_size)
+{
+       uint32_t outputSize = 0;
+
+       if (in == NULL) {
+               LOG("Input data incorrect");
+               return -1;
+       }
+
+       if (out == NULL || out_size == NULL) {
+               LOG("Output buffer incorrect");
+               return -1;
+       }
+
+       outputSize = KM_CalculatePaddedSize(padding, block_size, in_size);
+       if (outputSize == 0) {
+               LOG("Unsupported padding type");
+               return -1;
+       }
+
+       if (outputSize > *out_size) {
+               LOG("Output buffer too small");
+               return -1;
+       }
+
+       switch (padding) {
+       case KM_PADDING_ZERO: {
+               KM_PadBuffer_Zero(in, in_size, out, outputSize - in_size);
+       }
+       case KM_PADDING_PKCS7: {
+               KM_PadBuffer_PKCS7(in, in_size, out, outputSize - in_size);
+               break;
+       }
+       default: {
+               LOG("Unsupported padding requested");
+               return -1;
+       }
+       }
+
+       *out_size = outputSize;
+       return 0;
+}
+
+void KM_UnpadBuffer_PKCS7(void *buffer, size_t buffer_size, size_t *was_padded)
+{
+       *was_padded = ((unsigned char*)buffer)[buffer_size - 1];
+}
+
+int KM_UnpadBuffer(PaddingMode padding, void *buffer, size_t *buffer_size)
+{
+       uint32_t wasPadded = 0;
+
+       if (buffer == NULL || buffer_size == NULL) {
+               LOG("Output buffer incorrect");
+               return -1;
+       }
+
+       switch (padding) {
+               case KM_PADDING_PKCS7:
+                       KM_UnpadBuffer_PKCS7(buffer, *buffer_size, &wasPadded);
+                       break;
+               default:
+                       LOG("Unsupported padding requested");
+                       return -1;
+       }
+
+       *buffer_size -= wasPadded;
+       return 0;
+}
\ No newline at end of file
index dc558623287daca756e69a4e788a88a76eb7298c..d3f16978a91e33ccfe9fbc33bb6e71af2568023f 100644 (file)
@@ -107,6 +107,11 @@ TEE_Result KM_SymmetricCrypt(TEE_OperationHandle hndl, void *iv, uint32_t iv_siz
 {
        TEE_Result ret = TEE_SUCCESS;
 
+       if (iv_size != 16) {
+               LOG("Incorrect IV provided (%d bytes)", iv_size);
+               return TEE_ERROR_BAD_PARAMETERS;
+       }
+
        LOG("Cipher init");
        TEE_CipherInit(hndl, iv, iv_size);
 
index 9c282596608d9e98f6b9ba9e1b6ca2240d0d573d..b2268a08f292aa2e42a774409aded5b65133738e 100644 (file)
 
 int KM_CheckAESMode(uint32_t algo, uint32_t tagLen)
 {
-       switch (tagLen) {
-               case 128:
-                       return 0;
-               case 120:
-                       return algo != TEE_ALG_AES_GCM;
-               case 112:
-                       return 0;
-               case 104:
-                       return algo != TEE_ALG_AES_GCM;
-               case 96:
-                       return 0;
-               case 64:
-                       return algo != TEE_ALG_AES_CCM;
-               case 48:
-                       return algo != TEE_ALG_AES_CCM;
-               case 32:
-                       return algo != TEE_ALG_AES_CCM;
-               default:
-                       return 1;
+       switch (algo) {
+       case TEE_ALG_AES_GCM: {
+               switch (tagLen) {
+                       case 128:
+                       case 120:
+                       case 112:
+                       case 104:
+                       case 96:
+                               return 1;
+                       default:
+                               return 0;
+               }
+       }
+       case TEE_ALG_AES_CCM: {
+               switch (tagLen) {
+                       case 128:
+                       case 112:
+                       case 96:
+                       case 64:
+                       case 48:
+                       case 32:
+                               return 1;
+                       default:
+                               return 0;
+               }
+       }
+       default: {
+               return 0;
+       }
        }
 }
 
@@ -187,8 +197,6 @@ TEE_Result KM_SaveKey(void *data, size_t data_size, TEE_ObjectHandle key, void *
        uint32_t flags =
                                TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_OVERWRITE;
 
-       TEE_GenerateRandom(objId, objId_size);
-
        ret = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE, objId, objId_size, flags, key, data,
                                                                        data_size, &pers_handl);
        TEE_CloseObject(pers_handl);
index a9588772f5cfc84d4e9fe85e6d6bfda23b465a55..cd45c38cfc8b5a13cda9e00dbab83e6abb560319 100644 (file)
@@ -64,6 +64,7 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
        switch (commandID) {
        case CMD_GENERATE_KEY: {
                LOGD("!!! Generate key !!!");
+               LOGD("Alg: %x", param[0].value.a);
                ret = KM_ExecCmdGenerateKey(param);
                break;
        }
@@ -74,12 +75,14 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sessionContext, uint32_t commandID,
        }
        case CMD_GENERATE_KEY_PWD: {
                LOGD("!!! Generate Key from PWD !!!");
+               LOGD("Alg: %x", param[0].value.a);
                ret = KM_ExecCmdGenerateKeyPwd(param);
                break;
        }
        case CMD_ENCRYPT:
        case CMD_DECRYPT: {
                LOGD("!!! %scrypt !!!", (commandID == CMD_ENCRYPT) ? "En" : "De");
+               LOGD("Alg: %x", param[0].value.a);
 
                if (ALGO_AES_CTR != param[0].value.a &&
                        ALGO_AES_CBC != param[0].value.a &&