1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2019 Huawei Technologies Co., Ltd 4 */ 5 6 #include <assert.h> 7 #include <crypto/crypto.h> 8 #include <crypto/crypto_impl.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <string_ext.h> 12 #include <tee_api_types.h> 13 #include <util.h> 14 15 #include "sm4.h" 16 17 struct sm4_cbc_ctx { 18 struct crypto_cipher_ctx ctx; 19 struct sm4_context state; 20 uint8_t iv[16]; 21 }; 22 23 static const struct crypto_cipher_ops sm4_cbc_ops; 24 25 static struct sm4_cbc_ctx *to_sm4_cbc_ctx(struct crypto_cipher_ctx *ctx) 26 { 27 assert(ctx && ctx->ops == &sm4_cbc_ops); 28 29 return container_of(ctx, struct sm4_cbc_ctx, ctx); 30 } 31 32 static TEE_Result sm4_cbc_init(struct crypto_cipher_ctx *ctx, 33 TEE_OperationMode mode, const uint8_t *key1, 34 size_t key1_len, const uint8_t *key2 __unused, 35 size_t key2_len __unused, 36 const uint8_t *iv, size_t iv_len) 37 { 38 struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); 39 40 if (key1_len != 16 || iv_len != sizeof(c->iv)) 41 return TEE_ERROR_BAD_PARAMETERS; 42 43 if (mode == TEE_MODE_ENCRYPT) 44 sm4_setkey_enc(&c->state, key1); 45 else 46 sm4_setkey_dec(&c->state, key1); 47 48 memcpy(c->iv, iv, sizeof(c->iv)); 49 50 return TEE_SUCCESS; 51 } 52 53 static TEE_Result sm4_cbc_update(struct crypto_cipher_ctx *ctx, 54 bool last_block __unused, 55 const uint8_t *data, size_t len, uint8_t *dst) 56 { 57 struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); 58 59 sm4_crypt_cbc(&c->state, len, c->iv, data, dst); 60 61 return TEE_SUCCESS; 62 } 63 64 static void sm4_cbc_final(struct crypto_cipher_ctx *ctx) 65 { 66 struct sm4_cbc_ctx *c = to_sm4_cbc_ctx(ctx); 67 68 memzero_explicit(&c->state, sizeof(c->state)); 69 memzero_explicit(&c->iv, sizeof(c->iv)); 70 } 71 72 static void sm4_cbc_free_ctx(struct crypto_cipher_ctx *ctx) 73 { 74 free(to_sm4_cbc_ctx(ctx)); 75 } 76 77 static void sm4_cbc_copy_state(struct crypto_cipher_ctx *dst_ctx, 78 struct crypto_cipher_ctx *src_ctx) 79 { 80 struct sm4_cbc_ctx *src = to_sm4_cbc_ctx(src_ctx); 81 struct sm4_cbc_ctx *dst = to_sm4_cbc_ctx(dst_ctx); 82 83 dst->state = src->state; 84 memcpy(dst->iv, src->iv, sizeof(src->iv)); 85 } 86 87 static const struct crypto_cipher_ops sm4_cbc_ops = { 88 .init = sm4_cbc_init, 89 .update = sm4_cbc_update, 90 .final = sm4_cbc_final, 91 .free_ctx = sm4_cbc_free_ctx, 92 .copy_state = sm4_cbc_copy_state, 93 }; 94 95 TEE_Result crypto_sm4_cbc_alloc_ctx(struct crypto_cipher_ctx **ctx_ret) 96 { 97 struct sm4_cbc_ctx *c = NULL; 98 99 c = calloc(1, sizeof(*c)); 100 if (!c) 101 return TEE_ERROR_OUT_OF_MEMORY; 102 103 c->ctx.ops = &sm4_cbc_ops; 104 *ctx_ret = &c->ctx; 105 106 return TEE_SUCCESS; 107 } 108