15e64ae67SNicolas Toromanoff // SPDX-License-Identifier: BSD-2-Clause
25e64ae67SNicolas Toromanoff /*
35e64ae67SNicolas Toromanoff * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
45e64ae67SNicolas Toromanoff */
55e64ae67SNicolas Toromanoff
65e64ae67SNicolas Toromanoff #include <assert.h>
75e64ae67SNicolas Toromanoff #include <crypto/crypto.h>
85e64ae67SNicolas Toromanoff #include <crypto/crypto_impl.h>
95e64ae67SNicolas Toromanoff #include <drvcrypt.h>
105e64ae67SNicolas Toromanoff #include <drvcrypt_cipher.h>
115e64ae67SNicolas Toromanoff #include <stdlib.h>
125e64ae67SNicolas Toromanoff #include <string.h>
135e64ae67SNicolas Toromanoff #include <tee_api_types.h>
145e64ae67SNicolas Toromanoff #include <util.h>
155e64ae67SNicolas Toromanoff
165e64ae67SNicolas Toromanoff #include "common.h"
175e64ae67SNicolas Toromanoff #include "stm32_cryp.h"
184320f5cfSThomas Bourgoin #include "stm32_saes.h"
195e64ae67SNicolas Toromanoff
205e64ae67SNicolas Toromanoff #define DES3_KEY_SIZE 24
215e64ae67SNicolas Toromanoff
224320f5cfSThomas Bourgoin struct cryp_ctx {
234320f5cfSThomas Bourgoin struct stm32_cryp_context ctx;
244320f5cfSThomas Bourgoin enum stm32_cryp_algo_mode algo;
254320f5cfSThomas Bourgoin };
264320f5cfSThomas Bourgoin
274320f5cfSThomas Bourgoin struct saes_ctx {
284320f5cfSThomas Bourgoin struct stm32_saes_context ctx;
294320f5cfSThomas Bourgoin enum stm32_saes_chaining_mode algo;
3003de2c7bSEtienne Carriere /* Fallback to software implementation on 192bit AES key */
3103de2c7bSEtienne Carriere bool use_fallback;
3203de2c7bSEtienne Carriere struct crypto_cipher_ctx *fallback_ctx;
334320f5cfSThomas Bourgoin };
344320f5cfSThomas Bourgoin
354320f5cfSThomas Bourgoin /*
364320f5cfSThomas Bourgoin * Internal peripheral context
374320f5cfSThomas Bourgoin * SAES and CRYP are registered under the same ID in the crypto framework.
384320f5cfSThomas Bourgoin * Therefore, only one of them can be registered.
394320f5cfSThomas Bourgoin */
404320f5cfSThomas Bourgoin
414320f5cfSThomas Bourgoin union ip_ctx {
424320f5cfSThomas Bourgoin struct saes_ctx saes;
434320f5cfSThomas Bourgoin struct cryp_ctx cryp;
444320f5cfSThomas Bourgoin };
454320f5cfSThomas Bourgoin
464320f5cfSThomas Bourgoin /* Internal Peripheral cipher ops*/
474320f5cfSThomas Bourgoin struct ip_cipher_ops {
484320f5cfSThomas Bourgoin TEE_Result (*init)(union ip_ctx *ctx, bool is_decrypt,
494320f5cfSThomas Bourgoin const uint8_t *key, size_t key_len,
504320f5cfSThomas Bourgoin const uint8_t *iv, size_t iv_len);
514320f5cfSThomas Bourgoin TEE_Result (*update)(union ip_ctx *ctx, bool last_block, uint8_t *src,
524320f5cfSThomas Bourgoin uint8_t *dst, size_t len);
5303de2c7bSEtienne Carriere void (*final)(union ip_ctx *ctx);
5403de2c7bSEtienne Carriere void (*copy_state)(union ip_ctx *dst_ctx, union ip_ctx *src_ctx);
554320f5cfSThomas Bourgoin };
564320f5cfSThomas Bourgoin
575e64ae67SNicolas Toromanoff struct stm32_cipher_ctx {
585e64ae67SNicolas Toromanoff struct crypto_cipher_ctx c_ctx;
594320f5cfSThomas Bourgoin union ip_ctx ip_ctx;
604320f5cfSThomas Bourgoin const struct ip_cipher_ops *ops;
614320f5cfSThomas Bourgoin };
624320f5cfSThomas Bourgoin
cryp_init(union ip_ctx * ip_ctx,bool is_decrypt,const uint8_t * key,size_t key_len,const uint8_t * iv,size_t iv_len)634320f5cfSThomas Bourgoin static TEE_Result cryp_init(union ip_ctx *ip_ctx, bool is_decrypt,
644320f5cfSThomas Bourgoin const uint8_t *key, size_t key_len,
654320f5cfSThomas Bourgoin const uint8_t *iv, size_t iv_len)
664320f5cfSThomas Bourgoin {
674320f5cfSThomas Bourgoin uint8_t temp_key[DES3_KEY_SIZE] = { };
684320f5cfSThomas Bourgoin
694320f5cfSThomas Bourgoin if (!IS_ENABLED(CFG_STM32_CRYP))
704320f5cfSThomas Bourgoin return TEE_ERROR_NOT_IMPLEMENTED;
714320f5cfSThomas Bourgoin
724320f5cfSThomas Bourgoin if (key_len == 16 &&
734320f5cfSThomas Bourgoin (ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_ECB ||
744320f5cfSThomas Bourgoin ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_CBC)) {
754320f5cfSThomas Bourgoin /* Manage DES2: i.e. K=K1.K2.K1 */
764320f5cfSThomas Bourgoin memcpy(temp_key, key, key_len);
774320f5cfSThomas Bourgoin memcpy(temp_key + key_len, key, key_len / 2);
784320f5cfSThomas Bourgoin key_len = DES3_KEY_SIZE;
794320f5cfSThomas Bourgoin key = temp_key;
804320f5cfSThomas Bourgoin }
814320f5cfSThomas Bourgoin
824320f5cfSThomas Bourgoin return stm32_cryp_init(&ip_ctx->cryp.ctx, is_decrypt, ip_ctx->cryp.algo,
834320f5cfSThomas Bourgoin key, key_len, iv, iv_len);
844320f5cfSThomas Bourgoin }
854320f5cfSThomas Bourgoin
cryp_update(union ip_ctx * ip_ctx,bool last_block,uint8_t * src,uint8_t * dst,size_t len)864320f5cfSThomas Bourgoin static TEE_Result cryp_update(union ip_ctx *ip_ctx, bool last_block,
874320f5cfSThomas Bourgoin uint8_t *src, uint8_t *dst, size_t len)
884320f5cfSThomas Bourgoin {
894320f5cfSThomas Bourgoin if (!IS_ENABLED(CFG_STM32_CRYP))
904320f5cfSThomas Bourgoin return TEE_ERROR_NOT_IMPLEMENTED;
914320f5cfSThomas Bourgoin
924320f5cfSThomas Bourgoin return stm32_cryp_update(&ip_ctx->cryp.ctx, last_block, src, dst, len);
934320f5cfSThomas Bourgoin }
944320f5cfSThomas Bourgoin
cryp_copy_state(union ip_ctx * dst_ip_ctx,union ip_ctx * src_ip_ctx)9503de2c7bSEtienne Carriere static void cryp_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx)
9603de2c7bSEtienne Carriere {
9703de2c7bSEtienne Carriere memcpy(&dst_ip_ctx->cryp, &src_ip_ctx->cryp, sizeof(dst_ip_ctx->cryp));
9803de2c7bSEtienne Carriere }
9903de2c7bSEtienne Carriere
10099205375SEtienne Carriere static const struct ip_cipher_ops cryp_ops = {
10199205375SEtienne Carriere .init = cryp_init,
10299205375SEtienne Carriere .update = cryp_update,
10303de2c7bSEtienne Carriere .copy_state = cryp_copy_state,
10499205375SEtienne Carriere };
10599205375SEtienne Carriere
saes_init(union ip_ctx * ip_ctx,bool is_decrypt,const uint8_t * key,size_t key_len,const uint8_t * iv,size_t iv_len)1064320f5cfSThomas Bourgoin static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt,
1074320f5cfSThomas Bourgoin const uint8_t *key, size_t key_len,
1084320f5cfSThomas Bourgoin const uint8_t *iv, size_t iv_len)
1094320f5cfSThomas Bourgoin {
1104320f5cfSThomas Bourgoin enum stm32_saes_key_selection key_sel = STM32_SAES_KEY_SOFT;
1114320f5cfSThomas Bourgoin
1124320f5cfSThomas Bourgoin if (!IS_ENABLED(CFG_STM32_SAES))
1134320f5cfSThomas Bourgoin return TEE_ERROR_NOT_IMPLEMENTED;
1144320f5cfSThomas Bourgoin
11503de2c7bSEtienne Carriere if (key_len == AES_KEYSIZE_192) {
11603de2c7bSEtienne Carriere struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
11703de2c7bSEtienne Carriere TEE_OperationMode mode = TEE_MODE_ILLEGAL_VALUE;
11803de2c7bSEtienne Carriere TEE_Result res = TEE_ERROR_GENERIC;
11903de2c7bSEtienne Carriere
12003de2c7bSEtienne Carriere if (!IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) {
12103de2c7bSEtienne Carriere EMSG("STM32 SAES does not support 192bit keys");
12203de2c7bSEtienne Carriere
12303de2c7bSEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED;
12403de2c7bSEtienne Carriere }
12503de2c7bSEtienne Carriere
12603de2c7bSEtienne Carriere if (is_decrypt)
12703de2c7bSEtienne Carriere mode = TEE_MODE_DECRYPT;
12803de2c7bSEtienne Carriere else
12903de2c7bSEtienne Carriere mode = TEE_MODE_ENCRYPT;
13003de2c7bSEtienne Carriere
13103de2c7bSEtienne Carriere res = ctx->ops->init(ctx, mode, key, key_len, NULL, 0, iv,
13203de2c7bSEtienne Carriere iv_len);
13303de2c7bSEtienne Carriere if (res)
13403de2c7bSEtienne Carriere return res;
13503de2c7bSEtienne Carriere
13603de2c7bSEtienne Carriere ip_ctx->saes.use_fallback = true;
13703de2c7bSEtienne Carriere
13803de2c7bSEtienne Carriere return TEE_SUCCESS;
13903de2c7bSEtienne Carriere }
14003de2c7bSEtienne Carriere
14103de2c7bSEtienne Carriere ip_ctx->saes.use_fallback = false;
14203de2c7bSEtienne Carriere
1434320f5cfSThomas Bourgoin return stm32_saes_init(&ip_ctx->saes.ctx, is_decrypt, ip_ctx->saes.algo,
1444320f5cfSThomas Bourgoin key_sel, key, key_len, iv, iv_len);
1454320f5cfSThomas Bourgoin }
1464320f5cfSThomas Bourgoin
saes_update(union ip_ctx * ip_ctx,bool last_block,uint8_t * src,uint8_t * dst,size_t len)1474320f5cfSThomas Bourgoin static TEE_Result saes_update(union ip_ctx *ip_ctx, bool last_block,
1484320f5cfSThomas Bourgoin uint8_t *src, uint8_t *dst, size_t len)
1494320f5cfSThomas Bourgoin {
1504320f5cfSThomas Bourgoin if (!IS_ENABLED(CFG_STM32_SAES))
1514320f5cfSThomas Bourgoin return TEE_ERROR_NOT_IMPLEMENTED;
1524320f5cfSThomas Bourgoin
15303de2c7bSEtienne Carriere if (ip_ctx->saes.use_fallback) {
15403de2c7bSEtienne Carriere struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
15503de2c7bSEtienne Carriere
15603de2c7bSEtienne Carriere assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
15703de2c7bSEtienne Carriere
15803de2c7bSEtienne Carriere return ctx->ops->update(ctx, last_block, src, len, dst);
15903de2c7bSEtienne Carriere }
16003de2c7bSEtienne Carriere
1614320f5cfSThomas Bourgoin return stm32_saes_update(&ip_ctx->saes.ctx, last_block, src, dst, len);
1624320f5cfSThomas Bourgoin }
1634320f5cfSThomas Bourgoin
saes_final(union ip_ctx * ip_ctx)16403de2c7bSEtienne Carriere static void saes_final(union ip_ctx *ip_ctx)
16503de2c7bSEtienne Carriere {
16603de2c7bSEtienne Carriere struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
16703de2c7bSEtienne Carriere
16803de2c7bSEtienne Carriere if (ip_ctx->saes.use_fallback) {
16903de2c7bSEtienne Carriere assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
17003de2c7bSEtienne Carriere ctx->ops->final(ctx);
17103de2c7bSEtienne Carriere }
17203de2c7bSEtienne Carriere }
17303de2c7bSEtienne Carriere
saes_copy_state(union ip_ctx * dst_ip_ctx,union ip_ctx * src_ip_ctx)17403de2c7bSEtienne Carriere static void saes_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx)
17503de2c7bSEtienne Carriere {
17603de2c7bSEtienne Carriere struct saes_ctx *src_ctx = &src_ip_ctx->saes;
17703de2c7bSEtienne Carriere struct crypto_cipher_ctx *fb_ctx = src_ctx->fallback_ctx;
17803de2c7bSEtienne Carriere
17903de2c7bSEtienne Carriere memcpy(&dst_ip_ctx->saes.ctx, &src_ctx->ctx, sizeof(src_ctx->ctx));
18003de2c7bSEtienne Carriere
18103de2c7bSEtienne Carriere dst_ip_ctx->saes.algo = src_ctx->algo;
18203de2c7bSEtienne Carriere dst_ip_ctx->saes.use_fallback = src_ctx->use_fallback;
18303de2c7bSEtienne Carriere
18403de2c7bSEtienne Carriere if (src_ctx->use_fallback) {
18503de2c7bSEtienne Carriere assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
18603de2c7bSEtienne Carriere fb_ctx->ops->copy_state(dst_ip_ctx->saes.fallback_ctx, fb_ctx);
18703de2c7bSEtienne Carriere }
18803de2c7bSEtienne Carriere }
18903de2c7bSEtienne Carriere
19099205375SEtienne Carriere static const struct ip_cipher_ops saes_ops = {
1914320f5cfSThomas Bourgoin .init = saes_init,
1924320f5cfSThomas Bourgoin .update = saes_update,
19303de2c7bSEtienne Carriere .final = saes_final,
19403de2c7bSEtienne Carriere .copy_state = saes_copy_state,
1955e64ae67SNicolas Toromanoff };
1965e64ae67SNicolas Toromanoff
1975e64ae67SNicolas Toromanoff static struct stm32_cipher_ctx *
to_stm32_cipher_ctx(struct crypto_cipher_ctx * ctx)1985e64ae67SNicolas Toromanoff to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx)
1995e64ae67SNicolas Toromanoff {
2005e64ae67SNicolas Toromanoff assert(ctx);
2015e64ae67SNicolas Toromanoff
2025e64ae67SNicolas Toromanoff return container_of(ctx, struct stm32_cipher_ctx, c_ctx);
2035e64ae67SNicolas Toromanoff }
2045e64ae67SNicolas Toromanoff
stm32_cipher_initialize(struct drvcrypt_cipher_init * dinit)2055e64ae67SNicolas Toromanoff static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit)
2065e64ae67SNicolas Toromanoff {
2075e64ae67SNicolas Toromanoff struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx);
2085e64ae67SNicolas Toromanoff
2094320f5cfSThomas Bourgoin return c->ops->init(&c->ip_ctx, !dinit->encrypt, dinit->key1.data,
2104320f5cfSThomas Bourgoin dinit->key1.length, dinit->iv.data,
2115e64ae67SNicolas Toromanoff dinit->iv.length);
2125e64ae67SNicolas Toromanoff }
2135e64ae67SNicolas Toromanoff
stm32_cipher_update(struct drvcrypt_cipher_update * dupdate)2145e64ae67SNicolas Toromanoff static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate)
2155e64ae67SNicolas Toromanoff {
2165e64ae67SNicolas Toromanoff struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx);
2175e64ae67SNicolas Toromanoff size_t len = MIN(dupdate->src.length, dupdate->dst.length);
2185e64ae67SNicolas Toromanoff
2194320f5cfSThomas Bourgoin return c->ops->update(&c->ip_ctx, dupdate->last, dupdate->src.data,
2204320f5cfSThomas Bourgoin dupdate->dst.data, len);
2215e64ae67SNicolas Toromanoff }
2225e64ae67SNicolas Toromanoff
stm32_cipher_final(void * ctx __unused)2235e64ae67SNicolas Toromanoff static void stm32_cipher_final(void *ctx __unused)
2245e64ae67SNicolas Toromanoff {
22503de2c7bSEtienne Carriere struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
22603de2c7bSEtienne Carriere
22703de2c7bSEtienne Carriere if (c->ops->final)
22803de2c7bSEtienne Carriere c->ops->final(&c->ip_ctx);
2295e64ae67SNicolas Toromanoff }
2305e64ae67SNicolas Toromanoff
stm32_cipher_copy_state(void * dst_ctx,void * src_ctx)2315e64ae67SNicolas Toromanoff static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx)
2325e64ae67SNicolas Toromanoff {
23303de2c7bSEtienne Carriere struct stm32_cipher_ctx *src_c = to_stm32_cipher_ctx(src_ctx);
23403de2c7bSEtienne Carriere struct stm32_cipher_ctx *dst_c = to_stm32_cipher_ctx(dst_ctx);
2355e64ae67SNicolas Toromanoff
23603de2c7bSEtienne Carriere src_c->ops->copy_state(&dst_c->ip_ctx, &src_c->ip_ctx);
2375e64ae67SNicolas Toromanoff }
2385e64ae67SNicolas Toromanoff
alloc_cryp_ctx(void ** ctx,enum stm32_cryp_algo_mode algo)2394320f5cfSThomas Bourgoin static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
2405e64ae67SNicolas Toromanoff {
2415e64ae67SNicolas Toromanoff struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
2425e64ae67SNicolas Toromanoff
2435e64ae67SNicolas Toromanoff if (!c)
2445e64ae67SNicolas Toromanoff return TEE_ERROR_OUT_OF_MEMORY;
2455e64ae67SNicolas Toromanoff
246d5cb0882SEtienne Carriere FMSG("Using CRYP %d", algo);
2474320f5cfSThomas Bourgoin c->ip_ctx.cryp.algo = algo;
2484320f5cfSThomas Bourgoin c->ops = &cryp_ops;
2494320f5cfSThomas Bourgoin *ctx = &c->c_ctx;
2504320f5cfSThomas Bourgoin
2514320f5cfSThomas Bourgoin return TEE_SUCCESS;
2524320f5cfSThomas Bourgoin }
2534320f5cfSThomas Bourgoin
stm32_cryp_cipher_allocate(void ** ctx,uint32_t algo)2544320f5cfSThomas Bourgoin static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo)
2555e64ae67SNicolas Toromanoff {
2565e64ae67SNicolas Toromanoff /*
2575e64ae67SNicolas Toromanoff * Convert TEE_ALGO id to internal id
2585e64ae67SNicolas Toromanoff */
2595e64ae67SNicolas Toromanoff switch (algo) {
2605e64ae67SNicolas Toromanoff case TEE_ALG_DES_ECB_NOPAD:
2614320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_ECB);
2625e64ae67SNicolas Toromanoff case TEE_ALG_DES_CBC_NOPAD:
2634320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_CBC);
2645e64ae67SNicolas Toromanoff case TEE_ALG_DES3_ECB_NOPAD:
2654320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_ECB);
2665e64ae67SNicolas Toromanoff case TEE_ALG_DES3_CBC_NOPAD:
2674320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_CBC);
2685e64ae67SNicolas Toromanoff case TEE_ALG_AES_ECB_NOPAD:
2694320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_ECB);
2705e64ae67SNicolas Toromanoff case TEE_ALG_AES_CBC_NOPAD:
2714320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CBC);
2725e64ae67SNicolas Toromanoff case TEE_ALG_AES_CTR:
2734320f5cfSThomas Bourgoin return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CTR);
2745e64ae67SNicolas Toromanoff default:
2755e64ae67SNicolas Toromanoff return TEE_ERROR_NOT_IMPLEMENTED;
2765e64ae67SNicolas Toromanoff }
2775e64ae67SNicolas Toromanoff }
2785e64ae67SNicolas Toromanoff
stm32_cryp_cipher_free(void * ctx)27903de2c7bSEtienne Carriere static void stm32_cryp_cipher_free(void *ctx)
280496497dcSEtienne Carriere {
281496497dcSEtienne Carriere struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
282496497dcSEtienne Carriere
283496497dcSEtienne Carriere free(c);
284496497dcSEtienne Carriere }
285496497dcSEtienne Carriere
stm32_saes_cipher_allocate(void ** ctx,uint32_t algo)28603de2c7bSEtienne Carriere static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo)
28703de2c7bSEtienne Carriere {
28803de2c7bSEtienne Carriere enum stm32_saes_chaining_mode saes_algo = STM32_SAES_MODE_ECB;
28903de2c7bSEtienne Carriere struct crypto_cipher_ctx *fallback_ctx = NULL;
29003de2c7bSEtienne Carriere struct stm32_cipher_ctx *saes_ctx = NULL;
29103de2c7bSEtienne Carriere TEE_Result res = TEE_SUCCESS;
29203de2c7bSEtienne Carriere
29303de2c7bSEtienne Carriere switch (algo) {
29403de2c7bSEtienne Carriere case TEE_ALG_AES_ECB_NOPAD:
29503de2c7bSEtienne Carriere saes_algo = STM32_SAES_MODE_ECB;
29603de2c7bSEtienne Carriere if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
29703de2c7bSEtienne Carriere res = crypto_aes_ecb_alloc_ctx(&fallback_ctx);
29803de2c7bSEtienne Carriere break;
29903de2c7bSEtienne Carriere case TEE_ALG_AES_CBC_NOPAD:
30003de2c7bSEtienne Carriere saes_algo = STM32_SAES_MODE_CBC;
30103de2c7bSEtienne Carriere if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
30203de2c7bSEtienne Carriere res = crypto_aes_cbc_alloc_ctx(&fallback_ctx);
30303de2c7bSEtienne Carriere break;
30403de2c7bSEtienne Carriere case TEE_ALG_AES_CTR:
30503de2c7bSEtienne Carriere saes_algo = STM32_SAES_MODE_CTR;
30603de2c7bSEtienne Carriere if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
30703de2c7bSEtienne Carriere res = crypto_aes_ctr_alloc_ctx(&fallback_ctx);
30803de2c7bSEtienne Carriere break;
30903de2c7bSEtienne Carriere default:
31003de2c7bSEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED;
31103de2c7bSEtienne Carriere }
31203de2c7bSEtienne Carriere if (res)
31303de2c7bSEtienne Carriere return res;
31403de2c7bSEtienne Carriere
31503de2c7bSEtienne Carriere saes_ctx = calloc(1, sizeof(*saes_ctx));
31603de2c7bSEtienne Carriere if (!saes_ctx) {
31703de2c7bSEtienne Carriere if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
31803de2c7bSEtienne Carriere fallback_ctx->ops->free_ctx(fallback_ctx);
31903de2c7bSEtienne Carriere
32003de2c7bSEtienne Carriere return TEE_ERROR_OUT_OF_MEMORY;
32103de2c7bSEtienne Carriere }
32203de2c7bSEtienne Carriere
32303de2c7bSEtienne Carriere FMSG("Using SAES %d", saes_algo);
32403de2c7bSEtienne Carriere saes_ctx->ip_ctx.saes.algo = saes_algo;
32503de2c7bSEtienne Carriere saes_ctx->ops = &saes_ops;
32603de2c7bSEtienne Carriere saes_ctx->ip_ctx.saes.fallback_ctx = fallback_ctx;
32703de2c7bSEtienne Carriere *ctx = &saes_ctx->c_ctx;
32803de2c7bSEtienne Carriere
32903de2c7bSEtienne Carriere return TEE_SUCCESS;
33003de2c7bSEtienne Carriere }
33103de2c7bSEtienne Carriere
stm32_saes_cipher_free(void * ctx)33203de2c7bSEtienne Carriere static void stm32_saes_cipher_free(void *ctx)
33303de2c7bSEtienne Carriere {
33403de2c7bSEtienne Carriere struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
33503de2c7bSEtienne Carriere
33603de2c7bSEtienne Carriere if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) {
33703de2c7bSEtienne Carriere struct crypto_cipher_ctx *fb_ctx = c->ip_ctx.saes.fallback_ctx;
33803de2c7bSEtienne Carriere
33903de2c7bSEtienne Carriere fb_ctx->ops->free_ctx(fb_ctx);
34003de2c7bSEtienne Carriere }
34103de2c7bSEtienne Carriere
34203de2c7bSEtienne Carriere free(c);
34303de2c7bSEtienne Carriere }
34403de2c7bSEtienne Carriere
3454320f5cfSThomas Bourgoin static struct drvcrypt_cipher driver_cipher_cryp = {
346061e13f6SEtienne Carriere .alloc_ctx = stm32_cryp_cipher_allocate,
34703de2c7bSEtienne Carriere .free_ctx = stm32_cryp_cipher_free,
348061e13f6SEtienne Carriere .init = stm32_cipher_initialize,
349061e13f6SEtienne Carriere .update = stm32_cipher_update,
350061e13f6SEtienne Carriere .final = stm32_cipher_final,
351061e13f6SEtienne Carriere .copy_state = stm32_cipher_copy_state,
3525e64ae67SNicolas Toromanoff };
3535e64ae67SNicolas Toromanoff
3544320f5cfSThomas Bourgoin static struct drvcrypt_cipher driver_cipher_saes = {
355061e13f6SEtienne Carriere .alloc_ctx = stm32_saes_cipher_allocate,
35603de2c7bSEtienne Carriere .free_ctx = stm32_saes_cipher_free,
357061e13f6SEtienne Carriere .init = stm32_cipher_initialize,
358061e13f6SEtienne Carriere .update = stm32_cipher_update,
359061e13f6SEtienne Carriere .final = stm32_cipher_final,
360061e13f6SEtienne Carriere .copy_state = stm32_cipher_copy_state,
3614320f5cfSThomas Bourgoin };
3624320f5cfSThomas Bourgoin
stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip)3634320f5cfSThomas Bourgoin TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip)
3645e64ae67SNicolas Toromanoff {
365*e5500ff7SThomas Bourgoin void *op = drvcrypt_get_ops(CRYPTO_CIPHER);
366*e5500ff7SThomas Bourgoin
367*e5500ff7SThomas Bourgoin if (op) {
368*e5500ff7SThomas Bourgoin EMSG("%s already registered for CRYPTO_CIPHER",
369*e5500ff7SThomas Bourgoin op == &driver_cipher_cryp ? "CRYP peripheral" :
370*e5500ff7SThomas Bourgoin op == &driver_cipher_saes ? "SAES peripheral" :
371*e5500ff7SThomas Bourgoin "Other cipher driver");
372*e5500ff7SThomas Bourgoin return TEE_ERROR_GENERIC;
373*e5500ff7SThomas Bourgoin }
374*e5500ff7SThomas Bourgoin
3754320f5cfSThomas Bourgoin if (cipher_ip == SAES_IP)
3764320f5cfSThomas Bourgoin return drvcrypt_register_cipher(&driver_cipher_saes);
3774320f5cfSThomas Bourgoin else if (cipher_ip == CRYP_IP)
3784320f5cfSThomas Bourgoin return drvcrypt_register_cipher(&driver_cipher_cryp);
3794320f5cfSThomas Bourgoin else
3804320f5cfSThomas Bourgoin return TEE_ERROR_BAD_PARAMETERS;
3815e64ae67SNicolas Toromanoff }
382