1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2018-2020 NXP
4  *
5  * Brief   Cryptographic library using the NXP CAAM driver.
6  *         Mathematical Modulus operation implementation.
7  */
8 #include <drvcrypt.h>
9 #include <drvcrypt_math.h>
10 #include <string.h>
11 #include <util.h>
12 
drvcrypt_xor_mod_n(struct drvcrypt_mod_op * data)13 TEE_Result drvcrypt_xor_mod_n(struct drvcrypt_mod_op *data)
14 {
15 	TEE_Result ret = TEE_ERROR_GENERIC;
16 	struct drvcrypt_math *math = NULL;
17 
18 	if (!data->a.data || !data->a.length || !data->b.data ||
19 	    !data->b.length || !data->result.data || !data->result.length ||
20 	    !data->n.length)
21 		return TEE_ERROR_BAD_PARAMETERS;
22 
23 	if (data->result.length < data->n.length)
24 		return TEE_ERROR_BAD_PARAMETERS;
25 
26 	math = drvcrypt_get_ops(CRYPTO_MATH);
27 	if (math) {
28 		/* Operation done by Math driver */
29 		ret = math->xor_mod_n(data);
30 	} else {
31 		/* Operation done by Software */
32 		size_t min = 0, idx = 0;
33 
34 		/* Calculate the minimum size to do A xor B */
35 		min = MIN(data->a.length, data->b.length);
36 		min = MIN(min, data->n.length);
37 
38 		for (; idx < min; idx++)
39 			data->result.data[idx] =
40 				data->a.data[idx] ^ data->b.data[idx];
41 
42 		if (min < data->n.length) {
43 			/* Complete result to make a N modulus number */
44 			if (data->a.length > min) {
45 				memcpy(&data->result.data[idx],
46 				       &data->a.data[idx],
47 				       data->n.length - min);
48 			} else if (data->b.length > min) {
49 				memcpy(&data->result.data[idx],
50 				       &data->b.data[idx],
51 				       data->n.length - min);
52 			} else {
53 				memset(&data->result.data[idx], 0,
54 				       data->n.length - min);
55 			}
56 		}
57 
58 		ret = TEE_SUCCESS;
59 	}
60 
61 	return ret;
62 }
63