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