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