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