1*17c68af4SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*17c68af4SJens Wiklander /* 3*17c68af4SJens Wiklander * Copyright (c) 2014-2019, Linaro Limited 4*17c68af4SJens Wiklander */ 5*17c68af4SJens Wiklander 6*17c68af4SJens Wiklander #include <assert.h> 7*17c68af4SJens Wiklander #include <crypto/crypto.h> 8*17c68af4SJens Wiklander #include <crypto/crypto_impl.h> 9*17c68af4SJens Wiklander #include <stdlib.h> 10*17c68af4SJens Wiklander #include <tee_api_types.h> 11*17c68af4SJens Wiklander #include <tee/tee_cryp_utl.h> 12*17c68af4SJens Wiklander #include <util.h> 13*17c68af4SJens Wiklander 14*17c68af4SJens Wiklander 15*17c68af4SJens Wiklander /* From libtomcrypt doc: 16*17c68af4SJens Wiklander * Ciphertext stealing is a method of dealing with messages 17*17c68af4SJens Wiklander * in CBC mode which are not a multiple of the block 18*17c68af4SJens Wiklander * length. This is accomplished by encrypting the last 19*17c68af4SJens Wiklander * ciphertext block in ECB mode, and XOR'ing the output 20*17c68af4SJens Wiklander * against the last partial block of plaintext. LibTomCrypt 21*17c68af4SJens Wiklander * does not support this mode directly but it is fairly 22*17c68af4SJens Wiklander * easy to emulate with a call to the cipher's 23*17c68af4SJens Wiklander * ecb encrypt() callback function. 24*17c68af4SJens Wiklander * The more sane way to deal with partial blocks is to pad 25*17c68af4SJens Wiklander * them with zeroes, and then use CBC normally 26*17c68af4SJens Wiklander */ 27*17c68af4SJens Wiklander 28*17c68af4SJens Wiklander /* 29*17c68af4SJens Wiklander * From Global Platform: CTS = CBC-CS3 30*17c68af4SJens Wiklander */ 31*17c68af4SJens Wiklander 32*17c68af4SJens Wiklander struct cts_ctx { 33*17c68af4SJens Wiklander struct crypto_cipher_ctx ctx; 34*17c68af4SJens Wiklander struct crypto_cipher_ctx *ecb; 35*17c68af4SJens Wiklander struct crypto_cipher_ctx *cbc; 36*17c68af4SJens Wiklander TEE_OperationMode mode; 37*17c68af4SJens Wiklander }; 38*17c68af4SJens Wiklander 39*17c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops; 40*17c68af4SJens Wiklander 41*17c68af4SJens Wiklander static struct cts_ctx *to_cts_ctx(struct crypto_cipher_ctx *ctx) 42*17c68af4SJens Wiklander { 43*17c68af4SJens Wiklander assert(ctx && ctx->ops == &cts_ops); 44*17c68af4SJens Wiklander 45*17c68af4SJens Wiklander return container_of(ctx, struct cts_ctx, ctx); 46*17c68af4SJens Wiklander } 47*17c68af4SJens Wiklander 48*17c68af4SJens Wiklander static TEE_Result cts_init(struct crypto_cipher_ctx *ctx, 49*17c68af4SJens Wiklander TEE_OperationMode mode, const uint8_t *key1, 50*17c68af4SJens Wiklander size_t key1_len, const uint8_t *key2, 51*17c68af4SJens Wiklander size_t key2_len, const uint8_t *iv, size_t iv_len) 52*17c68af4SJens Wiklander { 53*17c68af4SJens Wiklander TEE_Result res = TEE_SUCCESS; 54*17c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 55*17c68af4SJens Wiklander 56*17c68af4SJens Wiklander c->mode = mode; 57*17c68af4SJens Wiklander 58*17c68af4SJens Wiklander res = crypto_cipher_init(c->ecb, TEE_ALG_AES_ECB_NOPAD, mode, key1, 59*17c68af4SJens Wiklander key1_len, key2, key2_len, iv, iv_len); 60*17c68af4SJens Wiklander if (res) 61*17c68af4SJens Wiklander return res; 62*17c68af4SJens Wiklander 63*17c68af4SJens Wiklander return crypto_cipher_init(c->cbc, TEE_ALG_AES_CBC_NOPAD, mode, key1, 64*17c68af4SJens Wiklander key1_len, key2, key2_len, iv, iv_len); 65*17c68af4SJens Wiklander } 66*17c68af4SJens Wiklander 67*17c68af4SJens Wiklander static TEE_Result cts_update(struct crypto_cipher_ctx *ctx, bool last_block, 68*17c68af4SJens Wiklander const uint8_t *data, size_t len, uint8_t *dst) 69*17c68af4SJens Wiklander { 70*17c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 71*17c68af4SJens Wiklander 72*17c68af4SJens Wiklander return tee_aes_cbc_cts_update(c->cbc, c->ecb, c->mode, last_block, 73*17c68af4SJens Wiklander data, len, dst); 74*17c68af4SJens Wiklander } 75*17c68af4SJens Wiklander 76*17c68af4SJens Wiklander static void cts_final(struct crypto_cipher_ctx *ctx) 77*17c68af4SJens Wiklander { 78*17c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 79*17c68af4SJens Wiklander 80*17c68af4SJens Wiklander crypto_cipher_final(c->cbc, TEE_ALG_AES_CBC_NOPAD); 81*17c68af4SJens Wiklander crypto_cipher_final(c->ecb, TEE_ALG_AES_ECB_NOPAD); 82*17c68af4SJens Wiklander } 83*17c68af4SJens Wiklander 84*17c68af4SJens Wiklander static void cts_free_ctx(struct crypto_cipher_ctx *ctx) 85*17c68af4SJens Wiklander { 86*17c68af4SJens Wiklander struct cts_ctx *c = to_cts_ctx(ctx); 87*17c68af4SJens Wiklander 88*17c68af4SJens Wiklander crypto_cipher_free_ctx(c->cbc, TEE_ALG_AES_CBC_NOPAD); 89*17c68af4SJens Wiklander crypto_cipher_free_ctx(c->ecb, TEE_ALG_AES_ECB_NOPAD); 90*17c68af4SJens Wiklander free(c); 91*17c68af4SJens Wiklander } 92*17c68af4SJens Wiklander 93*17c68af4SJens Wiklander static void cts_copy_state(struct crypto_cipher_ctx *dst_ctx, 94*17c68af4SJens Wiklander struct crypto_cipher_ctx *src_ctx) 95*17c68af4SJens Wiklander { 96*17c68af4SJens Wiklander struct cts_ctx *src = to_cts_ctx(src_ctx); 97*17c68af4SJens Wiklander struct cts_ctx *dst = to_cts_ctx(dst_ctx); 98*17c68af4SJens Wiklander 99*17c68af4SJens Wiklander crypto_cipher_copy_state(dst->cbc, src->cbc, TEE_ALG_AES_CBC_NOPAD); 100*17c68af4SJens Wiklander crypto_cipher_copy_state(dst->ecb, src->ecb, TEE_ALG_AES_ECB_NOPAD); 101*17c68af4SJens Wiklander } 102*17c68af4SJens Wiklander 103*17c68af4SJens Wiklander static const struct crypto_cipher_ops cts_ops = { 104*17c68af4SJens Wiklander .init = cts_init, 105*17c68af4SJens Wiklander .update = cts_update, 106*17c68af4SJens Wiklander .final = cts_final, 107*17c68af4SJens Wiklander .free_ctx = cts_free_ctx, 108*17c68af4SJens Wiklander .copy_state = cts_copy_state, 109*17c68af4SJens Wiklander }; 110*17c68af4SJens Wiklander 111*17c68af4SJens Wiklander TEE_Result crypto_aes_cts_alloc_ctx(struct crypto_cipher_ctx **ctx) 112*17c68af4SJens Wiklander { 113*17c68af4SJens Wiklander TEE_Result res = TEE_SUCCESS; 114*17c68af4SJens Wiklander struct cts_ctx *c = calloc(1, sizeof(*c)); 115*17c68af4SJens Wiklander 116*17c68af4SJens Wiklander if (!c) 117*17c68af4SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 118*17c68af4SJens Wiklander 119*17c68af4SJens Wiklander res = crypto_aes_ecb_alloc_ctx(&c->ecb); 120*17c68af4SJens Wiklander if (res) 121*17c68af4SJens Wiklander goto err; 122*17c68af4SJens Wiklander res = crypto_aes_cbc_alloc_ctx(&c->cbc); 123*17c68af4SJens Wiklander if (res) 124*17c68af4SJens Wiklander goto err; 125*17c68af4SJens Wiklander 126*17c68af4SJens Wiklander c->ctx.ops = &cts_ops; 127*17c68af4SJens Wiklander *ctx = &c->ctx; 128*17c68af4SJens Wiklander 129*17c68af4SJens Wiklander return TEE_SUCCESS; 130*17c68af4SJens Wiklander err: 131*17c68af4SJens Wiklander crypto_cipher_free_ctx(c->ecb, TEE_ALG_AES_ECB_NOPAD); 132*17c68af4SJens Wiklander free(c); 133*17c68af4SJens Wiklander 134*17c68af4SJens Wiklander return res; 135*17c68af4SJens Wiklander } 136