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