1f1e9b21bSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2f1e9b21bSJens Wiklander /* 3f1e9b21bSJens Wiklander * Copyright (c) 2014-2019, Linaro Limited 4f1e9b21bSJens Wiklander */ 5f1e9b21bSJens Wiklander 6f1e9b21bSJens Wiklander #include <assert.h> 7f1e9b21bSJens Wiklander #include <crypto/crypto.h> 8f1e9b21bSJens Wiklander #include <crypto/crypto_impl.h> 9f1e9b21bSJens Wiklander #include <stdlib.h> 10f1e9b21bSJens Wiklander #include <string.h> 11*8411e6adSJerome Forissier #include <string_ext.h> 12f1e9b21bSJens Wiklander #include <tee_api_types.h> 135a913ee7SJerome Forissier #include <tomcrypt_private.h> 14f1e9b21bSJens Wiklander #include <util.h> 15f1e9b21bSJens Wiklander 16f1e9b21bSJens Wiklander #define TEE_CCM_KEY_MAX_LENGTH 32 17f1e9b21bSJens Wiklander #define TEE_CCM_NONCE_MAX_LENGTH 13 18f1e9b21bSJens Wiklander #define TEE_CCM_TAG_MAX_LENGTH 16 19f1e9b21bSJens Wiklander 20f1e9b21bSJens Wiklander struct tee_ccm_state { 21f1e9b21bSJens Wiklander struct crypto_authenc_ctx aectx; 22f1e9b21bSJens Wiklander ccm_state ctx; /* the ccm state as defined by LTC */ 23f1e9b21bSJens Wiklander size_t tag_len; /* tag length */ 24f1e9b21bSJens Wiklander }; 25f1e9b21bSJens Wiklander 26f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_ccm_ops; 27f1e9b21bSJens Wiklander 28f1e9b21bSJens Wiklander TEE_Result crypto_aes_ccm_alloc_ctx(struct crypto_authenc_ctx **ctx_ret) 29f1e9b21bSJens Wiklander { 30f1e9b21bSJens Wiklander struct tee_ccm_state *ctx = calloc(1, sizeof(*ctx)); 31f1e9b21bSJens Wiklander 32f1e9b21bSJens Wiklander if (!ctx) 33f1e9b21bSJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 34f1e9b21bSJens Wiklander ctx->aectx.ops = &aes_ccm_ops; 35f1e9b21bSJens Wiklander 36f1e9b21bSJens Wiklander *ctx_ret = &ctx->aectx; 37f1e9b21bSJens Wiklander return TEE_SUCCESS; 38f1e9b21bSJens Wiklander } 39f1e9b21bSJens Wiklander 40f1e9b21bSJens Wiklander static struct tee_ccm_state *to_tee_ccm_state(struct crypto_authenc_ctx *aectx) 41f1e9b21bSJens Wiklander { 42f1e9b21bSJens Wiklander assert(aectx && aectx->ops == &aes_ccm_ops); 43f1e9b21bSJens Wiklander 44f1e9b21bSJens Wiklander return container_of(aectx, struct tee_ccm_state, aectx); 45f1e9b21bSJens Wiklander } 46f1e9b21bSJens Wiklander 47f1e9b21bSJens Wiklander static void crypto_aes_ccm_free_ctx(struct crypto_authenc_ctx *aectx) 48f1e9b21bSJens Wiklander { 49f1e9b21bSJens Wiklander free(to_tee_ccm_state(aectx)); 50f1e9b21bSJens Wiklander } 51f1e9b21bSJens Wiklander 52f1e9b21bSJens Wiklander static void crypto_aes_ccm_copy_state(struct crypto_authenc_ctx *dst_aectx, 53f1e9b21bSJens Wiklander struct crypto_authenc_ctx *src_aectx) 54f1e9b21bSJens Wiklander { 55f1e9b21bSJens Wiklander struct tee_ccm_state *dst_ctx = to_tee_ccm_state(dst_aectx); 56f1e9b21bSJens Wiklander struct tee_ccm_state *src_ctx = to_tee_ccm_state(src_aectx); 57f1e9b21bSJens Wiklander 58f1e9b21bSJens Wiklander dst_ctx->ctx = src_ctx->ctx; 59f1e9b21bSJens Wiklander dst_ctx->tag_len = src_ctx->tag_len; 60f1e9b21bSJens Wiklander } 61f1e9b21bSJens Wiklander 62f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_init(struct crypto_authenc_ctx *aectx, 63f1e9b21bSJens Wiklander TEE_OperationMode mode __unused, 64f1e9b21bSJens Wiklander const uint8_t *key, size_t key_len, 65f1e9b21bSJens Wiklander const uint8_t *nonce, size_t nonce_len, 66f1e9b21bSJens Wiklander size_t tag_len, size_t aad_len, 67f1e9b21bSJens Wiklander size_t payload_len) 68f1e9b21bSJens Wiklander { 69f1e9b21bSJens Wiklander int ltc_res = 0; 70f1e9b21bSJens Wiklander int ltc_cipherindex = find_cipher("aes"); 71f1e9b21bSJens Wiklander struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 72f1e9b21bSJens Wiklander 73f1e9b21bSJens Wiklander if (ltc_cipherindex < 0) 74f1e9b21bSJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 75f1e9b21bSJens Wiklander 76f1e9b21bSJens Wiklander /* reset the state */ 77f1e9b21bSJens Wiklander memset(&ccm->ctx, 0, sizeof(ccm->ctx)); 78f1e9b21bSJens Wiklander ccm->tag_len = tag_len; 79f1e9b21bSJens Wiklander 80f1e9b21bSJens Wiklander /* Check the key length */ 81f1e9b21bSJens Wiklander if ((!key) || (key_len > TEE_CCM_KEY_MAX_LENGTH)) 82f1e9b21bSJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 83f1e9b21bSJens Wiklander 84f1e9b21bSJens Wiklander /* check the nonce */ 85f1e9b21bSJens Wiklander if (nonce_len > TEE_CCM_NONCE_MAX_LENGTH) 86f1e9b21bSJens Wiklander return TEE_ERROR_BAD_PARAMETERS; 87f1e9b21bSJens Wiklander 88f1e9b21bSJens Wiklander /* check the tag len */ 89f1e9b21bSJens Wiklander if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) || 90f1e9b21bSJens Wiklander (tag_len % 2 != 0)) 91f1e9b21bSJens Wiklander return TEE_ERROR_NOT_SUPPORTED; 92f1e9b21bSJens Wiklander 93f1e9b21bSJens Wiklander ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len, 94f1e9b21bSJens Wiklander payload_len, tag_len, aad_len); 95f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 96f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 97f1e9b21bSJens Wiklander 98f1e9b21bSJens Wiklander /* Add the IV */ 99f1e9b21bSJens Wiklander ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len); 100f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 101f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 102f1e9b21bSJens Wiklander 103f1e9b21bSJens Wiklander return TEE_SUCCESS; 104f1e9b21bSJens Wiklander } 105f1e9b21bSJens Wiklander 106f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx, 107f1e9b21bSJens Wiklander const uint8_t *data, size_t len) 108f1e9b21bSJens Wiklander { 109f1e9b21bSJens Wiklander struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 110f1e9b21bSJens Wiklander int ltc_res = 0; 111f1e9b21bSJens Wiklander 112f1e9b21bSJens Wiklander /* Add the AAD (note: aad can be NULL if aadlen == 0) */ 113f1e9b21bSJens Wiklander ltc_res = ccm_add_aad(&ccm->ctx, data, len); 114f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 115f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 116f1e9b21bSJens Wiklander 117f1e9b21bSJens Wiklander return TEE_SUCCESS; 118f1e9b21bSJens Wiklander } 119f1e9b21bSJens Wiklander 120f1e9b21bSJens Wiklander static TEE_Result 121f1e9b21bSJens Wiklander crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx, 122f1e9b21bSJens Wiklander TEE_OperationMode mode, const uint8_t *src_data, 123f1e9b21bSJens Wiklander size_t len, uint8_t *dst_data) 124f1e9b21bSJens Wiklander { 125f1e9b21bSJens Wiklander int ltc_res = 0; 126f1e9b21bSJens Wiklander int dir = 0; 127f1e9b21bSJens Wiklander struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 128f1e9b21bSJens Wiklander unsigned char *pt = NULL; 129f1e9b21bSJens Wiklander unsigned char *ct = NULL; 130f1e9b21bSJens Wiklander 131f1e9b21bSJens Wiklander if (mode == TEE_MODE_ENCRYPT) { 132f1e9b21bSJens Wiklander pt = (unsigned char *)src_data; 133f1e9b21bSJens Wiklander ct = dst_data; 134f1e9b21bSJens Wiklander dir = CCM_ENCRYPT; 135f1e9b21bSJens Wiklander } else { 136f1e9b21bSJens Wiklander pt = dst_data; 137f1e9b21bSJens Wiklander ct = (unsigned char *)src_data; 138f1e9b21bSJens Wiklander dir = CCM_DECRYPT; 139f1e9b21bSJens Wiklander } 140f1e9b21bSJens Wiklander ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir); 141f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 142f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 143f1e9b21bSJens Wiklander 144f1e9b21bSJens Wiklander return TEE_SUCCESS; 145f1e9b21bSJens Wiklander } 146f1e9b21bSJens Wiklander 147f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx, 148f1e9b21bSJens Wiklander const uint8_t *src_data, 149f1e9b21bSJens Wiklander size_t len, uint8_t *dst_data, 150f1e9b21bSJens Wiklander uint8_t *dst_tag, 151f1e9b21bSJens Wiklander size_t *dst_tag_len) 152f1e9b21bSJens Wiklander { 153f1e9b21bSJens Wiklander TEE_Result res = TEE_SUCCESS; 154f1e9b21bSJens Wiklander struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 155f1e9b21bSJens Wiklander int ltc_res = 0; 156f1e9b21bSJens Wiklander 157f1e9b21bSJens Wiklander /* Finalize the remaining buffer */ 158f1e9b21bSJens Wiklander res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, 159f1e9b21bSJens Wiklander len, dst_data); 160f1e9b21bSJens Wiklander if (res != TEE_SUCCESS) 161f1e9b21bSJens Wiklander return res; 162f1e9b21bSJens Wiklander 163f1e9b21bSJens Wiklander /* Check the tag length */ 164f1e9b21bSJens Wiklander if (*dst_tag_len < ccm->tag_len) { 165f1e9b21bSJens Wiklander *dst_tag_len = ccm->tag_len; 166f1e9b21bSJens Wiklander return TEE_ERROR_SHORT_BUFFER; 167f1e9b21bSJens Wiklander } 168f1e9b21bSJens Wiklander *dst_tag_len = ccm->tag_len; 169f1e9b21bSJens Wiklander 170f1e9b21bSJens Wiklander /* Compute the tag */ 171f1e9b21bSJens Wiklander ltc_res = ccm_done(&ccm->ctx, dst_tag, 172f1e9b21bSJens Wiklander (unsigned long *)dst_tag_len); 173f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 174f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 175f1e9b21bSJens Wiklander 176f1e9b21bSJens Wiklander return TEE_SUCCESS; 177f1e9b21bSJens Wiklander } 178f1e9b21bSJens Wiklander 179f1e9b21bSJens Wiklander static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx, 180f1e9b21bSJens Wiklander const uint8_t *src_data, size_t len, 181f1e9b21bSJens Wiklander uint8_t *dst_data, 182f1e9b21bSJens Wiklander const uint8_t *tag, size_t tag_len) 183f1e9b21bSJens Wiklander { 184f1e9b21bSJens Wiklander TEE_Result res = TEE_ERROR_BAD_STATE; 185f1e9b21bSJens Wiklander struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 186f1e9b21bSJens Wiklander int ltc_res = 0; 187f1e9b21bSJens Wiklander uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 }; 188f1e9b21bSJens Wiklander unsigned long ltc_tag_len = tag_len; 189f1e9b21bSJens Wiklander 190f1e9b21bSJens Wiklander if (tag_len == 0) 191f1e9b21bSJens Wiklander return TEE_ERROR_SHORT_BUFFER; 192f1e9b21bSJens Wiklander if (tag_len > TEE_CCM_TAG_MAX_LENGTH) 193f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 194f1e9b21bSJens Wiklander 195f1e9b21bSJens Wiklander /* Process the last buffer, if any */ 196f1e9b21bSJens Wiklander res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, 197f1e9b21bSJens Wiklander len, dst_data); 198f1e9b21bSJens Wiklander if (res != TEE_SUCCESS) 199f1e9b21bSJens Wiklander return res; 200f1e9b21bSJens Wiklander 201f1e9b21bSJens Wiklander /* Finalize the authentication */ 202f1e9b21bSJens Wiklander ltc_res = ccm_done(&ccm->ctx, dst_tag, <c_tag_len); 203f1e9b21bSJens Wiklander if (ltc_res != CRYPT_OK) 204f1e9b21bSJens Wiklander return TEE_ERROR_BAD_STATE; 205f1e9b21bSJens Wiklander 206f1e9b21bSJens Wiklander if (consttime_memcmp(dst_tag, tag, tag_len) != 0) 207f1e9b21bSJens Wiklander res = TEE_ERROR_MAC_INVALID; 208f1e9b21bSJens Wiklander else 209f1e9b21bSJens Wiklander res = TEE_SUCCESS; 210f1e9b21bSJens Wiklander return res; 211f1e9b21bSJens Wiklander } 212f1e9b21bSJens Wiklander 213f1e9b21bSJens Wiklander static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx) 214f1e9b21bSJens Wiklander { 215f1e9b21bSJens Wiklander ccm_reset(&to_tee_ccm_state(aectx)->ctx); 216f1e9b21bSJens Wiklander } 217f1e9b21bSJens Wiklander 218f1e9b21bSJens Wiklander static const struct crypto_authenc_ops aes_ccm_ops = { 219f1e9b21bSJens Wiklander .init = crypto_aes_ccm_init, 220f1e9b21bSJens Wiklander .update_aad = crypto_aes_ccm_update_aad, 221f1e9b21bSJens Wiklander .update_payload = crypto_aes_ccm_update_payload, 222f1e9b21bSJens Wiklander .enc_final = crypto_aes_ccm_enc_final, 223f1e9b21bSJens Wiklander .dec_final = crypto_aes_ccm_dec_final, 224f1e9b21bSJens Wiklander .final = crypto_aes_ccm_final, 225f1e9b21bSJens Wiklander .free_ctx = crypto_aes_ccm_free_ctx, 226f1e9b21bSJens Wiklander .copy_state = crypto_aes_ccm_copy_state, 227f1e9b21bSJens Wiklander }; 228