1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2024, HiSilicon Technologies Co., Ltd.
4 * Kunpeng hardware accelerator pbkdf2 implementation.
5 */
6
7 #include <tee/tee_cryp_pbkdf2.h>
8 #include <tee/tee_cryp_utl.h>
9
10 #include "sec_main.h"
11 #include "sec_pbkdf2.h"
12
sec_pbkdf2_parse_sqe(void * bd,void * msg __unused)13 static enum hisi_drv_status sec_pbkdf2_parse_sqe(void *bd, void *msg __unused)
14 {
15 struct hisi_sec_sqe *sqe = bd;
16 uint16_t done = 0;
17
18 done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
19 if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
20 EMSG("SEC do pbkdf2 fail! done=%#"PRIx16", etype=%#"PRIx8,
21 done, sqe->type2.error_type);
22 return HISI_QM_DRVCRYPT_IN_EPARA;
23 }
24
25 return HISI_QM_DRVCRYPT_NO_ERR;
26 }
27
sec_pbkdf2_fill_sqe(void * bd,void * msg)28 static enum hisi_drv_status sec_pbkdf2_fill_sqe(void *bd, void *msg)
29 {
30 struct sec_pbkdf2_msg *pbkdf2_msg = msg;
31 struct hisi_sec_sqe *sqe = bd;
32
33 sqe->type_auth_cipher = BD_TYPE2;
34 sqe->type_auth_cipher |= SHIFT_U32(AUTH_MAC_CALCULATE, SEC_AUTH_OFFSET);
35 sqe->sds_sa_type = SHIFT_U32(SCENE_PBKDF2, SEC_SCENE_OFFSET);
36
37 sqe->type2.mac_key_alg = SHIFT_U32(pbkdf2_msg->derive_type,
38 SEC_AEAD_ALG_OFFSET);
39 /* mac_len = 1 and a_key_len = 1 only for hardware check */
40 sqe->type2.mac_key_alg |= 0x1;
41 sqe->type2.mac_key_alg |= SHIFT_U32(0x1, SEC_AKEY_OFFSET);
42
43 sqe->type2.alen_ivllen = pbkdf2_msg->salt_len;
44 sqe->type2.clen_ivhlen = pbkdf2_msg->c_num;
45 sqe->type2.pass_word_len = (uint16_t)pbkdf2_msg->key_len;
46 sqe->type2.dk_len = (uint16_t)pbkdf2_msg->out_len;
47
48 if (IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE))
49 sqe->huk_ci_key = SHIFT_U32(SEC_HUK_ENABLE, SEC_HUK_OFFSET);
50 else
51 sqe->type2.a_key_addr = pbkdf2_msg->key_dma;
52
53 sqe->type2.data_src_addr = pbkdf2_msg->salt_dma;
54 sqe->type2.mac_addr = pbkdf2_msg->out_dma;
55
56 return HISI_QM_DRVCRYPT_NO_ERR;
57 }
58
sec_pbkdf2_parse_bd3_sqe(void * bd,void * msg __unused)59 static enum hisi_drv_status sec_pbkdf2_parse_bd3_sqe(void *bd,
60 void *msg __unused)
61 {
62 struct hisi_sec_bd3_sqe *sqe = bd;
63 uint16_t done = 0;
64
65 done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
66 if (done != SEC_HW_TASK_DONE || sqe->error_type) {
67 EMSG("SEC do pbkdf2 fail! done=%#"PRIx16", etype=%#"PRIx8,
68 done, sqe->error_type);
69 return HISI_QM_DRVCRYPT_IN_EPARA;
70 }
71
72 return HISI_QM_DRVCRYPT_NO_ERR;
73 }
74
sec_pbkdf2_fill_bd3_sqe(void * bd,void * msg)75 static enum hisi_drv_status sec_pbkdf2_fill_bd3_sqe(void *bd, void *msg)
76 {
77 struct sec_pbkdf2_msg *pbkdf2_msg = msg;
78 struct hisi_sec_bd3_sqe *sqe = bd;
79
80 sqe->bd_param = BD_TYPE3 | SHIFT_U32(SCENE_PBKDF2, SEC_SCENE_OFFSET_V3);
81 sqe->auth_mac_key = AUTH_MAC_CALCULATE;
82 sqe->auth_mac_key |= SHIFT_U32(pbkdf2_msg->derive_type,
83 SEC_AUTH_ALG_OFFSET_V3);
84 /* mac_len = 1 and a_key_len = 1 only for hardware check */
85 sqe->auth_mac_key |= SHIFT_U32(0x1, SEC_AKEY_OFFSET_V3);
86 sqe->auth_mac_key |= SHIFT_U32(0x1, SEC_MAC_OFFSET_V3);
87 sqe->a_len_key = pbkdf2_msg->salt_len;
88 sqe->pbkdf2_scene.pbkdf2_salt_len = pbkdf2_msg->salt_len;
89 sqe->pbkdf2_scene.pass_word_dk_len = pbkdf2_msg->key_len;
90 sqe->pbkdf2_scene.c_num = pbkdf2_msg->c_num;
91 sqe->pbkdf2_scene.pass_word_dk_len |= SHIFT_U32(pbkdf2_msg->out_len,
92 SEC_DK_LEN_OFFSET_V3);
93
94 if (IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE))
95 sqe->auth_mac_key |= SHIFT_U32(SEC_IMG_ROTKEY_AP,
96 SEC_KEY_SEL_OFFSET_V3);
97 else
98 sqe->a_key_addr = pbkdf2_msg->key_dma;
99
100 sqe->data_src_addr = pbkdf2_msg->salt_dma;
101 sqe->mac_addr = pbkdf2_msg->out_dma;
102
103 return HISI_QM_DRVCRYPT_NO_ERR;
104 }
105
sec_pbkdf2_do_task(void * msg)106 static TEE_Result sec_pbkdf2_do_task(void *msg)
107 {
108 enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
109 TEE_Result res = TEE_SUCCESS;
110 struct hisi_qp *qp = NULL;
111
112 qp = sec_create_qp(HISI_QM_CHANNEL_TYPE1);
113 if (!qp) {
114 EMSG("Fail to create pbkdf2 qp");
115 return TEE_ERROR_BUSY;
116 }
117
118 if (qp->qm->version == HISI_QM_HW_V2) {
119 qp->fill_sqe = sec_pbkdf2_fill_sqe;
120 qp->parse_sqe = sec_pbkdf2_parse_sqe;
121 } else {
122 qp->fill_sqe = sec_pbkdf2_fill_bd3_sqe;
123 qp->parse_sqe = sec_pbkdf2_parse_bd3_sqe;
124 }
125
126 ret = hisi_qp_send(qp, msg);
127 if (ret) {
128 EMSG("Fail to send task, ret=%d", ret);
129 res = TEE_ERROR_BAD_STATE;
130 goto done_proc;
131 }
132
133 ret = hisi_qp_recv_sync(qp, msg);
134 if (ret) {
135 EMSG("Recv task error, ret=%d", ret);
136 res = TEE_ERROR_BAD_STATE;
137 goto done_proc;
138 }
139
140 done_proc:
141 hisi_qm_release_qp(qp);
142
143 return res;
144 }
145
sec_pbkdf2_dk_iteration_check(uint32_t alg,uint32_t c_num,size_t dk_len)146 static TEE_Result sec_pbkdf2_dk_iteration_check(uint32_t alg, uint32_t c_num,
147 size_t dk_len)
148 {
149 TEE_Result ret = TEE_SUCCESS;
150 size_t hash_len = 0;
151 size_t t_num = 0;
152 size_t time = 0;
153
154 if (dk_len > SEC_MAX_DK_LEN) {
155 EMSG("Unsupported derived key len %zu", dk_len);
156 return TEE_ERROR_NOT_SUPPORTED;
157 }
158
159 if (c_num > SEC_MAX_ITERATION_NUM) {
160 EMSG("Unsupported iteration count %"PRIu32, c_num);
161 return TEE_ERROR_NOT_SUPPORTED;
162 }
163
164 if (c_num <= SEC_CRITICAL_ITERATION_NUM)
165 return TEE_SUCCESS;
166
167 ret = tee_alg_get_digest_size(alg, &hash_len);
168 if (ret || hash_len == 0) {
169 EMSG("Fail to get digest size");
170 return TEE_ERROR_NOT_SUPPORTED;
171 }
172
173 t_num = ROUNDUP_DIV(dk_len, hash_len);
174
175 if (alg < TEE_ALG_HMAC_SHA384 || alg > TEE_ALG_HMAC_SHA512)
176 time = t_num * SEC_PER_BLOCK_TIME1_NS * c_num;
177 else
178 time = t_num * SEC_PER_BLOCK_TIME2_NS * c_num;
179
180 if (time > SEC_MAX_TIMEOUT_NS) {
181 EMSG("Time %zu is more than sec max timeout", time);
182 return TEE_ERROR_NOT_SUPPORTED;
183 }
184
185 return TEE_SUCCESS;
186 }
187
sec_pbkdf2_params_check(uint32_t hash_id,size_t password_len,size_t salt_len,uint32_t c_num,size_t derived_key_len)188 static TEE_Result sec_pbkdf2_params_check(uint32_t hash_id, size_t password_len,
189 size_t salt_len, uint32_t c_num,
190 size_t derived_key_len)
191 {
192 uint32_t alg = TEE_ALG_HMAC_ALGO(hash_id);
193
194 if (!password_len || !salt_len || !c_num || !derived_key_len) {
195 EMSG("Invalid input parameters");
196 return TEE_ERROR_BAD_PARAMETERS;
197 }
198
199 if ((alg < TEE_ALG_HMAC_SHA384 || alg > TEE_ALG_HMAC_SHA512) &&
200 (password_len > (SEC_MAX_PASSWORD_LEN / 2))) {
201 EMSG("Password_len %zu does not match alg %#"PRIx32,
202 password_len, alg);
203 return TEE_ERROR_BAD_PARAMETERS;
204 }
205
206 if (password_len > SEC_MAX_PASSWORD_LEN) {
207 EMSG("Unsupported password len %zu", password_len);
208 return TEE_ERROR_NOT_SUPPORTED;
209 }
210
211 if (salt_len > SEC_MAX_SALT_LEN) {
212 EMSG("Unsupported salt len %zu", salt_len);
213 return TEE_ERROR_NOT_SUPPORTED;
214 }
215
216 return sec_pbkdf2_dk_iteration_check(alg, c_num, derived_key_len);
217 }
218
sec_pbkdf2_set_derive_type(uint32_t hash_id,struct sec_pbkdf2_msg * msg)219 static TEE_Result sec_pbkdf2_set_derive_type(uint32_t hash_id,
220 struct sec_pbkdf2_msg *msg)
221 {
222 uint32_t alg = TEE_ALG_HMAC_ALGO(hash_id);
223
224 switch (alg) {
225 case TEE_ALG_HMAC_SHA1:
226 msg->derive_type = SEC_HMAC_SHA1;
227 break;
228 case TEE_ALG_HMAC_SHA224:
229 msg->derive_type = SEC_HMAC_SHA224;
230 break;
231 case TEE_ALG_HMAC_SHA256:
232 msg->derive_type = SEC_HMAC_SHA256;
233 break;
234 case TEE_ALG_HMAC_SHA384:
235 msg->derive_type = SEC_HMAC_SHA384;
236 break;
237 case TEE_ALG_HMAC_SHA512:
238 msg->derive_type = SEC_HMAC_SHA512;
239 break;
240 case TEE_ALG_HMAC_SM3:
241 msg->derive_type = SEC_HMAC_SM3;
242 break;
243 default:
244 EMSG("Invalid hamc alg type %#"PRIx32, alg);
245 return TEE_ERROR_BAD_PARAMETERS;
246 }
247
248 return TEE_SUCCESS;
249 }
250
sec_pbkdf2_set_buf(const uint8_t * password,const uint8_t * salt,struct sec_pbkdf2_msg * msg)251 static TEE_Result sec_pbkdf2_set_buf(const uint8_t *password,
252 const uint8_t *salt,
253 struct sec_pbkdf2_msg *msg)
254 {
255 msg->key_dma = virt_to_phys(msg->base_key);
256 if (!msg->key_dma) {
257 EMSG("Fail to get key dma addr");
258 return TEE_ERROR_BAD_STATE;
259 }
260
261 msg->salt_dma = virt_to_phys(msg->salt);
262 if (!msg->salt_dma) {
263 EMSG("Fail to get salt dma addr");
264 return TEE_ERROR_BAD_STATE;
265 }
266
267 msg->out_dma = virt_to_phys(msg->out);
268 if (!msg->out_dma) {
269 EMSG("Fail to get out dma addr");
270 return TEE_ERROR_BAD_STATE;
271 }
272
273 if (password)
274 memcpy(msg->base_key, password, msg->key_len);
275
276 memcpy(msg->salt, salt, msg->salt_len);
277
278 return TEE_SUCCESS;
279 }
280
sec_pbkdf2_clean_buf(struct sec_pbkdf2_msg * msg)281 static void sec_pbkdf2_clean_buf(struct sec_pbkdf2_msg *msg)
282 {
283 memzero_explicit(msg->base_key, msg->key_len);
284 memzero_explicit(msg->salt, msg->salt_len);
285 }
286
sec_pbkdf2_msg_init(uint32_t hash_id,size_t password_len,size_t salt_len,size_t derived_key_len,uint32_t iteration_count,struct sec_pbkdf2_msg * msg)287 static TEE_Result sec_pbkdf2_msg_init(uint32_t hash_id, size_t password_len,
288 size_t salt_len, size_t derived_key_len,
289 uint32_t iteration_count,
290 struct sec_pbkdf2_msg *msg)
291 {
292 msg->key_len = password_len;
293 msg->salt_len = salt_len;
294 msg->out_len = derived_key_len;
295 msg->c_num = iteration_count;
296 return sec_pbkdf2_set_derive_type(hash_id, msg);
297 }
298
tee_cryp_pbkdf2(uint32_t hash_id,const uint8_t * password,size_t password_len,const uint8_t * salt,size_t salt_len,uint32_t iteration_count,uint8_t * derived_key,size_t derived_key_len)299 TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
300 size_t password_len, const uint8_t *salt,
301 size_t salt_len, uint32_t iteration_count,
302 uint8_t *derived_key, size_t derived_key_len)
303 {
304 TEE_Result ret = TEE_ERROR_GENERIC;
305 struct sec_pbkdf2_msg *msg = NULL;
306
307 if (!IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE) && !password) {
308 EMSG("Password buf is NULL");
309 return TEE_ERROR_BAD_PARAMETERS;
310 }
311
312 if (!salt || !derived_key) {
313 EMSG("Invalid pbkdf2 buf");
314 return TEE_ERROR_BAD_PARAMETERS;
315 }
316
317 ret = sec_pbkdf2_params_check(hash_id, password_len, salt_len,
318 iteration_count, derived_key_len);
319 if (ret)
320 return ret;
321
322 msg = calloc(1, sizeof(*msg));
323 if (!msg) {
324 EMSG("Fail to calloc msg");
325 return TEE_ERROR_OUT_OF_MEMORY;
326 }
327
328 ret = sec_pbkdf2_msg_init(hash_id, password_len, salt_len,
329 derived_key_len, iteration_count, msg);
330 if (ret)
331 goto free_msg;
332
333 ret = sec_pbkdf2_set_buf(password, salt, msg);
334 if (ret)
335 goto free_msg;
336
337 ret = sec_pbkdf2_do_task(msg);
338 if (ret)
339 goto clean_buf;
340
341 memcpy(derived_key, msg->out, msg->out_len);
342
343 clean_buf:
344 sec_pbkdf2_clean_buf(msg);
345 free_msg:
346 free(msg);
347
348 return ret;
349 }
350