xref: /optee_os/core/drivers/crypto/stm32/cipher.c (revision 496497dc1a00c0528244583561beb1db87a242a8)
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_copy_state(void *dst_ctx, void *src_ctx)
153 {
154 	struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx);
155 	struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx);
156 
157 	memcpy(dst, src, sizeof(*dst));
158 }
159 
160 static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
161 {
162 	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
163 
164 	if (!c)
165 		return TEE_ERROR_OUT_OF_MEMORY;
166 
167 	FMSG("Using CRYP %d", algo);
168 	c->ip_ctx.cryp.algo = algo;
169 	c->ops = &cryp_ops;
170 	*ctx = &c->c_ctx;
171 
172 	return TEE_SUCCESS;
173 }
174 
175 static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo)
176 {
177 	/*
178 	 * Convert TEE_ALGO id to internal id
179 	 */
180 	switch (algo) {
181 	case TEE_ALG_DES_ECB_NOPAD:
182 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_ECB);
183 	case TEE_ALG_DES_CBC_NOPAD:
184 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_DES_CBC);
185 	case TEE_ALG_DES3_ECB_NOPAD:
186 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_ECB);
187 	case TEE_ALG_DES3_CBC_NOPAD:
188 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_TDES_CBC);
189 	case TEE_ALG_AES_ECB_NOPAD:
190 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_ECB);
191 	case TEE_ALG_AES_CBC_NOPAD:
192 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CBC);
193 	case TEE_ALG_AES_CTR:
194 		return alloc_cryp_ctx(ctx, STM32_CRYP_MODE_AES_CTR);
195 	default:
196 		return TEE_ERROR_NOT_IMPLEMENTED;
197 	}
198 }
199 
200 static TEE_Result alloc_saes_ctx(void **ctx, enum stm32_saes_chaining_mode algo)
201 {
202 	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
203 
204 	if (!c)
205 		return TEE_ERROR_OUT_OF_MEMORY;
206 
207 	FMSG("Using SAES %d", algo);
208 	c->ip_ctx.saes.algo = algo;
209 	c->ops = &saes_ops;
210 	*ctx = &c->c_ctx;
211 
212 	return TEE_SUCCESS;
213 }
214 
215 static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo)
216 {
217 	/*
218 	 * Convert TEE_ALGO id to internal id
219 	 */
220 	switch (algo) {
221 	case TEE_ALG_AES_ECB_NOPAD:
222 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_ECB);
223 	case TEE_ALG_AES_CBC_NOPAD:
224 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CBC);
225 	case TEE_ALG_AES_CTR:
226 		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CTR);
227 	default:
228 		return TEE_ERROR_NOT_IMPLEMENTED;
229 	}
230 }
231 
232 static void stm32_cipher_free(void *ctx)
233 {
234 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
235 
236 	free(c);
237 }
238 
239 static struct drvcrypt_cipher driver_cipher_cryp = {
240 	.alloc_ctx = stm32_cryp_cipher_allocate,
241 	.free_ctx = stm32_cipher_free,
242 	.init = stm32_cipher_initialize,
243 	.update = stm32_cipher_update,
244 	.final = stm32_cipher_final,
245 	.copy_state = stm32_cipher_copy_state,
246 };
247 
248 static struct drvcrypt_cipher driver_cipher_saes = {
249 	.alloc_ctx = stm32_saes_cipher_allocate,
250 	.free_ctx = stm32_cipher_free,
251 	.init = stm32_cipher_initialize,
252 	.update = stm32_cipher_update,
253 	.final = stm32_cipher_final,
254 	.copy_state = stm32_cipher_copy_state,
255 };
256 
257 TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip)
258 {
259 	if (cipher_ip == SAES_IP)
260 		return drvcrypt_register_cipher(&driver_cipher_saes);
261 	else if (cipher_ip == CRYP_IP)
262 		return drvcrypt_register_cipher(&driver_cipher_cryp);
263 	else
264 		return TEE_ERROR_BAD_PARAMETERS;
265 }
266