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 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 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 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 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 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 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 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 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 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 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 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 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