1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014-2019, Linaro Limited 4 */ 5 6 /* 7 * This is implemented here as being the plain text which is encoded with IV=0. 8 * Result of the CBC-MAC is the last 16-bytes cipher. 9 */ 10 11 #include <assert.h> 12 #include <crypto/crypto.h> 13 #include <crypto/crypto_impl.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <types_ext.h> 17 #include <util.h> 18 19 #define CBCMAC_MAX_BLOCK_LEN 16 20 21 struct crypto_cbc_mac_ctx { 22 struct crypto_mac_ctx ctx; 23 void *cbc_ctx; 24 uint32_t cbc_algo; 25 uint8_t block[CBCMAC_MAX_BLOCK_LEN]; 26 uint8_t digest[CBCMAC_MAX_BLOCK_LEN]; 27 unsigned char current_block_len; 28 unsigned char block_len; 29 bool is_computed; 30 bool pkcs5_pad; 31 }; 32 33 static const struct crypto_mac_ops crypto_cbc_mac_ops; 34 to_cbc_mac_ctx(struct crypto_mac_ctx * ctx)35 static struct crypto_cbc_mac_ctx *to_cbc_mac_ctx(struct crypto_mac_ctx *ctx) 36 { 37 assert(ctx && ctx->ops == &crypto_cbc_mac_ops); 38 39 return container_of(ctx, struct crypto_cbc_mac_ctx, ctx); 40 } 41 crypto_cbc_mac_init(struct crypto_mac_ctx * ctx,const uint8_t * key,size_t len)42 static TEE_Result crypto_cbc_mac_init(struct crypto_mac_ctx *ctx, 43 const uint8_t *key, size_t len) 44 { 45 struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); 46 47 memset(mc->block, 0, sizeof(mc->block)); 48 memset(mc->digest, 0, sizeof(mc->digest)); 49 mc->current_block_len = 0; 50 mc->is_computed = false; 51 52 /* IV should be zero and mc->block happens to be zero at this stage */ 53 return crypto_cipher_init(mc->cbc_ctx, TEE_MODE_ENCRYPT, key, len, 54 NULL, 0, mc->block, mc->block_len); 55 } 56 crypto_cbc_mac_update(struct crypto_mac_ctx * ctx,const uint8_t * data,size_t len)57 static TEE_Result crypto_cbc_mac_update(struct crypto_mac_ctx *ctx, 58 const uint8_t *data, size_t len) 59 { 60 size_t nblocks = 0; 61 size_t out_len = 0; 62 uint8_t *out_tmp = NULL; 63 uint8_t *out = NULL; 64 TEE_Result res = TEE_SUCCESS; 65 struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); 66 67 if ((mc->current_block_len > 0) && 68 (len + mc->current_block_len >= mc->block_len)) { 69 size_t pad_len = mc->block_len - mc->current_block_len; 70 71 memcpy(mc->block + mc->current_block_len, data, pad_len); 72 data += pad_len; 73 len -= pad_len; 74 res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, 75 false, mc->block, mc->block_len, 76 mc->digest); 77 if (res) 78 return res; 79 mc->is_computed = 1; 80 mc->current_block_len = 0; 81 } 82 83 nblocks = MIN(len / mc->block_len, 84 (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); 85 if (nblocks > 1) 86 out_tmp = malloc(nblocks * mc->block_len); 87 88 while (len >= mc->block_len) { 89 nblocks = MIN(len / mc->block_len, 90 (size_t)CFG_CRYPTO_CBC_MAC_BUNDLE_BLOCKS); 91 92 if (nblocks > 1 && out_tmp) { 93 out_len = nblocks * mc->block_len; 94 out = out_tmp; 95 } else { 96 out_len = mc->block_len; 97 out = mc->digest; 98 nblocks = 1; 99 } 100 101 res = crypto_cipher_update(mc->cbc_ctx, TEE_MODE_ENCRYPT, 102 false, data, out_len, out); 103 if (res) 104 goto out; 105 mc->is_computed = 1; 106 data += out_len; 107 len -= out_len; 108 if (nblocks > 1 && len < mc->block_len) { 109 assert(out_tmp); 110 /* Copy last block of output */ 111 memcpy(mc->digest, out_tmp + out_len - mc->block_len, 112 mc->block_len); 113 } 114 } 115 116 if (len > 0) { 117 assert(mc->current_block_len + len < mc->block_len); 118 memcpy(mc->block + mc->current_block_len, data, len); 119 mc->current_block_len += len; 120 } 121 122 out: 123 free(out_tmp); 124 return res; 125 } 126 crypto_cbc_mac_final(struct crypto_mac_ctx * ctx,uint8_t * digest,size_t digest_len)127 static TEE_Result crypto_cbc_mac_final(struct crypto_mac_ctx *ctx, 128 uint8_t *digest, size_t digest_len) 129 { 130 struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); 131 132 if (mc->pkcs5_pad) { 133 /* 134 * Padding is in whole bytes. The value of each added 135 * byte is the number of bytes that are added, i.e. N 136 * bytes, each of value N are added 137 */ 138 size_t pad_len = mc->block_len - mc->current_block_len; 139 140 memset(mc->block + mc->current_block_len, pad_len, pad_len); 141 mc->current_block_len = 0; 142 if (crypto_cbc_mac_update(ctx, mc->block, mc->block_len)) 143 return TEE_ERROR_BAD_STATE; 144 } 145 146 if (!mc->is_computed || mc->current_block_len) 147 return TEE_ERROR_BAD_STATE; 148 149 memcpy(digest, mc->digest, MIN(digest_len, mc->block_len)); 150 crypto_cipher_final(mc->cbc_ctx); 151 152 return TEE_SUCCESS; 153 } 154 crypto_cbc_mac_free_ctx(struct crypto_mac_ctx * ctx)155 static void crypto_cbc_mac_free_ctx(struct crypto_mac_ctx *ctx) 156 { 157 struct crypto_cbc_mac_ctx *mc = to_cbc_mac_ctx(ctx); 158 159 crypto_cipher_free_ctx(mc->cbc_ctx); 160 free(mc); 161 } 162 crypto_cbc_mac_copy_state(struct crypto_mac_ctx * dst_ctx,struct crypto_mac_ctx * src_ctx)163 static void crypto_cbc_mac_copy_state(struct crypto_mac_ctx *dst_ctx, 164 struct crypto_mac_ctx *src_ctx) 165 { 166 struct crypto_cbc_mac_ctx *dst = to_cbc_mac_ctx(dst_ctx); 167 struct crypto_cbc_mac_ctx *src = to_cbc_mac_ctx(src_ctx); 168 169 assert(dst->block_len == src->block_len); 170 assert(dst->pkcs5_pad == src->pkcs5_pad); 171 assert(dst->cbc_algo == src->cbc_algo); 172 173 crypto_cipher_copy_state(dst->cbc_ctx, src->cbc_ctx); 174 memcpy(dst->block, src->block, sizeof(dst->block)); 175 memcpy(dst->digest, src->digest, sizeof(dst->digest)); 176 dst->current_block_len = src->current_block_len; 177 dst->is_computed = src->is_computed; 178 } 179 180 static const struct crypto_mac_ops crypto_cbc_mac_ops = { 181 .init = crypto_cbc_mac_init, 182 .update = crypto_cbc_mac_update, 183 .final = crypto_cbc_mac_final, 184 .free_ctx = crypto_cbc_mac_free_ctx, 185 .copy_state = crypto_cbc_mac_copy_state, 186 }; 187 crypto_cbc_mac_alloc_ctx(struct crypto_mac_ctx ** ctx_ret,uint32_t cbc_algo,bool pkcs5_pad)188 static TEE_Result crypto_cbc_mac_alloc_ctx(struct crypto_mac_ctx **ctx_ret, 189 uint32_t cbc_algo, bool pkcs5_pad) 190 { 191 TEE_Result res; 192 void *cbc_ctx = NULL; 193 struct crypto_cbc_mac_ctx *ctx = NULL; 194 size_t block_size = 0; 195 196 res = crypto_cipher_get_block_size(cbc_algo, &block_size); 197 if (res) 198 return res; 199 200 res = crypto_cipher_alloc_ctx(&cbc_ctx, cbc_algo); 201 if (res) 202 return res; 203 204 ctx = calloc(1, sizeof(*ctx)); 205 if (!ctx) { 206 crypto_cipher_free_ctx(cbc_ctx); 207 return TEE_ERROR_OUT_OF_MEMORY; 208 } 209 210 ctx->cbc_ctx = cbc_ctx; 211 ctx->cbc_algo = cbc_algo; 212 ctx->pkcs5_pad = pkcs5_pad; 213 ctx->block_len = block_size; 214 ctx->ctx.ops = &crypto_cbc_mac_ops; 215 *ctx_ret = &ctx->ctx; 216 217 return TEE_SUCCESS; 218 } 219 crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx ** ctx)220 TEE_Result crypto_aes_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) 221 { 222 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, false); 223 } 224 crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx ** ctx)225 TEE_Result crypto_aes_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) 226 { 227 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_AES_CBC_NOPAD, true); 228 } 229 crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx ** ctx)230 TEE_Result crypto_des_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) 231 { 232 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, false); 233 } 234 crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx ** ctx)235 TEE_Result crypto_des_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) 236 { 237 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES_CBC_NOPAD, true); 238 } 239 crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx ** ctx)240 TEE_Result crypto_des3_cbc_mac_nopad_alloc_ctx(struct crypto_mac_ctx **ctx) 241 { 242 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, false); 243 } 244 crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx ** ctx)245 TEE_Result crypto_des3_cbc_mac_pkcs5_alloc_ctx(struct crypto_mac_ctx **ctx) 246 { 247 return crypto_cbc_mac_alloc_ctx(ctx, TEE_ALG_DES3_CBC_NOPAD, true); 248 } 249