Disable padding in stream ciphers 88/202188/2
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 21 Mar 2019 15:23:13 +0000 (16:23 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 26 Mar 2019 13:59:30 +0000 (14:59 +0100)
Stream ciphers like CFB or CTR should not be padded.

Adjust CFB implementation to work as a stream cipher. Remove unnecessary padding
in other cases.

Change-Id: Ibc12fa523898ddca0ab9296eaf8500c242d6f8e6

ta/include/internal.h
ta/src/cmd_exec.c
ta/src/crypto_symmetric.c

index 19c5d29f078f3b9f0fea17bd42919e9a53153c4f..e592ec12d66cc5c90b2efacdddd1eb2d0ffed741 100644 (file)
 
 #define S_VAR_NOT_USED(variable) (void)(variable);
 
-#ifdef TEF_BUILD_SIMULATOR
-#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);
index 1803ce751fee124e00ad4f72fa910fa2b21f631f..7ba1a4be84175b1f82640175d200a8a70ed972e1 100644 (file)
@@ -790,18 +790,12 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
                }
        }
 
-       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;
-       }
+       out_size = input_data->data_size;
+
+       // Only CBC is a block cipher and needs to be padded
+       if (commandID == CMD_ENCRYPT && algo == TEE_ALG_AES_CBC_NOPAD) {
+               out_size = KM_CalculatePaddedSize(KM_PADDING_PKCS7, AES_BLOCK_SIZE, input_data->data_size);
 
-       // GCM and CTR modes does not need to be padded
-       if (commandID == CMD_ENCRYPT &&
-               algo != TEE_ALG_AES_GCM &&
-               algo != TEE_ALG_AES_CTR) {
                in_padded_size = out_size;
                in_padded = malloc(in_padded_size);
                if (in_padded == NULL) {
@@ -818,6 +812,13 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
                }
        }
 
+       out = malloc(out_size);
+       if (out == NULL) {
+               LOG("Failed to allocate output buffer");
+               ret = TEE_ERROR_OUT_OF_MEMORY;
+               goto clean;
+       }
+
        // open key and (if needed) decrypt it
        if (pwd_data != NULL) {
                ret = KM_DecryptKey(key_id_data->data, key_id_data->data_size, pwd_data, &key);
@@ -831,22 +832,15 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
        }
 
        if (algo == KM_TA_ALG_AES_CFB) {
-               if (CMD_ENCRYPT == commandID) {
-                       ret = KM_SymmetricCrypt_AES_CFB(key, mode, iv_data->data, iv_data->data_size,
-                                                                                       in_padded, in_padded_size, out, &out_size);
-               } else {
-                       ret = KM_SymmetricCrypt_AES_CFB(key, mode, iv_data->data, iv_data->data_size,
-                                                                                       input_data->data, input_data->data_size, out, &out_size);
-               }
+               ret = KM_SymmetricCrypt_AES_CFB(key, mode, iv_data->data, iv_data->data_size,
+                                                                               input_data->data, input_data->data_size, out, &out_size);
        } else {
                ret = KM_CreateOperation(key, algo, mode, &operation);
                if (TEE_SUCCESS != ret) {
                        goto clean;
                }
 
-               if (commandID == CMD_ENCRYPT &&
-                       algo != TEE_ALG_AES_GCM &&
-                       algo != TEE_ALG_AES_CTR) {
+               if (commandID == CMD_ENCRYPT && algo == TEE_ALG_AES_CBC_NOPAD) {
                        ret = KM_SymmetricCrypt(operation, iv_data->data, iv_data->data_size,
                                                                        in_padded, in_padded_size, out, &out_size);
                } else {
@@ -859,7 +853,7 @@ TEE_Result KM_ExecCmdSymmetric(uint32_t commandID, TEE_Param param[4])
                goto clean;
        }
 
-       if (CMD_DECRYPT == commandID && TEE_ALG_AES_GCM != algo && TEE_ALG_AES_CTR != algo) {
+       if (CMD_DECRYPT == commandID && algo == TEE_ALG_AES_CBC_NOPAD) {
                if (KM_UnpadBuffer(PADDING_MODE, out, &out_size)) {
                        LOG("Error during unpadding operation");
                        ret = TEE_ERROR_GENERIC;
index 42a041e731bfabedc2ea11ef4e40856689b31af5..4a2a9e3f0ef36b9475b983fe3df0cdf99b81e57c 100644 (file)
@@ -36,23 +36,18 @@ TEE_Result KM_SymmetricCrypt_AES_CFB(TEE_ObjectHandle key, uint32_t mode,
        TEE_Result ret = TEE_SUCCESS;
 
        uint32_t input_index = 0;
-       uint32_t ecb_input[AES_BLOCK_SIZE];
-       uint32_t ecb_output[AES_BLOCK_SIZE];
-       uint32_t* input_buf = (uint32_t*)input;
-       uint32_t* output_buf = (uint32_t*)output;
+       unsigned char ecb_input[AES_BLOCK_SIZE];
+       unsigned char ecb_output[AES_BLOCK_SIZE];
+       unsigned char* input_buf = (unsigned char*)input;
+       unsigned char* output_buf = (unsigned char*)output;
        uint32_t ecb_index = 0;
        uint32_t ecb_out_size = AES_BLOCK_SIZE;
+       uint32_t xor_size;
        if (output_size)
                *output_size = 0;
 
        // below code assumes AES CFB mode - 128/192/256 bit key
 
-       if (input_size % AES_BLOCK_SIZE != 0) {
-               LOG("Data not padded to block size (missing %u bytes)", AES_BLOCK_SIZE - (input_size % AES_BLOCK_SIZE));
-               ret = TEE_ERROR_BAD_PARAMETERS;
-               goto clean;
-       }
-
        // CFB always uses AES in encryption mode
        ret = KM_CreateOperation(key, TEE_ALG_AES_ECB_NOPAD, TEE_MODE_ENCRYPT, &op);
        if (ret != TEE_SUCCESS) {
@@ -63,7 +58,7 @@ TEE_Result KM_SymmetricCrypt_AES_CFB(TEE_ObjectHandle key, uint32_t mode,
        // copy IV as our starting data
        memcpy(ecb_input, iv, AES_BLOCK_SIZE);
 
-       for (input_index = 0; input_index < input_size / sizeof(uint32_t); input_index += (AES_BLOCK_SIZE / sizeof(uint32_t))) {
+       for (input_index = 0; input_index < input_size; input_index += AES_BLOCK_SIZE) {
                // pass IV/previous ciphertext through cipher block
                ret = KM_SymmetricCrypt(op, iv, iv_size, ecb_input, AES_BLOCK_SIZE, ecb_output, &ecb_out_size);
                if (ret != TEE_SUCCESS) {
@@ -77,21 +72,28 @@ TEE_Result KM_SymmetricCrypt_AES_CFB(TEE_ObjectHandle key, uint32_t mode,
                        goto clean;
                }
 
+               xor_size = AES_BLOCK_SIZE;
+
+               // is it the last, shorter than AES_BLOCK_SIZE fragment of input?
+               if (input_index + AES_BLOCK_SIZE > input_size) {
+                       xor_size = input_index + AES_BLOCK_SIZE - input_size;
+               }
+
                // result of this is now XORed with input (plaintext/ciphertext)
-               for (ecb_index = 0; ecb_index < AES_BLOCK_SIZE / sizeof(uint32_t); ++ecb_index) {
+               for (ecb_index = 0; ecb_index < xor_size; ++ecb_index) {
                        output_buf[input_index + ecb_index] = ecb_output[ecb_index] ^ input_buf[input_index + ecb_index];
                }
 
                if (mode == TEE_MODE_ENCRYPT) {
                        // the result of XOR is our encryption result and new ecb_input
-                       memcpy(ecb_input, &output_buf[input_index], AES_BLOCK_SIZE);
+                       memcpy(ecb_input, &output_buf[input_index], xor_size);
                } else {
                        // input ciphertext is our new ecb_input
-                       memcpy(ecb_input, &input_buf[input_index], AES_BLOCK_SIZE);
+                       memcpy(ecb_input, &input_buf[input_index], xor_size);
                }
 
                if (output_size)
-                       *output_size += AES_BLOCK_SIZE;
+                       *output_size += xor_size;
        }
 
 clean: