// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2021, STMicroelectronics - All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "stm32_cryp.h" #define DES3_KEY_SIZE 24 struct stm32_cipher_ctx { struct crypto_cipher_ctx c_ctx; struct stm32_cryp_context cryp; enum stm32_cryp_algo_mode algo; }; static struct stm32_cipher_ctx * to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx) { assert(ctx); return container_of(ctx, struct stm32_cipher_ctx, c_ctx); } static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx); uint8_t temp_key[DES3_KEY_SIZE] = { 0 }; uint8_t *key = NULL; size_t key_size = 0; if (dinit->key1.length == 16 && (c->algo == STM32_CRYP_MODE_TDES_ECB || c->algo == STM32_CRYP_MODE_TDES_CBC)) { /* Manage DES2: ie K=K1.K2.K1 */ memcpy(temp_key, dinit->key1.data, dinit->key1.length); memcpy(temp_key + dinit->key1.length, dinit->key1.data, dinit->key1.length / 2); key_size = DES3_KEY_SIZE; key = temp_key; } else { key_size = dinit->key1.length; key = dinit->key1.data; } return stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo, key, key_size, dinit->iv.data, dinit->iv.length); } static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx); size_t len = MIN(dupdate->src.length, dupdate->dst.length); return stm32_cryp_update(&c->cryp, dupdate->last, dupdate->src.data, dupdate->dst.data, len); } static void stm32_cipher_final(void *ctx __unused) { } static void stm32_cipher_free(void *ctx) { struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx); free(c); } static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx) { struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx); struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx); memcpy(dst, src, sizeof(*dst)); } static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo) { struct stm32_cipher_ctx *c = calloc(1, sizeof(*c)); if (!c) return TEE_ERROR_OUT_OF_MEMORY; c->algo = algo; *ctx = &c->c_ctx; return TEE_SUCCESS; } /* * Allocate the SW cipher data context. * * @ctx [out] Caller context variable * @algo Algorithm ID of the context */ static TEE_Result stm32_cipher_allocate(void **ctx, uint32_t algo) { /* * Convert TEE_ALGO id to internal id */ switch (algo) { case TEE_ALG_DES_ECB_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_DES_ECB); case TEE_ALG_DES_CBC_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_DES_CBC); case TEE_ALG_DES3_ECB_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_ECB); case TEE_ALG_DES3_CBC_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_CBC); case TEE_ALG_AES_ECB_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_AES_ECB); case TEE_ALG_AES_CBC_NOPAD: return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CBC); case TEE_ALG_AES_CTR: return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CTR); default: return TEE_ERROR_NOT_IMPLEMENTED; } } static struct drvcrypt_cipher driver_cipher = { .alloc_ctx = &stm32_cipher_allocate, .free_ctx = &stm32_cipher_free, .init = &stm32_cipher_initialize, .update = &stm32_cipher_update, .final = &stm32_cipher_final, .copy_state = &stm32_cipher_copy_state, }; TEE_Result stm32_register_cipher(void) { return drvcrypt_register_cipher(&driver_cipher); }