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