1 /* $OpenBSD: gostr341001_ameth.c,v 1.15 2018/08/24 20:22:15 tb Exp $ */
3 * Copyright (c) 2014 Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
4 * Copyright (c) 2005-2006 Cryptocom LTD
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
32 * 6. Redistributions of any form whatsoever must retain the following
34 * "This product includes software developed by the OpenSSL Project
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
54 #include <openssl/opensslconf.h>
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>
65 #include "asn1_locl.h"
66 #include "gost_locl.h"
67 #include "gost_asn1.h"
70 pkey_free_gost01(EVP_PKEY
*key
)
72 GOST_KEY_free(key
->pkey
.gost
);
76 * Parses GOST algorithm parameters from X509_ALGOR and
77 * modifies pkey setting NID and parameters
80 decode_gost01_algor_params(EVP_PKEY
*pkey
, const unsigned char **p
, int len
)
82 int param_nid
= NID_undef
, digest_nid
= NID_undef
;
83 GOST_KEY_PARAMS
*gkp
= NULL
;
87 gkp
= d2i_GOST_KEY_PARAMS(NULL
, p
, len
);
89 GOSTerror(GOST_R_BAD_PKEY_PARAMETERS_FORMAT
);
92 param_nid
= OBJ_obj2nid(gkp
->key_params
);
93 digest_nid
= OBJ_obj2nid(gkp
->hash_params
);
94 GOST_KEY_PARAMS_free(gkp
);
101 if (EVP_PKEY_assign_GOST(pkey
, ec
) == 0)
105 group
= EC_GROUP_new_by_curve_name(param_nid
);
108 EC_GROUP_set_asn1_flag(group
, OPENSSL_EC_NAMED_CURVE
);
109 if (GOST_KEY_set_group(ec
, group
) == 0) {
110 EC_GROUP_free(group
);
113 EC_GROUP_free(group
);
114 if (GOST_KEY_set_digest(ec
, digest_nid
) == 0)
120 encode_gost01_algor_params(const EVP_PKEY
*key
)
122 ASN1_STRING
*params
= ASN1_STRING_new();
123 GOST_KEY_PARAMS
*gkp
= GOST_KEY_PARAMS_new();
124 int pkey_param_nid
= NID_undef
;
126 if (params
== NULL
|| gkp
== NULL
) {
127 GOSTerror(ERR_R_MALLOC_FAILURE
);
128 ASN1_STRING_free(params
);
134 EC_GROUP_get_curve_name(GOST_KEY_get0_group(key
->pkey
.gost
));
135 gkp
->key_params
= OBJ_nid2obj(pkey_param_nid
);
136 gkp
->hash_params
= OBJ_nid2obj(GOST_KEY_get_digest(key
->pkey
.gost
));
137 /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid); */
138 params
->length
= i2d_GOST_KEY_PARAMS(gkp
, ¶ms
->data
);
139 if (params
->length
<= 0) {
140 GOSTerror(ERR_R_MALLOC_FAILURE
);
141 ASN1_STRING_free(params
);
145 params
->type
= V_ASN1_SEQUENCE
;
147 GOST_KEY_PARAMS_free(gkp
);
152 pub_cmp_gost01(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
154 const GOST_KEY
*ea
= a
->pkey
.gost
;
155 const GOST_KEY
*eb
= b
->pkey
.gost
;
156 const EC_POINT
*ka
, *kb
;
159 if (ea
== NULL
|| eb
== NULL
)
161 ka
= GOST_KEY_get0_public_key(ea
);
162 kb
= GOST_KEY_get0_public_key(eb
);
163 if (ka
== NULL
|| kb
== NULL
)
165 ret
= (0 == EC_POINT_cmp(GOST_KEY_get0_group(ea
), ka
, kb
, NULL
));
170 pkey_size_gost01(const EVP_PKEY
*pk
)
172 if (GOST_KEY_get_digest(pk
->pkey
.gost
) == NID_id_tc26_gost3411_2012_512
)
178 pkey_bits_gost01(const EVP_PKEY
*pk
)
180 if (GOST_KEY_get_digest(pk
->pkey
.gost
) == NID_id_tc26_gost3411_2012_512
)
186 pub_decode_gost01(EVP_PKEY
*pk
, X509_PUBKEY
*pub
)
188 X509_ALGOR
*palg
= NULL
;
189 const unsigned char *pubkey_buf
= NULL
;
190 const unsigned char *p
;
191 ASN1_OBJECT
*palgobj
= NULL
;
194 ASN1_OCTET_STRING
*octet
= NULL
;
197 int ptype
= V_ASN1_UNDEF
;
198 ASN1_STRING
*pval
= NULL
;
200 if (X509_PUBKEY_get0_param(&palgobj
, &pubkey_buf
, &pub_len
, &palg
, pub
)
203 (void)EVP_PKEY_assign_GOST(pk
, NULL
);
204 X509_ALGOR_get0(NULL
, &ptype
, (const void **)&pval
, palg
);
205 if (ptype
!= V_ASN1_SEQUENCE
) {
206 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT
);
210 if (decode_gost01_algor_params(pk
, &p
, pval
->length
) == 0)
213 octet
= d2i_ASN1_OCTET_STRING(NULL
, &pubkey_buf
, pub_len
);
215 GOSTerror(ERR_R_MALLOC_FAILURE
);
218 len
= octet
->length
/ 2;
220 X
= GOST_le2bn(octet
->data
, len
, NULL
);
221 Y
= GOST_le2bn(octet
->data
+ len
, len
, NULL
);
223 ASN1_OCTET_STRING_free(octet
);
225 ret
= GOST_KEY_set_public_key_affine_coordinates(pk
->pkey
.gost
, X
, Y
);
227 GOSTerror(ERR_R_EC_LIB
);
236 pub_encode_gost01(X509_PUBKEY
*pub
, const EVP_PKEY
*pk
)
238 ASN1_OBJECT
*algobj
= NULL
;
239 ASN1_OCTET_STRING
*octet
= NULL
;
240 ASN1_STRING
*params
= NULL
;
242 unsigned char *buf
= NULL
, *sptr
;
243 int key_size
, ret
= 0;
244 const EC_POINT
*pub_key
;
245 BIGNUM
*X
= NULL
, *Y
= NULL
;
246 const GOST_KEY
*ec
= pk
->pkey
.gost
;
247 int ptype
= V_ASN1_UNDEF
;
249 algobj
= OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(ec
)));
250 if (pk
->save_parameters
) {
251 params
= encode_gost01_algor_params(pk
);
255 ptype
= V_ASN1_SEQUENCE
;
258 key_size
= GOST_KEY_get_size(ec
);
260 pub_key
= GOST_KEY_get0_public_key(ec
);
261 if (pub_key
== NULL
) {
262 GOSTerror(GOST_R_PUBLIC_KEY_UNDEFINED
);
266 octet
= ASN1_OCTET_STRING_new();
268 GOSTerror(ERR_R_MALLOC_FAILURE
);
272 ret
= ASN1_STRING_set(octet
, NULL
, 2 * key_size
);
274 GOSTerror(ERR_R_INTERNAL_ERROR
);
278 sptr
= ASN1_STRING_data(octet
);
282 if (X
== NULL
|| Y
== NULL
) {
283 GOSTerror(ERR_R_MALLOC_FAILURE
);
287 if (EC_POINT_get_affine_coordinates_GFp(GOST_KEY_get0_group(ec
),
288 pub_key
, X
, Y
, NULL
) == 0) {
289 GOSTerror(ERR_R_EC_LIB
);
293 GOST_bn2le(X
, sptr
, key_size
);
294 GOST_bn2le(Y
, sptr
+ key_size
, key_size
);
299 ret
= i2d_ASN1_OCTET_STRING(octet
, &buf
);
300 ASN1_BIT_STRING_free(octet
);
304 return X509_PUBKEY_set0_param(pub
, algobj
, ptype
, pval
, buf
, ret
);
309 ASN1_BIT_STRING_free(octet
);
310 ASN1_STRING_free(params
);
315 param_print_gost01(BIO
*out
, const EVP_PKEY
*pkey
, int indent
, ASN1_PCTX
*pctx
)
318 EC_GROUP_get_curve_name(GOST_KEY_get0_group(pkey
->pkey
.gost
));
320 if (BIO_indent(out
, indent
, 128) == 0)
322 BIO_printf(out
, "Parameter set: %s\n", OBJ_nid2ln(param_nid
));
323 if (BIO_indent(out
, indent
, 128) == 0)
325 BIO_printf(out
, "Digest Algorithm: %s\n",
326 OBJ_nid2ln(GOST_KEY_get_digest(pkey
->pkey
.gost
)));
331 pub_print_gost01(BIO
*out
, const EVP_PKEY
*pkey
, int indent
, ASN1_PCTX
*pctx
)
333 BN_CTX
*ctx
= BN_CTX_new();
335 const EC_POINT
*pubkey
;
336 const EC_GROUP
*group
;
339 GOSTerror(ERR_R_MALLOC_FAILURE
);
343 if ((X
= BN_CTX_get(ctx
)) == NULL
)
345 if ((Y
= BN_CTX_get(ctx
)) == NULL
)
347 pubkey
= GOST_KEY_get0_public_key(pkey
->pkey
.gost
);
348 group
= GOST_KEY_get0_group(pkey
->pkey
.gost
);
349 if (EC_POINT_get_affine_coordinates_GFp(group
, pubkey
, X
, Y
,
351 GOSTerror(ERR_R_EC_LIB
);
354 if (BIO_indent(out
, indent
, 128) == 0)
356 BIO_printf(out
, "Public key:\n");
357 if (BIO_indent(out
, indent
+ 3, 128) == 0)
359 BIO_printf(out
, "X:");
361 BIO_printf(out
, "\n");
362 BIO_indent(out
, indent
+ 3, 128);
363 BIO_printf(out
, "Y:");
365 BIO_printf(out
, "\n");
370 return param_print_gost01(out
, pkey
, indent
, pctx
);
379 priv_print_gost01(BIO
*out
, const EVP_PKEY
*pkey
, int indent
, ASN1_PCTX
*pctx
)
383 if (BIO_indent(out
, indent
, 128) == 0)
385 BIO_printf(out
, "Private key: ");
386 key
= GOST_KEY_get0_private_key(pkey
->pkey
.gost
);
388 BIO_printf(out
, "<undefined)");
391 BIO_printf(out
, "\n");
393 return pub_print_gost01(out
, pkey
, indent
, pctx
);
397 priv_decode_gost01(EVP_PKEY
*pk
, const PKCS8_PRIV_KEY_INFO
*p8inf
)
399 const unsigned char *pkey_buf
= NULL
, *p
= NULL
;
401 BIGNUM
*pk_num
= NULL
;
403 const X509_ALGOR
*palg
= NULL
;
404 const ASN1_OBJECT
*palg_obj
= NULL
;
405 ASN1_INTEGER
*priv_key
= NULL
;
407 int ptype
= V_ASN1_UNDEF
;
408 ASN1_STRING
*pval
= NULL
;
410 if (PKCS8_pkey_get0(&palg_obj
, &pkey_buf
, &priv_len
, &palg
, p8inf
) == 0)
412 (void)EVP_PKEY_assign_GOST(pk
, NULL
);
413 X509_ALGOR_get0(NULL
, &ptype
, (const void **)&pval
, palg
);
414 if (ptype
!= V_ASN1_SEQUENCE
) {
415 GOSTerror(GOST_R_BAD_KEY_PARAMETERS_FORMAT
);
419 if (decode_gost01_algor_params(pk
, &p
, pval
->length
) == 0)
422 if (V_ASN1_OCTET_STRING
== *p
) {
423 /* New format - Little endian octet string */
424 ASN1_OCTET_STRING
*s
=
425 d2i_ASN1_OCTET_STRING(NULL
, &p
, priv_len
);
428 GOSTerror(EVP_R_DECODE_ERROR
);
433 pk_num
= GOST_le2bn(s
->data
, s
->length
, NULL
);
436 priv_key
= d2i_ASN1_INTEGER(NULL
, &p
, priv_len
);
437 if (priv_key
== NULL
)
439 ret
= ((pk_num
= ASN1_INTEGER_to_BN(priv_key
, NULL
)) != NULL
);
440 ASN1_INTEGER_free(priv_key
);
442 GOSTerror(EVP_R_DECODE_ERROR
);
454 if (EVP_PKEY_assign_GOST(pk
, ec
) == 0) {
460 if (GOST_KEY_set_private_key(ec
, pk_num
) == 0) {
465 if (EVP_PKEY_missing_parameters(pk
) == 0)
466 ret
= gost2001_compute_public(ec
) != 0;
473 priv_encode_gost01(PKCS8_PRIV_KEY_INFO
*p8
, const EVP_PKEY
*pk
)
475 ASN1_OBJECT
*algobj
=
476 OBJ_nid2obj(GostR3410_get_pk_digest(GOST_KEY_get_digest(pk
->pkey
.gost
)));
477 ASN1_STRING
*params
= encode_gost01_algor_params(pk
);
478 unsigned char *priv_buf
= NULL
;
480 ASN1_INTEGER
*asn1key
= NULL
;
485 asn1key
= BN_to_ASN1_INTEGER(GOST_KEY_get0_private_key(pk
->pkey
.gost
),
487 if (asn1key
== NULL
) {
488 ASN1_STRING_free(params
);
491 priv_len
= i2d_ASN1_INTEGER(asn1key
, &priv_buf
);
492 ASN1_INTEGER_free(asn1key
);
493 return PKCS8_pkey_set0(p8
, algobj
, 0, V_ASN1_SEQUENCE
, params
, priv_buf
,
498 param_encode_gost01(const EVP_PKEY
*pkey
, unsigned char **pder
)
500 ASN1_STRING
*params
= encode_gost01_algor_params(pkey
);
505 len
= params
->length
;
507 memcpy(*pder
, params
->data
, params
->length
);
508 ASN1_STRING_free(params
);
513 param_decode_gost01(EVP_PKEY
*pkey
, const unsigned char **pder
, int derlen
)
515 ASN1_OBJECT
*obj
= NULL
;
522 if ((V_ASN1_SEQUENCE
| V_ASN1_CONSTRUCTED
) == **pder
)
523 return decode_gost01_algor_params(pkey
, pder
, derlen
);
526 if (d2i_ASN1_OBJECT(&obj
, pder
, derlen
) == NULL
) {
527 GOSTerror(ERR_R_MALLOC_FAILURE
);
530 nid
= OBJ_obj2nid(obj
);
531 ASN1_OBJECT_free(obj
);
535 GOSTerror(ERR_R_MALLOC_FAILURE
);
538 group
= EC_GROUP_new_by_curve_name(nid
);
540 GOSTerror(EC_R_EC_GROUP_NEW_BY_NAME_FAILURE
);
545 EC_GROUP_set_asn1_flag(group
, OPENSSL_EC_NAMED_CURVE
);
546 if (GOST_KEY_set_group(ec
, group
) == 0) {
547 GOSTerror(ERR_R_EC_LIB
);
548 EC_GROUP_free(group
);
552 EC_GROUP_free(group
);
553 if (GOST_KEY_set_digest(ec
,
554 NID_id_GostR3411_94_CryptoProParamSet
) == 0) {
555 GOSTerror(GOST_R_INVALID_DIGEST_TYPE
);
559 ret
= EVP_PKEY_assign_GOST(pkey
, ec
);
566 param_missing_gost01(const EVP_PKEY
*pk
)
568 const GOST_KEY
*ec
= pk
->pkey
.gost
;
572 if (GOST_KEY_get0_group(ec
) == NULL
)
574 if (GOST_KEY_get_digest(ec
) == NID_undef
)
580 param_copy_gost01(EVP_PKEY
*to
, const EVP_PKEY
*from
)
582 GOST_KEY
*eto
= to
->pkey
.gost
;
583 const GOST_KEY
*efrom
= from
->pkey
.gost
;
586 if (EVP_PKEY_base_id(from
) != EVP_PKEY_base_id(to
)) {
587 GOSTerror(GOST_R_INCOMPATIBLE_ALGORITHMS
);
591 GOSTerror(GOST_R_KEY_PARAMETERS_MISSING
);
595 eto
= GOST_KEY_new();
597 GOSTerror(ERR_R_MALLOC_FAILURE
);
600 if (EVP_PKEY_assign(to
, EVP_PKEY_base_id(from
), eto
) == 0) {
605 GOST_KEY_set_group(eto
, GOST_KEY_get0_group(efrom
));
606 GOST_KEY_set_digest(eto
, GOST_KEY_get_digest(efrom
));
607 if (GOST_KEY_get0_private_key(eto
) != NULL
)
608 ret
= gost2001_compute_public(eto
);
614 param_cmp_gost01(const EVP_PKEY
*a
, const EVP_PKEY
*b
)
616 if (EC_GROUP_get_curve_name(GOST_KEY_get0_group(a
->pkey
.gost
)) !=
617 EC_GROUP_get_curve_name(GOST_KEY_get0_group(b
->pkey
.gost
)))
620 if (GOST_KEY_get_digest(a
->pkey
.gost
) !=
621 GOST_KEY_get_digest(b
->pkey
.gost
))
628 pkey_ctrl_gost01(EVP_PKEY
*pkey
, int op
, long arg1
, void *arg2
)
630 X509_ALGOR
*alg1
= NULL
, *alg2
= NULL
, *alg3
= NULL
;
631 int digest
= GOST_KEY_get_digest(pkey
->pkey
.gost
);
634 case ASN1_PKEY_CTRL_PKCS7_SIGN
:
636 PKCS7_SIGNER_INFO_get0_algs(arg2
, NULL
, &alg1
, &alg2
);
639 case ASN1_PKEY_CTRL_PKCS7_ENCRYPT
:
641 PKCS7_RECIP_INFO_get0_alg(arg2
, &alg3
);
643 case ASN1_PKEY_CTRL_DEFAULT_MD_NID
:
644 *(int *)arg2
= GostR3410_get_md_digest(digest
);
652 X509_ALGOR_set0(alg1
, OBJ_nid2obj(GostR3410_get_md_digest(digest
)), V_ASN1_NULL
, 0);
654 X509_ALGOR_set0(alg2
, OBJ_nid2obj(GostR3410_get_pk_digest(digest
)), V_ASN1_NULL
, 0);
656 ASN1_STRING
*params
= encode_gost01_algor_params(pkey
);
657 if (params
== NULL
) {
660 X509_ALGOR_set0(alg3
,
661 OBJ_nid2obj(GostR3410_get_pk_digest(digest
)),
662 V_ASN1_SEQUENCE
, params
);
668 const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths
[] = {
670 .pkey_id
= EVP_PKEY_GOSTR01
,
671 .pkey_base_id
= EVP_PKEY_GOSTR01
,
672 .pkey_flags
= ASN1_PKEY_SIGPARAM_NULL
,
674 .pem_str
= "GOST2001",
675 .info
= "GOST R 34.10-2001",
677 .pkey_free
= pkey_free_gost01
,
678 .pkey_ctrl
= pkey_ctrl_gost01
,
680 .priv_decode
= priv_decode_gost01
,
681 .priv_encode
= priv_encode_gost01
,
682 .priv_print
= priv_print_gost01
,
684 .param_decode
= param_decode_gost01
,
685 .param_encode
= param_encode_gost01
,
686 .param_missing
= param_missing_gost01
,
687 .param_copy
= param_copy_gost01
,
688 .param_cmp
= param_cmp_gost01
,
689 .param_print
= param_print_gost01
,
691 .pub_decode
= pub_decode_gost01
,
692 .pub_encode
= pub_encode_gost01
,
693 .pub_cmp
= pub_cmp_gost01
,
694 .pub_print
= pub_print_gost01
,
695 .pkey_size
= pkey_size_gost01
,
696 .pkey_bits
= pkey_bits_gost01
,
699 .pkey_id
= EVP_PKEY_GOSTR12_256
,
700 .pkey_base_id
= EVP_PKEY_GOSTR01
,
701 .pkey_flags
= ASN1_PKEY_ALIAS
704 .pkey_id
= EVP_PKEY_GOSTR12_512
,
705 .pkey_base_id
= EVP_PKEY_GOSTR01
,
706 .pkey_flags
= ASN1_PKEY_ALIAS