xref: /optee_os/lib/libmbedtls/core/sm2-dsa.c (revision 77bdbf67c42209142ef43129e01113d29d9c62f6)
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  */
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 	return res;
143 }
144 
145 /*
146  * GM/T 0003.1‒2012 Part1 2 Section 7.1
147  */
148 TEE_Result sm2_mbedtls_dsa_verify(uint32_t algo __unused,
149 				  struct ecc_public_key *key,
150 				  const uint8_t *msg, size_t msg_len,
151 				  const uint8_t *sig, size_t sig_len)
152 {
153 	TEE_Result res = TEE_ERROR_BAD_STATE;
154 	mbedtls_ecp_group grp = { };
155 	mbedtls_mpi rprime = { };
156 	mbedtls_mpi sprime = { };
157 	mbedtls_mpi t = { };
158 	mbedtls_mpi eprime = { };
159 	mbedtls_mpi R = { };
160 	mbedtls_ecp_point x1y1p = { };
161 	mbedtls_ecp_point PA = { };
162 	int mres = 0;
163 
164 	if (sig_len != 64)
165 		return TEE_ERROR_BAD_PARAMETERS;
166 
167 	mbedtls_mpi_init(&rprime);
168 	mbedtls_mpi_init(&sprime);
169 	mbedtls_mpi_init(&t);
170 	mbedtls_mpi_init(&eprime);
171 	mbedtls_mpi_init(&R);
172 
173 	mbedtls_ecp_point_init(&x1y1p);
174 	mbedtls_ecp_point_init(&PA);
175 
176 	mbedtls_ecp_group_init(&grp);
177 	mres = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SM2);
178 	if (mres) {
179 		res = TEE_ERROR_GENERIC;
180 		goto out;
181 	}
182 
183 	mres = mbedtls_mpi_read_binary(&rprime, sig, 32);
184 	if (mres)
185 		goto out;
186 	mres = mbedtls_mpi_read_binary(&sprime, sig + 32, 32);
187 	if (mres)
188 		goto out;
189 
190 	/* Step B1: verify r' in [1, n - 1] */
191 
192 	if (mbedtls_mpi_cmp_int(&rprime, 1) < 0 ||
193 	    mbedtls_mpi_cmp_mpi(&rprime, &grp.N) >= 0) {
194 		res = TEE_ERROR_SIGNATURE_INVALID;
195 		goto out;
196 	}
197 
198 	/* Step B2: verify s' in [1, n - 1] */
199 
200 	if (mbedtls_mpi_cmp_int(&sprime, 1) < 0 ||
201 	    mbedtls_mpi_cmp_mpi(&sprime, &grp.N) >= 0) {
202 		res = TEE_ERROR_SIGNATURE_INVALID;
203 		goto out;
204 	}
205 
206 	/*
207 	 * Steps B3: M'bar = (ZA || M') and B4: e' = Hv(M'bar) are not done here
208 	 * because @msg is supposed to contain the hash value e' already.
209 	 */
210 
211 	/* Step B5: t = (r' + s') mod n and check t != 0 */
212 
213 	mres = mbedtls_mpi_add_mpi(&t, &rprime, &sprime);
214 	if (mres)
215 		goto out;
216 	mres = mbedtls_mpi_mod_mpi(&t, &t, &grp.N);
217 	if (mres)
218 		goto out;
219 	if (!mbedtls_mpi_cmp_int(&t, 0)) {
220 		res = TEE_ERROR_SIGNATURE_INVALID;
221 		goto out;
222 	}
223 
224 	/* Step B6: (x1', y1') = [s']G + [t]PA */
225 
226 	mres = mbedtls_mpi_copy(&PA.X, (mbedtls_mpi *)key->x);
227 	if (mres)
228 		goto out;
229 	mres = mbedtls_mpi_copy(&PA.Y, (mbedtls_mpi *)key->y);
230 	if (mres)
231 		goto out;
232 	mres = mbedtls_mpi_lset(&PA.Z, 1);
233 	if (mres)
234 		goto out;
235 
236 	mres = mbedtls_ecp_muladd(&grp, &x1y1p, &sprime, &grp.G, &t, &PA);
237 	if (mres)
238 		goto out;
239 
240 	/* Step B7: compute R = (e' + x1') mod n and verify R == r' */
241 
242 	mres = mbedtls_mpi_read_binary(&eprime, msg, msg_len);
243 	if (mres)
244 		goto out;
245 	mres = mbedtls_mpi_add_mpi(&R, &eprime, &x1y1p.X);
246 	if (mres)
247 		goto out;
248 	mres = mbedtls_mpi_mod_mpi(&R, &R, &grp.N);
249 	if (mres)
250 		goto out;
251 	if (mbedtls_mpi_cmp_mpi(&R, &rprime)) {
252 		res = TEE_ERROR_SIGNATURE_INVALID;
253 		goto out;
254 	}
255 
256 	res = TEE_SUCCESS;
257 out:
258 	mbedtls_ecp_point_free(&x1y1p);
259 	mbedtls_ecp_point_free(&PA);
260 	mbedtls_mpi_free(&rprime);
261 	mbedtls_mpi_free(&sprime);
262 	mbedtls_mpi_free(&t);
263 	mbedtls_mpi_free(&eprime);
264 	mbedtls_mpi_free(&R);
265 	return res;
266 }
267