diff options
-rw-r--r-- | src/lib/libcrypto/sm2/sm2.h | 147 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_crypt.c | 632 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_err.c | 106 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_locl.h | 43 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_pmeth.c | 316 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_sign.c | 465 | ||||
-rw-r--r-- | src/lib/libcrypto/sm2/sm2_za.c | 161 |
7 files changed, 1870 insertions, 0 deletions
diff --git a/src/lib/libcrypto/sm2/sm2.h b/src/lib/libcrypto/sm2/sm2.h new file mode 100644 index 0000000000..92eef8a6de --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2.h | |||
@@ -0,0 +1,147 @@ | |||
1 | /* $OpenBSD: sm2.h,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef HEADER_SM2_H | ||
19 | #define HEADER_SM2_H | ||
20 | |||
21 | #include <openssl/opensslconf.h> | ||
22 | |||
23 | #include <openssl/ec.h> | ||
24 | #include <openssl/ecdsa.h> | ||
25 | |||
26 | #ifdef OPENSSL_NO_SM2 | ||
27 | #error SM2 is disabled. | ||
28 | #endif | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" { | ||
32 | #endif | ||
33 | |||
34 | /* | ||
35 | * SM2 signature generation. | ||
36 | */ | ||
37 | int SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, | ||
38 | unsigned int *siglen, EC_KEY *eckey); | ||
39 | |||
40 | /* | ||
41 | * SM2 signature verification. Assumes input is an SM3 digest | ||
42 | */ | ||
43 | int SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, | ||
44 | int siglen, EC_KEY *eckey); | ||
45 | |||
46 | /* | ||
47 | * SM2 encryption | ||
48 | */ | ||
49 | int SM2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
50 | size_t *c_size); | ||
51 | |||
52 | int SM2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
53 | size_t *pl_size); | ||
54 | |||
55 | int SM2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg, | ||
56 | size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len); | ||
57 | |||
58 | int SM2_decrypt(const EC_KEY *key, const EVP_MD *digest, | ||
59 | const uint8_t *ciphertext, size_t ciphertext_len, uint8_t *ptext_buf, | ||
60 | size_t *ptext_len); | ||
61 | |||
62 | /* BEGIN ERROR CODES */ | ||
63 | /* The following lines are auto generated by the script mkerr.pl. Any changes | ||
64 | * made after this point may be overwritten when the script is next run. | ||
65 | */ | ||
66 | void ERR_load_SM2_strings(void); | ||
67 | |||
68 | /* Error codes for the SM2 functions. */ | ||
69 | |||
70 | /* Function codes. */ | ||
71 | # define SM2_F_PKEY_SM2_CTRL 274 | ||
72 | # define SM2_F_PKEY_SM2_CTRL_STR 275 | ||
73 | # define SM2_F_PKEY_SM2_KEYGEN 276 | ||
74 | # define SM2_F_PKEY_SM2_PARAMGEN 277 | ||
75 | # define SM2_F_PKEY_SM2_SIGN 278 | ||
76 | # define SM2_F_PKEY_SM2_VERIFY 279 | ||
77 | # define SM2_F_PKEY_SM2_ENCRYPT 280 | ||
78 | # define SM2_F_PKEY_SM2_DECRYPT 281 | ||
79 | |||
80 | /* Reason codes. */ | ||
81 | # define SM2_R_ASN1_ERROR 115 | ||
82 | # define SM2_R_ASN5_ERROR 1150 | ||
83 | # define SM2_R_BAD_SIGNATURE 156 | ||
84 | # define SM2_R_BIGNUM_OUT_OF_RANGE 144 | ||
85 | # define SM2_R_BUFFER_TOO_SMALL 100 | ||
86 | # define SM2_R_COORDINATES_OUT_OF_RANGE 146 | ||
87 | # define SM2_R_CURVE_DOES_NOT_SUPPORT_ECDH 160 | ||
88 | # define SM2_R_CURVE_DOES_NOT_SUPPORT_SIGNING 159 | ||
89 | # define SM2_R_D2I_ECPKPARAMETERS_FAILURE 117 | ||
90 | # define SM2_R_DECODE_ERROR 142 | ||
91 | # define SM2_R_DIGEST_FAILURE 163 | ||
92 | # define SM2_R_DISCRIMINANT_IS_ZERO 118 | ||
93 | # define SM2_R_EC_GROUP_NEW_BY_NAME_FAILURE 119 | ||
94 | # define SM2_R_FIELD_TOO_LARGE 143 | ||
95 | # define SM2_R_GF2M_NOT_SUPPORTED 147 | ||
96 | # define SM2_R_GROUP2PKPARAMETERS_FAILURE 120 | ||
97 | # define SM2_R_I2D_ECPKPARAMETERS_FAILURE 121 | ||
98 | # define SM2_R_INCOMPATIBLE_OBJECTS 101 | ||
99 | # define SM2_R_INVALID_ARGUMENT 112 | ||
100 | # define SM2_R_INVALID_COMPRESSED_POINT 110 | ||
101 | # define SM2_R_INVALID_COMPRESSION_BIT 109 | ||
102 | # define SM2_R_INVALID_CURVE 141 | ||
103 | # define SM2_R_INVALID_DIGEST 151 | ||
104 | # define SM2_R_INVALID_DIGEST_TYPE 138 | ||
105 | # define SM2_R_INVALID_ENCODING 102 | ||
106 | # define SM2_R_INVALID_FIELD 103 | ||
107 | # define SM2_R_INVALID_FORM 104 | ||
108 | # define SM2_R_INVALID_GROUP_ORDER 122 | ||
109 | # define SM2_R_INVALID_KEY 116 | ||
110 | # define SM2_R_INVALID_OUTPUT_LENGTH 161 | ||
111 | # define SM2_R_INVALID_PEER_KEY 133 | ||
112 | # define SM2_R_INVALID_PENTANOMIAL_BASIS 132 | ||
113 | # define SM2_R_INVALID_PRIVATE_KEY 123 | ||
114 | # define SM2_R_INVALID_TRINOMIAL_BASIS 137 | ||
115 | # define SM2_R_KDF_FAILURE 162 | ||
116 | # define SM2_R_KDF_PARAMETER_ERROR 148 | ||
117 | # define SM2_R_KEYS_NOT_SET 140 | ||
118 | # define SM2_R_MISSING_PARAMETERS 124 | ||
119 | # define SM2_R_MISSING_PRIVATE_KEY 125 | ||
120 | # define SM2_R_NEED_NEW_SETUP_VALUES 157 | ||
121 | # define SM2_R_NOT_A_NIST_PRIME 135 | ||
122 | # define SM2_R_NOT_IMPLEMENTED 126 | ||
123 | # define SM2_R_NOT_INITIALIZED 111 | ||
124 | # define SM2_R_NO_PARAMETERS_SET 139 | ||
125 | # define SM2_R_NO_PRIVATE_VALUE 154 | ||
126 | # define SM2_R_OPERATION_NOT_SUPPORTED 152 | ||
127 | # define SM2_R_PASSED_NULL_PARAMETER 134 | ||
128 | # define SM2_R_PEER_KEY_ERROR 149 | ||
129 | # define SM2_R_PKPARAMETERS2GROUP_FAILURE 127 | ||
130 | # define SM2_R_POINT_ARITHMETIC_FAILURE 155 | ||
131 | # define SM2_R_POINT_AT_INFINITY 106 | ||
132 | # define SM2_R_POINT_IS_NOT_ON_CURVE 107 | ||
133 | # define SM2_R_RANDOM_NUMBER_GENERATION_FAILED 158 | ||
134 | # define SM2_R_SHARED_INFO_ERROR 150 | ||
135 | # define SM2_R_SLOT_FULL 108 | ||
136 | # define SM2_R_UNDEFINED_GENERATOR 113 | ||
137 | # define SM2_R_UNDEFINED_ORDER 128 | ||
138 | # define SM2_R_UNKNOWN_GROUP 129 | ||
139 | # define SM2_R_UNKNOWN_ORDER 114 | ||
140 | # define SM2_R_UNSUPPORTED_FIELD 131 | ||
141 | # define SM2_R_WRONG_CURVE_PARAMETERS 145 | ||
142 | # define SM2_R_WRONG_ORDER 130 | ||
143 | |||
144 | #ifdef __cplusplus | ||
145 | } | ||
146 | #endif | ||
147 | #endif | ||
diff --git a/src/lib/libcrypto/sm2/sm2_crypt.c b/src/lib/libcrypto/sm2/sm2_crypt.c new file mode 100644 index 0000000000..2bb3b8ff63 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_crypt.c | |||
@@ -0,0 +1,632 @@ | |||
1 | /* $OpenBSD: sm2_crypt.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef OPENSSL_NO_SM2 | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | #include <openssl/asn1.h> | ||
23 | #include <openssl/asn1t.h> | ||
24 | #include <openssl/bn.h> | ||
25 | #include <openssl/err.h> | ||
26 | #include <openssl/evp.h> | ||
27 | #include <openssl/sm2.h> | ||
28 | |||
29 | #include "sm2_locl.h" | ||
30 | |||
31 | typedef struct SM2_Ciphertext_st SM2_Ciphertext; | ||
32 | |||
33 | SM2_Ciphertext *SM2_Ciphertext_new(void); | ||
34 | void SM2_Ciphertext_free(SM2_Ciphertext *a); | ||
35 | SM2_Ciphertext *d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in, | ||
36 | long len); | ||
37 | int i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out); | ||
38 | |||
39 | struct SM2_Ciphertext_st { | ||
40 | BIGNUM *C1x; | ||
41 | BIGNUM *C1y; | ||
42 | ASN1_OCTET_STRING *C3; | ||
43 | ASN1_OCTET_STRING *C2; | ||
44 | }; | ||
45 | |||
46 | static const ASN1_TEMPLATE SM2_Ciphertext_seq_tt[] = { | ||
47 | { | ||
48 | .flags = 0, | ||
49 | .tag = 0, | ||
50 | .offset = offsetof(SM2_Ciphertext, C1x), | ||
51 | .field_name = "C1x", | ||
52 | .item = &BIGNUM_it, | ||
53 | }, | ||
54 | { | ||
55 | .flags = 0, | ||
56 | .tag = 0, | ||
57 | .offset = offsetof(SM2_Ciphertext, C1y), | ||
58 | .field_name = "C1y", | ||
59 | .item = &BIGNUM_it, | ||
60 | }, | ||
61 | { | ||
62 | .flags = 0, | ||
63 | .tag = 0, | ||
64 | .offset = offsetof(SM2_Ciphertext, C3), | ||
65 | .field_name = "C3", | ||
66 | .item = &ASN1_OCTET_STRING_it, | ||
67 | }, | ||
68 | { | ||
69 | .flags = 0, | ||
70 | .tag = 0, | ||
71 | .offset = offsetof(SM2_Ciphertext, C2), | ||
72 | .field_name = "C2", | ||
73 | .item = &ASN1_OCTET_STRING_it, | ||
74 | }, | ||
75 | }; | ||
76 | |||
77 | const ASN1_ITEM SM2_Ciphertext_it = { | ||
78 | .itype = ASN1_ITYPE_SEQUENCE, | ||
79 | .utype = V_ASN1_SEQUENCE, | ||
80 | .templates = SM2_Ciphertext_seq_tt, | ||
81 | .tcount = sizeof(SM2_Ciphertext_seq_tt) / sizeof(ASN1_TEMPLATE), | ||
82 | .funcs = NULL, | ||
83 | .size = sizeof(SM2_Ciphertext), | ||
84 | .sname = "SM2_Ciphertext", | ||
85 | }; | ||
86 | |||
87 | SM2_Ciphertext * | ||
88 | d2i_SM2_Ciphertext(SM2_Ciphertext **a, const unsigned char **in, long len) | ||
89 | { | ||
90 | return (SM2_Ciphertext *) ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
91 | &SM2_Ciphertext_it); | ||
92 | } | ||
93 | |||
94 | int | ||
95 | i2d_SM2_Ciphertext(SM2_Ciphertext *a, unsigned char **out) | ||
96 | { | ||
97 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &SM2_Ciphertext_it); | ||
98 | } | ||
99 | |||
100 | SM2_Ciphertext * | ||
101 | SM2_Ciphertext_new(void) | ||
102 | { | ||
103 | return (SM2_Ciphertext *)ASN1_item_new(&SM2_Ciphertext_it); | ||
104 | } | ||
105 | |||
106 | void | ||
107 | SM2_Ciphertext_free(SM2_Ciphertext *a) | ||
108 | { | ||
109 | ASN1_item_free((ASN1_VALUE *)a, &SM2_Ciphertext_it); | ||
110 | } | ||
111 | |||
112 | static size_t | ||
113 | ec_field_size(const EC_GROUP *group) | ||
114 | { | ||
115 | /* Is there some simpler way to do this? */ | ||
116 | BIGNUM *p; | ||
117 | size_t field_size = 0; | ||
118 | |||
119 | if ((p = BN_new()) == NULL) | ||
120 | goto err; | ||
121 | if (!EC_GROUP_get_curve(group, p, NULL, NULL, NULL)) | ||
122 | goto err; | ||
123 | field_size = BN_num_bytes(p); | ||
124 | err: | ||
125 | BN_free(p); | ||
126 | return field_size; | ||
127 | } | ||
128 | |||
129 | int | ||
130 | SM2_plaintext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
131 | size_t *pl_size) | ||
132 | { | ||
133 | size_t field_size, overhead; | ||
134 | int md_size; | ||
135 | |||
136 | if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) { | ||
137 | SM2error(SM2_R_INVALID_FIELD); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
142 | SM2error(SM2_R_INVALID_DIGEST); | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | overhead = 10 + 2 * field_size + md_size; | ||
147 | if (msg_len <= overhead) { | ||
148 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | *pl_size = msg_len - overhead; | ||
153 | return 1; | ||
154 | } | ||
155 | |||
156 | int | ||
157 | SM2_ciphertext_size(const EC_KEY *key, const EVP_MD *digest, size_t msg_len, | ||
158 | size_t *c_size) | ||
159 | { | ||
160 | size_t asn_size, field_size; | ||
161 | int md_size; | ||
162 | |||
163 | if ((field_size = ec_field_size(EC_KEY_get0_group(key))) == 0) { | ||
164 | SM2error(SM2_R_INVALID_FIELD); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
169 | SM2error(SM2_R_INVALID_DIGEST); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | asn_size = 2 * ASN1_object_size(0, field_size + 1, V_ASN1_INTEGER) + | ||
174 | ASN1_object_size(0, md_size, V_ASN1_OCTET_STRING) + | ||
175 | ASN1_object_size(0, msg_len, V_ASN1_OCTET_STRING); | ||
176 | |||
177 | *c_size = ASN1_object_size(1, asn_size, V_ASN1_SEQUENCE); | ||
178 | return 1; | ||
179 | } | ||
180 | |||
181 | int | ||
182 | sm2_kdf(uint8_t *key, size_t key_len, uint8_t *secret, size_t secret_len, | ||
183 | const EVP_MD *digest) | ||
184 | { | ||
185 | EVP_MD_CTX *hash; | ||
186 | uint8_t *hash_buf = NULL; | ||
187 | uint32_t ctr = 1; | ||
188 | uint8_t ctr_buf[4] = {0}; | ||
189 | size_t hadd, hlen; | ||
190 | int rc = 0; | ||
191 | |||
192 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
193 | SM2error(ERR_R_MALLOC_FAILURE); | ||
194 | goto err; | ||
195 | } | ||
196 | |||
197 | if ((hlen = EVP_MD_size(digest)) < 0) { | ||
198 | SM2error(SM2_R_INVALID_DIGEST); | ||
199 | goto err; | ||
200 | } | ||
201 | if ((hash_buf = malloc(hlen)) == NULL) { | ||
202 | SM2error(ERR_R_MALLOC_FAILURE); | ||
203 | goto err; | ||
204 | } | ||
205 | |||
206 | EVP_MD_CTX_init(hash); | ||
207 | while ((key_len > 0) && (ctr != 0)) { | ||
208 | if (!EVP_DigestInit_ex(hash, digest, NULL)) { | ||
209 | SM2error(ERR_R_EVP_LIB); | ||
210 | goto err; | ||
211 | } | ||
212 | if (!EVP_DigestUpdate(hash, secret, secret_len)) { | ||
213 | SM2error(ERR_R_EVP_LIB); | ||
214 | goto err; | ||
215 | } | ||
216 | |||
217 | /* big-endian counter representation */ | ||
218 | ctr_buf[0] = (ctr >> 24) & 0xff; | ||
219 | ctr_buf[1] = (ctr >> 16) & 0xff; | ||
220 | ctr_buf[2] = (ctr >> 8) & 0xff; | ||
221 | ctr_buf[3] = ctr & 0xff; | ||
222 | ctr++; | ||
223 | |||
224 | if (!EVP_DigestUpdate(hash, ctr_buf, 4)) { | ||
225 | SM2error(ERR_R_EVP_LIB); | ||
226 | goto err; | ||
227 | } | ||
228 | if (!EVP_DigestFinal(hash, hash_buf, NULL)) { | ||
229 | SM2error(ERR_R_EVP_LIB); | ||
230 | goto err; | ||
231 | } | ||
232 | |||
233 | hadd = key_len > hlen ? hlen : key_len; | ||
234 | memcpy(key, hash_buf, hadd); | ||
235 | memset(hash_buf, 0, hlen); | ||
236 | key_len -= hadd; | ||
237 | key += hadd; | ||
238 | } | ||
239 | |||
240 | rc = 1; | ||
241 | err: | ||
242 | free(hash_buf); | ||
243 | EVP_MD_CTX_free(hash); | ||
244 | return rc; | ||
245 | } | ||
246 | |||
247 | int | ||
248 | SM2_encrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *msg, | ||
249 | size_t msg_len, uint8_t *ciphertext_buf, size_t *ciphertext_len) | ||
250 | { | ||
251 | SM2_Ciphertext ctext_struct; | ||
252 | EVP_MD_CTX *hash = NULL; | ||
253 | BN_CTX *ctx = NULL; | ||
254 | BIGNUM *order = NULL; | ||
255 | BIGNUM *k, *x1, *y1, *x2, *y2; | ||
256 | const EC_GROUP *group; | ||
257 | const EC_POINT *P; | ||
258 | EC_POINT *kG = NULL, *kP = NULL; | ||
259 | uint8_t *msg_mask = NULL, *x2y2 = NULL, *C3 = NULL; | ||
260 | size_t C3_size, field_size, i, x2size, y2size; | ||
261 | int rc = 0; | ||
262 | int clen; | ||
263 | |||
264 | ctext_struct.C2 = NULL; | ||
265 | ctext_struct.C3 = NULL; | ||
266 | |||
267 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
268 | SM2error(ERR_R_MALLOC_FAILURE); | ||
269 | goto err; | ||
270 | } | ||
271 | |||
272 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
273 | SM2error(SM2_R_INVALID_KEY); | ||
274 | goto err; | ||
275 | } | ||
276 | |||
277 | if ((order = BN_new()) == NULL) { | ||
278 | SM2error(ERR_R_MALLOC_FAILURE); | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
283 | SM2error(SM2_R_INVALID_GROUP_ORDER); | ||
284 | goto err; | ||
285 | } | ||
286 | |||
287 | if ((P = EC_KEY_get0_public_key(key)) == NULL) { | ||
288 | SM2error(SM2_R_INVALID_KEY); | ||
289 | goto err; | ||
290 | } | ||
291 | |||
292 | if ((field_size = ec_field_size(group)) == 0) { | ||
293 | SM2error(SM2_R_INVALID_FIELD); | ||
294 | goto err; | ||
295 | } | ||
296 | |||
297 | if ((C3_size = EVP_MD_size(digest)) < 0) { | ||
298 | SM2error(SM2_R_INVALID_DIGEST); | ||
299 | goto err; | ||
300 | } | ||
301 | |||
302 | if ((kG = EC_POINT_new(group)) == NULL) { | ||
303 | SM2error(ERR_R_MALLOC_FAILURE); | ||
304 | goto err; | ||
305 | } | ||
306 | if ((kP = EC_POINT_new(group)) == NULL) { | ||
307 | SM2error(ERR_R_MALLOC_FAILURE); | ||
308 | goto err; | ||
309 | } | ||
310 | |||
311 | if ((ctx = BN_CTX_new()) == NULL) { | ||
312 | SM2error(ERR_R_MALLOC_FAILURE); | ||
313 | goto err; | ||
314 | } | ||
315 | |||
316 | BN_CTX_start(ctx); | ||
317 | if ((k = BN_CTX_get(ctx)) == NULL) { | ||
318 | SM2error(ERR_R_BN_LIB); | ||
319 | goto err; | ||
320 | } | ||
321 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
322 | SM2error(ERR_R_BN_LIB); | ||
323 | goto err; | ||
324 | } | ||
325 | if ((x2 = BN_CTX_get(ctx)) == NULL) { | ||
326 | SM2error(ERR_R_BN_LIB); | ||
327 | goto err; | ||
328 | } | ||
329 | if ((y1 = BN_CTX_get(ctx)) == NULL) { | ||
330 | SM2error(ERR_R_BN_LIB); | ||
331 | goto err; | ||
332 | } | ||
333 | if ((y2 = BN_CTX_get(ctx)) == NULL) { | ||
334 | SM2error(ERR_R_BN_LIB); | ||
335 | goto err; | ||
336 | } | ||
337 | |||
338 | if ((x2y2 = calloc(2, field_size)) == NULL) { | ||
339 | SM2error(ERR_R_MALLOC_FAILURE); | ||
340 | goto err; | ||
341 | } | ||
342 | |||
343 | if ((C3 = calloc(1, C3_size)) == NULL) { | ||
344 | SM2error(ERR_R_MALLOC_FAILURE); | ||
345 | goto err; | ||
346 | } | ||
347 | |||
348 | memset(ciphertext_buf, 0, *ciphertext_len); | ||
349 | |||
350 | if (!BN_rand_range(k, order)) { | ||
351 | SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED); | ||
352 | goto err; | ||
353 | } | ||
354 | |||
355 | if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) { | ||
356 | SM2error(ERR_R_EC_LIB); | ||
357 | goto err; | ||
358 | } | ||
359 | |||
360 | if (!EC_POINT_get_affine_coordinates(group, kG, x1, y1, ctx)) { | ||
361 | SM2error(ERR_R_EC_LIB); | ||
362 | goto err; | ||
363 | } | ||
364 | |||
365 | if (!EC_POINT_mul(group, kP, NULL, P, k, ctx)) { | ||
366 | SM2error(ERR_R_EC_LIB); | ||
367 | goto err; | ||
368 | } | ||
369 | |||
370 | if (!EC_POINT_get_affine_coordinates(group, kP, x2, y2, ctx)) { | ||
371 | SM2error(ERR_R_EC_LIB); | ||
372 | goto err; | ||
373 | } | ||
374 | |||
375 | if ((x2size = BN_num_bytes(x2)) > field_size || | ||
376 | (y2size = BN_num_bytes(y2)) > field_size) { | ||
377 | SM2error(SM2_R_BIGNUM_OUT_OF_RANGE); | ||
378 | goto err; | ||
379 | } | ||
380 | |||
381 | BN_bn2bin(x2, x2y2 + field_size - x2size); | ||
382 | BN_bn2bin(y2, x2y2 + 2 * field_size - y2size); | ||
383 | |||
384 | if ((msg_mask = calloc(1, msg_len)) == NULL) { | ||
385 | SM2error(ERR_R_MALLOC_FAILURE); | ||
386 | goto err; | ||
387 | } | ||
388 | |||
389 | if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) { | ||
390 | SM2error(SM2_R_KDF_FAILURE); | ||
391 | goto err; | ||
392 | } | ||
393 | |||
394 | for (i = 0; i != msg_len; i++) | ||
395 | msg_mask[i] ^= msg[i]; | ||
396 | |||
397 | if (!EVP_DigestInit(hash, digest)) { | ||
398 | SM2error(ERR_R_EVP_LIB); | ||
399 | goto err; | ||
400 | } | ||
401 | |||
402 | if (!EVP_DigestUpdate(hash, x2y2, field_size)) { | ||
403 | SM2error(ERR_R_EVP_LIB); | ||
404 | goto err; | ||
405 | } | ||
406 | |||
407 | if (!EVP_DigestUpdate(hash, msg, msg_len)) { | ||
408 | SM2error(ERR_R_EVP_LIB); | ||
409 | goto err; | ||
410 | } | ||
411 | |||
412 | if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) { | ||
413 | SM2error(ERR_R_EVP_LIB); | ||
414 | goto err; | ||
415 | } | ||
416 | |||
417 | if (!EVP_DigestFinal(hash, C3, NULL)) { | ||
418 | SM2error(ERR_R_EVP_LIB); | ||
419 | goto err; | ||
420 | } | ||
421 | |||
422 | ctext_struct.C1x = x1; | ||
423 | ctext_struct.C1y = y1; | ||
424 | if ((ctext_struct.C3 = ASN1_OCTET_STRING_new()) == NULL) { | ||
425 | SM2error(ERR_R_MALLOC_FAILURE); | ||
426 | goto err; | ||
427 | } | ||
428 | if ((ctext_struct.C2 = ASN1_OCTET_STRING_new()) == NULL) { | ||
429 | SM2error(ERR_R_MALLOC_FAILURE); | ||
430 | goto err; | ||
431 | } | ||
432 | if (!ASN1_OCTET_STRING_set(ctext_struct.C3, C3, C3_size)) { | ||
433 | SM2error(ERR_R_INTERNAL_ERROR); | ||
434 | goto err; | ||
435 | } | ||
436 | if (!ASN1_OCTET_STRING_set(ctext_struct.C2, msg_mask, msg_len)) { | ||
437 | SM2error(ERR_R_INTERNAL_ERROR); | ||
438 | goto err; | ||
439 | } | ||
440 | |||
441 | if ((clen = i2d_SM2_Ciphertext(&ctext_struct, &ciphertext_buf)) < 0) { | ||
442 | SM2error(ERR_R_INTERNAL_ERROR); | ||
443 | goto err; | ||
444 | } | ||
445 | |||
446 | *ciphertext_len = clen; | ||
447 | rc = 1; | ||
448 | |||
449 | err: | ||
450 | ASN1_OCTET_STRING_free(ctext_struct.C2); | ||
451 | ASN1_OCTET_STRING_free(ctext_struct.C3); | ||
452 | free(msg_mask); | ||
453 | free(x2y2); | ||
454 | free(C3); | ||
455 | EVP_MD_CTX_free(hash); | ||
456 | BN_CTX_end(ctx); | ||
457 | BN_CTX_free(ctx); | ||
458 | EC_POINT_free(kG); | ||
459 | EC_POINT_free(kP); | ||
460 | BN_free(order); | ||
461 | return rc; | ||
462 | } | ||
463 | |||
464 | int | ||
465 | SM2_decrypt(const EC_KEY *key, const EVP_MD *digest, const uint8_t *ciphertext, | ||
466 | size_t ciphertext_len, uint8_t *ptext_buf, size_t *ptext_len) | ||
467 | { | ||
468 | SM2_Ciphertext *sm2_ctext = NULL; | ||
469 | EVP_MD_CTX *hash = NULL; | ||
470 | BN_CTX *ctx = NULL; | ||
471 | BIGNUM *x2, *y2; | ||
472 | const EC_GROUP *group; | ||
473 | EC_POINT *C1 = NULL; | ||
474 | const uint8_t *C2, *C3; | ||
475 | uint8_t *computed_C3 = NULL, *msg_mask = NULL, *x2y2 = NULL; | ||
476 | size_t field_size, x2size, y2size; | ||
477 | int msg_len = 0, rc = 0; | ||
478 | int hash_size, i; | ||
479 | |||
480 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
481 | SM2error(SM2_R_INVALID_KEY); | ||
482 | goto err; | ||
483 | } | ||
484 | |||
485 | if ((field_size = ec_field_size(group)) == 0) { | ||
486 | SM2error(SM2_R_INVALID_FIELD); | ||
487 | goto err; | ||
488 | } | ||
489 | |||
490 | if ((hash_size = EVP_MD_size(digest)) < 0) { | ||
491 | SM2error(SM2_R_INVALID_DIGEST); | ||
492 | goto err; | ||
493 | } | ||
494 | |||
495 | memset(ptext_buf, 0xFF, *ptext_len); | ||
496 | |||
497 | if ((sm2_ctext = d2i_SM2_Ciphertext(NULL, &ciphertext, | ||
498 | ciphertext_len)) == NULL) { | ||
499 | SM2error(SM2_R_ASN1_ERROR); | ||
500 | goto err; | ||
501 | } | ||
502 | |||
503 | if (sm2_ctext->C3->length != hash_size) { | ||
504 | SM2error(SM2_R_INVALID_ENCODING); | ||
505 | goto err; | ||
506 | } | ||
507 | |||
508 | C2 = sm2_ctext->C2->data; | ||
509 | C3 = sm2_ctext->C3->data; | ||
510 | msg_len = sm2_ctext->C2->length; | ||
511 | |||
512 | if ((ctx = BN_CTX_new()) == NULL) { | ||
513 | SM2error(ERR_R_MALLOC_FAILURE); | ||
514 | goto err; | ||
515 | } | ||
516 | |||
517 | BN_CTX_start(ctx); | ||
518 | if ((x2 = BN_CTX_get(ctx)) == NULL) { | ||
519 | SM2error(ERR_R_BN_LIB); | ||
520 | goto err; | ||
521 | } | ||
522 | if ((y2 = BN_CTX_get(ctx)) == NULL) { | ||
523 | SM2error(ERR_R_BN_LIB); | ||
524 | goto err; | ||
525 | } | ||
526 | |||
527 | if ((msg_mask = calloc(1, msg_len)) == NULL) { | ||
528 | SM2error(ERR_R_MALLOC_FAILURE); | ||
529 | goto err; | ||
530 | } | ||
531 | if ((x2y2 = calloc(2, field_size)) == NULL) { | ||
532 | SM2error(ERR_R_MALLOC_FAILURE); | ||
533 | goto err; | ||
534 | } | ||
535 | if ((computed_C3 = calloc(1, hash_size)) == NULL) { | ||
536 | SM2error(ERR_R_MALLOC_FAILURE); | ||
537 | goto err; | ||
538 | } | ||
539 | |||
540 | if ((C1 = EC_POINT_new(group)) == NULL) { | ||
541 | SM2error(ERR_R_MALLOC_FAILURE); | ||
542 | goto err; | ||
543 | } | ||
544 | |||
545 | if (!EC_POINT_set_affine_coordinates(group, C1, sm2_ctext->C1x, | ||
546 | sm2_ctext->C1y, ctx)) | ||
547 | { | ||
548 | SM2error(ERR_R_EC_LIB); | ||
549 | goto err; | ||
550 | } | ||
551 | |||
552 | if (!EC_POINT_mul(group, C1, NULL, C1, EC_KEY_get0_private_key(key), | ||
553 | ctx)) { | ||
554 | SM2error(ERR_R_EC_LIB); | ||
555 | goto err; | ||
556 | } | ||
557 | |||
558 | if (!EC_POINT_get_affine_coordinates(group, C1, x2, y2, ctx)) { | ||
559 | SM2error(ERR_R_EC_LIB); | ||
560 | goto err; | ||
561 | } | ||
562 | |||
563 | if ((x2size = BN_num_bytes(x2)) > field_size || | ||
564 | (y2size = BN_num_bytes(y2)) > field_size) { | ||
565 | SM2error(SM2_R_BIGNUM_OUT_OF_RANGE); | ||
566 | goto err; | ||
567 | } | ||
568 | |||
569 | BN_bn2bin(x2, x2y2 + field_size - x2size); | ||
570 | BN_bn2bin(y2, x2y2 + 2 * field_size - y2size); | ||
571 | |||
572 | if (!sm2_kdf(msg_mask, msg_len, x2y2, 2 * field_size, digest)) { | ||
573 | SM2error(SM2_R_KDF_FAILURE); | ||
574 | goto err; | ||
575 | } | ||
576 | |||
577 | for (i = 0; i != msg_len; ++i) | ||
578 | ptext_buf[i] = C2[i] ^ msg_mask[i]; | ||
579 | |||
580 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
581 | SM2error(ERR_R_EVP_LIB); | ||
582 | goto err; | ||
583 | } | ||
584 | |||
585 | if (!EVP_DigestInit(hash, digest)) { | ||
586 | SM2error(ERR_R_EVP_LIB); | ||
587 | goto err; | ||
588 | } | ||
589 | |||
590 | if (!EVP_DigestUpdate(hash, x2y2, field_size)) { | ||
591 | SM2error(ERR_R_EVP_LIB); | ||
592 | goto err; | ||
593 | } | ||
594 | |||
595 | if (!EVP_DigestUpdate(hash, ptext_buf, msg_len)) { | ||
596 | SM2error(ERR_R_EVP_LIB); | ||
597 | goto err; | ||
598 | } | ||
599 | |||
600 | if (!EVP_DigestUpdate(hash, x2y2 + field_size, field_size)) { | ||
601 | SM2error(ERR_R_EVP_LIB); | ||
602 | goto err; | ||
603 | } | ||
604 | |||
605 | if (!EVP_DigestFinal(hash, computed_C3, NULL)) { | ||
606 | SM2error(ERR_R_EVP_LIB); | ||
607 | goto err; | ||
608 | } | ||
609 | |||
610 | if (memcmp(computed_C3, C3, hash_size) != 0) | ||
611 | goto err; | ||
612 | |||
613 | rc = 1; | ||
614 | *ptext_len = msg_len; | ||
615 | |||
616 | err: | ||
617 | if (rc == 0) | ||
618 | memset(ptext_buf, 0, *ptext_len); | ||
619 | |||
620 | free(msg_mask); | ||
621 | free(x2y2); | ||
622 | free(computed_C3); | ||
623 | EC_POINT_free(C1); | ||
624 | BN_CTX_end(ctx); | ||
625 | BN_CTX_free(ctx); | ||
626 | SM2_Ciphertext_free(sm2_ctext); | ||
627 | EVP_MD_CTX_free(hash); | ||
628 | |||
629 | return rc; | ||
630 | } | ||
631 | |||
632 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_err.c b/src/lib/libcrypto/sm2/sm2_err.c new file mode 100644 index 0000000000..d34123cbf9 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_err.c | |||
@@ -0,0 +1,106 @@ | |||
1 | /* $OpenBSD: sm2_err.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Generated by util/mkerr.pl DO NOT EDIT | ||
4 | * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. | ||
5 | * | ||
6 | * Licensed under the OpenSSL license (the "License"). You may not use | ||
7 | * this file except in compliance with the License. You can obtain a copy | ||
8 | * in the file LICENSE in the source distribution or at | ||
9 | * https://www.openssl.org/source/license.html | ||
10 | */ | ||
11 | |||
12 | #ifndef OPENSSL_NO_SM2 | ||
13 | |||
14 | #include <openssl/err.h> | ||
15 | #include <openssl/sm2.h> | ||
16 | |||
17 | #ifndef OPENSSL_NO_ERR | ||
18 | |||
19 | #define ERR_FUNC(func) ERR_PACK(ERR_LIB_SM2,func,0) | ||
20 | #define ERR_REASON(reason) ERR_PACK(ERR_LIB_SM2,0,reason) | ||
21 | |||
22 | static ERR_STRING_DATA SM2_str_functs[] = { | ||
23 | {ERR_FUNC(0xfff), "CRYPTO_internal"}, | ||
24 | {0, NULL} | ||
25 | }; | ||
26 | |||
27 | static ERR_STRING_DATA SM2_str_reasons[] = { | ||
28 | {ERR_REASON(SM2_R_ASN1_ERROR), "asn1 error"}, | ||
29 | {ERR_REASON(SM2_R_ASN5_ERROR), "asn5 error"}, | ||
30 | {ERR_REASON(SM2_R_BAD_SIGNATURE), "bad signature"}, | ||
31 | {ERR_REASON(SM2_R_BIGNUM_OUT_OF_RANGE), "bignum out of range"}, | ||
32 | {ERR_REASON(SM2_R_BUFFER_TOO_SMALL), "buffer too small"}, | ||
33 | {ERR_REASON(SM2_R_COORDINATES_OUT_OF_RANGE), "coordinates out of range"}, | ||
34 | {ERR_REASON(SM2_R_CURVE_DOES_NOT_SUPPORT_ECDH), "curve does not support ecdh"}, | ||
35 | {ERR_REASON(SM2_R_CURVE_DOES_NOT_SUPPORT_SIGNING), "curve does not support signing"}, | ||
36 | {ERR_REASON(SM2_R_D2I_ECPKPARAMETERS_FAILURE), "d2i ecpkparameters failure"}, | ||
37 | {ERR_REASON(SM2_R_DECODE_ERROR), "decode error"}, | ||
38 | {ERR_REASON(SM2_R_DIGEST_FAILURE), "digest calculation failure"}, | ||
39 | {ERR_REASON(SM2_R_DISCRIMINANT_IS_ZERO), "discriminant is zero"}, | ||
40 | {ERR_REASON(SM2_R_EC_GROUP_NEW_BY_NAME_FAILURE), "ec group new by name failure"}, | ||
41 | {ERR_REASON(SM2_R_FIELD_TOO_LARGE), "field too large"}, | ||
42 | {ERR_REASON(SM2_R_GF2M_NOT_SUPPORTED), "gf2m not supported"}, | ||
43 | {ERR_REASON(SM2_R_GROUP2PKPARAMETERS_FAILURE), "group2pkparameters failure"}, | ||
44 | {ERR_REASON(SM2_R_I2D_ECPKPARAMETERS_FAILURE), "i2d ecpkparameters failure"}, | ||
45 | {ERR_REASON(SM2_R_INCOMPATIBLE_OBJECTS), "incompatible objects"}, | ||
46 | {ERR_REASON(SM2_R_INVALID_ARGUMENT), "invalid argument"}, | ||
47 | {ERR_REASON(SM2_R_INVALID_COMPRESSED_POINT), "invalid compressed point"}, | ||
48 | {ERR_REASON(SM2_R_INVALID_COMPRESSION_BIT), "invalid compression bit"}, | ||
49 | {ERR_REASON(SM2_R_INVALID_CURVE), "invalid curve"}, | ||
50 | {ERR_REASON(SM2_R_INVALID_DIGEST), "invalid digest"}, | ||
51 | {ERR_REASON(SM2_R_INVALID_DIGEST_TYPE), "invalid digest type"}, | ||
52 | {ERR_REASON(SM2_R_INVALID_ENCODING), "invalid encoding"}, | ||
53 | {ERR_REASON(SM2_R_INVALID_FIELD), "invalid field"}, | ||
54 | {ERR_REASON(SM2_R_INVALID_FORM), "invalid form"}, | ||
55 | {ERR_REASON(SM2_R_INVALID_GROUP_ORDER), "invalid group order"}, | ||
56 | {ERR_REASON(SM2_R_INVALID_KEY), "invalid key"}, | ||
57 | {ERR_REASON(SM2_R_INVALID_OUTPUT_LENGTH), "invalid output length"}, | ||
58 | {ERR_REASON(SM2_R_INVALID_PEER_KEY), "invalid peer key"}, | ||
59 | {ERR_REASON(SM2_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, | ||
60 | {ERR_REASON(SM2_R_INVALID_PRIVATE_KEY), "invalid private key"}, | ||
61 | {ERR_REASON(SM2_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"}, | ||
62 | {ERR_REASON(SM2_R_KDF_FAILURE), "kdf calculation failure"}, | ||
63 | {ERR_REASON(SM2_R_KDF_PARAMETER_ERROR), "kdf parameter error"}, | ||
64 | {ERR_REASON(SM2_R_KEYS_NOT_SET), "keys not set"}, | ||
65 | {ERR_REASON(SM2_R_MISSING_PARAMETERS), "missing parameters"}, | ||
66 | {ERR_REASON(SM2_R_MISSING_PRIVATE_KEY), "missing private key"}, | ||
67 | {ERR_REASON(SM2_R_NEED_NEW_SETUP_VALUES), "need new setup values"}, | ||
68 | {ERR_REASON(SM2_R_NOT_A_NIST_PRIME), "not a NIST prime"}, | ||
69 | {ERR_REASON(SM2_R_NOT_IMPLEMENTED), "not implemented"}, | ||
70 | {ERR_REASON(SM2_R_NOT_INITIALIZED), "not initialized"}, | ||
71 | {ERR_REASON(SM2_R_NO_PARAMETERS_SET), "no parameters set"}, | ||
72 | {ERR_REASON(SM2_R_NO_PRIVATE_VALUE), "no private value"}, | ||
73 | {ERR_REASON(SM2_R_OPERATION_NOT_SUPPORTED), "operation not supported"}, | ||
74 | {ERR_REASON(SM2_R_PASSED_NULL_PARAMETER), "passed null parameter"}, | ||
75 | {ERR_REASON(SM2_R_PEER_KEY_ERROR), "peer key error"}, | ||
76 | {ERR_REASON(SM2_R_PKPARAMETERS2GROUP_FAILURE), "pkparameters2group failure"}, | ||
77 | {ERR_REASON(SM2_R_POINT_ARITHMETIC_FAILURE), "point arithmetic failure"}, | ||
78 | {ERR_REASON(SM2_R_POINT_AT_INFINITY), "point at infinity"}, | ||
79 | {ERR_REASON(SM2_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"}, | ||
80 | {ERR_REASON(SM2_R_RANDOM_NUMBER_GENERATION_FAILED), "random number generation failed"}, | ||
81 | {ERR_REASON(SM2_R_SHARED_INFO_ERROR), "shared info error"}, | ||
82 | {ERR_REASON(SM2_R_SLOT_FULL), "slot full"}, | ||
83 | {ERR_REASON(SM2_R_UNDEFINED_GENERATOR), "undefined generator"}, | ||
84 | {ERR_REASON(SM2_R_UNDEFINED_ORDER), "undefined order"}, | ||
85 | {ERR_REASON(SM2_R_UNKNOWN_GROUP), "unknown group"}, | ||
86 | {ERR_REASON(SM2_R_UNKNOWN_ORDER), "unknown order"}, | ||
87 | {ERR_REASON(SM2_R_UNSUPPORTED_FIELD), "unsupported field"}, | ||
88 | {ERR_REASON(SM2_R_WRONG_CURVE_PARAMETERS), "wrong curve parameters"}, | ||
89 | {ERR_REASON(SM2_R_WRONG_ORDER), "wrong order"}, | ||
90 | {0, NULL} | ||
91 | }; | ||
92 | |||
93 | #endif | ||
94 | |||
95 | void | ||
96 | ERR_load_SM2_strings(void) | ||
97 | { | ||
98 | #ifndef OPENSSL_NO_ERR | ||
99 | if (ERR_func_error_string(SM2_str_functs[0].error) == NULL) { | ||
100 | ERR_load_strings(0, SM2_str_functs); | ||
101 | ERR_load_strings(0, SM2_str_reasons); | ||
102 | } | ||
103 | #endif | ||
104 | } | ||
105 | |||
106 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_locl.h b/src/lib/libcrypto/sm2/sm2_locl.h new file mode 100644 index 0000000000..2e1626824f --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_locl.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /* $OpenBSD: sm2_locl.h,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef HEADER_SM2_LOCL_H | ||
19 | #define HEADER_SM2_LOCL_H | ||
20 | |||
21 | #include <openssl/ec.h> | ||
22 | #include <openssl/ecdsa.h> | ||
23 | |||
24 | __BEGIN_HIDDEN_DECLS | ||
25 | |||
26 | int sm2_compute_userid_digest(uint8_t *out, const EVP_MD *digest, | ||
27 | const uint8_t *uid, size_t uid_len, const EC_KEY *key); | ||
28 | |||
29 | /* | ||
30 | * SM2 signature operation. Computes ZA (user id digest) and then signs | ||
31 | * H(ZA || msg) using SM2 | ||
32 | */ | ||
33 | ECDSA_SIG *sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, | ||
34 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len); | ||
35 | |||
36 | int sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, | ||
37 | const ECDSA_SIG *signature, const uint8_t *uid, size_t uid_len, | ||
38 | const uint8_t *msg, size_t msg_len); | ||
39 | |||
40 | __END_HIDDEN_DECLS | ||
41 | |||
42 | #endif | ||
43 | |||
diff --git a/src/lib/libcrypto/sm2/sm2_pmeth.c b/src/lib/libcrypto/sm2/sm2_pmeth.c new file mode 100644 index 0000000000..af6e180a70 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_pmeth.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* $OpenBSD: sm2_pmeth.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef OPENSSL_NO_SM2 | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | #include <openssl/sm2.h> | ||
23 | #include <openssl/asn1t.h> | ||
24 | #include <openssl/x509.h> | ||
25 | #include <openssl/err.h> | ||
26 | #include <openssl/evp.h> | ||
27 | |||
28 | #include "evp_locl.h" | ||
29 | #include "sm2_locl.h" | ||
30 | |||
31 | /* SM2 pkey context structure */ | ||
32 | |||
33 | typedef struct { | ||
34 | /* key and paramgen group */ | ||
35 | EC_GROUP *gen_group; | ||
36 | /* message digest */ | ||
37 | const EVP_MD *md; | ||
38 | EVP_MD_CTX *md_ctx; | ||
39 | /* personalization string */ | ||
40 | uint8_t* uid; | ||
41 | size_t uid_len; | ||
42 | } SM2_PKEY_CTX; | ||
43 | |||
44 | static int | ||
45 | pkey_sm2_init(EVP_PKEY_CTX *ctx) | ||
46 | { | ||
47 | SM2_PKEY_CTX *dctx; | ||
48 | |||
49 | if ((dctx = calloc(1, sizeof(*dctx))) == NULL) { | ||
50 | SM2error(ERR_R_MALLOC_FAILURE); | ||
51 | return 0; | ||
52 | } | ||
53 | ctx->data = dctx; | ||
54 | return 1; | ||
55 | } | ||
56 | |||
57 | static void | ||
58 | pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) | ||
59 | { | ||
60 | SM2_PKEY_CTX *dctx = ctx->data; | ||
61 | |||
62 | if (ctx == NULL || ctx->data == NULL) | ||
63 | return; | ||
64 | |||
65 | EC_GROUP_free(dctx->gen_group); | ||
66 | free(dctx->uid); | ||
67 | free(dctx); | ||
68 | ctx->data = NULL; | ||
69 | } | ||
70 | |||
71 | static int | ||
72 | pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) | ||
73 | { | ||
74 | SM2_PKEY_CTX *dctx, *sctx; | ||
75 | |||
76 | if (!pkey_sm2_init(dst)) | ||
77 | return 0; | ||
78 | sctx = src->data; | ||
79 | dctx = dst->data; | ||
80 | if (sctx->gen_group) { | ||
81 | if ((dctx->gen_group = EC_GROUP_dup(sctx->gen_group)) == NULL) { | ||
82 | SM2error(ERR_R_MALLOC_FAILURE); | ||
83 | goto err; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | if (sctx->uid != NULL) { | ||
88 | if ((dctx->uid = malloc(sctx->uid_len)) == NULL) { | ||
89 | SM2error(ERR_R_MALLOC_FAILURE); | ||
90 | goto err; | ||
91 | } | ||
92 | memcpy(dctx->uid, sctx->uid, sctx->uid_len); | ||
93 | dctx->uid_len = sctx->uid_len; | ||
94 | } | ||
95 | |||
96 | dctx->md = sctx->md; | ||
97 | |||
98 | if (!EVP_MD_CTX_copy(dctx->md_ctx, sctx->md_ctx)) | ||
99 | goto err; | ||
100 | |||
101 | return 1; | ||
102 | |||
103 | err: | ||
104 | pkey_sm2_cleanup(dst); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int | ||
109 | pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, | ||
110 | const unsigned char *tbs, size_t tbslen) | ||
111 | { | ||
112 | unsigned int sltmp; | ||
113 | int ret, sig_sz; | ||
114 | |||
115 | if ((sig_sz = ECDSA_size(ctx->pkey->pkey.ec)) <= 0) | ||
116 | return 0; | ||
117 | |||
118 | if (sig == NULL) { | ||
119 | *siglen = sig_sz; | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | if (*siglen < (size_t)sig_sz) { | ||
124 | SM2error(SM2_R_BUFFER_TOO_SMALL); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | if ((ret = SM2_sign(tbs, tbslen, sig, &sltmp, ctx->pkey->pkey.ec)) <= 0) | ||
129 | return ret; | ||
130 | |||
131 | *siglen = (size_t)sltmp; | ||
132 | return 1; | ||
133 | } | ||
134 | |||
135 | static int | ||
136 | pkey_sm2_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen, | ||
137 | const unsigned char *tbs, size_t tbslen) | ||
138 | { | ||
139 | return SM2_verify(tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec); | ||
140 | } | ||
141 | |||
142 | static int | ||
143 | pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, | ||
144 | const unsigned char *in, size_t inlen) | ||
145 | { | ||
146 | SM2_PKEY_CTX *dctx = ctx->data; | ||
147 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | ||
148 | |||
149 | if (out == NULL) { | ||
150 | if (!SM2_ciphertext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) | ||
151 | return -1; | ||
152 | else | ||
153 | return 1; | ||
154 | } | ||
155 | |||
156 | return SM2_encrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); | ||
157 | } | ||
158 | |||
159 | static int | ||
160 | pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen, | ||
161 | const unsigned char *in, size_t inlen) | ||
162 | { | ||
163 | SM2_PKEY_CTX *dctx = ctx->data; | ||
164 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | ||
165 | |||
166 | if (out == NULL) { | ||
167 | if (!SM2_plaintext_size(ctx->pkey->pkey.ec, md, inlen, outlen)) | ||
168 | return -1; | ||
169 | else | ||
170 | return 1; | ||
171 | } | ||
172 | |||
173 | return SM2_decrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen); | ||
174 | } | ||
175 | |||
176 | static int | ||
177 | pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | ||
178 | { | ||
179 | SM2_PKEY_CTX *dctx = ctx->data; | ||
180 | EC_GROUP *group = NULL; | ||
181 | |||
182 | switch (type) { | ||
183 | case EVP_PKEY_CTRL_DIGESTINIT: | ||
184 | dctx->md_ctx = p2; | ||
185 | return 1; | ||
186 | |||
187 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: | ||
188 | if ((group = EC_GROUP_new_by_curve_name(p1)) == NULL) { | ||
189 | SM2error(SM2_R_INVALID_CURVE); | ||
190 | return 0; | ||
191 | } | ||
192 | EC_GROUP_free(dctx->gen_group); | ||
193 | dctx->gen_group = group; | ||
194 | return 1; | ||
195 | |||
196 | case EVP_PKEY_CTRL_SM2_SET_UID: | ||
197 | if ((p1 < 0) || ((p1 == 0) && (p2 != NULL))) { | ||
198 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
199 | return 0; | ||
200 | } | ||
201 | if ((p1 > 0) && (p2 == NULL)) { | ||
202 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
203 | return 0; | ||
204 | } | ||
205 | free(dctx->uid); | ||
206 | if (p2 == NULL) { | ||
207 | dctx->uid = NULL; | ||
208 | dctx->uid_len = 0; | ||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | if ((dctx->uid = malloc(p1)) == NULL) { | ||
213 | SM2error(ERR_R_MALLOC_FAILURE); | ||
214 | return 1; | ||
215 | } | ||
216 | memcpy(dctx->uid, p2, p1); | ||
217 | dctx->uid_len = p1; | ||
218 | return 1; | ||
219 | |||
220 | case EVP_PKEY_CTRL_SM2_HASH_UID: | ||
221 | { | ||
222 | const EVP_MD* md; | ||
223 | uint8_t za[EVP_MAX_MD_SIZE] = {0}; | ||
224 | int md_len; | ||
225 | |||
226 | if (dctx->uid == NULL) { | ||
227 | SM2error(SM2_R_INVALID_ARGUMENT); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | if ((md = EVP_MD_CTX_md(dctx->md_ctx)) == NULL) { | ||
232 | SM2error(ERR_R_EVP_LIB); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | if ((md_len = EVP_MD_size(md)) < 0) { | ||
237 | SM2error(SM2_R_INVALID_DIGEST); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | if (sm2_compute_userid_digest(za, md, dctx->uid, dctx->uid_len, | ||
242 | ctx->pkey->pkey.ec) != 1) { | ||
243 | SM2error(SM2_R_DIGEST_FAILURE); | ||
244 | return 0; | ||
245 | } | ||
246 | return EVP_DigestUpdate(dctx->md_ctx, za, md_len); | ||
247 | } | ||
248 | |||
249 | case EVP_PKEY_CTRL_SM2_GET_UID_LEN: | ||
250 | if (p2 == NULL) { | ||
251 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
252 | return 0; | ||
253 | } | ||
254 | *(size_t *)p2 = dctx->uid_len; | ||
255 | return 1; | ||
256 | |||
257 | case EVP_PKEY_CTRL_SM2_GET_UID: | ||
258 | if (p2 == NULL) { | ||
259 | SM2error(ERR_R_PASSED_NULL_PARAMETER); | ||
260 | return 0; | ||
261 | } | ||
262 | if (dctx->uid_len == 0) { | ||
263 | return 1; | ||
264 | } | ||
265 | memcpy(p2, dctx->uid, dctx->uid_len); | ||
266 | return 1; | ||
267 | |||
268 | case EVP_PKEY_CTRL_MD: | ||
269 | dctx->md = p2; | ||
270 | return 1; | ||
271 | |||
272 | default: | ||
273 | return -2; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static int | ||
278 | pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value) | ||
279 | { | ||
280 | int nid; | ||
281 | |||
282 | if (strcmp(type, "ec_paramgen_curve") == 0) { | ||
283 | if (((nid = EC_curve_nist2nid(value)) == NID_undef) && | ||
284 | ((nid = OBJ_sn2nid(value)) == NID_undef) && | ||
285 | ((nid = OBJ_ln2nid(value)) == NID_undef)) { | ||
286 | SM2error(SM2_R_INVALID_CURVE); | ||
287 | return 0; | ||
288 | } | ||
289 | return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); | ||
290 | } else if (strcmp(type, "sm2_uid") == 0) { | ||
291 | return EVP_PKEY_CTX_set_sm2_uid(ctx, (void*) value, | ||
292 | (int)strlen(value)); | ||
293 | } | ||
294 | |||
295 | return -2; | ||
296 | } | ||
297 | |||
298 | const EVP_PKEY_METHOD sm2_pkey_meth = { | ||
299 | .pkey_id = EVP_PKEY_SM2, | ||
300 | .init = pkey_sm2_init, | ||
301 | .copy = pkey_sm2_copy, | ||
302 | .cleanup = pkey_sm2_cleanup, | ||
303 | |||
304 | .sign = pkey_sm2_sign, | ||
305 | |||
306 | .verify = pkey_sm2_verify, | ||
307 | |||
308 | .encrypt = pkey_sm2_encrypt, | ||
309 | |||
310 | .decrypt = pkey_sm2_decrypt, | ||
311 | |||
312 | .ctrl = pkey_sm2_ctrl, | ||
313 | .ctrl_str = pkey_sm2_ctrl_str | ||
314 | }; | ||
315 | |||
316 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_sign.c b/src/lib/libcrypto/sm2/sm2_sign.c new file mode 100644 index 0000000000..d306658a48 --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_sign.c | |||
@@ -0,0 +1,465 @@ | |||
1 | /* $OpenBSD: sm2_sign.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef OPENSSL_NO_SM2 | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | #include <openssl/sm2.h> | ||
23 | #include <openssl/evp.h> | ||
24 | #include <openssl/err.h> | ||
25 | #include <openssl/bn.h> | ||
26 | |||
27 | #include "bn_lcl.h" | ||
28 | #include "sm2_locl.h" | ||
29 | |||
30 | static BIGNUM * | ||
31 | sm2_compute_msg_hash(const EVP_MD *digest, const EC_KEY *key, | ||
32 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
33 | { | ||
34 | EVP_MD_CTX *hash; | ||
35 | BIGNUM *e = NULL; | ||
36 | int md_size; | ||
37 | uint8_t *za = NULL; | ||
38 | |||
39 | if ((hash = EVP_MD_CTX_new()) == NULL) { | ||
40 | SM2error(ERR_R_MALLOC_FAILURE); | ||
41 | goto err; | ||
42 | } | ||
43 | |||
44 | if ((md_size = EVP_MD_size(digest)) < 0) { | ||
45 | SM2error(SM2_R_INVALID_DIGEST); | ||
46 | goto err; | ||
47 | } | ||
48 | |||
49 | if ((za = calloc(1, md_size)) == NULL) { | ||
50 | SM2error(ERR_R_MALLOC_FAILURE); | ||
51 | goto err; | ||
52 | } | ||
53 | |||
54 | if (!sm2_compute_userid_digest(za, digest, uid, uid_len, key)) { | ||
55 | SM2error(SM2_R_DIGEST_FAILURE); | ||
56 | goto err; | ||
57 | } | ||
58 | |||
59 | if (!EVP_DigestInit(hash, digest)) { | ||
60 | SM2error(ERR_R_EVP_LIB); | ||
61 | goto err; | ||
62 | } | ||
63 | |||
64 | if (!EVP_DigestUpdate(hash, za, md_size)) { | ||
65 | SM2error(ERR_R_EVP_LIB); | ||
66 | goto err; | ||
67 | } | ||
68 | |||
69 | if (!EVP_DigestUpdate(hash, msg, msg_len)) { | ||
70 | SM2error(ERR_R_EVP_LIB); | ||
71 | goto err; | ||
72 | } | ||
73 | |||
74 | /* reuse za buffer to hold H(ZA || M) */ | ||
75 | if (!EVP_DigestFinal(hash, za, NULL)) { | ||
76 | SM2error(ERR_R_EVP_LIB); | ||
77 | goto err; | ||
78 | } | ||
79 | |||
80 | e = BN_bin2bn(za, md_size, NULL); | ||
81 | |||
82 | err: | ||
83 | free(za); | ||
84 | EVP_MD_CTX_free(hash); | ||
85 | return e; | ||
86 | } | ||
87 | |||
88 | static ECDSA_SIG * | ||
89 | sm2_sig_gen(const EC_KEY *key, const BIGNUM *e) | ||
90 | { | ||
91 | ECDSA_SIG *sig = NULL; | ||
92 | const EC_GROUP *group; | ||
93 | EC_POINT *kG = NULL; | ||
94 | BN_CTX *ctx = NULL; | ||
95 | const BIGNUM *dA; | ||
96 | BIGNUM *order = NULL, *r = NULL, *s = NULL; | ||
97 | BIGNUM *k, *rk, *tmp, *x1; | ||
98 | |||
99 | if ((dA = EC_KEY_get0_private_key(key)) == NULL) { | ||
100 | SM2error(SM2_R_INVALID_FIELD); | ||
101 | goto err; | ||
102 | } | ||
103 | |||
104 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
105 | SM2error(SM2_R_INVALID_FIELD); | ||
106 | goto err; | ||
107 | } | ||
108 | |||
109 | if ((order = BN_new()) == NULL) { | ||
110 | SM2error(ERR_R_MALLOC_FAILURE); | ||
111 | goto err; | ||
112 | } | ||
113 | |||
114 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
115 | SM2error(ERR_R_EC_LIB); | ||
116 | goto err; | ||
117 | } | ||
118 | |||
119 | if ((kG = EC_POINT_new(group)) == NULL) { | ||
120 | SM2error(ERR_R_MALLOC_FAILURE); | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | if ((ctx = BN_CTX_new()) == NULL) { | ||
125 | SM2error(ERR_R_MALLOC_FAILURE); | ||
126 | goto err; | ||
127 | } | ||
128 | |||
129 | BN_CTX_start(ctx); | ||
130 | |||
131 | if ((k = BN_CTX_get(ctx)) == NULL) { | ||
132 | SM2error(ERR_R_BN_LIB); | ||
133 | goto err; | ||
134 | } | ||
135 | if ((rk = BN_CTX_get(ctx)) == NULL) { | ||
136 | SM2error(ERR_R_BN_LIB); | ||
137 | goto err; | ||
138 | } | ||
139 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
140 | SM2error(ERR_R_BN_LIB); | ||
141 | goto err; | ||
142 | } | ||
143 | if ((tmp = BN_CTX_get(ctx)) == NULL) { | ||
144 | SM2error(ERR_R_BN_LIB); | ||
145 | goto err; | ||
146 | } | ||
147 | |||
148 | /* r and s are returned as part of sig, so they can't be part of ctx. */ | ||
149 | if ((r = BN_new()) == NULL) { | ||
150 | SM2error(ERR_R_MALLOC_FAILURE); | ||
151 | goto err; | ||
152 | } | ||
153 | if ((s = BN_new()) == NULL) { | ||
154 | SM2error(ERR_R_MALLOC_FAILURE); | ||
155 | goto err; | ||
156 | } | ||
157 | |||
158 | for (;;) { | ||
159 | if (!BN_rand_range(k, order)) { | ||
160 | SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED); | ||
161 | goto err; | ||
162 | } | ||
163 | |||
164 | if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) { | ||
165 | SM2error(ERR_R_EC_LIB); | ||
166 | goto err; | ||
167 | } | ||
168 | |||
169 | if (!EC_POINT_get_affine_coordinates(group, kG, x1, NULL, | ||
170 | ctx)) { | ||
171 | SM2error(ERR_R_EC_LIB); | ||
172 | goto err; | ||
173 | } | ||
174 | |||
175 | if (!BN_mod_add(r, e, x1, order, ctx)) { | ||
176 | SM2error(ERR_R_BN_LIB); | ||
177 | goto err; | ||
178 | } | ||
179 | |||
180 | /* try again if r == 0 or r + k == n */ | ||
181 | if (BN_is_zero(r)) | ||
182 | continue; | ||
183 | |||
184 | if (!BN_add(rk, r, k)) { | ||
185 | SM2error(ERR_R_BN_LIB); | ||
186 | goto err; | ||
187 | } | ||
188 | |||
189 | if (BN_cmp(rk, order) == 0) | ||
190 | continue; | ||
191 | |||
192 | if (!BN_add(s, dA, BN_value_one())) { | ||
193 | SM2error(ERR_R_BN_LIB); | ||
194 | goto err; | ||
195 | } | ||
196 | |||
197 | if (!BN_mod_inverse_ct(s, s, order, ctx)) { | ||
198 | SM2error(ERR_R_BN_LIB); | ||
199 | goto err; | ||
200 | } | ||
201 | |||
202 | if (!BN_mod_mul(tmp, dA, r, order, ctx)) { | ||
203 | SM2error(ERR_R_BN_LIB); | ||
204 | goto err; | ||
205 | } | ||
206 | |||
207 | if (!BN_sub(tmp, k, tmp)) { | ||
208 | SM2error(ERR_R_BN_LIB); | ||
209 | goto err; | ||
210 | } | ||
211 | |||
212 | if (!BN_mod_mul(s, s, tmp, order, ctx)) { | ||
213 | SM2error(ERR_R_BN_LIB); | ||
214 | goto err; | ||
215 | } | ||
216 | |||
217 | if ((sig = ECDSA_SIG_new()) == NULL) { | ||
218 | SM2error(ERR_R_MALLOC_FAILURE); | ||
219 | goto err; | ||
220 | } | ||
221 | |||
222 | /* sig takes ownership of r and s */ | ||
223 | if (!ECDSA_SIG_set0(sig, r, s)) { | ||
224 | SM2error(ERR_R_INTERNAL_ERROR); | ||
225 | goto err; | ||
226 | } | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | err: | ||
231 | if (sig == NULL) { | ||
232 | BN_free(r); | ||
233 | BN_free(s); | ||
234 | } | ||
235 | |||
236 | BN_free(order); | ||
237 | BN_CTX_end(ctx); | ||
238 | BN_CTX_free(ctx); | ||
239 | EC_POINT_free(kG); | ||
240 | return sig; | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, const BIGNUM *e) | ||
245 | { | ||
246 | const EC_GROUP *group; | ||
247 | EC_POINT *pt = NULL; | ||
248 | const BIGNUM *r = NULL, *s = NULL; | ||
249 | BN_CTX *ctx = NULL; | ||
250 | BIGNUM *order, *t, *x1; | ||
251 | int ret = 0; | ||
252 | |||
253 | if ((group = EC_KEY_get0_group(key)) == NULL) { | ||
254 | SM2error(SM2_R_INVALID_FIELD); | ||
255 | goto err; | ||
256 | } | ||
257 | |||
258 | if ((ctx = BN_CTX_new()) == NULL) { | ||
259 | SM2error(ERR_R_MALLOC_FAILURE); | ||
260 | goto err; | ||
261 | } | ||
262 | |||
263 | BN_CTX_start(ctx); | ||
264 | |||
265 | if ((order = BN_CTX_get(ctx)) == NULL) { | ||
266 | SM2error(ERR_R_MALLOC_FAILURE); | ||
267 | goto err; | ||
268 | } | ||
269 | |||
270 | if (!EC_GROUP_get_order(group, order, NULL)) { | ||
271 | SM2error(ERR_R_EC_LIB); | ||
272 | goto err; | ||
273 | } | ||
274 | |||
275 | if ((pt = EC_POINT_new(group)) == NULL) { | ||
276 | SM2error(ERR_R_MALLOC_FAILURE); | ||
277 | goto err; | ||
278 | } | ||
279 | |||
280 | if ((t = BN_CTX_get(ctx)) == NULL) { | ||
281 | SM2error(ERR_R_MALLOC_FAILURE); | ||
282 | goto err; | ||
283 | } | ||
284 | if ((x1 = BN_CTX_get(ctx)) == NULL) { | ||
285 | SM2error(ERR_R_MALLOC_FAILURE); | ||
286 | goto err; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * Section 5.3.1 in https://tools.ietf.org/html/draft-shen-sm2-ecdsa-00 | ||
291 | * | ||
292 | * B1: verify that r' is in [1, n-1] | ||
293 | * B2: verify that s' is in [1, n-1] | ||
294 | * B3: set M' ~= ZA || M' | ||
295 | * B4: calculate e' = Hv(M'~) | ||
296 | * B5: verify that t = r' + s' (mod n) is not zero | ||
297 | * B6: calculate the point (x1', y1') = [s']G + [t]PA | ||
298 | * B7: verify that r' == e' + x1' (mod n) | ||
299 | */ | ||
300 | |||
301 | ECDSA_SIG_get0(sig, &r, &s); | ||
302 | |||
303 | /* B1: verify that r' is in [1, n-1] */ | ||
304 | if (BN_cmp(r, BN_value_one()) < 0 || BN_cmp(order, r) <= 0) { | ||
305 | SM2error(SM2_R_BAD_SIGNATURE); | ||
306 | goto err; | ||
307 | } | ||
308 | |||
309 | /* B2: verify that s' is in [1, n-1] */ | ||
310 | if (BN_cmp(s, BN_value_one()) < 0 || BN_cmp(order, s) <= 0) { | ||
311 | SM2error(SM2_R_BAD_SIGNATURE); | ||
312 | goto err; | ||
313 | } | ||
314 | |||
315 | /* B5: verify that t = r + s is not zero */ | ||
316 | if (!BN_mod_add(t, r, s, order, ctx)) { | ||
317 | SM2error(ERR_R_BN_LIB); | ||
318 | goto err; | ||
319 | } | ||
320 | if (BN_is_zero(t)) { | ||
321 | SM2error(SM2_R_BAD_SIGNATURE); | ||
322 | goto err; | ||
323 | } | ||
324 | |||
325 | /* B6: calculate pt = (x1', y1') = [s']G + [t]PA */ | ||
326 | if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)) { | ||
327 | SM2error(ERR_R_EC_LIB); | ||
328 | goto err; | ||
329 | } | ||
330 | |||
331 | if (!EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) { | ||
332 | SM2error(ERR_R_EC_LIB); | ||
333 | goto err; | ||
334 | } | ||
335 | |||
336 | /* B7: verify that r' == e' + x1' (mod n) */ | ||
337 | if (!BN_mod_add(t, e, x1, order, ctx)) { | ||
338 | SM2error(ERR_R_BN_LIB); | ||
339 | goto err; | ||
340 | } | ||
341 | if (BN_cmp(r, t) == 0) | ||
342 | ret = 1; | ||
343 | |||
344 | err: | ||
345 | EC_POINT_free(pt); | ||
346 | BN_CTX_end(ctx); | ||
347 | BN_CTX_free(ctx); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | ECDSA_SIG * | ||
352 | sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, const uint8_t *uid, | ||
353 | size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
354 | { | ||
355 | ECDSA_SIG *sig = NULL; | ||
356 | BIGNUM *e; | ||
357 | |||
358 | e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); | ||
359 | if (e == NULL) { | ||
360 | SM2error(SM2_R_DIGEST_FAILURE); | ||
361 | goto err; | ||
362 | } | ||
363 | |||
364 | sig = sm2_sig_gen(key, e); | ||
365 | |||
366 | err: | ||
367 | BN_free(e); | ||
368 | return sig; | ||
369 | } | ||
370 | |||
371 | int | ||
372 | sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, const ECDSA_SIG *sig, | ||
373 | const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len) | ||
374 | { | ||
375 | BIGNUM *e; | ||
376 | int ret = -1; | ||
377 | |||
378 | e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len); | ||
379 | if (e == NULL) { | ||
380 | SM2error(SM2_R_DIGEST_FAILURE); | ||
381 | goto err; | ||
382 | } | ||
383 | |||
384 | ret = sm2_sig_verify(key, sig, e); | ||
385 | |||
386 | err: | ||
387 | BN_free(e); | ||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | int | ||
392 | SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig, | ||
393 | unsigned int *siglen, EC_KEY *eckey) | ||
394 | { | ||
395 | BIGNUM *e; | ||
396 | ECDSA_SIG *s = NULL; | ||
397 | int outlen = 0; | ||
398 | int ret = -1; | ||
399 | |||
400 | if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { | ||
401 | SM2error(ERR_R_MALLOC_FAILURE); | ||
402 | goto err; | ||
403 | } | ||
404 | |||
405 | if ((s = sm2_sig_gen(eckey, e)) == NULL) { | ||
406 | goto err; | ||
407 | } | ||
408 | |||
409 | if ((outlen = i2d_ECDSA_SIG(s, &sig)) < 0) { | ||
410 | SM2error(SM2_R_ASN1_ERROR); | ||
411 | goto err; | ||
412 | } | ||
413 | |||
414 | *siglen = outlen; | ||
415 | ret = 1; | ||
416 | |||
417 | err: | ||
418 | ECDSA_SIG_free(s); | ||
419 | BN_free(e); | ||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | int | ||
424 | SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig, | ||
425 | int sig_len, EC_KEY *eckey) | ||
426 | { | ||
427 | ECDSA_SIG *s; | ||
428 | BIGNUM *e = NULL; | ||
429 | const unsigned char *p = sig; | ||
430 | unsigned char *der = NULL; | ||
431 | int derlen = -1; | ||
432 | int ret = -1; | ||
433 | |||
434 | if ((s = ECDSA_SIG_new()) == NULL) { | ||
435 | SM2error(ERR_R_MALLOC_FAILURE); | ||
436 | goto err; | ||
437 | } | ||
438 | |||
439 | if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) { | ||
440 | SM2error(SM2_R_INVALID_ENCODING); | ||
441 | goto err; | ||
442 | } | ||
443 | |||
444 | /* Ensure signature uses DER and doesn't have trailing garbage */ | ||
445 | derlen = i2d_ECDSA_SIG(s, &der); | ||
446 | if (derlen != sig_len || memcmp(sig, der, derlen) != 0) { | ||
447 | SM2error(SM2_R_INVALID_ENCODING); | ||
448 | goto err; | ||
449 | } | ||
450 | |||
451 | if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) { | ||
452 | SM2error(ERR_R_BN_LIB); | ||
453 | goto err; | ||
454 | } | ||
455 | |||
456 | ret = sm2_sig_verify(eckey, s, e); | ||
457 | |||
458 | err: | ||
459 | free(der); | ||
460 | BN_free(e); | ||
461 | ECDSA_SIG_free(s); | ||
462 | return ret; | ||
463 | } | ||
464 | |||
465 | #endif /* OPENSSL_NO_SM2 */ | ||
diff --git a/src/lib/libcrypto/sm2/sm2_za.c b/src/lib/libcrypto/sm2/sm2_za.c new file mode 100644 index 0000000000..2a7f2846ec --- /dev/null +++ b/src/lib/libcrypto/sm2/sm2_za.c | |||
@@ -0,0 +1,161 @@ | |||
1 | /* $OpenBSD: sm2_za.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2019 Ribose Inc | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #ifndef OPENSSL_NO_SM2 | ||
19 | |||
20 | #include <openssl/sm2.h> | ||
21 | #include <openssl/evp.h> | ||
22 | #include <openssl/bn.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | int | ||
26 | sm2_compute_userid_digest(uint8_t *out, const EVP_MD *digest, uint8_t *uid, | ||
27 | size_t uid_len, const EC_KEY *key) | ||
28 | { | ||
29 | const EC_GROUP *group; | ||
30 | EVP_MD_CTX *hash = NULL; | ||
31 | BN_CTX *ctx = NULL; | ||
32 | BIGNUM *p, *a, *b, *xG, *yG, *xA, *yA; | ||
33 | uint8_t *buf = NULL; | ||
34 | uint16_t entla; | ||
35 | uint8_t e_byte; | ||
36 | int bytes, p_bytes; | ||
37 | int rc = 0; | ||
38 | |||
39 | if ((group = EC_KEY_get0_group(key)) == NULL) | ||
40 | goto err; | ||
41 | |||
42 | if ((hash = EVP_MD_CTX_new()) == NULL) | ||
43 | goto err; | ||
44 | |||
45 | if ((ctx = BN_CTX_new()) == NULL) | ||
46 | goto err; | ||
47 | |||
48 | if ((p = BN_CTX_get(ctx)) == NULL) | ||
49 | goto err; | ||
50 | if ((a = BN_CTX_get(ctx)) == NULL) | ||
51 | goto err; | ||
52 | if ((b = BN_CTX_get(ctx)) == NULL) | ||
53 | goto err; | ||
54 | if ((xG = BN_CTX_get(ctx)) == NULL) | ||
55 | goto err; | ||
56 | if ((yG = BN_CTX_get(ctx)) == NULL) | ||
57 | goto err; | ||
58 | if ((xA = BN_CTX_get(ctx)) == NULL) | ||
59 | goto err; | ||
60 | if ((yA = BN_CTX_get(ctx)) == NULL) | ||
61 | goto err; | ||
62 | |||
63 | memset(out, 0, EVP_MD_size(digest)); | ||
64 | |||
65 | if (!EVP_DigestInit(hash, digest)) | ||
66 | goto err; | ||
67 | |||
68 | /* | ||
69 | * ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA) | ||
70 | */ | ||
71 | |||
72 | if (uid_len >= 8192) | ||
73 | goto err; | ||
74 | |||
75 | entla = (unsigned short)(8 * uid_len); | ||
76 | |||
77 | e_byte = entla >> 8; | ||
78 | if (!EVP_DigestUpdate(hash, &e_byte, 1)) | ||
79 | goto err; | ||
80 | |||
81 | e_byte = entla & 0xFF; | ||
82 | if (!EVP_DigestUpdate(hash, &e_byte, 1)) | ||
83 | goto err; | ||
84 | |||
85 | if (!EVP_DigestUpdate(hash, uid, uid_len)) | ||
86 | goto err; | ||
87 | |||
88 | if (!EC_GROUP_get_curve(group, p, a, b, ctx)) | ||
89 | goto err; | ||
90 | |||
91 | p_bytes = BN_num_bytes(p); | ||
92 | |||
93 | if ((buf = calloc(1, p_bytes)) == NULL) | ||
94 | goto err; | ||
95 | |||
96 | if ((bytes = BN_num_bytes(a)) > p_bytes) | ||
97 | goto err; | ||
98 | BN_bn2bin(a, buf + p_bytes - bytes); | ||
99 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
100 | goto err; | ||
101 | |||
102 | if ((bytes = BN_num_bytes(b)) > p_bytes) | ||
103 | goto err; | ||
104 | memset(buf, 0, p_bytes - bytes); | ||
105 | BN_bn2bin(b, buf + p_bytes - bytes); | ||
106 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
107 | goto err; | ||
108 | |||
109 | if (!EC_POINT_get_affine_coordinates(group, | ||
110 | EC_GROUP_get0_generator(group), xG, yG, ctx)) | ||
111 | goto err; | ||
112 | |||
113 | if ((bytes = BN_num_bytes(xG)) > p_bytes) | ||
114 | goto err; | ||
115 | memset(buf, 0, p_bytes - bytes); | ||
116 | BN_bn2bin(xG, buf + p_bytes - bytes); | ||
117 | |||
118 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
119 | goto err; | ||
120 | |||
121 | if ((bytes = BN_num_bytes(yG)) > p_bytes) | ||
122 | goto err; | ||
123 | memset(buf, 0, p_bytes - bytes); | ||
124 | BN_bn2bin(yG, buf + p_bytes - bytes); | ||
125 | |||
126 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
127 | goto err; | ||
128 | |||
129 | if (!EC_POINT_get_affine_coordinates(group, | ||
130 | EC_KEY_get0_public_key(key), xA, yA, ctx)) | ||
131 | goto err; | ||
132 | |||
133 | if ((bytes = BN_num_bytes(xA)) > p_bytes) | ||
134 | goto err; | ||
135 | memset(buf, 0, p_bytes - bytes); | ||
136 | BN_bn2bin(xA, buf + p_bytes - bytes); | ||
137 | |||
138 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
139 | goto err; | ||
140 | |||
141 | if ((bytes = BN_num_bytes(yA)) > p_bytes) | ||
142 | goto err; | ||
143 | memset(buf, 0, p_bytes - bytes); | ||
144 | BN_bn2bin(yA, buf + p_bytes - bytes); | ||
145 | |||
146 | if (!EVP_DigestUpdate(hash, buf, p_bytes)) | ||
147 | goto err; | ||
148 | |||
149 | if (!EVP_DigestFinal(hash, out, NULL)) | ||
150 | goto err; | ||
151 | |||
152 | rc = 1; | ||
153 | |||
154 | err: | ||
155 | free(buf); | ||
156 | BN_CTX_free(ctx); | ||
157 | EVP_MD_CTX_free(hash); | ||
158 | return rc; | ||
159 | } | ||
160 | |||
161 | #endif /* OPENSSL_NO_SM2 */ | ||