]>
Commit | Line | Data |
---|---|---|
ddb634fe | 1 | /* |
33388b44 | 2 | * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. |
ddb634fe | 3 | * |
f9f859ad | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
ddb634fe JL |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
579422c8 P |
10 | /* |
11 | * ECDSA low level APIs are deprecated for public use, but still ok for | |
12 | * internal use. | |
13 | */ | |
14 | #include "internal/deprecated.h" | |
15 | ||
ddb634fe JL |
16 | #include "internal/cryptlib.h" |
17 | #include <openssl/asn1t.h> | |
18 | #include <openssl/ec.h> | |
19 | #include <openssl/evp.h> | |
25f2138b DMSP |
20 | #include "crypto/evp.h" |
21 | #include "crypto/sm2.h" | |
22 | #include "crypto/sm2err.h" | |
5ccada09 | 23 | #include "crypto/ec.h" |
ddb634fe JL |
24 | |
25 | /* EC pkey context structure */ | |
26 | ||
27 | typedef struct { | |
ddb634fe JL |
28 | /* message digest */ |
29 | const EVP_MD *md; | |
123c2fef | 30 | /* Distinguishing Identifier, ISO/IEC 15946-3, FIPS 196 */ |
00433bad PY |
31 | uint8_t *id; |
32 | size_t id_len; | |
4803717f PY |
33 | /* id_set indicates if the 'id' field is set (1) or not (0) */ |
34 | int id_set; | |
ddb634fe JL |
35 | } SM2_PKEY_CTX; |
36 | ||
37 | static int pkey_sm2_init(EVP_PKEY_CTX *ctx) | |
38 | { | |
4803717f | 39 | SM2_PKEY_CTX *smctx; |
ddb634fe | 40 | |
4803717f | 41 | if ((smctx = OPENSSL_zalloc(sizeof(*smctx))) == NULL) { |
ddb634fe JL |
42 | SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE); |
43 | return 0; | |
44 | } | |
45 | ||
4803717f | 46 | ctx->data = smctx; |
ddb634fe JL |
47 | return 1; |
48 | } | |
49 | ||
50 | static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx) | |
51 | { | |
4803717f | 52 | SM2_PKEY_CTX *smctx = ctx->data; |
ddb634fe | 53 | |
4803717f | 54 | if (smctx != NULL) { |
4803717f PY |
55 | OPENSSL_free(smctx->id); |
56 | OPENSSL_free(smctx); | |
ddb634fe JL |
57 | ctx->data = NULL; |
58 | } | |
59 | } | |
60 | ||
9fdcc21f | 61 | static int pkey_sm2_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src) |
ddb634fe JL |
62 | { |
63 | SM2_PKEY_CTX *dctx, *sctx; | |
64 | ||
65 | if (!pkey_sm2_init(dst)) | |
66 | return 0; | |
67 | sctx = src->data; | |
68 | dctx = dst->data; | |
4803717f PY |
69 | if (sctx->id != NULL) { |
70 | dctx->id = OPENSSL_malloc(sctx->id_len); | |
71 | if (dctx->id == NULL) { | |
f922dac8 | 72 | SM2err(SM2_F_PKEY_SM2_COPY, ERR_R_MALLOC_FAILURE); |
4803717f PY |
73 | pkey_sm2_cleanup(dst); |
74 | return 0; | |
75 | } | |
76 | memcpy(dctx->id, sctx->id, sctx->id_len); | |
77 | } | |
78 | dctx->id_len = sctx->id_len; | |
79 | dctx->id_set = sctx->id_set; | |
ddb634fe JL |
80 | dctx->md = sctx->md; |
81 | ||
82 | return 1; | |
83 | } | |
84 | ||
85 | static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, | |
86 | const unsigned char *tbs, size_t tbslen) | |
87 | { | |
88 | int ret; | |
89 | unsigned int sltmp; | |
90 | EC_KEY *ec = ctx->pkey->pkey.ec; | |
91 | const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec); | |
92 | ||
93 | if (sig_sz <= 0) { | |
94 | return 0; | |
95 | } | |
96 | ||
97 | if (sig == NULL) { | |
98 | *siglen = (size_t)sig_sz; | |
99 | return 1; | |
100 | } | |
101 | ||
102 | if (*siglen < (size_t)sig_sz) { | |
103 | SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL); | |
104 | return 0; | |
105 | } | |
106 | ||
d0b79f86 | 107 | ret = sm2_internal_sign(tbs, tbslen, sig, &sltmp, ec); |
ddb634fe JL |
108 | |
109 | if (ret <= 0) | |
110 | return ret; | |
111 | *siglen = (size_t)sltmp; | |
112 | return 1; | |
113 | } | |
114 | ||
115 | static int pkey_sm2_verify(EVP_PKEY_CTX *ctx, | |
116 | const unsigned char *sig, size_t siglen, | |
117 | const unsigned char *tbs, size_t tbslen) | |
118 | { | |
119 | EC_KEY *ec = ctx->pkey->pkey.ec; | |
120 | ||
d0b79f86 | 121 | return sm2_internal_verify(tbs, tbslen, sig, siglen, ec); |
ddb634fe JL |
122 | } |
123 | ||
124 | static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, | |
125 | unsigned char *out, size_t *outlen, | |
126 | const unsigned char *in, size_t inlen) | |
127 | { | |
5ccada09 | 128 | int ret; |
ddb634fe JL |
129 | EC_KEY *ec = ctx->pkey->pkey.ec; |
130 | SM2_PKEY_CTX *dctx = ctx->data; | |
131 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | |
5ccada09 SL |
132 | OPENSSL_CTX *libctx = ec_key_get_libctx(ec); |
133 | EVP_MD *fetched_md = NULL; | |
ddb634fe JL |
134 | |
135 | if (out == NULL) { | |
136 | if (!sm2_ciphertext_size(ec, md, inlen, outlen)) | |
137 | return -1; | |
138 | else | |
139 | return 1; | |
140 | } | |
141 | ||
5ccada09 SL |
142 | fetched_md = EVP_MD_fetch(libctx, EVP_MD_name(md), 0); |
143 | if (fetched_md == NULL) | |
144 | return 0; | |
145 | ret = sm2_encrypt(ec, fetched_md, in, inlen, out, outlen); | |
146 | EVP_MD_free(fetched_md); | |
147 | return ret; | |
ddb634fe JL |
148 | } |
149 | ||
150 | static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, | |
151 | unsigned char *out, size_t *outlen, | |
152 | const unsigned char *in, size_t inlen) | |
153 | { | |
5ccada09 | 154 | int ret; |
ddb634fe JL |
155 | EC_KEY *ec = ctx->pkey->pkey.ec; |
156 | SM2_PKEY_CTX *dctx = ctx->data; | |
157 | const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md; | |
5ccada09 SL |
158 | OPENSSL_CTX *libctx = ec_key_get_libctx(ec); |
159 | EVP_MD *fetched_md = NULL; | |
ddb634fe JL |
160 | |
161 | if (out == NULL) { | |
162 | if (!sm2_plaintext_size(ec, md, inlen, outlen)) | |
163 | return -1; | |
164 | else | |
165 | return 1; | |
166 | } | |
167 | ||
5ccada09 SL |
168 | fetched_md = EVP_MD_fetch(libctx, EVP_MD_name(md), 0); |
169 | if (fetched_md == NULL) | |
170 | return 0; | |
171 | ret = sm2_decrypt(ec, fetched_md, in, inlen, out, outlen); | |
172 | EVP_MD_free(fetched_md); | |
173 | return ret; | |
ddb634fe JL |
174 | } |
175 | ||
176 | static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) | |
177 | { | |
4803717f | 178 | SM2_PKEY_CTX *smctx = ctx->data; |
675f4cee | 179 | uint8_t *tmp_id; |
ddb634fe JL |
180 | |
181 | switch (type) { | |
182 | case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: | |
0943d5dd RL |
183 | /* |
184 | * This control could be removed, which would signal it being | |
185 | * unsupported. However, that means that when the caller uses | |
186 | * the correct curve, it may interpret the unsupported signal | |
187 | * as an error, so it's better to accept the control, check the | |
188 | * value and return a corresponding value. | |
189 | */ | |
190 | if (p1 != NID_sm2) { | |
ddb634fe JL |
191 | SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE); |
192 | return 0; | |
193 | } | |
ddb634fe JL |
194 | return 1; |
195 | ||
196 | case EVP_PKEY_CTRL_MD: | |
4803717f | 197 | smctx->md = p2; |
ddb634fe JL |
198 | return 1; |
199 | ||
200 | case EVP_PKEY_CTRL_GET_MD: | |
4803717f PY |
201 | *(const EVP_MD **)p2 = smctx->md; |
202 | return 1; | |
203 | ||
204 | case EVP_PKEY_CTRL_SET1_ID: | |
4803717f | 205 | if (p1 > 0) { |
675f4cee | 206 | tmp_id = OPENSSL_malloc(p1); |
f922dac8 PY |
207 | if (tmp_id == NULL) { |
208 | SM2err(SM2_F_PKEY_SM2_CTRL, ERR_R_MALLOC_FAILURE); | |
4803717f | 209 | return 0; |
f922dac8 | 210 | } |
675f4cee PY |
211 | memcpy(tmp_id, p2, p1); |
212 | OPENSSL_free(smctx->id); | |
213 | smctx->id = tmp_id; | |
4803717f PY |
214 | } else { |
215 | /* set null-ID */ | |
675f4cee | 216 | OPENSSL_free(smctx->id); |
4803717f PY |
217 | smctx->id = NULL; |
218 | } | |
219 | smctx->id_len = (size_t)p1; | |
220 | smctx->id_set = 1; | |
221 | return 1; | |
222 | ||
223 | case EVP_PKEY_CTRL_GET1_ID: | |
224 | memcpy(p2, smctx->id, smctx->id_len); | |
225 | return 1; | |
226 | ||
227 | case EVP_PKEY_CTRL_GET1_ID_LEN: | |
228 | *(size_t *)p2 = smctx->id_len; | |
ddb634fe JL |
229 | return 1; |
230 | ||
8267becb | 231 | case EVP_PKEY_CTRL_DIGESTINIT: |
232 | /* nothing to be inited, this is to suppress the error... */ | |
233 | return 1; | |
234 | ||
ddb634fe JL |
235 | default: |
236 | return -2; | |
ddb634fe JL |
237 | } |
238 | } | |
239 | ||
240 | static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, | |
241 | const char *type, const char *value) | |
242 | { | |
a45eb7e8 PY |
243 | uint8_t *hex_id; |
244 | long hex_len = 0; | |
245 | int ret = 0; | |
246 | ||
ddb634fe JL |
247 | if (strcmp(type, "ec_paramgen_curve") == 0) { |
248 | int nid = NID_undef; | |
249 | ||
250 | if (((nid = EC_curve_nist2nid(value)) == NID_undef) | |
251 | && ((nid = OBJ_sn2nid(value)) == NID_undef) | |
252 | && ((nid = OBJ_ln2nid(value)) == NID_undef)) { | |
253 | SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE); | |
254 | return 0; | |
255 | } | |
256 | return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); | |
257 | } else if (strcmp(type, "ec_param_enc") == 0) { | |
258 | int param_enc; | |
259 | ||
260 | if (strcmp(value, "explicit") == 0) | |
261 | param_enc = 0; | |
262 | else if (strcmp(value, "named_curve") == 0) | |
263 | param_enc = OPENSSL_EC_NAMED_CURVE; | |
264 | else | |
265 | return -2; | |
266 | return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc); | |
123c2fef | 267 | } else if (strcmp(type, "distid") == 0) { |
a7cef52f PY |
268 | return pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, |
269 | (int)strlen(value), (void *)value); | |
123c2fef | 270 | } else if (strcmp(type, "hexdistid") == 0) { |
a45eb7e8 PY |
271 | hex_id = OPENSSL_hexstr2buf((const char *)value, &hex_len); |
272 | if (hex_id == NULL) { | |
273 | SM2err(SM2_F_PKEY_SM2_CTRL_STR, ERR_R_PASSED_INVALID_ARGUMENT); | |
274 | return 0; | |
275 | } | |
276 | ret = pkey_sm2_ctrl(ctx, EVP_PKEY_CTRL_SET1_ID, (int)hex_len, | |
277 | (void *)hex_id); | |
278 | OPENSSL_free(hex_id); | |
279 | return ret; | |
ddb634fe JL |
280 | } |
281 | ||
282 | return -2; | |
283 | } | |
284 | ||
00433bad PY |
285 | static int pkey_sm2_digest_custom(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx) |
286 | { | |
287 | uint8_t z[EVP_MAX_MD_SIZE]; | |
4803717f | 288 | SM2_PKEY_CTX *smctx = ctx->data; |
00433bad PY |
289 | EC_KEY *ec = ctx->pkey->pkey.ec; |
290 | const EVP_MD *md = EVP_MD_CTX_md(mctx); | |
d689f313 | 291 | int mdlen = EVP_MD_size(md); |
00433bad | 292 | |
4803717f PY |
293 | if (!smctx->id_set) { |
294 | /* | |
295 | * An ID value must be set. The specifications are not clear whether a | |
296 | * NULL is allowed. We only allow it if set explicitly for maximum | |
297 | * flexibility. | |
00433bad | 298 | */ |
675f4cee | 299 | SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_ID_NOT_SET); |
00433bad PY |
300 | return 0; |
301 | } | |
302 | ||
d689f313 MC |
303 | if (mdlen < 0) { |
304 | SM2err(SM2_F_PKEY_SM2_DIGEST_CUSTOM, SM2_R_INVALID_DIGEST); | |
305 | return 0; | |
306 | } | |
307 | ||
4803717f PY |
308 | /* get hashed prefix 'z' of tbs message */ |
309 | if (!sm2_compute_z_digest(z, md, smctx->id, smctx->id_len, ec)) | |
00433bad PY |
310 | return 0; |
311 | ||
d689f313 | 312 | return EVP_DigestUpdate(mctx, z, (size_t)mdlen); |
00433bad PY |
313 | } |
314 | ||
0943d5dd RL |
315 | static int pkey_sm2_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) |
316 | { | |
317 | EC_KEY *ec = NULL; | |
318 | int ret; | |
319 | ||
320 | ec = EC_KEY_new_by_curve_name(NID_sm2); | |
321 | if (ec == NULL) | |
322 | return 0; | |
323 | if (!ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec))) | |
324 | EC_KEY_free(ec); | |
325 | return ret; | |
326 | } | |
327 | ||
328 | static int pkey_sm2_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) | |
329 | { | |
330 | EC_KEY *ec = NULL; | |
331 | ||
332 | ec = EC_KEY_new_by_curve_name(NID_sm2); | |
333 | if (ec == NULL) | |
334 | return 0; | |
335 | if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) { | |
336 | EC_KEY_free(ec); | |
337 | return 0; | |
338 | } | |
339 | /* Note: if error is returned, we count on caller to free pkey->pkey.ec */ | |
340 | if (ctx->pkey != NULL | |
341 | && !EVP_PKEY_copy_parameters(pkey, ctx->pkey)) | |
342 | return 0; | |
343 | ||
344 | return EC_KEY_generate_key(ec); | |
345 | } | |
346 | ||
19bd1fa1 | 347 | static const EVP_PKEY_METHOD sm2_pkey_meth = { |
ddb634fe JL |
348 | EVP_PKEY_SM2, |
349 | 0, | |
350 | pkey_sm2_init, | |
351 | pkey_sm2_copy, | |
352 | pkey_sm2_cleanup, | |
353 | ||
354 | 0, | |
0943d5dd | 355 | pkey_sm2_paramgen, |
ddb634fe JL |
356 | |
357 | 0, | |
0943d5dd | 358 | pkey_sm2_keygen, |
ddb634fe JL |
359 | |
360 | 0, | |
361 | pkey_sm2_sign, | |
362 | ||
363 | 0, | |
364 | pkey_sm2_verify, | |
365 | ||
366 | 0, 0, | |
367 | ||
368 | 0, 0, 0, 0, | |
369 | ||
370 | 0, | |
371 | pkey_sm2_encrypt, | |
372 | ||
373 | 0, | |
374 | pkey_sm2_decrypt, | |
375 | ||
376 | 0, | |
377 | 0, | |
378 | pkey_sm2_ctrl, | |
00433bad PY |
379 | pkey_sm2_ctrl_str, |
380 | ||
381 | 0, 0, | |
382 | ||
383 | 0, 0, 0, | |
384 | ||
385 | pkey_sm2_digest_custom | |
ddb634fe | 386 | }; |
19bd1fa1 PS |
387 | |
388 | const EVP_PKEY_METHOD *sm2_pkey_method(void) | |
389 | { | |
390 | return &sm2_pkey_meth; | |
391 | } |