xref: /linux/drivers/firmware/xilinx/zynqmp-crypto.c (revision 08df88fa142f3ba298bf0f7840fa9187e2fb5956)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Firmware layer for XilSecure APIs.
4  *
5  * Copyright (C) 2014-2022 Xilinx, Inc.
6  * Copyright (C) 2022-2025 Advanced Micro Devices, Inc.
7  */
8 
9 #include <linux/firmware/xlnx-zynqmp.h>
10 #include <linux/module.h>
11 
12 /**
13  * zynqmp_pm_aes_engine - Access AES hardware to encrypt/decrypt the data using
14  * AES-GCM core.
15  * @address:	Address of the AesParams structure.
16  * @out:	Returned output value
17  *
18  * Return:	Returns status, either success or error code.
19  */
20 int zynqmp_pm_aes_engine(const u64 address, u32 *out)
21 {
22 	u32 ret_payload[PAYLOAD_ARG_CNT];
23 	int ret;
24 
25 	if (!out)
26 		return -EINVAL;
27 
28 	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, ret_payload, 2, upper_32_bits(address),
29 				  lower_32_bits(address));
30 	*out = ret_payload[1];
31 
32 	return ret;
33 }
34 EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine);
35 
36 /**
37  * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
38  * @address:	Address of the data/ Address of output buffer where
39  *		hash should be stored.
40  * @size:	Size of the data.
41  * @flags:
42  *		BIT(0) - for initializing csudma driver and SHA3(Here address
43  *		and size inputs can be NULL).
44  *		BIT(1) - to call Sha3_Update API which can be called multiple
45  *		times when data is not contiguous.
46  *		BIT(2) - to get final hash of the whole updated data.
47  *		Hash will be overwritten at provided address with
48  *		48 bytes.
49  *
50  * Return:	Returns status, either success or error code.
51  */
52 int zynqmp_pm_sha_hash(const u64 address, const u32 size, const u32 flags)
53 {
54 	u32 lower_addr = lower_32_bits(address);
55 	u32 upper_addr = upper_32_bits(address);
56 
57 	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, NULL, 4, upper_addr, lower_addr, size, flags);
58 }
59 EXPORT_SYMBOL_GPL(zynqmp_pm_sha_hash);
60 
61 /**
62  * xlnx_get_crypto_dev_data() - Get crypto dev data of platform
63  * @feature_map:	List of available feature map of all platform
64  *
65  * Return: Returns crypto dev data, either address crypto dev or ERR PTR
66  */
67 void *xlnx_get_crypto_dev_data(struct xlnx_feature *feature_map)
68 {
69 	struct xlnx_feature *feature;
70 	u32 pm_family_code;
71 	int ret;
72 
73 	/* Get the Family code and sub family code of platform */
74 	ret = zynqmp_pm_get_family_info(&pm_family_code);
75 	if (ret < 0)
76 		return ERR_PTR(ret);
77 
78 	feature = feature_map;
79 	for (; feature->family; feature++) {
80 		if (feature->family == pm_family_code) {
81 			ret = zynqmp_pm_feature(feature->feature_id);
82 			if (ret < 0)
83 				return ERR_PTR(ret);
84 
85 			return feature->data;
86 		}
87 	}
88 	return ERR_PTR(-ENODEV);
89 }
90 EXPORT_SYMBOL_GPL(xlnx_get_crypto_dev_data);
91 
92 /**
93  * versal_pm_aes_key_write - Write AES key registers
94  * @keylen:	Size of the input key to be written
95  * @keysrc:	Key Source to be selected to which provided
96  *		key should be updated
97  * @keyaddr:	Address of a buffer which should contain the key
98  *		to be written
99  *
100  * This function provides support to write AES volatile user keys.
101  *
102  * Return: Returns status, either success or error+reason
103  */
104 int versal_pm_aes_key_write(const u32 keylen,
105 			    const u32 keysrc, const u64 keyaddr)
106 {
107 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_WRITE_KEY, NULL, 4,
108 				   keylen, keysrc,
109 				   lower_32_bits(keyaddr),
110 				   upper_32_bits(keyaddr));
111 }
112 EXPORT_SYMBOL_GPL(versal_pm_aes_key_write);
113 
114 /**
115  * versal_pm_aes_key_zero - Zeroise AES User key registers
116  * @keysrc:	Key Source to be selected to which provided
117  *		key should be updated
118  *
119  * This function provides support to zeroise AES volatile user keys.
120  *
121  * Return: Returns status, either success or error+reason
122  */
123 int versal_pm_aes_key_zero(const u32 keysrc)
124 {
125 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_KEY_ZERO, NULL, 1, keysrc);
126 }
127 EXPORT_SYMBOL_GPL(versal_pm_aes_key_zero);
128 
129 /**
130  * versal_pm_aes_op_init - Init AES operation
131  * @hw_req:	AES op init structure address
132  *
133  * This function provides support to init AES operation.
134  *
135  * Return: Returns status, either success or error+reason
136  */
137 int versal_pm_aes_op_init(const u64 hw_req)
138 {
139 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_OP_INIT, NULL, 2,
140 				   lower_32_bits(hw_req),
141 				   upper_32_bits(hw_req));
142 }
143 EXPORT_SYMBOL_GPL(versal_pm_aes_op_init);
144 
145 /**
146  * versal_pm_aes_update_aad - AES update aad
147  * @aad_addr:	AES aad address
148  * @aad_len:	AES aad data length
149  *
150  * This function provides support to update AAD data.
151  *
152  * Return: Returns status, either success or error+reason
153  */
154 int versal_pm_aes_update_aad(const u64 aad_addr, const u32 aad_len)
155 {
156 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_UPDATE_AAD, NULL, 3,
157 				   lower_32_bits(aad_addr),
158 				   upper_32_bits(aad_addr),
159 				   aad_len);
160 }
161 EXPORT_SYMBOL_GPL(versal_pm_aes_update_aad);
162 
163 /**
164  * versal_pm_aes_enc_update - Access AES hardware to encrypt the data using
165  * AES-GCM core.
166  * @in_params:	Address of the AesParams structure
167  * @in_addr:	Address of input buffer
168  *
169  * Return:	Returns status, either success or error code.
170  */
171 int versal_pm_aes_enc_update(const u64 in_params, const u64 in_addr)
172 {
173 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_ENCRYPT_UPDATE, NULL, 4,
174 				   lower_32_bits(in_params),
175 				   upper_32_bits(in_params),
176 				   lower_32_bits(in_addr),
177 				   upper_32_bits(in_addr));
178 }
179 EXPORT_SYMBOL_GPL(versal_pm_aes_enc_update);
180 
181 /**
182  * versal_pm_aes_enc_final - Access AES hardware to store the GCM tag
183  * @gcm_addr:	Address of the gcm tag
184  *
185  * Return:	Returns status, either success or error code.
186  */
187 int versal_pm_aes_enc_final(const u64 gcm_addr)
188 {
189 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_ENCRYPT_FINAL, NULL, 2,
190 				   lower_32_bits(gcm_addr),
191 				   upper_32_bits(gcm_addr));
192 }
193 EXPORT_SYMBOL_GPL(versal_pm_aes_enc_final);
194 
195 /**
196  * versal_pm_aes_dec_update - Access AES hardware to decrypt the data using
197  * AES-GCM core.
198  * @in_params:	Address of the AesParams structure
199  * @in_addr:	Address of input buffer
200  *
201  * Return:	Returns status, either success or error code.
202  */
203 int versal_pm_aes_dec_update(const u64 in_params, const u64 in_addr)
204 {
205 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_DECRYPT_UPDATE, NULL, 4,
206 				   lower_32_bits(in_params),
207 				   upper_32_bits(in_params),
208 				   lower_32_bits(in_addr),
209 				   upper_32_bits(in_addr));
210 }
211 EXPORT_SYMBOL_GPL(versal_pm_aes_dec_update);
212 
213 /**
214  * versal_pm_aes_dec_final - Access AES hardware to get the GCM tag
215  * @gcm_addr:	Address of the gcm tag
216  *
217  * Return:	Returns status, either success or error code.
218  */
219 int versal_pm_aes_dec_final(const u64 gcm_addr)
220 {
221 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_DECRYPT_FINAL, NULL, 2,
222 				   lower_32_bits(gcm_addr),
223 				   upper_32_bits(gcm_addr));
224 }
225 EXPORT_SYMBOL_GPL(versal_pm_aes_dec_final);
226 
227 /**
228  * versal_pm_aes_init - Init AES block
229  *
230  * This function initialise AES block.
231  *
232  * Return: Returns status, either success or error+reason
233  */
234 int versal_pm_aes_init(void)
235 {
236 	return zynqmp_pm_invoke_fn(XSECURE_API_AES_INIT, NULL, 0);
237 }
238 EXPORT_SYMBOL_GPL(versal_pm_aes_init);
239