diff options
Diffstat (limited to 'src/lib/libcrypto/gost/gostr341001_ameth.c')
-rw-r--r-- | src/lib/libcrypto/gost/gostr341001_ameth.c | 737 |
1 files changed, 0 insertions, 737 deletions
diff --git a/src/lib/libcrypto/gost/gostr341001_ameth.c b/src/lib/libcrypto/gost/gostr341001_ameth.c deleted file mode 100644 index 3153d2f2eb..0000000000 --- a/src/lib/libcrypto/gost/gostr341001_ameth.c +++ /dev/null | |||
@@ -1,737 +0,0 @@ | |||
1 | /* $OpenBSD: gostr341001_ameth.c,v 1.9 2015/02/14 06:40:04 jsing Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | ||
4 | * Copyright (c) 2005-2006 Cryptocom LTD | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions | ||
8 | * are met: | ||
9 | * | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in | ||
15 | * the documentation and/or other materials provided with the | ||
16 | * distribution. | ||
17 | * | ||
18 | * 3. All advertising materials mentioning features or use of this | ||
19 | * software must display the following acknowledgment: | ||
20 | * "This product includes software developed by the OpenSSL Project | ||
21 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | ||
22 | * | ||
23 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
24 | * endorse or promote products derived from this software without | ||
25 | * prior written permission. For written permission, please contact | ||
26 | * openssl-core@openssl.org. | ||
27 | * | ||
28 | * 5. Products derived from this software may not be called "OpenSSL" | ||
29 | * nor may "OpenSSL" appear in their names without prior written | ||
30 | * permission of the OpenSSL Project. | ||
31 | * | ||
32 | * 6. Redistributions of any form whatsoever must retain the following | ||
33 | * acknowledgment: | ||
34 | * "This product includes software developed by the OpenSSL Project | ||
35 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | ||
36 | * | ||
37 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
38 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
39 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
40 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
41 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
42 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
43 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
44 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
45 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
46 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
47 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
48 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
49 | * ==================================================================== | ||
50 | */ | ||
51 | |||
52 | #include <string.h> | ||
53 | |||
54 | #include <openssl/opensslconf.h> | ||
55 | |||
56 | #ifndef OPENSSL_NO_GOST | ||
57 | #include <openssl/bn.h> | ||
58 | #include <openssl/evp.h> | ||
59 | #include <openssl/ec.h> | ||
60 | #include <openssl/err.h> | ||
61 | #include <openssl/x509.h> | ||
62 | #include <openssl/gost.h> | ||
63 | |||
64 | #ifndef OPENSSL_NO_CMS | ||
65 | #include <openssl/cms.h> | ||
66 | #endif | ||
67 | |||
68 | #include "asn1_locl.h" | ||
69 | #include "gost_locl.h" | ||
70 | #include "gost_asn1.h" | ||
71 | |||
72 | static void | ||
73 | pkey_free_gost01(EVP_PKEY *key) | ||
74 | { | ||
75 | GOST_KEY_free(key->pkey.gost); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Parses GOST algorithm parameters from X509_ALGOR and | ||
80 | * modifies pkey setting NID and parameters | ||
81 | */ | ||
82 | static int | ||
83 | decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len) | ||
84 | { | ||
85 | int param_nid = NID_undef, digest_nid = NID_undef; | ||
86 | GOST_KEY_PARAMS *gkp = NULL; | ||
87 | EC_GROUP *group; | ||
88 | GOST_KEY *ec; | ||
89 | |||
90 | gkp = d2i_GOST_KEY_PARAMS(NULL, p, len); | ||
91 | if (gkp == NULL) { | ||
92 | GOSTerr(GOST_F_DECODE_GOST01_ALGOR_PARAMS, | ||
93 | GOST_R_BAD_PKEY_PARAMETERS_FORMAT); | ||
94 | return 0; | ||
95 | } | ||
96 | param_nid = OBJ_obj2nid(gkp->key_params); | ||
97 | digest_nid = OBJ_obj2nid(gkp->hash_params); | ||
98 | GOST_KEY_PARAMS_free(gkp); | ||
99 | |||
100 | ec = pkey->pkey.gost; | ||
101 | if (ec == NULL) { | ||
102 | ec = GOST_KEY_new(); | ||
103 | if (ec == NULL) | ||
104 | return 0; | ||
105 | if (EVP_PKEY_assign_GOST(pkey, ec) == 0) | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | group = EC_GROUP_new_by_curve_name(param_nid); | ||
110 | if (group == NULL) | ||
111 | return 0; | ||
112 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); | ||
113 | if (GOST_KEY_set_group(ec, group) == 0) { | ||
114 | EC_GROUP_free(group); | ||
115 | return 0; | ||
116 | } | ||
117 | EC_GROUP_free(group); | ||
118 | if (GOST_KEY_set_digest(ec, digest_nid) == 0) | ||
119 | return 0; | ||
120 | return 1; | ||
121 | } | ||
122 | |||
123 | static ASN1_STRING * | ||
124 | encode_gost01_algor_params(const EVP_PKEY *key) | ||
125 | { | ||
126 | ASN1_STRING *params = ASN1_STRING_new(); | ||
127 | GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new(); | ||
128 | int pkey_param_nid = NID_undef; | ||
129 | |||
130 | if (params == NULL || gkp == NULL) { | ||
131 | GOSTerr(GOST_F_ENCODE_GOST01_ALGOR_PARAMS, | ||
132 | ERR_R_MALLOC_FAILURE); | ||
133 | ASN1_STRING_free(params); | ||
134 | params = NULL; | ||
135 | goto err; | ||
136 | } | ||
137 | |||
138 | pkey_param_nid = | ||
139 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost)); | ||
140 | gkp->key_params = OBJ_nid2obj(pkey_param_nid); | ||
141 | gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost)); | ||
142 | /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */ | ||
143 | params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data); | ||
144 | if (params->length <= 0) { | ||
145 | GOSTerr(GOST_F_ENCODE_GOST01_ALGOR_PARAMS, | ||
146 | ERR_R_MALLOC_FAILURE); | ||
147 | ASN1_STRING_free(params); | ||
148 | params = NULL; | ||
149 | goto err; | ||
150 | } | ||
151 | params->type = V_ASN1_SEQUENCE; | ||
152 | err: | ||
153 | GOST_KEY_PARAMS_free(gkp); | ||
154 | return params; | ||
155 | } | ||
156 | |||
157 | static int | ||
158 | pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) | ||
159 | { | ||
160 | const GOST_KEY *ea = a->pkey.gost; | ||
161 | const GOST_KEY *eb = b->pkey.gost; | ||
162 | const EC_POINT *ka, *kb; | ||
163 | int ret = 0; | ||
164 | |||
165 | if (ea == NULL || eb == NULL) | ||
166 | return 0; | ||
167 | ka = GOST_KEY_get0_public_key(ea); | ||
168 | kb = GOST_KEY_get0_public_key(eb); | ||
169 | if (ka == NULL || kb == NULL) | ||
170 | return 0; | ||
171 | ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL)); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int | ||
176 | pkey_size_gost01(const EVP_PKEY *pk) | ||
177 | { | ||
178 | if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512) | ||
179 | return 128; | ||
180 | return 64; | ||
181 | } | ||
182 | |||
183 | static int | ||
184 | pkey_bits_gost01(const EVP_PKEY *pk) | ||
185 | { | ||
186 | if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512) | ||
187 | return 512; | ||
188 | return 256; | ||
189 | } | ||
190 | |||
191 | static int | ||
192 | pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub) | ||
193 | { | ||
194 | X509_ALGOR *palg = NULL; | ||
195 | const unsigned char *pubkey_buf = NULL; | ||
196 | const unsigned char *p; | ||
197 | ASN1_OBJECT *palgobj = NULL; | ||
198 | int pub_len; | ||
199 | BIGNUM *X, *Y; | ||
200 | ASN1_OCTET_STRING *octet = NULL; | ||
201 | int len; | ||
202 | int ret; | ||
203 | int ptype = V_ASN1_UNDEF; | ||
204 | ASN1_STRING *pval = NULL; | ||
205 | |||
206 | if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub) | ||
207 | == 0) | ||
208 | return 0; | ||
209 | (void)EVP_PKEY_assign_GOST(pk, NULL); | ||
210 | X509_ALGOR_get0(NULL, &ptype, (void **)&pval, palg); | ||
211 | if (ptype != V_ASN1_SEQUENCE) { | ||
212 | GOSTerr(GOST_F_PUB_DECODE_GOST01, | ||
213 | GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
214 | return 0; | ||
215 | } | ||
216 | p = pval->data; | ||
217 | if (decode_gost01_algor_params(pk, &p, pval->length) == 0) | ||
218 | return 0; | ||
219 | |||
220 | octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len); | ||
221 | if (octet == NULL) { | ||
222 | GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_MALLOC_FAILURE); | ||
223 | return 0; | ||
224 | } | ||
225 | len = octet->length / 2; | ||
226 | |||
227 | X = GOST_le2bn(octet->data, len, NULL); | ||
228 | Y = GOST_le2bn(octet->data + len, len, NULL); | ||
229 | |||
230 | ASN1_OCTET_STRING_free(octet); | ||
231 | |||
232 | ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y); | ||
233 | if (ret == 0) | ||
234 | GOSTerr(GOST_F_PUB_DECODE_GOST01, ERR_R_EC_LIB); | ||
235 | |||
236 | BN_free(X); | ||
237 | BN_free(Y); | ||
238 | |||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static int | ||
243 | pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk) | ||
244 | { | ||
245 | ASN1_OBJECT *algobj = NULL; | ||
246 | ASN1_OCTET_STRING *octet = NULL; | ||
247 | ASN1_STRING *params = NULL; | ||
248 | void *pval = NULL; | ||
249 | unsigned char *buf = NULL, *sptr; | ||
250 | int key_size, ret = 0; | ||
251 | const EC_POINT *pub_key; | ||
252 | BIGNUM *X = NULL, *Y = NULL; | ||
253 | const GOST_KEY *ec = pk->pkey.gost; | ||
254 | int ptype = V_ASN1_UNDEF; | ||
255 | |||
256 | algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec))); | ||
257 | if (pk->save_parameters) { | ||
258 | params = encode_gost01_algor_params(pk); | ||
259 | if (params == NULL) | ||
260 | return 0; | ||
261 | pval = params; | ||
262 | ptype = V_ASN1_SEQUENCE; | ||
263 | } | ||
264 | |||
265 | key_size = GOST_KEY_get_size(ec); | ||
266 | |||
267 | pub_key = GOST_KEY_get0_public_key(ec); | ||
268 | if (pub_key == NULL) { | ||
269 | GOSTerr(GOST_F_PUB_ENCODE_GOST01, GOST_R_PUBLIC_KEY_UNDEFINED); | ||
270 | goto err; | ||
271 | } | ||
272 | |||
273 | octet = ASN1_OCTET_STRING_new(); | ||
274 | if (octet == NULL) { | ||
275 | GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); | ||
276 | goto err; | ||
277 | } | ||
278 | |||
279 | ret = ASN1_STRING_set(octet, NULL, 2 * key_size); | ||
280 | if (ret == 0) { | ||
281 | GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR); | ||
282 | goto err; | ||
283 | } | ||
284 | |||
285 | sptr = ASN1_STRING_data(octet); | ||
286 | |||
287 | X = BN_new(); | ||
288 | Y = BN_new(); | ||
289 | if (X == NULL || Y == NULL) { | ||
290 | GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); | ||
291 | goto err; | ||
292 | } | ||
293 | |||
294 | if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec), | ||
295 | pub_key, X, Y, NULL) == 0) { | ||
296 | GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_EC_LIB); | ||
297 | goto err; | ||
298 | } | ||
299 | |||
300 | GOST_bn2le(X, sptr, key_size); | ||
301 | GOST_bn2le(Y, sptr + key_size, key_size); | ||
302 | |||
303 | BN_free(Y); | ||
304 | BN_free(X); | ||
305 | |||
306 | ret = i2d_ASN1_OCTET_STRING(octet, &buf); | ||
307 | ASN1_BIT_STRING_free(octet); | ||
308 | if (ret < 0) | ||
309 | return 0; | ||
310 | |||
311 | return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret); | ||
312 | |||
313 | err: | ||
314 | BN_free(Y); | ||
315 | BN_free(X); | ||
316 | ASN1_BIT_STRING_free(octet); | ||
317 | ASN1_STRING_free(params); | ||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | static int | ||
322 | param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
323 | { | ||
324 | int param_nid = | ||
325 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost)); | ||
326 | |||
327 | if (BIO_indent(out, indent, 128) == 0) | ||
328 | return 0; | ||
329 | BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid)); | ||
330 | if (BIO_indent(out, indent, 128) == 0) | ||
331 | return 0; | ||
332 | BIO_printf(out, "Digest Algorithm: %s\n", | ||
333 | OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost))); | ||
334 | return 1; | ||
335 | } | ||
336 | |||
337 | static int | ||
338 | pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
339 | { | ||
340 | BN_CTX *ctx = BN_CTX_new(); | ||
341 | BIGNUM *X, *Y; | ||
342 | const EC_POINT *pubkey; | ||
343 | const EC_GROUP *group; | ||
344 | |||
345 | if (ctx == NULL) { | ||
346 | GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_MALLOC_FAILURE); | ||
347 | return 0; | ||
348 | } | ||
349 | BN_CTX_start(ctx); | ||
350 | if ((X = BN_CTX_get(ctx)) == NULL) | ||
351 | goto err; | ||
352 | if ((Y = BN_CTX_get(ctx)) == NULL) | ||
353 | goto err; | ||
354 | pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost); | ||
355 | group = GOST_KEY_get0_group(pkey->pkey.gost); | ||
356 | if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, | ||
357 | ctx) == 0) { | ||
358 | GOSTerr(GOST_F_PUB_PRINT_GOST01, ERR_R_EC_LIB); | ||
359 | goto err; | ||
360 | } | ||
361 | if (BIO_indent(out, indent, 128) == 0) | ||
362 | goto err; | ||
363 | BIO_printf(out, "Public key:\n"); | ||
364 | if (BIO_indent(out, indent + 3, 128) == 0) | ||
365 | goto err; | ||
366 | BIO_printf(out, "X:"); | ||
367 | BN_print(out, X); | ||
368 | BIO_printf(out, "\n"); | ||
369 | BIO_indent(out, indent + 3, 128); | ||
370 | BIO_printf(out, "Y:"); | ||
371 | BN_print(out, Y); | ||
372 | BIO_printf(out, "\n"); | ||
373 | |||
374 | BN_CTX_end(ctx); | ||
375 | BN_CTX_free(ctx); | ||
376 | |||
377 | return param_print_gost01(out, pkey, indent, pctx); | ||
378 | |||
379 | err: | ||
380 | BN_CTX_end(ctx); | ||
381 | BN_CTX_free(ctx); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int | ||
386 | priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx) | ||
387 | { | ||
388 | const BIGNUM *key; | ||
389 | |||
390 | if (BIO_indent(out, indent, 128) == 0) | ||
391 | return 0; | ||
392 | BIO_printf(out, "Private key: "); | ||
393 | key = GOST_KEY_get0_private_key(pkey->pkey.gost); | ||
394 | if (key == NULL) | ||
395 | BIO_printf(out, "<undefined)"); | ||
396 | else | ||
397 | BN_print(out, key); | ||
398 | BIO_printf(out, "\n"); | ||
399 | |||
400 | return pub_print_gost01(out, pkey, indent, pctx); | ||
401 | } | ||
402 | |||
403 | static int | ||
404 | priv_decode_gost01(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf) | ||
405 | { | ||
406 | const unsigned char *pkey_buf = NULL, *p = NULL; | ||
407 | int priv_len = 0; | ||
408 | BIGNUM *pk_num = NULL; | ||
409 | int ret = 0; | ||
410 | X509_ALGOR *palg = NULL; | ||
411 | ASN1_OBJECT *palg_obj = NULL; | ||
412 | ASN1_INTEGER *priv_key = NULL; | ||
413 | GOST_KEY *ec; | ||
414 | int ptype = V_ASN1_UNDEF; | ||
415 | ASN1_STRING *pval = NULL; | ||
416 | |||
417 | if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0) | ||
418 | return 0; | ||
419 | (void)EVP_PKEY_assign_GOST(pk, NULL); | ||
420 | X509_ALGOR_get0(NULL, &ptype, (void **)&pval, palg); | ||
421 | if (ptype != V_ASN1_SEQUENCE) { | ||
422 | GOSTerr(GOST_F_PUB_DECODE_GOST01, | ||
423 | GOST_R_BAD_KEY_PARAMETERS_FORMAT); | ||
424 | return 0; | ||
425 | } | ||
426 | p = pval->data; | ||
427 | if (decode_gost01_algor_params(pk, &p, pval->length) == 0) | ||
428 | return 0; | ||
429 | p = pkey_buf; | ||
430 | if (V_ASN1_OCTET_STRING == *p) { | ||
431 | /* New format - Little endian octet string */ | ||
432 | unsigned char rev_buf[32]; | ||
433 | int i; | ||
434 | ASN1_OCTET_STRING *s = | ||
435 | d2i_ASN1_OCTET_STRING(NULL, &p, priv_len); | ||
436 | |||
437 | if (s == NULL || s->length != 32) { | ||
438 | GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR); | ||
439 | ASN1_STRING_free(s); | ||
440 | return 0; | ||
441 | } | ||
442 | for (i = 0; i < 32; i++) { | ||
443 | rev_buf[31 - i] = s->data[i]; | ||
444 | } | ||
445 | ASN1_STRING_free(s); | ||
446 | pk_num = BN_bin2bn(rev_buf, 32, NULL); | ||
447 | } else { | ||
448 | priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len); | ||
449 | if (priv_key == NULL) | ||
450 | return 0; | ||
451 | ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL); | ||
452 | ASN1_INTEGER_free(priv_key); | ||
453 | if (ret == 0) { | ||
454 | GOSTerr(GOST_F_PRIV_DECODE_GOST01, EVP_R_DECODE_ERROR); | ||
455 | return 0; | ||
456 | } | ||
457 | } | ||
458 | |||
459 | ec = pk->pkey.gost; | ||
460 | if (ec == NULL) { | ||
461 | ec = GOST_KEY_new(); | ||
462 | if (ec == NULL) { | ||
463 | BN_free(pk_num); | ||
464 | return 0; | ||
465 | } | ||
466 | if (EVP_PKEY_assign_GOST(pk, ec) == 0) { | ||
467 | BN_free(pk_num); | ||
468 | GOST_KEY_free(ec); | ||
469 | return 0; | ||
470 | } | ||
471 | } | ||
472 | if (GOST_KEY_set_private_key(ec, pk_num) == 0) { | ||
473 | BN_free(pk_num); | ||
474 | return 0; | ||
475 | } | ||
476 | ret = 0; | ||
477 | if (EVP_PKEY_missing_parameters(pk) == 0) | ||
478 | ret = gost2001_compute_public(ec) != 0; | ||
479 | BN_free(pk_num); | ||
480 | |||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static int | ||
485 | priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk) | ||
486 | { | ||
487 | ASN1_OBJECT *algobj = | ||
488 | OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost))); | ||
489 | ASN1_STRING *params = encode_gost01_algor_params(pk); | ||
490 | unsigned char *priv_buf = NULL; | ||
491 | int priv_len; | ||
492 | ASN1_INTEGER *asn1key = NULL; | ||
493 | |||
494 | if (params == NULL) | ||
495 | return 0; | ||
496 | |||
497 | asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost), | ||
498 | NULL); | ||
499 | if (asn1key == NULL) { | ||
500 | ASN1_STRING_free(params); | ||
501 | return 0; | ||
502 | } | ||
503 | priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf); | ||
504 | ASN1_INTEGER_free(asn1key); | ||
505 | return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf, | ||
506 | priv_len); | ||
507 | } | ||
508 | |||
509 | static int | ||
510 | param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder) | ||
511 | { | ||
512 | ASN1_STRING *params = encode_gost01_algor_params(pkey); | ||
513 | int len; | ||
514 | |||
515 | if (params == NULL) | ||
516 | return 0; | ||
517 | len = params->length; | ||
518 | if (pder != NULL) | ||
519 | memcpy(*pder, params->data, params->length); | ||
520 | ASN1_STRING_free(params); | ||
521 | return len; | ||
522 | } | ||
523 | |||
524 | static int | ||
525 | param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen) | ||
526 | { | ||
527 | ASN1_OBJECT *obj = NULL; | ||
528 | int nid; | ||
529 | GOST_KEY *ec; | ||
530 | EC_GROUP *group; | ||
531 | int ret; | ||
532 | |||
533 | /* New format */ | ||
534 | if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder) | ||
535 | return decode_gost01_algor_params(pkey, pder, derlen); | ||
536 | |||
537 | /* Compatibility */ | ||
538 | if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) { | ||
539 | GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_MALLOC_FAILURE); | ||
540 | return 0; | ||
541 | } | ||
542 | nid = OBJ_obj2nid(obj); | ||
543 | ASN1_OBJECT_free(obj); | ||
544 | |||
545 | ec = GOST_KEY_new(); | ||
546 | if (ec == NULL) { | ||
547 | GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_MALLOC_FAILURE); | ||
548 | return 0; | ||
549 | } | ||
550 | group = EC_GROUP_new_by_curve_name(nid); | ||
551 | if (group == NULL) { | ||
552 | GOSTerr(GOST_F_PARAM_DECODE_GOST01, | ||
553 | EC_R_EC_GROUP_NEW_BY_NAME_FAILURE); | ||
554 | GOST_KEY_free(ec); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); | ||
559 | if (GOST_KEY_set_group(ec, group) == 0) { | ||
560 | GOSTerr(GOST_F_PARAM_DECODE_GOST01, ERR_R_EC_LIB); | ||
561 | EC_GROUP_free(group); | ||
562 | GOST_KEY_free(ec); | ||
563 | return 0; | ||
564 | } | ||
565 | EC_GROUP_free(group); | ||
566 | if (GOST_KEY_set_digest(ec, | ||
567 | NID_id_GostR3411_94_CryptoProParamSet) == 0) { | ||
568 | GOSTerr(GOST_F_PARAM_DECODE_GOST01, GOST_R_INVALID_DIGEST_TYPE); | ||
569 | GOST_KEY_free(ec); | ||
570 | return 0; | ||
571 | } | ||
572 | ret = EVP_PKEY_assign_GOST(pkey, ec); | ||
573 | if (ret == 0) | ||
574 | GOST_KEY_free(ec); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | static int | ||
579 | param_missing_gost01(const EVP_PKEY *pk) | ||
580 | { | ||
581 | const GOST_KEY *ec = pk->pkey.gost; | ||
582 | |||
583 | if (ec == NULL) | ||
584 | return 1; | ||
585 | if (GOST_KEY_get0_group(ec) == NULL) | ||
586 | return 1; | ||
587 | if (GOST_KEY_get_digest(ec) == NID_undef) | ||
588 | return 1; | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | static int | ||
593 | param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) | ||
594 | { | ||
595 | GOST_KEY *eto = to->pkey.gost; | ||
596 | const GOST_KEY *efrom = from->pkey.gost; | ||
597 | int ret = 1; | ||
598 | |||
599 | if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) { | ||
600 | GOSTerr(GOST_F_PARAM_COPY_GOST01, | ||
601 | GOST_R_INCOMPATIBLE_ALGORITHMS); | ||
602 | return 0; | ||
603 | } | ||
604 | if (efrom == NULL) { | ||
605 | GOSTerr(GOST_F_PARAM_COPY_GOST01, | ||
606 | GOST_R_KEY_PARAMETERS_MISSING); | ||
607 | return 0; | ||
608 | } | ||
609 | if (eto == NULL) { | ||
610 | eto = GOST_KEY_new(); | ||
611 | if (eto == NULL) { | ||
612 | GOSTerr(GOST_F_PARAM_COPY_GOST01, | ||
613 | ERR_R_MALLOC_FAILURE); | ||
614 | return 0; | ||
615 | } | ||
616 | if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) { | ||
617 | GOST_KEY_free(eto); | ||
618 | return 0; | ||
619 | } | ||
620 | } | ||
621 | GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom)); | ||
622 | GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom)); | ||
623 | if (GOST_KEY_get0_private_key(eto) != NULL) | ||
624 | ret = gost2001_compute_public(eto); | ||
625 | |||
626 | return ret; | ||
627 | } | ||
628 | |||
629 | static int | ||
630 | param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b) | ||
631 | { | ||
632 | if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) != | ||
633 | EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost))) | ||
634 | return 0; | ||
635 | |||
636 | if (GOST_KEY_get_digest(a->pkey.gost) != | ||
637 | GOST_KEY_get_digest(b->pkey.gost)) | ||
638 | return 0; | ||
639 | |||
640 | return 1; | ||
641 | } | ||
642 | |||
643 | static int | ||
644 | pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2) | ||
645 | { | ||
646 | X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL; | ||
647 | int digest = GOST_KEY_get_digest(pkey->pkey.gost); | ||
648 | |||
649 | switch (op) { | ||
650 | case ASN1_PKEY_CTRL_PKCS7_SIGN: | ||
651 | if (arg1 == 0) | ||
652 | PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2); | ||
653 | break; | ||
654 | |||
655 | case ASN1_PKEY_CTRL_PKCS7_ENCRYPT: | ||
656 | if (arg1 == 0) | ||
657 | PKCS7_RECIP_INFO_get0_alg(arg2, &alg3); | ||
658 | break; | ||
659 | #ifndef OPENSSL_NO_CMS | ||
660 | case ASN1_PKEY_CTRL_CMS_SIGN: | ||
661 | if (arg1 == 0) | ||
662 | CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2); | ||
663 | break; | ||
664 | |||
665 | case ASN1_PKEY_CTRL_CMS_ENVELOPE: | ||
666 | if (arg1 == 0) | ||
667 | CMS_RecipientInfo_ktri_get0_algs(arg2, NULL, NULL, &alg3); | ||
668 | break; | ||
669 | #endif | ||
670 | case ASN1_PKEY_CTRL_DEFAULT_MD_NID: | ||
671 | *(int *)arg2 = GostR3410_get_md_digest(digest); | ||
672 | return 2; | ||
673 | |||
674 | default: | ||
675 | return -2; | ||
676 | } | ||
677 | |||
678 | if (alg1) | ||
679 | X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0); | ||
680 | if (alg2) | ||
681 | X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0); | ||
682 | if (alg3) { | ||
683 | ASN1_STRING *params = encode_gost01_algor_params(pkey); | ||
684 | if (params == NULL) { | ||
685 | return -1; | ||
686 | } | ||
687 | X509_ALGOR_set0(alg3, | ||
688 | OBJ_nid2obj(GostR3410_get_pk_digest(digest)), | ||
689 | V_ASN1_SEQUENCE, params); | ||
690 | } | ||
691 | |||
692 | return 1; | ||
693 | } | ||
694 | |||
695 | const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = { | ||
696 | { | ||
697 | .pkey_id = EVP_PKEY_GOSTR01, | ||
698 | .pkey_base_id = EVP_PKEY_GOSTR01, | ||
699 | .pkey_flags = ASN1_PKEY_SIGPARAM_NULL, | ||
700 | |||
701 | .pem_str = "GOST2001", | ||
702 | .info = "GOST R 34.10-2001", | ||
703 | |||
704 | .pkey_free = pkey_free_gost01, | ||
705 | .pkey_ctrl = pkey_ctrl_gost01, | ||
706 | |||
707 | .priv_decode = priv_decode_gost01, | ||
708 | .priv_encode = priv_encode_gost01, | ||
709 | .priv_print = priv_print_gost01, | ||
710 | |||
711 | .param_decode = param_decode_gost01, | ||
712 | .param_encode = param_encode_gost01, | ||
713 | .param_missing = param_missing_gost01, | ||
714 | .param_copy = param_copy_gost01, | ||
715 | .param_cmp = param_cmp_gost01, | ||
716 | .param_print = param_print_gost01, | ||
717 | |||
718 | .pub_decode = pub_decode_gost01, | ||
719 | .pub_encode = pub_encode_gost01, | ||
720 | .pub_cmp = pub_cmp_gost01, | ||
721 | .pub_print = pub_print_gost01, | ||
722 | .pkey_size = pkey_size_gost01, | ||
723 | .pkey_bits = pkey_bits_gost01, | ||
724 | }, | ||
725 | { | ||
726 | .pkey_id = EVP_PKEY_GOSTR12_256, | ||
727 | .pkey_base_id = EVP_PKEY_GOSTR01, | ||
728 | .pkey_flags = ASN1_PKEY_ALIAS | ||
729 | }, | ||
730 | { | ||
731 | .pkey_id = EVP_PKEY_GOSTR12_512, | ||
732 | .pkey_base_id = EVP_PKEY_GOSTR01, | ||
733 | .pkey_flags = ASN1_PKEY_ALIAS | ||
734 | }, | ||
735 | }; | ||
736 | |||
737 | #endif | ||