xref: /optee_os/core/lib/libtomcrypt/sm2-dsa.c (revision 8cda2ac42aaaf0328b00347a6b08759458a4fc20)
176c7ba4bSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
276c7ba4bSJerome Forissier /*
376c7ba4bSJerome Forissier  * Copyright (c) 2019 Huawei Technologies Co., Ltd
476c7ba4bSJerome Forissier  */
576c7ba4bSJerome Forissier 
676c7ba4bSJerome Forissier #include <crypto/crypto.h>
776c7ba4bSJerome Forissier #include <stdlib.h>
876c7ba4bSJerome Forissier #include <string.h>
976c7ba4bSJerome Forissier #include <tee_api_types.h>
1076c7ba4bSJerome Forissier #include <util.h>
1176c7ba4bSJerome Forissier #include <utee_defines.h>
1276c7ba4bSJerome Forissier 
1376c7ba4bSJerome Forissier #include "acipher_helpers.h"
1476c7ba4bSJerome Forissier 
15*8cda2ac4SJerome Forissier /* SM2 uses 256 bit unsigned integers in big endian format */
16*8cda2ac4SJerome Forissier #define SM2_INT_SIZE_BYTES 32
17*8cda2ac4SJerome Forissier 
1876c7ba4bSJerome Forissier /*
1976c7ba4bSJerome Forissier  * GM/T 0003.1‒2012 Part1 2 Section 6.1
2076c7ba4bSJerome Forissier  */
2176c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo,
2276c7ba4bSJerome Forissier 				       struct ecc_keypair *key,
2376c7ba4bSJerome Forissier 				       const uint8_t *msg, size_t msg_len,
2476c7ba4bSJerome Forissier 				       uint8_t *sig, size_t *sig_len)
2576c7ba4bSJerome Forissier {
2676c7ba4bSJerome Forissier 	TEE_Result res = TEE_SUCCESS;
2776c7ba4bSJerome Forissier 	ecc_point *x1y1p = NULL;
2876c7ba4bSJerome Forissier 	ecc_key ltc_key = { };
2976c7ba4bSJerome Forissier 	int ltc_res = 0;
3076c7ba4bSJerome Forissier 	void *k = NULL;
3176c7ba4bSJerome Forissier 	void *e = NULL;
3276c7ba4bSJerome Forissier 	void *r = NULL;
3376c7ba4bSJerome Forissier 	void *s = NULL;
3476c7ba4bSJerome Forissier 	void *tmp = NULL;
3576c7ba4bSJerome Forissier 
36*8cda2ac4SJerome Forissier 	if (*sig_len < 2 * SM2_INT_SIZE_BYTES) {
3776c7ba4bSJerome Forissier 		*sig_len = 64;
3876c7ba4bSJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
3976c7ba4bSJerome Forissier 	}
4076c7ba4bSJerome Forissier 
4176c7ba4bSJerome Forissier 	ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL);
4276c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK)
4376c7ba4bSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
4476c7ba4bSJerome Forissier 
4576c7ba4bSJerome Forissier 	x1y1p = ltc_ecc_new_point();
4676c7ba4bSJerome Forissier 	if (!x1y1p) {
4776c7ba4bSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
4876c7ba4bSJerome Forissier 		goto out;
4976c7ba4bSJerome Forissier 	}
5076c7ba4bSJerome Forissier 
5176c7ba4bSJerome Forissier 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo, NULL);
5276c7ba4bSJerome Forissier 	if (res)
5376c7ba4bSJerome Forissier 		goto out;
5476c7ba4bSJerome Forissier 
5576c7ba4bSJerome Forissier 	/*
5676c7ba4bSJerome Forissier 	 * Steps A1 and A2 are the generation of the hash value e from user
5776c7ba4bSJerome Forissier 	 * information (ZA) and the message to be signed (M). There are not done
5876c7ba4bSJerome Forissier 	 * here since @msg is expected to be the hash value e already.
5976c7ba4bSJerome Forissier 	 */
6076c7ba4bSJerome Forissier 
6176c7ba4bSJerome Forissier 	/* Step A3: generate random number 1 <= k < n */
6276c7ba4bSJerome Forissier A3:
6376c7ba4bSJerome Forissier 	ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL,
6476c7ba4bSJerome Forissier 			       find_prng("prng_crypto"));
6576c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
6676c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
6776c7ba4bSJerome Forissier 		goto out;
6876c7ba4bSJerome Forissier 	}
6976c7ba4bSJerome Forissier 
7076c7ba4bSJerome Forissier 	/* Step A4: compute (x1, y1) = [k]G */
7176c7ba4bSJerome Forissier 
7276c7ba4bSJerome Forissier 	ltc_res = ltc_ecc_mulmod(k, &ltc_key.dp.base, x1y1p, ltc_key.dp.A,
7376c7ba4bSJerome Forissier 				 ltc_key.dp.prime, 1);
7476c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
7576c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
7676c7ba4bSJerome Forissier 		goto out;
7776c7ba4bSJerome Forissier 	}
7876c7ba4bSJerome Forissier 
7976c7ba4bSJerome Forissier 	/* Step A5: compute r = (e + x1) mod n */
8076c7ba4bSJerome Forissier 
8176c7ba4bSJerome Forissier 	mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len);
8276c7ba4bSJerome Forissier 	ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r);
8376c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
8476c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
8576c7ba4bSJerome Forissier 		goto out;
8676c7ba4bSJerome Forissier 	}
8776c7ba4bSJerome Forissier 	ltc_res = mp_add(r, k, tmp);
8876c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
8976c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
9076c7ba4bSJerome Forissier 		goto out;
9176c7ba4bSJerome Forissier 	}
9276c7ba4bSJerome Forissier 	if (mp_cmp_d(r, 0) == LTC_MP_EQ ||
9376c7ba4bSJerome Forissier 	    mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ)
9476c7ba4bSJerome Forissier 		goto A3;
9576c7ba4bSJerome Forissier 
9676c7ba4bSJerome Forissier 	/* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */
9776c7ba4bSJerome Forissier 
9876c7ba4bSJerome Forissier 	ltc_res = mp_add_d(ltc_key.k, 1, s);
9976c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
10076c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
10176c7ba4bSJerome Forissier 		goto out;
10276c7ba4bSJerome Forissier 	}
10376c7ba4bSJerome Forissier 	ltc_res = mp_invmod(s, ltc_key.dp.order, s);
10476c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
10576c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
10676c7ba4bSJerome Forissier 		goto out;
10776c7ba4bSJerome Forissier 	}
10876c7ba4bSJerome Forissier 	ltc_res = mp_mul(r, ltc_key.k, tmp);
10976c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
11076c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
11176c7ba4bSJerome Forissier 		goto out;
11276c7ba4bSJerome Forissier 	}
11376c7ba4bSJerome Forissier 	ltc_res = mp_sub(k, tmp, tmp);
11476c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
11576c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
11676c7ba4bSJerome Forissier 		goto out;
11776c7ba4bSJerome Forissier 	}
11876c7ba4bSJerome Forissier 	ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s);
11976c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
12076c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
12176c7ba4bSJerome Forissier 		goto out;
12276c7ba4bSJerome Forissier 	}
12376c7ba4bSJerome Forissier 
12476c7ba4bSJerome Forissier 	/* Step A7: convert (r, s) to binary for output */
12576c7ba4bSJerome Forissier 
126*8cda2ac4SJerome Forissier 	*sig_len = 2 * SM2_INT_SIZE_BYTES;
127*8cda2ac4SJerome Forissier 	memset(sig, 0, *sig_len);
128*8cda2ac4SJerome Forissier 	mp_to_unsigned_bin2(r, sig, SM2_INT_SIZE_BYTES);
129*8cda2ac4SJerome Forissier 	mp_to_unsigned_bin2(s, sig + SM2_INT_SIZE_BYTES, SM2_INT_SIZE_BYTES);
13076c7ba4bSJerome Forissier out:
1310b38353cSJerome Forissier 	ecc_free(&ltc_key);
13276c7ba4bSJerome Forissier 	ltc_ecc_del_point(x1y1p);
13376c7ba4bSJerome Forissier 	mp_clear_multi(k, e, r, s, tmp, NULL);
13476c7ba4bSJerome Forissier 	return res;
13576c7ba4bSJerome Forissier }
13676c7ba4bSJerome Forissier 
13776c7ba4bSJerome Forissier /*
13876c7ba4bSJerome Forissier  * GM/T 0003.1‒2012 Part1 2 Section 7.1
13976c7ba4bSJerome Forissier  */
14076c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo,
14176c7ba4bSJerome Forissier 					 struct ecc_public_key *key,
14276c7ba4bSJerome Forissier 					 const uint8_t *msg, size_t msg_len,
14376c7ba4bSJerome Forissier 					 const uint8_t *sig, size_t sig_len)
14476c7ba4bSJerome Forissier {
14576c7ba4bSJerome Forissier 	TEE_Result res = TEE_SUCCESS;
14676c7ba4bSJerome Forissier 	ecc_key ltc_key = { };
14776c7ba4bSJerome Forissier 	int ltc_res = 0;
14876c7ba4bSJerome Forissier 	void *rprime = NULL;
14976c7ba4bSJerome Forissier 	void *sprime = NULL;
15076c7ba4bSJerome Forissier 	void *t = NULL;
15176c7ba4bSJerome Forissier 	void *mp = NULL;
15276c7ba4bSJerome Forissier 	void *mu = NULL;
15376c7ba4bSJerome Forissier 	void *ma = NULL;
15476c7ba4bSJerome Forissier 	void *eprime = NULL;
15576c7ba4bSJerome Forissier 	void *R = NULL;
15676c7ba4bSJerome Forissier 	ecc_point *x1y1p = NULL;
15776c7ba4bSJerome Forissier 
15876c7ba4bSJerome Forissier 	if (sig_len != 64)
15976c7ba4bSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
16076c7ba4bSJerome Forissier 
16176c7ba4bSJerome Forissier 	ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R,
16276c7ba4bSJerome Forissier 				NULL);
16376c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK)
16476c7ba4bSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
16576c7ba4bSJerome Forissier 
16676c7ba4bSJerome Forissier 	mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32);
16776c7ba4bSJerome Forissier 	mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32);
16876c7ba4bSJerome Forissier 
16976c7ba4bSJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_key, key, algo, NULL);
17076c7ba4bSJerome Forissier 	if (res)
17176c7ba4bSJerome Forissier 		goto out;
17276c7ba4bSJerome Forissier 
17376c7ba4bSJerome Forissier 	/* Step B1: verify r' in [1, n - 1] */
17476c7ba4bSJerome Forissier 
17576c7ba4bSJerome Forissier 	if (mp_cmp_d(rprime, 1) == LTC_MP_LT ||
17676c7ba4bSJerome Forissier 	    mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) {
17776c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
17876c7ba4bSJerome Forissier 		goto out;
17976c7ba4bSJerome Forissier 	}
18076c7ba4bSJerome Forissier 
18176c7ba4bSJerome Forissier 	/* Step B2: verify s' in [1, n - 1] */
18276c7ba4bSJerome Forissier 
18376c7ba4bSJerome Forissier 	if (mp_cmp_d(sprime, 1) == LTC_MP_LT ||
18476c7ba4bSJerome Forissier 	    mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) {
18576c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
18676c7ba4bSJerome Forissier 		goto out;
18776c7ba4bSJerome Forissier 	}
18876c7ba4bSJerome Forissier 
18976c7ba4bSJerome Forissier 	/*
19076c7ba4bSJerome Forissier 	 * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here
19176c7ba4bSJerome Forissier 	 * because @msg is supposed to contain the hash value e' already.
19276c7ba4bSJerome Forissier 	 */
19376c7ba4bSJerome Forissier 
19476c7ba4bSJerome Forissier 	/* Step B5: t = (r' + s') mod n and check t != 0 */
19576c7ba4bSJerome Forissier 
19676c7ba4bSJerome Forissier 	ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t);
19776c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
19876c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
19976c7ba4bSJerome Forissier 		goto out;
20076c7ba4bSJerome Forissier 	}
20176c7ba4bSJerome Forissier 	if (mp_cmp_d(t, 0) == LTC_MP_EQ) {
20276c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
20376c7ba4bSJerome Forissier 		goto out;
20476c7ba4bSJerome Forissier 	}
20576c7ba4bSJerome Forissier 
20676c7ba4bSJerome Forissier 	/* Step B6: (x1', y1') = [s']G + [t]PA */
20776c7ba4bSJerome Forissier 
20876c7ba4bSJerome Forissier 	x1y1p = ltc_ecc_new_point();
20976c7ba4bSJerome Forissier 	if (!x1y1p) {
21076c7ba4bSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
21176c7ba4bSJerome Forissier 		goto out;
21276c7ba4bSJerome Forissier 	}
21376c7ba4bSJerome Forissier 	ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp);
21476c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
21576c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
21676c7ba4bSJerome Forissier 		goto out;
21776c7ba4bSJerome Forissier 	}
21876c7ba4bSJerome Forissier 	ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime);
21976c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
22076c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
22176c7ba4bSJerome Forissier 		goto out;
22276c7ba4bSJerome Forissier 	}
22376c7ba4bSJerome Forissier 	ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma);
22476c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
22576c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
22676c7ba4bSJerome Forissier 		goto out;
22776c7ba4bSJerome Forissier 	}
22876c7ba4bSJerome Forissier 	ltc_res = ltc_ecc_mul2add(&ltc_key.dp.base, sprime, &ltc_key.pubkey, t,
22976c7ba4bSJerome Forissier 				  x1y1p, ma, ltc_key.dp.prime);
23076c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
23176c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
23276c7ba4bSJerome Forissier 		goto out;
23376c7ba4bSJerome Forissier 	}
23476c7ba4bSJerome Forissier 
23576c7ba4bSJerome Forissier 	/* Step B7: compute R = (e' + x1') mod n and verify R == r' */
23676c7ba4bSJerome Forissier 
23776c7ba4bSJerome Forissier 	mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len);
23876c7ba4bSJerome Forissier 	ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R);
23976c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
24076c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
24176c7ba4bSJerome Forissier 		goto out;
24276c7ba4bSJerome Forissier 	}
24376c7ba4bSJerome Forissier 	if (mp_cmp(R, rprime) != LTC_MP_EQ)
24476c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
24576c7ba4bSJerome Forissier out:
24676c7ba4bSJerome Forissier 	mp_montgomery_free(mp);
24776c7ba4bSJerome Forissier 	ltc_ecc_del_point(x1y1p);
2480b38353cSJerome Forissier 	ecc_free(&ltc_key);
24976c7ba4bSJerome Forissier 	mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL);
25076c7ba4bSJerome Forissier 	return res;
25176c7ba4bSJerome Forissier }
252