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