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