Skip to content

Commit

Permalink
Remove buffering for AES CTR
Browse files Browse the repository at this point in the history
CTR mode of AES algorithm turns block cipher into stream cipher.
It means that input data can has any size independent from block
size. It must be processed and result ciphertext must be
generated after each TEE_CipherUpdate function call. That is why
it is incorrect to apply for AES CTR the input buffering on
TEE_CipherUpdate call when size is not multiple of block size.

Signed-off-by: Bogdan Liulko <bogdan.liulko@globallogic.com>
Tested-by: Jerome Forissier <jerome.forissier> (HiKey)
Tested-by: Bogdan Liulko <bogdan.liulko@globallogic.com> (R-Car)
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
  • Loading branch information
bogdan-liulko committed Jun 6, 2017
1 parent afc0c18 commit d4a2293
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 16 deletions.
2 changes: 1 addition & 1 deletion core/tee/tee_cryp_utl.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo,
if (res != TEE_SUCCESS)
return res;
if ((len % block_size) != 0) {
if (!last_block)
if (!last_block && algo != TEE_ALG_AES_CTR)
return TEE_ERROR_BAD_PARAMETERS;

switch (algo) {
Expand Down
53 changes: 38 additions & 15 deletions lib/libutee/tee_api_operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
/* FALLTHROUGH */
case TEE_ALG_AES_ECB_NOPAD:
case TEE_ALG_AES_CBC_NOPAD:
case TEE_ALG_AES_CTR:
case TEE_ALG_AES_CCM:
case TEE_ALG_DES_ECB_NOPAD:
case TEE_ALG_DES_CBC_NOPAD:
Expand All @@ -145,6 +144,7 @@ TEE_Result TEE_AllocateOperation(TEE_OperationHandle *operation,
else
block_size = TEE_DES_BLOCK_SIZE;
/* FALLTHROUGH */
case TEE_ALG_AES_CTR:
case TEE_ALG_AES_GCM:
if (mode == TEE_MODE_ENCRYPT)
req_key_usage = TEE_USAGE_ENCRYPT;
Expand Down Expand Up @@ -993,8 +993,12 @@ TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
}

/* Calculate required dlen */
req_dlen = ((operation->buffer_offs + srcLen) / operation->block_size) *
operation->block_size;
if (operation->block_size > 1) {
req_dlen = ((operation->buffer_offs + srcLen) /
operation->block_size) * operation->block_size;
} else {
req_dlen = srcLen;
}
if (operation->buffer_two_blocks) {
if (req_dlen > operation->block_size * 2)
req_dlen -= operation->block_size * 2;
Expand All @@ -1013,8 +1017,18 @@ TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
}

dl = *destLen;
res = tee_buffer_update(operation, utee_cipher_update, srcData, srcLen,
destData, &dl);
if (operation->block_size > 1) {
res = tee_buffer_update(operation, utee_cipher_update, srcData,
srcLen, destData, &dl);
} else {
if (srcLen > 0) {
res = utee_cipher_update(operation->state, srcData,
srcLen, destData, &dl);
} else {
res = TEE_SUCCESS;
dl = 0;
}
}
*destLen = dl;

out:
Expand Down Expand Up @@ -1080,25 +1094,34 @@ TEE_Result TEE_CipherDoFinal(TEE_OperationHandle operation,
* data to the algorithm. Errors during feeding of data are fatal as we
* can't restore sync with this API.
*/
req_dlen = operation->buffer_offs + srcLen;
if (operation->block_size > 1) {
req_dlen = operation->buffer_offs + srcLen;
} else {
req_dlen = srcLen;
}
if (*destLen < req_dlen) {
*destLen = req_dlen;
res = TEE_ERROR_SHORT_BUFFER;
goto out;
}

tmp_dlen = *destLen - acc_dlen;
res = tee_buffer_update(operation, utee_cipher_update, srcData, srcLen,
dst, &tmp_dlen);
if (res != TEE_SUCCESS)
goto out;
if (operation->block_size > 1) {
res = tee_buffer_update(operation, utee_cipher_update,
srcData, srcLen, dst, &tmp_dlen);
if (res != TEE_SUCCESS)
goto out;

dst += tmp_dlen;
acc_dlen += tmp_dlen;
dst += tmp_dlen;
acc_dlen += tmp_dlen;

tmp_dlen = *destLen - acc_dlen;
res = utee_cipher_final(operation->state, operation->buffer,
operation->buffer_offs, dst, &tmp_dlen);
tmp_dlen = *destLen - acc_dlen;
res = utee_cipher_final(operation->state, operation->buffer,
operation->buffer_offs, dst, &tmp_dlen);
} else {
res = utee_cipher_final(operation->state, srcData,
srcLen, dst, &tmp_dlen);
}
if (res != TEE_SUCCESS)
goto out;

Expand Down

0 comments on commit d4a2293

Please sign in to comment.