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
#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);
}
}
- 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) {
}
}
+ 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);
}
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 {
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;
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) {
// 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) {
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: