Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Intel Keem Bay OCS ECC Crypto Driver.
0004  *
0005  * Copyright (C) 2019-2021 Intel Corporation
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 /* ECC Instruction : for ECC_COMMAND */
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  * struct ocs_ecc_dev - ECC device context
0080  * @list: List of device contexts
0081  * @dev: OCS ECC device
0082  * @base_reg: IO base address of OCS ECC
0083  * @engine: Crypto engine for the device
0084  * @irq_done: IRQ done completion.
0085  * @irq: IRQ number
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  * struct ocs_ecc_ctx - Transformation context.
0098  * @engine_ctx:  Crypto engine ctx.
0099  * @ecc_dev:     The ECC driver associated with this context.
0100  * @curve:   The elliptic curve used by this transformation.
0101  * @private_key: The private key.
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 /* Driver data. */
0111 struct ocs_ecc_drv {
0112     struct list_head dev_list;
0113     spinlock_t lock;    /* Protects dev_list. */
0114 };
0115 
0116 /* Global variable holding the list of OCS ECC devices (only one expected). */
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 /* Get OCS ECC tfm context from kpp_request. */
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 /* Converts number of digits to number of bytes. */
0129 static inline unsigned int digits_to_bytes(unsigned int n)
0130 {
0131     return n << ECC_DIGITS_TO_BYTES_SHIFT;
0132 }
0133 
0134 /*
0135  * Wait for ECC idle i.e when an operation (other than write operations)
0136  * is done.
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 /* Direct write of u32 buffer to ECC engine with associated instruction. */
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     /* MMIO Write src uint32 to dst. */
0164     memcpy_toio(dev->base_reg + HW_OFFS_OCS_ECC_DATA_IN, data_in,
0165             data_size);
0166 }
0167 
0168 /* Start OCS ECC operation and wait for its completion. */
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  * ocs_ecc_read_cx_out() - Read the CX data output buffer.
0182  * @dev:    The OCS ECC device to read from.
0183  * @cx_out: The buffer where to store the CX value. Must be at least
0184  *      @byte_count byte long.
0185  * @byte_count: The amount of data to read.
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  * ocs_ecc_read_cy_out() - Read the CX data output buffer.
0196  * @dev:    The OCS ECC device to read from.
0197  * @cy_out: The buffer where to store the CY value. Must be at least
0198  *      @byte_count byte long.
0199  * @byte_count: The amount of data to read.
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     /* Only a single OCS device available. */
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 /* Do point multiplication using OCS ECC HW. */
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]; /* Use the maximum data size. */
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     /* Generate random nbytes for Simple and Differential SCA protection. */
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     /* Wait engine to be idle before starting new operation. */
0248     rc = ocs_ecc_wait_idle(ecc_dev);
0249     if (rc)
0250         return rc;
0251 
0252     /* Send ecc_start pulse as well as indicating operation size. */
0253     ocs_ecc_cmd_start(ecc_dev, op_size);
0254 
0255     /* Write ax param; Base point (Gx). */
0256     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AX,
0257                    point->x, nbytes);
0258 
0259     /* Write ay param; Base point (Gy). */
0260     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AY,
0261                    point->y, nbytes);
0262 
0263     /*
0264      * Write the private key into DATA_IN reg.
0265      *
0266      * Since DATA_IN register is used to write different values during the
0267      * computation private Key value is overwritten with
0268      * side-channel-resistance value.
0269      */
0270     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_BX_D,
0271                    scalar, nbytes);
0272 
0273     /* Write operand by/l. */
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     /* Write p = curve prime(GF modulus). */
0279     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_P,
0280                    curve->p, nbytes);
0281 
0282     /* Write a = curve coefficient. */
0283     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_A,
0284                    curve->a, nbytes);
0285 
0286     /* Make hardware perform the multiplication. */
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     /* Read result. */
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  * kmb_ecc_do_scalar_op() - Perform Scalar operation using OCS ECC HW.
0300  * @ecc_dev:    The OCS ECC device to use.
0301  * @scalar_out: Where to store the output scalar.
0302  * @scalar_a:   Input scalar operand 'a'.
0303  * @scalar_b:   Input scalar operand 'b'
0304  * @curve:  The curve on which the operation is performed.
0305  * @ndigits:    The size of the operands (in digits).
0306  * @inst:   The operation to perform (as an OCS ECC instruction).
0307  *
0308  * Return:  0 on success, negative error code otherwise.
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     /* Wait engine to be idle before starting new operation. */
0321     rc = ocs_ecc_wait_idle(ecc_dev);
0322     if (rc)
0323         return rc;
0324 
0325     /* Send ecc_start pulse as well as indicating operation size. */
0326     ocs_ecc_cmd_start(ecc_dev, op_size);
0327 
0328     /* Write ax param (Base point (Gx).*/
0329     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AX,
0330                    scalar_a, nbytes);
0331 
0332     /* Write ay param Base point (Gy).*/
0333     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_AY,
0334                    scalar_b, nbytes);
0335 
0336     /* Write p = curve prime(GF modulus).*/
0337     ocs_ecc_write_cmd_and_data(ecc_dev, op_size, OCS_ECC_INST_WRITE_P,
0338                    curve->p, nbytes);
0339 
0340     /* Give instruction A.B or A+B to ECC engine. */
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 /* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
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     /* Check 1: Verify key is not the zero point. */
0367     if (ecc_point_is_zero(pk))
0368         return -EINVAL;
0369 
0370     /* Check 2: Verify key is in the range [0, p-1]. */
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     /* Check 3: Verify that y^2 == (x^3 + a·x + b) mod p */
0378 
0379      /* y^2 */
0380     /* Compute y^2 -> store in yy */
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     /* x^3 */
0387     /* Assigning w = 3, used for calculating x^3. */
0388     w[0] = POW_CUBE;
0389     /* Load the next stage.*/
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     /* Do a*x -> store in w. */
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     /* Do ax + b == w + b; store in w. */
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     /* x^3 + ax + b == x^3 + w -> store in w. */
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     /* Compare y^2 == x^3 + a·x + b. */
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 /* SP800-56A section 5.6.2.3.3 full verification */
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     /* Checks 1 through 3 */
0437     rc = kmb_ocs_ecc_is_pubkey_valid_partial(ecc_dev, curve, pk);
0438     if (rc)
0439         return rc;
0440 
0441     /* Check 4: Verify that nQ is the zero point. */
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     /* Make sure the private key is in the range [2, n-3]. */
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  * ECC private keys are generated using the method of extra random bits,
0486  * equivalent to that described in FIPS 186-4, Appendix B.4.1.
0487  *
0488  * d = (c mod(n–1)) + 1    where c is a string of random bits, 64 bits longer
0489  *                         than requested
0490  * 0 <= c mod(n-1) <= n-2  and implies that
0491  * 1 <= d <= n-1
0492  *
0493  * This method generates a private key uniformly distributed in the range
0494  * [1, n-1].
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     /* Check that N is included in Table 1 of FIPS 186-4, section 6.1.1 */
0506     if (nbits < 160 || curve->g.ndigits > ARRAY_SIZE(priv))
0507         return -EINVAL;
0508 
0509     /*
0510      * FIPS 186-4 recommends that the private key should be obtained from a
0511      * RBG with a security strength equal to or greater than the security
0512      * strength associated with N.
0513      *
0514      * The maximum security strength identified by NIST SP800-57pt1r4 for
0515      * ECC is 256 (N >= 512).
0516      *
0517      * This condition is met by the default RNG because it selects a favored
0518      * DRBG with a security strength of 256.
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, &params);
0548     if (rc)
0549         goto cleanup;
0550 
0551     /* Ensure key size is not bigger then expected. */
0552     if (params.key_size > digits_to_bytes(tctx->curve->g.ndigits)) {
0553         rc = -EINVAL;
0554         goto cleanup;
0555     }
0556 
0557     /* Auto-generate private key is not provided. */
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(&params, sizeof(params));
0572 
0573     if (rc)
0574         tctx->curve = NULL;
0575 
0576     return rc;
0577 }
0578 
0579 /* Compute shared secret. */
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     /* Public key is a point, thus it has two coordinates */
0594     pubk_len = 2 * nbytes;
0595 
0596     /* Copy public key from SG list to pubk_buf. */
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     /* Allocate and initialize public key point. */
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      * Check the public key for following
0613      * Check 1: Verify key is not the zero point.
0614      * Check 2: Verify key is in the range [1, p-1].
0615      * Check 3: Verify that y^2 == (x^3 + a·x + b) mod p
0616      */
0617     rc = kmb_ocs_ecc_is_pubkey_valid_partial(ecc_dev, curve, pk);
0618     if (rc)
0619         goto exit_free_pk;
0620 
0621     /* Allocate point for storing computed shared secret. */
0622     result = ecc_alloc_point(pk->ndigits);
0623     if (!result) {
0624         rc = -ENOMEM;
0625         goto exit_free_pk;
0626     }
0627 
0628     /* Calculate the shared secret.*/
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     /* Copy shared secret from point to buffer. */
0639     ecc_swap_digits(result->x, shared_secret, result->ndigits);
0640 
0641     /* Request might ask for less bytes than what we have. */
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 /* Compute public key. */
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     /* Public key is a point, so it has double the digits. */
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     /* Public Key(pk) = priv * G. */
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     /* SP800-56A rev 3 5.6.2.1.3 key check */
0687     if (kmb_ocs_ecc_is_pubkey_valid_full(tctx->ecc_dev, curve, pk)) {
0688         rc = -EAGAIN;
0689         goto exit;
0690     }
0691 
0692     /* Copy public key from point to buffer. */
0693     ecc_swap_digits(pk->x, pubk_buf, pk->ndigits);
0694     ecc_swap_digits(pk->y, &pubk_buf[pk->ndigits], pk->ndigits);
0695 
0696     /* Copy public key to req->dst. */
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     /* Ensure kmb_ocs_ecdh_set_secret() has been successfully called. */
0734     if (!tctx->curve)
0735         return -EINVAL;
0736 
0737     /* Ensure dst is present. */
0738     if (!req->dst)
0739         return -EINVAL;
0740 
0741     /* Check the request dst is big enough to hold the public key. */
0742     if (req->dst_len < (2 * digits_to_bytes(curve->g.ndigits)))
0743         return -EINVAL;
0744 
0745     /* 'src' is not supposed to be present when generate pubk is called. */
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     /* Ensure kmb_ocs_ecdh_set_secret() has been successfully called. */
0759     if (!tctx->curve)
0760         return -EINVAL;
0761 
0762     /* Ensure dst is present. */
0763     if (!req->dst)
0764         return -EINVAL;
0765 
0766     /* Ensure src is present. */
0767     if (!req->src)
0768         return -EINVAL;
0769 
0770     /*
0771      * req->src is expected to the (other-side) public key, so its length
0772      * must be 2 * coordinate size (in bytes).
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     /* Public key is made of two coordinates, so double the digits. */
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      * Read the status register and write it back to clear the
0872      * DONE_INT_STATUS bit.
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     /* Get base register address. */
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     /* Get and request IRQ */
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     /* Add device to the list of OCS ECC devices. */
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     /* Initialize crypto engine. */
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     /* Register the KPP algo. */
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 /* Device tree driver match. */
0993 static const struct of_device_id kmb_ocs_ecc_of_match[] = {
0994     {
0995         .compatible = "intel,keembay-ocs-ecc",
0996     },
0997     {}
0998 };
0999 
1000 /* The OCS driver is a platform device. */
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");