1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019-2021 Huawei Technologies Co., Ltd
4  */
5 
6 #include <compiler.h>
7 #include <crypto/crypto.h>
8 #include <mbedtls/bignum.h>
9 #include <mbedtls/ecp.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <tee_api_types.h>
13 #include <util.h>
14 #include <utee_defines.h>
15 
16 #include "mbed_helpers.h"
17 #include "sm2-dsa.h"
18 
19 /* SM2 uses 256 bit unsigned integers in big endian format */
20 #define SM2_INT_SIZE_BYTES 32
21 
22 /*
23  * GM/T 0003.1‒2012 Part1 2 Section 6.1
24  */
sm2_mbedtls_dsa_sign(uint32_t algo __unused,struct ecc_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)25 TEE_Result sm2_mbedtls_dsa_sign(uint32_t algo __unused, struct ecc_keypair *key,
26 				const uint8_t *msg, size_t msg_len,
27 				uint8_t *sig, size_t *sig_len)
28 {
29 	TEE_Result res = TEE_SUCCESS;
30 	mbedtls_ecp_group grp = { };
31 	mbedtls_ecp_point x1y1p = { };
32 	int mres = 0;
33 	mbedtls_mpi k = { };
34 	mbedtls_mpi e = { };
35 	mbedtls_mpi r = { };
36 	mbedtls_mpi s = { };
37 	mbedtls_mpi tmp = { };
38 
39 	if (*sig_len < 2 * SM2_INT_SIZE_BYTES) {
40 		*sig_len = 64;
41 		return TEE_ERROR_SHORT_BUFFER;
42 	}
43 
44 	mbedtls_mpi_init(&k);
45 	mbedtls_mpi_init(&e);
46 	mbedtls_mpi_init(&r);
47 	mbedtls_mpi_init(&s);
48 	mbedtls_mpi_init(&tmp);
49 
50 	mbedtls_ecp_point_init(&x1y1p);
51 
52 	mbedtls_ecp_group_init(&grp);
53 	mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2);
54 	if (mres) {
55 		res = TEE_ERROR_GENERIC;
56 		goto out;
57 	}
58 
59 	/*
60 	 * Steps A1 and A2 are the generation of the hash value e from user
61 	 * information (ZA) and the message to be signed (M). There are not done
62 	 * here since @msg is expected to be the hash value e already.
63 	 */
64 
65 	/* Step A3: generate random number 1 <= k < n */
66 	do {
67 		res = mbed_gen_random_upto(&k, &grp.N);
68 		if (res)
69 			goto out;
70 
71 		res = TEE_ERROR_BAD_STATE;
72 
73 		/* Step A4: compute (x1, y1) = [k]G */
74 
75 		mres = mbedtls_ecp_mul(&grp, &x1y1p, &k, &grp.G, mbd_rand,
76 				       NULL);
77 		if (mres)
78 			goto out;
79 
80 		/* Step A5: compute r = (e + x1) mod n */
81 
82 		mbedtls_mpi_read_binary(&e, (unsigned char *)msg, msg_len);
83 		mres = mbedtls_mpi_add_mpi(&r, &e, &x1y1p.X);
84 		if (mres)
85 			goto out;
86 		mres = mbedtls_mpi_mod_mpi(&r, &r, &grp.N);
87 		if (mres)
88 			goto out;
89 
90 		/* Step A5 (continued): return to A3 if r = 0 or r + k = n */
91 
92 		mres = mbedtls_mpi_add_mpi(&tmp, &r, &k);
93 		if (mres)
94 			goto out;
95 	} while (!mbedtls_mpi_cmp_int(&r, 0) ||
96 		 !mbedtls_mpi_cmp_mpi(&tmp, &grp.N));
97 
98 	/* Step A6: compute s = ((1 + dA)^-1 * (k - r*dA)) mod n */
99 
100 	mres = mbedtls_mpi_add_int(&s, (mbedtls_mpi *)key->d, 1);
101 	if (mres)
102 		goto out;
103 	mres = mbedtls_mpi_inv_mod(&s, &s, &grp.N);
104 	if (mres)
105 		goto out;
106 	mres = mbedtls_mpi_mul_mpi(&tmp, &r, (mbedtls_mpi *)key->d);
107 	if (mres)
108 		goto out;
109 	mres = mbedtls_mpi_mod_mpi(&tmp, &tmp, &grp.N);
110 	if (mres)
111 		goto out;
112 	mres = mbedtls_mpi_sub_mpi(&tmp, &k, &tmp);
113 	if (mres)
114 		goto out;
115 	mres = mbedtls_mpi_mul_mpi(&s, &s, &tmp);
116 	if (mres)
117 		goto out;
118 	mres = mbedtls_mpi_mod_mpi(&s, &s, &grp.N);
119 	if (mres)
120 		goto out;
121 
122 	/* Step A7: convert (r, s) to binary for output */
123 
124 	*sig_len = 2 * SM2_INT_SIZE_BYTES;
125 	memset(sig, 0, *sig_len);
126 	mres = mbedtls_mpi_write_binary(&r, sig, SM2_INT_SIZE_BYTES);
127 	if (mres)
128 		goto out;
129 	mres = mbedtls_mpi_write_binary(&s, sig + SM2_INT_SIZE_BYTES,
130 					SM2_INT_SIZE_BYTES);
131 	if (mres)
132 		goto out;
133 
134 	res = TEE_SUCCESS;
135 out:
136 	mbedtls_ecp_point_free(&x1y1p);
137 	mbedtls_mpi_free(&k);
138 	mbedtls_mpi_free(&e);
139 	mbedtls_mpi_free(&r);
140 	mbedtls_mpi_free(&s);
141 	mbedtls_mpi_free(&tmp);
142 	mbedtls_ecp_group_free(&grp);
143 	return res;
144 }
145 
146 /*
147  * GM/T 0003.1‒2012 Part1 2 Section 7.1
148  */
sm2_mbedtls_dsa_verify(uint32_t algo __unused,struct ecc_public_key * key,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len)149 TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo __unused,
150 				  struct ecc_public_key *key,
151 				  const uint8_t *msg, size_t msg_len,
152 				  const uint8_t *sig, size_t sig_len)
153 {
154 	TEE_Result res = TEE_ERROR_BAD_STATE;
155 	mbedtls_ecp_group grp = { };
156 	mbedtls_mpi rprime = { };
157 	mbedtls_mpi sprime = { };
158 	mbedtls_mpi t = { };
159 	mbedtls_mpi eprime = { };
160 	mbedtls_mpi R = { };
161 	mbedtls_ecp_point x1y1p = { };
162 	mbedtls_ecp_point PA = { };
163 	int mres = 0;
164 
165 	if (sig_len != 64)
166 		return TEE_ERROR_BAD_PARAMETERS;
167 
168 	mbedtls_mpi_init(&rprime);
169 	mbedtls_mpi_init(&sprime);
170 	mbedtls_mpi_init(&t);
171 	mbedtls_mpi_init(&eprime);
172 	mbedtls_mpi_init(&R);
173 
174 	mbedtls_ecp_point_init(&x1y1p);
175 	mbedtls_ecp_point_init(&PA);
176 
177 	mbedtls_ecp_group_init(&grp);
178 	mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2);
179 	if (mres) {
180 		res = TEE_ERROR_GENERIC;
181 		goto out;
182 	}
183 
184 	mres = mbedtls_mpi_read_binary(&rprime, sig, 32);
185 	if (mres)
186 		goto out;
187 	mres = mbedtls_mpi_read_binary(&sprime, sig + 32, 32);
188 	if (mres)
189 		goto out;
190 
191 	/* Step B1: verify r' in [1, n - 1] */
192 
193 	if (mbedtls_mpi_cmp_int(&rprime, 1) < 0 ||
194 	    mbedtls_mpi_cmp_mpi(&rprime, &grp.N) >= 0) {
195 		res = TEE_ERROR_SIGNATURE_INVALID;
196 		goto out;
197 	}
198 
199 	/* Step B2: verify s' in [1, n - 1] */
200 
201 	if (mbedtls_mpi_cmp_int(&sprime, 1) < 0 ||
202 	    mbedtls_mpi_cmp_mpi(&sprime, &grp.N) >= 0) {
203 		res = TEE_ERROR_SIGNATURE_INVALID;
204 		goto out;
205 	}
206 
207 	/*
208 	 * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here
209 	 * because @msg is supposed to contain the hash value e' already.
210 	 */
211 
212 	/* Step B5: t = (r' + s') mod n and check t != 0 */
213 
214 	mres = mbedtls_mpi_add_mpi(&t, &rprime, &sprime);
215 	if (mres)
216 		goto out;
217 	mres = mbedtls_mpi_mod_mpi(&t, &t, &grp.N);
218 	if (mres)
219 		goto out;
220 	if (!mbedtls_mpi_cmp_int(&t, 0)) {
221 		res = TEE_ERROR_SIGNATURE_INVALID;
222 		goto out;
223 	}
224 
225 	/* Step B6: (x1', y1') = [s']G + [t]PA */
226 
227 	mres = mbedtls_mpi_copy(&PA.X, (mbedtls_mpi *)key->x);
228 	if (mres)
229 		goto out;
230 	mres = mbedtls_mpi_copy(&PA.Y, (mbedtls_mpi *)key->y);
231 	if (mres)
232 		goto out;
233 	mres = mbedtls_mpi_lset(&PA.Z, 1);
234 	if (mres)
235 		goto out;
236 
237 	mres = mbedtls_ecp_muladd(&grp, &x1y1p, &sprime, &grp.G, &t, &PA);
238 	if (mres)
239 		goto out;
240 
241 	/* Step B7: compute R = (e' + x1') mod n and verify R == r' */
242 
243 	mres = mbedtls_mpi_read_binary(&eprime, msg, msg_len);
244 	if (mres)
245 		goto out;
246 	mres = mbedtls_mpi_add_mpi(&R, &eprime, &x1y1p.X);
247 	if (mres)
248 		goto out;
249 	mres = mbedtls_mpi_mod_mpi(&R, &R, &grp.N);
250 	if (mres)
251 		goto out;
252 	if (mbedtls_mpi_cmp_mpi(&R, &rprime)) {
253 		res = TEE_ERROR_SIGNATURE_INVALID;
254 		goto out;
255 	}
256 
257 	res = TEE_SUCCESS;
258 out:
259 	mbedtls_ecp_point_free(&x1y1p);
260 	mbedtls_ecp_point_free(&PA);
261 	mbedtls_mpi_free(&rprime);
262 	mbedtls_mpi_free(&sprime);
263 	mbedtls_mpi_free(&t);
264 	mbedtls_mpi_free(&eprime);
265 	mbedtls_mpi_free(&R);
266 	mbedtls_ecp_group_free(&grp);
267 	return res;
268 }
269