Skip to content

aes: add support for CCM and GCM algorithms #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 81 additions & 17 deletions aes/host/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,42 @@ void cipher_buffer(struct test_ctx *ctx, char *in, char *out, size_t sz)
res, origin);
}

void auth_aes_ops(struct test_ctx *ctx, bool encrypt, void *in_buf, size_t
in_sz, void *out_buf, size_t *out_sz, void *tag, size_t
*tag_len)
{
TEEC_Operation op;
TEEC_Result res;
uint32_t err_origin;

memset(&op, 0, sizeof(op));

op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
TEEC_MEMREF_TEMP_OUTPUT,
TEEC_VALUE_INPUT,
TEEC_MEMREF_TEMP_OUTPUT);
op.params[0].tmpref.buffer = in_buf;
op.params[0].tmpref.size = in_sz;

op.params[1].tmpref.buffer = out_buf;
op.params[1].tmpref.size = *out_sz;

op.params[2].value.a = encrypt ? 1 : 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the ternary operator needed?


op.params[3].tmpref.buffer = (void *)tag;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tag is already a void pointer.

op.params[3].tmpref.size = *tag_len;

res = TEEC_InvokeCommand(&ctx->sess, CMD_AUTH_AES_INIT, &op, &err_origin);

if (res == TEEC_SUCCESS) {
*out_sz = op.params[1].tmpref.size;
*tag_len = op.params[3].tmpref.size;
} else {
printf("InvokeCommand failed with %x\n", res);
}

}

int main(int argc, char *argv[])
{
struct test_ctx ctx;
Expand All @@ -174,6 +210,13 @@ int main(int argc, char *argv[])
char ciph[AES_TEST_BUFFER_SIZE];
char temp[AES_TEST_BUFFER_SIZE];
char *algo;
const char *plaintext = "TestCCMMessage";
uint8_t ciphertext[80] = {0};
uint8_t decrypted[80] = {0};
size_t ct_len = sizeof(ciphertext);
size_t dec_len = sizeof(decrypted);
uint8_t tag[16] = {0};
size_t tag_len = 16;

if (argc > 1) {
algo = argv[1];
Expand All @@ -184,6 +227,10 @@ int main(int argc, char *argv[])
ctx.algo_num = TA_AES_ALGO_CBC;
} else if (strcmp(algo, "TA_AES_ALGO_CTR") == 0) {
ctx.algo_num = TA_AES_ALGO_CTR;
} else if (strcmp(algo, "TA_AES_ALGO_CCM") == 0) {
ctx.algo_num = TA_AES_ALGO_CCM;
} else if (strcmp(algo, "TA_AES_ALGO_GCM") == 0) {
ctx.algo_num = TA_AES_ALGO_GCM;
} else {
printf("%s algo is invalid\n", algo);
return -1;
Expand All @@ -203,13 +250,18 @@ int main(int argc, char *argv[])
memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
set_key(&ctx, key, AES_TEST_KEY_SIZE);

printf("Reset ciphering operation in TA (provides the initial vector)\n");
memset(iv, 0, sizeof(iv)); /* Load some dummy value */
set_iv(&ctx, iv, AES_BLOCK_SIZE);

printf("Encode buffer from TA\n");
memset(clear, 0x5a, sizeof(clear)); /* Load some dummy value */
cipher_buffer(&ctx, clear, ciph, AES_TEST_BUFFER_SIZE);
if ((ctx.algo_num == TA_AES_ALGO_CCM) || (ctx.algo_num == TA_AES_ALGO_GCM)) {
auth_aes_ops(&ctx, true, (void *)plaintext,
strlen(plaintext),
ciphertext, &ct_len, tag, &tag_len);
} else {
printf("Reset ciphering operation in TA (provides the initial vector)\n");
memset(iv, 0, sizeof(iv)); /* Load some dummy value */
set_iv(&ctx, iv, AES_BLOCK_SIZE);
printf("Encode buffer from TA\n");
memset(clear, 0x5a, sizeof(clear)); /* Load some dummy value */
cipher_buffer(&ctx, clear, ciph, AES_TEST_BUFFER_SIZE);
}

printf("Prepare decode operation\n");
prepare_aes(&ctx, DECODE);
Expand All @@ -218,18 +270,30 @@ int main(int argc, char *argv[])
memset(key, 0xa5, sizeof(key)); /* Load some dummy value */
set_key(&ctx, key, AES_TEST_KEY_SIZE);

printf("Reset ciphering operation in TA (provides the initial vector)\n");
memset(iv, 0, sizeof(iv)); /* Load some dummy value */
set_iv(&ctx, iv, AES_BLOCK_SIZE);

printf("Decode buffer from TA\n");
cipher_buffer(&ctx, ciph, temp, AES_TEST_BUFFER_SIZE);
if ((ctx.algo_num == TA_AES_ALGO_CCM) || (ctx.algo_num == TA_AES_ALGO_GCM)) {
auth_aes_ops(&ctx, false, ciphertext, ct_len, decrypted,
&dec_len, tag, &tag_len);
} else {
printf("Reset ciphering operation in TA (provides the initial vector)\n");
memset(iv, 0, sizeof(iv)); /* Load some dummy value */
set_iv(&ctx, iv, AES_BLOCK_SIZE);
printf("Decode buffer from TA\n");
cipher_buffer(&ctx, ciph, temp, AES_TEST_BUFFER_SIZE);
}

/* Check decoded is the clear content */
if (memcmp(clear, temp, AES_TEST_BUFFER_SIZE))
printf("Clear text and decoded text differ => ERROR\n");
else
printf("Clear text and decoded text match\n");
if ((ctx.algo_num == TA_AES_ALGO_CCM) || (ctx.algo_num == TA_AES_ALGO_GCM)) {
if (memcmp(plaintext, decrypted, strlen(plaintext)) == 0)
printf("CCM encryption/decryption successful!\n");
else
printf("Decryption failed or tag mismatch!\n");

} else {
if (memcmp(clear, temp, AES_TEST_BUFFER_SIZE))
printf("Clear text and decoded text differ => ERROR\n");
else
printf("Clear text and decoded text match\n");
}

terminate_tee_session(&ctx);
return 0;
Expand Down
101 changes: 101 additions & 0 deletions aes/ta/aes_ta.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ static TEE_Result ta2tee_algo_id(uint32_t param, uint32_t *algo)
case TA_AES_ALGO_CTR:
*algo = TEE_ALG_AES_CTR;
return TEE_SUCCESS;
case TA_AES_ALGO_CCM:
*algo = TEE_ALG_AES_CCM;
return TEE_SUCCESS;
case TA_AES_ALGO_GCM:
*algo = TEE_ALG_AES_GCM;
return TEE_SUCCESS;
default:
EMSG("Invalid algo %u", param);
return TEE_ERROR_BAD_PARAMETERS;
Expand Down Expand Up @@ -362,6 +368,99 @@ static TEE_Result cipher_buffer(void *session, uint32_t param_types,
params[1].memref.buffer, &params[1].memref.size);
}

static TEE_Result auth_aes_op(void *session, uint32_t param_types, TEE_Param params[4])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't auth_enc_op make more sense?

{
const uint32_t expected_pt =
TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
TEE_PARAM_TYPE_MEMREF_OUTPUT,
TEE_PARAM_TYPE_VALUE_INPUT,
TEE_PARAM_TYPE_MEMREF_OUTPUT);

if (param_types != expected_pt)
return TEE_ERROR_BAD_PARAMETERS;

struct aes_cipher *sess = (struct aes_cipher *)session;
TEE_Result res = TEE_ERROR_OUT_OF_MEMORY;
uint32_t tag_len = params[3].memref.size;
uint32_t out_len = params[1].memref.size;
void *in_buf = params[0].memref.buffer;
size_t in_sz = params[0].memref.size;
bool encrypt = (params[2].value.a != 0);
void *b2 = NULL;
void *b3 = NULL;

if (params[1].memref.buffer && params[1].memref.size) {
b2 = TEE_Malloc(params[1].memref.size, 0);
if (!b2)
goto out;
}

uint8_t nonce[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B};
DMSG("Initializing an Authentication Encryption operation");

res = TEE_AEInit(sess->op_handle, nonce, sizeof(nonce),
tag_len * 8, 0, in_sz);

if (res != TEE_SUCCESS)
return res;

if (encrypt) {
if (params[3].memref.buffer && params[3].memref.size) {
b3 = TEE_Malloc(params[3].memref.size, 0);
if (!b3)
goto out;
}
DMSG("AE Encryption");
res = TEE_AEEncryptFinal(sess->op_handle,
in_buf, in_sz,
b2, &out_len,
b3, &tag_len);

if (res == TEE_SUCCESS) {
if (b2) {
TEE_MemMove(params[1].memref.buffer, b2,
out_len);
}
if (b3) {
TEE_MemMove(params[3].memref.buffer, b3,
tag_len);
}

params[1].memref.size = out_len;
params[3].memref.size = tag_len;
} else {
EMSG("TEE_AEEncryptFinal failed with %x\n", res);
}
} else {

DMSG("AE Decryption");
res = TEE_AEDecryptFinal(sess->op_handle,
in_buf, in_sz,
b2, &out_len,
params[3].memref.buffer,
tag_len);
if (res == TEE_SUCCESS) {

if (b2) {
TEE_MemMove(params[1].memref.buffer, b2,
out_len);
}

params[1].memref.size = out_len;
params[3].memref.size = tag_len;
} else {
EMSG("TEE_AEDecryptFinal failed with %x\n", res);
}
}
out:
TEE_Free(b2);
TEE_Free(b3);

return res;

}

TEE_Result TA_CreateEntryPoint(void)
{
/* Nothing to do */
Expand Down Expand Up @@ -427,6 +526,8 @@ TEE_Result TA_InvokeCommandEntryPoint(void *session,
return reset_aes_iv(session, param_types, params);
case TA_AES_CMD_CIPHER:
return cipher_buffer(session, param_types, params);
case CMD_AUTH_AES_INIT:
return auth_aes_op(session, param_types, params);
default:
EMSG("Command ID 0x%x is not supported", cmd);
return TEE_ERROR_NOT_SUPPORTED;
Expand Down
4 changes: 4 additions & 0 deletions aes/ta/include/aes_ta.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#define TA_AES_ALGO_ECB 0
#define TA_AES_ALGO_CBC 1
#define TA_AES_ALGO_CTR 2
#define TA_AES_ALGO_CCM 3
#define TA_AES_ALGO_GCM 4

#define TA_AES_SIZE_128BIT (128 / 8)
#define TA_AES_SIZE_256BIT (256 / 8)
Expand Down Expand Up @@ -79,4 +81,6 @@
*/
#define TA_AES_CMD_CIPHER 3

#define CMD_AUTH_AES_INIT 4

#endif /* __AES_TA_H */