xref: /optee_os/core/drivers/crypto/stm32/cipher.c (revision 061e13f64e8470a8d82bd356dc3e7c81ab80116c)
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 <stdlib.h>
12 #include <string.h>
13 #include <tee_api_types.h>
14 #include <util.h>
15 
16 #include "common.h"
17 #include "stm32_cryp.h"
18 #include "stm32_saes.h"
19 
20 #define DES3_KEY_SIZE		24
21 
22 struct cryp_ctx {
23 	struct stm32_cryp_context ctx;
24 	enum stm32_cryp_algo_mode algo;
25 };
26 
27 struct saes_ctx {
28 	struct stm32_saes_context ctx;
29 	enum stm32_saes_chaining_mode algo;
30 };
31 
32 /*
33  * Internal peripheral context
34  * SAES and CRYP are registered under the same ID in the crypto framework.
35  * Therefore, only one of them can be registered.
36  */
37 
38 union ip_ctx {
39 	struct saes_ctx saes;
40 	struct cryp_ctx cryp;
41 };
42 
43 /* Internal Peripheral cipher ops*/
44 struct ip_cipher_ops {
45 	TEE_Result (*init)(union ip_ctx *ctx, bool is_decrypt,
46 			   const uint8_t *key, size_t key_len,
47 			   const uint8_t *iv, size_t iv_len);
48 	TEE_Result (*update)(union ip_ctx *ctx, bool last_block, uint8_t *src,
49 			     uint8_t *dst, size_t len);
50 };
51 
52 struct stm32_cipher_ctx {
53 	struct crypto_cipher_ctx c_ctx;
54 	union ip_ctx ip_ctx;
55 	const struct ip_cipher_ops *ops;
56 };
57 
58 static TEE_Result cryp_init(union ip_ctx *ip_ctx, bool is_decrypt,
59 			    const uint8_t *key, size_t key_len,
60 			    const uint8_t *iv, size_t iv_len)
61 {
62 	uint8_t temp_key[DES3_KEY_SIZE] = { };
63 
64 	if (!IS_ENABLED(CFG_STM32_CRYP))
65 		return TEE_ERROR_NOT_IMPLEMENTED;
66 
67 	if (key_len == 16 &&
68 	    (ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_ECB ||
69 	     ip_ctx->cryp.algo == STM32_CRYP_MODE_TDES_CBC)) {
70 		/* Manage DES2: i.e. K=K1.K2.K1 */
71 		memcpy(temp_key, key, key_len);
72 		memcpy(temp_key + key_len, key, key_len / 2);
73 		key_len = DES3_KEY_SIZE;
74 		key = temp_key;
75 	}
76 
77 	return stm32_cryp_init(&ip_ctx->cryp.ctx, is_decrypt, ip_ctx->cryp.algo,
78 			       key, key_len, iv, iv_len);
79 }
80 
81 static TEE_Result cryp_update(union ip_ctx *ip_ctx, bool last_block,
82 			      uint8_t *src, uint8_t *dst, size_t len)
83 {
84 	if (!IS_ENABLED(CFG_STM32_CRYP))
85 		return TEE_ERROR_NOT_IMPLEMENTED;
86 
87 	return stm32_cryp_update(&ip_ctx->cryp.ctx, last_block, src, dst, len);
88 }
89 
90 static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt,
91 			    const uint8_t *key, size_t key_len,
92 			    const uint8_t *iv, size_t iv_len)
93 {
94 	enum stm32_saes_key_selection key_sel = STM32_SAES_KEY_SOFT;
95 
96 	if (!IS_ENABLED(CFG_STM32_SAES))
97 		return TEE_ERROR_NOT_IMPLEMENTED;
98 
99 	return stm32_saes_init(&ip_ctx->saes.ctx, is_decrypt, ip_ctx->saes.algo,
100 			       key_sel, key, key_len, iv, iv_len);
101 }
102 
103 static TEE_Result saes_update(union ip_ctx *ip_ctx, bool last_block,
104 			      uint8_t *src, uint8_t *dst, size_t len)
105 {
106 	if (!IS_ENABLED(CFG_STM32_SAES))
107 		return TEE_ERROR_NOT_IMPLEMENTED;
108 
109 	return stm32_saes_update(&ip_ctx->saes.ctx, last_block, src, dst, len);
110 }
111 
112 const struct ip_cipher_ops cryp_ops = {
113 	.init = cryp_init,
114 	.update = cryp_update,
115 };
116 
117 const struct ip_cipher_ops saes_ops = {
118 	.init = saes_init,
119 	.update = saes_update,
120 };
121 
122 static struct stm32_cipher_ctx *
123 to_stm32_cipher_ctx(struct crypto_cipher_ctx *ctx)
124 {
125 	assert(ctx);
126 
127 	return container_of(ctx, struct stm32_cipher_ctx, c_ctx);
128 }
129 
130 static TEE_Result stm32_cipher_initialize(struct drvcrypt_cipher_init *dinit)
131 {
132 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dinit->ctx);
133 
134 	return c->ops->init(&c->ip_ctx, !dinit->encrypt, dinit->key1.data,
135 			    dinit->key1.length, dinit->iv.data,
136 			    dinit->iv.length);
137 }
138 
139 static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate)
140 {
141 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(dupdate->ctx);
142 	size_t len = MIN(dupdate->src.length, dupdate->dst.length);
143 
144 	return c->ops->update(&c->ip_ctx, dupdate->last, dupdate->src.data,
145 			      dupdate->dst.data, len);
146 }
147 
148 static void stm32_cipher_final(void *ctx __unused)
149 {
150 }
151 
152 static void stm32_cipher_free(void *ctx)
153 {
154 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
155 
156 	free(c);
157 }
158 
159 static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx)
160 {
161 	struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx);
162 	struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx);
163 
164 	memcpy(dst, src, sizeof(*dst));
165 }
166 
167 static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
168 {
169 	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
170 
171 	if (!c)
172 		return TEE_ERROR_OUT_OF_MEMORY;
173 
174 	FMSG("Using CRYP %d", algo);
175 	c->ip_ctx.cryp.algo = algo;
176 	c->ops = &cryp_ops;
177 	*ctx = &c->c_ctx;
178 
179 	return TEE_SUCCESS;
180 }
181 
182 static TEE_Result alloc_saes_ctx(void **ctx, enum stm32_saes_chaining_mode algo)
183 {
184 	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
185 
186 	if (!c)
187 		return TEE_ERROR_OUT_OF_MEMORY;
188 
189 	FMSG("Using SAES %d", algo);
190 	c->ip_ctx.saes.algo = algo;
191 	c->ops = &saes_ops;
192 	*ctx = &c->c_ctx;
193 
194 	return TEE_SUCCESS;
195 }
196 
197 /*
198  * Allocate the SW cipher data context for CRYP peripheral.
199  *
200  * @ctx   [out] Caller context variable
201  * @algo  Algorithm ID of the context
202  */
203 static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo)
204 {
205 	/*
206 	 * Convert TEE_ALGO id to internal id
207 	 */
208 	switch (algo) {
209 	case TEE_ALG_DES_ECB_NOPAD:
210 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_ECB);
211 	case TEE_ALG_DES_CBC_NOPAD:
212 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_CBC);
213 	case TEE_ALG_DES3_ECB_NOPAD:
214 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_ECB);
215 	case TEE_ALG_DES3_CBC_NOPAD:
216 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_CBC);
217 	case TEE_ALG_AES_ECB_NOPAD:
218 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_ECB);
219 	case TEE_ALG_AES_CBC_NOPAD:
220 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CBC);
221 	case TEE_ALG_AES_CTR:
222 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CTR);
223 	default:
224 		return TEE_ERROR_NOT_IMPLEMENTED;
225 	}
226 }
227 
228 /*
229  * Allocate the SW cipher data context for SAES peripheral.
230  *
231  * @ctx   [out] Caller context variable
232  * @algo  Algorithm ID of the context
233  */
234 static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo)
235 {
236 	/*
237 	 * Convert TEE_ALGO id to internal id
238 	 */
239 	switch (algo) {
240 	case TEE_ALG_AES_ECB_NOPAD:
241 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_ECB);
242 	case TEE_ALG_AES_CBC_NOPAD:
243 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CBC);
244 	case TEE_ALG_AES_CTR:
245 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CTR);
246 	default:
247 		return TEE_ERROR_NOT_IMPLEMENTED;
248 	}
249 }
250 
251 static struct drvcrypt_cipher driver_cipher_cryp = {
252 	.alloc_ctx = stm32_cryp_cipher_allocate,
253 	.free_ctx = stm32_cipher_free,
254 	.init = stm32_cipher_initialize,
255 	.update = stm32_cipher_update,
256 	.final = stm32_cipher_final,
257 	.copy_state = stm32_cipher_copy_state,
258 };
259 
260 static struct drvcrypt_cipher driver_cipher_saes = {
261 	.alloc_ctx = stm32_saes_cipher_allocate,
262 	.free_ctx = stm32_cipher_free,
263 	.init = stm32_cipher_initialize,
264 	.update = stm32_cipher_update,
265 	.final = stm32_cipher_final,
266 	.copy_state = stm32_cipher_copy_state,
267 };
268 
269 TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip)
270 {
271 	if (cipher_ip == SAES_IP)
272 		return drvcrypt_register_cipher(&driver_cipher_saes);
273 	else if (cipher_ip == CRYP_IP)
274 		return drvcrypt_register_cipher(&driver_cipher_cryp);
275 	else
276 		return TEE_ERROR_BAD_PARAMETERS;
277 }
278