1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021, STMicroelectronics - All Rights Reserved
4  *
5  * Crypto authenc interface implementation to enable HW driver.
6  */
7 #include <assert.h>
8 #include <crypto/crypto.h>
9 #include <crypto/crypto_impl.h>
10 #include <drvcrypt.h>
11 #include <drvcrypt_authenc.h>
12 #include <kernel/panic.h>
13 #include <malloc.h>
14 #include <utee_defines.h>
15 #include <util.h>
16 
17 static const struct crypto_authenc_ops authenc_ops;
18 
19 /*
20  * Returns the reference to the driver context
21  *
22  * @ctx    Reference the API context pointer
23  */
to_authenc_ctx(struct crypto_authenc_ctx * ctx)24 static struct crypto_authenc *to_authenc_ctx(struct crypto_authenc_ctx *ctx)
25 {
26 	assert(ctx && ctx->ops == &authenc_ops);
27 
28 	return container_of(ctx, struct crypto_authenc, authenc_ctx);
29 }
30 
31 /*
32  * Free authenc context
33  *
34  * @ctx    Reference the API context pointer
35  */
authenc_free_ctx(struct crypto_authenc_ctx * ctx)36 static void authenc_free_ctx(struct crypto_authenc_ctx *ctx)
37 {
38 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
39 
40 	if (authenc->op && authenc->op->free_ctx)
41 		authenc->op->free_ctx(authenc->ctx);
42 
43 	free(authenc);
44 }
45 
46 /*
47  * Copy authenc context
48  *
49  * @dst_ctx  [out] Reference the API context pointer destination
50  * @src_ctx  Reference the API context pointer source
51  */
authenc_copy_state(struct crypto_authenc_ctx * dst_ctx,struct crypto_authenc_ctx * src_ctx)52 static void authenc_copy_state(struct crypto_authenc_ctx *dst_ctx,
53 			       struct crypto_authenc_ctx *src_ctx)
54 {
55 	struct crypto_authenc *authenc_src = to_authenc_ctx(src_ctx);
56 	struct crypto_authenc *authenc_dst = to_authenc_ctx(dst_ctx);
57 
58 	if (authenc_src->op && authenc_src->op->copy_state)
59 		authenc_src->op->copy_state(authenc_dst->ctx, authenc_src->ctx);
60 }
61 
62 /*
63  * Initialization of the authenc operation
64  *
65  * @ctx         Reference the API context pointer
66  * @mode        Operation mode
67  * @key         Key
68  * @key_len     Length of the key
69  * @nonce       Nonce
70  * @nonce_len   Length of the nonce
71  * @tag_len     Length of the requested tag
72  * @aad_len     Length of the associated authenticated data
73  * @payload_len Length of payload
74  */
authenc_init(struct crypto_authenc_ctx * ctx,TEE_OperationMode mode,const uint8_t * key,size_t key_len,const uint8_t * nonce,size_t nonce_len,size_t tag_len,size_t aad_len,size_t payload_len)75 static TEE_Result authenc_init(struct crypto_authenc_ctx *ctx,
76 			       TEE_OperationMode mode, const uint8_t *key,
77 			       size_t key_len, const uint8_t *nonce,
78 			       size_t nonce_len, size_t tag_len, size_t aad_len,
79 			       size_t payload_len)
80 {
81 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
82 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
83 
84 	if ((!key && key_len) || (!nonce && nonce_len)) {
85 		CRYPTO_TRACE("One of the key is not correct");
86 		CRYPTO_TRACE("key   @%p-%zu bytes", key, key_len);
87 		CRYPTO_TRACE("nonce @%p-%zu bytes", nonce, nonce_len);
88 		return TEE_ERROR_BAD_PARAMETERS;
89 	}
90 
91 	if (authenc->op && authenc->op->init) {
92 		struct drvcrypt_authenc_init dinit = {
93 			.ctx = authenc->ctx,
94 			.encrypt = (mode == TEE_MODE_ENCRYPT),
95 			.key.data = (uint8_t *)key,
96 			.key.length = key_len,
97 			.nonce.data = (uint8_t *)nonce,
98 			.nonce.length = nonce_len,
99 			.tag_len = tag_len,
100 			.aad_len = aad_len,
101 			.payload_len = payload_len,
102 		};
103 
104 		ret = authenc->op->init(&dinit);
105 	}
106 
107 	CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
108 	return ret;
109 }
110 
111 /*
112  * Update Additional Authenticated Data part of the authenc operation
113  *
114  * @ctx        Reference the API context pointer
115  * @data       Data to authenticate without encrypt/decrypt (AAD)
116  * @len        AAD length in bytes
117  */
authenc_update_aad(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len)118 static TEE_Result authenc_update_aad(struct crypto_authenc_ctx *ctx,
119 				     const uint8_t *data, size_t len)
120 {
121 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
122 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
123 
124 	if (!data && len) {
125 		CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
126 		return TEE_ERROR_BAD_PARAMETERS;
127 	}
128 
129 	if (authenc->op && authenc->op->update_aad) {
130 		struct drvcrypt_authenc_update_aad dupdate = {
131 			.ctx = authenc->ctx,
132 			.aad.data = (uint8_t *)data,
133 			.aad.length = len,
134 		};
135 
136 		ret = authenc->op->update_aad(&dupdate);
137 	}
138 
139 	CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
140 	return ret;
141 }
142 
143 /*
144  * Update payload part of the authenc operation
145  *
146  * @ctx        Reference the API context pointer
147  * @data       Data to authenticate and encrypt/decrypt
148  * @len        Length of the input data and output result
149  * @dst        [out] Output data of the operation
150  */
authenc_update_payload(struct crypto_authenc_ctx * ctx,TEE_OperationMode mode,const uint8_t * data,size_t len,uint8_t * dst)151 static TEE_Result authenc_update_payload(struct crypto_authenc_ctx *ctx,
152 					 TEE_OperationMode mode,
153 					 const uint8_t *data,
154 					 size_t len, uint8_t *dst)
155 {
156 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
157 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
158 
159 	if (!dst) {
160 		CRYPTO_TRACE("Destination buffer error");
161 		return TEE_ERROR_BAD_PARAMETERS;
162 	}
163 
164 	if (!data && len) {
165 		CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
166 		return TEE_ERROR_BAD_PARAMETERS;
167 	}
168 
169 	if (authenc->op && authenc->op->update_payload) {
170 		struct drvcrypt_authenc_update_payload dupdate = {
171 			.ctx = authenc->ctx,
172 			.encrypt = (mode == TEE_MODE_ENCRYPT),
173 			.src.data = (uint8_t *)data,
174 			.src.length = len,
175 			.dst.data = dst,
176 			.dst.length = len,
177 		};
178 
179 		ret = authenc->op->update_payload(&dupdate);
180 	}
181 
182 	CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
183 	return ret;
184 }
185 
186 /*
187  * Last block for the authenc encrypt and get tag operation
188  *
189  * @ctx     Reference the API context pointer
190  * @data    Data to authenticate and encrypt (can be NULL)
191  * @len     Length of the input data and output result (can be 0)
192  * @dst     [out] Output data of the operation
193  * @tag     [out] Output tag of the operation
194  * @tag_len [in/out] in: size of the dst_tag buffer
195  *                  out: size of the computed tag
196  */
authenc_enc_final(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len,uint8_t * dst,uint8_t * tag,size_t * tag_len)197 static TEE_Result authenc_enc_final(struct crypto_authenc_ctx *ctx,
198 				    const uint8_t *data, size_t len,
199 				    uint8_t *dst, uint8_t *tag,
200 				    size_t *tag_len)
201 {
202 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
203 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
204 
205 	if (!dst && len) {
206 		CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len);
207 		return TEE_ERROR_BAD_PARAMETERS;
208 	}
209 
210 	if (!data && len) {
211 		CRYPTO_TRACE("Bad input @%p-%zu bytes", data, len);
212 		return TEE_ERROR_BAD_PARAMETERS;
213 	}
214 
215 	if (authenc->op && authenc->op->enc_final) {
216 		struct drvcrypt_authenc_final dfinal = {
217 			.ctx = authenc->ctx,
218 			.src.data = (uint8_t *)data,
219 			.src.length = len,
220 			.dst.data = dst,
221 			.dst.length = len,
222 			.tag.data = tag,
223 			.tag.length = *tag_len
224 		};
225 
226 		ret = authenc->op->enc_final(&dfinal);
227 		if (ret == TEE_SUCCESS)
228 			*tag_len = dfinal.tag.length;
229 	}
230 
231 	CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
232 	return ret;
233 }
234 
235 /*
236  * Last block for the authenc decrypt and check tag operation
237  *
238  * @ctx         Reference the API context pointer
239  * @src_data    Data to authenticate and encrypt (can be NULL)
240  * @len         Length of the input data and output result (can be 0)
241  * @dst         [out] Output data of the operation
242  * @tag         Tag to check at end of operation
243  * @tag_len     Length of @tag
244  */
authenc_dec_final(struct crypto_authenc_ctx * ctx,const uint8_t * data,size_t len,uint8_t * dst,const uint8_t * tag,size_t tag_len)245 static TEE_Result authenc_dec_final(struct crypto_authenc_ctx *ctx,
246 				    const uint8_t *data, size_t len,
247 				    uint8_t *dst, const uint8_t *tag,
248 				    size_t tag_len)
249 {
250 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
251 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
252 
253 	if (!dst && len) {
254 		CRYPTO_TRACE("Bad output @%p-%zu bytes", dst, len);
255 		return TEE_ERROR_BAD_PARAMETERS;
256 	}
257 
258 	if (!data && len) {
259 		CRYPTO_TRACE("Bad data @%p-%zu bytes", data, len);
260 		return TEE_ERROR_BAD_PARAMETERS;
261 	}
262 
263 	if (authenc->op && authenc->op->dec_final) {
264 		struct drvcrypt_authenc_final dfinal = {
265 			.ctx = authenc->ctx,
266 			.src.data = (uint8_t *)data,
267 			.src.length = len,
268 			.dst.data = dst,
269 			.dst.length = len,
270 			.tag.data = (uint8_t *)tag,
271 			.tag.length = tag_len
272 		};
273 
274 		ret = authenc->op->dec_final(&dfinal);
275 	}
276 
277 	CRYPTO_TRACE("authenc ret 0x%" PRIx32, ret);
278 	return ret;
279 }
280 
281 /*
282  * Finalize the authenc operation
283  *
284  * @ctx   Reference the API context pointer
285  */
authenc_final(struct crypto_authenc_ctx * ctx)286 static void authenc_final(struct crypto_authenc_ctx *ctx)
287 {
288 	struct crypto_authenc *authenc = to_authenc_ctx(ctx);
289 
290 	if (authenc->op && authenc->op->final)
291 		authenc->op->final(authenc->ctx);
292 }
293 
294 static const struct crypto_authenc_ops authenc_ops = {
295 	.init = authenc_init,
296 	.update_aad = authenc_update_aad,
297 	.update_payload = authenc_update_payload,
298 	.enc_final = authenc_enc_final,
299 	.dec_final = authenc_dec_final,
300 	.final = authenc_final,
301 	.free_ctx = authenc_free_ctx,
302 	.copy_state = authenc_copy_state,
303 };
304 
drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx ** ctx,uint32_t algo)305 TEE_Result drvcrypt_authenc_alloc_ctx(struct crypto_authenc_ctx **ctx,
306 				      uint32_t algo)
307 {
308 	TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
309 	struct crypto_authenc *authenc = NULL;
310 
311 	CRYPTO_TRACE("authenc alloc_ctx algo 0x%" PRIx32, algo);
312 
313 	assert(ctx);
314 
315 	authenc = calloc(1, sizeof(*authenc));
316 	if (!authenc)
317 		return TEE_ERROR_OUT_OF_MEMORY;
318 
319 	authenc->op = drvcrypt_get_ops(CRYPTO_AUTHENC);
320 	if (authenc->op && authenc->op->alloc_ctx)
321 		ret = authenc->op->alloc_ctx(&authenc->ctx, algo);
322 
323 	if (ret != TEE_SUCCESS) {
324 		free(authenc);
325 	} else {
326 		authenc->authenc_ctx.ops = &authenc_ops;
327 		*ctx = &authenc->authenc_ctx;
328 	}
329 
330 	CRYPTO_TRACE("authenc alloc_ctx ret 0x%" PRIx32, ret);
331 	return ret;
332 }
333