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