1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
4  */
5 
6 #include <assert.h>
7 #include <crypto/crypto.h>
8 #include <crypto/crypto_impl.h>
9 #include <drvcrypt.h>
10 #include <drvcrypt_cipher.h>
11 #include <kernel/dt.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <tee_api_types.h>
15 #include <util.h>
16 
17 #include "common.h"
18 #include "stm32_cryp.h"
19 
20 #define DES3_KEY_SIZE		24
21 
22 struct stm32_cipher_ctx {
23 	struct crypto_cipher_ctx c_ctx;
24 	struct stm32_cryp_context cryp;
25 	enum stm32_cryp_algo_mode algo;
26 };
27 
28 static struct stm32_cipher_ctx *
to_stm32_cipher_ctx(struct crypto_cipher_ctx * ctx)29 to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx)
30 {
31 	assert(ctx);
32 
33 	return container_of(ctx, struct stm32_cipher_ctx, c_ctx);
34 }
35 
stm32_cipher_initialize(struct drvcrypt_cipher_init * dinit)36 static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit)
37 {
38 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx);
39 	uint8_t temp_key[DES3_KEY_SIZE] = { 0 };
40 	uint8_t *key = NULL;
41 	size_t key_size = 0;
42 
43 	if (dinit->key1.length == 16 &&
44 	    (c->algo == STM32_CRYP_MODE_TDES_ECB ||
45 	     c->algo == STM32_CRYP_MODE_TDES_CBC)) {
46 		/* Manage DES2: ie K=K1.K2.K1 */
47 		memcpy(temp_key, dinit->key1.data, dinit->key1.length);
48 		memcpy(temp_key + dinit->key1.length, dinit->key1.data,
49 		       dinit->key1.length / 2);
50 		key_size = DES3_KEY_SIZE;
51 		key = temp_key;
52 	} else {
53 		key_size =  dinit->key1.length;
54 		key = dinit->key1.data;
55 	}
56 
57 	return stm32_cryp_init(&c->cryp, !dinit->encrypt, c->algo,
58 			       key, key_size, dinit->iv.data,
59 			       dinit->iv.length);
60 }
61 
stm32_cipher_update(struct drvcrypt_cipher_update * dupdate)62 static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate)
63 {
64 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx);
65 	size_t len = MIN(dupdate->src.length, dupdate->dst.length);
66 
67 	return stm32_cryp_update(&c->cryp, dupdate->last,
68 				 dupdate->src.data, dupdate->dst.data,
69 				 len);
70 }
71 
stm32_cipher_final(void * ctx __unused)72 static void stm32_cipher_final(void *ctx __unused)
73 {
74 }
75 
stm32_cipher_free(void * ctx)76 static void stm32_cipher_free(void *ctx)
77 {
78 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
79 
80 	free(c);
81 }
82 
stm32_cipher_copy_state(void * dst_ctx,void * src_ctx)83 static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx)
84 {
85 	struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx);
86 	struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx);
87 
88 	memcpy(dst, src, sizeof(*dst));
89 }
90 
alloc_ctx(void ** ctx,enum stm32_cryp_algo_mode algo)91 static TEE_Result alloc_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
92 {
93 	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
94 
95 	if (!c)
96 		return TEE_ERROR_OUT_OF_MEMORY;
97 
98 	c->algo = algo;
99 	*ctx = &c->c_ctx;
100 
101 	return TEE_SUCCESS;
102 }
103 
104 /*
105  * Allocate the SW cipher data context.
106  *
107  * @ctx   [out] Caller context variable
108  * @algo  Algorithm ID of the context
109  */
stm32_cipher_allocate(void ** ctx,uint32_t algo)110 static TEE_Result stm32_cipher_allocate(void **ctx, uint32_t algo)
111 {
112 	/*
113 	 * Convert TEE_ALGO id to internal id
114 	 */
115 	switch (algo) {
116 	case TEE_ALG_DES_ECB_NOPAD:
117 		return alloc_ctx(ctx, STM32_CRYP_MODE_DES_ECB);
118 	case TEE_ALG_DES_CBC_NOPAD:
119 		return alloc_ctx(ctx, STM32_CRYP_MODE_DES_CBC);
120 	case TEE_ALG_DES3_ECB_NOPAD:
121 		return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_ECB);
122 	case TEE_ALG_DES3_CBC_NOPAD:
123 		return alloc_ctx(ctx, STM32_CRYP_MODE_TDES_CBC);
124 	case TEE_ALG_AES_ECB_NOPAD:
125 		return alloc_ctx(ctx, STM32_CRYP_MODE_AES_ECB);
126 	case TEE_ALG_AES_CBC_NOPAD:
127 		return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CBC);
128 	case TEE_ALG_AES_CTR:
129 		return alloc_ctx(ctx, STM32_CRYP_MODE_AES_CTR);
130 	default:
131 		return TEE_ERROR_NOT_IMPLEMENTED;
132 	}
133 }
134 
135 static struct drvcrypt_cipher driver_cipher = {
136 	.alloc_ctx = &stm32_cipher_allocate,
137 	.free_ctx = &stm32_cipher_free,
138 	.init = &stm32_cipher_initialize,
139 	.update = &stm32_cipher_update,
140 	.final = &stm32_cipher_final,
141 	.copy_state = &stm32_cipher_copy_state,
142 };
143 
stm32_register_cipher(void)144 TEE_Result stm32_register_cipher(void)
145 {
146 	return drvcrypt_register_cipher(&driver_cipher);
147 }
148