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 that payload_len and aad_len will fit into ints */ 89 if (payload_len > INT_MAX || aad_len > INT_MAX) 90 return TEE_ERROR_BAD_PARAMETERS; 91 92 /* check the tag len */ 93 if ((tag_len < 4) || (tag_len > TEE_CCM_TAG_MAX_LENGTH) || 94 (tag_len % 2 != 0)) 95 return TEE_ERROR_NOT_SUPPORTED; 96 97 ltc_res = ccm_init(&ccm->ctx, ltc_cipherindex, key, key_len, 98 payload_len, tag_len, aad_len); 99 if (ltc_res != CRYPT_OK) 100 return TEE_ERROR_BAD_STATE; 101 102 /* Add the IV */ 103 ltc_res = ccm_add_nonce(&ccm->ctx, nonce, nonce_len); 104 if (ltc_res != CRYPT_OK) 105 return TEE_ERROR_BAD_STATE; 106 107 return TEE_SUCCESS; 108 } 109 110 static TEE_Result crypto_aes_ccm_update_aad(struct crypto_authenc_ctx *aectx, 111 const uint8_t *data, size_t len) 112 { 113 struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 114 int ltc_res = 0; 115 116 /* Add the AAD (note: aad can be NULL if aadlen == 0) */ 117 ltc_res = ccm_add_aad(&ccm->ctx, data, len); 118 if (ltc_res != CRYPT_OK) 119 return TEE_ERROR_BAD_STATE; 120 121 return TEE_SUCCESS; 122 } 123 124 static TEE_Result 125 crypto_aes_ccm_update_payload(struct crypto_authenc_ctx *aectx, 126 TEE_OperationMode mode, const uint8_t *src_data, 127 size_t len, uint8_t *dst_data) 128 { 129 int ltc_res = 0; 130 int dir = 0; 131 struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 132 unsigned char *pt = NULL; 133 unsigned char *ct = NULL; 134 135 if (mode == TEE_MODE_ENCRYPT) { 136 pt = (unsigned char *)src_data; 137 ct = dst_data; 138 dir = CCM_ENCRYPT; 139 } else { 140 pt = dst_data; 141 ct = (unsigned char *)src_data; 142 dir = CCM_DECRYPT; 143 } 144 ltc_res = ccm_process(&ccm->ctx, pt, len, ct, dir); 145 if (ltc_res != CRYPT_OK) 146 return TEE_ERROR_BAD_STATE; 147 148 return TEE_SUCCESS; 149 } 150 151 static TEE_Result crypto_aes_ccm_enc_final(struct crypto_authenc_ctx *aectx, 152 const uint8_t *src_data, 153 size_t len, uint8_t *dst_data, 154 uint8_t *dst_tag, 155 size_t *dst_tag_len) 156 { 157 TEE_Result res = TEE_SUCCESS; 158 struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 159 int ltc_res = 0; 160 161 /* Finalize the remaining buffer */ 162 res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_ENCRYPT, src_data, 163 len, dst_data); 164 if (res != TEE_SUCCESS) 165 return res; 166 167 /* Check the tag length */ 168 if (*dst_tag_len < ccm->tag_len) { 169 *dst_tag_len = ccm->tag_len; 170 return TEE_ERROR_SHORT_BUFFER; 171 } 172 *dst_tag_len = ccm->tag_len; 173 174 /* Compute the tag */ 175 ltc_res = ccm_done(&ccm->ctx, dst_tag, 176 (unsigned long *)dst_tag_len); 177 if (ltc_res != CRYPT_OK) 178 return TEE_ERROR_BAD_STATE; 179 180 return TEE_SUCCESS; 181 } 182 183 static TEE_Result crypto_aes_ccm_dec_final(struct crypto_authenc_ctx *aectx, 184 const uint8_t *src_data, size_t len, 185 uint8_t *dst_data, 186 const uint8_t *tag, size_t tag_len) 187 { 188 TEE_Result res = TEE_ERROR_BAD_STATE; 189 struct tee_ccm_state *ccm = to_tee_ccm_state(aectx); 190 int ltc_res = 0; 191 uint8_t dst_tag[TEE_CCM_TAG_MAX_LENGTH] = { 0 }; 192 unsigned long ltc_tag_len = tag_len; 193 194 if (tag_len == 0) 195 return TEE_ERROR_SHORT_BUFFER; 196 if (tag_len > TEE_CCM_TAG_MAX_LENGTH) 197 return TEE_ERROR_BAD_STATE; 198 199 /* Process the last buffer, if any */ 200 res = crypto_aes_ccm_update_payload(aectx, TEE_MODE_DECRYPT, src_data, 201 len, dst_data); 202 if (res != TEE_SUCCESS) 203 return res; 204 205 /* Finalize the authentication */ 206 ltc_res = ccm_done(&ccm->ctx, dst_tag, <c_tag_len); 207 if (ltc_res != CRYPT_OK) 208 return TEE_ERROR_BAD_STATE; 209 210 if (consttime_memcmp(dst_tag, tag, tag_len) != 0) 211 res = TEE_ERROR_MAC_INVALID; 212 else 213 res = TEE_SUCCESS; 214 return res; 215 } 216 217 static void crypto_aes_ccm_final(struct crypto_authenc_ctx *aectx) 218 { 219 ccm_reset(&to_tee_ccm_state(aectx)->ctx); 220 } 221 222 static const struct crypto_authenc_ops aes_ccm_ops = { 223 .init = crypto_aes_ccm_init, 224 .update_aad = crypto_aes_ccm_update_aad, 225 .update_payload = crypto_aes_ccm_update_payload, 226 .enc_final = crypto_aes_ccm_enc_final, 227 .dec_final = crypto_aes_ccm_dec_final, 228 .final = crypto_aes_ccm_final, 229 .free_ctx = crypto_aes_ccm_free_ctx, 230 .copy_state = crypto_aes_ccm_copy_state, 231 }; 232