xref: /optee_os/core/lib/libtomcrypt/sm2-dsa.c (revision 76c7ba4b9ff76dc053e34ad9f9c790a6c59febf5)
1*76c7ba4bSJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2*76c7ba4bSJerome Forissier /*
3*76c7ba4bSJerome Forissier  * Copyright (c) 2019 Huawei Technologies Co., Ltd
4*76c7ba4bSJerome Forissier  */
5*76c7ba4bSJerome Forissier 
6*76c7ba4bSJerome Forissier #include <crypto/crypto.h>
7*76c7ba4bSJerome Forissier #include <stdlib.h>
8*76c7ba4bSJerome Forissier #include <string.h>
9*76c7ba4bSJerome Forissier #include <tee_api_types.h>
10*76c7ba4bSJerome Forissier #include <util.h>
11*76c7ba4bSJerome Forissier #include <utee_defines.h>
12*76c7ba4bSJerome Forissier 
13*76c7ba4bSJerome Forissier #include "acipher_helpers.h"
14*76c7ba4bSJerome Forissier 
15*76c7ba4bSJerome Forissier /*
16*76c7ba4bSJerome Forissier  * GM/T 0003.1‒2012 Part1 2 Section 6.1
17*76c7ba4bSJerome Forissier  */
18*76c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_sign(uint32_t algo,
19*76c7ba4bSJerome Forissier 				       struct ecc_keypair *key,
20*76c7ba4bSJerome Forissier 				       const uint8_t *msg, size_t msg_len,
21*76c7ba4bSJerome Forissier 				       uint8_t *sig, size_t *sig_len)
22*76c7ba4bSJerome Forissier {
23*76c7ba4bSJerome Forissier 	TEE_Result res = TEE_SUCCESS;
24*76c7ba4bSJerome Forissier 	ecc_point *x1y1p = NULL;
25*76c7ba4bSJerome Forissier 	ecc_key ltc_key = { };
26*76c7ba4bSJerome Forissier 	int ltc_res = 0;
27*76c7ba4bSJerome Forissier 	void *k = NULL;
28*76c7ba4bSJerome Forissier 	void *e = NULL;
29*76c7ba4bSJerome Forissier 	void *r = NULL;
30*76c7ba4bSJerome Forissier 	void *s = NULL;
31*76c7ba4bSJerome Forissier 	void *tmp = NULL;
32*76c7ba4bSJerome Forissier 
33*76c7ba4bSJerome Forissier 	if (*sig_len < 64) {
34*76c7ba4bSJerome Forissier 		*sig_len = 64;
35*76c7ba4bSJerome Forissier 		return TEE_ERROR_SHORT_BUFFER;
36*76c7ba4bSJerome Forissier 	}
37*76c7ba4bSJerome Forissier 
38*76c7ba4bSJerome Forissier 	ltc_res = mp_init_multi(&k, &e, &r, &s, &tmp, NULL);
39*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK)
40*76c7ba4bSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
41*76c7ba4bSJerome Forissier 
42*76c7ba4bSJerome Forissier 	x1y1p = ltc_ecc_new_point();
43*76c7ba4bSJerome Forissier 	if (!x1y1p) {
44*76c7ba4bSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
45*76c7ba4bSJerome Forissier 		goto out;
46*76c7ba4bSJerome Forissier 	}
47*76c7ba4bSJerome Forissier 
48*76c7ba4bSJerome Forissier 	res = ecc_populate_ltc_private_key(&ltc_key, key, algo, NULL);
49*76c7ba4bSJerome Forissier 	if (res)
50*76c7ba4bSJerome Forissier 		goto out;
51*76c7ba4bSJerome Forissier 
52*76c7ba4bSJerome Forissier 	/*
53*76c7ba4bSJerome Forissier 	 * Steps A1 and A2 are the generation of the hash value e from user
54*76c7ba4bSJerome Forissier 	 * information (ZA) and the message to be signed (M). There are not done
55*76c7ba4bSJerome Forissier 	 * here since @msg is expected to be the hash value e already.
56*76c7ba4bSJerome Forissier 	 */
57*76c7ba4bSJerome Forissier 
58*76c7ba4bSJerome Forissier 	/* Step A3: generate random number 1 <= k < n */
59*76c7ba4bSJerome Forissier A3:
60*76c7ba4bSJerome Forissier 	ltc_res = rand_bn_upto(k, ltc_key.dp.order, NULL,
61*76c7ba4bSJerome Forissier 			       find_prng("prng_crypto"));
62*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
63*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
64*76c7ba4bSJerome Forissier 		goto out;
65*76c7ba4bSJerome Forissier 	}
66*76c7ba4bSJerome Forissier 
67*76c7ba4bSJerome Forissier 	/* Step A4: compute (x1, y1) = [k]G */
68*76c7ba4bSJerome Forissier 
69*76c7ba4bSJerome Forissier 	ltc_res = ltc_ecc_mulmod(k, &ltc_key.dp.base, x1y1p, ltc_key.dp.A,
70*76c7ba4bSJerome Forissier 				 ltc_key.dp.prime, 1);
71*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
72*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
73*76c7ba4bSJerome Forissier 		goto out;
74*76c7ba4bSJerome Forissier 	}
75*76c7ba4bSJerome Forissier 
76*76c7ba4bSJerome Forissier 	/* Step A5: compute r = (e + x1) mod n */
77*76c7ba4bSJerome Forissier 
78*76c7ba4bSJerome Forissier 	mp_read_unsigned_bin(e, (unsigned char *)msg, msg_len);
79*76c7ba4bSJerome Forissier 	ltc_res = mp_addmod(e, x1y1p->x, ltc_key.dp.order, r);
80*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
81*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
82*76c7ba4bSJerome Forissier 		goto out;
83*76c7ba4bSJerome Forissier 	}
84*76c7ba4bSJerome Forissier 	ltc_res = mp_add(r, k, tmp);
85*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
86*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
87*76c7ba4bSJerome Forissier 		goto out;
88*76c7ba4bSJerome Forissier 	}
89*76c7ba4bSJerome Forissier 	if (mp_cmp_d(r, 0) == LTC_MP_EQ ||
90*76c7ba4bSJerome Forissier 	    mp_cmp(tmp, ltc_key.dp.order) == LTC_MP_EQ)
91*76c7ba4bSJerome Forissier 		goto A3;
92*76c7ba4bSJerome Forissier 
93*76c7ba4bSJerome Forissier 	/* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */
94*76c7ba4bSJerome Forissier 
95*76c7ba4bSJerome Forissier 	ltc_res = mp_add_d(ltc_key.k, 1, s);
96*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
97*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
98*76c7ba4bSJerome Forissier 		goto out;
99*76c7ba4bSJerome Forissier 	}
100*76c7ba4bSJerome Forissier 	ltc_res = mp_invmod(s, ltc_key.dp.order, s);
101*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
102*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
103*76c7ba4bSJerome Forissier 		goto out;
104*76c7ba4bSJerome Forissier 	}
105*76c7ba4bSJerome Forissier 	ltc_res = mp_mul(r, ltc_key.k, tmp);
106*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
107*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
108*76c7ba4bSJerome Forissier 		goto out;
109*76c7ba4bSJerome Forissier 	}
110*76c7ba4bSJerome Forissier 	ltc_res = mp_sub(k, tmp, tmp);
111*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
112*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
113*76c7ba4bSJerome Forissier 		goto out;
114*76c7ba4bSJerome Forissier 	}
115*76c7ba4bSJerome Forissier 	ltc_res = mp_mulmod(s, tmp, ltc_key.dp.order, s);
116*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
117*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
118*76c7ba4bSJerome Forissier 		goto out;
119*76c7ba4bSJerome Forissier 	}
120*76c7ba4bSJerome Forissier 
121*76c7ba4bSJerome Forissier 	/* Step A7: convert (r, s) to binary for output */
122*76c7ba4bSJerome Forissier 
123*76c7ba4bSJerome Forissier 	memset(sig, 0, 64);
124*76c7ba4bSJerome Forissier 	mp_to_unsigned_bin(r, sig);
125*76c7ba4bSJerome Forissier 	mp_to_unsigned_bin(s, sig + 32);
126*76c7ba4bSJerome Forissier 	*sig_len = 64;
127*76c7ba4bSJerome Forissier out:
128*76c7ba4bSJerome Forissier 	ltc_ecc_del_point(x1y1p);
129*76c7ba4bSJerome Forissier 	mp_clear_multi(k, e, r, s, tmp, NULL);
130*76c7ba4bSJerome Forissier 	return res;
131*76c7ba4bSJerome Forissier }
132*76c7ba4bSJerome Forissier 
133*76c7ba4bSJerome Forissier /*
134*76c7ba4bSJerome Forissier  * GM/T 0003.1‒2012 Part1 2 Section 7.1
135*76c7ba4bSJerome Forissier  */
136*76c7ba4bSJerome Forissier TEE_Result crypto_acipher_sm2_dsa_verify(uint32_t algo,
137*76c7ba4bSJerome Forissier 					 struct ecc_public_key *key,
138*76c7ba4bSJerome Forissier 					 const uint8_t *msg, size_t msg_len,
139*76c7ba4bSJerome Forissier 					 const uint8_t *sig, size_t sig_len)
140*76c7ba4bSJerome Forissier {
141*76c7ba4bSJerome Forissier 	TEE_Result res = TEE_SUCCESS;
142*76c7ba4bSJerome Forissier 	ecc_key ltc_key = { };
143*76c7ba4bSJerome Forissier 	int ltc_res = 0;
144*76c7ba4bSJerome Forissier 	void *rprime = NULL;
145*76c7ba4bSJerome Forissier 	void *sprime = NULL;
146*76c7ba4bSJerome Forissier 	void *t = NULL;
147*76c7ba4bSJerome Forissier 	void *mp = NULL;
148*76c7ba4bSJerome Forissier 	void *mu = NULL;
149*76c7ba4bSJerome Forissier 	void *ma = NULL;
150*76c7ba4bSJerome Forissier 	void *eprime = NULL;
151*76c7ba4bSJerome Forissier 	void *R = NULL;
152*76c7ba4bSJerome Forissier 	ecc_point *x1y1p = NULL;
153*76c7ba4bSJerome Forissier 
154*76c7ba4bSJerome Forissier 	if (sig_len != 64)
155*76c7ba4bSJerome Forissier 		return TEE_ERROR_BAD_PARAMETERS;
156*76c7ba4bSJerome Forissier 
157*76c7ba4bSJerome Forissier 	ltc_res = mp_init_multi(&rprime, &sprime, &t, &mu, &ma, &eprime, &R,
158*76c7ba4bSJerome Forissier 				NULL);
159*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK)
160*76c7ba4bSJerome Forissier 		return TEE_ERROR_OUT_OF_MEMORY;
161*76c7ba4bSJerome Forissier 
162*76c7ba4bSJerome Forissier 	mp_read_unsigned_bin(rprime, (unsigned char *)sig, 32);
163*76c7ba4bSJerome Forissier 	mp_read_unsigned_bin(sprime, (unsigned char *)sig + 32, 32);
164*76c7ba4bSJerome Forissier 
165*76c7ba4bSJerome Forissier 	res = ecc_populate_ltc_public_key(&ltc_key, key, algo, NULL);
166*76c7ba4bSJerome Forissier 	if (res)
167*76c7ba4bSJerome Forissier 		goto out;
168*76c7ba4bSJerome Forissier 
169*76c7ba4bSJerome Forissier 	/* Step B1: verify r' in [1, n - 1] */
170*76c7ba4bSJerome Forissier 
171*76c7ba4bSJerome Forissier 	if (mp_cmp_d(rprime, 1) == LTC_MP_LT ||
172*76c7ba4bSJerome Forissier 	    mp_cmp(rprime, ltc_key.dp.order) != LTC_MP_LT) {
173*76c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
174*76c7ba4bSJerome Forissier 		goto out;
175*76c7ba4bSJerome Forissier 	}
176*76c7ba4bSJerome Forissier 
177*76c7ba4bSJerome Forissier 	/* Step B2: verify s' in [1, n - 1] */
178*76c7ba4bSJerome Forissier 
179*76c7ba4bSJerome Forissier 	if (mp_cmp_d(sprime, 1) == LTC_MP_LT ||
180*76c7ba4bSJerome Forissier 	    mp_cmp(sprime, ltc_key.dp.order) != LTC_MP_LT) {
181*76c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
182*76c7ba4bSJerome Forissier 		goto out;
183*76c7ba4bSJerome Forissier 	}
184*76c7ba4bSJerome Forissier 
185*76c7ba4bSJerome Forissier 	/*
186*76c7ba4bSJerome Forissier 	 * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here
187*76c7ba4bSJerome Forissier 	 * because @msg is supposed to contain the hash value e' already.
188*76c7ba4bSJerome Forissier 	 */
189*76c7ba4bSJerome Forissier 
190*76c7ba4bSJerome Forissier 	/* Step B5: t = (r' + s') mod n and check t != 0 */
191*76c7ba4bSJerome Forissier 
192*76c7ba4bSJerome Forissier 	ltc_res = mp_addmod(rprime, sprime, ltc_key.dp.order, t);
193*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
194*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
195*76c7ba4bSJerome Forissier 		goto out;
196*76c7ba4bSJerome Forissier 	}
197*76c7ba4bSJerome Forissier 	if (mp_cmp_d(t, 0) == LTC_MP_EQ) {
198*76c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
199*76c7ba4bSJerome Forissier 		goto out;
200*76c7ba4bSJerome Forissier 	}
201*76c7ba4bSJerome Forissier 
202*76c7ba4bSJerome Forissier 	/* Step B6: (x1', y1') = [s']G + [t]PA */
203*76c7ba4bSJerome Forissier 
204*76c7ba4bSJerome Forissier 	x1y1p = ltc_ecc_new_point();
205*76c7ba4bSJerome Forissier 	if (!x1y1p) {
206*76c7ba4bSJerome Forissier 		res = TEE_ERROR_OUT_OF_MEMORY;
207*76c7ba4bSJerome Forissier 		goto out;
208*76c7ba4bSJerome Forissier 	}
209*76c7ba4bSJerome Forissier 	ltc_res = mp_montgomery_setup(ltc_key.dp.prime, &mp);
210*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
211*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
212*76c7ba4bSJerome Forissier 		goto out;
213*76c7ba4bSJerome Forissier 	}
214*76c7ba4bSJerome Forissier 	ltc_res = mp_montgomery_normalization(mu, ltc_key.dp.prime);
215*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
216*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
217*76c7ba4bSJerome Forissier 		goto out;
218*76c7ba4bSJerome Forissier 	}
219*76c7ba4bSJerome Forissier 	ltc_res = mp_mulmod(ltc_key.dp.A, mu, ltc_key.dp.prime, ma);
220*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
221*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
222*76c7ba4bSJerome Forissier 		goto out;
223*76c7ba4bSJerome Forissier 	}
224*76c7ba4bSJerome Forissier 	ltc_res = ltc_ecc_mul2add(&ltc_key.dp.base, sprime, &ltc_key.pubkey, t,
225*76c7ba4bSJerome Forissier 				  x1y1p, ma, ltc_key.dp.prime);
226*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
227*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
228*76c7ba4bSJerome Forissier 		goto out;
229*76c7ba4bSJerome Forissier 	}
230*76c7ba4bSJerome Forissier 
231*76c7ba4bSJerome Forissier 	/* Step B7: compute R = (e' + x1') mod n and verify R == r' */
232*76c7ba4bSJerome Forissier 
233*76c7ba4bSJerome Forissier 	mp_read_unsigned_bin(eprime, (unsigned char *)msg, msg_len);
234*76c7ba4bSJerome Forissier 	ltc_res = mp_addmod(eprime, x1y1p->x, ltc_key.dp.order, R);
235*76c7ba4bSJerome Forissier 	if (ltc_res != CRYPT_OK) {
236*76c7ba4bSJerome Forissier 		res = TEE_ERROR_BAD_STATE;
237*76c7ba4bSJerome Forissier 		goto out;
238*76c7ba4bSJerome Forissier 	}
239*76c7ba4bSJerome Forissier 	if (mp_cmp(R, rprime) != LTC_MP_EQ)
240*76c7ba4bSJerome Forissier 		res = TEE_ERROR_SIGNATURE_INVALID;
241*76c7ba4bSJerome Forissier out:
242*76c7ba4bSJerome Forissier 	mp_montgomery_free(mp);
243*76c7ba4bSJerome Forissier 	ltc_ecc_del_point(x1y1p);
244*76c7ba4bSJerome Forissier 	mp_clear_multi(rprime, sprime, t, mu, ma, eprime, R, NULL);
245*76c7ba4bSJerome Forissier 	return res;
246*76c7ba4bSJerome Forissier }
247