From 6f52ae30da34e0b37878a5968014079f5ac8cff6 Mon Sep 17 00:00:00 2001 From: Amey Avinash Raghatate Date: Fri, 8 Aug 2025 20:57:24 +0530 Subject: [PATCH] aes: add support for CCM and GCM algorithms Add support for two new AES algorithms: - TEE_ALG_AES_CCM - TEE_ALG_AES_GCM The user can now invoke: optee_example_aes Supported values for are: - TA_AES_ALGO_CCM - TA_AES_ALGO_GCM Signed-off-by: Amey Avinash Raghatate --- aes/host/main.c | 98 +++++++++++++++++++++++++++++++------- aes/ta/aes_ta.c | 101 ++++++++++++++++++++++++++++++++++++++++ aes/ta/include/aes_ta.h | 4 ++ 3 files changed, 186 insertions(+), 17 deletions(-) diff --git a/aes/host/main.c b/aes/host/main.c index 08676b4..78e5338 100644 --- a/aes/host/main.c +++ b/aes/host/main.c @@ -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; + + op.params[3].tmpref.buffer = (void *)tag; + 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; @@ -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]; @@ -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; @@ -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); @@ -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; diff --git a/aes/ta/aes_ta.c b/aes/ta/aes_ta.c index 21ef2f3..9b5e33a 100644 --- a/aes/ta/aes_ta.c +++ b/aes/ta/aes_ta.c @@ -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; @@ -362,6 +368,99 @@ static TEE_Result cipher_buffer(void *session, uint32_t param_types, params[1].memref.buffer, ¶ms[1].memref.size); } +static TEE_Result auth_aes_op(void *session, uint32_t param_types, TEE_Param params[4]) +{ + 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 */ @@ -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; diff --git a/aes/ta/include/aes_ta.h b/aes/ta/include/aes_ta.h index a711326..ba9c0a2 100644 --- a/aes/ta/include/aes_ta.h +++ b/aes/ta/include/aes_ta.h @@ -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) @@ -79,4 +81,6 @@ */ #define TA_AES_CMD_CIPHER 3 +#define CMD_AUTH_AES_INIT 4 + #endif /* __AES_TA_H */