0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/clk.h>
0011 #include <linux/completion.h>
0012 #include <linux/crypto.h>
0013 #include <linux/delay.h>
0014 #include <linux/fips.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/io.h>
0017 #include <linux/iopoll.h>
0018 #include <linux/irq.h>
0019 #include <linux/module.h>
0020 #include <linux/of.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/scatterlist.h>
0023 #include <linux/slab.h>
0024 #include <linux/types.h>
0025
0026 #include <crypto/ecc_curve.h>
0027 #include <crypto/ecdh.h>
0028 #include <crypto/engine.h>
0029 #include <crypto/kpp.h>
0030 #include <crypto/rng.h>
0031
0032 #include <crypto/internal/ecc.h>
0033 #include <crypto/internal/kpp.h>
0034
0035 #define DRV_NAME "keembay-ocs-ecc"
0036
0037 #define KMB_OCS_ECC_PRIORITY 350
0038
0039 #define HW_OFFS_OCS_ECC_COMMAND 0x00000000
0040 #define HW_OFFS_OCS_ECC_STATUS 0x00000004
0041 #define HW_OFFS_OCS_ECC_DATA_IN 0x00000080
0042 #define HW_OFFS_OCS_ECC_CX_DATA_OUT 0x00000100
0043 #define HW_OFFS_OCS_ECC_CY_DATA_OUT 0x00000180
0044 #define HW_OFFS_OCS_ECC_ISR 0x00000400
0045 #define HW_OFFS_OCS_ECC_IER 0x00000404
0046
0047 #define HW_OCS_ECC_ISR_INT_STATUS_DONE BIT(0)
0048 #define HW_OCS_ECC_COMMAND_INS_BP BIT(0)
0049
0050 #define HW_OCS_ECC_COMMAND_START_VAL BIT(0)
0051
0052 #define OCS_ECC_OP_SIZE_384 BIT(8)
0053 #define OCS_ECC_OP_SIZE_256 0
0054
0055
0056 #define OCS_ECC_INST_WRITE_AX (0x1 << HW_OCS_ECC_COMMAND_INS_BP)
0057 #define OCS_ECC_INST_WRITE_AY (0x2 << HW_OCS_ECC_COMMAND_INS_BP)
0058 #define OCS_ECC_INST_WRITE_BX_D (0x3 << HW_OCS_ECC_COMMAND_INS_BP)
0059 #define OCS_ECC_INST_WRITE_BY_L (0x4 << HW_OCS_ECC_COMMAND_INS_BP)
0060 #define OCS_ECC_INST_WRITE_P (0x5 << HW_OCS_ECC_COMMAND_INS_BP)
0061 #define OCS_ECC_INST_WRITE_A (0x6 << HW_OCS_ECC_COMMAND_INS_BP)
0062 #define OCS_ECC_INST_CALC_D_IDX_A (0x8 << HW_OCS_ECC_COMMAND_INS_BP)
0063 #define OCS_ECC_INST_CALC_A_POW_B_MODP (0xB << HW_OCS_ECC_COMMAND_INS_BP)
0064 #define OCS_ECC_INST_CALC_A_MUL_B_MODP (0xC << HW_OCS_ECC_COMMAND_INS_BP)
0065 #define OCS_ECC_INST_CALC_A_ADD_B_MODP (0xD << HW_OCS_ECC_COMMAND_INS_BP)
0066
0067 #define ECC_ENABLE_INTR 1
0068
0069 #define POLL_USEC 100
0070 #define TIMEOUT_USEC 10000
0071
0072 #define KMB_ECC_VLI_MAX_DIGITS ECC_CURVE_NIST_P384_DIGITS
0073 #define KMB_ECC_VLI_MAX_BYTES (KMB_ECC_VLI_MAX_DIGITS \
0074 << ECC_DIGITS_TO_BYTES_SHIFT)
0075
0076 #define POW_CUBE 3
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 struct ocs_ecc_dev {
0088 struct list_head list;
0089 struct device *dev;
0090 void __iomem *base_reg;
0091 struct crypto_engine *engine;
0092 struct completion irq_done;
0093 int irq;
0094 };
0095
0096
0097
0098
0099
0100
0101
0102
0103 struct ocs_ecc_ctx {
0104 struct crypto_engine_ctx engine_ctx;
0105 struct ocs_ecc_dev *ecc_dev;
0106 const struct ecc_curve *curve;
0107 u64 private_key[KMB_ECC_VLI_MAX_DIGITS];
0108 };
0109
0110
0111 struct ocs_ecc_drv {
0112 struct list_head dev_list;
0113 spinlock_t lock;
0114 };
0115
0116
0117 static struct ocs_ecc_drv ocs_ecc = {
0118 .dev_list = LIST_HEAD_INIT(ocs_ecc.dev_list),
0119 .lock = __SPIN_LOCK_UNLOCKED(ocs_ecc.lock),
0120 };
0121
0122
0123 static inline struct ocs_ecc_ctx *kmb_ocs_ecc_tctx(struct kpp_request *req)
0124 {
0125 return kpp_tfm_ctx(crypto_kpp_reqtfm(req));
0126 }
0127
0128
0129 static inline unsigned int digits_to_bytes(unsigned int n)
0130 {
0131 return n << ECC_DIGITS_TO_BYTES_SHIFT;
0132 }
0133
0134
0135
0136
0137
0138 static inline int ocs_ecc_wait_idle(struct ocs_ecc_dev *dev)
0139 {
0140 u32 value;
0141
0142 return readl_poll_timeout((dev->base_reg + HW_OFFS_OCS_ECC_STATUS),
0143 value,
0144 !(value & HW_OCS_ECC_ISR_INT_STATUS_DONE),
0145 POLL_USEC, TIMEOUT_USEC);
0146 }
0147
0148 static void ocs_ecc_cmd_start(struct ocs_ecc_dev *ecc_dev, u32 op_size)
0149 {
0150 iowrite32(op_size | HW_OCS_ECC_COMMAND_START_VAL,
0151 ecc_dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);
0152 }
0153
0154
0155 static void ocs_ecc_write_cmd_and_data(struct ocs_ecc_dev *dev,
0156 u32 op_size,
0157 u32 inst,
0158 const void *data_in,
0159 size_t data_size)
0160 {
0161 iowrite32(op_size | inst, dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);
0162
0163
0164 memcpy_toio(dev->base_reg + HW_OFFS_OCS_ECC_DATA_IN, data_in,
0165 data_size);
0166 }
0167
0168
0169 static int ocs_ecc_trigger_op(struct ocs_ecc_dev *ecc_dev, u32 op_size,
0170 u32 inst)
0171 {
0172 reinit_completion(&ecc_dev->irq_done);
0173
0174 iowrite32(ECC_ENABLE_INTR, ecc_dev->base_reg + HW_OFFS_OCS_ECC_IER);
0175 iowrite32(op_size | inst, ecc_dev->base_reg + HW_OFFS_OCS_ECC_COMMAND);
0176
0177 return wait_for_completion_interruptible(&ecc_dev->irq_done);
0178 }
0179
0180
0181
0182
0183
0184
0185
0186
0187 static inline void ocs_ecc_read_cx_out(struct ocs_ecc_dev *dev, void *cx_out,
0188 size_t byte_count)
0189 {
0190 memcpy_fromio(cx_out, dev->base_reg + HW_OFFS_OCS_ECC_CX_DATA_OUT,
0191 byte_count);
0192 }
0193
0194
0195
0196
0197
0198
0199
0200
0201 static inline void ocs_ecc_read_cy_out(struct ocs_ecc_dev *dev, void *cy_out,
0202 size_t byte_count)
0203 {
0204 memcpy_fromio(cy_out, dev->base_reg + HW_OFFS_OCS_ECC_CY_DATA_OUT,
0205 byte_count);
0206 }
0207
0208 static struct ocs_ecc_dev *kmb_ocs_ecc_find_dev(struct ocs_ecc_ctx *tctx)
0209 {
0210 if (tctx->ecc_dev)
0211 return tctx->ecc_dev;
0212
0213 spin_lock(&ocs_ecc.lock);
0214
0215
0216 tctx->ecc_dev = list_first_entry(&ocs_ecc.dev_list, struct ocs_ecc_dev,
0217 list);
0218
0219 spin_unlock(&ocs_ecc.lock);
0220
0221 return tctx->ecc_dev;
0222 }
0223
0224
0225 static int kmb_ecc_point_mult(struct ocs_ecc_dev *ecc_dev,
0226 struct ecc_point *result,
0227 const struct ecc_point *point,
0228 u64 *scalar,
0229 const struct ecc_curve *curve)
0230 {
0231 u8 sca[KMB_ECC_VLI_MAX_BYTES];
0232 u32 op_size = (curve->g.ndigits > ECC_CURVE_NIST_P256_DIGITS) ?
0233 OCS_ECC_OP_SIZE_384 : OCS_ECC_OP_SIZE_256;
0234 size_t nbytes = digits_to_bytes(curve->g.ndigits);
0235 int rc = 0;
0236
0237
0238 rc = crypto_get_default_rng();
0239 if (rc)
0240 return rc;
0241
0242 rc = crypto_rng_get_bytes(crypto_default_rng, sca, nbytes);
0243 crypto_put_default_rng();
0244 if (rc)
0245 return rc;
0246
0247
0248 rc = ocs_ecc_wait_idle(ecc_dev);
0249 if (rc)
0250 return rc;
0251
0252
0253 ocs_ecc_cmd_start(ecc_dev, op_size);
0254
0255
0256 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AX,
0257 point->x, nbytes);
0258
0259
0260 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AY,
0261 point->y, nbytes);
0262
0263
0264
0265
0266
0267
0268
0269
0270 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_BX_D,
0271 scalar, nbytes);
0272
0273
0274 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_BY_L,
0275 sca, nbytes);
0276 memzero_explicit(sca, sizeof(sca));
0277
0278
0279 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_P,
0280 curve->p, nbytes);
0281
0282
0283 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_A,
0284 curve->a, nbytes);
0285
0286
0287 rc = ocs_ecc_trigger_op(ecc_dev, op_size, OCS_ECC_INST_CALC_D_IDX_A);
0288 if (rc)
0289 return rc;
0290
0291
0292 ocs_ecc_read_cx_out(ecc_dev, result->x, nbytes);
0293 ocs_ecc_read_cy_out(ecc_dev, result->y, nbytes);
0294
0295 return 0;
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 static int kmb_ecc_do_scalar_op(struct ocs_ecc_dev *ecc_dev, u64 *scalar_out,
0311 const u64 *scalar_a, const u64 *scalar_b,
0312 const struct ecc_curve *curve,
0313 unsigned int ndigits, const u32 inst)
0314 {
0315 u32 op_size = (ndigits > ECC_CURVE_NIST_P256_DIGITS) ?
0316 OCS_ECC_OP_SIZE_384 : OCS_ECC_OP_SIZE_256;
0317 size_t nbytes = digits_to_bytes(ndigits);
0318 int rc;
0319
0320
0321 rc = ocs_ecc_wait_idle(ecc_dev);
0322 if (rc)
0323 return rc;
0324
0325
0326 ocs_ecc_cmd_start(ecc_dev, op_size);
0327
0328
0329 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AX,
0330 scalar_a, nbytes);
0331
0332
0333 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AY,
0334 scalar_b, nbytes);
0335
0336
0337 ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_P,
0338 curve->p, nbytes);
0339
0340
0341 rc = ocs_ecc_trigger_op(ecc_dev, op_size, inst);
0342 if (rc)
0343 return rc;
0344
0345 ocs_ecc_read_cx_out(ecc_dev, scalar_out, nbytes);
0346
0347 if (vli_is_zero(scalar_out, ndigits))
0348 return -EINVAL;
0349
0350 return 0;
0351 }
0352
0353
0354 static int kmb_ocs_ecc_is_pubkey_valid_partial(struct ocs_ecc_dev *ecc_dev,
0355 const struct ecc_curve *curve,
0356 struct ecc_point *pk)
0357 {
0358 u64 xxx[KMB_ECC_VLI_MAX_DIGITS] = { 0 };
0359 u64 yy[KMB_ECC_VLI_MAX_DIGITS] = { 0 };
0360 u64 w[KMB_ECC_VLI_MAX_DIGITS] = { 0 };
0361 int rc;
0362
0363 if (WARN_ON(pk->ndigits != curve->g.ndigits))
0364 return -EINVAL;
0365
0366
0367 if (ecc_point_is_zero(pk))
0368 return -EINVAL;
0369
0370
0371 if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
0372 return -EINVAL;
0373
0374 if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
0375 return -EINVAL;
0376
0377
0378
0379
0380
0381 rc = kmb_ecc_do_scalar_op(ecc_dev, yy, pk->y, pk->y, curve, pk->ndigits,
0382 OCS_ECC_INST_CALC_A_MUL_B_MODP);
0383 if (rc)
0384 goto exit;
0385
0386
0387
0388 w[0] = POW_CUBE;
0389
0390 rc = kmb_ecc_do_scalar_op(ecc_dev, xxx, pk->x, w, curve, pk->ndigits,
0391 OCS_ECC_INST_CALC_A_POW_B_MODP);
0392 if (rc)
0393 goto exit;
0394
0395
0396 rc = kmb_ecc_do_scalar_op(ecc_dev, w, curve->a, pk->x, curve,
0397 pk->ndigits,
0398 OCS_ECC_INST_CALC_A_MUL_B_MODP);
0399 if (rc)
0400 goto exit;
0401
0402
0403 rc = kmb_ecc_do_scalar_op(ecc_dev, w, w, curve->b, curve,
0404 pk->ndigits,
0405 OCS_ECC_INST_CALC_A_ADD_B_MODP);
0406 if (rc)
0407 goto exit;
0408
0409
0410 rc = kmb_ecc_do_scalar_op(ecc_dev, w, xxx, w, curve, pk->ndigits,
0411 OCS_ECC_INST_CALC_A_ADD_B_MODP);
0412 if (rc)
0413 goto exit;
0414
0415
0416 rc = vli_cmp(yy, w, pk->ndigits);
0417 if (rc)
0418 rc = -EINVAL;
0419
0420 exit:
0421 memzero_explicit(xxx, sizeof(xxx));
0422 memzero_explicit(yy, sizeof(yy));
0423 memzero_explicit(w, sizeof(w));
0424
0425 return rc;
0426 }
0427
0428
0429 static int kmb_ocs_ecc_is_pubkey_valid_full(struct ocs_ecc_dev *ecc_dev,
0430 const struct ecc_curve *curve,
0431 struct ecc_point *pk)
0432 {
0433 struct ecc_point *nQ;
0434 int rc;
0435
0436
0437 rc = kmb_ocs_ecc_is_pubkey_valid_partial(ecc_dev, curve, pk);
0438 if (rc)
0439 return rc;
0440
0441
0442 nQ = ecc_alloc_point(pk->ndigits);
0443 if (!nQ)
0444 return -ENOMEM;
0445
0446 rc = kmb_ecc_point_mult(ecc_dev, nQ, pk, curve->n, curve);
0447 if (rc)
0448 goto exit;
0449
0450 if (!ecc_point_is_zero(nQ))
0451 rc = -EINVAL;
0452
0453 exit:
0454 ecc_free_point(nQ);
0455
0456 return rc;
0457 }
0458
0459 static int kmb_ecc_is_key_valid(const struct ecc_curve *curve,
0460 const u64 *private_key, size_t private_key_len)
0461 {
0462 size_t ndigits = curve->g.ndigits;
0463 u64 one[KMB_ECC_VLI_MAX_DIGITS] = {1};
0464 u64 res[KMB_ECC_VLI_MAX_DIGITS];
0465
0466 if (private_key_len != digits_to_bytes(ndigits))
0467 return -EINVAL;
0468
0469 if (!private_key)
0470 return -EINVAL;
0471
0472
0473 if (vli_cmp(one, private_key, ndigits) != -1)
0474 return -EINVAL;
0475
0476 vli_sub(res, curve->n, one, ndigits);
0477 vli_sub(res, res, one, ndigits);
0478 if (vli_cmp(res, private_key, ndigits) != 1)
0479 return -EINVAL;
0480
0481 return 0;
0482 }
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496 static int kmb_ecc_gen_privkey(const struct ecc_curve *curve, u64 *privkey)
0497 {
0498 size_t nbytes = digits_to_bytes(curve->g.ndigits);
0499 u64 priv[KMB_ECC_VLI_MAX_DIGITS];
0500 size_t nbits;
0501 int rc;
0502
0503 nbits = vli_num_bits(curve->n, curve->g.ndigits);
0504
0505
0506 if (nbits < 160 || curve->g.ndigits > ARRAY_SIZE(priv))
0507 return -EINVAL;
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 if (crypto_get_default_rng())
0521 return -EFAULT;
0522
0523 rc = crypto_rng_get_bytes(crypto_default_rng, (u8 *)priv, nbytes);
0524 crypto_put_default_rng();
0525 if (rc)
0526 goto cleanup;
0527
0528 rc = kmb_ecc_is_key_valid(curve, priv, nbytes);
0529 if (rc)
0530 goto cleanup;
0531
0532 ecc_swap_digits(priv, privkey, curve->g.ndigits);
0533
0534 cleanup:
0535 memzero_explicit(&priv, sizeof(priv));
0536
0537 return rc;
0538 }
0539
0540 static int kmb_ocs_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
0541 unsigned int len)
0542 {
0543 struct ocs_ecc_ctx *tctx = kpp_tfm_ctx(tfm);
0544 struct ecdh params;
0545 int rc = 0;
0546
0547 rc = crypto_ecdh_decode_key(buf, len, ¶ms);
0548 if (rc)
0549 goto cleanup;
0550
0551
0552 if (params.key_size > digits_to_bytes(tctx->curve->g.ndigits)) {
0553 rc = -EINVAL;
0554 goto cleanup;
0555 }
0556
0557
0558 if (!params.key || !params.key_size) {
0559 rc = kmb_ecc_gen_privkey(tctx->curve, tctx->private_key);
0560 goto cleanup;
0561 }
0562
0563 rc = kmb_ecc_is_key_valid(tctx->curve, (const u64 *)params.key,
0564 params.key_size);
0565 if (rc)
0566 goto cleanup;
0567
0568 ecc_swap_digits((const u64 *)params.key, tctx->private_key,
0569 tctx->curve->g.ndigits);
0570 cleanup:
0571 memzero_explicit(¶ms, sizeof(params));
0572
0573 if (rc)
0574 tctx->curve = NULL;
0575
0576 return rc;
0577 }
0578
0579
0580 static int kmb_ecc_do_shared_secret(struct ocs_ecc_ctx *tctx,
0581 struct kpp_request *req)
0582 {
0583 struct ocs_ecc_dev *ecc_dev = tctx->ecc_dev;
0584 const struct ecc_curve *curve = tctx->curve;
0585 u64 shared_secret[KMB_ECC_VLI_MAX_DIGITS];
0586 u64 pubk_buf[KMB_ECC_VLI_MAX_DIGITS * 2];
0587 size_t copied, nbytes, pubk_len;
0588 struct ecc_point *pk, *result;
0589 int rc;
0590
0591 nbytes = digits_to_bytes(curve->g.ndigits);
0592
0593
0594 pubk_len = 2 * nbytes;
0595
0596
0597 copied = sg_copy_to_buffer(req->src,
0598 sg_nents_for_len(req->src, pubk_len),
0599 pubk_buf, pubk_len);
0600 if (copied != pubk_len)
0601 return -EINVAL;
0602
0603
0604 pk = ecc_alloc_point(curve->g.ndigits);
0605 if (!pk)
0606 return -ENOMEM;
0607
0608 ecc_swap_digits(pubk_buf, pk->x, curve->g.ndigits);
0609 ecc_swap_digits(&pubk_buf[curve->g.ndigits], pk->y, curve->g.ndigits);
0610
0611
0612
0613
0614
0615
0616
0617 rc = kmb_ocs_ecc_is_pubkey_valid_partial(ecc_dev, curve, pk);
0618 if (rc)
0619 goto exit_free_pk;
0620
0621
0622 result = ecc_alloc_point(pk->ndigits);
0623 if (!result) {
0624 rc = -ENOMEM;
0625 goto exit_free_pk;
0626 }
0627
0628
0629 rc = kmb_ecc_point_mult(ecc_dev, result, pk, tctx->private_key, curve);
0630 if (rc)
0631 goto exit_free_result;
0632
0633 if (ecc_point_is_zero(result)) {
0634 rc = -EFAULT;
0635 goto exit_free_result;
0636 }
0637
0638
0639 ecc_swap_digits(result->x, shared_secret, result->ndigits);
0640
0641
0642 nbytes = min_t(size_t, nbytes, req->dst_len);
0643
0644 copied = sg_copy_from_buffer(req->dst,
0645 sg_nents_for_len(req->dst, nbytes),
0646 shared_secret, nbytes);
0647
0648 if (copied != nbytes)
0649 rc = -EINVAL;
0650
0651 memzero_explicit(shared_secret, sizeof(shared_secret));
0652
0653 exit_free_result:
0654 ecc_free_point(result);
0655
0656 exit_free_pk:
0657 ecc_free_point(pk);
0658
0659 return rc;
0660 }
0661
0662
0663 static int kmb_ecc_do_public_key(struct ocs_ecc_ctx *tctx,
0664 struct kpp_request *req)
0665 {
0666 const struct ecc_curve *curve = tctx->curve;
0667 u64 pubk_buf[KMB_ECC_VLI_MAX_DIGITS * 2];
0668 struct ecc_point *pk;
0669 size_t pubk_len;
0670 size_t copied;
0671 int rc;
0672
0673
0674 pubk_len = 2 * digits_to_bytes(curve->g.ndigits);
0675
0676 pk = ecc_alloc_point(curve->g.ndigits);
0677 if (!pk)
0678 return -ENOMEM;
0679
0680
0681 rc = kmb_ecc_point_mult(tctx->ecc_dev, pk, &curve->g, tctx->private_key,
0682 curve);
0683 if (rc)
0684 goto exit;
0685
0686
0687 if (kmb_ocs_ecc_is_pubkey_valid_full(tctx->ecc_dev, curve, pk)) {
0688 rc = -EAGAIN;
0689 goto exit;
0690 }
0691
0692
0693 ecc_swap_digits(pk->x, pubk_buf, pk->ndigits);
0694 ecc_swap_digits(pk->y, &pubk_buf[pk->ndigits], pk->ndigits);
0695
0696
0697 copied = sg_copy_from_buffer(req->dst,
0698 sg_nents_for_len(req->dst, pubk_len),
0699 pubk_buf, pubk_len);
0700
0701 if (copied != pubk_len)
0702 rc = -EINVAL;
0703
0704 exit:
0705 ecc_free_point(pk);
0706
0707 return rc;
0708 }
0709
0710 static int kmb_ocs_ecc_do_one_request(struct crypto_engine *engine,
0711 void *areq)
0712 {
0713 struct kpp_request *req = container_of(areq, struct kpp_request, base);
0714 struct ocs_ecc_ctx *tctx = kmb_ocs_ecc_tctx(req);
0715 struct ocs_ecc_dev *ecc_dev = tctx->ecc_dev;
0716 int rc;
0717
0718 if (req->src)
0719 rc = kmb_ecc_do_shared_secret(tctx, req);
0720 else
0721 rc = kmb_ecc_do_public_key(tctx, req);
0722
0723 crypto_finalize_kpp_request(ecc_dev->engine, req, rc);
0724
0725 return 0;
0726 }
0727
0728 static int kmb_ocs_ecdh_generate_public_key(struct kpp_request *req)
0729 {
0730 struct ocs_ecc_ctx *tctx = kmb_ocs_ecc_tctx(req);
0731 const struct ecc_curve *curve = tctx->curve;
0732
0733
0734 if (!tctx->curve)
0735 return -EINVAL;
0736
0737
0738 if (!req->dst)
0739 return -EINVAL;
0740
0741
0742 if (req->dst_len < (2 * digits_to_bytes(curve->g.ndigits)))
0743 return -EINVAL;
0744
0745
0746 if (req->src)
0747 return -EINVAL;
0748
0749 return crypto_transfer_kpp_request_to_engine(tctx->ecc_dev->engine,
0750 req);
0751 }
0752
0753 static int kmb_ocs_ecdh_compute_shared_secret(struct kpp_request *req)
0754 {
0755 struct ocs_ecc_ctx *tctx = kmb_ocs_ecc_tctx(req);
0756 const struct ecc_curve *curve = tctx->curve;
0757
0758
0759 if (!tctx->curve)
0760 return -EINVAL;
0761
0762
0763 if (!req->dst)
0764 return -EINVAL;
0765
0766
0767 if (!req->src)
0768 return -EINVAL;
0769
0770
0771
0772
0773
0774 if (req->src_len != 2 * digits_to_bytes(curve->g.ndigits))
0775 return -EINVAL;
0776
0777 return crypto_transfer_kpp_request_to_engine(tctx->ecc_dev->engine,
0778 req);
0779 }
0780
0781 static int kmb_ecc_tctx_init(struct ocs_ecc_ctx *tctx, unsigned int curve_id)
0782 {
0783 memset(tctx, 0, sizeof(*tctx));
0784
0785 tctx->ecc_dev = kmb_ocs_ecc_find_dev(tctx);
0786
0787 if (IS_ERR(tctx->ecc_dev)) {
0788 pr_err("Failed to find the device : %ld\n",
0789 PTR_ERR(tctx->ecc_dev));
0790 return PTR_ERR(tctx->ecc_dev);
0791 }
0792
0793 tctx->curve = ecc_get_curve(curve_id);
0794 if (!tctx->curve)
0795 return -EOPNOTSUPP;
0796
0797 tctx->engine_ctx.op.prepare_request = NULL;
0798 tctx->engine_ctx.op.do_one_request = kmb_ocs_ecc_do_one_request;
0799 tctx->engine_ctx.op.unprepare_request = NULL;
0800
0801 return 0;
0802 }
0803
0804 static int kmb_ocs_ecdh_nist_p256_init_tfm(struct crypto_kpp *tfm)
0805 {
0806 struct ocs_ecc_ctx *tctx = kpp_tfm_ctx(tfm);
0807
0808 return kmb_ecc_tctx_init(tctx, ECC_CURVE_NIST_P256);
0809 }
0810
0811 static int kmb_ocs_ecdh_nist_p384_init_tfm(struct crypto_kpp *tfm)
0812 {
0813 struct ocs_ecc_ctx *tctx = kpp_tfm_ctx(tfm);
0814
0815 return kmb_ecc_tctx_init(tctx, ECC_CURVE_NIST_P384);
0816 }
0817
0818 static void kmb_ocs_ecdh_exit_tfm(struct crypto_kpp *tfm)
0819 {
0820 struct ocs_ecc_ctx *tctx = kpp_tfm_ctx(tfm);
0821
0822 memzero_explicit(tctx->private_key, sizeof(*tctx->private_key));
0823 }
0824
0825 static unsigned int kmb_ocs_ecdh_max_size(struct crypto_kpp *tfm)
0826 {
0827 struct ocs_ecc_ctx *tctx = kpp_tfm_ctx(tfm);
0828
0829
0830 return digits_to_bytes(tctx->curve->g.ndigits) * 2;
0831 }
0832
0833 static struct kpp_alg ocs_ecdh_p256 = {
0834 .set_secret = kmb_ocs_ecdh_set_secret,
0835 .generate_public_key = kmb_ocs_ecdh_generate_public_key,
0836 .compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret,
0837 .init = kmb_ocs_ecdh_nist_p256_init_tfm,
0838 .exit = kmb_ocs_ecdh_exit_tfm,
0839 .max_size = kmb_ocs_ecdh_max_size,
0840 .base = {
0841 .cra_name = "ecdh-nist-p256",
0842 .cra_driver_name = "ecdh-nist-p256-keembay-ocs",
0843 .cra_priority = KMB_OCS_ECC_PRIORITY,
0844 .cra_module = THIS_MODULE,
0845 .cra_ctxsize = sizeof(struct ocs_ecc_ctx),
0846 },
0847 };
0848
0849 static struct kpp_alg ocs_ecdh_p384 = {
0850 .set_secret = kmb_ocs_ecdh_set_secret,
0851 .generate_public_key = kmb_ocs_ecdh_generate_public_key,
0852 .compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret,
0853 .init = kmb_ocs_ecdh_nist_p384_init_tfm,
0854 .exit = kmb_ocs_ecdh_exit_tfm,
0855 .max_size = kmb_ocs_ecdh_max_size,
0856 .base = {
0857 .cra_name = "ecdh-nist-p384",
0858 .cra_driver_name = "ecdh-nist-p384-keembay-ocs",
0859 .cra_priority = KMB_OCS_ECC_PRIORITY,
0860 .cra_module = THIS_MODULE,
0861 .cra_ctxsize = sizeof(struct ocs_ecc_ctx),
0862 },
0863 };
0864
0865 static irqreturn_t ocs_ecc_irq_handler(int irq, void *dev_id)
0866 {
0867 struct ocs_ecc_dev *ecc_dev = dev_id;
0868 u32 status;
0869
0870
0871
0872
0873
0874 status = ioread32(ecc_dev->base_reg + HW_OFFS_OCS_ECC_ISR);
0875 iowrite32(status, ecc_dev->base_reg + HW_OFFS_OCS_ECC_ISR);
0876
0877 if (!(status & HW_OCS_ECC_ISR_INT_STATUS_DONE))
0878 return IRQ_NONE;
0879
0880 complete(&ecc_dev->irq_done);
0881
0882 return IRQ_HANDLED;
0883 }
0884
0885 static int kmb_ocs_ecc_probe(struct platform_device *pdev)
0886 {
0887 struct device *dev = &pdev->dev;
0888 struct ocs_ecc_dev *ecc_dev;
0889 int rc;
0890
0891 ecc_dev = devm_kzalloc(dev, sizeof(*ecc_dev), GFP_KERNEL);
0892 if (!ecc_dev)
0893 return -ENOMEM;
0894
0895 ecc_dev->dev = dev;
0896
0897 platform_set_drvdata(pdev, ecc_dev);
0898
0899 INIT_LIST_HEAD(&ecc_dev->list);
0900 init_completion(&ecc_dev->irq_done);
0901
0902
0903 ecc_dev->base_reg = devm_platform_ioremap_resource(pdev, 0);
0904 if (IS_ERR(ecc_dev->base_reg)) {
0905 dev_err(dev, "Failed to get base address\n");
0906 rc = PTR_ERR(ecc_dev->base_reg);
0907 goto list_del;
0908 }
0909
0910
0911 ecc_dev->irq = platform_get_irq(pdev, 0);
0912 if (ecc_dev->irq < 0) {
0913 rc = ecc_dev->irq;
0914 goto list_del;
0915 }
0916
0917 rc = devm_request_threaded_irq(dev, ecc_dev->irq, ocs_ecc_irq_handler,
0918 NULL, 0, "keembay-ocs-ecc", ecc_dev);
0919 if (rc < 0) {
0920 dev_err(dev, "Could not request IRQ\n");
0921 goto list_del;
0922 }
0923
0924
0925 spin_lock(&ocs_ecc.lock);
0926 list_add_tail(&ecc_dev->list, &ocs_ecc.dev_list);
0927 spin_unlock(&ocs_ecc.lock);
0928
0929
0930 ecc_dev->engine = crypto_engine_alloc_init(dev, 1);
0931 if (!ecc_dev->engine) {
0932 dev_err(dev, "Could not allocate crypto engine\n");
0933 rc = -ENOMEM;
0934 goto list_del;
0935 }
0936
0937 rc = crypto_engine_start(ecc_dev->engine);
0938 if (rc) {
0939 dev_err(dev, "Could not start crypto engine\n");
0940 goto cleanup;
0941 }
0942
0943
0944 rc = crypto_register_kpp(&ocs_ecdh_p256);
0945 if (rc) {
0946 dev_err(dev,
0947 "Could not register OCS algorithms with Crypto API\n");
0948 goto cleanup;
0949 }
0950
0951 rc = crypto_register_kpp(&ocs_ecdh_p384);
0952 if (rc) {
0953 dev_err(dev,
0954 "Could not register OCS algorithms with Crypto API\n");
0955 goto ocs_ecdh_p384_error;
0956 }
0957
0958 return 0;
0959
0960 ocs_ecdh_p384_error:
0961 crypto_unregister_kpp(&ocs_ecdh_p256);
0962
0963 cleanup:
0964 crypto_engine_exit(ecc_dev->engine);
0965
0966 list_del:
0967 spin_lock(&ocs_ecc.lock);
0968 list_del(&ecc_dev->list);
0969 spin_unlock(&ocs_ecc.lock);
0970
0971 return rc;
0972 }
0973
0974 static int kmb_ocs_ecc_remove(struct platform_device *pdev)
0975 {
0976 struct ocs_ecc_dev *ecc_dev;
0977
0978 ecc_dev = platform_get_drvdata(pdev);
0979
0980 crypto_unregister_kpp(&ocs_ecdh_p384);
0981 crypto_unregister_kpp(&ocs_ecdh_p256);
0982
0983 spin_lock(&ocs_ecc.lock);
0984 list_del(&ecc_dev->list);
0985 spin_unlock(&ocs_ecc.lock);
0986
0987 crypto_engine_exit(ecc_dev->engine);
0988
0989 return 0;
0990 }
0991
0992
0993 static const struct of_device_id kmb_ocs_ecc_of_match[] = {
0994 {
0995 .compatible = "intel,keembay-ocs-ecc",
0996 },
0997 {}
0998 };
0999
1000
1001 static struct platform_driver kmb_ocs_ecc_driver = {
1002 .probe = kmb_ocs_ecc_probe,
1003 .remove = kmb_ocs_ecc_remove,
1004 .driver = {
1005 .name = DRV_NAME,
1006 .of_match_table = kmb_ocs_ecc_of_match,
1007 },
1008 };
1009 module_platform_driver(kmb_ocs_ecc_driver);
1010
1011 MODULE_LICENSE("GPL");
1012 MODULE_DESCRIPTION("Intel Keem Bay OCS ECC Driver");
1013 MODULE_ALIAS_CRYPTO("ecdh-nist-p256");
1014 MODULE_ALIAS_CRYPTO("ecdh-nist-p384");
1015 MODULE_ALIAS_CRYPTO("ecdh-nist-p256-keembay-ocs");
1016 MODULE_ALIAS_CRYPTO("ecdh-nist-p384-keembay-ocs");