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