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