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