1 /* $OpenBSD: gostr341001_ameth.c,v 1.19 2021/12/26 15:38:49 tb 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 "evp_locl.h"
67 #include "gost_locl.h"
68 #include "gost_asn1.h"
69
70 static void
pkey_free_gost01(EVP_PKEY * key)71 pkey_free_gost01(EVP_PKEY *key)
72 {
73 GOST_KEY_free(key->pkey.gost);
74 }
75
76 /*
77 * Parses GOST algorithm parameters from X509_ALGOR and
78 * modifies pkey setting NID and parameters
79 */
80 static int
decode_gost01_algor_params(EVP_PKEY * pkey,const unsigned char ** p,int len)81 decode_gost01_algor_params(EVP_PKEY *pkey, const unsigned char **p, int len)
82 {
83 int param_nid = NID_undef, digest_nid = NID_undef;
84 GOST_KEY_PARAMS *gkp = NULL;
85 EC_GROUP *group;
86 GOST_KEY *ec;
87
88 gkp = d2i_GOST_KEY_PARAMS(NULL, p, len);
89 if (gkp == NULL) {
90 GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT);
91 return 0;
92 }
93 param_nid = OBJ_obj2nid(gkp->key_params);
94 digest_nid = OBJ_obj2nid(gkp->hash_params);
95 GOST_KEY_PARAMS_free(gkp);
96
97 ec = pkey->pkey.gost;
98 if (ec == NULL) {
99 ec = GOST_KEY_new();
100 if (ec == NULL) {
101 GOSTerror(ERR_R_MALLOC_FAILURE);
102 return 0;
103 }
104 if (EVP_PKEY_assign_GOST(pkey, ec) == 0)
105 return 0;
106 }
107
108 group = EC_GROUP_new_by_curve_name(param_nid);
109 if (group == NULL) {
110 GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
111 return 0;
112 }
113 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
114 if (GOST_KEY_set_group(ec, group) == 0) {
115 EC_GROUP_free(group);
116 return 0;
117 }
118 EC_GROUP_free(group);
119 if (GOST_KEY_set_digest(ec, digest_nid) == 0)
120 return 0;
121 return 1;
122 }
123
124 static ASN1_STRING *
encode_gost01_algor_params(const EVP_PKEY * key)125 encode_gost01_algor_params(const EVP_PKEY *key)
126 {
127 ASN1_STRING *params = ASN1_STRING_new();
128 GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
129 int pkey_param_nid = NID_undef;
130
131 if (params == NULL || gkp == NULL) {
132 GOSTerror(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 GOSTerror(ERR_R_MALLOC_FAILURE);
146 ASN1_STRING_free(params);
147 params = NULL;
148 goto err;
149 }
150 params->type = V_ASN1_SEQUENCE;
151 err:
152 GOST_KEY_PARAMS_free(gkp);
153 return params;
154 }
155
156 static int
pub_cmp_gost01(const EVP_PKEY * a,const EVP_PKEY * b)157 pub_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
158 {
159 const GOST_KEY *ea = a->pkey.gost;
160 const GOST_KEY *eb = b->pkey.gost;
161 const EC_POINT *ka, *kb;
162 int ret = 0;
163
164 if (ea == NULL || eb == NULL)
165 return 0;
166 ka = GOST_KEY_get0_public_key(ea);
167 kb = GOST_KEY_get0_public_key(eb);
168 if (ka == NULL || kb == NULL)
169 return 0;
170 ret = (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea), ka, kb, NULL));
171 return ret;
172 }
173
174 static int
pkey_size_gost01(const EVP_PKEY * pk)175 pkey_size_gost01(const EVP_PKEY *pk)
176 {
177 if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
178 return 128;
179 return 64;
180 }
181
182 static int
pkey_bits_gost01(const EVP_PKEY * pk)183 pkey_bits_gost01(const EVP_PKEY *pk)
184 {
185 if (GOST_KEY_get_digest(pk->pkey.gost) == NID_id_tc26_gost3411_2012_512)
186 return 512;
187 return 256;
188 }
189
190 static int
pub_decode_gost01(EVP_PKEY * pk,X509_PUBKEY * pub)191 pub_decode_gost01(EVP_PKEY *pk, X509_PUBKEY *pub)
192 {
193 X509_ALGOR *palg = NULL;
194 const unsigned char *pubkey_buf = NULL;
195 const unsigned char *p;
196 ASN1_OBJECT *palgobj = NULL;
197 int pub_len;
198 BIGNUM *X, *Y;
199 ASN1_OCTET_STRING *octet = NULL;
200 int len;
201 int ret;
202 int ptype = V_ASN1_UNDEF;
203 ASN1_STRING *pval = NULL;
204
205 if (X509_PUBKEY_get0_param(&palgobj, &pubkey_buf, &pub_len, &palg, pub)
206 == 0)
207 return 0;
208 (void)EVP_PKEY_assign_GOST(pk, NULL);
209 X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
210 if (ptype != V_ASN1_SEQUENCE) {
211 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
212 return 0;
213 }
214 p = pval->data;
215 if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
216 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
217 return 0;
218 }
219
220 octet = d2i_ASN1_OCTET_STRING(NULL, &pubkey_buf, pub_len);
221 if (octet == NULL) {
222 GOSTerror(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 GOSTerror(ERR_R_EC_LIB);
235
236 BN_free(X);
237 BN_free(Y);
238
239 return ret;
240 }
241
242 static int
pub_encode_gost01(X509_PUBKEY * pub,const EVP_PKEY * pk)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 GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED);
270 goto err;
271 }
272
273 octet = ASN1_OCTET_STRING_new();
274 if (octet == NULL) {
275 GOSTerror(ERR_R_MALLOC_FAILURE);
276 goto err;
277 }
278
279 ret = ASN1_STRING_set(octet, NULL, 2 * key_size);
280 if (ret == 0) {
281 GOSTerror(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 GOSTerror(ERR_R_MALLOC_FAILURE);
291 goto err;
292 }
293
294 if (EC_POINT_get_affine_coordinates(GOST_KEY_get0_group(ec),
295 pub_key, X, Y, NULL) == 0) {
296 GOSTerror(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
param_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)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
pub_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)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 GOSTerror(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(group, pubkey, X, Y, 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 if (BIO_indent(out, indent + 3, 128) == 0)
369 goto err;
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
priv_print_gost01(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)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
priv_decode_gost01(EVP_PKEY * pk,const PKCS8_PRIV_KEY_INFO * p8inf)404 priv_decode_gost01(EVP_PKEY *pk, const 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 const X509_ALGOR *palg = NULL;
411 const 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 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
419 return 0;
420 }
421 (void)EVP_PKEY_assign_GOST(pk, NULL);
422 X509_ALGOR_get0(NULL, &ptype, (const void **)&pval, palg);
423 if (ptype != V_ASN1_SEQUENCE) {
424 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
425 return 0;
426 }
427 p = pval->data;
428 if (decode_gost01_algor_params(pk, &p, pval->length) == 0) {
429 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT);
430 return 0;
431 }
432 p = pkey_buf;
433 if (V_ASN1_OCTET_STRING == *p) {
434 /* New format - Little endian octet string */
435 ASN1_OCTET_STRING *s =
436 d2i_ASN1_OCTET_STRING(NULL, &p, priv_len);
437
438 if (s == NULL) {
439 GOSTerror(EVP_R_DECODE_ERROR);
440 ASN1_STRING_free(s);
441 return 0;
442 }
443
444 pk_num = GOST_le2bn(s->data, s->length, NULL);
445 ASN1_STRING_free(s);
446 } else {
447 priv_key = d2i_ASN1_INTEGER(NULL, &p, priv_len);
448 if (priv_key == NULL)
449 return 0;
450 ret = ((pk_num = ASN1_INTEGER_to_BN(priv_key, NULL)) != NULL);
451 ASN1_INTEGER_free(priv_key);
452 if (ret == 0) {
453 GOSTerror(EVP_R_DECODE_ERROR);
454 return 0;
455 }
456 }
457
458 ec = pk->pkey.gost;
459 if (ec == NULL) {
460 ec = GOST_KEY_new();
461 if (ec == NULL) {
462 BN_free(pk_num);
463 return 0;
464 }
465 if (EVP_PKEY_assign_GOST(pk, ec) == 0) {
466 BN_free(pk_num);
467 GOST_KEY_free(ec);
468 return 0;
469 }
470 }
471 if (GOST_KEY_set_private_key(ec, pk_num) == 0) {
472 BN_free(pk_num);
473 return 0;
474 }
475 ret = 0;
476 if (EVP_PKEY_missing_parameters(pk) == 0)
477 ret = gost2001_compute_public(ec) != 0;
478 BN_free(pk_num);
479
480 return ret;
481 }
482
483 static int
priv_encode_gost01(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pk)484 priv_encode_gost01(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk)
485 {
486 ASN1_OBJECT *algobj =
487 OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk->pkey.gost)));
488 ASN1_STRING *params = encode_gost01_algor_params(pk);
489 unsigned char *priv_buf = NULL;
490 int priv_len;
491 ASN1_INTEGER *asn1key = NULL;
492
493 if (params == NULL)
494 return 0;
495
496 asn1key = BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk->pkey.gost),
497 NULL);
498 if (asn1key == NULL) {
499 ASN1_STRING_free(params);
500 return 0;
501 }
502 priv_len = i2d_ASN1_INTEGER(asn1key, &priv_buf);
503 ASN1_INTEGER_free(asn1key);
504 return PKCS8_pkey_set0(p8, algobj, 0, V_ASN1_SEQUENCE, params, priv_buf,
505 priv_len);
506 }
507
508 static int
param_encode_gost01(const EVP_PKEY * pkey,unsigned char ** pder)509 param_encode_gost01(const EVP_PKEY *pkey, unsigned char **pder)
510 {
511 ASN1_STRING *params = encode_gost01_algor_params(pkey);
512 int len;
513
514 if (params == NULL)
515 return 0;
516 len = params->length;
517 if (pder != NULL)
518 memcpy(*pder, params->data, params->length);
519 ASN1_STRING_free(params);
520 return len;
521 }
522
523 static int
param_decode_gost01(EVP_PKEY * pkey,const unsigned char ** pder,int derlen)524 param_decode_gost01(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
525 {
526 ASN1_OBJECT *obj = NULL;
527 int nid;
528 GOST_KEY *ec;
529 EC_GROUP *group;
530 int ret;
531
532 /* New format */
533 if ((V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) == **pder)
534 return decode_gost01_algor_params(pkey, pder, derlen);
535
536 /* Compatibility */
537 if (d2i_ASN1_OBJECT(&obj, pder, derlen) == NULL) {
538 GOSTerror(ERR_R_MALLOC_FAILURE);
539 return 0;
540 }
541 nid = OBJ_obj2nid(obj);
542 ASN1_OBJECT_free(obj);
543
544 ec = GOST_KEY_new();
545 if (ec == NULL) {
546 GOSTerror(ERR_R_MALLOC_FAILURE);
547 return 0;
548 }
549 group = EC_GROUP_new_by_curve_name(nid);
550 if (group == NULL) {
551 GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
552 GOST_KEY_free(ec);
553 return 0;
554 }
555
556 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
557 if (GOST_KEY_set_group(ec, group) == 0) {
558 GOSTerror(ERR_R_EC_LIB);
559 EC_GROUP_free(group);
560 GOST_KEY_free(ec);
561 return 0;
562 }
563 EC_GROUP_free(group);
564 if (GOST_KEY_set_digest(ec,
565 NID_id_GostR3411_94_CryptoProParamSet) == 0) {
566 GOSTerror(GOST_R_INVALID_DIGEST_TYPE);
567 GOST_KEY_free(ec);
568 return 0;
569 }
570 ret = EVP_PKEY_assign_GOST(pkey, ec);
571 if (ret == 0)
572 GOST_KEY_free(ec);
573 return ret;
574 }
575
576 static int
param_missing_gost01(const EVP_PKEY * pk)577 param_missing_gost01(const EVP_PKEY *pk)
578 {
579 const GOST_KEY *ec = pk->pkey.gost;
580
581 if (ec == NULL)
582 return 1;
583 if (GOST_KEY_get0_group(ec) == NULL)
584 return 1;
585 if (GOST_KEY_get_digest(ec) == NID_undef)
586 return 1;
587 return 0;
588 }
589
590 static int
param_copy_gost01(EVP_PKEY * to,const EVP_PKEY * from)591 param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from)
592 {
593 GOST_KEY *eto = to->pkey.gost;
594 const GOST_KEY *efrom = from->pkey.gost;
595 int ret = 1;
596
597 if (EVP_PKEY_base_id(from) != EVP_PKEY_base_id(to)) {
598 GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS);
599 return 0;
600 }
601 if (efrom == NULL) {
602 GOSTerror(GOST_R_KEY_PARAMETERS_MISSING);
603 return 0;
604 }
605 if (eto == NULL) {
606 eto = GOST_KEY_new();
607 if (eto == NULL) {
608 GOSTerror(ERR_R_MALLOC_FAILURE);
609 return 0;
610 }
611 if (EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto) == 0) {
612 GOST_KEY_free(eto);
613 return 0;
614 }
615 }
616 GOST_KEY_set_group(eto, GOST_KEY_get0_group(efrom));
617 GOST_KEY_set_digest(eto, GOST_KEY_get_digest(efrom));
618 if (GOST_KEY_get0_private_key(eto) != NULL)
619 ret = gost2001_compute_public(eto);
620
621 return ret;
622 }
623
624 static int
param_cmp_gost01(const EVP_PKEY * a,const EVP_PKEY * b)625 param_cmp_gost01(const EVP_PKEY *a, const EVP_PKEY *b)
626 {
627 if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a->pkey.gost)) !=
628 EC_GROUP_get_curve_name(GOST_KEY_get0_group(b->pkey.gost)))
629 return 0;
630
631 if (GOST_KEY_get_digest(a->pkey.gost) !=
632 GOST_KEY_get_digest(b->pkey.gost))
633 return 0;
634
635 return 1;
636 }
637
638 static int
pkey_ctrl_gost01(EVP_PKEY * pkey,int op,long arg1,void * arg2)639 pkey_ctrl_gost01(EVP_PKEY *pkey, int op, long arg1, void *arg2)
640 {
641 X509_ALGOR *alg1 = NULL, *alg2 = NULL, *alg3 = NULL;
642 int digest = GOST_KEY_get_digest(pkey->pkey.gost);
643
644 switch (op) {
645 case ASN1_PKEY_CTRL_PKCS7_SIGN:
646 if (arg1 == 0)
647 PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
648 break;
649
650 case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
651 if (arg1 == 0)
652 PKCS7_RECIP_INFO_get0_alg(arg2, &alg3);
653 break;
654 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
655 *(int *)arg2 = GostR3410_get_md_digest(digest);
656 return 2;
657
658 default:
659 return -2;
660 }
661
662 if (alg1)
663 X509_ALGOR_set0(alg1, OBJ_nid2obj(GostR3410_get_md_digest(digest)), V_ASN1_NULL, 0);
664 if (alg2)
665 X509_ALGOR_set0(alg2, OBJ_nid2obj(GostR3410_get_pk_digest(digest)), V_ASN1_NULL, 0);
666 if (alg3) {
667 ASN1_STRING *params = encode_gost01_algor_params(pkey);
668 if (params == NULL) {
669 return -1;
670 }
671 X509_ALGOR_set0(alg3,
672 OBJ_nid2obj(GostR3410_get_pk_digest(digest)),
673 V_ASN1_SEQUENCE, params);
674 }
675
676 return 1;
677 }
678
679 const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[] = {
680 {
681 .pkey_id = EVP_PKEY_GOSTR01,
682 .pkey_base_id = EVP_PKEY_GOSTR01,
683 .pkey_flags = ASN1_PKEY_SIGPARAM_NULL,
684
685 .pem_str = "GOST2001",
686 .info = "GOST R 34.10-2001",
687
688 .pkey_free = pkey_free_gost01,
689 .pkey_ctrl = pkey_ctrl_gost01,
690
691 .priv_decode = priv_decode_gost01,
692 .priv_encode = priv_encode_gost01,
693 .priv_print = priv_print_gost01,
694
695 .param_decode = param_decode_gost01,
696 .param_encode = param_encode_gost01,
697 .param_missing = param_missing_gost01,
698 .param_copy = param_copy_gost01,
699 .param_cmp = param_cmp_gost01,
700 .param_print = param_print_gost01,
701
702 .pub_decode = pub_decode_gost01,
703 .pub_encode = pub_encode_gost01,
704 .pub_cmp = pub_cmp_gost01,
705 .pub_print = pub_print_gost01,
706 .pkey_size = pkey_size_gost01,
707 .pkey_bits = pkey_bits_gost01,
708 },
709 {
710 .pkey_id = EVP_PKEY_GOSTR12_256,
711 .pkey_base_id = EVP_PKEY_GOSTR01,
712 .pkey_flags = ASN1_PKEY_ALIAS
713 },
714 {
715 .pkey_id = EVP_PKEY_GOSTR12_512,
716 .pkey_base_id = EVP_PKEY_GOSTR01,
717 .pkey_flags = ASN1_PKEY_ALIAS
718 },
719 };
720
721 #endif
722