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