2020-11-18 03:50:39

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 0/5] crypto: hisilicon/hpre - add something for Kunpeng 930

Add algorithms(ECDH and CURVE25519) in Kunpeng 930.

v2 -> v3:
- patch #1: add a 'Signed-off-by' from its author
- patch #5: fix sparse warnings
- patch #5: add 'CRYPTO_LIB_CURVE25519_GENERIC' in 'Kconfig'

v1 -> v2:
- patch #5: delete 'curve25519_null_point'

Hui Tang (1):
crypto: hisilicon/hpre - add initial settings adapt to 'Kunpeng 930'

Meng Yu (4):
crypto: hisilicon/hpre - add version adapt to new algorithms
crypto: hisilicon/hpre - add algorithm type
crypto: hisilicon/hpre - add 'ECDH' algorithm
crypto: hisilicon/hpre - add 'CURVE25519' algorithm

drivers/crypto/hisilicon/Kconfig | 1 +
drivers/crypto/hisilicon/hpre/hpre.h | 25 +-
drivers/crypto/hisilicon/hpre/hpre_crypto.c | 1194 ++++++++++++++++++++++++++-
drivers/crypto/hisilicon/hpre/hpre_main.c | 105 ++-
drivers/crypto/hisilicon/qm.c | 4 +-
drivers/crypto/hisilicon/qm.h | 4 +-
drivers/crypto/hisilicon/sec2/sec.h | 4 +-
drivers/crypto/hisilicon/sec2/sec_crypto.c | 4 +-
drivers/crypto/hisilicon/sec2/sec_crypto.h | 4 +-
drivers/crypto/hisilicon/zip/zip.h | 4 +-
drivers/crypto/hisilicon/zip/zip_crypto.c | 4 +-
11 files changed, 1289 insertions(+), 64 deletions(-)

--
2.8.1


2020-11-18 03:50:39

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 4/5] crypto: hisilicon/hpre - add 'ECDH' algorithm

Enable 'ECDH' algorithm in Kunpeng 930.

Signed-off-by: Meng Yu <[email protected]>
Reviewed-by: Zaibo Xu <[email protected]>
---
drivers/crypto/hisilicon/hpre/hpre.h | 2 +-
drivers/crypto/hisilicon/hpre/hpre_crypto.c | 802 +++++++++++++++++++++++++++-
drivers/crypto/hisilicon/hpre/hpre_main.c | 1 +
3 files changed, 800 insertions(+), 5 deletions(-)

diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index 02193e1..50e6b2e 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -83,6 +83,7 @@ enum hpre_alg_type {
HPRE_ALG_KG_CRT = 0x3,
HPRE_ALG_DH_G2 = 0x4,
HPRE_ALG_DH = 0x5,
+ HPRE_ALG_ECC_MUL = 0xD,
};

struct hpre_sqe {
@@ -104,5 +105,4 @@ struct hisi_qp *hpre_create_qp(u8 type);
int hpre_algs_register(struct hisi_qm *qm);
void hpre_algs_unregister(struct hisi_qm *qm);

-
#endif
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index 712bea9..b7814ce 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -2,6 +2,7 @@
/* Copyright (c) 2019 HiSilicon Limited. */
#include <crypto/akcipher.h>
#include <crypto/dh.h>
+#include <crypto/ecdh.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/kpp.h>
#include <crypto/internal/rsa.h>
@@ -36,6 +37,342 @@ struct hpre_ctx;
#define HPRE_DFX_SEC_TO_US 1000000
#define HPRE_DFX_US_TO_NS 1000

+/* HPRE support 7 curves (include curve P192 and P256 in ecdh.h) */
+#define HPRE_ECC_CURVE_NIST_P128 0X0003
+#define HPRE_ECC_CURVE_NIST_P320 0X0004
+#define HPRE_ECC_CURVE_NIST_P384 0X0005
+#define HPRE_ECC_CURVE_NIST_P521 0X0006
+#define HPRE_ECC_CURVE_NIST_P224 0X0007
+
+/* size in bytes of the n prime */
+#define HPRE_ECC_NIST_P128_N_SIZE 16
+#define HPRE_ECC_NIST_P192_N_SIZE 24
+#define HPRE_ECC_NIST_P224_N_SIZE 28
+#define HPRE_ECC_NIST_P256_N_SIZE 32
+#define HPRE_ECC_NIST_P320_N_SIZE 40
+#define HPRE_ECC_NIST_P384_N_SIZE 48
+#define HPRE_ECC_NIST_P521_N_SIZE 66
+
+/* size in bytes */
+#define HPRE_ECC_HW256_KSZ_B 32
+#define HPRE_ECC_HW384_KSZ_B 48
+#define HPRE_ECC_HW576_KSZ_B 72
+
+#define HPRE_ECDH_MAX_SZ HPRE_ECC_HW576_KSZ_B
+
+struct curve_param_desc {
+ __u32 id;
+ const unsigned char *p;
+ const unsigned char *a;
+ const unsigned char *b;
+ const unsigned char *gx;
+ const unsigned char *gy;
+ const unsigned char *n;
+};
+
+/* ECC CURVE PARAMS */
+/* 128 bits */
+static const unsigned char ecdh_p128_p[] = {
+ 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const unsigned char ecdh_p128_a[] = {
+ 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFC
+};
+static const unsigned char ecdh_p128_b[] = {
+ 0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C,
+ 0x2C, 0xEE, 0x5E, 0xD3
+};
+static const unsigned char ecdh_p128_x[] = {
+ 0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C,
+ 0xA5, 0x2C, 0x5B, 0x86
+};
+static const unsigned char ecdh_p128_y[] = {
+ 0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2, 0x92,
+ 0xdd, 0xed, 0x7a, 0x83
+};
+static const unsigned char ecdh_p128_n[] = {
+ 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B,
+ 0x90, 0x38, 0xA1, 0x15
+};
+
+/* 192 bits */
+static const unsigned char ecdh_p192_p[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const unsigned char ecdh_p192_a[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+static const unsigned char ecdh_p192_b[] = {
+ 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB,
+ 0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1
+};
+static const unsigned char ecdh_p192_x[] = {
+ 0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB,
+ 0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12
+};
+static const unsigned char ecdh_p192_y[] = {
+ 0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed,
+ 0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11
+};
+static const unsigned char ecdh_p192_n[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31
+};
+
+/* 224 bits */
+static const unsigned char ecdh_p224_p[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01
+};
+static const unsigned char ecdh_p224_a[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE
+};
+static const unsigned char ecdh_p224_b[] = {
+ 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
+ 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
+ 0x23, 0x55, 0xFF, 0xB4
+};
+static const unsigned char ecdh_p224_x[] = {
+ 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
+ 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
+ 0x11, 0x5C, 0x1D, 0x21
+};
+static const unsigned char ecdh_p224_y[] = {
+ 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
+ 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
+ 0x85, 0x00, 0x7e, 0x34
+};
+static const unsigned char ecdh_p224_n[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
+ 0x5C, 0x5C, 0x2A, 0x3D
+};
+
+/* 256 bits */
+static const unsigned char ecdh_p256_p[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const unsigned char ecdh_p256_a[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+static const unsigned char ecdh_p256_b[] = {
+ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
+ 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
+ 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B
+};
+static const unsigned char ecdh_p256_x[] = {
+ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96
+};
+static const unsigned char ecdh_p256_y[] = {
+ 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
+ 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+ 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
+};
+static const unsigned char ecdh_p256_n[] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
+};
+
+/* 320 bits */
+static const unsigned char ecdh_p320_p[] = {
+ 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,
+ 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF,
+ 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12, 0xB1,
+ 0xF1, 0xB3, 0x2E, 0x27
+};
+static const unsigned char ecdh_p320_a[] = {
+ 0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4,
+ 0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA,
+ 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3, 0x75, 0xA9,
+ 0x7D, 0x86, 0x0E, 0xB4
+};
+static const unsigned char ecdh_p320_b[] = {
+ 0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86,
+ 0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A,
+ 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4, 0xAC,
+ 0x8F, 0xB1, 0xF1, 0xA6
+};
+static const unsigned char ecdh_p320_x[] = {
+ 0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4,
+ 0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6,
+ 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF, 0x8D, 0x0D,
+ 0x39, 0xE2, 0x06, 0x11
+};
+static const unsigned char ecdh_p320_y[] = {
+ 0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24,
+ 0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA,
+ 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52, 0x45, 0xD1,
+ 0x69, 0x2E, 0x8E, 0xE1
+};
+static const unsigned char ecdh_p320_n[] = {
+ 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,
+ 0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3,
+ 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55, 0x5B,
+ 0x44, 0xC5, 0x93, 0x11
+};
+
+/* 384 bits */
+static const unsigned char ecdh_p384_p[] = {
+ 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
+ 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4,
+ 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7, 0x29,
+ 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53
+};
+static const unsigned char ecdh_p384_a[] = {
+ 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A,
+ 0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87,
+ 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81, 0x4A,
+ 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26
+};
+static const unsigned char ecdh_p384_b[] = {
+ 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54,
+ 0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6,
+ 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39, 0x02,
+ 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11
+};
+static const unsigned char ecdh_p384_x[] = {
+ 0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81,
+ 0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3,
+ 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0, 0x34,
+ 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E
+};
+static const unsigned char ecdh_p384_y[] = {
+ 0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E,
+ 0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64,
+ 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46, 0x21,
+ 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15
+};
+static const unsigned char ecdh_p384_n[] = {
+ 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E,
+ 0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3,
+ 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6, 0xAF,
+ 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65
+};
+
+/* 521 bits */
+static const unsigned char ecdh_p521_p[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+static const unsigned char ecdh_p521_a[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+static const unsigned char ecdh_p521_b[] = {
+ 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
+ 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
+ 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
+ 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
+ 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
+ 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00
+};
+static const unsigned char ecdh_p521_x[] = {
+ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+ 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+ 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+ 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+ 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+ 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66
+};
+static const unsigned char ecdh_p521_y[] = {
+ 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
+ 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+ 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
+ 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+ 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+ 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50
+};
+static const unsigned char ecdh_p521_n[] = {
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
+ 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+ 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
+ 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
+};
+
+static const struct curve_param_desc ecdh_curve_list[] = {
+ {
+ .id = ECC_CURVE_NIST_P192,
+ .p = ecdh_p192_p,
+ .a = ecdh_p192_a,
+ .b = ecdh_p192_b,
+ .gx = ecdh_p192_x,
+ .gy = ecdh_p192_y,
+ .n = ecdh_p192_n,
+ }, {
+ .id = ECC_CURVE_NIST_P256,
+ .p = ecdh_p256_p,
+ .a = ecdh_p256_a,
+ .b = ecdh_p256_b,
+ .gx = ecdh_p256_x,
+ .gy = ecdh_p256_y,
+ .n = ecdh_p256_n,
+ }, {
+ .id = HPRE_ECC_CURVE_NIST_P128,
+ .p = ecdh_p128_p,
+ .a = ecdh_p128_a,
+ .b = ecdh_p128_b,
+ .gx = ecdh_p128_x,
+ .gy = ecdh_p128_y,
+ .n = ecdh_p128_n,
+ }, {
+ .id = HPRE_ECC_CURVE_NIST_P320,
+ .p = ecdh_p320_p,
+ .a = ecdh_p320_a,
+ .b = ecdh_p320_b,
+ .gx = ecdh_p320_x,
+ .gy = ecdh_p320_y,
+ .n = ecdh_p320_n,
+ }, {
+ .id = HPRE_ECC_CURVE_NIST_P384,
+ .p = ecdh_p384_p,
+ .a = ecdh_p384_a,
+ .b = ecdh_p384_b,
+ .gx = ecdh_p384_x,
+ .gy = ecdh_p384_y,
+ .n = ecdh_p384_n,
+ }, {
+ .id = HPRE_ECC_CURVE_NIST_P521,
+ .p = ecdh_p521_p,
+ .a = ecdh_p521_a,
+ .b = ecdh_p521_b,
+ .gx = ecdh_p521_x,
+ .gy = ecdh_p521_y,
+ .n = ecdh_p521_n,
+ }, {
+ .id = HPRE_ECC_CURVE_NIST_P224,
+ .p = ecdh_p224_p,
+ .a = ecdh_p224_a,
+ .b = ecdh_p224_b,
+ .gx = ecdh_p224_x,
+ .gy = ecdh_p224_y,
+ .n = ecdh_p224_n,
+ }
+};
+
typedef void (*hpre_cb)(struct hpre_ctx *ctx, void *sqe);

struct hpre_rsa_ctx {
@@ -61,14 +398,25 @@ struct hpre_dh_ctx {
* else if base if the counterpart public key we
* compute the shared secret
* ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
+ * low address: d--->n, please refer to Hisilicon HPRE UM
*/
- char *xa_p; /* low address: d--->n, please refer to Hisilicon HPRE UM */
+ char *xa_p;
dma_addr_t dma_xa_p;

char *g; /* m */
dma_addr_t dma_g;
};

+struct hpre_ecdh_ctx {
+ /* low address: p->a->k->b */
+ unsigned char *p;
+ dma_addr_t dma_p;
+
+ /* low address: x->y */
+ unsigned char *g;
+ dma_addr_t dma_g;
+};
+
struct hpre_ctx {
struct hisi_qp *qp;
struct hpre_asym_request **req_list;
@@ -80,7 +428,10 @@ struct hpre_ctx {
union {
struct hpre_rsa_ctx rsa;
struct hpre_dh_ctx dh;
+ struct hpre_ecdh_ctx ecdh;
};
+ /* for ecc algorithms */
+ unsigned int curve_id;
};

struct hpre_asym_request {
@@ -91,6 +442,7 @@ struct hpre_asym_request {
union {
struct akcipher_request *rsa;
struct kpp_request *dh;
+ struct kpp_request *ecdh;
} areq;
int err;
int req_id;
@@ -1115,6 +1467,416 @@ static void hpre_rsa_exit_tfm(struct crypto_akcipher *tfm)
crypto_free_akcipher(ctx->rsa.soft_tfm);
}

+static void hpre_ecc_clear_ctx(struct hpre_ctx *ctx, bool is_clear_all,
+ bool is_ecdh)
+{
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int sz = ctx->key_sz;
+ unsigned int shift = sz << 1;
+
+ if (is_clear_all)
+ hisi_qm_stop_qp(ctx->qp);
+
+ if (is_ecdh && ctx->ecdh.p) {
+ /* ecdh: p->a->k->b */
+ memzero_explicit(ctx->ecdh.p + shift, sz);
+ dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx->ecdh.dma_p);
+ ctx->ecdh.p = NULL;
+ }
+
+ ctx->curve_id = 0;
+ hpre_ctx_clear(ctx, is_clear_all);
+}
+
+/*
+ * only the bits of 128/192/224/256/320/384/521 are supported by HPRE,
+ * and convert the bits like:
+ * bits<=256, bits=256; 256<bits<=384, bits=384; 384<bits<=576, bits=576;
+ * If the parameter bit width is insufficient, then we fill in the
+ * high-order zeros by soft, so TASK_LENGTH1 is 0x3/0x5/0x8;
+ */
+static unsigned int hpre_ecdh_supported_curve(unsigned int curve_id)
+{
+ switch (curve_id) {
+ case ECC_CURVE_NIST_P192:
+ case ECC_CURVE_NIST_P256:
+ case HPRE_ECC_CURVE_NIST_P128:
+ case HPRE_ECC_CURVE_NIST_P224:
+ return HPRE_ECC_HW256_KSZ_B;
+ case HPRE_ECC_CURVE_NIST_P320:
+ case HPRE_ECC_CURVE_NIST_P384:
+ return HPRE_ECC_HW384_KSZ_B;
+ case HPRE_ECC_CURVE_NIST_P521:
+ return HPRE_ECC_HW576_KSZ_B;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct curve_param_desc *ecdh_get_curve_param(__u32 curve_id)
+{
+ if (curve_id >= 1 && curve_id <= ARRAY_SIZE(ecdh_curve_list))
+ return &ecdh_curve_list[curve_id - 1];
+
+ return NULL;
+}
+
+static int hpre_ecdh_fill_curve(struct hpre_ctx *ctx, struct ecdh *params,
+ unsigned int cur_sz)
+{
+ unsigned int shifta = ctx->key_sz << 1;
+ unsigned int shiftb = ctx->key_sz << 2;
+ void *p = ctx->ecdh.p + ctx->key_sz - cur_sz;
+ void *a = ctx->ecdh.p + shifta - cur_sz;
+ void *b = ctx->ecdh.p + shiftb - cur_sz;
+ void *x = ctx->ecdh.g + ctx->key_sz - cur_sz;
+ void *y = ctx->ecdh.g + shifta - cur_sz;
+ const struct curve_param_desc *curve;
+ char *n;
+
+ n = kzalloc(ctx->key_sz, GFP_KERNEL);
+ if (!n)
+ return -ENOMEM;
+
+ curve = ecdh_get_curve_param(params->curve_id);
+ if (!curve)
+ goto free;
+
+ memcpy(p, curve->p, cur_sz);
+ memcpy(a, curve->a, cur_sz);
+ memcpy(b, curve->b, cur_sz);
+ memcpy(x, curve->gx, cur_sz);
+ memcpy(y, curve->gy, cur_sz);
+ memcpy(n, curve->n, cur_sz);
+
+ if (params->key_size == cur_sz && strcmp(params->key, n) >= 0)
+ goto free;
+
+ kfree(n);
+ return 0;
+
+free:
+ kfree(n);
+ return -EINVAL;
+}
+
+static unsigned int hpre_ecdh_get_curvesz(unsigned short id)
+{
+ switch (id) {
+ case ECC_CURVE_NIST_P192:
+ return HPRE_ECC_NIST_P192_N_SIZE;
+ case ECC_CURVE_NIST_P256:
+ return HPRE_ECC_NIST_P256_N_SIZE;
+ case HPRE_ECC_CURVE_NIST_P128:
+ return HPRE_ECC_NIST_P128_N_SIZE;
+ case HPRE_ECC_CURVE_NIST_P224:
+ return HPRE_ECC_NIST_P224_N_SIZE;
+ case HPRE_ECC_CURVE_NIST_P320:
+ return HPRE_ECC_NIST_P320_N_SIZE;
+ case HPRE_ECC_CURVE_NIST_P384:
+ return HPRE_ECC_NIST_P384_N_SIZE;
+ case HPRE_ECC_CURVE_NIST_P521:
+ return HPRE_ECC_NIST_P521_N_SIZE;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int hpre_ecdh_set_param(struct hpre_ctx *ctx, struct ecdh *params)
+{
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int sz, shift, curve_sz;
+ int ret;
+
+ ctx->key_sz = hpre_ecdh_supported_curve(params->curve_id);
+ if (!ctx->key_sz)
+ return -EINVAL;
+
+ curve_sz = hpre_ecdh_get_curvesz(params->curve_id);
+ if (!curve_sz || params->key_size > curve_sz)
+ return -EINVAL;
+
+ sz = ctx->key_sz;
+ ctx->curve_id = params->curve_id;
+
+ if (!ctx->ecdh.p) {
+ ctx->ecdh.p = dma_alloc_coherent(dev, sz << 3, &ctx->ecdh.dma_p,
+ GFP_KERNEL);
+ if (!ctx->ecdh.p)
+ return -ENOMEM;
+ }
+
+ shift = sz << 2;
+ ctx->ecdh.g = ctx->ecdh.p + shift;
+ ctx->ecdh.dma_g = ctx->ecdh.dma_p + shift;
+
+ ret = hpre_ecdh_fill_curve(ctx, params, curve_sz);
+ if (ret) {
+ dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx->ecdh.dma_p);
+ dev_err(dev, "failed to fill curve_param, ret = %d!\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static bool hpre_key_is_valid(char *key, unsigned short key_sz)
+{
+ int i;
+
+ for (i = 0; i < key_sz; i++)
+ if (key[i])
+ return true;
+
+ return false;
+}
+
+static int hpre_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
+ unsigned int len)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int sz, sz_shift;
+ struct ecdh params;
+ int ret;
+
+ if (crypto_ecdh_decode_key(buf, len, &params) < 0) {
+ dev_err(dev, "failed to decode ecdh key!\n");
+ return -EINVAL;
+ }
+
+ if (!hpre_key_is_valid(params.key, params.key_size)) {
+ dev_err(dev, "Invalid hpre key!\n");
+ return -EINVAL;
+ }
+
+ hpre_ecc_clear_ctx(ctx, false, true);
+
+ ret = hpre_ecdh_set_param(ctx, &params);
+ if (ret < 0) {
+ dev_err(dev, "failed to set hpre param, ret = %d!\n", ret);
+ goto err_clear_ctx;
+ }
+
+ sz = ctx->key_sz;
+ sz_shift = (sz << 1) + sz - params.key_size;
+ memcpy(ctx->ecdh.p + sz_shift, params.key, params.key_size);
+ return 0;
+
+err_clear_ctx:
+ hpre_ecc_clear_ctx(ctx, false, true);
+ return ret;
+}
+
+static void hpre_ecdh_hw_data_clr_all(struct hpre_ctx *ctx,
+ struct hpre_asym_request *req,
+ struct scatterlist *dst,
+ struct scatterlist *src)
+{
+ struct device *dev = HPRE_DEV(ctx);
+ struct hpre_sqe *sqe = &req->req;
+ dma_addr_t dma;
+
+ dma = le64_to_cpu(sqe->in);
+ if (unlikely(!dma))
+ return;
+
+ if (src && req->src)
+ dma_free_coherent(dev, ctx->key_sz << 2, req->src, dma);
+
+ dma = le64_to_cpu(sqe->out);
+ if (unlikely(!dma))
+ return;
+
+ if (req->dst)
+ dma_free_coherent(dev, ctx->key_sz << 1, req->dst, dma);
+ if (dst)
+ dma_unmap_single(dev, dma, ctx->key_sz << 1, DMA_FROM_DEVICE);
+}
+
+static void hpre_ecdh_cb(struct hpre_ctx *ctx, void *resp)
+{
+ struct hpre_dfx *dfx = ctx->hpre->debug.dfx;
+ struct hpre_asym_request *req = NULL;
+ struct kpp_request *areq;
+ u64 overtime_thrhld;
+ int ret;
+
+ ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
+ areq = req->areq.ecdh;
+ areq->dst_len = ctx->key_sz << 1;
+
+ overtime_thrhld = atomic64_read(&dfx[HPRE_OVERTIME_THRHLD].value);
+ if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld))
+ atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
+
+ hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src);
+ kpp_request_complete(areq, ret);
+
+ atomic64_inc(&dfx[HPRE_RECV_CNT].value);
+}
+
+static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx,
+ struct kpp_request *req)
+{
+ struct hpre_asym_request *h_req;
+ struct hpre_sqe *msg;
+ int req_id;
+ void *tmp;
+
+ if (req->dst_len < ctx->key_sz << 1) {
+ req->dst_len = ctx->key_sz << 1;
+ return -EINVAL;
+ }
+
+ tmp = kpp_request_ctx(req);
+ h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+ h_req->cb = hpre_ecdh_cb;
+ h_req->areq.ecdh = req;
+ msg = &h_req->req;
+ memset(msg, 0, sizeof(*msg));
+ msg->key = cpu_to_le64(ctx->ecdh.dma_p);
+
+ msg->dw0 |= cpu_to_le32(0x1U << HPRE_SQE_DONE_SHIFT);
+ msg->task_len1 = (ctx->key_sz >> HPRE_BITS_2_BYTES_SHIFT) - 1;
+ h_req->ctx = ctx;
+
+ req_id = hpre_add_req_to_ctx(h_req);
+ if (req_id < 0)
+ return -EBUSY;
+
+ msg->tag = cpu_to_le16((u16)req_id);
+ return 0;
+}
+
+static int hpre_ecdh_src_data_init(struct hpre_asym_request *hpre_req,
+ struct scatterlist *data, unsigned int len)
+{
+ struct hpre_sqe *msg = &hpre_req->req;
+ struct hpre_ctx *ctx = hpre_req->ctx;
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int tmpshift;
+ dma_addr_t dma = 0;
+ void *ptr;
+ int shift;
+
+ /* Src_data include gx and gy. */
+ shift = ctx->key_sz - (len >> 1);
+ if (unlikely(shift < 0))
+ return -EINVAL;
+
+ ptr = dma_alloc_coherent(dev, ctx->key_sz << 2, &dma, GFP_KERNEL);
+ if (unlikely(!ptr))
+ return -ENOMEM;
+
+ tmpshift = ctx->key_sz << 1;
+ scatterwalk_map_and_copy(ptr + tmpshift, data, 0, len, 0);
+ memcpy(ptr + shift, ptr + tmpshift, len >> 1);
+ memcpy(ptr + ctx->key_sz + shift, ptr + tmpshift + (len >> 1), len >> 1);
+
+ hpre_req->src = ptr;
+ msg->in = cpu_to_le64(dma);
+ return 0;
+}
+
+static int hpre_ecdh_dst_data_init(struct hpre_asym_request *hpre_req,
+ struct scatterlist *data, unsigned int len)
+{
+ struct hpre_sqe *msg = &hpre_req->req;
+ struct hpre_ctx *ctx = hpre_req->ctx;
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int dst_len;
+ dma_addr_t dma = 0;
+ void *ptr;
+
+ if (sg_is_last(data)) {
+ hpre_req->dst = NULL;
+ dma = dma_map_single(dev, sg_virt(data), len, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev, dma))) {
+ dev_err(dev, "dma map data err!\n");
+ return -ENOMEM;
+ }
+ } else {
+ dst_len = ctx->key_sz << 1;
+ ptr = dma_alloc_coherent(dev, dst_len, &dma, GFP_KERNEL);
+ if (unlikely(!ptr))
+ return -ENOMEM;
+ hpre_req->dst = ptr;
+ }
+
+ msg->out = cpu_to_le64(dma);
+ return 0;
+}
+
+static int hpre_ecdh_compute_value(struct kpp_request *req)
+{
+ struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+ struct device *dev = HPRE_DEV(ctx);
+ void *tmp = kpp_request_ctx(req);
+ struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+ struct hpre_sqe *msg = &hpre_req->req;
+ int ret;
+
+ ret = hpre_ecdh_msg_request_set(ctx, req);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to set ecdh request, ret = %d!\n", ret);
+ return ret;
+ }
+
+ if (req->src) {
+ ret = hpre_ecdh_src_data_init(hpre_req, req->src, req->src_len);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to init src data, ret = %d!\n", ret);
+ goto clear_all;
+ }
+ } else {
+ msg->in = cpu_to_le64(ctx->ecdh.dma_g);
+ }
+
+ ret = hpre_ecdh_dst_data_init(hpre_req, req->dst, req->dst_len);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to init dst data, ret = %d!\n", ret);
+ goto clear_all;
+ }
+
+ msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) | HPRE_ALG_ECC_MUL);
+ ret = hpre_send(ctx, msg);
+ if (likely(!ret))
+ return -EINPROGRESS;
+
+clear_all:
+ hpre_rm_req_from_ctx(hpre_req);
+ hpre_ecdh_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
+ return ret;
+}
+
+static unsigned int hpre_ecdh_max_size(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ /* max size is the pub_key_size, include x and y */
+ return ctx->key_sz << 1;
+}
+
+static int hpre_ecdh_init_tfm(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ return hpre_ctx_init(ctx, HPRE_V3_ECC_ALG_TYPE);
+}
+
+static void hpre_ecdh_exit_tfm(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ hpre_ecc_clear_ctx(ctx, true, true);
+}
+
static struct akcipher_alg rsa = {
.sign = hpre_rsa_dec,
.verify = hpre_rsa_enc,
@@ -1154,6 +1916,22 @@ static struct kpp_alg dh = {
};
#endif

+static struct kpp_alg ecdh = {
+ .set_secret = hpre_ecdh_set_secret,
+ .generate_public_key = hpre_ecdh_compute_value,
+ .compute_shared_secret = hpre_ecdh_compute_value,
+ .max_size = hpre_ecdh_max_size,
+ .init = hpre_ecdh_init_tfm,
+ .exit = hpre_ecdh_exit_tfm,
+ .reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
+ .base = {
+ .cra_ctxsize = sizeof(struct hpre_ctx),
+ .cra_priority = HPRE_CRYPTO_ALG_PRI,
+ .cra_name = "ecdh",
+ .cra_driver_name = "hpre-ecdh",
+ .cra_module = THIS_MODULE,
+ },
+};
int hpre_algs_register(struct hisi_qm *qm)
{
int ret;
@@ -1164,17 +1942,33 @@ int hpre_algs_register(struct hisi_qm *qm)
return ret;
#ifdef CONFIG_CRYPTO_DH
ret = crypto_register_kpp(&dh);
- if (ret)
+ if (ret) {
crypto_unregister_akcipher(&rsa);
+ return ret;
+ }
#endif

- return ret;
+ if (qm->ver >= QM_HW_V3) {
+ ret = crypto_register_kpp(&ecdh);
+ if (ret) {
+#ifdef CONFIG_CRYPTO_DH
+ crypto_unregister_kpp(&dh);
+#endif
+ crypto_unregister_akcipher(&rsa);
+ return ret;
+ }
+ }
+
+ return 0;
}

void hpre_algs_unregister(struct hisi_qm *qm)
{
- crypto_unregister_akcipher(&rsa);
+ if (qm->ver >= QM_HW_V3)
+ crypto_unregister_kpp(&ecdh);
+
#ifdef CONFIG_CRYPTO_DH
crypto_unregister_kpp(&dh);
#endif
+ crypto_unregister_akcipher(&rsa);
}
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index 1ae8fa1..2ccc3dc 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -1020,4 +1020,5 @@ module_exit(hpre_exit);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Zaibo Xu <[email protected]>");
+MODULE_AUTHOR("Meng Yu <[email protected]>");
MODULE_DESCRIPTION("Driver for HiSilicon HPRE accelerator");
--
2.8.1

2020-11-18 03:51:21

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 3/5] crypto: hisilicon/hpre - add algorithm type

Algorithm type is brought in to get hardware HPRE queue
to support different algorithms.

Signed-off-by: Meng Yu <[email protected]>
Reviewed-by: Zaibo Xu <[email protected]>
---
drivers/crypto/hisilicon/hpre/hpre.h | 10 +++++++++-
drivers/crypto/hisilicon/hpre/hpre_crypto.c | 12 ++++++------
drivers/crypto/hisilicon/hpre/hpre_main.c | 11 +++++++++--
3 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index cc50f23..02193e1 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -10,6 +10,14 @@
#define HPRE_PF_DEF_Q_NUM 64
#define HPRE_PF_DEF_Q_BASE 0

+/*
+ * type used in qm sqc DW6.
+ * 0 - Algorithm which has been supported in V2, like RSA, DH and so on;
+ * 1 - ECC algorithm in V3.
+ */
+#define HPRE_V2_ALG_TYPE 0
+#define HPRE_V3_ECC_ALG_TYPE 1
+
enum {
HPRE_CLUSTER0,
HPRE_CLUSTER1,
@@ -92,7 +100,7 @@ struct hpre_sqe {
__le32 rsvd1[_HPRE_SQE_ALIGN_EXT];
};

-struct hisi_qp *hpre_create_qp(void);
+struct hisi_qp *hpre_create_qp(u8 type);
int hpre_algs_register(struct hisi_qm *qm);
void hpre_algs_unregister(struct hisi_qm *qm);

diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index d89b2f5..712bea9 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -152,12 +152,12 @@ static void hpre_rm_req_from_ctx(struct hpre_asym_request *hpre_req)
}
}

-static struct hisi_qp *hpre_get_qp_and_start(void)
+static struct hisi_qp *hpre_get_qp_and_start(u8 type)
{
struct hisi_qp *qp;
int ret;

- qp = hpre_create_qp();
+ qp = hpre_create_qp(type);
if (!qp) {
pr_err("Can not create hpre qp!\n");
return ERR_PTR(-ENODEV);
@@ -422,11 +422,11 @@ static void hpre_alg_cb(struct hisi_qp *qp, void *resp)
req->cb(ctx, resp);
}

-static int hpre_ctx_init(struct hpre_ctx *ctx)
+static int hpre_ctx_init(struct hpre_ctx *ctx, u8 type)
{
struct hisi_qp *qp;

- qp = hpre_get_qp_and_start();
+ qp = hpre_get_qp_and_start(type);
if (IS_ERR(qp))
return PTR_ERR(qp);

@@ -674,7 +674,7 @@ static int hpre_dh_init_tfm(struct crypto_kpp *tfm)
{
struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);

- return hpre_ctx_init(ctx);
+ return hpre_ctx_init(ctx, HPRE_V2_ALG_TYPE);
}

static void hpre_dh_exit_tfm(struct crypto_kpp *tfm)
@@ -1100,7 +1100,7 @@ static int hpre_rsa_init_tfm(struct crypto_akcipher *tfm)
return PTR_ERR(ctx->rsa.soft_tfm);
}

- ret = hpre_ctx_init(ctx);
+ ret = hpre_ctx_init(ctx, HPRE_V2_ALG_TYPE);
if (ret)
crypto_free_akcipher(ctx->rsa.soft_tfm);

diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index fc7173a..1ae8fa1 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -209,13 +209,20 @@ static u32 vfs_num;
module_param_cb(vfs_num, &vfs_num_ops, &vfs_num, 0444);
MODULE_PARM_DESC(vfs_num, "Number of VFs to enable(1-63), 0(default)");

-struct hisi_qp *hpre_create_qp(void)
+struct hisi_qp *hpre_create_qp(u8 type)
{
int node = cpu_to_node(smp_processor_id());
struct hisi_qp *qp = NULL;
int ret;

- ret = hisi_qm_alloc_qps_node(&hpre_devices, 1, 0, node, &qp);
+ if (type != HPRE_V2_ALG_TYPE && type != HPRE_V3_ECC_ALG_TYPE)
+ return NULL;
+
+ /*
+ * type: 0 - RSA/DH. algorithm supported in V2,
+ * 1 - ECC algorithm in V3.
+ */
+ ret = hisi_qm_alloc_qps_node(&hpre_devices, 1, type, node, &qp);
if (!ret)
return qp;

--
2.8.1

2020-11-18 03:51:24

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 2/5] crypto: hisilicon/hpre - add version adapt to new algorithms

'DH' and 'RSA' algorithms are supported by Kunpeng 920 and Kunpeng 930,
but some new algrithms(like ECDH) are only supported by Kunpeng 930, so
we add parameter 'struct hisi_qm *qm' to 'hpre_algs_(un)register' to
identify the chip's version.

Signed-off-by: Meng Yu <[email protected]>
Reviewed-by: Zaibo Xu <[email protected]>
---
drivers/crypto/hisilicon/hpre/hpre.h | 5 +++--
drivers/crypto/hisilicon/hpre/hpre_crypto.c | 4 ++--
drivers/crypto/hisilicon/qm.c | 4 ++--
drivers/crypto/hisilicon/qm.h | 4 ++--
drivers/crypto/hisilicon/sec2/sec.h | 4 ++--
drivers/crypto/hisilicon/sec2/sec_crypto.c | 4 ++--
drivers/crypto/hisilicon/sec2/sec_crypto.h | 4 ++--
drivers/crypto/hisilicon/zip/zip.h | 4 ++--
drivers/crypto/hisilicon/zip/zip_crypto.c | 4 ++--
9 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index 181c109..cc50f23 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -93,7 +93,8 @@ struct hpre_sqe {
};

struct hisi_qp *hpre_create_qp(void);
-int hpre_algs_register(void);
-void hpre_algs_unregister(void);
+int hpre_algs_register(struct hisi_qm *qm);
+void hpre_algs_unregister(struct hisi_qm *qm);
+

#endif
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index a87f990..d89b2f5 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -1154,7 +1154,7 @@ static struct kpp_alg dh = {
};
#endif

-int hpre_algs_register(void)
+int hpre_algs_register(struct hisi_qm *qm)
{
int ret;

@@ -1171,7 +1171,7 @@ int hpre_algs_register(void)
return ret;
}

-void hpre_algs_unregister(void)
+void hpre_algs_unregister(struct hisi_qm *qm)
{
crypto_unregister_akcipher(&rsa);
#ifdef CONFIG_CRYPTO_DH
diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c
index f21ccae..e25636b 100644
--- a/drivers/crypto/hisilicon/qm.c
+++ b/drivers/crypto/hisilicon/qm.c
@@ -4012,7 +4012,7 @@ int hisi_qm_alg_register(struct hisi_qm *qm, struct hisi_qm_list *qm_list)
mutex_unlock(&qm_list->lock);

if (flag) {
- ret = qm_list->register_to_crypto();
+ ret = qm_list->register_to_crypto(qm);
if (ret) {
mutex_lock(&qm_list->lock);
list_del(&qm->list);
@@ -4040,7 +4040,7 @@ void hisi_qm_alg_unregister(struct hisi_qm *qm, struct hisi_qm_list *qm_list)
mutex_unlock(&qm_list->lock);

if (list_empty(&qm_list->list))
- qm_list->unregister_from_crypto();
+ qm_list->unregister_from_crypto(qm);
}
EXPORT_SYMBOL_GPL(hisi_qm_alg_unregister);

diff --git a/drivers/crypto/hisilicon/qm.h b/drivers/crypto/hisilicon/qm.h
index 8624d12..a63256a 100644
--- a/drivers/crypto/hisilicon/qm.h
+++ b/drivers/crypto/hisilicon/qm.h
@@ -193,8 +193,8 @@ struct hisi_qm_err_ini {
struct hisi_qm_list {
struct mutex lock;
struct list_head list;
- int (*register_to_crypto)(void);
- void (*unregister_from_crypto)(void);
+ int (*register_to_crypto)(struct hisi_qm *qm);
+ void (*unregister_from_crypto)(struct hisi_qm *qm);
};

struct hisi_qm {
diff --git a/drivers/crypto/hisilicon/sec2/sec.h b/drivers/crypto/hisilicon/sec2/sec.h
index 0849191..17ddb20 100644
--- a/drivers/crypto/hisilicon/sec2/sec.h
+++ b/drivers/crypto/hisilicon/sec2/sec.h
@@ -183,6 +183,6 @@ struct sec_dev {

void sec_destroy_qps(struct hisi_qp **qps, int qp_num);
struct hisi_qp **sec_create_qps(void);
-int sec_register_to_crypto(void);
-void sec_unregister_from_crypto(void);
+int sec_register_to_crypto(struct hisi_qm *qm);
+void sec_unregister_from_crypto(struct hisi_qm *qm);
#endif
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c
index 87bc08a..f512ce2 100644
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.c
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c
@@ -1632,7 +1632,7 @@ static struct aead_alg sec_aeads[] = {
AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
};

-int sec_register_to_crypto(void)
+int sec_register_to_crypto(struct hisi_qm *qm)
{
int ret;

@@ -1649,7 +1649,7 @@ int sec_register_to_crypto(void)
return ret;
}

-void sec_unregister_from_crypto(void)
+void sec_unregister_from_crypto(struct hisi_qm *qm)
{
crypto_unregister_skciphers(sec_skciphers,
ARRAY_SIZE(sec_skciphers));
diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.h b/drivers/crypto/hisilicon/sec2/sec_crypto.h
index b2786e1..0e933e7 100644
--- a/drivers/crypto/hisilicon/sec2/sec_crypto.h
+++ b/drivers/crypto/hisilicon/sec2/sec_crypto.h
@@ -211,6 +211,6 @@ struct sec_sqe {
struct sec_sqe_type2 type2;
};

-int sec_register_to_crypto(void);
-void sec_unregister_from_crypto(void);
+int sec_register_to_crypto(struct hisi_qm *qm);
+void sec_unregister_from_crypto(struct hisi_qm *qm);
#endif
diff --git a/drivers/crypto/hisilicon/zip/zip.h b/drivers/crypto/hisilicon/zip/zip.h
index 92397f9..9ed7461 100644
--- a/drivers/crypto/hisilicon/zip/zip.h
+++ b/drivers/crypto/hisilicon/zip/zip.h
@@ -62,6 +62,6 @@ struct hisi_zip_sqe {
};

int zip_create_qps(struct hisi_qp **qps, int ctx_num, int node);
-int hisi_zip_register_to_crypto(void);
-void hisi_zip_unregister_from_crypto(void);
+int hisi_zip_register_to_crypto(struct hisi_qm *qm);
+void hisi_zip_unregister_from_crypto(struct hisi_qm *qm);
#endif
diff --git a/drivers/crypto/hisilicon/zip/zip_crypto.c b/drivers/crypto/hisilicon/zip/zip_crypto.c
index 08b4660..41f6966 100644
--- a/drivers/crypto/hisilicon/zip/zip_crypto.c
+++ b/drivers/crypto/hisilicon/zip/zip_crypto.c
@@ -665,7 +665,7 @@ static struct acomp_alg hisi_zip_acomp_gzip = {
}
};

-int hisi_zip_register_to_crypto(void)
+int hisi_zip_register_to_crypto(struct hisi_qm *qm)
{
int ret;

@@ -684,7 +684,7 @@ int hisi_zip_register_to_crypto(void)
return ret;
}

-void hisi_zip_unregister_from_crypto(void)
+void hisi_zip_unregister_from_crypto(struct hisi_qm *qm)
{
crypto_unregister_acomp(&hisi_zip_acomp_gzip);
crypto_unregister_acomp(&hisi_zip_acomp_zlib);
--
2.8.1

2020-11-18 03:51:38

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 1/5] crypto: hisilicon/hpre - add initial settings adapt to 'Kunpeng 930'

From: Hui Tang <[email protected]>

HPRE of Kunpeng 930 is updated on cluster numbers and configurations
of Kunpeng 920 HPRE, so we try to update this driver to make it running
okay on both chips.

Signed-off-by: Hui Tang <[email protected]>
Signed-off-by: Meng Yu <[email protected]>
Reviewed-by: Zaibo Xu <[email protected]>
---
drivers/crypto/hisilicon/hpre/hpre.h | 8 ++-
drivers/crypto/hisilicon/hpre/hpre_main.c | 93 +++++++++++++++++++++----------
2 files changed, 68 insertions(+), 33 deletions(-)

diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index f69252b..181c109 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -14,8 +14,7 @@ enum {
HPRE_CLUSTER0,
HPRE_CLUSTER1,
HPRE_CLUSTER2,
- HPRE_CLUSTER3,
- HPRE_CLUSTERS_NUM,
+ HPRE_CLUSTER3
};

enum hpre_ctrl_dbgfs_file {
@@ -36,7 +35,10 @@ enum hpre_dfx_dbgfs_file {
HPRE_DFX_FILE_NUM
};

-#define HPRE_DEBUGFS_FILE_NUM (HPRE_DEBUG_FILE_NUM + HPRE_CLUSTERS_NUM - 1)
+#define HPRE_CLUSTERS_NUM_V2 (HPRE_CLUSTER3 + 1)
+#define HPRE_CLUSTERS_NUM_V3 1
+#define HPRE_CLUSTERS_NUM_MAX HPRE_CLUSTERS_NUM_V2
+#define HPRE_DEBUGFS_FILE_NUM (HPRE_DEBUG_FILE_NUM + HPRE_CLUSTERS_NUM_MAX - 1)

struct hpre_debugfs_file {
int index;
diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c
index e5c9919..fc7173a 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -29,6 +29,8 @@
#define HPRE_BD_ARUSR_CFG 0x301030
#define HPRE_BD_AWUSR_CFG 0x301034
#define HPRE_TYPES_ENB 0x301038
+#define HPRE_RSA_ENB BIT(0)
+#define HPRE_ECC_ENB BIT(1)
#define HPRE_DATA_RUSER_CFG 0x30103c
#define HPRE_DATA_WUSER_CFG 0x301040
#define HPRE_INT_MASK 0x301400
@@ -73,7 +75,8 @@
#define HPRE_QM_AXI_CFG_MASK 0xffff
#define HPRE_QM_VFG_AX_MASK 0xff
#define HPRE_BD_USR_MASK 0x3
-#define HPRE_CLUSTER_CORE_MASK 0xf
+#define HPRE_CLUSTER_CORE_MASK_V2 0xf
+#define HPRE_CLUSTER_CORE_MASK_V3 0xff

#define HPRE_AM_OOO_SHUTDOWN_ENB 0x301044
#define HPRE_AM_OOO_SHUTDOWN_ENABLE BIT(0)
@@ -86,6 +89,11 @@
#define HPRE_QM_PM_FLR BIT(11)
#define HPRE_QM_SRIOV_FLR BIT(12)

+#define HPRE_CLUSTERS_NUM(qm) \
+ (((qm)->ver >= QM_HW_V3) ? HPRE_CLUSTERS_NUM_V3 : HPRE_CLUSTERS_NUM_V2)
+#define HPRE_CLUSTER_CORE_MASK(qm) \
+ (((qm)->ver >= QM_HW_V3) ? HPRE_CLUSTER_CORE_MASK_V3 :\
+ HPRE_CLUSTER_CORE_MASK_V2)
#define HPRE_VIA_MSI_DSM 1
#define HPRE_SQE_MASK_OFFSET 8
#define HPRE_SQE_MASK_LEN 24
@@ -238,8 +246,40 @@ static int hpre_cfg_by_dsm(struct hisi_qm *qm)
return 0;
}

+static int hpre_set_cluster(struct hisi_qm *qm)
+{
+ u32 cluster_core_mask = HPRE_CLUSTER_CORE_MASK(qm);
+ u8 clusters_num = HPRE_CLUSTERS_NUM(qm);
+ struct device *dev = &qm->pdev->dev;
+ unsigned long offset;
+ u32 val = 0;
+ int ret, i;
+
+ for (i = 0; i < clusters_num; i++) {
+ offset = i * HPRE_CLSTR_ADDR_INTRVL;
+
+ /* clusters initiating */
+ writel(cluster_core_mask,
+ HPRE_ADDR(qm, offset + HPRE_CORE_ENB));
+ writel(0x1, HPRE_ADDR(qm, offset + HPRE_CORE_INI_CFG));
+ ret = readl_relaxed_poll_timeout(HPRE_ADDR(qm, offset +
+ HPRE_CORE_INI_STATUS), val,
+ ((val & cluster_core_mask) ==
+ cluster_core_mask),
+ HPRE_REG_RD_INTVRL_US,
+ HPRE_REG_RD_TMOUT_US);
+ if (ret) {
+ dev_err(dev,
+ "cluster %d int st status timeout!\n", i);
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
/*
- * For Hi1620, we shoul disable FLR triggered by hardware (BME/PM/SRIOV).
+ * For Kunpeng 920, we shoul disable FLR triggered by hardware (BME/PM/SRIOV).
* Or it may stay in D3 state when we bind and unbind hpre quickly,
* as it does FLR triggered by hardware.
*/
@@ -257,9 +297,8 @@ static void disable_flr_of_bme(struct hisi_qm *qm)
static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
{
struct device *dev = &qm->pdev->dev;
- unsigned long offset;
- int ret, i;
u32 val;
+ int ret;

writel(HPRE_QM_USR_CFG_MASK, HPRE_ADDR(qm, QM_ARUSER_M_CFG_ENABLE));
writel(HPRE_QM_USR_CFG_MASK, HPRE_ADDR(qm, QM_AWUSER_M_CFG_ENABLE));
@@ -270,7 +309,12 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
val |= BIT(HPRE_TIMEOUT_ABNML_BIT);
writel_relaxed(val, HPRE_ADDR(qm, HPRE_QM_ABNML_INT_MASK));

- writel(0x1, HPRE_ADDR(qm, HPRE_TYPES_ENB));
+ if (qm->ver >= QM_HW_V3)
+ writel(HPRE_RSA_ENB | HPRE_ECC_ENB,
+ HPRE_ADDR(qm, HPRE_TYPES_ENB));
+ else
+ writel(HPRE_RSA_ENB, HPRE_ADDR(qm, HPRE_TYPES_ENB));
+
writel(HPRE_QM_VFG_AX_MASK, HPRE_ADDR(qm, HPRE_VFG_AXCACHE));
writel(0x0, HPRE_ADDR(qm, HPRE_BD_ENDIAN));
writel(0x0, HPRE_ADDR(qm, HPRE_INT_MASK));
@@ -291,37 +335,25 @@ static int hpre_set_user_domain_and_cache(struct hisi_qm *qm)
return -ETIMEDOUT;
}

- for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
- offset = i * HPRE_CLSTR_ADDR_INTRVL;
-
- /* clusters initiating */
- writel(HPRE_CLUSTER_CORE_MASK,
- HPRE_ADDR(qm, offset + HPRE_CORE_ENB));
- writel(0x1, HPRE_ADDR(qm, offset + HPRE_CORE_INI_CFG));
- ret = readl_relaxed_poll_timeout(HPRE_ADDR(qm, offset +
- HPRE_CORE_INI_STATUS), val,
- ((val & HPRE_CLUSTER_CORE_MASK) ==
- HPRE_CLUSTER_CORE_MASK),
- HPRE_REG_RD_INTVRL_US,
- HPRE_REG_RD_TMOUT_US);
- if (ret) {
- dev_err(dev,
- "cluster %d int st status timeout!\n", i);
- return -ETIMEDOUT;
- }
- }
-
- ret = hpre_cfg_by_dsm(qm);
+ ret = hpre_set_cluster(qm);
if (ret)
- dev_err(dev, "acpi_evaluate_dsm err.\n");
+ return -ETIMEDOUT;

- disable_flr_of_bme(qm);
+ /* This setting is only needed by Kunpeng 920. */
+ if (qm->ver == QM_HW_V2) {
+ ret = hpre_cfg_by_dsm(qm);
+ if (ret)
+ dev_err(dev, "acpi_evaluate_dsm err.\n");
+
+ disable_flr_of_bme(qm);
+ }

return ret;
}

static void hpre_cnt_regs_clear(struct hisi_qm *qm)
{
+ u8 clusters_num = HPRE_CLUSTERS_NUM(qm);
unsigned long offset;
int i;

@@ -330,7 +362,7 @@ static void hpre_cnt_regs_clear(struct hisi_qm *qm)
writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);

/* clear clusterX/cluster_ctrl */
- for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
+ for (i = 0; i < clusters_num; i++) {
offset = HPRE_CLSTR_BASE + i * HPRE_CLSTR_ADDR_INTRVL;
writel(0x0, qm->io_base + offset + HPRE_CLUSTER_INQURY);
}
@@ -629,13 +661,14 @@ static int hpre_pf_comm_regs_debugfs_init(struct hisi_qm *qm)

static int hpre_cluster_debugfs_init(struct hisi_qm *qm)
{
+ u8 clusters_num = HPRE_CLUSTERS_NUM(qm);
struct device *dev = &qm->pdev->dev;
char buf[HPRE_DBGFS_VAL_MAX_LEN];
struct debugfs_regset32 *regset;
struct dentry *tmp_d;
int i, ret;

- for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
+ for (i = 0; i < clusters_num; i++) {
ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i);
if (ret < 0)
return -EINVAL;
--
2.8.1

2020-11-18 03:51:41

by Meng Yu

[permalink] [raw]
Subject: [PATCH v3 5/5] crypto: hisilicon/hpre - add 'CURVE25519' algorithm

Enable 'CURVE25519' algorithm in Kunpeng 930.

Signed-off-by: Meng Yu <[email protected]>
Reviewed-by: Zaibo Xu <[email protected]>
Reported-by: kernel test robot <[email protected]>
---
drivers/crypto/hisilicon/Kconfig | 1 +
drivers/crypto/hisilicon/hpre/hpre.h | 2 +
drivers/crypto/hisilicon/hpre/hpre_crypto.c | 394 +++++++++++++++++++++++++++-
3 files changed, 388 insertions(+), 9 deletions(-)

diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig
index 9c3b3ca..bf2f0e3 100644
--- a/drivers/crypto/hisilicon/Kconfig
+++ b/drivers/crypto/hisilicon/Kconfig
@@ -65,6 +65,7 @@ config CRYPTO_DEV_HISI_HPRE
depends on UACCE || UACCE=n
depends on ARM64 || (COMPILE_TEST && 64BIT)
depends on ACPI
+ select CRYPTO_LIB_CURVE25519_GENERIC
select CRYPTO_DEV_HISI_QM
select CRYPTO_DH
select CRYPTO_RSA
diff --git a/drivers/crypto/hisilicon/hpre/hpre.h b/drivers/crypto/hisilicon/hpre/hpre.h
index 50e6b2e..92892e3 100644
--- a/drivers/crypto/hisilicon/hpre/hpre.h
+++ b/drivers/crypto/hisilicon/hpre/hpre.h
@@ -84,6 +84,8 @@ enum hpre_alg_type {
HPRE_ALG_DH_G2 = 0x4,
HPRE_ALG_DH = 0x5,
HPRE_ALG_ECC_MUL = 0xD,
+ /* shared by x25519 and x448, but x448 is not supported now */
+ HPRE_ALG_CURVE25519_MUL = 0x10,
};

struct hpre_sqe {
diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
index b7814ce..8c4d52c 100644
--- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 HiSilicon Limited. */
#include <crypto/akcipher.h>
+#include <crypto/curve25519.h>
#include <crypto/dh.h>
#include <crypto/ecdh.h>
#include <crypto/internal/akcipher.h>
@@ -70,6 +71,25 @@ struct curve_param_desc {
const unsigned char *n;
};

+/* curve25519 CURVE PARAMS, in big-endian order */
+/* p = (2 ^ 255 - 19) */
+static const unsigned char curve25519_p[] = {
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed
+};
+ /* a = (486662 - 2) / 4 = 121665 */
+static const unsigned char curve25519_a[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41
+};
+static const unsigned char curve25519_x[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09
+};
+
/* ECC CURVE PARAMS */
/* 128 bits */
static const unsigned char ecdh_p128_p[] = {
@@ -417,6 +437,16 @@ struct hpre_ecdh_ctx {
dma_addr_t dma_g;
};

+struct hpre_curve25519_ctx {
+ /* low address: p->a->k */
+ unsigned char *p;
+ dma_addr_t dma_p;
+
+ /* gx coordinate */
+ unsigned char *g;
+ dma_addr_t dma_g;
+};
+
struct hpre_ctx {
struct hisi_qp *qp;
struct hpre_asym_request **req_list;
@@ -429,6 +459,7 @@ struct hpre_ctx {
struct hpre_rsa_ctx rsa;
struct hpre_dh_ctx dh;
struct hpre_ecdh_ctx ecdh;
+ struct hpre_curve25519_ctx curve25519;
};
/* for ecc algorithms */
unsigned int curve_id;
@@ -443,6 +474,7 @@ struct hpre_asym_request {
struct akcipher_request *rsa;
struct kpp_request *dh;
struct kpp_request *ecdh;
+ struct kpp_request *curve25519;
} areq;
int err;
int req_id;
@@ -765,7 +797,6 @@ static void hpre_alg_cb(struct hisi_qp *qp, void *resp)
struct hpre_sqe *sqe = resp;
struct hpre_asym_request *req = ctx->req_list[le16_to_cpu(sqe->tag)];

-
if (unlikely(!req)) {
atomic64_inc(&dfx[HPRE_INVALID_REQ_CNT].value);
return;
@@ -1482,6 +1513,12 @@ static void hpre_ecc_clear_ctx(struct hpre_ctx *ctx, bool is_clear_all,
memzero_explicit(ctx->ecdh.p + shift, sz);
dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx->ecdh.dma_p);
ctx->ecdh.p = NULL;
+ } else if (!is_ecdh && ctx->curve25519.p) {
+ /* curve25519: p->a->k */
+ memzero_explicit(ctx->curve25519.p + shift, sz);
+ dma_free_coherent(dev, sz << 2, ctx->curve25519.p,
+ ctx->curve25519.dma_p);
+ ctx->curve25519.p = NULL;
}

ctx->curve_id = 0;
@@ -1877,6 +1914,318 @@ static void hpre_ecdh_exit_tfm(struct crypto_kpp *tfm)
hpre_ecc_clear_ctx(ctx, true, true);
}

+static void hpre_key_to_big_end(u8 *data, int len)
+{
+ int i, j;
+ u8 tmp;
+
+ for (i = 0; i < len / 2; i++) {
+ j = len - i - 1;
+ tmp = data[j];
+ data[j] = data[i];
+ data[i] = tmp;
+ }
+}
+
+static void hpre_curve25519_fill_curve(struct hpre_ctx *ctx, const void *buf,
+ unsigned int len)
+{
+ u8 secret[CURVE25519_KEY_SIZE] = { 0 };
+ unsigned int sz = ctx->key_sz;
+ unsigned int shift = sz << 1;
+ void *p;
+
+ /**
+ * The key from 'buf' is in little-endian, we should preprocess it as
+ * the description in rfc7748: "k[0] &= 248, k[31] &= 127, k[31] |= 64",
+ * then convert it to big endian. Only in this way, the result can be
+ * the same as the software curve-25519 that exists in crypto.
+ */
+ memcpy(secret, buf, len);
+ curve25519_clamp_secret(secret);
+ hpre_key_to_big_end(secret, CURVE25519_KEY_SIZE);
+
+ p = ctx->curve25519.p + sz - len;
+
+ /* fill curve parameters */
+ memcpy(p, curve25519_p, len);
+ memcpy(p + sz, curve25519_a, len);
+ memcpy(p + shift, secret, len);
+ memcpy(p + shift + sz, curve25519_x, len);
+ memzero_explicit(secret, CURVE25519_KEY_SIZE);
+}
+
+static int hpre_curve25519_set_param(struct hpre_ctx *ctx, const void *buf,
+ unsigned int len)
+{
+ struct device *dev = HPRE_DEV(ctx);
+ unsigned int sz = ctx->key_sz;
+ unsigned int shift = sz << 1;
+
+ /* p->a->k->gx */
+ if (!ctx->curve25519.p) {
+ ctx->curve25519.p = dma_alloc_coherent(dev, sz << 2,
+ &ctx->curve25519.dma_p,
+ GFP_KERNEL);
+ if (!ctx->curve25519.p)
+ return -ENOMEM;
+ }
+
+ ctx->curve25519.g = ctx->curve25519.p + shift + sz;
+ ctx->curve25519.dma_g = ctx->curve25519.dma_p + shift + sz;
+
+ hpre_curve25519_fill_curve(ctx, buf, len);
+
+ return 0;
+}
+
+static int hpre_curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
+ unsigned int len)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+ struct device *dev = HPRE_DEV(ctx);
+ int ret = -EINVAL;
+
+ if (len != CURVE25519_KEY_SIZE ||
+ !crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) {
+ dev_err(dev, "key is null or key len is not 32bytes!\n");
+ return ret;
+ }
+
+ /* Free old secret if any */
+ hpre_ecc_clear_ctx(ctx, false, false);
+
+ ctx->key_sz = CURVE25519_KEY_SIZE;
+ ret = hpre_curve25519_set_param(ctx, buf, CURVE25519_KEY_SIZE);
+ if (ret) {
+ dev_err(dev, "failed to set curve25519 param, ret = %d!\n", ret);
+ hpre_ecc_clear_ctx(ctx, false, false);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void hpre_curve25519_hw_data_clr_all(struct hpre_ctx *ctx,
+ struct hpre_asym_request *req,
+ struct scatterlist *dst,
+ struct scatterlist *src)
+{
+ struct device *dev = HPRE_DEV(ctx);
+ struct hpre_sqe *sqe = &req->req;
+ dma_addr_t dma;
+
+ dma = le64_to_cpu(sqe->in);
+ if (unlikely(!dma))
+ return;
+
+ if (src && req->src)
+ dma_free_coherent(dev, ctx->key_sz, req->src, dma);
+
+ dma = le64_to_cpu(sqe->out);
+ if (unlikely(!dma))
+ return;
+
+ if (req->dst)
+ dma_free_coherent(dev, ctx->key_sz, req->dst, dma);
+ if (dst)
+ dma_unmap_single(dev, dma, ctx->key_sz, DMA_FROM_DEVICE);
+}
+
+static void hpre_curve25519_cb(struct hpre_ctx *ctx, void *resp)
+{
+ struct hpre_dfx *dfx = ctx->hpre->debug.dfx;
+ struct hpre_asym_request *req = NULL;
+ struct kpp_request *areq;
+ u64 overtime_thrhld;
+ int ret;
+
+ ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
+ areq = req->areq.curve25519;
+ areq->dst_len = ctx->key_sz;
+
+ overtime_thrhld = atomic64_read(&dfx[HPRE_OVERTIME_THRHLD].value);
+ if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld))
+ atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
+
+ hpre_curve25519_hw_data_clr_all(ctx, req, areq->dst, areq->src);
+ kpp_request_complete(areq, ret);
+
+ atomic64_inc(&dfx[HPRE_RECV_CNT].value);
+}
+
+static int hpre_curve25519_msg_request_set(struct hpre_ctx *ctx,
+ struct kpp_request *req)
+{
+ struct hpre_asym_request *h_req;
+ struct hpre_sqe *msg;
+ int req_id;
+ void *tmp;
+
+ if (unlikely(req->dst_len < ctx->key_sz)) {
+ req->dst_len = ctx->key_sz;
+ return -EINVAL;
+ }
+
+ tmp = kpp_request_ctx(req);
+ h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+ h_req->cb = hpre_curve25519_cb;
+ h_req->areq.curve25519 = req;
+ msg = &h_req->req;
+ memset(msg, 0, sizeof(*msg));
+ msg->key = cpu_to_le64(ctx->curve25519.dma_p);
+
+ msg->dw0 |= cpu_to_le32(0x1U << HPRE_SQE_DONE_SHIFT);
+ msg->task_len1 = (ctx->key_sz >> HPRE_BITS_2_BYTES_SHIFT) - 1;
+ h_req->ctx = ctx;
+
+ req_id = hpre_add_req_to_ctx(h_req);
+ if (req_id < 0)
+ return -EBUSY;
+
+ msg->tag = cpu_to_le16((u16)req_id);
+ return 0;
+}
+
+static int hpre_curve25519_src_init(struct hpre_asym_request *hpre_req,
+ struct scatterlist *data, unsigned int len)
+{
+ struct hpre_sqe *msg = &hpre_req->req;
+ struct hpre_ctx *ctx = hpre_req->ctx;
+ struct device *dev = HPRE_DEV(ctx);
+ dma_addr_t dma = 0;
+ u8 *ptr;
+
+ if (len != CURVE25519_KEY_SIZE) {
+ dev_err(dev, "sourc_data len is not 32bytes, len = %u!\n", len);
+ return -EINVAL;
+ }
+
+ ptr = dma_alloc_coherent(dev, ctx->key_sz, &dma, GFP_KERNEL);
+ if (unlikely(!ptr))
+ return -ENOMEM;
+
+ scatterwalk_map_and_copy(ptr, data, 0, len, 0);
+
+ if (!crypto_memneq(ptr, curve25519_null_point, CURVE25519_KEY_SIZE)) {
+ dev_err(dev, "gx is null!\n");
+ goto err;
+ }
+
+ /**
+ * Src_data(gx) is in little-endian order, MSB in the final byte should
+ * be masked as discribed in RFC7748, then transform it to big-endian
+ * form, then hisi_hpre can use the data.
+ */
+ ptr[31] &= 0x7f;
+ hpre_key_to_big_end(ptr, CURVE25519_KEY_SIZE);
+
+ if (strcmp(ptr, curve25519_p) >= 0) {
+ dev_err(dev, "gx is out of p!\n");
+ goto err;
+ }
+
+ hpre_req->src = ptr;
+ msg->in = cpu_to_le64(dma);
+ return 0;
+
+err:
+ dma_free_coherent(dev, ctx->key_sz, ptr, dma);
+ return -EINVAL;
+}
+
+static int hpre_curve25519_dst_init(struct hpre_asym_request *hpre_req,
+ struct scatterlist *data, unsigned int len)
+{
+ struct hpre_sqe *msg = &hpre_req->req;
+ struct hpre_ctx *ctx = hpre_req->ctx;
+ struct device *dev = HPRE_DEV(ctx);
+ dma_addr_t dma = 0;
+ void *ptr;
+
+ if (sg_is_last(data)) {
+ hpre_req->dst = NULL;
+ dma = dma_map_single(dev, sg_virt(data), len, DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(dev, dma))) {
+ dev_err(dev, "dma map data err!\n");
+ return -ENOMEM;
+ }
+ } else {
+ ptr = dma_alloc_coherent(dev, ctx->key_sz, &dma, GFP_KERNEL);
+ if (unlikely(!ptr))
+ return -ENOMEM;
+ hpre_req->dst = ptr;
+ }
+
+ msg->out = cpu_to_le64(dma);
+ return 0;
+}
+
+static int hpre_curve25519_compute_value(struct kpp_request *req)
+{
+ struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+ struct device *dev = HPRE_DEV(ctx);
+ void *tmp = kpp_request_ctx(req);
+ struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+ struct hpre_sqe *msg = &hpre_req->req;
+ int ret;
+
+ ret = hpre_curve25519_msg_request_set(ctx, req);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to set curve25519 request, ret = %d!\n", ret);
+ return ret;
+ }
+
+ if (req->src) {
+ ret = hpre_curve25519_src_init(hpre_req, req->src, req->src_len);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to init src data, ret = %d!\n",
+ ret);
+ goto clear_all;
+ }
+ } else {
+ msg->in = cpu_to_le64(ctx->curve25519.dma_g);
+ }
+
+ ret = hpre_curve25519_dst_init(hpre_req, req->dst, req->dst_len);
+ if (unlikely(ret)) {
+ dev_err(dev, "failed to init dst data, ret = %d!\n", ret);
+ goto clear_all;
+ }
+
+ msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) | HPRE_ALG_CURVE25519_MUL);
+ ret = hpre_send(ctx, msg);
+ if (likely(!ret))
+ return -EINPROGRESS;
+
+clear_all:
+ hpre_rm_req_from_ctx(hpre_req);
+ hpre_curve25519_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
+ return ret;
+}
+
+static unsigned int hpre_curve25519_max_size(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ return ctx->key_sz;
+}
+
+static int hpre_curve25519_init_tfm(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ return hpre_ctx_init(ctx, HPRE_V3_ECC_ALG_TYPE);
+}
+
+static void hpre_curve25519_exit_tfm(struct crypto_kpp *tfm)
+{
+ struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+ hpre_ecc_clear_ctx(ctx, true, false);
+}
+
static struct akcipher_alg rsa = {
.sign = hpre_rsa_dec,
.verify = hpre_rsa_enc,
@@ -1932,6 +2281,24 @@ static struct kpp_alg ecdh = {
.cra_module = THIS_MODULE,
},
};
+
+static struct kpp_alg curve25519_alg = {
+ .set_secret = hpre_curve25519_set_secret,
+ .generate_public_key = hpre_curve25519_compute_value,
+ .compute_shared_secret = hpre_curve25519_compute_value,
+ .max_size = hpre_curve25519_max_size,
+ .init = hpre_curve25519_init_tfm,
+ .exit = hpre_curve25519_exit_tfm,
+ .reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
+ .base = {
+ .cra_ctxsize = sizeof(struct hpre_ctx),
+ .cra_priority = HPRE_CRYPTO_ALG_PRI,
+ .cra_name = "curve25519",
+ .cra_driver_name = "hpre-curve25519",
+ .cra_module = THIS_MODULE,
+ },
+};
+
int hpre_algs_register(struct hisi_qm *qm)
{
int ret;
@@ -1946,26 +2313,35 @@ int hpre_algs_register(struct hisi_qm *qm)
crypto_unregister_akcipher(&rsa);
return ret;
}
-#endif

+#endif
if (qm->ver >= QM_HW_V3) {
ret = crypto_register_kpp(&ecdh);
+ if (ret)
+ goto reg_err;
+
+ ret = crypto_register_kpp(&curve25519_alg);
if (ret) {
-#ifdef CONFIG_CRYPTO_DH
- crypto_unregister_kpp(&dh);
-#endif
- crypto_unregister_akcipher(&rsa);
- return ret;
+ crypto_unregister_kpp(&ecdh);
+ goto reg_err;
}
}
-
return 0;
+
+reg_err:
+#ifdef CONFIG_CRYPTO_DH
+ crypto_unregister_kpp(&dh);
+#endif
+ crypto_unregister_akcipher(&rsa);
+ return ret;
}

void hpre_algs_unregister(struct hisi_qm *qm)
{
- if (qm->ver >= QM_HW_V3)
+ if (qm->ver >= QM_HW_V3) {
+ crypto_unregister_kpp(&curve25519_alg);
crypto_unregister_kpp(&ecdh);
+ }

#ifdef CONFIG_CRYPTO_DH
crypto_unregister_kpp(&dh);
--
2.8.1

2020-11-18 20:26:28

by Stephan Müller

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] crypto: hisilicon/hpre - add 'ECDH' algorithm

Am Mittwoch, den 18.11.2020, 11:47 +0800 schrieb Meng Yu:

Hi Meng,

> Enable 'ECDH' algorithm in Kunpeng 930.
>
> Signed-off-by: Meng Yu <[email protected]>
> Reviewed-by: Zaibo Xu <[email protected]>
> ---
>  drivers/crypto/hisilicon/hpre/hpre.h        |   2 +-
>  drivers/crypto/hisilicon/hpre/hpre_crypto.c | 802
> +++++++++++++++++++++++++++-
>  drivers/crypto/hisilicon/hpre/hpre_main.c   |   1 +
>  3 files changed, 800 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/crypto/hisilicon/hpre/hpre.h
> b/drivers/crypto/hisilicon/hpre/hpre.h
> index 02193e1..50e6b2e 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre.h
> +++ b/drivers/crypto/hisilicon/hpre/hpre.h
> @@ -83,6 +83,7 @@ enum hpre_alg_type {
>         HPRE_ALG_KG_CRT = 0x3,
>         HPRE_ALG_DH_G2 = 0x4,
>         HPRE_ALG_DH = 0x5,
> +       HPRE_ALG_ECC_MUL = 0xD,
>  };
>  
>  struct hpre_sqe {
> @@ -104,5 +105,4 @@ struct hisi_qp *hpre_create_qp(u8 type);
>  int hpre_algs_register(struct hisi_qm *qm);
>  void hpre_algs_unregister(struct hisi_qm *qm);
>  
> -
>  #endif
> diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> index 712bea9..b7814ce 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> @@ -2,6 +2,7 @@
>  /* Copyright (c) 2019 HiSilicon Limited. */
>  #include <crypto/akcipher.h>
>  #include <crypto/dh.h>
> +#include <crypto/ecdh.h>
>  #include <crypto/internal/akcipher.h>
>  #include <crypto/internal/kpp.h>
>  #include <crypto/internal/rsa.h>
> @@ -36,6 +37,342 @@ struct hpre_ctx;
>  #define HPRE_DFX_SEC_TO_US     1000000
>  #define HPRE_DFX_US_TO_NS      1000
>  
> +/* HPRE support 7 curves (include curve P192 and P256 in ecdh.h) */
> +#define HPRE_ECC_CURVE_NIST_P128       0X0003
> +#define HPRE_ECC_CURVE_NIST_P320       0X0004
> +#define HPRE_ECC_CURVE_NIST_P384       0X0005
> +#define HPRE_ECC_CURVE_NIST_P521       0X0006
> +#define HPRE_ECC_CURVE_NIST_P224       0X0007
> +
> +/* size in bytes of the n prime */
> +#define HPRE_ECC_NIST_P128_N_SIZE      16
> +#define HPRE_ECC_NIST_P192_N_SIZE      24
> +#define HPRE_ECC_NIST_P224_N_SIZE      28
> +#define HPRE_ECC_NIST_P256_N_SIZE      32
> +#define HPRE_ECC_NIST_P320_N_SIZE      40
> +#define HPRE_ECC_NIST_P384_N_SIZE      48
> +#define HPRE_ECC_NIST_P521_N_SIZE      66
> +
> +/* size in bytes */
> +#define HPRE_ECC_HW256_KSZ_B   32
> +#define HPRE_ECC_HW384_KSZ_B   48
> +#define HPRE_ECC_HW576_KSZ_B   72
> +
> +#define HPRE_ECDH_MAX_SZ       HPRE_ECC_HW576_KSZ_B
> +
> +struct curve_param_desc {
> +       __u32 id;
> +       const unsigned char *p;
> +       const unsigned char *a;
> +       const unsigned char *b;
> +       const unsigned char *gx;
> +       const unsigned char *gy;
> +       const unsigned char *n;
> +};
> +
> +/* ECC CURVE PARAMS */
> +/* 128 bits */
> +static const unsigned char ecdh_p128_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF
> +};
> +static const unsigned char ecdh_p128_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFC
> +};
> +static const unsigned char ecdh_p128_b[] = {
> +       0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99,
> 0x3C,
> +       0x2C, 0xEE, 0x5E, 0xD3
> +};
> +static const unsigned char ecdh_p128_x[] = {
> +       0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60,
> 0x7C,
> +       0xA5, 0x2C, 0x5B, 0x86
> +};
> +static const unsigned char ecdh_p128_y[] = {
> +       0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d, 0xa2,
> 0x92,
> +       0xdd, 0xed, 0x7a, 0x83
> +};
> +static const unsigned char ecdh_p128_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D,
> 0x1B,
> +       0x90, 0x38, 0xA1, 0x15
> +};
> +
> +/* 192 bits */
> +static const unsigned char ecdh_p192_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF
> +};
> +static const unsigned char ecdh_p192_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFC
> +};
> +static const unsigned char ecdh_p192_b[] = {
> +       0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9,
> 0xAB,
> +       0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9,
> 0xB1
> +};
> +static const unsigned char ecdh_p192_x[] = {
> +       0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20,
> 0xEB,
> +       0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10,
> 0x12
> +};
> +static const unsigned char ecdh_p192_y[] = {
> +       0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11,
> 0xed,
> +       0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48,
> 0x11
> +};
> +static const unsigned char ecdh_p192_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28,
> 0x31
> +};
> +
> +/* 224 bits */
> +static const unsigned char ecdh_p224_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x01
> +};
> +static const unsigned char ecdh_p224_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE
> +};
> +static const unsigned char ecdh_p224_b[] = {
> +       0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32,
> 0x56,
> +       0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39,
> 0x43,
> +       0x23, 0x55, 0xFF, 0xB4
> +};
> +static const unsigned char ecdh_p224_x[] = {
> +       0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90,
> 0xB9,
> +       0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80,
> 0xD6,
> +       0x11, 0x5C, 0x1D, 0x21
> +};
> +static const unsigned char ecdh_p224_y[] = {
> +       0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf,
> 0xe6,
> +       0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81,
> 0x99,
> +       0x85, 0x00, 0x7e, 0x34
> +};
> +static const unsigned char ecdh_p224_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29,
> 0x45,
> +       0x5C, 0x5C, 0x2A, 0x3D
> +};
> +
> +/* 256 bits */
> +static const unsigned char ecdh_p256_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
> +};
> +static const unsigned char ecdh_p256_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
> +};
> +static const unsigned char ecdh_p256_b[] = {
> +       0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD,
> 0x55,
> +       0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0,
> 0xF6,
> +       0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B
> +};
> +static const unsigned char ecdh_p256_x[] = {
> +       0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6,
> 0xE5,
> +       0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33,
> 0xA0,
> +       0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96
> +};
> +static const unsigned char ecdh_p256_y[] = {
> +       0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
> 0x4a,
> +       0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e,
> 0xce,
> +       0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
> +};
> +static const unsigned char ecdh_p256_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E,
> 0x84,
> +       0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
> +};

Do we really need to re-define the parameters? crypto/ecc_curve_defs.h already
contains P-192 and P-256.

If we want more curves, I would like to suggest to keep them all at one common
place.
> +
> +/* 320 bits */
> +static const unsigned char ecdh_p320_p[] = {
> +       0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78,
> 0x5E,
> +       0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D,
> 0xEF,
> +       0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4, 0x12,
> 0xB1,
> +       0xF1, 0xB3, 0x2E, 0x27
> +};
> +static const unsigned char ecdh_p320_a[] = {
> +       0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB,
> 0xD4,
> +       0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79,
> 0xDA,
> +       0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3, 0x75,
> 0xA9,
> +       0x7D, 0x86, 0x0E, 0xB4
> +};
> +static const unsigned char ecdh_p320_b[] = {
> +       0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19,
> 0x86,
> +       0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4,
> 0x9A,
> +       0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E, 0xB4,
> 0xAC,
> +       0x8F, 0xB1, 0xF1, 0xA6
> +};
> +static const unsigned char ecdh_p320_x[] = {
> +       0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC,
> 0xC4,
> +       0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E,
> 0xB6,
> +       0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF, 0x8D,
> 0x0D,
> +       0x39, 0xE2, 0x06, 0x11
> +};
> +static const unsigned char ecdh_p320_y[] = {
> +       0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93,
> 0x24,
> +       0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82,
> 0xEA,
> +       0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52, 0x45,
> 0xD1,
> +       0x69, 0x2E, 0x8E, 0xE1
> +};
> +static const unsigned char ecdh_p320_n[] = {
> +       0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78,
> 0x5E,
> +       0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12,
> 0xA3,
> +       0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91, 0x55,
> 0x5B,
> +       0x44, 0xC5, 0x93, 0x11
> +};
> +
> +/* 384 bits */
> +static const unsigned char ecdh_p384_p[] = {
> +       0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F,
> 0x7E,
> +       0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56,
> 0xB4,
> +       0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3, 0xA7,
> 0x29,
> +       0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC,
> 0x53
> +};
> +static const unsigned char ecdh_p384_a[] = {
> +       0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08,
> 0x0A,
> +       0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27,
> 0x87,
> +       0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5, 0x81,
> 0x4A,
> +       0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28,
> 0x26
> +};
> +static const unsigned char ecdh_p384_b[] = {
> +       0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5,
> 0x54,
> +       0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2,
> 0xA6,
> +       0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4, 0x39,
> 0x02,
> +       0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C,
> 0x11
> +};
> +static const unsigned char ecdh_p384_x[] = {
> +       0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A,
> 0x81,
> +       0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F,
> 0xE3,
> +       0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26, 0xE0,
> 0x34,
> +       0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF,
> 0x1E
> +};
> +static const unsigned char ecdh_p384_y[] = {
> +       0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB,
> 0x8E,
> +       0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58,
> 0x64,
> +       0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46, 0x46,
> 0x21,
> +       0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53,
> 0x15
> +};
> +static const unsigned char ecdh_p384_n[] = {
> +       0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F,
> 0x7E,
> +       0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56,
> 0xB3,
> +       0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A, 0xB6,
> 0xAF,
> +       0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65,
> 0x65
> +};
> +
> +/* 521 bits */
> +static const unsigned char ecdh_p521_p[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
> +};
> +static const unsigned char ecdh_p521_a[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
> +};
> +static const unsigned char ecdh_p521_b[] = {
> +       0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92,
> 0x9A,
> +       0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99,
> 0xB3,
> +       0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56,
> 0x19,
> +       0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B,
> 0xB1,
> +       0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF,
> 0x45,
> +       0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00
> +};
> +static const unsigned char ecdh_p521_x[] = {
> +       0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E,
> 0x3E,
> +       0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05,
> 0x3F,
> +       0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1,
> 0x4B,
> +       0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2,
> 0xFF,
> +       0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9,
> 0x7E,
> +       0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66
> +};
> +static const unsigned char ecdh_p521_y[] = {
> +       0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c,
> 0x8a,
> +       0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57,
> 0x9b,
> +       0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97,
> 0xee,
> +       0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f,
> 0xad,
> +       0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88,
> 0xbe,
> +       0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50
> +};
> +static const unsigned char ecdh_p521_n[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51,
> 0x86,
> +       0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7,
> 0x09,
> +       0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB,
> 0x6F,
> +       0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
> +};
> +
> +static const struct curve_param_desc ecdh_curve_list[] = {
> +       {
> +               .id = ECC_CURVE_NIST_P192,
> +               .p = ecdh_p192_p,
> +               .a = ecdh_p192_a,
> +               .b = ecdh_p192_b,
> +               .gx = ecdh_p192_x,
> +               .gy = ecdh_p192_y,
> +               .n = ecdh_p192_n,
> +       }, {
> +               .id = ECC_CURVE_NIST_P256,
> +               .p = ecdh_p256_p,
> +               .a = ecdh_p256_a,
> +               .b = ecdh_p256_b,
> +               .gx = ecdh_p256_x,
> +               .gy = ecdh_p256_y,
> +               .n = ecdh_p256_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P128,
> +               .p = ecdh_p128_p,
> +               .a = ecdh_p128_a,
> +               .b = ecdh_p128_b,
> +               .gx = ecdh_p128_x,
> +               .gy = ecdh_p128_y,
> +               .n = ecdh_p128_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P320,
> +               .p = ecdh_p320_p,
> +               .a = ecdh_p320_a,
> +               .b = ecdh_p320_b,
> +               .gx = ecdh_p320_x,
> +               .gy = ecdh_p320_y,
> +               .n = ecdh_p320_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P384,
> +               .p = ecdh_p384_p,
> +               .a = ecdh_p384_a,
> +               .b = ecdh_p384_b,
> +               .gx = ecdh_p384_x,
> +               .gy = ecdh_p384_y,
> +               .n = ecdh_p384_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P521,
> +               .p = ecdh_p521_p,
> +               .a = ecdh_p521_a,
> +               .b = ecdh_p521_b,
> +               .gx = ecdh_p521_x,
> +               .gy = ecdh_p521_y,
> +               .n = ecdh_p521_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P224,
> +               .p = ecdh_p224_p,
> +               .a = ecdh_p224_a,
> +               .b = ecdh_p224_b,
> +               .gx = ecdh_p224_x,
> +               .gy = ecdh_p224_y,
> +               .n = ecdh_p224_n,
> +       }
> +};
> +
>  typedef void (*hpre_cb)(struct hpre_ctx *ctx, void *sqe);
>  
>  struct hpre_rsa_ctx {
> @@ -61,14 +398,25 @@ struct hpre_dh_ctx {
>          * else if base if the counterpart public key we
>          * compute the shared secret
>          *      ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
> +        * low address: d--->n, please refer to Hisilicon HPRE UM
>          */
> -       char *xa_p; /* low address: d--->n, please refer to Hisilicon HPRE
> UM */
> +       char *xa_p;
>         dma_addr_t dma_xa_p;
>  
>         char *g; /* m */
>         dma_addr_t dma_g;
>  };
>  
> +struct hpre_ecdh_ctx {
> +       /* low address: p->a->k->b */
> +       unsigned char *p;
> +       dma_addr_t dma_p;
> +
> +       /* low address: x->y */
> +       unsigned char *g;
> +       dma_addr_t dma_g;
> +};
> +
>  struct hpre_ctx {
>         struct hisi_qp *qp;
>         struct hpre_asym_request **req_list;
> @@ -80,7 +428,10 @@ struct hpre_ctx {
>         union {
>                 struct hpre_rsa_ctx rsa;
>                 struct hpre_dh_ctx dh;
> +               struct hpre_ecdh_ctx ecdh;
>         };
> +       /* for ecc algorithms */
> +       unsigned int curve_id;
>  };
>  
>  struct hpre_asym_request {
> @@ -91,6 +442,7 @@ struct hpre_asym_request {
>         union {
>                 struct akcipher_request *rsa;
>                 struct kpp_request *dh;
> +               struct kpp_request *ecdh;
>         } areq;
>         int err;
>         int req_id;
> @@ -1115,6 +1467,416 @@ static void hpre_rsa_exit_tfm(struct crypto_akcipher
> *tfm)
>         crypto_free_akcipher(ctx->rsa.soft_tfm);
>  }
>  
> +static void hpre_ecc_clear_ctx(struct hpre_ctx *ctx, bool is_clear_all,
> +                              bool is_ecdh)
> +{
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz = ctx->key_sz;
> +       unsigned int shift = sz << 1;
> +
> +       if (is_clear_all)
> +               hisi_qm_stop_qp(ctx->qp);
> +
> +       if (is_ecdh && ctx->ecdh.p) {
> +               /* ecdh: p->a->k->b */
> +               memzero_explicit(ctx->ecdh.p + shift, sz);
> +               dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx-
> >ecdh.dma_p);
> +               ctx->ecdh.p = NULL;
> +       }
> +
> +       ctx->curve_id = 0;
> +       hpre_ctx_clear(ctx, is_clear_all);
> +}
> +
> +/*
> + * only the bits of 128/192/224/256/320/384/521 are supported by HPRE,
> + * and convert the bits like:
> + * bits<=256, bits=256; 256<bits<=384, bits=384; 384<bits<=576, bits=576;
> + * If the parameter bit width is insufficient, then we fill in the
> + * high-order zeros by soft, so TASK_LENGTH1 is 0x3/0x5/0x8;
> + */
> +static unsigned int hpre_ecdh_supported_curve(unsigned int curve_id)
> +{
> +       switch (curve_id) {
> +       case ECC_CURVE_NIST_P192:
> +       case ECC_CURVE_NIST_P256:
> +       case HPRE_ECC_CURVE_NIST_P128:
> +       case HPRE_ECC_CURVE_NIST_P224:
> +               return HPRE_ECC_HW256_KSZ_B;
> +       case HPRE_ECC_CURVE_NIST_P320:
> +       case HPRE_ECC_CURVE_NIST_P384:
> +               return HPRE_ECC_HW384_KSZ_B;
> +       case HPRE_ECC_CURVE_NIST_P521:
> +               return HPRE_ECC_HW576_KSZ_B;
> +       default:
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct curve_param_desc *ecdh_get_curve_param(__u32 curve_id)
> +{
> +       if (curve_id >= 1 && curve_id <= ARRAY_SIZE(ecdh_curve_list))
> +               return &ecdh_curve_list[curve_id - 1];
> +
> +       return NULL;
> +}
> +
> +static int hpre_ecdh_fill_curve(struct hpre_ctx *ctx, struct ecdh *params,
> +                               unsigned int cur_sz)
> +{
> +       unsigned int shifta = ctx->key_sz << 1;
> +       unsigned int shiftb = ctx->key_sz << 2;
> +       void *p = ctx->ecdh.p + ctx->key_sz - cur_sz;
> +       void *a = ctx->ecdh.p + shifta - cur_sz;
> +       void *b = ctx->ecdh.p + shiftb - cur_sz;
> +       void *x = ctx->ecdh.g + ctx->key_sz - cur_sz;
> +       void *y = ctx->ecdh.g + shifta - cur_sz;
> +       const struct curve_param_desc *curve;
> +       char *n;
> +
> +       n = kzalloc(ctx->key_sz, GFP_KERNEL);
> +       if (!n)
> +               return -ENOMEM;
> +
> +       curve = ecdh_get_curve_param(params->curve_id);
> +       if (!curve)
> +               goto free;
> +
> +       memcpy(p, curve->p, cur_sz);
> +       memcpy(a, curve->a, cur_sz);
> +       memcpy(b, curve->b, cur_sz);
> +       memcpy(x, curve->gx, cur_sz);
> +       memcpy(y, curve->gy, cur_sz);
> +       memcpy(n, curve->n, cur_sz);
> +
> +       if (params->key_size == cur_sz && strcmp(params->key, n) >= 0)
> +               goto free;
> +
> +       kfree(n);
> +       return 0;
> +
> +free:
> +       kfree(n);
> +       return -EINVAL;
> +}
> +
> +static unsigned int hpre_ecdh_get_curvesz(unsigned short id)
> +{
> +       switch (id) {
> +       case ECC_CURVE_NIST_P192:
> +               return HPRE_ECC_NIST_P192_N_SIZE;
> +       case ECC_CURVE_NIST_P256:
> +               return HPRE_ECC_NIST_P256_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P128:
> +               return HPRE_ECC_NIST_P128_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P224:
> +               return HPRE_ECC_NIST_P224_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P320:
> +               return HPRE_ECC_NIST_P320_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P384:
> +               return HPRE_ECC_NIST_P384_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P521:
> +               return HPRE_ECC_NIST_P521_N_SIZE;
> +       default:
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int hpre_ecdh_set_param(struct hpre_ctx *ctx, struct ecdh *params)
> +{
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz, shift, curve_sz;
> +       int ret;
> +
> +       ctx->key_sz = hpre_ecdh_supported_curve(params->curve_id);
> +       if (!ctx->key_sz)
> +               return -EINVAL;
> +
> +       curve_sz = hpre_ecdh_get_curvesz(params->curve_id);
> +       if (!curve_sz || params->key_size > curve_sz)
> +               return -EINVAL;
> +
> +       sz = ctx->key_sz;
> +       ctx->curve_id = params->curve_id;
> +
> +       if (!ctx->ecdh.p) {
> +               ctx->ecdh.p = dma_alloc_coherent(dev, sz << 3, &ctx-
> >ecdh.dma_p,
> +                                                GFP_KERNEL);
> +               if (!ctx->ecdh.p)
> +                       return -ENOMEM;
> +       }
> +
> +       shift = sz << 2;
> +       ctx->ecdh.g = ctx->ecdh.p + shift;
> +       ctx->ecdh.dma_g = ctx->ecdh.dma_p + shift;
> +
> +       ret = hpre_ecdh_fill_curve(ctx, params, curve_sz);
> +       if (ret) {
> +               dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx-
> >ecdh.dma_p);
> +               dev_err(dev, "failed to fill curve_param, ret = %d!\n",
> ret);
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static bool hpre_key_is_valid(char *key, unsigned short key_sz)
> +{
> +       int i;
> +
> +       for (i = 0; i < key_sz; i++)
> +               if (key[i])
> +                       return true;
> +
> +       return false;
> +}
> +
> +static int hpre_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
> +                               unsigned int len)
> +{
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz, sz_shift;
> +       struct ecdh params;
> +       int ret;
> +
> +       if (crypto_ecdh_decode_key(buf, len, &params) < 0) {
> +               dev_err(dev, "failed to decode ecdh key!\n");
> +               return -EINVAL;
> +       }
> +
> +       if (!hpre_key_is_valid(params.key, params.key_size)) {
> +               dev_err(dev, "Invalid hpre key!\n");
> +               return -EINVAL;
> +       }
> +
> +       hpre_ecc_clear_ctx(ctx, false, true);
> +
> +       ret = hpre_ecdh_set_param(ctx, &params);
> +       if (ret < 0) {
> +               dev_err(dev, "failed to set hpre param, ret = %d!\n", ret);
> +               goto err_clear_ctx;
> +       }
> +
> +       sz = ctx->key_sz;
> +       sz_shift = (sz << 1) + sz - params.key_size;
> +       memcpy(ctx->ecdh.p + sz_shift, params.key, params.key_size);
> +       return 0;
> +
> +err_clear_ctx:
> +       hpre_ecc_clear_ctx(ctx, false, true);
> +       return ret;
> +}
> +
> +static void hpre_ecdh_hw_data_clr_all(struct hpre_ctx *ctx,
> +                                     struct hpre_asym_request *req,
> +                                     struct scatterlist *dst,
> +                                     struct scatterlist *src)
> +{
> +       struct device *dev = HPRE_DEV(ctx);
> +       struct hpre_sqe *sqe = &req->req;
> +       dma_addr_t dma;
> +
> +       dma = le64_to_cpu(sqe->in);
> +       if (unlikely(!dma))
> +               return;
> +
> +       if (src && req->src)
> +               dma_free_coherent(dev, ctx->key_sz << 2, req->src, dma);
> +
> +       dma = le64_to_cpu(sqe->out);
> +       if (unlikely(!dma))
> +               return;
> +
> +       if (req->dst)
> +               dma_free_coherent(dev, ctx->key_sz << 1, req->dst, dma);
> +       if (dst)
> +               dma_unmap_single(dev, dma, ctx->key_sz << 1,
> DMA_FROM_DEVICE);
> +}
> +
> +static void hpre_ecdh_cb(struct hpre_ctx *ctx, void *resp)
> +{
> +       struct hpre_dfx *dfx = ctx->hpre->debug.dfx;
> +       struct hpre_asym_request *req = NULL;
> +       struct kpp_request *areq;
> +       u64 overtime_thrhld;
> +       int ret;
> +
> +       ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
> +       areq = req->areq.ecdh;
> +       areq->dst_len = ctx->key_sz << 1;
> +
> +       overtime_thrhld = atomic64_read(&dfx[HPRE_OVERTIME_THRHLD].value);
> +       if (overtime_thrhld && hpre_is_bd_timeout(req, overtime_thrhld))
> +               atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
> +
> +       hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src);
> +       kpp_request_complete(areq, ret);
> +
> +       atomic64_inc(&dfx[HPRE_RECV_CNT].value);
> +}
> +
> +static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx,
> +                                    struct kpp_request *req)
> +{
> +       struct hpre_asym_request *h_req;
> +       struct hpre_sqe *msg;
> +       int req_id;
> +       void *tmp;
> +
> +       if (req->dst_len < ctx->key_sz << 1) {
> +               req->dst_len = ctx->key_sz << 1;
> +               return -EINVAL;
> +       }
> +
> +       tmp = kpp_request_ctx(req);
> +       h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
> +       h_req->cb = hpre_ecdh_cb;
> +       h_req->areq.ecdh = req;
> +       msg = &h_req->req;
> +       memset(msg, 0, sizeof(*msg));
> +       msg->key = cpu_to_le64(ctx->ecdh.dma_p);
> +
> +       msg->dw0 |= cpu_to_le32(0x1U << HPRE_SQE_DONE_SHIFT);
> +       msg->task_len1 = (ctx->key_sz >> HPRE_BITS_2_BYTES_SHIFT) - 1;
> +       h_req->ctx = ctx;
> +
> +       req_id = hpre_add_req_to_ctx(h_req);
> +       if (req_id < 0)
> +               return -EBUSY;
> +
> +       msg->tag = cpu_to_le16((u16)req_id);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_src_data_init(struct hpre_asym_request *hpre_req,
> +                                  struct scatterlist *data, unsigned int
> len)
> +{
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       struct hpre_ctx *ctx = hpre_req->ctx;
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int tmpshift;
> +       dma_addr_t dma = 0;
> +       void *ptr;
> +       int shift;
> +
> +       /* Src_data include gx and gy. */
> +       shift = ctx->key_sz - (len >> 1);
> +       if (unlikely(shift < 0))
> +               return -EINVAL;
> +
> +       ptr = dma_alloc_coherent(dev, ctx->key_sz << 2, &dma, GFP_KERNEL);
> +       if (unlikely(!ptr))
> +               return -ENOMEM;
> +
> +       tmpshift = ctx->key_sz << 1;
> +       scatterwalk_map_and_copy(ptr + tmpshift, data, 0, len, 0);
> +       memcpy(ptr + shift, ptr + tmpshift, len >> 1);
> +       memcpy(ptr + ctx->key_sz + shift, ptr + tmpshift + (len >> 1), len
> >> 1);
> +
> +       hpre_req->src = ptr;
> +       msg->in = cpu_to_le64(dma);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_dst_data_init(struct hpre_asym_request *hpre_req,
> +                                  struct scatterlist *data, unsigned int
> len)
> +{
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       struct hpre_ctx *ctx = hpre_req->ctx;
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int dst_len;
> +       dma_addr_t dma = 0;
> +       void *ptr;
> +
> +       if (sg_is_last(data)) {
> +               hpre_req->dst = NULL;
> +               dma = dma_map_single(dev, sg_virt(data), len,
> DMA_FROM_DEVICE);
> +               if (unlikely(dma_mapping_error(dev, dma))) {
> +                       dev_err(dev, "dma map data err!\n");
> +                       return -ENOMEM;
> +               }
> +       } else {
> +               dst_len = ctx->key_sz << 1;
> +               ptr = dma_alloc_coherent(dev, dst_len, &dma, GFP_KERNEL);
> +               if (unlikely(!ptr))
> +                       return -ENOMEM;
> +               hpre_req->dst = ptr;
> +       }
> +
> +       msg->out = cpu_to_le64(dma);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_compute_value(struct kpp_request *req)
> +{
> +       struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +       struct device *dev = HPRE_DEV(ctx);
> +       void *tmp = kpp_request_ctx(req);
> +       struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       int ret;
> +
> +       ret = hpre_ecdh_msg_request_set(ctx, req);
> +       if (unlikely(ret)) {
> +               dev_err(dev, "failed to set ecdh request, ret = %d!\n",
> ret);
> +               return ret;
> +       }
> +
> +       if (req->src) {
> +               ret = hpre_ecdh_src_data_init(hpre_req, req->src, req-
> >src_len);
> +               if (unlikely(ret)) {
> +                       dev_err(dev, "failed to init src data, ret = %d!\n",
> ret);
> +                       goto clear_all;
> +               }
> +       } else {
> +               msg->in = cpu_to_le64(ctx->ecdh.dma_g);
> +       }
> +
> +       ret = hpre_ecdh_dst_data_init(hpre_req, req->dst, req->dst_len);
> +       if (unlikely(ret)) {
> +               dev_err(dev, "failed to init dst data, ret = %d!\n", ret);
> +               goto clear_all;
> +       }
> +
> +       msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) | HPRE_ALG_ECC_MUL);
> +       ret = hpre_send(ctx, msg);
> +       if (likely(!ret))
> +               return -EINPROGRESS;
> +
> +clear_all:
> +       hpre_rm_req_from_ctx(hpre_req);
> +       hpre_ecdh_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
> +       return ret;
> +}
> +
> +static unsigned int hpre_ecdh_max_size(struct crypto_kpp *tfm)
> +{
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       /* max size is the pub_key_size, include x and y */
> +       return ctx->key_sz << 1;
> +}
> +
> +static int hpre_ecdh_init_tfm(struct crypto_kpp *tfm)
> +{
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       return hpre_ctx_init(ctx, HPRE_V3_ECC_ALG_TYPE);
> +}
> +
> +static void hpre_ecdh_exit_tfm(struct crypto_kpp *tfm)
> +{
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       hpre_ecc_clear_ctx(ctx, true, true);
> +}
> +
>  static struct akcipher_alg rsa = {
>         .sign = hpre_rsa_dec,
>         .verify = hpre_rsa_enc,
> @@ -1154,6 +1916,22 @@ static struct kpp_alg dh = {
>  };
>  #endif
>  
> +static struct kpp_alg ecdh = {
> +       .set_secret = hpre_ecdh_set_secret,
> +       .generate_public_key = hpre_ecdh_compute_value,
> +       .compute_shared_secret = hpre_ecdh_compute_value,
> +       .max_size = hpre_ecdh_max_size,
> +       .init = hpre_ecdh_init_tfm,
> +       .exit = hpre_ecdh_exit_tfm,
> +       .reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
> +       .base = {
> +               .cra_ctxsize = sizeof(struct hpre_ctx),
> +               .cra_priority = HPRE_CRYPTO_ALG_PRI,
> +               .cra_name = "ecdh",
> +               .cra_driver_name = "hpre-ecdh",
> +               .cra_module = THIS_MODULE,
> +       },
> +};
>  int hpre_algs_register(struct hisi_qm *qm)
>  {
>         int ret;
> @@ -1164,17 +1942,33 @@ int hpre_algs_register(struct hisi_qm *qm)
>                 return ret;
>  #ifdef CONFIG_CRYPTO_DH
>         ret = crypto_register_kpp(&dh);
> -       if (ret)
> +       if (ret) {
>                 crypto_unregister_akcipher(&rsa);
> +               return ret;
> +       }
>  #endif
>  
> -       return ret;
> +       if (qm->ver >= QM_HW_V3) {
> +               ret = crypto_register_kpp(&ecdh);
> +               if (ret) {
> +#ifdef CONFIG_CRYPTO_DH
> +                       crypto_unregister_kpp(&dh);
> +#endif
> +                       crypto_unregister_akcipher(&rsa);
> +                       return ret;
> +               }
> +       }
> +
> +       return 0;
>  }
>  
>  void hpre_algs_unregister(struct hisi_qm *qm)
>  {
> -       crypto_unregister_akcipher(&rsa);
> +       if (qm->ver >= QM_HW_V3)
> +               crypto_unregister_kpp(&ecdh);
> +
>  #ifdef CONFIG_CRYPTO_DH
>         crypto_unregister_kpp(&dh);
>  #endif
> +       crypto_unregister_akcipher(&rsa);
>  }
> diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c
> b/drivers/crypto/hisilicon/hpre/hpre_main.c
> index 1ae8fa1..2ccc3dc 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre_main.c
> +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
> @@ -1020,4 +1020,5 @@ module_exit(hpre_exit);
>  
>  MODULE_LICENSE("GPL v2");
>  MODULE_AUTHOR("Zaibo Xu <[email protected]>");
> +MODULE_AUTHOR("Meng Yu <[email protected]>");
>  MODULE_DESCRIPTION("Driver for HiSilicon HPRE accelerator");


2020-11-25 07:17:10

by Meng Yu

[permalink] [raw]
Subject: 答复: [PATCH v3 4/5] crypto: hisilicon/hpre - add 'ECDH' algorithm

Ok, I think I can make a patch to keep them at "include/crypto" .

-----邮件原件-----
发件人: Stephan Mueller [mailto:[email protected]]
发送时间: 2020年11月19日 4:25
收件人: yumeng (J) <[email protected]>; [email protected]; [email protected]
抄送: [email protected]; Xu Zaibo <[email protected]>; Wangzhou (B) <[email protected]>; [email protected]
主题: Re: [PATCH v3 4/5] crypto: hisilicon/hpre - add 'ECDH' algorithm

Am Mittwoch, den 18.11.2020, 11:47 +0800 schrieb Meng Yu:

Hi Meng,

> Enable 'ECDH' algorithm in Kunpeng 930.
>
> Signed-off-by: Meng Yu <[email protected]>
> Reviewed-by: Zaibo Xu <[email protected]>
> ---
>  drivers/crypto/hisilicon/hpre/hpre.h        |   2 +-
>  drivers/crypto/hisilicon/hpre/hpre_crypto.c | 802
> +++++++++++++++++++++++++++-
>  drivers/crypto/hisilicon/hpre/hpre_main.c   |   1 +
>  3 files changed, 800 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/crypto/hisilicon/hpre/hpre.h
> b/drivers/crypto/hisilicon/hpre/hpre.h
> index 02193e1..50e6b2e 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre.h
> +++ b/drivers/crypto/hisilicon/hpre/hpre.h
> @@ -83,6 +83,7 @@ enum hpre_alg_type {
>         HPRE_ALG_KG_CRT = 0x3,
>         HPRE_ALG_DH_G2 = 0x4,
>         HPRE_ALG_DH = 0x5,
> +       HPRE_ALG_ECC_MUL = 0xD,
>  };
>  
>  struct hpre_sqe {
> @@ -104,5 +105,4 @@ struct hisi_qp *hpre_create_qp(u8 type);
>  int hpre_algs_register(struct hisi_qm *qm);
>  void hpre_algs_unregister(struct hisi_qm *qm);
>  
> -
>  #endif
> diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> index 712bea9..b7814ce 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c
> @@ -2,6 +2,7 @@
>  /* Copyright (c) 2019 HiSilicon Limited. */
>  #include <crypto/akcipher.h>
>  #include <crypto/dh.h>
> +#include <crypto/ecdh.h>
>  #include <crypto/internal/akcipher.h>
>  #include <crypto/internal/kpp.h>
>  #include <crypto/internal/rsa.h>
> @@ -36,6 +37,342 @@ struct hpre_ctx;
>  #define HPRE_DFX_SEC_TO_US     1000000
>  #define HPRE_DFX_US_TO_NS      1000
>  
> +/* HPRE support 7 curves (include curve P192 and P256 in ecdh.h) */
> +#define HPRE_ECC_CURVE_NIST_P128       0X0003 #define
> +HPRE_ECC_CURVE_NIST_P320       0X0004 #define
> +HPRE_ECC_CURVE_NIST_P384       0X0005 #define
> +HPRE_ECC_CURVE_NIST_P521       0X0006 #define
> +HPRE_ECC_CURVE_NIST_P224       0X0007
> +
> +/* size in bytes of the n prime */
> +#define HPRE_ECC_NIST_P128_N_SIZE      16 #define
> +HPRE_ECC_NIST_P192_N_SIZE      24 #define HPRE_ECC_NIST_P224_N_SIZE      
> +28 #define HPRE_ECC_NIST_P256_N_SIZE      32 #define
> +HPRE_ECC_NIST_P320_N_SIZE      40 #define HPRE_ECC_NIST_P384_N_SIZE      
> +48 #define HPRE_ECC_NIST_P521_N_SIZE      66
> +
> +/* size in bytes */
> +#define HPRE_ECC_HW256_KSZ_B   32
> +#define HPRE_ECC_HW384_KSZ_B   48
> +#define HPRE_ECC_HW576_KSZ_B   72
> +
> +#define HPRE_ECDH_MAX_SZ       HPRE_ECC_HW576_KSZ_B
> +
> +struct curve_param_desc {
> +       __u32 id;
> +       const unsigned char *p;
> +       const unsigned char *a;
> +       const unsigned char *b;
> +       const unsigned char *gx;
> +       const unsigned char *gy;
> +       const unsigned char *n;
> +};
> +
> +/* ECC CURVE PARAMS */
> +/* 128 bits */
> +static const unsigned char ecdh_p128_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF
> +};
> +static const unsigned char ecdh_p128_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFC
> +};
> +static const unsigned char ecdh_p128_b[] = {
> +       0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24,
> +0x99,
> 0x3C,
> +       0x2C, 0xEE, 0x5E, 0xD3
> +};
> +static const unsigned char ecdh_p128_x[] = {
> +       0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28,
> +0x60,
> 0x7C,
> +       0xA5, 0x2C, 0x5B, 0x86
> +};
> +static const unsigned char ecdh_p128_y[] = {
> +       0xcf, 0x5a, 0xc8, 0x39, 0x5b, 0xaf, 0xeb, 0x13, 0xc0, 0x2d,
> +0xa2,
> 0x92,
> +       0xdd, 0xed, 0x7a, 0x83
> +};
> +static const unsigned char ecdh_p128_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3,
> +0x0D,
> 0x1B,
> +       0x90, 0x38, 0xA1, 0x15
> +};
> +
> +/* 192 bits */
> +static const unsigned char ecdh_p192_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF
> +};
> +static const unsigned char ecdh_p192_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFC
> +};
> +static const unsigned char ecdh_p192_b[] = {
> +       0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7,
> +0xE9,
> 0xAB,
> +       0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46,
> +0xB9,
> 0xB1
> +};
> +static const unsigned char ecdh_p192_x[] = {
> +       0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF,
> +0x20,
> 0xEB,
> +       0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF,
> +0x10,
> 0x12
> +};
> +static const unsigned char ecdh_p192_y[] = {
> +       0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10,
> +0x11,
> 0xed,
> +       0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79,
> +0x48,
> 0x11
> +};
> +static const unsigned char ecdh_p192_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2,
> +0x28,
> 0x31
> +};
> +
> +/* 224 bits */
> +static const unsigned char ecdh_p224_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x01
> +};
> +static const unsigned char ecdh_p224_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFE
> +};
> +static const unsigned char ecdh_p224_b[] = {
> +       0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41,
> +0x32,
> 0x56,
> +       0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B,
> +0x39,
> 0x43,
> +       0x23, 0x55, 0xFF, 0xB4
> +};
> +static const unsigned char ecdh_p224_x[] = {
> +       0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13,
> +0x90,
> 0xB9,
> +       0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32,
> +0x80,
> 0xD6,
> +       0x11, 0x5C, 0x1D, 0x21
> +};
> +static const unsigned char ecdh_p224_y[] = {
> +       0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22,
> +0xdf,
> 0xe6,
> +       0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5,
> +0x81,
> 0x99,
> +       0x85, 0x00, 0x7e, 0x34
> +};
> +static const unsigned char ecdh_p224_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD,
> +0x29,
> 0x45,
> +       0x5C, 0x5C, 0x2A, 0x3D
> +};
> +
> +/* 256 bits */
> +static const unsigned char ecdh_p256_p[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
> +0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const
> +unsigned char ecdh_p256_a[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
> +0x00,
> 0x00,
> +       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC }; static const
> +unsigned char ecdh_p256_b[] = {
> +       0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB,
> +0xBD,
> 0x55,
> +       0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53,
> +0xB0,
> 0xF6,
> +       0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B }; static const
> +unsigned char ecdh_p256_x[] = {
> +       0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC,
> +0xE6,
> 0xE5,
> +       0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB,
> +0x33,
> 0xA0,
> +       0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 }; static const
> +unsigned char ecdh_p256_y[] = {
> +       0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7,
> +0xeb,
> 0x4a,
> +       0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
> +0x5e,
> 0xce,
> +       0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 }; static const
> +unsigned char ecdh_p256_n[] = {
> +       0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17,
> +0x9E,
> 0x84,
> +       0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };

Do we really need to re-define the parameters? crypto/ecc_curve_defs.h already contains P-192 and P-256.

If we want more curves, I would like to suggest to keep them all at one common place.
> +
> +/* 320 bits */
> +static const unsigned char ecdh_p320_p[] = {
> +       0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C,
> +0x78,
> 0x5E,
> +       0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4,
> +0x0D,
> 0xEF,
> +       0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, 0xFC, 0xD4,
> +0x12,
> 0xB1,
> +       0xF1, 0xB3, 0x2E, 0x27
> +};
> +static const unsigned char ecdh_p320_a[] = {
> +       0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC,
> +0xEB,
> 0xD4,
> +       0x6D, 0x3F, 0x3B, 0xB8, 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB,
> +0x79,
> 0xDA,
> +       0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, 0x92, 0xF3,
> +0x75,
> 0xA9,
> +       0x7D, 0x86, 0x0E, 0xB4
> +};
> +static const unsigned char ecdh_p320_b[] = {
> +       0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD,
> +0x19,
> 0x86,
> +       0x40, 0x68, 0x8A, 0x6F, 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54,
> +0xB4,
> 0x9A,
> +       0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, 0x6F, 0x5E,
> +0xB4,
> 0xAC,
> +       0x8F, 0xB1, 0xF1, 0xA6
> +};
> +static const unsigned char ecdh_p320_x[] = {
> +       0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89,
> +0xBC,
> 0xC4,
> +       0x8E, 0xE5, 0xBF, 0xE6, 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08,
> +0x7E,
> 0xB6,
> +       0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, 0x10, 0xAF,
> +0x8D,
> 0x0D,
> +       0x39, 0xE2, 0x06, 0x11
> +};
> +static const unsigned char ecdh_p320_y[] = {
> +       0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40,
> +0x93,
> 0x24,
> +       0x7F, 0x77, 0x27, 0x5E, 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71,
> +0x82,
> 0xEA,
> +       0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, 0xD3, 0x52,
> +0x45,
> 0xD1,
> +       0x69, 0x2E, 0x8E, 0xE1
> +};
> +static const unsigned char ecdh_p320_n[] = {
> +       0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C,
> +0x78,
> 0x5E,
> +       0xD2, 0x01, 0xE0, 0x65, 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F,
> +0x12,
> 0xA3,
> +       0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, 0x86, 0x91,
> +0x55,
> 0x5B,
> +       0x44, 0xC5, 0x93, 0x11
> +};
> +
> +/* 384 bits */
> +static const unsigned char ecdh_p384_p[] = {
> +       0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D,
> +0x6F,
> 0x7E,
> +       0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54,
> +0x56,
> 0xB4,
> +       0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, 0xAC, 0xD3,
> +0xA7,
> 0x29,
> +       0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07,
> +0xEC,
> 0x53
> +};
> +static const unsigned char ecdh_p384_a[] = {
> +       0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72,
> +0x08,
> 0x0A,
> +       0xCE, 0x05, 0xAF, 0xA0, 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2,
> +0x27,
> 0x87,
> +       0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, 0x8A, 0xA5,
> +0x81,
> 0x4A,
> +       0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE,
> +0x28,
> 0x26
> +};
> +static const unsigned char ecdh_p384_b[] = {
> +       0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39,
> +0xB5,
> 0x54,
> +       0x16, 0xF0, 0x44, 0x7C, 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC,
> +0xD2,
> 0xA6,
> +       0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, 0x7C, 0xB4,
> +0x39,
> 0x02,
> +       0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50,
> +0x4C,
> 0x11
> +};
> +static const unsigned char ecdh_p384_x[] = {
> +       0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6,
> +0x3A,
> 0x81,
> +       0xB7, 0xC1, 0x3F, 0x6B, 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1,
> +0x4F,
> 0xE3,
> +       0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, 0xE8, 0x26,
> +0xE0,
> 0x34,
> +       0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4,
> +0xAF,
> 0x1E
> +};
> +static const unsigned char ecdh_p384_y[] = {
> +       0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1,
> +0xEB,
> 0x8E,
> +       0x95, 0xCF, 0xD5, 0x52, 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC,
> +0x58,
> 0x64,
> +       0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, 0x0E, 0x46,
> +0x46,
> 0x21,
> +       0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C,
> +0x53,
> 0x15
> +};
> +static const unsigned char ecdh_p384_n[] = {
> +       0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D,
> +0x6F,
> 0x7E,
> +       0x50, 0xE6, 0x41, 0xDF, 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54,
> +0x56,
> 0xB3,
> +       0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, 0xCF, 0x3A,
> +0xB6,
> 0xAF,
> +       0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04,
> +0x65,
> 0x65
> +};
> +
> +/* 521 bits */
> +static const unsigned char ecdh_p521_p[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const unsigned
> +char ecdh_p521_a[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC }; static const unsigned
> +char ecdh_p521_b[] = {
> +       0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F,
> +0x92,
> 0x9A,
> +       0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B,
> +0x99,
> 0xB3,
> +       0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1,
> +0x56,
> 0x19,
> +       0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD,
> +0x3B,
> 0xB1,
> +       0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1,
> +0xEF,
> 0x45,
> +       0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 }; static const unsigned
> +char ecdh_p521_x[] = {
> +       0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD,
> +0x9E,
> 0x3E,
> +       0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39,
> +0x05,
> 0x3F,
> +       0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA,
> +0xA1,
> 0x4B,
> +       0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27,
> +0xA2,
> 0xFF,
> +       0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B,
> +0xF9,
> 0x7E,
> +       0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 }; static const unsigned
> +char ecdh_p521_y[] = {
> +       0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04,
> +0x5c,
> 0x8a,
> +       0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49,
> +0x57,
> 0x9b,
> +       0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c,
> +0x97,
> 0xee,
> +       0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01,
> +0x3f,
> 0xad,
> +       0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40,
> +0x88,
> 0xbe,
> +       0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50 }; static const unsigned
> +char ecdh_p521_n[] = {
> +       0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
> +0xFF,
> 0xFF,
> +       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA,
> +0x51,
> 0x86,
> +       0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48,
> +0xF7,
> 0x09,
> +       0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE,
> +0xBB,
> 0x6F,
> +       0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
> +
> +static const struct curve_param_desc ecdh_curve_list[] = {
> +       {
> +               .id = ECC_CURVE_NIST_P192,
> +               .p = ecdh_p192_p,
> +               .a = ecdh_p192_a,
> +               .b = ecdh_p192_b,
> +               .gx = ecdh_p192_x,
> +               .gy = ecdh_p192_y,
> +               .n = ecdh_p192_n,
> +       }, {
> +               .id = ECC_CURVE_NIST_P256,
> +               .p = ecdh_p256_p,
> +               .a = ecdh_p256_a,
> +               .b = ecdh_p256_b,
> +               .gx = ecdh_p256_x,
> +               .gy = ecdh_p256_y,
> +               .n = ecdh_p256_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P128,
> +               .p = ecdh_p128_p,
> +               .a = ecdh_p128_a,
> +               .b = ecdh_p128_b,
> +               .gx = ecdh_p128_x,
> +               .gy = ecdh_p128_y,
> +               .n = ecdh_p128_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P320,
> +               .p = ecdh_p320_p,
> +               .a = ecdh_p320_a,
> +               .b = ecdh_p320_b,
> +               .gx = ecdh_p320_x,
> +               .gy = ecdh_p320_y,
> +               .n = ecdh_p320_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P384,
> +               .p = ecdh_p384_p,
> +               .a = ecdh_p384_a,
> +               .b = ecdh_p384_b,
> +               .gx = ecdh_p384_x,
> +               .gy = ecdh_p384_y,
> +               .n = ecdh_p384_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P521,
> +               .p = ecdh_p521_p,
> +               .a = ecdh_p521_a,
> +               .b = ecdh_p521_b,
> +               .gx = ecdh_p521_x,
> +               .gy = ecdh_p521_y,
> +               .n = ecdh_p521_n,
> +       }, {
> +               .id = HPRE_ECC_CURVE_NIST_P224,
> +               .p = ecdh_p224_p,
> +               .a = ecdh_p224_a,
> +               .b = ecdh_p224_b,
> +               .gx = ecdh_p224_x,
> +               .gy = ecdh_p224_y,
> +               .n = ecdh_p224_n,
> +       }
> +};
> +
>  typedef void (*hpre_cb)(struct hpre_ctx *ctx, void *sqe);
>  
>  struct hpre_rsa_ctx {
> @@ -61,14 +398,25 @@ struct hpre_dh_ctx {
>          * else if base if the counterpart public key we
>          * compute the shared secret
>          *      ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
> +        * low address: d--->n, please refer to Hisilicon HPRE UM
>          */
> -       char *xa_p; /* low address: d--->n, please refer to Hisilicon
> HPRE UM */
> +       char *xa_p;
>         dma_addr_t dma_xa_p;
>  
>         char *g; /* m */
>         dma_addr_t dma_g;
>  };
>  
> +struct hpre_ecdh_ctx {
> +       /* low address: p->a->k->b */
> +       unsigned char *p;
> +       dma_addr_t dma_p;
> +
> +       /* low address: x->y */
> +       unsigned char *g;
> +       dma_addr_t dma_g;
> +};
> +
>  struct hpre_ctx {
>         struct hisi_qp *qp;
>         struct hpre_asym_request **req_list; @@ -80,7 +428,10 @@
> struct hpre_ctx {
>         union {
>                 struct hpre_rsa_ctx rsa;
>                 struct hpre_dh_ctx dh;
> +               struct hpre_ecdh_ctx ecdh;
>         };
> +       /* for ecc algorithms */
> +       unsigned int curve_id;
>  };
>  
>  struct hpre_asym_request {
> @@ -91,6 +442,7 @@ struct hpre_asym_request {
>         union {
>                 struct akcipher_request *rsa;
>                 struct kpp_request *dh;
> +               struct kpp_request *ecdh;
>         } areq;
>         int err;
>         int req_id;
> @@ -1115,6 +1467,416 @@ static void hpre_rsa_exit_tfm(struct
> crypto_akcipher
> *tfm)
>         crypto_free_akcipher(ctx->rsa.soft_tfm);
>  }
>  
> +static void hpre_ecc_clear_ctx(struct hpre_ctx *ctx, bool
> +is_clear_all,
> +                              bool is_ecdh) {
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz = ctx->key_sz;
> +       unsigned int shift = sz << 1;
> +
> +       if (is_clear_all)
> +               hisi_qm_stop_qp(ctx->qp);
> +
> +       if (is_ecdh && ctx->ecdh.p) {
> +               /* ecdh: p->a->k->b */
> +               memzero_explicit(ctx->ecdh.p + shift, sz);
> +               dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx-
> >ecdh.dma_p);
> +               ctx->ecdh.p = NULL;
> +       }
> +
> +       ctx->curve_id = 0;
> +       hpre_ctx_clear(ctx, is_clear_all); }
> +
> +/*
> + * only the bits of 128/192/224/256/320/384/521 are supported by
> +HPRE,
> + * and convert the bits like:
> + * bits<=256, bits=256; 256<bits<=384, bits=384; 384<bits<=576,
> +bits=576;
> + * If the parameter bit width is insufficient, then we fill in the
> + * high-order zeros by soft, so TASK_LENGTH1 is 0x3/0x5/0x8; */
> +static unsigned int hpre_ecdh_supported_curve(unsigned int curve_id)
> +{
> +       switch (curve_id) {
> +       case ECC_CURVE_NIST_P192:
> +       case ECC_CURVE_NIST_P256:
> +       case HPRE_ECC_CURVE_NIST_P128:
> +       case HPRE_ECC_CURVE_NIST_P224:
> +               return HPRE_ECC_HW256_KSZ_B;
> +       case HPRE_ECC_CURVE_NIST_P320:
> +       case HPRE_ECC_CURVE_NIST_P384:
> +               return HPRE_ECC_HW384_KSZ_B;
> +       case HPRE_ECC_CURVE_NIST_P521:
> +               return HPRE_ECC_HW576_KSZ_B;
> +       default:
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static const struct curve_param_desc *ecdh_get_curve_param(__u32
> +curve_id) {
> +       if (curve_id >= 1 && curve_id <= ARRAY_SIZE(ecdh_curve_list))
> +               return &ecdh_curve_list[curve_id - 1];
> +
> +       return NULL;
> +}
> +
> +static int hpre_ecdh_fill_curve(struct hpre_ctx *ctx, struct ecdh
> +*params,
> +                               unsigned int cur_sz) {
> +       unsigned int shifta = ctx->key_sz << 1;
> +       unsigned int shiftb = ctx->key_sz << 2;
> +       void *p = ctx->ecdh.p + ctx->key_sz - cur_sz;
> +       void *a = ctx->ecdh.p + shifta - cur_sz;
> +       void *b = ctx->ecdh.p + shiftb - cur_sz;
> +       void *x = ctx->ecdh.g + ctx->key_sz - cur_sz;
> +       void *y = ctx->ecdh.g + shifta - cur_sz;
> +       const struct curve_param_desc *curve;
> +       char *n;
> +
> +       n = kzalloc(ctx->key_sz, GFP_KERNEL);
> +       if (!n)
> +               return -ENOMEM;
> +
> +       curve = ecdh_get_curve_param(params->curve_id);
> +       if (!curve)
> +               goto free;
> +
> +       memcpy(p, curve->p, cur_sz);
> +       memcpy(a, curve->a, cur_sz);
> +       memcpy(b, curve->b, cur_sz);
> +       memcpy(x, curve->gx, cur_sz);
> +       memcpy(y, curve->gy, cur_sz);
> +       memcpy(n, curve->n, cur_sz);
> +
> +       if (params->key_size == cur_sz && strcmp(params->key, n) >= 0)
> +               goto free;
> +
> +       kfree(n);
> +       return 0;
> +
> +free:
> +       kfree(n);
> +       return -EINVAL;
> +}
> +
> +static unsigned int hpre_ecdh_get_curvesz(unsigned short id) {
> +       switch (id) {
> +       case ECC_CURVE_NIST_P192:
> +               return HPRE_ECC_NIST_P192_N_SIZE;
> +       case ECC_CURVE_NIST_P256:
> +               return HPRE_ECC_NIST_P256_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P128:
> +               return HPRE_ECC_NIST_P128_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P224:
> +               return HPRE_ECC_NIST_P224_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P320:
> +               return HPRE_ECC_NIST_P320_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P384:
> +               return HPRE_ECC_NIST_P384_N_SIZE;
> +       case HPRE_ECC_CURVE_NIST_P521:
> +               return HPRE_ECC_NIST_P521_N_SIZE;
> +       default:
> +               break;
> +       }
> +
> +       return 0;
> +}
> +
> +static int hpre_ecdh_set_param(struct hpre_ctx *ctx, struct ecdh
> +*params) {
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz, shift, curve_sz;
> +       int ret;
> +
> +       ctx->key_sz = hpre_ecdh_supported_curve(params->curve_id);
> +       if (!ctx->key_sz)
> +               return -EINVAL;
> +
> +       curve_sz = hpre_ecdh_get_curvesz(params->curve_id);
> +       if (!curve_sz || params->key_size > curve_sz)
> +               return -EINVAL;
> +
> +       sz = ctx->key_sz;
> +       ctx->curve_id = params->curve_id;
> +
> +       if (!ctx->ecdh.p) {
> +               ctx->ecdh.p = dma_alloc_coherent(dev, sz << 3, &ctx-
> >ecdh.dma_p,
> +                                                GFP_KERNEL);
> +               if (!ctx->ecdh.p)
> +                       return -ENOMEM;
> +       }
> +
> +       shift = sz << 2;
> +       ctx->ecdh.g = ctx->ecdh.p + shift;
> +       ctx->ecdh.dma_g = ctx->ecdh.dma_p + shift;
> +
> +       ret = hpre_ecdh_fill_curve(ctx, params, curve_sz);
> +       if (ret) {
> +               dma_free_coherent(dev, sz << 3, ctx->ecdh.p, ctx-
> >ecdh.dma_p);
> +               dev_err(dev, "failed to fill curve_param, ret =
> +%d!\n",
> ret);
> +               return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static bool hpre_key_is_valid(char *key, unsigned short key_sz) {
> +       int i;
> +
> +       for (i = 0; i < key_sz; i++)
> +               if (key[i])
> +                       return true;
> +
> +       return false;
> +}
> +
> +static int hpre_ecdh_set_secret(struct crypto_kpp *tfm, const void
> +*buf,
> +                               unsigned int len) {
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int sz, sz_shift;
> +       struct ecdh params;
> +       int ret;
> +
> +       if (crypto_ecdh_decode_key(buf, len, &params) < 0) {
> +               dev_err(dev, "failed to decode ecdh key!\n");
> +               return -EINVAL;
> +       }
> +
> +       if (!hpre_key_is_valid(params.key, params.key_size)) {
> +               dev_err(dev, "Invalid hpre key!\n");
> +               return -EINVAL;
> +       }
> +
> +       hpre_ecc_clear_ctx(ctx, false, true);
> +
> +       ret = hpre_ecdh_set_param(ctx, &params);
> +       if (ret < 0) {
> +               dev_err(dev, "failed to set hpre param, ret = %d!\n",
> +ret);
> +               goto err_clear_ctx;
> +       }
> +
> +       sz = ctx->key_sz;
> +       sz_shift = (sz << 1) + sz - params.key_size;
> +       memcpy(ctx->ecdh.p + sz_shift, params.key, params.key_size);
> +       return 0;
> +
> +err_clear_ctx:
> +       hpre_ecc_clear_ctx(ctx, false, true);
> +       return ret;
> +}
> +
> +static void hpre_ecdh_hw_data_clr_all(struct hpre_ctx *ctx,
> +                                     struct hpre_asym_request *req,
> +                                     struct scatterlist *dst,
> +                                     struct scatterlist *src) {
> +       struct device *dev = HPRE_DEV(ctx);
> +       struct hpre_sqe *sqe = &req->req;
> +       dma_addr_t dma;
> +
> +       dma = le64_to_cpu(sqe->in);
> +       if (unlikely(!dma))
> +               return;
> +
> +       if (src && req->src)
> +               dma_free_coherent(dev, ctx->key_sz << 2, req->src,
> +dma);
> +
> +       dma = le64_to_cpu(sqe->out);
> +       if (unlikely(!dma))
> +               return;
> +
> +       if (req->dst)
> +               dma_free_coherent(dev, ctx->key_sz << 1, req->dst,
> +dma);
> +       if (dst)
> +               dma_unmap_single(dev, dma, ctx->key_sz << 1,
> DMA_FROM_DEVICE);
> +}
> +
> +static void hpre_ecdh_cb(struct hpre_ctx *ctx, void *resp) {
> +       struct hpre_dfx *dfx = ctx->hpre->debug.dfx;
> +       struct hpre_asym_request *req = NULL;
> +       struct kpp_request *areq;
> +       u64 overtime_thrhld;
> +       int ret;
> +
> +       ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
> +       areq = req->areq.ecdh;
> +       areq->dst_len = ctx->key_sz << 1;
> +
> +       overtime_thrhld =
> +atomic64_read(&dfx[HPRE_OVERTIME_THRHLD].value);
> +       if (overtime_thrhld && hpre_is_bd_timeout(req,
> +overtime_thrhld))
> +               atomic64_inc(&dfx[HPRE_OVER_THRHLD_CNT].value);
> +
> +       hpre_ecdh_hw_data_clr_all(ctx, req, areq->dst, areq->src);
> +       kpp_request_complete(areq, ret);
> +
> +       atomic64_inc(&dfx[HPRE_RECV_CNT].value);
> +}
> +
> +static int hpre_ecdh_msg_request_set(struct hpre_ctx *ctx,
> +                                    struct kpp_request *req) {
> +       struct hpre_asym_request *h_req;
> +       struct hpre_sqe *msg;
> +       int req_id;
> +       void *tmp;
> +
> +       if (req->dst_len < ctx->key_sz << 1) {
> +               req->dst_len = ctx->key_sz << 1;
> +               return -EINVAL;
> +       }
> +
> +       tmp = kpp_request_ctx(req);
> +       h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
> +       h_req->cb = hpre_ecdh_cb;
> +       h_req->areq.ecdh = req;
> +       msg = &h_req->req;
> +       memset(msg, 0, sizeof(*msg));
> +       msg->key = cpu_to_le64(ctx->ecdh.dma_p);
> +
> +       msg->dw0 |= cpu_to_le32(0x1U << HPRE_SQE_DONE_SHIFT);
> +       msg->task_len1 = (ctx->key_sz >> HPRE_BITS_2_BYTES_SHIFT) - 1;
> +       h_req->ctx = ctx;
> +
> +       req_id = hpre_add_req_to_ctx(h_req);
> +       if (req_id < 0)
> +               return -EBUSY;
> +
> +       msg->tag = cpu_to_le16((u16)req_id);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_src_data_init(struct hpre_asym_request
> +*hpre_req,
> +                                  struct scatterlist *data, unsigned
> +int
> len)
> +{
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       struct hpre_ctx *ctx = hpre_req->ctx;
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int tmpshift;
> +       dma_addr_t dma = 0;
> +       void *ptr;
> +       int shift;
> +
> +       /* Src_data include gx and gy. */
> +       shift = ctx->key_sz - (len >> 1);
> +       if (unlikely(shift < 0))
> +               return -EINVAL;
> +
> +       ptr = dma_alloc_coherent(dev, ctx->key_sz << 2, &dma,
> +GFP_KERNEL);
> +       if (unlikely(!ptr))
> +               return -ENOMEM;
> +
> +       tmpshift = ctx->key_sz << 1;
> +       scatterwalk_map_and_copy(ptr + tmpshift, data, 0, len, 0);
> +       memcpy(ptr + shift, ptr + tmpshift, len >> 1);
> +       memcpy(ptr + ctx->key_sz + shift, ptr + tmpshift + (len >> 1),
> +len
> >> 1);
> +
> +       hpre_req->src = ptr;
> +       msg->in = cpu_to_le64(dma);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_dst_data_init(struct hpre_asym_request
> +*hpre_req,
> +                                  struct scatterlist *data, unsigned
> +int
> len)
> +{
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       struct hpre_ctx *ctx = hpre_req->ctx;
> +       struct device *dev = HPRE_DEV(ctx);
> +       unsigned int dst_len;
> +       dma_addr_t dma = 0;
> +       void *ptr;
> +
> +       if (sg_is_last(data)) {
> +               hpre_req->dst = NULL;
> +               dma = dma_map_single(dev, sg_virt(data), len,
> DMA_FROM_DEVICE);
> +               if (unlikely(dma_mapping_error(dev, dma))) {
> +                       dev_err(dev, "dma map data err!\n");
> +                       return -ENOMEM;
> +               }
> +       } else {
> +               dst_len = ctx->key_sz << 1;
> +               ptr = dma_alloc_coherent(dev, dst_len, &dma,
> +GFP_KERNEL);
> +               if (unlikely(!ptr))
> +                       return -ENOMEM;
> +               hpre_req->dst = ptr;
> +       }
> +
> +       msg->out = cpu_to_le64(dma);
> +       return 0;
> +}
> +
> +static int hpre_ecdh_compute_value(struct kpp_request *req) {
> +       struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +       struct device *dev = HPRE_DEV(ctx);
> +       void *tmp = kpp_request_ctx(req);
> +       struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp,
> +HPRE_ALIGN_SZ);
> +       struct hpre_sqe *msg = &hpre_req->req;
> +       int ret;
> +
> +       ret = hpre_ecdh_msg_request_set(ctx, req);
> +       if (unlikely(ret)) {
> +               dev_err(dev, "failed to set ecdh request, ret =
> +%d!\n",
> ret);
> +               return ret;
> +       }
> +
> +       if (req->src) {
> +               ret = hpre_ecdh_src_data_init(hpre_req, req->src, req-
> >src_len);
> +               if (unlikely(ret)) {
> +                       dev_err(dev, "failed to init src data, ret =
> +%d!\n",
> ret);
> +                       goto clear_all;
> +               }
> +       } else {
> +               msg->in = cpu_to_le64(ctx->ecdh.dma_g);
> +       }
> +
> +       ret = hpre_ecdh_dst_data_init(hpre_req, req->dst,
> +req->dst_len);
> +       if (unlikely(ret)) {
> +               dev_err(dev, "failed to init dst data, ret = %d!\n",
> +ret);
> +               goto clear_all;
> +       }
> +
> +       msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) |
> +HPRE_ALG_ECC_MUL);
> +       ret = hpre_send(ctx, msg);
> +       if (likely(!ret))
> +               return -EINPROGRESS;
> +
> +clear_all:
> +       hpre_rm_req_from_ctx(hpre_req);
> +       hpre_ecdh_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
> +       return ret;
> +}
> +
> +static unsigned int hpre_ecdh_max_size(struct crypto_kpp *tfm) {
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       /* max size is the pub_key_size, include x and y */
> +       return ctx->key_sz << 1;
> +}
> +
> +static int hpre_ecdh_init_tfm(struct crypto_kpp *tfm) {
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       return hpre_ctx_init(ctx, HPRE_V3_ECC_ALG_TYPE); }
> +
> +static void hpre_ecdh_exit_tfm(struct crypto_kpp *tfm) {
> +       struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
> +
> +       hpre_ecc_clear_ctx(ctx, true, true); }
> +
>  static struct akcipher_alg rsa = {
>         .sign = hpre_rsa_dec,
>         .verify = hpre_rsa_enc,
> @@ -1154,6 +1916,22 @@ static struct kpp_alg dh = {
>  };
>  #endif
>  
> +static struct kpp_alg ecdh = {
> +       .set_secret = hpre_ecdh_set_secret,
> +       .generate_public_key = hpre_ecdh_compute_value,
> +       .compute_shared_secret = hpre_ecdh_compute_value,
> +       .max_size = hpre_ecdh_max_size,
> +       .init = hpre_ecdh_init_tfm,
> +       .exit = hpre_ecdh_exit_tfm,
> +       .reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
> +       .base = {
> +               .cra_ctxsize = sizeof(struct hpre_ctx),
> +               .cra_priority = HPRE_CRYPTO_ALG_PRI,
> +               .cra_name = "ecdh",
> +               .cra_driver_name = "hpre-ecdh",
> +               .cra_module = THIS_MODULE,
> +       },
> +};
>  int hpre_algs_register(struct hisi_qm *qm)
>  {
>         int ret;
> @@ -1164,17 +1942,33 @@ int hpre_algs_register(struct hisi_qm *qm)
>                 return ret;
>  #ifdef CONFIG_CRYPTO_DH
>         ret = crypto_register_kpp(&dh);
> -       if (ret)
> +       if (ret) {
>                 crypto_unregister_akcipher(&rsa);
> +               return ret;
> +       }
>  #endif
>  
> -       return ret;
> +       if (qm->ver >= QM_HW_V3) {
> +               ret = crypto_register_kpp(&ecdh);
> +               if (ret) {
> +#ifdef CONFIG_CRYPTO_DH
> +                       crypto_unregister_kpp(&dh); #endif
> +                       crypto_unregister_akcipher(&rsa);
> +                       return ret;
> +               }
> +       }
> +
> +       return 0;
>  }
>  
>  void hpre_algs_unregister(struct hisi_qm *qm)
>  {
> -       crypto_unregister_akcipher(&rsa);
> +       if (qm->ver >= QM_HW_V3)
> +               crypto_unregister_kpp(&ecdh);
> +
>  #ifdef CONFIG_CRYPTO_DH
>         crypto_unregister_kpp(&dh);
>  #endif
> +       crypto_unregister_akcipher(&rsa);
>  }
> diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c
> b/drivers/crypto/hisilicon/hpre/hpre_main.c
> index 1ae8fa1..2ccc3dc 100644
> --- a/drivers/crypto/hisilicon/hpre/hpre_main.c
> +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c
> @@ -1020,4 +1020,5 @@ module_exit(hpre_exit);
>  
>  MODULE_LICENSE("GPL v2");
>  MODULE_AUTHOR("Zaibo Xu <[email protected]>");
> +MODULE_AUTHOR("Meng Yu <[email protected]>");
>  MODULE_DESCRIPTION("Driver for HiSilicon HPRE accelerator");