1 /* $OpenBSD: gostr341001_ameth.c,v 1.16 2020/06/05 17:17:22 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
65 #include "asn1_locl.h"
66 #include "gost_locl.h"
67 #include "gost_asn1.h"
68
69 static void
pkey_free_gost01(EVP_PKEY * key)70 pkey_free_gost01(EVP_PKEY *key)
71 {
72 GOST_KEY_free(key->pkey.gost);
73 }
74
75 /*
76 * Parses GOST algorithm parameters from X509_ALGOR and
77 * modifies pkey setting NID and parameters
78 */
79 static int
decode_gost01_algor_params(EVP_PKEY * pkey,const unsigned char ** p,int len)80 decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
81 {
82 int param_nid = NID_undef, digest_nid = NID_undef;
83 GOST_KEY_PARAMS *gkp = NULL;
84 EC_GROUP *group;
85 GOST_KEY *ec;
86
87 gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
88 if (gkp == NULL) {
89 GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
90 return 0;
91 }
92 param_nid = OBJ_obj2nid(gkp->key_params);
93 digest_nid = OBJ_obj2nid(gkp->hash_params);
94 GOST_KEY_PARAMS_free(gkp);
95
96 ec = pkey->pkey.gost;
97 if (ec == NULL) {
98 ec = GOST_KEY_new();
99 if (ec == NULL) {
100 GOSTerror(ERR_R_MALLOC_FAILURE);
101 return 0;
102 }
103 if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
104 return 0;
105 }
106
107 group = EC_GROUP_new_by_curve_name(param_nid);
108 if (group == NULL) {
109 GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
110 return 0;
111 }
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 *
encode_gost01_algor_params(const EVP_PKEY * key)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 GOSTerror(ERR_R_MALLOC_FAILURE);
132 ASN1_STRING_free(params);
133 params = NULL;
134 goto err;
135 }
136
137 pkey_param_nid =
138 EC_GROUP_get_curve_name(GOST_KEY_get0_group(key->pkey.gost));
139 gkp->key_params = OBJ_nid2obj(pkey_param_nid);
140 gkp->hash_params = OBJ_nid2obj(GOST_KEY_get_digest(key->pkey.gost));
141 /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
142 params->length = i2d_GOST_KEY_PARAMS(gkp, ¶ms->data);
143 if (params->length <= 0) {
144 GOSTerror(ERR_R_MALLOC_FAILURE);
145 ASN1_STRING_free(params);
146 params = NULL;
147 goto err;
148 }
149 params->type = V_ASN1_SEQUENCE;
150 err:
151 GOST_KEY_PARAMS_free(gkp);
152 return params;
153 }
154
155 static int
pub_cmp_gost01(const EVP_PKEY * a,const EVP_PKEY * b)156 pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
157 {
158 const GOST_KEY *ea = a->pkey.gost;
159 const GOST_KEY *eb = b->pkey.gost;
160 const EC_POINT *ka, *kb;
161 int ret = 0;
162
163 if (ea == NULL || eb == NULL)
164 return 0;
165 ka = GOST_KEY_get0_public_key(ea);
166 kb = GOST_KEY_get0_public_key(eb);
167 if (ka == NULL || kb == NULL)
168 return 0;
169 ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
170 return ret;
171 }
172
173 static int
pkey_size_gost01(const EVP_PKEY * pk)174 pkey_size_gost01(const EVP_PKEY *pk)
175 {
176 if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
177 return 128;
178 return 64;
179 }
180
181 static int
pkey_bits_gost01(const EVP_PKEY * pk)182 pkey_bits_gost01(const EVP_PKEY *pk)
183 {
184 if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
185 return 512;
186 return 256;
187 }
188
189 static int
pub_decode_gost01(EVP_PKEY * pk,X509_PUBKEY * pub)190 pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
191 {
192 X509_ALGOR *palg = NULL;
193 const unsigned char *pubkey_buf = NULL;
194 const unsigned char *p;
195 ASN1_OBJECT *palgobj = NULL;
196 int pub_len;
197 BIGNUM *X, *Y;
198 ASN1_OCTET_STRING *octet = NULL;
199 int len;
200 int ret;
201 int ptype = V_ASN1_UNDEF;
202 ASN1_STRING *pval = NULL;
203
204 if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
205 == 0)
206 return 0;
207 (void)EVP_PKEY_assign_GOST(pk, NULL);
208 X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
209 if (ptype != V_ASN1_SEQUENCE) {
210 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
211 return 0;
212 }
213 p = pval->data;
214 if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
215 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
216 return 0;
217 }
218
219 octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
220 if (octet == NULL) {
221 GOSTerror(ERR_R_MALLOC_FAILURE);
222 return 0;
223 }
224 len = octet->length / 2;
225
226 X = GOST_le2bn(octet->data, len, NULL);
227 Y = GOST_le2bn(octet->data + len, len, NULL);
228
229 ASN1_OCTET_STRING_free(octet);
230
231 ret = GOST_KEY_set_public_key_affine_coordinates(pk->pkey.gost, X, Y);
232 if (ret == 0)
233 GOSTerror(ERR_R_EC_LIB);
234
235 BN_free(X);
236 BN_free(Y);
237
238 return ret;
239 }
240
241 static int
pub_encode_gost01(X509_PUBKEY * pub,const EVP_PKEY * pk)242 pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk)
243 {
244 ASN1_OBJECT *algobj = NULL;
245 ASN1_OCTET_STRING *octet = NULL;
246 ASN1_STRING *params = NULL;
247 void *pval = NULL;
248 unsigned char *buf = NULL, *sptr;
249 int key_size, ret = 0;
250 const EC_POINT *pub_key;
251 BIGNUM *X = NULL, *Y = NULL;
252 const GOST_KEY *ec = pk->pkey.gost;
253 int ptype = V_ASN1_UNDEF;
254
255 algobj = OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec)));
256 if (pk->save_parameters) {
257 params = encode_gost01_algor_params(pk);
258 if (params == NULL)
259 return 0;
260 pval = params;
261 ptype = V_ASN1_SEQUENCE;
262 }
263
264 key_size = GOST_KEY_get_size(ec);
265
266 pub_key = GOST_KEY_get0_public_key(ec);
267 if (pub_key == NULL) {
268 GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED);
269 goto err;
270 }
271
272 octet = ASN1_OCTET_STRING_new();
273 if (octet == NULL) {
274 GOSTerror(ERR_R_MALLOC_FAILURE);
275 goto err;
276 }
277
278 ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
279 if (ret == 0) {
280 GOSTerror(ERR_R_INTERNAL_ERROR);
281 goto err;
282 }
283
284 sptr = ASN1_STRING_data(octet);
285
286 X = BN_new();
287 Y = BN_new();
288 if (X == NULL || Y == NULL) {
289 GOSTerror(ERR_R_MALLOC_FAILURE);
290 goto err;
291 }
292
293 if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec),
294 pub_key, X, Y, NULL) == 0) {
295 GOSTerror(ERR_R_EC_LIB);
296 goto err;
297 }
298
299 GOST_bn2le(X, sptr, key_size);
300 GOST_bn2le(Y, sptr + key_size, key_size);
301
302 BN_free(Y);
303 BN_free(X);
304
305 ret = i2d_ASN1_OCTET_STRING(octet, &buf);
306 ASN1_BIT_STRING_free(octet);
307 if (ret < 0)
308 return 0;
309
310 return X509_PUBKEY_set0_param(pub, algobj, ptype, pval, buf, ret);
311
312 err:
313 BN_free(Y);
314 BN_free(X);
315 ASN1_BIT_STRING_free(octet);
316 ASN1_STRING_free(params);
317 return 0;
318 }
319
320 static int
param_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)321 param_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
322 {
323 int param_nid =
324 EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey->pkey.gost));
325
326 if (BIO_indent(out, indent, 128) == 0)
327 return 0;
328 BIO_printf(out, "Parameter set: %s\n", OBJ_nid2ln(param_nid));
329 if (BIO_indent(out, indent, 128) == 0)
330 return 0;
331 BIO_printf(out, "Digest Algorithm: %s\n",
332 OBJ_nid2ln(GOST_KEY_get_digest(pkey->pkey.gost)));
333 return 1;
334 }
335
336 static int
pub_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)337 pub_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
338 {
339 BN_CTX *ctx = BN_CTX_new();
340 BIGNUM *X, *Y;
341 const EC_POINT *pubkey;
342 const EC_GROUP *group;
343
344 if (ctx == NULL) {
345 GOSTerror(ERR_R_MALLOC_FAILURE);
346 return 0;
347 }
348 BN_CTX_start(ctx);
349 if ((X = BN_CTX_get(ctx)) == NULL)
350 goto err;
351 if ((Y = BN_CTX_get(ctx)) == NULL)
352 goto err;
353 pubkey = GOST_KEY_get0_public_key(pkey->pkey.gost);
354 group = GOST_KEY_get0_group(pkey->pkey.gost);
355 if (EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y,
356 ctx) == 0) {
357 GOSTerror(ERR_R_EC_LIB);
358 goto err;
359 }
360 if (BIO_indent(out, indent, 128) == 0)
361 goto err;
362 BIO_printf(out, "Public key:\n");
363 if (BIO_indent(out, indent + 3, 128) == 0)
364 goto err;
365 BIO_printf(out, "X:");
366 BN_print(out, X);
367 BIO_printf(out, "\n");
368 BIO_indent(out, indent + 3, 128);
369 BIO_printf(out, "Y:");
370 BN_print(out, Y);
371 BIO_printf(out, "\n");
372
373 BN_CTX_end(ctx);
374 BN_CTX_free(ctx);
375
376 return param_print_gost01(out, pkey, indent, pctx);
377
378 err:
379 BN_CTX_end(ctx);
380 BN_CTX_free(ctx);
381 return 0;
382 }
383
384 static int
priv_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)385 priv_print_gost01(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx)
386 {
387 const BIGNUM *key;
388
389 if (BIO_indent(out, indent, 128) == 0)
390 return 0;
391 BIO_printf(out, "Private key: ");
392 key = GOST_KEY_get0_private_key(pkey->pkey.gost);
393 if (key == NULL)
394 BIO_printf(out, "<undefined)");
395 else
396 BN_print(out, key);
397 BIO_printf(out, "\n");
398
399 return pub_print_gost01(out, pkey, indent, pctx);
400 }
401
402 static int
priv_decode_gost01(EVP_PKEY * pk,const PKCS8_PRIV_KEY_INFO * p8inf)403 priv_decode_gost01(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf)
404 {
405 const unsigned char *pkey_buf = NULL, *p = NULL;
406 int priv_len = 0;
407 BIGNUM *pk_num = NULL;
408 int ret = 0;
409 const X509_ALGOR *palg = NULL;
410 const ASN1_OBJECT *palg_obj = NULL;
411 ASN1_INTEGER *priv_key = NULL;
412 GOST_KEY *ec;
413 int ptype = V_ASN1_UNDEF;
414 ASN1_STRING *pval = NULL;
415
416 if (PKCS8_pkey_get0(&palg_obj, &pkey_buf, &priv_len, &palg, p8inf) == 0) {
417 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
418 return 0;
419 }
420 (void)EVP_PKEY_assign_GOST(pk, NULL);
421 X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
422 if (ptype != V_ASN1_SEQUENCE) {
423 GOSTerror(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 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
429 return 0;
430 }
431 p = pkey_buf;
432 if (V_ASN1_OCTET_STRING == *p) {
433 /* New format - Little endian octet string */
434 ASN1_OCTET_STRING *s =
435 d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
436
437 if (s == NULL) {
438 GOSTerror(EVP_R_DECODE_ERROR);
439 ASN1_STRING_free(s);
440 return 0;
441 }
442
443 pk_num = GOST_le2bn(s->data, s->length, NULL);
444 ASN1_STRING_free(s);
445 } else {
446 priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
447 if (priv_key == NULL)
448 return 0;
449 ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
450 ASN1_INTEGER_free(priv_key);
451 if (ret == 0) {
452 GOSTerror(EVP_R_DECODE_ERROR);
453 return 0;
454 }
455 }
456
457 ec = pk->pkey.gost;
458 if (ec == NULL) {
459 ec = GOST_KEY_new();
460 if (ec == NULL) {
461 BN_free(pk_num);
462 return 0;
463 }
464 if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
465 BN_free(pk_num);
466 GOST_KEY_free(ec);
467 return 0;
468 }
469 }
470 if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
471 BN_free(pk_num);
472 return 0;
473 }
474 ret = 0;
475 if (EVP_PKEY_missing_parameters(pk) == 0)
476 ret = gost2001_compute_public(ec) != 0;
477 BN_free(pk_num);
478
479 return ret;
480 }
481
482 static int
priv_encode_gost01(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pk)483 priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
484 {
485 ASN1_OBJECT *algobj =
486 OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
487 ASN1_STRING *params = encode_gost01_algor_params(pk);
488 unsigned char *priv_buf = NULL;
489 int priv_len;
490 ASN1_INTEGER *asn1key = NULL;
491
492 if (params == NULL)
493 return 0;
494
495 asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
496 NULL);
497 if (asn1key == NULL) {
498 ASN1_STRING_free(params);
499 return 0;
500 }
501 priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
502 ASN1_INTEGER_free(asn1key);
503 return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
504 priv_len);
505 }
506
507 static int
param_encode_gost01(const EVP_PKEY * pkey,unsigned char ** pder)508 param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
509 {
510 ASN1_STRING *params = encode_gost01_algor_params(pkey);
511 int len;
512
513 if (params == NULL)
514 return 0;
515 len = params->length;
516 if (pder != NULL)
517 memcpy(*pder, params->data, params->length);
518 ASN1_STRING_free(params);
519 return len;
520 }
521
522 static int
param_decode_gost01(EVP_PKEY * pkey,const unsigned char ** pder,int derlen)523 param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
524 {
525 ASN1_OBJECT *obj = NULL;
526 int nid;
527 GOST_KEY *ec;
528 EC_GROUP *group;
529 int ret;
530
531 /* New format */
532 if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
533 return decode_gost01_algor_params(pkey, pder, derlen);
534
535 /* Compatibility */
536 if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
537 GOSTerror(ERR_R_MALLOC_FAILURE);
538 return 0;
539 }
540 nid = OBJ_obj2nid(obj);
541 ASN1_OBJECT_free(obj);
542
543 ec = GOST_KEY_new();
544 if (ec == NULL) {
545 GOSTerror(ERR_R_MALLOC_FAILURE);
546 return 0;
547 }
548 group = EC_GROUP_new_by_curve_name(nid);
549 if (group == NULL) {
550 GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
551 GOST_KEY_free(ec);
552 return 0;
553 }
554
555 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
556 if (GOST_KEY_set_group(ec, group) == 0) {
557 GOSTerror(ERR_R_EC_LIB);
558 EC_GROUP_free(group);
559 GOST_KEY_free(ec);
560 return 0;
561 }
562 EC_GROUP_free(group);
563 if (GOST_KEY_set_digest(ec,
564 NID_id_GostR3411_94_CryptoProParamSet) == 0) {
565 GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
566 GOST_KEY_free(ec);
567 return 0;
568 }
569 ret = EVP_PKEY_assign_GOST(pkey, ec);
570 if (ret == 0)
571 GOST_KEY_free(ec);
572 return ret;
573 }
574
575 static int
param_missing_gost01(const EVP_PKEY * pk)576 param_missing_gost01(const EVP_PKEY *pk)
577 {
578 const GOST_KEY *ec = pk->pkey.gost;
579
580 if (ec == NULL)
581 return 1;
582 if (GOST_KEY_get0_group(ec) == NULL)
583 return 1;
584 if (GOST_KEY_get_digest(ec) == NID_undef)
585 return 1;
586 return 0;
587 }
588
589 static int
param_copy_gost01(EVP_PKEY * to,const EVP_PKEY * from)590 param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
591 {
592 GOST_KEY *eto = to->pkey.gost;
593 const GOST_KEY *efrom = from->pkey.gost;
594 int ret = 1;
595
596 if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
597 GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
598 return 0;
599 }
600 if (efrom == NULL) {
601 GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
602 return 0;
603 }
604 if (eto == NULL) {
605 eto = GOST_KEY_new();
606 if (eto == NULL) {
607 GOSTerror(ERR_R_MALLOC_FAILURE);
608 return 0;
609 }
610 if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
611 GOST_KEY_free(eto);
612 return 0;
613 }
614 }
615 GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
616 GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
617 if (GOST_KEY_get0_private_key(eto) != NULL)
618 ret = gost2001_compute_public(eto);
619
620 return ret;
621 }
622
623 static int
param_cmp_gost01(const EVP_PKEY * a,const EVP_PKEY * b)624 param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
625 {
626 if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
627 EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
628 return 0;
629
630 if (GOST_KEY_get_digest(a->pkey.gost) !=
631 GOST_KEY_get_digest(b->pkey.gost))
632 return 0;
633
634 return 1;
635 }
636
637 static int
pkey_ctrl_gost01(EVP_PKEY * pkey,int op,long arg1,void * arg2)638 pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
639 {
640 X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
641 int digest = GOST_KEY_get_digest(pkey->pkey.gost);
642
643 switch (op) {
644 case ASN1_PKEY_CTRL_PKCS7_SIGN:
645 if (arg1 == 0)
646 PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
647 break;
648
649 case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
650 if (arg1 == 0)
651 PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
652 break;
653 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
654 *(int *)arg2 = GostR3410_get_md_digest(digest);
655 return 2;
656
657 default:
658 return -2;
659 }
660
661 if (alg1)
662 X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
663 if (alg2)
664 X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
665 if (alg3) {
666 ASN1_STRING *params = encode_gost01_algor_params(pkey);
667 if (params == NULL) {
668 return -1;
669 }
670 X509_ALGOR_set0(alg3,
671 OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
672 V_ASN1_SEQUENCE, params);
673 }
674
675 return 1;
676 }
677
678 const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
679 {
680 .pkey_id = EVP_PKEY_GOSTR01,
681 .pkey_base_id = EVP_PKEY_GOSTR01,
682 .pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
683
684 .pem_str = "GOST2001",
685 .info = "GOST R 34.10-2001",
686
687 .pkey_free = pkey_free_gost01,
688 .pkey_ctrl = pkey_ctrl_gost01,
689
690 .priv_decode = priv_decode_gost01,
691 .priv_encode = priv_encode_gost01,
692 .priv_print = priv_print_gost01,
693
694 .param_decode = param_decode_gost01,
695 .param_encode = param_encode_gost01,
696 .param_missing = param_missing_gost01,
697 .param_copy = param_copy_gost01,
698 .param_cmp = param_cmp_gost01,
699 .param_print = param_print_gost01,
700
701 .pub_decode = pub_decode_gost01,
702 .pub_encode = pub_encode_gost01,
703 .pub_cmp = pub_cmp_gost01,
704 .pub_print = pub_print_gost01,
705 .pkey_size = pkey_size_gost01,
706 .pkey_bits = pkey_bits_gost01,
707 },
708 {
709 .pkey_id = EVP_PKEY_GOSTR12_256,
710 .pkey_base_id = EVP_PKEY_GOSTR01,
711 .pkey_flags = ASN1_PKEY_ALIAS
712 },
713 {
714 .pkey_id = EVP_PKEY_GOSTR12_512,
715 .pkey_base_id = EVP_PKEY_GOSTR01,
716 .pkey_flags = ASN1_PKEY_ALIAS
717 },
718 };
719
720 #endif
721