1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd. 4 * Kunpeng hardware accelerator hpre dh algorithm implementation. 5 */ 6 7 #include <drvcrypt.h> 8 #include <drvcrypt_acipher.h> 9 #include <hpre_dh.h> 10 #include <hpre_main.h> 11 #include <initcall.h> 12 #include <malloc.h> 13 #include <rng_support.h> 14 #include <stdlib_ext.h> 15 #include <string.h> 16 #include <string_ext.h> 17 #include <trace.h> 18 19 static TEE_Result hpre_dh_alloc_keypair(struct dh_keypair *key, 20 size_t size_bits) 21 { 22 if (!key || !size_bits) { 23 EMSG("Invalid input parameter"); 24 return TEE_ERROR_BAD_PARAMETERS; 25 } 26 27 memset(key, 0, sizeof(*key)); 28 key->g = crypto_bignum_allocate(size_bits); 29 if (!key->g) 30 goto g_err; 31 32 key->p = crypto_bignum_allocate(size_bits); 33 if (!key->p) 34 goto p_err; 35 36 key->x = crypto_bignum_allocate(size_bits); 37 if (!key->x) 38 goto x_err; 39 40 key->y = crypto_bignum_allocate(size_bits); 41 if (!key->y) 42 goto y_err; 43 44 /* Allocate subprime even if not used */ 45 key->q = crypto_bignum_allocate(size_bits); 46 if (!key->q) 47 goto q_err; 48 49 return TEE_SUCCESS; 50 q_err: 51 crypto_bignum_free(&key->y); 52 y_err: 53 crypto_bignum_free(&key->x); 54 x_err: 55 crypto_bignum_free(&key->p); 56 p_err: 57 crypto_bignum_free(&key->g); 58 g_err: 59 EMSG("HPRE dh alloc key pair fail."); 60 61 return TEE_ERROR_OUT_OF_MEMORY; 62 } 63 64 static enum hisi_drv_status hpre_dh_fill_sqe(void *bd, void *info) 65 { 66 struct hpre_dh_msg *msg = info; 67 struct hpre_sqe *sqe = bd; 68 69 sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT); 70 sqe->task_len1 = TASK_LENGTH(msg->key_bytes); 71 sqe->key = msg->x_p_dma; 72 sqe->in = msg->g_dma; 73 sqe->out = msg->out_dma; 74 75 return HISI_QM_DRVCRYPT_NO_ERR; 76 } 77 78 static enum hisi_drv_status hpre_dh_parse_sqe(void *bd, void *info) 79 { 80 struct hpre_dh_msg *msg = info; 81 struct hpre_sqe *sqe = bd; 82 uint16_t err = 0; 83 uint16_t done = 0; 84 85 err = HPRE_TASK_ETYPE(sqe->w0); 86 done = HPRE_TASK_DONE(sqe->w0); 87 if (done != HPRE_HW_TASK_DONE || err) { 88 EMSG("HPRE do dh fail! done=0x%"PRIx16", etype=0x%"PRIx16, 89 done, err); 90 return HISI_QM_DRVCRYPT_IN_EPARA; 91 } 92 93 if (hpre_bin_to_crypto_bin(msg->out, msg->out, msg->key_bytes, 94 msg->out_bytes)) { 95 EMSG("Fail to transfer dh_y from hpre_bin to crypto_bin"); 96 return HISI_QM_DRVCRYPT_EINVAL; 97 } 98 99 return HISI_QM_DRVCRYPT_NO_ERR; 100 } 101 102 static TEE_Result hpre_dh_do_task(void *msg) 103 { 104 enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; 105 TEE_Result res = TEE_SUCCESS; 106 struct hisi_qp *qp = NULL; 107 108 qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE0); 109 if (!qp) { 110 EMSG("Fail to create dh qp"); 111 return TEE_ERROR_BUSY; 112 } 113 114 qp->fill_sqe = hpre_dh_fill_sqe; 115 qp->parse_sqe = hpre_dh_parse_sqe; 116 ret = hisi_qp_send(qp, msg); 117 if (ret) { 118 EMSG("Fail to send task, ret=%d", ret); 119 res = TEE_ERROR_BAD_STATE; 120 goto done_proc; 121 } 122 123 ret = hisi_qp_recv_sync(qp, msg); 124 if (ret) { 125 EMSG("Recv task error, ret=%d", ret); 126 res = TEE_ERROR_BAD_STATE; 127 goto done_proc; 128 } 129 130 done_proc: 131 hisi_qm_release_qp(qp); 132 133 return res; 134 } 135 136 static size_t round_key_size_to_hw_size(size_t key_bytes) 137 { 138 size_t size = 0; 139 140 if (key_bytes <= 96) 141 size = 96; 142 else if (key_bytes <= 128) 143 size = 128; 144 else if (key_bytes <= 192) 145 size = 192; 146 else if (key_bytes <= 256) 147 size = 256; 148 else if (key_bytes <= 384) 149 size = 384; 150 else if (key_bytes <= 512) 151 size = 512; 152 else 153 EMSG("Invalid key_bytes[%zu]", key_bytes); 154 155 return size; 156 } 157 158 static TEE_Result hpre_dh_gen_privkey(struct bignum *x, size_t key_bits) 159 { 160 size_t key_bytes = BITS_TO_BYTES(key_bits); 161 uint8_t buf[HPRE_DH_MAX_KEY_BYTES] = { }; 162 TEE_Result ret = TEE_SUCCESS; 163 164 if (hw_get_random_bytes(buf, key_bytes)) { 165 EMSG("Fail to fill privkey"); 166 return TEE_ERROR_NO_DATA; 167 } 168 169 ret = crypto_bignum_bin2bn(buf, key_bytes, x); 170 memzero_explicit(buf, key_bytes); 171 172 return ret; 173 } 174 175 static enum hisi_drv_status hpre_dh_params_alloc(struct hpre_dh_msg *msg) 176 { 177 uint32_t size = HPRE_DH_TOTAL_BUF_SIZE(msg->key_bytes); 178 uint8_t *data = NULL; 179 180 data = calloc(1, size); 181 if (!data) { 182 EMSG("Fail to alloc dh total buf"); 183 return HISI_QM_DRVCRYPT_ENOMEM; 184 } 185 186 msg->x_p = data; 187 msg->x_p_dma = virt_to_phys(msg->x_p); 188 189 msg->g = msg->x_p + (msg->key_bytes << 1); 190 msg->g_dma = msg->x_p_dma + (msg->key_bytes << 1); 191 msg->out = msg->g + msg->key_bytes; 192 msg->out_dma = msg->g_dma + msg->key_bytes; 193 194 return HISI_QM_DRVCRYPT_NO_ERR; 195 } 196 197 static void hpre_dh_params_free(struct hpre_dh_msg *msg) 198 { 199 if (msg->x_p) { 200 free_wipe(msg->x_p); 201 msg->x_p = NULL; 202 } 203 } 204 205 static enum hisi_drv_status hpre_dh_params_bn2bin(struct hpre_dh_msg *msg, 206 struct dh_keypair *key, 207 struct bignum *pubkey) 208 { 209 uint8_t *p = msg->x_p + msg->key_bytes; 210 uint8_t *x = msg->x_p; 211 enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; 212 213 msg->xbytes = BITS_TO_BYTES(key->xbits); 214 msg->out_bytes = msg->pbytes; 215 crypto_bignum_bn2bin(key->x, x); 216 crypto_bignum_bn2bin(key->p, p); 217 218 if (!pubkey) { 219 msg->gbytes = crypto_bignum_num_bytes(key->g); 220 crypto_bignum_bn2bin(key->g, msg->g); 221 } else { 222 msg->gbytes = crypto_bignum_num_bytes(pubkey); 223 if (msg->gbytes != msg->pbytes) 224 return HISI_QM_DRVCRYPT_EINVAL; 225 crypto_bignum_bn2bin(pubkey, msg->g); 226 } 227 228 ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes, msg->xbytes); 229 if (ret) { 230 EMSG("Fail to transfer dh_x from crypto_bin to hpre_bin"); 231 return ret; 232 } 233 234 ret = hpre_bin_from_crypto_bin(p, p, msg->key_bytes, msg->pbytes); 235 if (ret) { 236 EMSG("Fail to transfer dh_p from crypto_bin to hpre_bin"); 237 return ret; 238 } 239 240 ret = hpre_bin_from_crypto_bin(msg->g, msg->g, msg->key_bytes, 241 msg->gbytes); 242 if (ret) 243 EMSG("Fail to transfer dh_g from crypto_bin to hpre_bin"); 244 245 return ret; 246 } 247 248 static TEE_Result hpre_dh_request_init(struct hpre_dh_msg *msg, 249 struct dh_keypair *key, 250 struct bignum *pubkey) 251 { 252 enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR; 253 254 msg->alg_type = HPRE_ALG_DH; 255 msg->key_bytes = round_key_size_to_hw_size(msg->pbytes); 256 if (!msg->key_bytes) 257 return TEE_ERROR_BAD_PARAMETERS; 258 259 ret = hpre_dh_params_alloc(msg); 260 if (ret) 261 return TEE_ERROR_OUT_OF_MEMORY; 262 263 ret = hpre_dh_params_bn2bin(msg, key, pubkey); 264 if (ret) { 265 hpre_dh_params_free(msg); 266 return TEE_ERROR_BAD_STATE; 267 } 268 269 return TEE_SUCCESS; 270 } 271 272 static void hpre_dh_request_deinit(struct hpre_dh_msg *msg) 273 { 274 hpre_dh_params_free(msg); 275 } 276 277 static TEE_Result hpre_dh_gen_keypair(struct dh_keypair *key, 278 struct bignum *q __unused, 279 size_t key_size) 280 { 281 struct hpre_dh_msg msg = { }; 282 TEE_Result ret = TEE_SUCCESS; 283 size_t p_bits = 0; 284 285 if (!key || !key->g || !key->p || !key->x || !key->y) { 286 EMSG("Invalid dh_gen_keypair input parameters"); 287 return TEE_ERROR_BAD_PARAMETERS; 288 } 289 290 p_bits = crypto_bignum_num_bits(key->p); 291 if (!p_bits) { 292 EMSG("p_bits can not be zero"); 293 return TEE_ERROR_BAD_PARAMETERS; 294 } 295 msg.pbytes = BITS_TO_BYTES(p_bits); 296 297 if (!key_size) { 298 /* xbits */ 299 key->xbits = p_bits; 300 ret = hpre_dh_gen_privkey(key->x, key->xbits); 301 if (ret) { 302 EMSG("Fail to gen dh privkey"); 303 return ret; 304 } 305 } else { 306 key->xbits = key_size; 307 } 308 309 ret = hpre_dh_request_init(&msg, key, NULL); 310 if (ret) { 311 EMSG("Fail to init dh msg"); 312 return ret; 313 } 314 315 ret = hpre_dh_do_task(&msg); 316 if (ret) 317 goto req_deinit; 318 319 ret = crypto_bignum_bin2bn(msg.out, msg.out_bytes, key->y); 320 if (ret) 321 EMSG("Fail to bin2bn msg out"); 322 323 req_deinit: 324 hpre_dh_request_deinit(&msg); 325 326 return ret; 327 } 328 329 static TEE_Result hpre_dh_do_shared_secret(struct drvcrypt_secret_data *sdata) 330 { 331 struct hpre_dh_msg msg = { }; 332 struct dh_keypair *key = NULL; 333 TEE_Result ret = TEE_SUCCESS; 334 335 if (!sdata || !sdata->key_priv || !sdata->key_pub) { 336 EMSG("Invalid dh_do_shared_secret input parameters"); 337 return TEE_ERROR_BAD_PARAMETERS; 338 } 339 340 key = sdata->key_priv; 341 key->xbits = crypto_bignum_num_bits(key->x); 342 if (!key->xbits) { 343 EMSG("xbits can not be zero"); 344 return TEE_ERROR_BAD_PARAMETERS; 345 } 346 msg.pbytes = crypto_bignum_num_bytes(key->p); 347 348 ret = hpre_dh_request_init(&msg, key, (struct bignum *)sdata->key_pub); 349 if (ret) { 350 EMSG("Fail to init dh msg"); 351 return ret; 352 } 353 354 ret = hpre_dh_do_task(&msg); 355 if (ret) 356 goto req_deinit; 357 358 sdata->secret.length = msg.out_bytes; 359 memcpy(sdata->secret.data, msg.out, msg.out_bytes); 360 memzero_explicit(msg.out, msg.out_bytes); 361 362 req_deinit: 363 hpre_dh_request_deinit(&msg); 364 365 return ret; 366 } 367 368 static struct drvcrypt_dh driver_dh = { 369 .alloc_keypair = hpre_dh_alloc_keypair, 370 .gen_keypair = hpre_dh_gen_keypair, 371 .shared_secret = hpre_dh_do_shared_secret, 372 }; 373 374 TEE_Result hpre_dh_init(void) 375 { 376 TEE_Result ret = drvcrypt_register_dh(&driver_dh); 377 378 if (ret != TEE_SUCCESS) 379 EMSG("hpre dh register to crypto fail."); 380 381 return ret; 382 } 383 384 driver_init(hpre_dh_init); 385