117c68af4SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 217c68af4SJens Wiklander /* 317c68af4SJens Wiklander * Copyright (c) 2014-2019, Linaro Limited 417c68af4SJens Wiklander */ 517c68af4SJens Wiklander 617c68af4SJens Wiklander #include <assert.h> 717c68af4SJens Wiklander #include <crypto/crypto.h> 817c68af4SJens Wiklander #include <crypto/crypto_impl.h> 917c68af4SJens Wiklander #include <stdlib.h> 10*cbda7091SJens Wiklander #include <string.h> 1117c68af4SJens Wiklander #include <tee_api_types.h> 1217c68af4SJens Wiklander #include <tee/tee_cryp_utl.h> 1317c68af4SJens Wiklander #include <util.h> 1417c68af4SJens Wiklander 1517c68af4SJens Wiklander 1617c68af4SJens Wiklander /* From libtomcrypt doc: 1717c68af4SJens Wiklander * Ciphertext stealing is a method of dealing with messages 1817c68af4SJens Wiklander * in CBC mode which are not a multiple of the block 1917c68af4SJens Wiklander * length. This is accomplished by encrypting the last 2017c68af4SJens Wiklander * ciphertext block in ECB mode, and XOR'ing the output 2117c68af4SJens Wiklander * against the last partial block of plaintext. LibTomCrypt 2217c68af4SJens Wiklander * does not support this mode directly but it is fairly 2317c68af4SJens Wiklander * easy to emulate with a call to the cipher's 2417c68af4SJens Wiklander * ecb encrypt() callback function. 2517c68af4SJens Wiklander * The more sane way to deal with partial blocks is to pad 2617c68af4SJens Wiklander * them with zeroes, and then use CBC normally 2717c68af4SJens Wiklander */ 2817c68af4SJens Wiklander 2917c68af4SJens Wiklander /* 3017c68af4SJens Wiklander * From Global Platform: CTS = CBC-CS3 3117c68af4SJens Wiklander */ 3217c68af4SJens Wiklander 3317c68af4SJens Wiklander struct cts_ctx { 3417c68af4SJens Wiklander struct crypto_cipher_ctx ctx; 3517c68af4SJens Wiklander struct crypto_cipher_ctx *ecb; 3617c68af4SJens Wiklander struct crypto_cipher_ctx *cbc; 3717c68af4SJens Wiklander TEE_OperationMode mode; 3817c68af4SJens Wiklander }; 3917c68af4SJens Wiklander 4017c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops; 4117c68af4SJens Wiklander 4217c68af4SJens Wiklander static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx) 4317c68af4SJens Wiklander { 4417c68af4SJens Wiklander assert(ctx && ctx->ops == &cts_ops); 4517c68af4SJens Wiklander 4617c68af4SJens Wiklander return container_of(ctx, struct cts_ctx, ctx); 4717c68af4SJens Wiklander } 4817c68af4SJens Wiklander 4917c68af4SJens Wiklander static TEE_Result cts_init(struct crypto_cipher_ctx *ctx, 5017c68af4SJens Wiklander TEE_OperationMode mode, const uint8_t *key1, 5117c68af4SJens Wiklander size_t key1_len, const uint8_t *key2, 5217c68af4SJens Wiklander size_t key2_len, const uint8_t *iv, size_t iv_len) 5317c68af4SJens Wiklander { 5417c68af4SJens Wiklander TEE_Result res = TEE_SUCCESS; 5517c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 5617c68af4SJens Wiklander 5717c68af4SJens Wiklander c->mode = mode; 5817c68af4SJens Wiklander 59*cbda7091SJens Wiklander res = crypto_cipher_init(c->ecb, mode, key1, key1_len, key2, key2_len, 60*cbda7091SJens Wiklander iv, iv_len); 6117c68af4SJens Wiklander if (res) 6217c68af4SJens Wiklander return res; 6317c68af4SJens Wiklander 64*cbda7091SJens Wiklander return crypto_cipher_init(c->cbc, mode, key1, key1_len, key2, key2_len, 65*cbda7091SJens Wiklander iv, iv_len); 66*cbda7091SJens Wiklander } 67*cbda7091SJens Wiklander 68*cbda7091SJens Wiklander /* 69*cbda7091SJens Wiklander * From http://en.wikipedia.org/wiki/Ciphertext_stealing 70*cbda7091SJens Wiklander * CBC ciphertext stealing encryption using a standard 71*cbda7091SJens Wiklander * CBC interface: 72*cbda7091SJens Wiklander * 1. Pad the last partial plaintext block with 0. 73*cbda7091SJens Wiklander * 2. Encrypt the whole padded plaintext using the 74*cbda7091SJens Wiklander * standard CBC mode. 75*cbda7091SJens Wiklander * 3. Swap the last two ciphertext blocks. 76*cbda7091SJens Wiklander * 4. Truncate the ciphertext to the length of the 77*cbda7091SJens Wiklander * original plaintext. 78*cbda7091SJens Wiklander * 79*cbda7091SJens Wiklander * CBC ciphertext stealing decryption using a standard 80*cbda7091SJens Wiklander * CBC interface 81*cbda7091SJens Wiklander * 1. Dn = Decrypt (K, Cn-1). Decrypt the second to last 82*cbda7091SJens Wiklander * ciphertext block. 83*cbda7091SJens Wiklander * 2. Cn = Cn || Tail (Dn, B-M). Pad the ciphertext to the 84*cbda7091SJens Wiklander * nearest multiple of the block size using the last 85*cbda7091SJens Wiklander * B-M bits of block cipher decryption of the 86*cbda7091SJens Wiklander * second-to-last ciphertext block. 87*cbda7091SJens Wiklander * 3. Swap the last two ciphertext blocks. 88*cbda7091SJens Wiklander * 4. Decrypt the (modified) ciphertext using the standard 89*cbda7091SJens Wiklander * CBC mode. 90*cbda7091SJens Wiklander * 5. Truncate the plaintext to the length of the original 91*cbda7091SJens Wiklander * ciphertext. 92*cbda7091SJens Wiklander */ 93*cbda7091SJens Wiklander static TEE_Result cbc_cts_update(void *cbc_ctx, void *ecb_ctx, 94*cbda7091SJens Wiklander TEE_OperationMode mode, bool last_block, 95*cbda7091SJens Wiklander const uint8_t *data, size_t len, uint8_t *dst) 96*cbda7091SJens Wiklander { 97*cbda7091SJens Wiklander TEE_Result res; 98*cbda7091SJens Wiklander int nb_blocks, len_last_block, block_size = 16; 99*cbda7091SJens Wiklander uint8_t tmp_block[64], tmp2_block[64]; 100*cbda7091SJens Wiklander 101*cbda7091SJens Wiklander if (!last_block) 102*cbda7091SJens Wiklander return tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, 103*cbda7091SJens Wiklander mode, last_block, data, len, dst); 104*cbda7091SJens Wiklander 105*cbda7091SJens Wiklander /* Compute the last block length and check constraints */ 106*cbda7091SJens Wiklander nb_blocks = ((len + block_size - 1) / block_size); 107*cbda7091SJens Wiklander if (nb_blocks < 2) 108*cbda7091SJens Wiklander return TEE_ERROR_BAD_STATE; 109*cbda7091SJens Wiklander len_last_block = len % block_size; 110*cbda7091SJens Wiklander if (len_last_block == 0) 111*cbda7091SJens Wiklander len_last_block = block_size; 112*cbda7091SJens Wiklander 113*cbda7091SJens Wiklander if (mode == TEE_MODE_ENCRYPT) { 114*cbda7091SJens Wiklander memcpy(tmp_block, 115*cbda7091SJens Wiklander data + ((nb_blocks - 1) * block_size), 116*cbda7091SJens Wiklander len_last_block); 117*cbda7091SJens Wiklander memset(tmp_block + len_last_block, 118*cbda7091SJens Wiklander 0, 119*cbda7091SJens Wiklander block_size - len_last_block); 120*cbda7091SJens Wiklander 121*cbda7091SJens Wiklander res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, 122*cbda7091SJens Wiklander mode, 0, data, 123*cbda7091SJens Wiklander (nb_blocks - 1) * block_size, dst); 124*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 125*cbda7091SJens Wiklander return res; 126*cbda7091SJens Wiklander 127*cbda7091SJens Wiklander memcpy(dst + (nb_blocks - 1) * block_size, 128*cbda7091SJens Wiklander dst + (nb_blocks - 2) * block_size, 129*cbda7091SJens Wiklander len_last_block); 130*cbda7091SJens Wiklander 131*cbda7091SJens Wiklander res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, 132*cbda7091SJens Wiklander mode, 0, tmp_block, block_size, 133*cbda7091SJens Wiklander dst + (nb_blocks - 2) * block_size); 134*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 135*cbda7091SJens Wiklander return res; 136*cbda7091SJens Wiklander } else { 137*cbda7091SJens Wiklander /* 1. Decrypt the second to last ciphertext block */ 138*cbda7091SJens Wiklander res = tee_do_cipher_update(ecb_ctx, TEE_ALG_AES_ECB_NOPAD, 139*cbda7091SJens Wiklander mode, 0, 140*cbda7091SJens Wiklander data + (nb_blocks - 2) * block_size, 141*cbda7091SJens Wiklander block_size, tmp2_block); 142*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 143*cbda7091SJens Wiklander return res; 144*cbda7091SJens Wiklander 145*cbda7091SJens Wiklander /* 2. Cn = Cn || Tail (Dn, B-M) */ 146*cbda7091SJens Wiklander memcpy(tmp_block, data + ((nb_blocks - 1) * block_size), 147*cbda7091SJens Wiklander len_last_block); 148*cbda7091SJens Wiklander memcpy(tmp_block + len_last_block, tmp2_block + len_last_block, 149*cbda7091SJens Wiklander block_size - len_last_block); 150*cbda7091SJens Wiklander 151*cbda7091SJens Wiklander /* 3. Swap the last two ciphertext blocks */ 152*cbda7091SJens Wiklander /* done by passing the correct buffers in step 4. */ 153*cbda7091SJens Wiklander 154*cbda7091SJens Wiklander /* 4. Decrypt the (modified) ciphertext */ 155*cbda7091SJens Wiklander if (nb_blocks > 2) { 156*cbda7091SJens Wiklander res = tee_do_cipher_update(cbc_ctx, 157*cbda7091SJens Wiklander TEE_ALG_AES_CBC_NOPAD, mode, 158*cbda7091SJens Wiklander 0, data, 159*cbda7091SJens Wiklander (nb_blocks - 2) * 160*cbda7091SJens Wiklander block_size, dst); 161*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 162*cbda7091SJens Wiklander return res; 163*cbda7091SJens Wiklander } 164*cbda7091SJens Wiklander 165*cbda7091SJens Wiklander res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, 166*cbda7091SJens Wiklander mode, 0, tmp_block, block_size, 167*cbda7091SJens Wiklander dst + 168*cbda7091SJens Wiklander ((nb_blocks - 2) * block_size)); 169*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 170*cbda7091SJens Wiklander return res; 171*cbda7091SJens Wiklander 172*cbda7091SJens Wiklander res = tee_do_cipher_update(cbc_ctx, TEE_ALG_AES_CBC_NOPAD, 173*cbda7091SJens Wiklander mode, 0, data + 174*cbda7091SJens Wiklander ((nb_blocks - 2) * block_size), 175*cbda7091SJens Wiklander block_size, tmp_block); 176*cbda7091SJens Wiklander if (res != TEE_SUCCESS) 177*cbda7091SJens Wiklander return res; 178*cbda7091SJens Wiklander 179*cbda7091SJens Wiklander /* 5. Truncate the plaintext */ 180*cbda7091SJens Wiklander memcpy(dst + (nb_blocks - 1) * block_size, tmp_block, 181*cbda7091SJens Wiklander len_last_block); 182*cbda7091SJens Wiklander } 183*cbda7091SJens Wiklander return TEE_SUCCESS; 18417c68af4SJens Wiklander } 18517c68af4SJens Wiklander 18617c68af4SJens Wiklander static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block, 18717c68af4SJens Wiklander const uint8_t *data, size_t len, uint8_t *dst) 18817c68af4SJens Wiklander { 18917c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 19017c68af4SJens Wiklander 191*cbda7091SJens Wiklander return cbc_cts_update(c->cbc, c->ecb, c->mode, last_block, data, len, 192*cbda7091SJens Wiklander dst); 19317c68af4SJens Wiklander } 19417c68af4SJens Wiklander 19517c68af4SJens Wiklander static void cts_final(struct crypto_cipher_ctx *ctx) 19617c68af4SJens Wiklander { 19717c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 19817c68af4SJens Wiklander 199*cbda7091SJens Wiklander crypto_cipher_final(c->cbc); 200*cbda7091SJens Wiklander crypto_cipher_final(c->ecb); 20117c68af4SJens Wiklander } 20217c68af4SJens Wiklander 20317c68af4SJens Wiklander static void cts_free_ctx(struct crypto_cipher_ctx *ctx) 20417c68af4SJens Wiklander { 20517c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 20617c68af4SJens Wiklander 207*cbda7091SJens Wiklander crypto_cipher_free_ctx(c->cbc); 208*cbda7091SJens Wiklander crypto_cipher_free_ctx(c->ecb); 20917c68af4SJens Wiklander free(c); 21017c68af4SJens Wiklander } 21117c68af4SJens Wiklander 21217c68af4SJens Wiklander static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx, 21317c68af4SJens Wiklander struct crypto_cipher_ctx *src_ctx) 21417c68af4SJens Wiklander { 21517c68af4SJens Wiklander struct cts_ctx *src = to_cts_ctx(src_ctx); 21617c68af4SJens Wiklander struct cts_ctx *dst = to_cts_ctx(dst_ctx); 21717c68af4SJens Wiklander 218*cbda7091SJens Wiklander crypto_cipher_copy_state(dst->cbc, src->cbc); 219*cbda7091SJens Wiklander crypto_cipher_copy_state(dst->ecb, src->ecb); 22017c68af4SJens Wiklander } 22117c68af4SJens Wiklander 22217c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops = { 22317c68af4SJens Wiklander .init = cts_init, 22417c68af4SJens Wiklander .update = cts_update, 22517c68af4SJens Wiklander .final = cts_final, 22617c68af4SJens Wiklander .free_ctx = cts_free_ctx, 22717c68af4SJens Wiklander .copy_state = cts_copy_state, 22817c68af4SJens Wiklander }; 22917c68af4SJens Wiklander 23017c68af4SJens Wiklander TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx) 23117c68af4SJens Wiklander { 23217c68af4SJens Wiklander TEE_Result res = TEE_SUCCESS; 23317c68af4SJens Wiklander struct cts_ctx *c = calloc(1, sizeof(*c)); 23417c68af4SJens Wiklander 23517c68af4SJens Wiklander if (!c) 23617c68af4SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 23717c68af4SJens Wiklander 23817c68af4SJens Wiklander res = crypto_aes_ecb_alloc_ctx(&c->ecb); 23917c68af4SJens Wiklander if (res) 24017c68af4SJens Wiklander goto err; 24117c68af4SJens Wiklander res = crypto_aes_cbc_alloc_ctx(&c->cbc); 24217c68af4SJens Wiklander if (res) 24317c68af4SJens Wiklander goto err; 24417c68af4SJens Wiklander 24517c68af4SJens Wiklander c->ctx.ops = &cts_ops; 24617c68af4SJens Wiklander *ctx = &c->ctx; 24717c68af4SJens Wiklander 24817c68af4SJens Wiklander return TEE_SUCCESS; 24917c68af4SJens Wiklander err: 250*cbda7091SJens Wiklander crypto_cipher_free_ctx(c->ecb); 25117c68af4SJens Wiklander free(c); 25217c68af4SJens Wiklander 25317c68af4SJens Wiklander return res; 25417c68af4SJens Wiklander } 255