1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2018, ARM Limited 4 * Copyright (C) 2019, Linaro Limited 5 * Copyright (C) 2021, SumUp Services GmbH 6 */ 7 8 #include <assert.h> 9 #include <crypto/crypto.h> 10 #include <crypto/crypto_impl.h> 11 #include <kernel/panic.h> 12 #include <mbedtls/cipher.h> 13 #include <mbedtls/cmac.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <tee_api_types.h> 17 #include <utee_defines.h> 18 #include <util.h> 19 20 struct mbed_cmac_ctx { 21 struct crypto_mac_ctx mac_ctx; 22 mbedtls_cipher_context_t cipher_ctx; 23 mbedtls_cipher_id_t cipher_id; 24 }; 25 26 static const struct crypto_mac_ops mbed_cmac_ops; 27 28 static struct mbed_cmac_ctx *to_cmac_ctx(struct crypto_mac_ctx *ctx) 29 { 30 assert(ctx); 31 assert(ctx->ops == &mbed_cmac_ops); 32 33 return container_of(ctx, struct mbed_cmac_ctx, mac_ctx); 34 } 35 36 static TEE_Result mbed_cmac_init(struct crypto_mac_ctx *ctx, 37 const uint8_t *key, size_t len) 38 { 39 struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); 40 const mbedtls_cipher_info_t *cipher_info = NULL; 41 42 cipher_info = mbedtls_cipher_info_from_values(c->cipher_id, 43 len * 8, 44 MBEDTLS_MODE_ECB); 45 if (!cipher_info) 46 return TEE_ERROR_NOT_SUPPORTED; 47 48 if (mbedtls_cipher_setup_info(&c->cipher_ctx, cipher_info)) 49 return TEE_ERROR_BAD_STATE; 50 51 if (mbedtls_cipher_cmac_reset(&c->cipher_ctx)) 52 return TEE_ERROR_BAD_STATE; 53 54 if (mbedtls_cipher_cmac_starts(&c->cipher_ctx, key, len * 8)) 55 return TEE_ERROR_BAD_STATE; 56 57 return TEE_SUCCESS; 58 } 59 60 static TEE_Result mbed_cmac_update(struct crypto_mac_ctx *ctx, 61 const uint8_t *data, size_t len) 62 { 63 struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); 64 65 if (mbedtls_cipher_cmac_update(&c->cipher_ctx, data, len)) 66 return TEE_ERROR_BAD_STATE; 67 68 return TEE_SUCCESS; 69 } 70 71 static TEE_Result mbed_cmac_final(struct crypto_mac_ctx *ctx, 72 uint8_t *digest, size_t len) 73 { 74 struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); 75 size_t block_size = TEE_AES_BLOCK_SIZE; 76 uint8_t block_digest[TEE_AES_BLOCK_SIZE] = { }; 77 uint8_t *tmp_digest = NULL; 78 79 COMPILE_TIME_ASSERT(TEE_AES_BLOCK_SIZE >= TEE_DES_BLOCK_SIZE); 80 81 if (len == 0) 82 return TEE_ERROR_BAD_PARAMETERS; 83 84 if (c->cipher_id == MBEDTLS_CIPHER_ID_3DES) 85 block_size = TEE_DES_BLOCK_SIZE; 86 87 if (len < block_size) 88 tmp_digest = block_digest; /* use a tempory buffer */ 89 else 90 tmp_digest = digest; 91 92 if (mbedtls_cipher_cmac_finish(&c->cipher_ctx, tmp_digest)) 93 return TEE_ERROR_BAD_STATE; 94 95 if (len < block_size) 96 memcpy(digest, tmp_digest, len); 97 98 return TEE_SUCCESS; 99 } 100 101 static void mbed_cmac_free_ctx(struct crypto_mac_ctx *ctx) 102 { 103 struct mbed_cmac_ctx *c = to_cmac_ctx(ctx); 104 105 mbedtls_cipher_free(&c->cipher_ctx); 106 free(c); 107 } 108 109 static void mbed_cmac_copy_state(struct crypto_mac_ctx *dst_ctx, 110 struct crypto_mac_ctx *src_ctx) 111 { 112 struct mbed_cmac_ctx *src = to_cmac_ctx(src_ctx); 113 struct mbed_cmac_ctx *dst = to_cmac_ctx(dst_ctx); 114 115 if (mbedtls_cipher_clone(&dst->cipher_ctx, &src->cipher_ctx)) 116 panic(); 117 } 118 119 static const struct crypto_mac_ops mbed_cmac_ops = { 120 .init = mbed_cmac_init, 121 .update = mbed_cmac_update, 122 .final = mbed_cmac_final, 123 .free_ctx = mbed_cmac_free_ctx, 124 .copy_state = mbed_cmac_copy_state, 125 }; 126 127 static TEE_Result crypto_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, 128 const mbedtls_cipher_id_t cipher_id, 129 int key_bitlen) 130 { 131 int mbed_res = 0; 132 struct mbed_cmac_ctx *c = NULL; 133 const mbedtls_cipher_info_t *cipher_info = NULL; 134 135 /* 136 * Use a default key length for getting 'cipher_info' to do the 137 * setup. The 'cipher_info' will need to be re-assigned with final 138 * key length obtained in mbed_cmac_init() above. 139 * 140 * This is safe since 'mbedtls_cipher_base_t' (used for cipher 141 * context) uses the same fixed allocation all key lengths. 142 */ 143 cipher_info = mbedtls_cipher_info_from_values(cipher_id, key_bitlen, 144 MBEDTLS_MODE_ECB); 145 if (!cipher_info) 146 return TEE_ERROR_NOT_SUPPORTED; 147 148 c = calloc(1, sizeof(*c)); 149 if (!c) 150 return TEE_ERROR_OUT_OF_MEMORY; 151 152 c->cipher_id = cipher_id; 153 c->mac_ctx.ops = &mbed_cmac_ops; 154 155 mbedtls_cipher_init(&c->cipher_ctx); 156 mbed_res = mbedtls_cipher_setup(&c->cipher_ctx, cipher_info); 157 if (mbed_res) { 158 free(c); 159 if (mbed_res == MBEDTLS_ERR_CIPHER_ALLOC_FAILED) 160 return TEE_ERROR_OUT_OF_MEMORY; 161 return TEE_ERROR_NOT_SUPPORTED; 162 } 163 mbed_res = mbedtls_cipher_cmac_setup(&c->cipher_ctx); 164 if (mbed_res) { 165 free(c); 166 return TEE_ERROR_NOT_SUPPORTED; 167 } 168 169 *ctx_ret = &c->mac_ctx; 170 171 return TEE_SUCCESS; 172 } 173 174 TEE_Result crypto_des3_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) 175 { 176 return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_3DES, 192); 177 } 178 179 TEE_Result crypto_aes_cmac_alloc_ctx(struct crypto_mac_ctx **ctx_ret) 180 { 181 return crypto_cmac_alloc_ctx(ctx_ret, MBEDTLS_CIPHER_ID_AES, 128); 182 } 183