1 /**********************************************************************
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
6 * Implementation of RFC 4357 (GOST R 34.10) Publick key method *
8 * Requires OpenSSL 0.9.9 for compilation *
9 **********************************************************************/
10 #include <openssl/evp.h>
11 #include <openssl/objects.h>
12 #include <openssl/ec.h>
13 #include <openssl/x509v3.h> /* For string_to_hex */
17 #include "gost_params.h"
19 #include "e_gost_err.h"
20 /* -----init, cleanup, copy - uniform for all algs ---------------*/
21 /* Allocates new gost_pmeth_data structure and assigns it as data */
22 static int pkey_gost_init(EVP_PKEY_CTX
*ctx
)
24 struct gost_pmeth_data
*data
;
25 EVP_PKEY
*pkey
= EVP_PKEY_CTX_get0_pkey(ctx
);
26 data
= OPENSSL_malloc(sizeof(struct gost_pmeth_data
));
29 memset(data
, 0, sizeof(struct gost_pmeth_data
));
30 if (pkey
&& EVP_PKEY_get0(pkey
)) {
31 switch (EVP_PKEY_base_id(pkey
)) {
32 case NID_id_GostR3410_94
:
33 data
->sign_param_nid
= gost94_nid_by_params(EVP_PKEY_get0(pkey
));
35 case NID_id_GostR3410_2001
:
36 data
->sign_param_nid
=
37 EC_GROUP_get_curve_name(EC_KEY_get0_group
38 (EVP_PKEY_get0((EVP_PKEY
*)pkey
)));
44 EVP_PKEY_CTX_set_data(ctx
, data
);
48 /* Copies contents of gost_pmeth_data structure */
49 static int pkey_gost_copy(EVP_PKEY_CTX
*dst
, EVP_PKEY_CTX
*src
)
51 struct gost_pmeth_data
*dst_data
, *src_data
;
52 if (!pkey_gost_init(dst
)) {
55 src_data
= EVP_PKEY_CTX_get_data(src
);
56 dst_data
= EVP_PKEY_CTX_get_data(dst
);
57 *dst_data
= *src_data
;
58 if (src_data
->shared_ukm
) {
59 dst_data
->shared_ukm
= NULL
;
64 /* Frees up gost_pmeth_data structure */
65 static void pkey_gost_cleanup(EVP_PKEY_CTX
*ctx
)
67 struct gost_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
69 OPENSSL_free(data
->shared_ukm
);
73 /* --------------------- control functions ------------------------------*/
74 static int pkey_gost_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
76 struct gost_pmeth_data
*pctx
=
77 (struct gost_pmeth_data
*)EVP_PKEY_CTX_get_data(ctx
);
79 case EVP_PKEY_CTRL_MD
:
81 if (EVP_MD_type((const EVP_MD
*)p2
) != NID_id_GostR3411_94
) {
82 GOSTerr(GOST_F_PKEY_GOST_CTRL
, GOST_R_INVALID_DIGEST_TYPE
);
85 pctx
->md
= (EVP_MD
*)p2
;
90 case EVP_PKEY_CTRL_PKCS7_ENCRYPT
:
91 case EVP_PKEY_CTRL_PKCS7_DECRYPT
:
92 case EVP_PKEY_CTRL_PKCS7_SIGN
:
93 case EVP_PKEY_CTRL_DIGESTINIT
:
94 #ifndef OPENSSL_NO_CMS
95 case EVP_PKEY_CTRL_CMS_ENCRYPT
:
96 case EVP_PKEY_CTRL_CMS_DECRYPT
:
97 case EVP_PKEY_CTRL_CMS_SIGN
:
101 case EVP_PKEY_CTRL_GOST_PARAMSET
:
102 pctx
->sign_param_nid
= (int)p1
;
104 case EVP_PKEY_CTRL_SET_IV
:
105 pctx
->shared_ukm
= OPENSSL_malloc((int)p1
);
106 memcpy(pctx
->shared_ukm
, p2
, (int)p1
);
108 case EVP_PKEY_CTRL_PEER_KEY
:
109 if (p1
== 0 || p1
== 1) /* call from EVP_PKEY_derive_set_peer */
111 if (p1
== 2) /* TLS: peer key used? */
112 return pctx
->peer_key_used
;
113 if (p1
== 3) /* TLS: peer key used! */
114 return (pctx
->peer_key_used
= 1);
120 static int pkey_gost_ctrl94_str(EVP_PKEY_CTX
*ctx
,
121 const char *type
, const char *value
)
124 if (!strcmp(type
, param_ctrl_string
)) {
128 if (strlen(value
) == 1) {
129 switch (toupper((unsigned char)value
[0])) {
131 param_nid
= NID_id_GostR3410_94_CryptoPro_A_ParamSet
;
134 param_nid
= NID_id_GostR3410_94_CryptoPro_B_ParamSet
;
137 param_nid
= NID_id_GostR3410_94_CryptoPro_C_ParamSet
;
140 param_nid
= NID_id_GostR3410_94_CryptoPro_D_ParamSet
;
146 } else if ((strlen(value
) == 2)
147 && (toupper((unsigned char)value
[0]) == 'X')) {
148 switch (toupper((unsigned char)value
[1])) {
150 param_nid
= NID_id_GostR3410_94_CryptoPro_XchA_ParamSet
;
153 param_nid
= NID_id_GostR3410_94_CryptoPro_XchB_ParamSet
;
156 param_nid
= NID_id_GostR3410_94_CryptoPro_XchC_ParamSet
;
163 R3410_params
*p
= R3410_paramset
;
164 param_nid
= OBJ_txt2nid(value
);
165 if (param_nid
== NID_undef
) {
168 for (; p
->nid
!= NID_undef
; p
++) {
169 if (p
->nid
== param_nid
)
172 if (p
->nid
== NID_undef
) {
173 GOSTerr(GOST_F_PKEY_GOST_CTRL94_STR
, GOST_R_INVALID_PARAMSET
);
178 return pkey_gost_ctrl(ctx
, EVP_PKEY_CTRL_GOST_PARAMSET
,
184 static int pkey_gost_ctrl01_str(EVP_PKEY_CTX
*ctx
,
185 const char *type
, const char *value
)
188 if (!strcmp(type
, param_ctrl_string
)) {
192 if (strlen(value
) == 1) {
193 switch (toupper((unsigned char)value
[0])) {
195 param_nid
= NID_id_GostR3410_2001_CryptoPro_A_ParamSet
;
198 param_nid
= NID_id_GostR3410_2001_CryptoPro_B_ParamSet
;
201 param_nid
= NID_id_GostR3410_2001_CryptoPro_C_ParamSet
;
204 param_nid
= NID_id_GostR3410_2001_TestParamSet
;
210 } else if ((strlen(value
) == 2)
211 && (toupper((unsigned char)value
[0]) == 'X')) {
212 switch (toupper((unsigned char)value
[1])) {
214 param_nid
= NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet
;
217 param_nid
= NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet
;
224 R3410_2001_params
*p
= R3410_2001_paramset
;
225 param_nid
= OBJ_txt2nid(value
);
226 if (param_nid
== NID_undef
) {
229 for (; p
->nid
!= NID_undef
; p
++) {
230 if (p
->nid
== param_nid
)
233 if (p
->nid
== NID_undef
) {
234 GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR
, GOST_R_INVALID_PARAMSET
);
239 return pkey_gost_ctrl(ctx
, EVP_PKEY_CTRL_GOST_PARAMSET
,
245 /* --------------------- key generation --------------------------------*/
247 static int pkey_gost_paramgen_init(EVP_PKEY_CTX
*ctx
)
252 static int pkey_gost94_paramgen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
254 struct gost_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
256 if (data
->sign_param_nid
== NID_undef
) {
257 GOSTerr(GOST_F_PKEY_GOST94_PARAMGEN
, GOST_R_NO_PARAMETERS_SET
);
261 if (!fill_GOST94_params(dsa
, data
->sign_param_nid
)) {
265 EVP_PKEY_assign(pkey
, NID_id_GostR3410_94
, dsa
);
269 static int pkey_gost01_paramgen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
271 struct gost_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
274 if (data
->sign_param_nid
== NID_undef
) {
275 GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN
, GOST_R_NO_PARAMETERS_SET
);
280 if (!fill_GOST2001_params(ec
, data
->sign_param_nid
)) {
284 EVP_PKEY_assign(pkey
, NID_id_GostR3410_2001
, ec
);
288 /* Generates Gost_R3410_94_cp key */
289 static int pkey_gost94cp_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
292 if (!pkey_gost94_paramgen(ctx
, pkey
))
294 dsa
= EVP_PKEY_get0(pkey
);
295 gost_sign_keygen(dsa
);
299 /* Generates GOST_R3410 2001 key and assigns it using specified type */
300 static int pkey_gost01cp_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
303 if (!pkey_gost01_paramgen(ctx
, pkey
))
305 ec
= EVP_PKEY_get0(pkey
);
310 /* ----------- sign callbacks --------------------------------------*/
312 static int pkey_gost94_cp_sign(EVP_PKEY_CTX
*ctx
, unsigned char *sig
,
313 size_t *siglen
, const unsigned char *tbs
,
316 DSA_SIG
*unpacked_sig
= NULL
;
317 EVP_PKEY
*pkey
= EVP_PKEY_CTX_get0_pkey(ctx
);
321 *siglen
= 64; /* better to check size of pkey->pkey.dsa-q */
324 unpacked_sig
= gost_do_sign(tbs
, tbs_len
, EVP_PKEY_get0(pkey
));
328 return pack_sign_cp(unpacked_sig
, 32, sig
, siglen
);
331 static int pkey_gost01_cp_sign(EVP_PKEY_CTX
*ctx
, unsigned char *sig
,
332 size_t *siglen
, const unsigned char *tbs
,
335 DSA_SIG
*unpacked_sig
= NULL
;
336 EVP_PKEY
*pkey
= EVP_PKEY_CTX_get0_pkey(ctx
);
340 *siglen
= 64; /* better to check size of curve order */
343 unpacked_sig
= gost2001_do_sign(tbs
, tbs_len
, EVP_PKEY_get0(pkey
));
347 return pack_sign_cp(unpacked_sig
, 32, sig
, siglen
);
350 /* ------------------- verify callbacks ---------------------------*/
352 static int pkey_gost94_cp_verify(EVP_PKEY_CTX
*ctx
, const unsigned char *sig
,
353 size_t siglen
, const unsigned char *tbs
,
357 EVP_PKEY
*pub_key
= EVP_PKEY_CTX_get0_pkey(ctx
);
358 DSA_SIG
*s
= unpack_cp_signature(sig
, siglen
);
362 ok
= gost_do_verify(tbs
, tbs_len
, s
, EVP_PKEY_get0(pub_key
));
367 static int pkey_gost01_cp_verify(EVP_PKEY_CTX
*ctx
, const unsigned char *sig
,
368 size_t siglen
, const unsigned char *tbs
,
372 EVP_PKEY
*pub_key
= EVP_PKEY_CTX_get0_pkey(ctx
);
373 DSA_SIG
*s
= unpack_cp_signature(sig
, siglen
);
377 fprintf(stderr
, "R=");
378 BN_print_fp(stderr
, s
->r
);
379 fprintf(stderr
, "\nS=");
380 BN_print_fp(stderr
, s
->s
);
381 fprintf(stderr
, "\n");
384 ok
= gost2001_do_verify(tbs
, tbs_len
, s
, EVP_PKEY_get0(pub_key
));
389 /* ------------- encrypt init -------------------------------------*/
390 /* Generates ephermeral key */
391 static int pkey_gost_encrypt_init(EVP_PKEY_CTX
*ctx
)
396 /* --------------- Derive init ------------------------------------*/
397 static int pkey_gost_derive_init(EVP_PKEY_CTX
*ctx
)
402 /* -------- PKEY_METHOD for GOST MAC algorithm --------------------*/
403 static int pkey_gost_mac_init(EVP_PKEY_CTX
*ctx
)
405 struct gost_mac_pmeth_data
*data
;
406 data
= OPENSSL_malloc(sizeof(struct gost_mac_pmeth_data
));
409 memset(data
, 0, sizeof(struct gost_mac_pmeth_data
));
410 EVP_PKEY_CTX_set_data(ctx
, data
);
414 static void pkey_gost_mac_cleanup(EVP_PKEY_CTX
*ctx
)
416 struct gost_mac_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
420 static int pkey_gost_mac_copy(EVP_PKEY_CTX
*dst
, EVP_PKEY_CTX
*src
)
422 struct gost_mac_pmeth_data
*dst_data
, *src_data
;
423 if (!pkey_gost_mac_init(dst
)) {
426 src_data
= EVP_PKEY_CTX_get_data(src
);
427 dst_data
= EVP_PKEY_CTX_get_data(dst
);
428 *dst_data
= *src_data
;
432 static int pkey_gost_mac_ctrl(EVP_PKEY_CTX
*ctx
, int type
, int p1
, void *p2
)
434 struct gost_mac_pmeth_data
*data
=
435 (struct gost_mac_pmeth_data
*)EVP_PKEY_CTX_get_data(ctx
);
438 case EVP_PKEY_CTRL_MD
:
440 if (EVP_MD_type((const EVP_MD
*)p2
) != NID_id_Gost28147_89_MAC
) {
441 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL
,
442 GOST_R_INVALID_DIGEST_TYPE
);
445 data
->md
= (EVP_MD
*)p2
;
450 case EVP_PKEY_CTRL_PKCS7_ENCRYPT
:
451 case EVP_PKEY_CTRL_PKCS7_DECRYPT
:
452 case EVP_PKEY_CTRL_PKCS7_SIGN
:
454 case EVP_PKEY_CTRL_SET_MAC_KEY
:
456 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL
, GOST_R_INVALID_MAC_KEY_LENGTH
);
460 memcpy(data
->key
, p2
, 32);
463 case EVP_PKEY_CTRL_DIGESTINIT
:
465 EVP_MD_CTX
*mctx
= p2
;
467 if (!data
->key_set
) {
468 EVP_PKEY
*pkey
= EVP_PKEY_CTX_get0_pkey(ctx
);
470 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL
,
471 GOST_R_MAC_KEY_NOT_SET
);
474 key
= EVP_PKEY_get0(pkey
);
476 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL
,
477 GOST_R_MAC_KEY_NOT_SET
);
483 return mctx
->digest
->md_ctrl(mctx
, EVP_MD_CTRL_SET_KEY
, 32, key
);
489 static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX
*ctx
,
490 const char *type
, const char *value
)
492 if (!strcmp(type
, key_ctrl_string
)) {
493 if (strlen(value
) != 32) {
494 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR
,
495 GOST_R_INVALID_MAC_KEY_LENGTH
);
498 return pkey_gost_mac_ctrl(ctx
, EVP_PKEY_CTRL_SET_MAC_KEY
,
501 if (!strcmp(type
, hexkey_ctrl_string
)) {
504 unsigned char *keybuf
= string_to_hex(value
, &keylen
);
506 GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR
,
507 GOST_R_INVALID_MAC_KEY_LENGTH
);
508 OPENSSL_free(keybuf
);
511 ret
= pkey_gost_mac_ctrl(ctx
, EVP_PKEY_CTRL_SET_MAC_KEY
, 32, keybuf
);
512 OPENSSL_free(keybuf
);
519 static int pkey_gost_mac_keygen(EVP_PKEY_CTX
*ctx
, EVP_PKEY
*pkey
)
521 struct gost_mac_pmeth_data
*data
= EVP_PKEY_CTX_get_data(ctx
);
522 unsigned char *keydata
;
523 if (!data
->key_set
) {
524 GOSTerr(GOST_F_PKEY_GOST_MAC_KEYGEN
, GOST_R_MAC_KEY_NOT_SET
);
527 keydata
= OPENSSL_malloc(32);
528 memcpy(keydata
, data
->key
, 32);
529 EVP_PKEY_assign(pkey
, NID_id_Gost28147_89_MAC
, keydata
);
533 static int pkey_gost_mac_signctx_init(EVP_PKEY_CTX
*ctx
, EVP_MD_CTX
*mctx
)
538 static int pkey_gost_mac_signctx(EVP_PKEY_CTX
*ctx
, unsigned char *sig
,
539 size_t *siglen
, EVP_MD_CTX
*mctx
)
541 unsigned int tmpsiglen
= *siglen
; /* for platforms where
542 * sizeof(int)!=sizeof(size_t) */
548 ret
= EVP_DigestFinal_ex(mctx
, sig
, &tmpsiglen
);
553 /* ----------------------------------------------------------------*/
554 int register_pmeth_gost(int id
, EVP_PKEY_METHOD
**pmeth
, int flags
)
556 *pmeth
= EVP_PKEY_meth_new(id
, flags
);
561 case NID_id_GostR3410_94
:
562 EVP_PKEY_meth_set_ctrl(*pmeth
, pkey_gost_ctrl
, pkey_gost_ctrl94_str
);
563 EVP_PKEY_meth_set_keygen(*pmeth
, NULL
, pkey_gost94cp_keygen
);
564 EVP_PKEY_meth_set_sign(*pmeth
, NULL
, pkey_gost94_cp_sign
);
565 EVP_PKEY_meth_set_verify(*pmeth
, NULL
, pkey_gost94_cp_verify
);
566 EVP_PKEY_meth_set_encrypt(*pmeth
,
567 pkey_gost_encrypt_init
,
568 pkey_GOST94cp_encrypt
);
569 EVP_PKEY_meth_set_decrypt(*pmeth
, NULL
, pkey_GOST94cp_decrypt
);
570 EVP_PKEY_meth_set_derive(*pmeth
,
571 pkey_gost_derive_init
, pkey_gost94_derive
);
572 EVP_PKEY_meth_set_paramgen(*pmeth
, pkey_gost_paramgen_init
,
573 pkey_gost94_paramgen
);
575 case NID_id_GostR3410_2001
:
576 EVP_PKEY_meth_set_ctrl(*pmeth
, pkey_gost_ctrl
, pkey_gost_ctrl01_str
);
577 EVP_PKEY_meth_set_sign(*pmeth
, NULL
, pkey_gost01_cp_sign
);
578 EVP_PKEY_meth_set_verify(*pmeth
, NULL
, pkey_gost01_cp_verify
);
580 EVP_PKEY_meth_set_keygen(*pmeth
, NULL
, pkey_gost01cp_keygen
);
582 EVP_PKEY_meth_set_encrypt(*pmeth
,
583 pkey_gost_encrypt_init
,
584 pkey_GOST01cp_encrypt
);
585 EVP_PKEY_meth_set_decrypt(*pmeth
, NULL
, pkey_GOST01cp_decrypt
);
586 EVP_PKEY_meth_set_derive(*pmeth
,
587 pkey_gost_derive_init
, pkey_gost2001_derive
);
588 EVP_PKEY_meth_set_paramgen(*pmeth
, pkey_gost_paramgen_init
,
589 pkey_gost01_paramgen
);
591 case NID_id_Gost28147_89_MAC
:
592 EVP_PKEY_meth_set_ctrl(*pmeth
, pkey_gost_mac_ctrl
,
593 pkey_gost_mac_ctrl_str
);
594 EVP_PKEY_meth_set_signctx(*pmeth
, pkey_gost_mac_signctx_init
,
595 pkey_gost_mac_signctx
);
596 EVP_PKEY_meth_set_keygen(*pmeth
, NULL
, pkey_gost_mac_keygen
);
597 EVP_PKEY_meth_set_init(*pmeth
, pkey_gost_mac_init
);
598 EVP_PKEY_meth_set_cleanup(*pmeth
, pkey_gost_mac_cleanup
);
599 EVP_PKEY_meth_set_copy(*pmeth
, pkey_gost_mac_copy
);
601 default: /* Unsupported method */
604 EVP_PKEY_meth_set_init(*pmeth
, pkey_gost_init
);
605 EVP_PKEY_meth_set_cleanup(*pmeth
, pkey_gost_cleanup
);
607 EVP_PKEY_meth_set_copy(*pmeth
, pkey_gost_copy
);
609 * FIXME derive etc...