core: crypto add support for SM2 DSA

Adds SM2 Digital Signature Algorithm [1] using LibTomCrypt. The TA
interface complies with the GlobalPlatform TEE Internal Core API
version 1.2.

SM2 DSA is enabled with CFG_CRYPTO_SM2_DSA=y (default y) which currently
requires that CFG_CRYPTOLIB_NAME=tomcrypt. An Mbed TLS implementation
could be added later if needed.

[1] http://www.gmbz.org.cn/main/postDetail.html?id=20180724110812

Signed-off-by: Jerome Forissier <jerome@forissier.org>
Acked-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/core/crypto.mk b/core/crypto.mk
index d7b5a07..0fdbac6 100644
--- a/core/crypto.mk
+++ b/core/crypto.mk
@@ -41,10 +41,14 @@
 CFG_CRYPTO_ECC ?= y
 ifeq ($(CFG_CRYPTOLIB_NAME),tomcrypt)
 CFG_CRYPTO_SM2_PKE ?= y
+CFG_CRYPTO_SM2_DSA ?= y
 endif
 ifeq ($(CFG_CRYPTOLIB_NAME)-$(CFG_CRYPTO_SM2_PKE),mbedtls-y)
 $(error Error: CFG_CRYPTO_SM2_PKE=y requires CFG_CRYPTOLIB_NAME=tomcrypt)
 endif
+ifeq ($(CFG_CRYPTOLIB_NAME)-$(CFG_CRYPTO_SM2_DSA),mbedtls-y)
+$(error Error: CFG_CRYPTO_SM2_DSA=y requires CFG_CRYPTOLIB_NAME=tomcrypt)
+endif
 
 # Authenticated encryption
 CFG_CRYPTO_CCM ?= y
@@ -137,6 +141,7 @@
 $(eval $(call cryp-dep-one, DES, ECB CBC))
 # SM2 is Elliptic Curve Cryptography, it uses some generic ECC functions
 $(eval $(call cryp-dep-one, SM2_PKE, ECC))
+$(eval $(call cryp-dep-one, SM2_DSA, ECC))
 
 ###############################################################
 # libtomcrypt (LTC) specifics, phase #1
@@ -168,6 +173,7 @@
 core-ltc-vars += SHA256_ARM32_CE SHA256_ARM64_CE
 core-ltc-vars += SIZE_OPTIMIZATION
 core-ltc-vars += SM2_PKE
+core-ltc-vars += SM2_DSA
 # Assigned selected CFG_CRYPTO_xxx as _CFG_CORE_LTC_xxx
 $(foreach v, $(core-ltc-vars), $(eval _CFG_CORE_LTC_$(v) := $(CFG_CRYPTO_$(v))))
 _CFG_CORE_LTC_MPI := $(CFG_CORE_MBEDTLS_MPI)
diff --git a/core/crypto/crypto.c b/core/crypto/crypto.c
index eeaa269..578514d 100644
--- a/core/crypto/crypto.c
+++ b/core/crypto/crypto.c
@@ -711,3 +711,25 @@
 	return TEE_ERROR_NOT_IMPLEMENTED;
 }
 #endif /* !CFG_CRYPTO_SM2_PKE */
+
+#if !defined(CFG_CRYPTO_SM2_DSA)
+TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo __unused,
+				       struct ecc_keypair *key __unused,
+				       const uint8_t *msg __unused,
+				       size_t msg_len __unused,
+				       uint8_t *sig __unused,
+				       size_t *sig_len __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo __unused,
+					 struct ecc_public_key *key __unused,
+					 const uint8_t *msg __unused,
+					 size_t msg_len __unused,
+					 const uint8_t *sig __unused,
+					 size_t sig_len __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+#endif /* !CFG_CRYPTO_SM2_DSA */
diff --git a/core/include/crypto/crypto.h b/core/include/crypto/crypto.h
index 7da7446..e913875 100644
--- a/core/include/crypto/crypto.h
+++ b/core/include/crypto/crypto.h
@@ -244,6 +244,13 @@
 TEE_Result crypto_acipher_sm2_pke_encrypt(struct ecc_public_key *key,
 					  const uint8_t *src, size_t src_len,
 					  uint8_t *dst, size_t *dst_len);
+TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo, struct ecc_keypair *key,
+				       const uint8_t *msg, size_t msg_len,
+				       uint8_t *sig, size_t *sig_len);
+TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo,
+					 struct ecc_public_key *key,
+					 const uint8_t *msg, size_t msg_len,
+					 const uint8_t *sig, size_t sig_len);
 
 /*
  * Verifies a SHA-256 hash, doesn't require crypto_init() to be called in
diff --git a/core/lib/libtomcrypt/ecc.c b/core/lib/libtomcrypt/ecc.c
index 051da77..92d773a 100644
--- a/core/lib/libtomcrypt/ecc.c
+++ b/core/lib/libtomcrypt/ecc.c
@@ -128,7 +128,8 @@
 		size_bits = 256;
 		size_bytes = 32;
 		name = "SM2";
-		if ((algo != 0) && (algo != TEE_ALG_SM2_PKE))
+		if ((algo != 0) && (algo != TEE_ALG_SM2_PKE) &&
+		    (algo != TEE_ALG_SM2_DSA_SM3))
 			return TEE_ERROR_BAD_PARAMETERS;
 		break;
 	default:
diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c
index 622fd29..17d8dec 100644
--- a/core/tee/tee_svc_cryp.c
+++ b/core/tee/tee_svc_cryp.c
@@ -487,6 +487,14 @@
 		sizeof(struct ecc_keypair),
 		tee_cryp_obj_ecc_keypair_attrs),
 
+	PROP(TEE_TYPE_SM2_DSA_PUBLIC_KEY, 1, 256, 256,
+	     sizeof(struct ecc_public_key),
+	     tee_cryp_obj_ecc_pub_key_attrs),
+
+	PROP(TEE_TYPE_SM2_DSA_KEYPAIR, 1, 256, 256,
+	     sizeof(struct ecc_keypair),
+	     tee_cryp_obj_ecc_keypair_attrs),
+
 	PROP(TEE_TYPE_SM2_PKE_PUBLIC_KEY, 1, 256, 256,
 	     sizeof(struct ecc_public_key),
 	     tee_cryp_obj_ecc_pub_key_attrs),
@@ -1145,6 +1153,9 @@
 		} else if (o->info.objectType == TEE_TYPE_ECDH_PUBLIC_KEY) {
 			if (src->info.objectType != TEE_TYPE_ECDH_KEYPAIR)
 				return TEE_ERROR_BAD_PARAMETERS;
+		} else if (o->info.objectType == TEE_TYPE_SM2_DSA_PUBLIC_KEY) {
+			if (src->info.objectType != TEE_TYPE_SM2_DSA_KEYPAIR)
+				return TEE_ERROR_BAD_PARAMETERS;
 		} else if (o->info.objectType == TEE_TYPE_SM2_PKE_PUBLIC_KEY) {
 			if (src->info.objectType != TEE_TYPE_SM2_PKE_KEYPAIR)
 				return TEE_ERROR_BAD_PARAMETERS;
@@ -1236,12 +1247,14 @@
 		break;
 	case TEE_TYPE_ECDSA_PUBLIC_KEY:
 	case TEE_TYPE_ECDH_PUBLIC_KEY:
+	case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
 	case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
 		res = crypto_acipher_alloc_ecc_public_key(o->attr,
 							  max_key_size);
 		break;
 	case TEE_TYPE_ECDSA_KEYPAIR:
 	case TEE_TYPE_ECDH_KEYPAIR:
+	case TEE_TYPE_SM2_DSA_KEYPAIR:
 	case TEE_TYPE_SM2_PKE_KEYPAIR:
 		res = crypto_acipher_alloc_ecc_keypair(o->attr, max_key_size);
 		break;
@@ -2033,6 +2046,12 @@
 		else
 			req_key_type = TEE_TYPE_SM2_PKE_KEYPAIR;
 		break;
+	case TEE_MAIN_ALGO_SM2_DSA_SM3:
+		if (mode == TEE_MODE_VERIFY)
+			req_key_type = TEE_TYPE_SM2_DSA_PUBLIC_KEY;
+		else
+			req_key_type = TEE_TYPE_SM2_DSA_KEYPAIR;
+		break;
 #if defined(CFG_CRYPTO_HKDF)
 	case TEE_MAIN_ALGO_HKDF:
 		req_key_type = TEE_TYPE_HKDF_IKM;
@@ -3505,6 +3524,10 @@
 		res = crypto_acipher_ecc_sign(cs->algo, o->attr, src_data,
 					      src_len, dst_data, &dlen);
 		break;
+	case TEE_ALG_SM2_DSA_SM3:
+		res = crypto_acipher_sm2_dsa_sign(cs->algo, o->attr, src_data,
+						  src_len, dst_data, &dlen);
+		break;
 
 	default:
 		res = TEE_ERROR_BAD_PARAMETERS;
@@ -3628,6 +3651,11 @@
 						data_len, sig, sig_len);
 		break;
 
+	case TEE_MAIN_ALGO_SM2_DSA_SM3:
+		res = crypto_acipher_sm2_dsa_verify(cs->algo, o->attr, data,
+						    data_len, sig, sig_len);
+		break;
+
 	default:
 		res = TEE_ERROR_NOT_SUPPORTED;
 	}
diff --git a/lib/libutee/include/tee_api_defines.h b/lib/libutee/include/tee_api_defines.h
index d60c03b..fa64d3a 100644
--- a/lib/libutee/include/tee_api_defines.h
+++ b/lib/libutee/include/tee_api_defines.h
@@ -161,6 +161,7 @@
 #define TEE_ALG_DSA_SHA1                        0x70002131
 #define TEE_ALG_DSA_SHA224                      0x70003131
 #define TEE_ALG_DSA_SHA256                      0x70004131
+#define TEE_ALG_SM2_DSA_SM3                     0x70006045
 #define TEE_ALG_DH_DERIVE_SHARED_SECRET         0x80000032
 #define TEE_ALG_MD5                             0x50000001
 #define TEE_ALG_SHA1                            0x50000002
@@ -221,6 +222,8 @@
 #define TEE_TYPE_ECDSA_KEYPAIR              0xA1000041
 #define TEE_TYPE_ECDH_PUBLIC_KEY            0xA0000042
 #define TEE_TYPE_ECDH_KEYPAIR               0xA1000042
+#define TEE_TYPE_SM2_DSA_PUBLIC_KEY         0xA0000045
+#define TEE_TYPE_SM2_DSA_KEYPAIR            0xA1000045
 #define TEE_TYPE_SM2_PKE_PUBLIC_KEY         0xA0000047
 #define TEE_TYPE_SM2_PKE_KEYPAIR            0xA1000047
 #define TEE_TYPE_GENERIC_SECRET             0xA0000000
diff --git a/lib/libutee/include/utee_defines.h b/lib/libutee/include/utee_defines.h
index 6255d1b..e442cb3 100644
--- a/lib/libutee/include/utee_defines.h
+++ b/lib/libutee/include/utee_defines.h
@@ -30,6 +30,7 @@
 #define TEE_MAIN_ALGO_DH         0x32
 #define TEE_MAIN_ALGO_ECDSA      0x41
 #define TEE_MAIN_ALGO_ECDH       0x42
+#define TEE_MAIN_ALGO_SM2_DSA_SM3 0x45 /* Not in v1.2 spec */
 #define TEE_MAIN_ALGO_SM2_PKE    0x47 /* Not in v1.2 spec */
 #define TEE_MAIN_ALGO_HKDF       0xC0 /* OP-TEE extension */
 #define TEE_MAIN_ALGO_CONCAT_KDF 0xC1 /* OP-TEE extension */
@@ -75,8 +76,24 @@
 	/* Bits [11:8] */
 #define TEE_ALG_GET_CHAIN_MODE(algo)    (((algo) >> 8) & 0xF)
 
+/*
+ * Value not defined in the GP spec, and not used as bits 15-12 of any TEE_ALG*
+ * value. TEE_ALG_SM2_DSA_SM3 has value 0x6 for bits 15-12 which would yield the
+ * SHA512 digest if we were to apply the bit masks that were valid up to the TEE
+ * Internal Core API v1.1.
+ */
+#define __TEE_MAIN_HASH_SM3 0x7
+
+static inline uint32_t __tee_alg_get_digest_hash(uint32_t algo)
+{
+	if (algo == TEE_ALG_SM2_DSA_SM3)
+		return __TEE_MAIN_HASH_SM3;
+
 	/* Bits [15:12] */
-#define TEE_ALG_GET_DIGEST_HASH(algo)   (((algo) >> 12) & 0xF)
+	return (algo >> 12) & 0xF;
+}
+
+#define TEE_ALG_GET_DIGEST_HASH(algo) __tee_alg_get_digest_hash(algo)
 
 	/* Bits [23:20] */
 #define TEE_ALG_GET_INTERNAL_HASH(algo) (((algo) >> 20) & 0x7)
@@ -94,9 +111,16 @@
 #define TEE_ALG_GET_KEY_TYPE(algo, with_private_key) \
 	__tee_alg_get_key_type(algo, with_private_key)
 
+static inline uint32_t __tee_alg_hash_algo(uint32_t main_hash)
+{
+	if (main_hash == __TEE_MAIN_HASH_SM3)
+		return TEE_ALG_SM3;
+
+	return (TEE_OPERATION_DIGEST << 28) | main_hash;
+}
+
 	/* Return hash algorithm based on main hash */
-#define TEE_ALG_HASH_ALGO(main_hash) \
-        (TEE_OPERATION_DIGEST << 28 | (main_hash))
+#define TEE_ALG_HASH_ALGO(main_hash) __tee_alg_hash_algo(main_hash)
 
 	/* Extract internal hash and return hash algorithm */
 #define TEE_INTERNAL_HASH_TO_ALGO(algo) \
diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c
index e3368f9..e8a9efb 100644
--- a/lib/libutee/tee_api_operations.c
+++ b/lib/libutee/tee_api_operations.c
@@ -85,6 +85,7 @@
 	case TEE_ALG_ECDSA_P256:
 	case TEE_ALG_ECDH_P256:
 	case TEE_ALG_SM2_PKE:
+	case TEE_ALG_SM2_DSA_SM3:
 		if (maxKeySize != 256)
 			return TEE_ERROR_NOT_SUPPORTED;
 		break;
@@ -160,6 +161,7 @@
 	case TEE_ALG_ECDSA_P256:
 	case TEE_ALG_ECDSA_P384:
 	case TEE_ALG_ECDSA_P521:
+	case TEE_ALG_SM2_DSA_SM3:
 		if (mode == TEE_MODE_SIGN) {
 			with_private_key = true;
 			req_key_usage = TEE_USAGE_SIGN;