[openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Rich Salz via RT
This is a second patch to add new Russian standard GOST algorithms.

Needs GOST 34.11-2012 hash implementation listed in RT #3311.

See also both patches required in a pull request on github:
https://github.com/openssl/openssl/pull/75

No test cases added, as there are none present in ccgost nor the format
of such is apparent.
However generated certificates were tested against CryptoPro CSP 4.0 and
vise-versa.

Some examples of usage:

dmitry@linux64 ~/openssl/apps $ ./openssl req -engine gost -keyout
new.pem -newkey gost2012-512 -pkeyopt paramset:B -batch  > new.req
engine "gost" set.
Generating a 2048 bit GOST2012-512 private key
writing new private key to 'new.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
dmitry@linux64 ~/openssl/apps $ ./openssl x509 -engine gost -signkey
new.pem -req < new.req
engine "gost" set.
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
Enter pass phrase for new.pem:
-----BEGIN CERTIFICATE-----
MIICCjCCAXQCCQDa+tA+pJiE/DAMBggqhQMHAQEDAwUAMEUxCzAJBgNVBAYTAkFV
MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz
IFB0eSBMdGQwHhcNMTQwNDIzMTMzMzIzWhcNMTQwNTIzMTMzMzIzWjBFMQswCQYD
VQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQg
V2lkZ2l0cyBQdHkgTHRkMIGqMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAgYIKoUD
BwEBAgMDgYQABIGAxmt61J1wPiggpm21ILxGboDoMekKHo+9ZD+uhlCIRgNFnIZ9
FBjPyUGvMKPwicE4QPyouId4+pAzf7W3gxP9SQtIIJ9cEKUyHwaF1fU8RgQ4P3JF
qzVo5O5u5Gpj0TgdriCjRig1Z0n2CWw045tsqK+AScj2Wer/3BDbiVEgon0wDAYI
KoUDBwEBAwMFAAOBgQAi7B2eNIFJt/B+uCxh5Bey9OoRbwgnkU00rZf8Yx83jYrb
C7P6+jtJg4XDihaLzHXIScG4Qvoi0LGMa7ZYxzG9OhCGpNH7koxA4t/78JIqn7zY
sFvbj/HZx7DjyiAGnqNh1uBDjPQrFEFm1jJyNooypYHjFyUvt9EbxKDXbiPP9w==
-----END CERTIFICATE-----


--
Dmitry Olshansky

Systems Engineer
Demos llc.
security.demos.ru



diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index f9e422c..64134bd 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -62,12 +62,12 @@
  * [including the GNU Public Licence.]
  */
 
-#define NUM_NID 963
-#define NUM_SN 954
-#define NUM_LN 954
-#define NUM_OBJ 893
+#define NUM_NID 975
+#define NUM_SN 966
+#define NUM_LN 966
+#define NUM_OBJ 905
 
-static const unsigned char lvalues[6282]={
+static const unsigned char lvalues[6382]={
 0x00,                                        /* [  0] OBJ_undef */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  1] OBJ_rsadsi */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  7] OBJ_pkcs */
@@ -961,6 +961,18 @@ static const unsigned char lvalues[6282]={
 0x2A,0x85,0x03,0x07,0x01,                    /* [6260] OBJ_tc_26 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02,     /* [6265] OBJ_id_tc26_gost3411_12_256 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03,     /* [6273] OBJ_id_tc26_gost3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01,     /* [6281] OBJ_id_tc26_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02,     /* [6289] OBJ_id_tc26_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02,     /* [6297] OBJ_id_tc26_signwithdigest_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03,     /* [6305] OBJ_id_tc26_signwithdigest_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01,     /* [6313] OBJ_id_tc26_hmac_gost_3411_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02,     /* [6321] OBJ_id_tc26_hmac_gost_3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x01,     /* [6329] OBJ_id_tc26_agreement_gost_3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x02,     /* [6337] OBJ_id_tc26_agreement_gost_3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00,/* [6345] OBJ_id_tc26_gost_3410_12_512_paramSetTest */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01,/* [6354] OBJ_id_tc26_gost_3410_12_512_paramSetA */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02,/* [6363] OBJ_id_tc26_gost_3410_12_512_paramSetB */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01,/* [6372] OBJ_id_tc26_gost_28147_param_A */
 };
 
 static const ASN1_OBJECT nid_objs[NUM_NID]={
@@ -2531,6 +2543,37 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
    NID_id_tc26_gost3411_12_256,8,&(lvalues[6265]),0},
 {"md_gost12_512","GOST R 34.11-2012 512-bit length",
    NID_id_tc26_gost3411_12_512,8,&(lvalues[6273]),0},
+{"gost2012_256","GOST R 34.10-2012 with 256-bit key",
+   NID_id_tc26_gost3410_12_256,8,&(lvalues[6281]),0},
+{"gost2012_512","GOST R 34.10-2012 with 512-bit key",
+   NID_id_tc26_gost3410_12_512,8,&(lvalues[6289]),0},
+{"id-tc26-signwithdigest-gost3410-12-256",
+   "GOST R 34.10-2012 with 34.11-2012 256-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_256,8,&(lvalues[6297]),0},
+{"id-tc26-signwithdigest-gost3410-12-512",
+   "GOST R 34.10-2012 with 34.11-2012 512-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_512,8,&(lvalues[6305]),0},
+{"id-tc26-hmac-gost-3411-12-256","HMAC GOST R 34.11-2012 L=32 B=64",
+   NID_id_tc26_hmac_gost_3411_12_256,8,&(lvalues[6313]),0},
+{"id-tc26-hmac-gost-3411-12-512","HMAC GOST R 34.11-2012 L=64 B=64",
+   NID_id_tc26_hmac_gost_3411_12_512,8,&(lvalues[6321]),0},
+{"id-tc26-agreement-gost-3410-12-256",
+   "Key agreement schemes GOST R 34.10-2012 256-bit key",
+   NID_id_tc26_agreement_gost_3410_12_256,8,&(lvalues[6329]),0},
+{"id-tc26-agreement-gost-3410-12-512",
+   "Key agreement schemes GOST R 34.10-2012 512-bit key",
+   NID_id_tc26_agreement_gost_3410_12_512,8,&(lvalues[6337]),0},
+{"id-tc26-gost-3410-12-512-paramSetTest",
+   "id-tc26-gost-3410-12-512-paramSetTest",
+   NID_id_tc26_gost_3410_12_512_paramSetTest,9,&(lvalues[6345]),0},
+{"id-tc26-gost-3410-12-512-paramSetA",
+   "id-tc26-gost-3410-12-512-paramSetA",
+   NID_id_tc26_gost_3410_12_512_paramSetA,9,&(lvalues[6354]),0},
+{"id-tc26-gost-3410-12-512-paramSetB",
+   "id-tc26-gost-3410-12-512-paramSetB",
+   NID_id_tc26_gost_3410_12_512_paramSetB,9,&(lvalues[6363]),0},
+{"id-tc26-gost-28147-param-A","id-tc26-gost-28147-param-A",
+   NID_id_tc26_gost_28147_param_A,9,&(lvalues[6372]),0},
 };
 
 static const unsigned int sn_objs[NUM_SN]={
@@ -2877,6 +2920,8 @@ static const unsigned int sn_objs[NUM_SN]={
 815,   /* "gost-mac" */
 811,   /* "gost2001" */
 851,   /* "gost2001cc" */
+963,   /* "gost2012_256" */
+964,   /* "gost2012_512" */
 813,   /* "gost89" */
 814,   /* "gost89-cnt" */
 812,   /* "gost94" */
@@ -3132,6 +3177,16 @@ static const unsigned int sn_objs[NUM_SN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+969,   /* "id-tc26-agreement-gost-3410-12-256" */
+970,   /* "id-tc26-agreement-gost-3410-12-512" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
+967,   /* "id-tc26-hmac-gost-3411-12-256" */
+968,   /* "id-tc26-hmac-gost-3411-12-512" */
+965,   /* "id-tc26-signwithdigest-gost3410-12-256" */
+966,   /* "id-tc26-signwithdigest-gost3410-12-512" */
 676,   /* "identified-organization" */
 461,   /* "info" */
 748,   /* "inhibitAnyPolicy" */
@@ -3521,6 +3576,10 @@ static const unsigned int ln_objs[NUM_LN]={
 850,   /* "GOST 34.10-94 Cryptocom" */
 811,   /* "GOST R 34.10-2001" */
 817,   /* "GOST R 34.10-2001 DH" */
+963,   /* "GOST R 34.10-2012 with 256-bit key" */
+965,   /* "GOST R 34.10-2012 with 34.11-2012 256-bit" */
+966,   /* "GOST R 34.10-2012 with 34.11-2012 512-bit" */
+964,   /* "GOST R 34.10-2012 with 512-bit key" */
 812,   /* "GOST R 34.10-94" */
 818,   /* "GOST R 34.10-94 DH" */
 961,   /* "GOST R 34.11-2012 256-bit length" */
@@ -3533,6 +3592,8 @@ static const unsigned int ln_objs[NUM_LN]={
 852,   /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
 854,   /* "GOST R 3410-2001 Parameter Set Cryptocom" */
 810,   /* "HMAC GOST 34.11-94" */
+967,   /* "HMAC GOST R 34.11-2012 L=32 B=64" */
+968,   /* "HMAC GOST R 34.11-2012 L=64 B=64" */
 432,   /* "Hold Instruction Call Issuer" */
 430,   /* "Hold Instruction Code" */
 431,   /* "Hold Instruction None" */
@@ -3547,6 +3608,8 @@ static const unsigned int ln_objs[NUM_LN]={
 665,   /* "Inherit all" */
 647,   /* "International Organizations" */
 142,   /* "Invalidity Date" */
+969,   /* "Key agreement schemes GOST R 34.10-2012 256-bit key" */
+970,   /* "Key agreement schemes GOST R 34.10-2012 512-bit key" */
 504,   /* "MIME MHS" */
 388,   /* "Mail" */
 383,   /* "Management" */
@@ -4075,6 +4138,10 @@ static const unsigned int ln_objs[NUM_LN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
 34,    /* "idea-cbc" */
 35,    /* "idea-cfb" */
 36,    /* "idea-ecb" */
@@ -4870,8 +4937,16 @@ static const unsigned int obj_objs[NUM_OBJ]={
 851,   /* OBJ_id_GostR3410_2001_cc         1 2 643 2 9 1 5 4 */
 849,   /* OBJ_id_Gost28147_89_cc           1 2 643 2 9 1 6 1 */
 854,   /* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
+963,   /* OBJ_id_tc26_gost3410_12_256      1 2 643 7 1 1 1 1 */
+964,   /* OBJ_id_tc26_gost3410_12_512      1 2 643 7 1 1 1 2 */
 961,   /* OBJ_id_tc26_gost3411_12_256      1 2 643 7 1 1 2 2 */
 962,   /* OBJ_id_tc26_gost3411_12_512      1 2 643 7 1 1 2 3 */
+965,   /* OBJ_id_tc26_signwithdigest_gost3410_12_256 1 2 643 7 1 1 3 2 */
+966,   /* OBJ_id_tc26_signwithdigest_gost3410_12_512 1 2 643 7 1 1 3 3 */
+967,   /* OBJ_id_tc26_hmac_gost_3411_12_256 1 2 643 7 1 1 4 1 */
+968,   /* OBJ_id_tc26_hmac_gost_3411_12_512 1 2 643 7 1 1 4 2 */
+969,   /* OBJ_id_tc26_agreement_gost_3410_12_256 1 2 643 7 1 1 6 1 */
+970,   /* OBJ_id_tc26_agreement_gost_3410_12_512 1 2 643 7 1 1 6 2 */
 186,   /* OBJ_pkcs1                        1 2 840 113549 1 1 */
 27,    /* OBJ_pkcs3                        1 2 840 113549 1 3 */
 187,   /* OBJ_pkcs5                        1 2 840 113549 1 5 */
@@ -5039,6 +5114,10 @@ static const unsigned int obj_objs[NUM_OBJ]={
 439,   /* OBJ_pilotAttributeSyntax         0 9 2342 19200300 100 3 */
 440,   /* OBJ_pilotObjectClass             0 9 2342 19200300 100 4 */
 441,   /* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
+971,   /* OBJ_id_tc26_gost_3410_12_512_paramSetTest 1 2 643 7 1 2 1 2 0 */
+972,   /* OBJ_id_tc26_gost_3410_12_512_paramSetA 1 2 643 7 1 2 1 2 1 */
+973,   /* OBJ_id_tc26_gost_3410_12_512_paramSetB 1 2 643 7 1 2 1 2 2 */
+974,   /* OBJ_id_tc26_gost_28147_param_A   1 2 643 7 1 2 5 1 1 */
 108,   /* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
 112,   /* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
 782,   /* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h
index 70f41d2..c88ae68 100644
--- a/crypto/objects/obj_mac.h
+++ b/crypto/objects/obj_mac.h
@@ -3748,6 +3748,16 @@
 #define NID_id_Gost28147_89_None_KeyMeshing        820
 #define OBJ_id_Gost28147_89_None_KeyMeshing        OBJ_cryptopro,14L,0L
 
+#define SN_id_tc26_gost3410_12_256     "gost2012_256"
+#define LN_id_tc26_gost3410_12_256     "GOST R 34.10-2012 with 256-bit key"
+#define NID_id_tc26_gost3410_12_256        963
+#define OBJ_id_tc26_gost3410_12_256        OBJ_tc_26,1L,1L,1L
+
+#define SN_id_tc26_gost3410_12_512     "gost2012_512"
+#define LN_id_tc26_gost3410_12_512     "GOST R 34.10-2012 with 512-bit key"
+#define NID_id_tc26_gost3410_12_512        964
+#define OBJ_id_tc26_gost3410_12_512        OBJ_tc_26,1L,1L,2L
+
 #define SN_id_tc26_gost3411_12_256     "md_gost12_256"
 #define LN_id_tc26_gost3411_12_256     "GOST R 34.11-2012 256-bit length"
 #define NID_id_tc26_gost3411_12_256        961
@@ -3758,6 +3768,36 @@
 #define NID_id_tc26_gost3411_12_512        962
 #define OBJ_id_tc26_gost3411_12_512        OBJ_tc_26,1L,2L,3L
 
+#define SN_id_tc26_signwithdigest_gost3410_12_256      "id-tc26-signwithdigest-gost3410-12-256"
+#define LN_id_tc26_signwithdigest_gost3410_12_256      "GOST R 34.10-2012 with 34.11-2012 256-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_256     965
+#define OBJ_id_tc26_signwithdigest_gost3410_12_256     OBJ_tc_26,1L,3L,2L
+
+#define SN_id_tc26_signwithdigest_gost3410_12_512      "id-tc26-signwithdigest-gost3410-12-512"
+#define LN_id_tc26_signwithdigest_gost3410_12_512      "GOST R 34.10-2012 with 34.11-2012 512-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_512     966
+#define OBJ_id_tc26_signwithdigest_gost3410_12_512     OBJ_tc_26,1L,3L,3L
+
+#define SN_id_tc26_hmac_gost_3411_12_256       "id-tc26-hmac-gost-3411-12-256"
+#define LN_id_tc26_hmac_gost_3411_12_256       "HMAC GOST R 34.11-2012 L=32 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_256      967
+#define OBJ_id_tc26_hmac_gost_3411_12_256      OBJ_tc_26,1L,4L,1L
+
+#define SN_id_tc26_hmac_gost_3411_12_512       "id-tc26-hmac-gost-3411-12-512"
+#define LN_id_tc26_hmac_gost_3411_12_512       "HMAC GOST R 34.11-2012 L=64 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_512      968
+#define OBJ_id_tc26_hmac_gost_3411_12_512      OBJ_tc_26,1L,4L,2L
+
+#define SN_id_tc26_agreement_gost_3410_12_256      "id-tc26-agreement-gost-3410-12-256"
+#define LN_id_tc26_agreement_gost_3410_12_256      "Key agreement schemes GOST R 34.10-2012 256-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_256     969
+#define OBJ_id_tc26_agreement_gost_3410_12_256     OBJ_tc_26,1L,6L,1L
+
+#define SN_id_tc26_agreement_gost_3410_12_512      "id-tc26-agreement-gost-3410-12-512"
+#define LN_id_tc26_agreement_gost_3410_12_512      "Key agreement schemes GOST R 34.10-2012 512-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_512     970
+#define OBJ_id_tc26_agreement_gost_3410_12_512     OBJ_tc_26,1L,6L,2L
+
 #define SN_id_GostR3411_94_TestParamSet        "id-GostR3411-94-TestParamSet"
 #define NID_id_GostR3411_94_TestParamSet       821
 #define OBJ_id_GostR3411_94_TestParamSet       OBJ_cryptopro,30L,0L
@@ -3870,6 +3910,22 @@
 #define NID_id_GostR3410_94_bBis       848
 #define OBJ_id_GostR3410_94_bBis       OBJ_id_GostR3410_94,4L
 
+#define SN_id_tc26_gost_3410_12_512_paramSetTest       "id-tc26-gost-3410-12-512-paramSetTest"
+#define NID_id_tc26_gost_3410_12_512_paramSetTest      971
+#define OBJ_id_tc26_gost_3410_12_512_paramSetTest      OBJ_tc_26,2L,1L,2L,0L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetA      "id-tc26-gost-3410-12-512-paramSetA"
+#define NID_id_tc26_gost_3410_12_512_paramSetA     972
+#define OBJ_id_tc26_gost_3410_12_512_paramSetA     OBJ_tc_26,2L,1L,2L,1L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetB      "id-tc26-gost-3410-12-512-paramSetB"
+#define NID_id_tc26_gost_3410_12_512_paramSetB     973
+#define OBJ_id_tc26_gost_3410_12_512_paramSetB     OBJ_tc_26,2L,1L,2L,2L
+
+#define SN_id_tc26_gost_28147_param_A      "id-tc26-gost-28147-param-A"
+#define NID_id_tc26_gost_28147_param_A     974
+#define OBJ_id_tc26_gost_28147_param_A     OBJ_tc_26,2L,5L,1L,1L
+
 #define SN_id_Gost28147_89_cc      "id-Gost28147-89-cc"
 #define LN_id_Gost28147_89_cc      "GOST 28147-89 Cryptocom ParamSet"
 #define NID_id_Gost28147_89_cc     849
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 0010bf8..d65d512 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -960,3 +960,15 @@ md_gost12_256      959
 md_gost12_512      960
 id_tc26_gost3411_12_256        961
 id_tc26_gost3411_12_512        962
+id_tc26_gost3410_12_256        963
+id_tc26_gost3410_12_512        964
+id_tc26_signwithdigest_gost3410_12_256     965
+id_tc26_signwithdigest_gost3410_12_512     966
+id_tc26_hmac_gost_3411_12_256      967
+id_tc26_hmac_gost_3411_12_512      968
+id_tc26_agreement_gost_3410_12_256     969
+id_tc26_agreement_gost_3410_12_512     970
+id_tc26_gost_3410_12_512_paramSetTest      971
+id_tc26_gost_3410_12_512_paramSetA     972
+id_tc26_gost_3410_12_512_paramSetB     973
+id_tc26_gost_28147_param_A     974
diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h
index cfd628a..4bebb0d 100644
--- a/crypto/objects/obj_xref.h
+++ b/crypto/objects/obj_xref.h
@@ -49,13 +49,15 @@ static const nid_triple sigoid_srt[] =
    {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf},
+   {NID_id_tc26_signwithdigest_gost3410_12_256, NID_id_tc26_gost3411_12_256, NID_id_tc26_gost3410_12_256},
+   {NID_id_tc26_signwithdigest_gost3410_12_512, NID_id_tc26_gost3411_12_512, NID_id_tc26_gost3410_12_512},
    };
 
 static const nid_triple * const sigoid_srt_xref[] =
    {
    &sigoid_srt[29],
-   &sigoid_srt[17],
    &sigoid_srt[18],
+   &sigoid_srt[17],
    &sigoid_srt[0],
    &sigoid_srt[1],
    &sigoid_srt[7],
@@ -93,5 +95,7 @@ static const nid_triple * const sigoid_srt_xref[] =
    &sigoid_srt[26],
    &sigoid_srt[27],
    &sigoid_srt[28],
+   &sigoid_srt[40],
+   &sigoid_srt[41],
    };
 
diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt
index 19c9422..094a204 100644
--- a/crypto/objects/obj_xref.txt
+++ b/crypto/objects/obj_xref.txt
@@ -44,6 +44,8 @@ id_GostR3411_94_with_GostR3410_2001   id_GostR3411_94 id_GostR3410_2001
 id_GostR3411_94_with_GostR3410_94  id_GostR3411_94 id_GostR3410_94
 id_GostR3411_94_with_GostR3410_94_cc   id_GostR3411_94 id_GostR3410_94_cc
 id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc
+id_tc26_signwithdigest_gost3410_12_256 id_tc26_gost3411_12_256 id_tc26_gost3410_12_256
+id_tc26_signwithdigest_gost3410_12_512 id_tc26_gost3411_12_512 id_tc26_gost3410_12_512
 # ECDH KDFs and their corresponding message digests and schemes
 dhSinglePass_stdDH_sha1kdf_scheme      sha1    dh_std_kdf
 dhSinglePass_stdDH_sha224kdf_scheme        sha224  dh_std_kdf
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index a61f8d7..bc4f56c 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1181,10 +1181,20 @@ cryptopro 14 1      : id-Gost28147-89-CryptoPro-KeyMeshing
 cryptopro 14 0     : id-Gost28147-89-None-KeyMeshing
 
 # TC-26 GOST OIDs
+!Cname id-tc26-gost3410-12-256
+tc-26 1 1 1  : gost2012_256 : GOST R 34.10-2012 with 256-bit key
+!Cname id-tc26-gost3410-12-512
+tc-26 1 1 2  : gost2012_512 : GOST R 34.10-2012 with 512-bit key
 !Cname id-tc26-gost3411-12-256
 tc-26 1 2 2  : md_gost12_256 : GOST R 34.11-2012 256-bit length
 !Cname id-tc26-gost3411-12-512
 tc-26 1 2 3  : md_gost12_512 : GOST R 34.11-2012 512-bit length
+tc-26 1 3 2  : id-tc26-signwithdigest-gost3410-12-256 : GOST R 34.10-2012 with 34.11-2012 256-bit
+tc-26 1 3 3  : id-tc26-signwithdigest-gost3410-12-512 : GOST R 34.10-2012 with 34.11-2012 512-bit
+tc-26 1 4 1  : id-tc26-hmac-gost-3411-12-256 : HMAC GOST R 34.11-2012 L=32 B=64
+tc-26 1 4 2  : id-tc26-hmac-gost-3411-12-512 : HMAC GOST R 34.11-2012 L=64 B=64
+tc-26 1 6 1     : id-tc26-agreement-gost-3410-12-256 : Key agreement schemes GOST R 34.10-2012 256-bit key
+tc-26 1 6 2  : id-tc26-agreement-gost-3410-12-512 :    Key agreement schemes GOST R 34.10-2012 512-bit key
 
 # GOST parameter set OIDs
 
@@ -1223,6 +1233,13 @@ id-GostR3410-94 2    : id-GostR3410-94-aBis
 id-GostR3410-94 3  : id-GostR3410-94-b
 id-GostR3410-94 4  : id-GostR3410-94-bBis
 
+# TC-26 GOST parameter set OIDs
+
+tc-26 2 1 2 0      : id-tc26-gost-3410-12-512-paramSetTest
+tc-26 2 1 2 1      : id-tc26-gost-3410-12-512-paramSetA
+tc-26 2 1 2 2      : id-tc26-gost-3410-12-512-paramSetB
+tc-26 2 5 1 1       : id-tc26-gost-28147-param-A
+
 # Cryptocom LTD GOST OIDs
 
 cryptocom 1 6 1        : id-Gost28147-89-cc    : GOST 28147-89 Cryptocom ParamSet
diff --git a/engines/ccgost/README.gost b/engines/ccgost/README.gost
index b8eb56e..000774f 100644
--- a/engines/ccgost/README.gost
+++ b/engines/ccgost/README.gost
@@ -14,7 +14,12 @@ GOST R 34.10-94 and GOST R 34.10-2001 - digital signature algorithms.
    256 bit private keys. Public keys are 1024 bit for 94 and 512 bit for
    2001 (which is elliptic-curve based). Key exchange algorithms
    (VKO R 34.10) are supported on these keys too.
-  
+
+GOST R 34.10-2012 - digital signature algorithm.
+   Consists of 2 versions with 256 bit and 512 bit private keys.
+   Both are based on elliptic curve and have public keys of 512 bit
+   and 1024 bit respectively.
+
 GOST R 34.11-94  Message digest algorithm. 256-bit hash value
 
 GOST R 34.11-2012 Message digest algorithm. Has versions with
@@ -108,6 +113,8 @@ USAGE WITH COMMAND LINE openssl UTILITY
   are supported by
    gost94: 0,A,B,C,D,XA,XB,XC
    gost2001: 0,A,B,C,XA,XB
+        gost2012-256: 0,A,B,C,XA,XB
+        gost2012-512: A,B
   You can also use numeric representation of OID as to destinate
   paramset.
 
diff --git a/engines/ccgost/gost2001.c b/engines/ccgost/gost2001.c
index dacd82d..bbc52be 100644
--- a/engines/ccgost/gost2001.c
+++ b/engines/ccgost/gost2001.c
@@ -31,14 +31,12 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig);
  * Also fils DSA->q field with copy of EC_GROUP order field to make
  * DSA_size function work
  */
-int fill_GOST2001_params(EC_KEY *eckey, int nid)
+void fill_GOST_EC_params(EC_KEY *eckey, R3410_2001_params *params)
    {
-   R3410_2001_params *params = R3410_2001_paramset;
    EC_GROUP *grp=NULL;
    BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL;
    EC_POINT *P=NULL;
    BN_CTX *ctx=BN_CTX_new();
-   int ok=0;
   
    BN_CTX_start(ctx);
    p=BN_CTX_get(ctx);
@@ -47,12 +45,6 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    x=BN_CTX_get(ctx);
    y=BN_CTX_get(ctx);
    q=BN_CTX_get(ctx);
-   while (params->nid!=NID_undef && params->nid != nid) params++;
-   if (params->nid == NID_undef)
-       {
-       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
-       goto err;
-       }  
    BN_hex2bn(&p,params->p);
    BN_hex2bn(&a,params->a);
    BN_hex2bn(&b,params->b);
@@ -76,15 +68,44 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    EC_GROUP_set_curve_name(grp,params->nid);
 
    EC_KEY_set_group(eckey,grp);
-   ok=1;
-   err:
    EC_POINT_free(P);
    EC_GROUP_free(grp);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
-   return ok;
-   }  
+   }
 
+int fill_GOST2001_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2001_paramset;
+
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }
+
+// paramset selection is exactly the same
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid)
+   {
+   return fill_GOST2001_params(eckey, nid);
+   }
+
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2012_512_paramset;
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }
 
 /*
  * Computes gost2001 signature as DSA_SIG structure
@@ -94,7 +115,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
 DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    {
    DSA_SIG *newsig = NULL;
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    BIGNUM *order = NULL;
    const EC_GROUP *group;
    const BIGNUM *priv_key;
@@ -102,7 +123,7 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    EC_POINT *C=NULL;
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);
-   OPENSSL_assert(dlen==32);
+   OPENSSL_assert(dlen==32 || dlen==64);
    newsig=DSA_SIG_new();
    if (!newsig)
        {
@@ -212,7 +233,7 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
        goto err;
 
        }
-   md = hashsum2bn(dgst);
+   md = hashsum2bn(dgst,dgst_len);
 
    BN_mod(e,md,order,ctx);
 #ifdef DEBUG_SIGN
diff --git a/engines/ccgost/gost_ameth.c b/engines/ccgost/gost_ameth.c
index 2cde1fc..4293bf1 100644
--- a/engines/ccgost/gost_ameth.c
+++ b/engines/ccgost/gost_ameth.c
@@ -20,6 +20,22 @@
 #include "gost_lcl.h"
 #include "e_gost_err.h"
 
+static int md_nid_by_pmeth_nid(int pmeth_nid)
+{
+   switch(pmeth_nid)
+   {
+   case NID_id_GostR3410_94:
+   case NID_id_GostR3410_2001:
+       return NID_id_GostR3411_94;
+   case NID_id_tc26_gost3410_12_256:
+       return NID_id_tc26_gost3411_12_256;
+   case NID_id_tc26_gost3410_12_512:
+       return NID_id_tc26_gost3411_12_512;
+   default:
+       return NID_undef;
+   }
+}
+
 int gost94_nid_by_params(DSA *p)
    {
    R3410_params *gost_params;
@@ -42,6 +58,7 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
    ASN1_STRING *params = ASN1_STRING_new();
    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
    int pkey_param_nid = NID_undef;
+   int hash_param_nid = NID_undef;
 
    if (!params || !gkp)
        {
@@ -55,6 +72,15 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
        {
        case NID_id_GostR3410_2001:
            pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
+           break;
+       case NID_id_tc26_gost3410_12_256:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_256;
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_512;
            break;
        case NID_id_GostR3410_94:
            pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
@@ -65,11 +91,12 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
                ASN1_STRING_free(params);
                params=NULL;
                goto err;
-               }  
+               }          
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
            break;
        }  
    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
-   gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
+   gkp->hash_params = OBJ_nid2obj(hash_param_nid);
    /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
    if (params->length <=0 )
@@ -143,6 +170,29 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
            }
        if (!fill_GOST2001_params(ec,param_nid)) return 0;
        }
+       break;
+       case NID_id_tc26_gost3410_12_256:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_256_params(ec,param_nid)) return 0;
+       }
+       break;
+       case NID_id_tc26_gost3410_12_512:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_512_params(ec,param_nid)) return 0;
+       }
+       break;
        }
 
    return 1;
@@ -166,6 +216,8 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
        break;
        }  
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0(pkey);
        if (!ec)
@@ -197,6 +249,8 @@ BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey)
        break;
        }  
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
        const BIGNUM* priv;
@@ -224,7 +278,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2,
                    NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -241,7 +295,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
                    NULL, NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -282,7 +336,10 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
            return 1;
 #endif
        case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
-           *(int *)arg2 = NID_id_GostR3411_94;
+           {
+           int nid = EVP_PKEY_base_id(pkey);
+           *(int *)arg2 = md_nid_by_pmeth_nid(nid);
+           }
            return 2;
        }
   
@@ -824,6 +881,16 @@ static int pkey_bits_gost(const EVP_PKEY *pk)
    {
    return 256;
    }
+
+static int pkey_size_gost_512(const EVP_PKEY *pk)
+   {
+   return 128;
+   }
+
+static int pkey_bits_gost_512(const EVP_PKEY *pk)
+   {
+   return 512;
+   }
 /*------------------------ ASN1 METHOD for GOST MAC  -------------------*/
 static void  mackey_free_gost(EVP_PKEY *pk)
    {
@@ -872,7 +939,8 @@ static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int d
    return 1;
 }  
 
-static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+//generic version for all EC-based GOST 34.10: 2001, 2012-256, 2012-512
+static int gost_ec_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen, void (*fill_params(EC_KEY*,int)), int meth_nid) {
    ASN1_OBJECT *obj=NULL;
    int nid;
    EC_KEY *ec = EVP_PKEY_get0(pkey);
@@ -884,15 +952,23 @@ static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int
    if (!ec)
        {
        ec = EC_KEY_new();
-       if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
+       if (!EVP_PKEY_assign(pkey,meth_nid,ec)) return 0;
        }  
-   if (!fill_GOST2001_params(ec, nid)) return 0;
+   if (!fill_params(ec, nid)) return 0;
    return 1;
 }  
 
+static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2001_params, NID_id_GostR3410_2001);
+}  
 
+static int gost2012_256_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_256_params, NID_id_tc26_gost3410_12_256);
+}
 
-
+static int gost2012_512_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_512_params, NID_id_tc26_gost3410_12_512);
+}
 
 /* ----------------------------------------------------------------------*/
 int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
@@ -936,6 +1012,40 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
   
            EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_256_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost, pkey_bits_gost);
+  
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_512_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost_512, pkey_bits_gost_512);
+  
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
            EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);  
diff --git a/engines/ccgost/gost_eng.c b/engines/ccgost/gost_eng.c
index dc6bd72..977b5b3 100644
--- a/engines/ccgost/gost_eng.c
+++ b/engines/ccgost/gost_eng.c
@@ -40,15 +40,20 @@ static int gost_digest_nids[] =
     NID_id_tc26_gost3411_12_256,NID_id_tc26_gost3411_12_512,0};
 
 static int gost_pkey_meth_nids[] =
-   {NID_id_GostR3410_94,
-    NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
+   {NID_id_GostR3410_94, NID_id_GostR3410_2001,
+    NID_id_tc26_gost3410_12_256,NID_id_tc26_gost3410_12_512,
+    NID_id_Gost28147_89_MAC, 0};
 
 static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
-    *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2012_256 = NULL,
+   *pmeth_GostR3410_2012_512 = NULL,
    *pmeth_Gost28147_MAC = NULL;
 
 static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
    *ameth_GostR3410_2001 = NULL,
+   *ameth_GostR3410_2012_256 = NULL,
+   *ameth_GostR3410_2012_512 = NULL,
    *ameth_Gost28147_MAC = NULL;
 
 
@@ -68,9 +73,13 @@ static int gost_engine_destroy(ENGINE *e)
 
    pmeth_GostR3410_94 = NULL;
    pmeth_GostR3410_2001 = NULL;
+   pmeth_GostR3410_2012_256 = NULL;
+   pmeth_GostR3410_2012_512 = NULL;
    pmeth_Gost28147_MAC = NULL;
    ameth_GostR3410_94 = NULL;
    ameth_GostR3410_2001 = NULL;
+   ameth_GostR3410_2012_256 = NULL;
+   ameth_GostR3410_2012_512 = NULL;
    ameth_Gost28147_MAC = NULL;
    return 1;
    }
@@ -130,11 +139,17 @@ static int bind_gost (ENGINE *e,const char *id)
 
    if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
    if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_256, &ameth_GostR3410_2012_256,
+       "GOST2012-256", "GOST R 34.10-2012 256bit")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_512, &ameth_GostR3410_2012_512,
+       "GOST2012-512", "GOST R 34.10-2012 512bit")) goto end;
    if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
        "GOST-MAC", "GOST 28147-89 MAC")) goto end;
 
    if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
    if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_256, &pmeth_GostR3410_2012_256, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_512, &pmeth_GostR3410_2012_512, 0)) goto end;
    if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
        goto end;
    if ( ! ENGINE_register_ciphers(e)
@@ -229,7 +244,7 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
    if (!pmeth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }
 
    switch (nid)
@@ -237,6 +252,8 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
        case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1;
+       case NID_id_tc26_gost3410_12_256: *pmeth = pmeth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *pmeth = pmeth_GostR3410_2012_512; return 1;
        default:;
        }
   
@@ -247,17 +264,19 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
 static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
    const int **nids, int nid)
    {
+
    if (!ameth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }
    switch (nid)
        {
        case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1;
-  
+       case NID_id_tc26_gost3410_12_256: *ameth = ameth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *ameth = ameth_GostR3410_2012_512; return 1;
        default:;
        }
   
diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h
index 90c262d..7d0b526 100644
--- a/engines/ccgost/gost_lcl.h
+++ b/engines/ccgost/gost_lcl.h
@@ -185,6 +185,8 @@ int pkey_gost94_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
 /* Internal functions for signature algorithms */
 int fill_GOST94_params(DSA *dsa,int nid);
 int fill_GOST2001_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid);
 int gost_sign_keygen(DSA *dsa) ;
 int gost2001_keygen(EC_KEY *ec) ;
 
@@ -200,7 +202,7 @@ int gost94_compute_public(DSA *dsa) ;
 /*============== miscellaneous functions============================= */
 /* from gost_sign.c */
 /* Convert GOST R 34.11 hash sum to bignum according to standard */
-BIGNUM *hashsum2bn(const unsigned char *dgst) ;
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen) ;
 /* Store bignum in byte array of given length, prepending by zeros
  * if nesseccary */
 int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
diff --git a/engines/ccgost/gost_params.c b/engines/ccgost/gost_params.c
index 40fc343..6fcb3dc 100644
--- a/engines/ccgost/gost_params.c
+++ b/engines/ccgost/gost_params.c
@@ -196,3 +196,42 @@ R3410_2001_params R3410_2001_paramset[]={
    { 0,NULL,NULL,NULL,NULL,NULL,NULL
    }
 };
+
+R3410_2001_params R3410_2012_512_paramset[]={
+   /*1.2.643.7.1.2.1.2.1*/
+   {NID_id_tc26_gost_3410_12_512_paramSetA,
+   /* A */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",
+   /* B */
+   "E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265"
+"EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",
+   /* P */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",
+   /* Q */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2"
+"7E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",
+   /* X */
+   "3",
+   /* Y */
+   "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921D"
+"F1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4"
+   },
+   /*1.2.643.7.1.2.1.2.2*/
+   {NID_id_tc26_gost_3410_12_512_paramSetB,
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006C",
+   "687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3"
+"E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006F",
+   "80000000000000000000000000000000000000000000000000000000000000014"
+"9A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",
+   "2",
+   "1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335D"
+"CB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD"
+   },
+   { 0,NULL,NULL,NULL,NULL,NULL,NULL
+   }
+};
\ No newline at end of file
diff --git a/engines/ccgost/gost_params.h b/engines/ccgost/gost_params.h
index 4c3f556..3a1c6e0 100644
--- a/engines/ccgost/gost_params.h
+++ b/engines/ccgost/gost_params.h
@@ -30,5 +30,6 @@ typedef struct R3410_2001 {
 } R3410_2001_params;
 
 extern R3410_2001_params R3410_2001_paramset[];
+extern R3410_2001_params R3410_2012_512_paramset[];
 
 #endif
diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c
index 3189798..f73cae5 100644
--- a/engines/ccgost/gost_pmeth.c
+++ b/engines/ccgost/gost_pmeth.c
@@ -33,6 +33,8 @@ static int pkey_gost_init(EVP_PKEY_CTX *ctx)
          data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey));
          break;
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
           data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
        break;
        default:
@@ -54,9 +56,10 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
    src_data = EVP_PKEY_CTX_get_data(src);
    dst_data = EVP_PKEY_CTX_get_data(dst);
    *dst_data = *src_data;
-   if (src_data -> shared_ukm) {
+   if (src_data->shared_ukm)
+       {
        dst_data->shared_ukm=NULL;
-   }  
+       }  
    return 1;
    }
 
@@ -72,11 +75,17 @@ static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
    {
    struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
+   int base_id;
+   int md_type;
    switch (type)
        {
        case EVP_PKEY_CTRL_MD:
        {
-       if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
+       base_id = EVP_PKEY_base_id(EVP_PKEY_CTX_get0_pkey(ctx));
+       md_type = EVP_MD_type((const EVP_MD *)p2);
+       if (((base_id == NID_id_GostR3410_94 || base_id == NID_id_GostR3410_2001) && md_type != NID_id_GostR3411_94)
+           || (base_id == NID_id_tc26_gost3410_12_256 && md_type != NID_id_tc26_gost3411_12_256)
+           || (base_id == NID_id_tc26_gost3410_12_512 && md_type != NID_id_tc26_gost3411_12_512))
            {
            GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
            return 0;
@@ -268,6 +277,63 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
    return -2;
    }
 
+static int pkey_gost_ctrl12_256_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+{
+   return pkey_gost_ctrl01_str(ctx, type, value);
+}
+
+static int pkey_gost_ctrl12_512_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+   {
+   int param_nid=0;
+   printf("CTL %s %s \n", type, value);
+   if(!strcmp(type, param_ctrl_string))
+       {
+       if (!value)
+           {
+           return 0;
+           }
+       if (strlen(value) == 1)
+           {
+           switch(toupper((unsigned char)value[0]))
+               {
+               case 'A':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetA;
+                   break;  
+               case 'B':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetB;
+                   break;
+               default:
+                   return 0;
+                   break;
+               }
+           }
+       else
+           {
+           R3410_2001_params *p = R3410_2012_512_paramset;
+           param_nid = OBJ_txt2nid(value);
+           if (param_nid == NID_undef)
+               {
+               return 0;
+               }
+           for (;p->nid != NID_undef;p++)
+               {
+               if (p->nid == param_nid) break;
+               }          
+           if (p->nid == NID_undef)
+               {
+               GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
+                   GOST_R_INVALID_PARAMSET);
+               return 0;
+               }
+           }
+
+       return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
+           param_nid, NULL);
+       }
+   return -2;
+   }
 /* --------------------- key generation  --------------------------------*/
 
 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) {
@@ -303,8 +369,11 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
                GOST_R_NO_PARAMETERS_SET);
            return 0;
        }
-   if (!ec)    
+   if (!ec)
+       {
        ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
    if (!fill_GOST2001_params(ec,data->sign_param_nid))
        {
        EC_KEY_free(ec);
@@ -314,6 +383,54 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }
 
+static int pkey_gost12_256_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)
+       {
+       ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
+   if (!fill_GOST2012_256_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_256,ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)    
+       ec = EC_KEY_new();
+   if(!fill_GOST2012_512_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+  
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_512,ec);
+   return 1;
+   }
+
 /* Generates Gost_R3410_94_cp key */
 static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    {
@@ -334,6 +451,23 @@ static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }
 
+static int pkey_gost12_256_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_256_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_512_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }
 
 
 /* ----------- sign callbacks --------------------------------------*/
@@ -363,17 +497,25 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
    DSA_SIG *unpacked_sig=NULL;
    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
    if (!siglen) return 0;
+   // GOST-2012 signature can be 512 or 1024 bits long
+   const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0(pkey));
+
+   int pkey_len = EC_GROUP_get_degree(group)/8;
    if (!sig)
        {
-       *siglen= 64; /* better to check size of curve order*/
+       *siglen = pkey_len*2;
        return 1;
        }  
+   if (tbs_len != pkey_len)
+       {
+       return 0;
+       }
    unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
    if (!unpacked_sig)
        {
        return 0;
        }
-   return pack_sign_cp(unpacked_sig,32,sig,siglen);
+   return pack_sign_cp(unpacked_sig,pkey_len,sig,siglen);
    }
 
 /* ------------------- verify callbacks ---------------------------*/
@@ -600,7 +742,7 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost94_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost94_paramgen);  
            break;
-       case NID_id_GostR3410_2001:
+       case NID_id_GostR3410_2001:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
            EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
            EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
@@ -614,6 +756,34 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost2001_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost01_paramgen);  
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_256_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_256_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_256_paramgen);  
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_512_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_512_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_512_paramgen);  
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
            EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
diff --git a/engines/ccgost/gost_sign.c b/engines/ccgost/gost_sign.c
index 4095654..3f3902c 100644
--- a/engines/ccgost/gost_sign.c
+++ b/engines/ccgost/gost_sign.c
@@ -52,7 +52,7 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
    {
    BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
    DSA_SIG *newsig = DSA_SIG_new();
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    /* check if H(M) mod q is zero */
    BN_CTX *ctx=BN_CTX_new();
    BN_CTX_start(ctx);
@@ -149,7 +149,7 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len,
        GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
        return 0;
        }
-   md=hashsum2bn(dgst);
+   md=hashsum2bn(dgst,dgst_len);
   
    tmp=BN_CTX_get(ctx);
    v=BN_CTX_get(ctx);
@@ -279,15 +279,16 @@ DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
    }
 
 /* Convert little-endian byte array into bignum */
-BIGNUM *hashsum2bn(const unsigned char *dgst)
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen)
    {
-   unsigned char buf[32];
+   unsigned char buf[64];    
    int i;
-   for (i=0;i<32;i++)
+    OPENSSL_assert(dlen==32 || dlen == 64);
+   for (i=0;i<dlen;i++)
        {
-       buf[31-i]=dgst[i];
+       buf[dlen-1-i]=dgst[i];
        }
-   return getbnfrombuf(buf,32);
+   return getbnfrombuf(buf,dlen);
    }
 
 /* Convert byte buffer to bignum, skipping leading zeros*/
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Billy Brumley
Please read CVE-2011-1945. You need to propagate the fix in gost2001_do_sign. If you're unsure, check the comments in crypto/ecdsa/ecs_ossl.c.

BBB


On Wed, Apr 23, 2014 at 9:29 AM, Дмитрий Ольшанский via RT <[hidden email]> wrote:
This is a second patch to add new Russian standard GOST algorithms.

Needs GOST 34.11-2012 hash implementation listed in RT #3311.

See also both patches required in a pull request on github:
https://github.com/openssl/openssl/pull/75

No test cases added, as there are none present in ccgost nor the format
of such is apparent.
However generated certificates were tested against CryptoPro CSP 4.0 and
vise-versa.

Some examples of usage:

dmitry@linux64 ~/openssl/apps $ ./openssl req -engine gost -keyout
new.pem -newkey gost2012-512 -pkeyopt paramset:B -batch  > new.req
engine "gost" set.
Generating a 2048 bit GOST2012-512 private key
writing new private key to 'new.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
dmitry@linux64 ~/openssl/apps $ ./openssl x509 -engine gost -signkey
new.pem -req < new.req
engine "gost" set.
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
Getting Private key
Enter pass phrase for new.pem:
-----BEGIN CERTIFICATE-----
MIICCjCCAXQCCQDa+tA+pJiE/DAMBggqhQMHAQEDAwUAMEUxCzAJBgNVBAYTAkFV
MRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRz
IFB0eSBMdGQwHhcNMTQwNDIzMTMzMzIzWhcNMTQwNTIzMTMzMzIzWjBFMQswCQYD
VQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQg
V2lkZ2l0cyBQdHkgTHRkMIGqMCEGCCqFAwcBAQECMBUGCSqFAwcBAgECAgYIKoUD
BwEBAgMDgYQABIGAxmt61J1wPiggpm21ILxGboDoMekKHo+9ZD+uhlCIRgNFnIZ9
FBjPyUGvMKPwicE4QPyouId4+pAzf7W3gxP9SQtIIJ9cEKUyHwaF1fU8RgQ4P3JF
qzVo5O5u5Gpj0TgdriCjRig1Z0n2CWw045tsqK+AScj2Wer/3BDbiVEgon0wDAYI
KoUDBwEBAwMFAAOBgQAi7B2eNIFJt/B+uCxh5Bey9OoRbwgnkU00rZf8Yx83jYrb
C7P6+jtJg4XDihaLzHXIScG4Qvoi0LGMa7ZYxzG9OhCGpNH7koxA4t/78JIqn7zY
sFvbj/HZx7DjyiAGnqNh1uBDjPQrFEFm1jJyNooypYHjFyUvt9EbxKDXbiPP9w==
-----END CERTIFICATE-----


--
Dmitry Olshansky

Systems Engineer
Demos llc.
security.demos.ru



diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index f9e422c..64134bd 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -62,12 +62,12 @@
  * [including the GNU Public Licence.]
  */

-#define NUM_NID 963
-#define NUM_SN 954
-#define NUM_LN 954
-#define NUM_OBJ 893
+#define NUM_NID 975
+#define NUM_SN 966
+#define NUM_LN 966
+#define NUM_OBJ 905

-static const unsigned char lvalues[6282]={
+static const unsigned char lvalues[6382]={
 0x00,                                        /* [  0] OBJ_undef */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  1] OBJ_rsadsi */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  7] OBJ_pkcs */
@@ -961,6 +961,18 @@ static const unsigned char lvalues[6282]={
 0x2A,0x85,0x03,0x07,0x01,                    /* [6260] OBJ_tc_26 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02,     /* [6265] OBJ_id_tc26_gost3411_12_256 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03,     /* [6273] OBJ_id_tc26_gost3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01,     /* [6281] OBJ_id_tc26_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02,     /* [6289] OBJ_id_tc26_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02,     /* [6297] OBJ_id_tc26_signwithdigest_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03,     /* [6305] OBJ_id_tc26_signwithdigest_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01,     /* [6313] OBJ_id_tc26_hmac_gost_3411_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02,     /* [6321] OBJ_id_tc26_hmac_gost_3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x01,     /* [6329] OBJ_id_tc26_agreement_gost_3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x02,     /* [6337] OBJ_id_tc26_agreement_gost_3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00,/* [6345] OBJ_id_tc26_gost_3410_12_512_paramSetTest */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01,/* [6354] OBJ_id_tc26_gost_3410_12_512_paramSetA */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02,/* [6363] OBJ_id_tc26_gost_3410_12_512_paramSetB */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01,/* [6372] OBJ_id_tc26_gost_28147_param_A */
 };

 static const ASN1_OBJECT nid_objs[NUM_NID]={
@@ -2531,6 +2543,37 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
    NID_id_tc26_gost3411_12_256,8,&(lvalues[6265]),0},
 {"md_gost12_512","GOST R 34.11-2012 512-bit length",
    NID_id_tc26_gost3411_12_512,8,&(lvalues[6273]),0},
+{"gost2012_256","GOST R 34.10-2012 with 256-bit key",
+   NID_id_tc26_gost3410_12_256,8,&(lvalues[6281]),0},
+{"gost2012_512","GOST R 34.10-2012 with 512-bit key",
+   NID_id_tc26_gost3410_12_512,8,&(lvalues[6289]),0},
+{"id-tc26-signwithdigest-gost3410-12-256",
+   "GOST R 34.10-2012 with 34.11-2012 256-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_256,8,&(lvalues[6297]),0},
+{"id-tc26-signwithdigest-gost3410-12-512",
+   "GOST R 34.10-2012 with 34.11-2012 512-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_512,8,&(lvalues[6305]),0},
+{"id-tc26-hmac-gost-3411-12-256","HMAC GOST R 34.11-2012 L=32 B=64",
+   NID_id_tc26_hmac_gost_3411_12_256,8,&(lvalues[6313]),0},
+{"id-tc26-hmac-gost-3411-12-512","HMAC GOST R 34.11-2012 L=64 B=64",
+   NID_id_tc26_hmac_gost_3411_12_512,8,&(lvalues[6321]),0},
+{"id-tc26-agreement-gost-3410-12-256",
+   "Key agreement schemes GOST R 34.10-2012 256-bit key",
+   NID_id_tc26_agreement_gost_3410_12_256,8,&(lvalues[6329]),0},
+{"id-tc26-agreement-gost-3410-12-512",
+   "Key agreement schemes GOST R 34.10-2012 512-bit key",
+   NID_id_tc26_agreement_gost_3410_12_512,8,&(lvalues[6337]),0},
+{"id-tc26-gost-3410-12-512-paramSetTest",
+   "id-tc26-gost-3410-12-512-paramSetTest",
+   NID_id_tc26_gost_3410_12_512_paramSetTest,9,&(lvalues[6345]),0},
+{"id-tc26-gost-3410-12-512-paramSetA",
+   "id-tc26-gost-3410-12-512-paramSetA",
+   NID_id_tc26_gost_3410_12_512_paramSetA,9,&(lvalues[6354]),0},
+{"id-tc26-gost-3410-12-512-paramSetB",
+   "id-tc26-gost-3410-12-512-paramSetB",
+   NID_id_tc26_gost_3410_12_512_paramSetB,9,&(lvalues[6363]),0},
+{"id-tc26-gost-28147-param-A","id-tc26-gost-28147-param-A",
+   NID_id_tc26_gost_28147_param_A,9,&(lvalues[6372]),0},
 };

 static const unsigned int sn_objs[NUM_SN]={
@@ -2877,6 +2920,8 @@ static const unsigned int sn_objs[NUM_SN]={
 815,   /* "gost-mac" */
 811,   /* "gost2001" */
 851,   /* "gost2001cc" */
+963,   /* "gost2012_256" */
+964,   /* "gost2012_512" */
 813,   /* "gost89" */
 814,   /* "gost89-cnt" */
 812,   /* "gost94" */
@@ -3132,6 +3177,16 @@ static const unsigned int sn_objs[NUM_SN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+969,   /* "id-tc26-agreement-gost-3410-12-256" */
+970,   /* "id-tc26-agreement-gost-3410-12-512" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
+967,   /* "id-tc26-hmac-gost-3411-12-256" */
+968,   /* "id-tc26-hmac-gost-3411-12-512" */
+965,   /* "id-tc26-signwithdigest-gost3410-12-256" */
+966,   /* "id-tc26-signwithdigest-gost3410-12-512" */
 676,   /* "identified-organization" */
 461,   /* "info" */
 748,   /* "inhibitAnyPolicy" */
@@ -3521,6 +3576,10 @@ static const unsigned int ln_objs[NUM_LN]={
 850,   /* "GOST 34.10-94 Cryptocom" */
 811,   /* "GOST R 34.10-2001" */
 817,   /* "GOST R 34.10-2001 DH" */
+963,   /* "GOST R 34.10-2012 with 256-bit key" */
+965,   /* "GOST R 34.10-2012 with 34.11-2012 256-bit" */
+966,   /* "GOST R 34.10-2012 with 34.11-2012 512-bit" */
+964,   /* "GOST R 34.10-2012 with 512-bit key" */
 812,   /* "GOST R 34.10-94" */
 818,   /* "GOST R 34.10-94 DH" */
 961,   /* "GOST R 34.11-2012 256-bit length" */
@@ -3533,6 +3592,8 @@ static const unsigned int ln_objs[NUM_LN]={
 852,   /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
 854,   /* "GOST R 3410-2001 Parameter Set Cryptocom" */
 810,   /* "HMAC GOST 34.11-94" */
+967,   /* "HMAC GOST R 34.11-2012 L=32 B=64" */
+968,   /* "HMAC GOST R 34.11-2012 L=64 B=64" */
 432,   /* "Hold Instruction Call Issuer" */
 430,   /* "Hold Instruction Code" */
 431,   /* "Hold Instruction None" */
@@ -3547,6 +3608,8 @@ static const unsigned int ln_objs[NUM_LN]={
 665,   /* "Inherit all" */
 647,   /* "International Organizations" */
 142,   /* "Invalidity Date" */
+969,   /* "Key agreement schemes GOST R 34.10-2012 256-bit key" */
+970,   /* "Key agreement schemes GOST R 34.10-2012 512-bit key" */
 504,   /* "MIME MHS" */
 388,   /* "Mail" */
 383,   /* "Management" */
@@ -4075,6 +4138,10 @@ static const unsigned int ln_objs[NUM_LN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
 34,    /* "idea-cbc" */
 35,    /* "idea-cfb" */
 36,    /* "idea-ecb" */
@@ -4870,8 +4937,16 @@ static const unsigned int obj_objs[NUM_OBJ]={
 851,   /* OBJ_id_GostR3410_2001_cc         1 2 643 2 9 1 5 4 */
 849,   /* OBJ_id_Gost28147_89_cc           1 2 643 2 9 1 6 1 */
 854,   /* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
+963,   /* OBJ_id_tc26_gost3410_12_256      1 2 643 7 1 1 1 1 */
+964,   /* OBJ_id_tc26_gost3410_12_512      1 2 643 7 1 1 1 2 */
 961,   /* OBJ_id_tc26_gost3411_12_256      1 2 643 7 1 1 2 2 */
 962,   /* OBJ_id_tc26_gost3411_12_512      1 2 643 7 1 1 2 3 */
+965,   /* OBJ_id_tc26_signwithdigest_gost3410_12_256 1 2 643 7 1 1 3 2 */
+966,   /* OBJ_id_tc26_signwithdigest_gost3410_12_512 1 2 643 7 1 1 3 3 */
+967,   /* OBJ_id_tc26_hmac_gost_3411_12_256 1 2 643 7 1 1 4 1 */
+968,   /* OBJ_id_tc26_hmac_gost_3411_12_512 1 2 643 7 1 1 4 2 */
+969,   /* OBJ_id_tc26_agreement_gost_3410_12_256 1 2 643 7 1 1 6 1 */
+970,   /* OBJ_id_tc26_agreement_gost_3410_12_512 1 2 643 7 1 1 6 2 */
 186,   /* OBJ_pkcs1                        1 2 840 113549 1 1 */
 27,    /* OBJ_pkcs3                        1 2 840 113549 1 3 */
 187,   /* OBJ_pkcs5                        1 2 840 113549 1 5 */
@@ -5039,6 +5114,10 @@ static const unsigned int obj_objs[NUM_OBJ]={
 439,   /* OBJ_pilotAttributeSyntax         0 9 2342 19200300 100 3 */
 440,   /* OBJ_pilotObjectClass             0 9 2342 19200300 100 4 */
 441,   /* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
+971,   /* OBJ_id_tc26_gost_3410_12_512_paramSetTest 1 2 643 7 1 2 1 2 0 */
+972,   /* OBJ_id_tc26_gost_3410_12_512_paramSetA 1 2 643 7 1 2 1 2 1 */
+973,   /* OBJ_id_tc26_gost_3410_12_512_paramSetB 1 2 643 7 1 2 1 2 2 */
+974,   /* OBJ_id_tc26_gost_28147_param_A   1 2 643 7 1 2 5 1 1 */
 108,   /* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
 112,   /* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
 782,   /* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h
index 70f41d2..c88ae68 100644
--- a/crypto/objects/obj_mac.h
+++ b/crypto/objects/obj_mac.h
@@ -3748,6 +3748,16 @@
 #define NID_id_Gost28147_89_None_KeyMeshing        820
 #define OBJ_id_Gost28147_89_None_KeyMeshing        OBJ_cryptopro,14L,0L

+#define SN_id_tc26_gost3410_12_256     "gost2012_256"
+#define LN_id_tc26_gost3410_12_256     "GOST R 34.10-2012 with 256-bit key"
+#define NID_id_tc26_gost3410_12_256        963
+#define OBJ_id_tc26_gost3410_12_256        OBJ_tc_26,1L,1L,1L
+
+#define SN_id_tc26_gost3410_12_512     "gost2012_512"
+#define LN_id_tc26_gost3410_12_512     "GOST R 34.10-2012 with 512-bit key"
+#define NID_id_tc26_gost3410_12_512        964
+#define OBJ_id_tc26_gost3410_12_512        OBJ_tc_26,1L,1L,2L
+
 #define SN_id_tc26_gost3411_12_256     "md_gost12_256"
 #define LN_id_tc26_gost3411_12_256     "GOST R 34.11-2012 256-bit length"
 #define NID_id_tc26_gost3411_12_256        961
@@ -3758,6 +3768,36 @@
 #define NID_id_tc26_gost3411_12_512        962
 #define OBJ_id_tc26_gost3411_12_512        OBJ_tc_26,1L,2L,3L

+#define SN_id_tc26_signwithdigest_gost3410_12_256      "id-tc26-signwithdigest-gost3410-12-256"
+#define LN_id_tc26_signwithdigest_gost3410_12_256      "GOST R 34.10-2012 with 34.11-2012 256-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_256     965
+#define OBJ_id_tc26_signwithdigest_gost3410_12_256     OBJ_tc_26,1L,3L,2L
+
+#define SN_id_tc26_signwithdigest_gost3410_12_512      "id-tc26-signwithdigest-gost3410-12-512"
+#define LN_id_tc26_signwithdigest_gost3410_12_512      "GOST R 34.10-2012 with 34.11-2012 512-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_512     966
+#define OBJ_id_tc26_signwithdigest_gost3410_12_512     OBJ_tc_26,1L,3L,3L
+
+#define SN_id_tc26_hmac_gost_3411_12_256       "id-tc26-hmac-gost-3411-12-256"
+#define LN_id_tc26_hmac_gost_3411_12_256       "HMAC GOST R 34.11-2012 L=32 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_256      967
+#define OBJ_id_tc26_hmac_gost_3411_12_256      OBJ_tc_26,1L,4L,1L
+
+#define SN_id_tc26_hmac_gost_3411_12_512       "id-tc26-hmac-gost-3411-12-512"
+#define LN_id_tc26_hmac_gost_3411_12_512       "HMAC GOST R 34.11-2012 L=64 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_512      968
+#define OBJ_id_tc26_hmac_gost_3411_12_512      OBJ_tc_26,1L,4L,2L
+
+#define SN_id_tc26_agreement_gost_3410_12_256      "id-tc26-agreement-gost-3410-12-256"
+#define LN_id_tc26_agreement_gost_3410_12_256      "Key agreement schemes GOST R 34.10-2012 256-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_256     969
+#define OBJ_id_tc26_agreement_gost_3410_12_256     OBJ_tc_26,1L,6L,1L
+
+#define SN_id_tc26_agreement_gost_3410_12_512      "id-tc26-agreement-gost-3410-12-512"
+#define LN_id_tc26_agreement_gost_3410_12_512      "Key agreement schemes GOST R 34.10-2012 512-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_512     970
+#define OBJ_id_tc26_agreement_gost_3410_12_512     OBJ_tc_26,1L,6L,2L
+
 #define SN_id_GostR3411_94_TestParamSet        "id-GostR3411-94-TestParamSet"
 #define NID_id_GostR3411_94_TestParamSet       821
 #define OBJ_id_GostR3411_94_TestParamSet       OBJ_cryptopro,30L,0L
@@ -3870,6 +3910,22 @@
 #define NID_id_GostR3410_94_bBis       848
 #define OBJ_id_GostR3410_94_bBis       OBJ_id_GostR3410_94,4L

+#define SN_id_tc26_gost_3410_12_512_paramSetTest       "id-tc26-gost-3410-12-512-paramSetTest"
+#define NID_id_tc26_gost_3410_12_512_paramSetTest      971
+#define OBJ_id_tc26_gost_3410_12_512_paramSetTest      OBJ_tc_26,2L,1L,2L,0L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetA      "id-tc26-gost-3410-12-512-paramSetA"
+#define NID_id_tc26_gost_3410_12_512_paramSetA     972
+#define OBJ_id_tc26_gost_3410_12_512_paramSetA     OBJ_tc_26,2L,1L,2L,1L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetB      "id-tc26-gost-3410-12-512-paramSetB"
+#define NID_id_tc26_gost_3410_12_512_paramSetB     973
+#define OBJ_id_tc26_gost_3410_12_512_paramSetB     OBJ_tc_26,2L,1L,2L,2L
+
+#define SN_id_tc26_gost_28147_param_A      "id-tc26-gost-28147-param-A"
+#define NID_id_tc26_gost_28147_param_A     974
+#define OBJ_id_tc26_gost_28147_param_A     OBJ_tc_26,2L,5L,1L,1L
+
 #define SN_id_Gost28147_89_cc      "id-Gost28147-89-cc"
 #define LN_id_Gost28147_89_cc      "GOST 28147-89 Cryptocom ParamSet"
 #define NID_id_Gost28147_89_cc     849
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 0010bf8..d65d512 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -960,3 +960,15 @@ md_gost12_256      959
 md_gost12_512      960
 id_tc26_gost3411_12_256        961
 id_tc26_gost3411_12_512        962
+id_tc26_gost3410_12_256        963
+id_tc26_gost3410_12_512        964
+id_tc26_signwithdigest_gost3410_12_256     965
+id_tc26_signwithdigest_gost3410_12_512     966
+id_tc26_hmac_gost_3411_12_256      967
+id_tc26_hmac_gost_3411_12_512      968
+id_tc26_agreement_gost_3410_12_256     969
+id_tc26_agreement_gost_3410_12_512     970
+id_tc26_gost_3410_12_512_paramSetTest      971
+id_tc26_gost_3410_12_512_paramSetA     972
+id_tc26_gost_3410_12_512_paramSetB     973
+id_tc26_gost_28147_param_A     974
diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h
index cfd628a..4bebb0d 100644
--- a/crypto/objects/obj_xref.h
+++ b/crypto/objects/obj_xref.h
@@ -49,13 +49,15 @@ static const nid_triple sigoid_srt[] =
    {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf},
+   {NID_id_tc26_signwithdigest_gost3410_12_256, NID_id_tc26_gost3411_12_256, NID_id_tc26_gost3410_12_256},
+   {NID_id_tc26_signwithdigest_gost3410_12_512, NID_id_tc26_gost3411_12_512, NID_id_tc26_gost3410_12_512},
    };

 static const nid_triple * const sigoid_srt_xref[] =
    {
    &sigoid_srt[29],
-   &sigoid_srt[17],
    &sigoid_srt[18],
+   &sigoid_srt[17],
    &sigoid_srt[0],
    &sigoid_srt[1],
    &sigoid_srt[7],
@@ -93,5 +95,7 @@ static const nid_triple * const sigoid_srt_xref[] =
    &sigoid_srt[26],
    &sigoid_srt[27],
    &sigoid_srt[28],
+   &sigoid_srt[40],
+   &sigoid_srt[41],
    };

diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt
index 19c9422..094a204 100644
--- a/crypto/objects/obj_xref.txt
+++ b/crypto/objects/obj_xref.txt
@@ -44,6 +44,8 @@ id_GostR3411_94_with_GostR3410_2001   id_GostR3411_94 id_GostR3410_2001
 id_GostR3411_94_with_GostR3410_94  id_GostR3411_94 id_GostR3410_94
 id_GostR3411_94_with_GostR3410_94_cc   id_GostR3411_94 id_GostR3410_94_cc
 id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc
+id_tc26_signwithdigest_gost3410_12_256 id_tc26_gost3411_12_256 id_tc26_gost3410_12_256
+id_tc26_signwithdigest_gost3410_12_512 id_tc26_gost3411_12_512 id_tc26_gost3410_12_512
 # ECDH KDFs and their corresponding message digests and schemes
 dhSinglePass_stdDH_sha1kdf_scheme      sha1    dh_std_kdf
 dhSinglePass_stdDH_sha224kdf_scheme        sha224  dh_std_kdf
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index a61f8d7..bc4f56c 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1181,10 +1181,20 @@ cryptopro 14 1      : id-Gost28147-89-CryptoPro-KeyMeshing
 cryptopro 14 0     : id-Gost28147-89-None-KeyMeshing

 # TC-26 GOST OIDs
+!Cname id-tc26-gost3410-12-256
+tc-26 1 1 1  : gost2012_256 : GOST R 34.10-2012 with 256-bit key
+!Cname id-tc26-gost3410-12-512
+tc-26 1 1 2  : gost2012_512 : GOST R 34.10-2012 with 512-bit key
 !Cname id-tc26-gost3411-12-256
 tc-26 1 2 2  : md_gost12_256 : GOST R 34.11-2012 256-bit length
 !Cname id-tc26-gost3411-12-512
 tc-26 1 2 3  : md_gost12_512 : GOST R 34.11-2012 512-bit length
+tc-26 1 3 2  : id-tc26-signwithdigest-gost3410-12-256 : GOST R 34.10-2012 with 34.11-2012 256-bit
+tc-26 1 3 3  : id-tc26-signwithdigest-gost3410-12-512 : GOST R 34.10-2012 with 34.11-2012 512-bit
+tc-26 1 4 1  : id-tc26-hmac-gost-3411-12-256 : HMAC GOST R 34.11-2012 L=32 B=64
+tc-26 1 4 2  : id-tc26-hmac-gost-3411-12-512 : HMAC GOST R 34.11-2012 L=64 B=64
+tc-26 1 6 1     : id-tc26-agreement-gost-3410-12-256 : Key agreement schemes GOST R 34.10-2012 256-bit key
+tc-26 1 6 2  : id-tc26-agreement-gost-3410-12-512 :    Key agreement schemes GOST R 34.10-2012 512-bit key

 # GOST parameter set OIDs

@@ -1223,6 +1233,13 @@ id-GostR3410-94 2    : id-GostR3410-94-aBis
 id-GostR3410-94 3  : id-GostR3410-94-b
 id-GostR3410-94 4  : id-GostR3410-94-bBis

+# TC-26 GOST parameter set OIDs
+
+tc-26 2 1 2 0      : id-tc26-gost-3410-12-512-paramSetTest
+tc-26 2 1 2 1      : id-tc26-gost-3410-12-512-paramSetA
+tc-26 2 1 2 2      : id-tc26-gost-3410-12-512-paramSetB
+tc-26 2 5 1 1       : id-tc26-gost-28147-param-A
+
 # Cryptocom LTD GOST OIDs

 cryptocom 1 6 1        : id-Gost28147-89-cc    : GOST 28147-89 Cryptocom ParamSet
diff --git a/engines/ccgost/README.gost b/engines/ccgost/README.gost
index b8eb56e..000774f 100644
--- a/engines/ccgost/README.gost
+++ b/engines/ccgost/README.gost
@@ -14,7 +14,12 @@ GOST R 34.10-94 and GOST R 34.10-2001 - digital signature algorithms.
    256 bit private keys. Public keys are 1024 bit for 94 and 512 bit for
    2001 (which is elliptic-curve based). Key exchange algorithms
    (VKO R 34.10) are supported on these keys too.
-
+
+GOST R 34.10-2012 - digital signature algorithm.
+   Consists of 2 versions with 256 bit and 512 bit private keys.
+   Both are based on elliptic curve and have public keys of 512 bit
+   and 1024 bit respectively.
+
 GOST R 34.11-94  Message digest algorithm. 256-bit hash value

 GOST R 34.11-2012 Message digest algorithm. Has versions with
@@ -108,6 +113,8 @@ USAGE WITH COMMAND LINE openssl UTILITY
   are supported by
    gost94: 0,A,B,C,D,XA,XB,XC
    gost2001: 0,A,B,C,XA,XB
+        gost2012-256: 0,A,B,C,XA,XB
+        gost2012-512: A,B
   You can also use numeric representation of OID as to destinate
   paramset.

diff --git a/engines/ccgost/gost2001.c b/engines/ccgost/gost2001.c
index dacd82d..bbc52be 100644
--- a/engines/ccgost/gost2001.c
+++ b/engines/ccgost/gost2001.c
@@ -31,14 +31,12 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig);
  * Also fils DSA->q field with copy of EC_GROUP order field to make
  * DSA_size function work
  */
-int fill_GOST2001_params(EC_KEY *eckey, int nid)
+void fill_GOST_EC_params(EC_KEY *eckey, R3410_2001_params *params)
    {
-   R3410_2001_params *params = R3410_2001_paramset;
    EC_GROUP *grp=NULL;
    BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL;
    EC_POINT *P=NULL;
    BN_CTX *ctx=BN_CTX_new();
-   int ok=0;

    BN_CTX_start(ctx);
    p=BN_CTX_get(ctx);
@@ -47,12 +45,6 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    x=BN_CTX_get(ctx);
    y=BN_CTX_get(ctx);
    q=BN_CTX_get(ctx);
-   while (params->nid!=NID_undef && params->nid != nid) params++;
-   if (params->nid == NID_undef)
-       {
-       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
-       goto err;
-       }
    BN_hex2bn(&p,params->p);
    BN_hex2bn(&a,params->a);
    BN_hex2bn(&b,params->b);
@@ -76,15 +68,44 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    EC_GROUP_set_curve_name(grp,params->nid);

    EC_KEY_set_group(eckey,grp);
-   ok=1;
-   err:
    EC_POINT_free(P);
    EC_GROUP_free(grp);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
-   return ok;
-   }
+   }

+int fill_GOST2001_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2001_paramset;
+
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }
+
+// paramset selection is exactly the same
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid)
+   {
+   return fill_GOST2001_params(eckey, nid);
+   }
+
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2012_512_paramset;
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }

 /*
  * Computes gost2001 signature as DSA_SIG structure
@@ -94,7 +115,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
 DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    {
    DSA_SIG *newsig = NULL;
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    BIGNUM *order = NULL;
    const EC_GROUP *group;
    const BIGNUM *priv_key;
@@ -102,7 +123,7 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    EC_POINT *C=NULL;
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);
-   OPENSSL_assert(dlen==32);
+   OPENSSL_assert(dlen==32 || dlen==64);
    newsig=DSA_SIG_new();
    if (!newsig)
        {
@@ -212,7 +233,7 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
        goto err;

        }
-   md = hashsum2bn(dgst);
+   md = hashsum2bn(dgst,dgst_len);

    BN_mod(e,md,order,ctx);
 #ifdef DEBUG_SIGN
diff --git a/engines/ccgost/gost_ameth.c b/engines/ccgost/gost_ameth.c
index 2cde1fc..4293bf1 100644
--- a/engines/ccgost/gost_ameth.c
+++ b/engines/ccgost/gost_ameth.c
@@ -20,6 +20,22 @@
 #include "gost_lcl.h"
 #include "e_gost_err.h"

+static int md_nid_by_pmeth_nid(int pmeth_nid)
+{
+   switch(pmeth_nid)
+   {
+   case NID_id_GostR3410_94:
+   case NID_id_GostR3410_2001:
+       return NID_id_GostR3411_94;
+   case NID_id_tc26_gost3410_12_256:
+       return NID_id_tc26_gost3411_12_256;
+   case NID_id_tc26_gost3410_12_512:
+       return NID_id_tc26_gost3411_12_512;
+   default:
+       return NID_undef;
+   }
+}
+
 int gost94_nid_by_params(DSA *p)
    {
    R3410_params *gost_params;
@@ -42,6 +58,7 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
    ASN1_STRING *params = ASN1_STRING_new();
    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
    int pkey_param_nid = NID_undef;
+   int hash_param_nid = NID_undef;

    if (!params || !gkp)
        {
@@ -55,6 +72,15 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
        {
        case NID_id_GostR3410_2001:
            pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
+           break;
+       case NID_id_tc26_gost3410_12_256:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_256;
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_512;
            break;
        case NID_id_GostR3410_94:
            pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
@@ -65,11 +91,12 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
                ASN1_STRING_free(params);
                params=NULL;
                goto err;
-               }
+               }
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
            break;
        }
    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
-   gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
+   gkp->hash_params = OBJ_nid2obj(hash_param_nid);
    /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
    if (params->length <=0 )
@@ -143,6 +170,29 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
            }
        if (!fill_GOST2001_params(ec,param_nid)) return 0;
        }
+       break;
+       case NID_id_tc26_gost3410_12_256:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_256_params(ec,param_nid)) return 0;
+       }
+       break;
+       case NID_id_tc26_gost3410_12_512:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_512_params(ec,param_nid)) return 0;
+       }
+       break;
        }

    return 1;
@@ -166,6 +216,8 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
        break;
        }
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0(pkey);
        if (!ec)
@@ -197,6 +249,8 @@ BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey)
        break;
        }
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
        const BIGNUM* priv;
@@ -224,7 +278,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2,
                    NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -241,7 +295,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
                    NULL, NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -282,7 +336,10 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
            return 1;
 #endif
        case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
-           *(int *)arg2 = NID_id_GostR3411_94;
+           {
+           int nid = EVP_PKEY_base_id(pkey);
+           *(int *)arg2 = md_nid_by_pmeth_nid(nid);
+           }
            return 2;
        }

@@ -824,6 +881,16 @@ static int pkey_bits_gost(const EVP_PKEY *pk)
    {
    return 256;
    }
+
+static int pkey_size_gost_512(const EVP_PKEY *pk)
+   {
+   return 128;
+   }
+
+static int pkey_bits_gost_512(const EVP_PKEY *pk)
+   {
+   return 512;
+   }
 /*------------------------ ASN1 METHOD for GOST MAC  -------------------*/
 static void  mackey_free_gost(EVP_PKEY *pk)
    {
@@ -872,7 +939,8 @@ static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int d
    return 1;
 }

-static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+//generic version for all EC-based GOST 34.10: 2001, 2012-256, 2012-512
+static int gost_ec_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen, void (*fill_params(EC_KEY*,int)), int meth_nid) {
    ASN1_OBJECT *obj=NULL;
    int nid;
    EC_KEY *ec = EVP_PKEY_get0(pkey);
@@ -884,15 +952,23 @@ static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int
    if (!ec)
        {
        ec = EC_KEY_new();
-       if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
+       if (!EVP_PKEY_assign(pkey,meth_nid,ec)) return 0;
        }
-   if (!fill_GOST2001_params(ec, nid)) return 0;
+   if (!fill_params(ec, nid)) return 0;
    return 1;
 }

+static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2001_params, NID_id_GostR3410_2001);
+}

+static int gost2012_256_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_256_params, NID_id_tc26_gost3410_12_256);
+}

-
+static int gost2012_512_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_512_params, NID_id_tc26_gost3410_12_512);
+}

 /* ----------------------------------------------------------------------*/
 int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
@@ -936,6 +1012,40 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems

            EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_256_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost, pkey_bits_gost);
+
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_512_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost_512, pkey_bits_gost_512);
+
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
            EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);
diff --git a/engines/ccgost/gost_eng.c b/engines/ccgost/gost_eng.c
index dc6bd72..977b5b3 100644
--- a/engines/ccgost/gost_eng.c
+++ b/engines/ccgost/gost_eng.c
@@ -40,15 +40,20 @@ static int gost_digest_nids[] =
     NID_id_tc26_gost3411_12_256,NID_id_tc26_gost3411_12_512,0};

 static int gost_pkey_meth_nids[] =
-   {NID_id_GostR3410_94,
-    NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
+   {NID_id_GostR3410_94, NID_id_GostR3410_2001,
+    NID_id_tc26_gost3410_12_256,NID_id_tc26_gost3410_12_512,
+    NID_id_Gost28147_89_MAC, 0};

 static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
-    *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2012_256 = NULL,
+   *pmeth_GostR3410_2012_512 = NULL,
    *pmeth_Gost28147_MAC = NULL;

 static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
    *ameth_GostR3410_2001 = NULL,
+   *ameth_GostR3410_2012_256 = NULL,
+   *ameth_GostR3410_2012_512 = NULL,
    *ameth_Gost28147_MAC = NULL;


@@ -68,9 +73,13 @@ static int gost_engine_destroy(ENGINE *e)

    pmeth_GostR3410_94 = NULL;
    pmeth_GostR3410_2001 = NULL;
+   pmeth_GostR3410_2012_256 = NULL;
+   pmeth_GostR3410_2012_512 = NULL;
    pmeth_Gost28147_MAC = NULL;
    ameth_GostR3410_94 = NULL;
    ameth_GostR3410_2001 = NULL;
+   ameth_GostR3410_2012_256 = NULL;
+   ameth_GostR3410_2012_512 = NULL;
    ameth_Gost28147_MAC = NULL;
    return 1;
    }
@@ -130,11 +139,17 @@ static int bind_gost (ENGINE *e,const char *id)

    if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
    if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_256, &ameth_GostR3410_2012_256,
+       "GOST2012-256", "GOST R 34.10-2012 256bit")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_512, &ameth_GostR3410_2012_512,
+       "GOST2012-512", "GOST R 34.10-2012 512bit")) goto end;
    if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
        "GOST-MAC", "GOST 28147-89 MAC")) goto end;

    if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
    if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_256, &pmeth_GostR3410_2012_256, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_512, &pmeth_GostR3410_2012_512, 0)) goto end;
    if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
        goto end;
    if ( ! ENGINE_register_ciphers(e)
@@ -229,7 +244,7 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
    if (!pmeth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }

    switch (nid)
@@ -237,6 +252,8 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
        case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1;
+       case NID_id_tc26_gost3410_12_256: *pmeth = pmeth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *pmeth = pmeth_GostR3410_2012_512; return 1;
        default:;
        }

@@ -247,17 +264,19 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
 static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
    const int **nids, int nid)
    {
+
    if (!ameth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }
    switch (nid)
        {
        case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1;
-
+       case NID_id_tc26_gost3410_12_256: *ameth = ameth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *ameth = ameth_GostR3410_2012_512; return 1;
        default:;
        }

diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h
index 90c262d..7d0b526 100644
--- a/engines/ccgost/gost_lcl.h
+++ b/engines/ccgost/gost_lcl.h
@@ -185,6 +185,8 @@ int pkey_gost94_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
 /* Internal functions for signature algorithms */
 int fill_GOST94_params(DSA *dsa,int nid);
 int fill_GOST2001_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid);
 int gost_sign_keygen(DSA *dsa) ;
 int gost2001_keygen(EC_KEY *ec) ;

@@ -200,7 +202,7 @@ int gost94_compute_public(DSA *dsa) ;
 /*============== miscellaneous functions============================= */
 /* from gost_sign.c */
 /* Convert GOST R 34.11 hash sum to bignum according to standard */
-BIGNUM *hashsum2bn(const unsigned char *dgst) ;
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen) ;
 /* Store bignum in byte array of given length, prepending by zeros
  * if nesseccary */
 int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
diff --git a/engines/ccgost/gost_params.c b/engines/ccgost/gost_params.c
index 40fc343..6fcb3dc 100644
--- a/engines/ccgost/gost_params.c
+++ b/engines/ccgost/gost_params.c
@@ -196,3 +196,42 @@ R3410_2001_params R3410_2001_paramset[]={
    { 0,NULL,NULL,NULL,NULL,NULL,NULL
    }
 };
+
+R3410_2001_params R3410_2012_512_paramset[]={
+   /*1.2.643.7.1.2.1.2.1*/
+   {NID_id_tc26_gost_3410_12_512_paramSetA,
+   /* A */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",
+   /* B */
+   "E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265"
+"EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",
+   /* P */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",
+   /* Q */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2"
+"7E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",
+   /* X */
+   "3",
+   /* Y */
+   "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921D"
+"F1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4"
+   },
+   /*1.2.643.7.1.2.1.2.2*/
+   {NID_id_tc26_gost_3410_12_512_paramSetB,
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006C",
+   "687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3"
+"E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006F",
+   "80000000000000000000000000000000000000000000000000000000000000014"
+"9A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",
+   "2",
+   "1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335D"
+"CB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD"
+   },
+   { 0,NULL,NULL,NULL,NULL,NULL,NULL
+   }
+};
\ No newline at end of file
diff --git a/engines/ccgost/gost_params.h b/engines/ccgost/gost_params.h
index 4c3f556..3a1c6e0 100644
--- a/engines/ccgost/gost_params.h
+++ b/engines/ccgost/gost_params.h
@@ -30,5 +30,6 @@ typedef struct R3410_2001 {
 } R3410_2001_params;

 extern R3410_2001_params R3410_2001_paramset[];
+extern R3410_2001_params R3410_2012_512_paramset[];

 #endif
diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c
index 3189798..f73cae5 100644
--- a/engines/ccgost/gost_pmeth.c
+++ b/engines/ccgost/gost_pmeth.c
@@ -33,6 +33,8 @@ static int pkey_gost_init(EVP_PKEY_CTX *ctx)
          data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey));
          break;
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
           data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
        break;
        default:
@@ -54,9 +56,10 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
    src_data = EVP_PKEY_CTX_get_data(src);
    dst_data = EVP_PKEY_CTX_get_data(dst);
    *dst_data = *src_data;
-   if (src_data -> shared_ukm) {
+   if (src_data->shared_ukm)
+       {
        dst_data->shared_ukm=NULL;
-   }
+       }
    return 1;
    }

@@ -72,11 +75,17 @@ static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
    {
    struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
+   int base_id;
+   int md_type;
    switch (type)
        {
        case EVP_PKEY_CTRL_MD:
        {
-       if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
+       base_id = EVP_PKEY_base_id(EVP_PKEY_CTX_get0_pkey(ctx));
+       md_type = EVP_MD_type((const EVP_MD *)p2);
+       if (((base_id == NID_id_GostR3410_94 || base_id == NID_id_GostR3410_2001) && md_type != NID_id_GostR3411_94)
+           || (base_id == NID_id_tc26_gost3410_12_256 && md_type != NID_id_tc26_gost3411_12_256)
+           || (base_id == NID_id_tc26_gost3410_12_512 && md_type != NID_id_tc26_gost3411_12_512))
            {
            GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
            return 0;
@@ -268,6 +277,63 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
    return -2;
    }

+static int pkey_gost_ctrl12_256_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+{
+   return pkey_gost_ctrl01_str(ctx, type, value);
+}
+
+static int pkey_gost_ctrl12_512_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+   {
+   int param_nid=0;
+   printf("CTL %s %s \n", type, value);
+   if(!strcmp(type, param_ctrl_string))
+       {
+       if (!value)
+           {
+           return 0;
+           }
+       if (strlen(value) == 1)
+           {
+           switch(toupper((unsigned char)value[0]))
+               {
+               case 'A':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetA;
+                   break;
+               case 'B':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetB;
+                   break;
+               default:
+                   return 0;
+                   break;
+               }
+           }
+       else
+           {
+           R3410_2001_params *p = R3410_2012_512_paramset;
+           param_nid = OBJ_txt2nid(value);
+           if (param_nid == NID_undef)
+               {
+               return 0;
+               }
+           for (;p->nid != NID_undef;p++)
+               {
+               if (p->nid == param_nid) break;
+               }
+           if (p->nid == NID_undef)
+               {
+               GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
+                   GOST_R_INVALID_PARAMSET);
+               return 0;
+               }
+           }
+
+       return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
+           param_nid, NULL);
+       }
+   return -2;
+   }
 /* --------------------- key generation  --------------------------------*/

 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) {
@@ -303,8 +369,11 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
                GOST_R_NO_PARAMETERS_SET);
            return 0;
        }
-   if (!ec)
+   if (!ec)
+       {
        ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
    if (!fill_GOST2001_params(ec,data->sign_param_nid))
        {
        EC_KEY_free(ec);
@@ -314,6 +383,54 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }

+static int pkey_gost12_256_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)
+       {
+       ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
+   if (!fill_GOST2012_256_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_256,ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)
+       ec = EC_KEY_new();
+   if(!fill_GOST2012_512_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_512,ec);
+   return 1;
+   }
+
 /* Generates Gost_R3410_94_cp key */
 static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    {
@@ -334,6 +451,23 @@ static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }

+static int pkey_gost12_256_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_256_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_512_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }


 /* ----------- sign callbacks --------------------------------------*/
@@ -363,17 +497,25 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
    DSA_SIG *unpacked_sig=NULL;
    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
    if (!siglen) return 0;
+   // GOST-2012 signature can be 512 or 1024 bits long
+   const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0(pkey));
+
+   int pkey_len = EC_GROUP_get_degree(group)/8;
    if (!sig)
        {
-       *siglen= 64; /* better to check size of curve order*/
+       *siglen = pkey_len*2;
        return 1;
        }
+   if (tbs_len != pkey_len)
+       {
+       return 0;
+       }
    unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
    if (!unpacked_sig)
        {
        return 0;
        }
-   return pack_sign_cp(unpacked_sig,32,sig,siglen);
+   return pack_sign_cp(unpacked_sig,pkey_len,sig,siglen);
    }

 /* ------------------- verify callbacks ---------------------------*/
@@ -600,7 +742,7 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost94_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost94_paramgen);
            break;
-       case NID_id_GostR3410_2001:
+       case NID_id_GostR3410_2001:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
            EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
            EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
@@ -614,6 +756,34 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost2001_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost01_paramgen);
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_256_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_256_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_256_paramgen);
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_512_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_512_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_512_paramgen);
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
            EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
diff --git a/engines/ccgost/gost_sign.c b/engines/ccgost/gost_sign.c
index 4095654..3f3902c 100644
--- a/engines/ccgost/gost_sign.c
+++ b/engines/ccgost/gost_sign.c
@@ -52,7 +52,7 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
    {
    BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
    DSA_SIG *newsig = DSA_SIG_new();
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    /* check if H(M) mod q is zero */
    BN_CTX *ctx=BN_CTX_new();
    BN_CTX_start(ctx);
@@ -149,7 +149,7 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len,
        GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
        return 0;
        }
-   md=hashsum2bn(dgst);
+   md=hashsum2bn(dgst,dgst_len);

    tmp=BN_CTX_get(ctx);
    v=BN_CTX_get(ctx);
@@ -279,15 +279,16 @@ DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
    }

 /* Convert little-endian byte array into bignum */
-BIGNUM *hashsum2bn(const unsigned char *dgst)
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen)
    {
-   unsigned char buf[32];
+   unsigned char buf[64];
    int i;
-   for (i=0;i<32;i++)
+    OPENSSL_assert(dlen==32 || dlen == 64);
+   for (i=0;i<dlen;i++)
        {
-       buf[31-i]=dgst[i];
+       buf[dlen-1-i]=dgst[i];
        }
-   return getbnfrombuf(buf,32);
+   return getbnfrombuf(buf,dlen);
    }

 /* Convert byte buffer to bignum, skipping leading zeros*/


Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Dmitry Olshansky-2
23-Apr-2014 20:48, Billy Brumley пишет:
> Please read CVE-2011-1945. You need to propagate the fix in
> gost2001_do_sign. If you're unsure, check the comments in
> crypto/ecdsa/ecs_ossl.c.
>
I see the place you refer to. What I can't quite get in this piece is
adding `order` 2 times. Shouldn't the first BN_add get us where we want
(that is a number as wide as `order`)?

     /* We do not want timing information to leak the length of k,
          * so we compute G*k using an equivalent scalar of fixed
          * bit-length. */

         if (!BN_add(k, k, order)) goto err;  //<---here I would expect
k to be > order afterwards
         if (BN_num_bits(k) <= BN_num_bits(order)) // then this is
trivially false?
             if (!BN_add(k, k, order)) goto err;  //and this should not
even be reached?
...

> BBB
>
>


--
Dmitry Olshansky
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Billy Brumley

Say order is m bits. Then k+order is either m or m+1 bits. The condition fixes it at m+1. (You're right that for most standardized curves the branch is either negligibly taken or overwhelmingly taken, depending on what the order looks like.)

BBB

On Apr 23, 2014 12:52 PM, "Dmitry Olshansky" <[hidden email]> wrote:
23-Apr-2014 20:48, Billy Brumley пишет:
Please read CVE-2011-1945. You need to propagate the fix in gost2001_do_sign. If you're unsure, check the comments in crypto/ecdsa/ecs_ossl.c.

I see the place you refer to. What I can't quite get in this piece is adding `order` 2 times. Shouldn't the first BN_add get us where we want (that is a number as wide as `order`)?

    /* We do not want timing information to leak the length of k,
         * so we compute G*k using an equivalent scalar of fixed
         * bit-length. */

        if (!BN_add(k, k, order)) goto err;  //<---here I would expect k to be > order afterwards
        if (BN_num_bits(k) <= BN_num_bits(order)) // then this is trivially false?
            if (!BN_add(k, k, order)) goto err;  //and this should not even be reached?
...

BBB




--
Dmitry Olshansky
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Dmitry Olshansky
24-Apr-2014 00:11, Billy Brumley пишет:

Say order is m bits. Then k+order is either m or m+1 bits. The condition fixes it at m+1. (You're right that for most standardized curves the branch is either negligibly taken or overwhelmingly taken, depending on what the order looks like.)

Got it, thanks. I've incorporated analogous fix in gost2001.c

BBB

On Apr 23, 2014 12:52 PM, "Dmitry Olshansky" <[hidden email]> wrote:
23-Apr-2014 20:48, Billy Brumley пишет:
Please read CVE-2011-1945. You need to propagate the fix in gost2001_do_sign. If you're unsure, check the comments in crypto/ecdsa/ecs_ossl.c.

I see the place you refer to. What I can't quite get in this piece is adding `order` 2 times. Shouldn't the first BN_add get us where we want (that is a number as wide as `order`)?

    /* We do not want timing information to leak the length of k,
         * so we compute G*k using an equivalent scalar of fixed
         * bit-length. */

        if (!BN_add(k, k, order)) goto err;  //<---here I would expect k to be > order afterwards
        if (BN_num_bits(k) <= BN_num_bits(order)) // then this is trivially false?
            if (!BN_add(k, k, order)) goto err;  //and this should not even be reached?
...

BBB




--
Dmitry Olshansky
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [hidden email]
Automated List Manager                           [hidden email]


-- 
С уважением,
Ольшанский Дмитрий
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Rich Salz via RT
In reply to this post by Rich Salz via RT
Updated patch with a fix for CVE-2011-1945 related bug in gost2001/2012
signature.

--
Dmitry Olshansky
Systems Engineer
Demos llc.



diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index f9e422c..64134bd 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -62,12 +62,12 @@
  * [including the GNU Public Licence.]
  */
 
-#define NUM_NID 963
-#define NUM_SN 954
-#define NUM_LN 954
-#define NUM_OBJ 893
+#define NUM_NID 975
+#define NUM_SN 966
+#define NUM_LN 966
+#define NUM_OBJ 905
 
-static const unsigned char lvalues[6282]={
+static const unsigned char lvalues[6382]={
 0x00,                                        /* [  0] OBJ_undef */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  1] OBJ_rsadsi */
 0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  7] OBJ_pkcs */
@@ -961,6 +961,18 @@ static const unsigned char lvalues[6282]={
 0x2A,0x85,0x03,0x07,0x01,                    /* [6260] OBJ_tc_26 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02,     /* [6265] OBJ_id_tc26_gost3411_12_256 */
 0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03,     /* [6273] OBJ_id_tc26_gost3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01,     /* [6281] OBJ_id_tc26_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02,     /* [6289] OBJ_id_tc26_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02,     /* [6297] OBJ_id_tc26_signwithdigest_gost3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03,     /* [6305] OBJ_id_tc26_signwithdigest_gost3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01,     /* [6313] OBJ_id_tc26_hmac_gost_3411_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02,     /* [6321] OBJ_id_tc26_hmac_gost_3411_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x01,     /* [6329] OBJ_id_tc26_agreement_gost_3410_12_256 */
+0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x02,     /* [6337] OBJ_id_tc26_agreement_gost_3410_12_512 */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00,/* [6345] OBJ_id_tc26_gost_3410_12_512_paramSetTest */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01,/* [6354] OBJ_id_tc26_gost_3410_12_512_paramSetA */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02,/* [6363] OBJ_id_tc26_gost_3410_12_512_paramSetB */
+0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01,/* [6372] OBJ_id_tc26_gost_28147_param_A */
 };
 
 static const ASN1_OBJECT nid_objs[NUM_NID]={
@@ -2531,6 +2543,37 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
    NID_id_tc26_gost3411_12_256,8,&(lvalues[6265]),0},
 {"md_gost12_512","GOST R 34.11-2012 512-bit length",
    NID_id_tc26_gost3411_12_512,8,&(lvalues[6273]),0},
+{"gost2012_256","GOST R 34.10-2012 with 256-bit key",
+   NID_id_tc26_gost3410_12_256,8,&(lvalues[6281]),0},
+{"gost2012_512","GOST R 34.10-2012 with 512-bit key",
+   NID_id_tc26_gost3410_12_512,8,&(lvalues[6289]),0},
+{"id-tc26-signwithdigest-gost3410-12-256",
+   "GOST R 34.10-2012 with 34.11-2012 256-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_256,8,&(lvalues[6297]),0},
+{"id-tc26-signwithdigest-gost3410-12-512",
+   "GOST R 34.10-2012 with 34.11-2012 512-bit",
+   NID_id_tc26_signwithdigest_gost3410_12_512,8,&(lvalues[6305]),0},
+{"id-tc26-hmac-gost-3411-12-256","HMAC GOST R 34.11-2012 L=32 B=64",
+   NID_id_tc26_hmac_gost_3411_12_256,8,&(lvalues[6313]),0},
+{"id-tc26-hmac-gost-3411-12-512","HMAC GOST R 34.11-2012 L=64 B=64",
+   NID_id_tc26_hmac_gost_3411_12_512,8,&(lvalues[6321]),0},
+{"id-tc26-agreement-gost-3410-12-256",
+   "Key agreement schemes GOST R 34.10-2012 256-bit key",
+   NID_id_tc26_agreement_gost_3410_12_256,8,&(lvalues[6329]),0},
+{"id-tc26-agreement-gost-3410-12-512",
+   "Key agreement schemes GOST R 34.10-2012 512-bit key",
+   NID_id_tc26_agreement_gost_3410_12_512,8,&(lvalues[6337]),0},
+{"id-tc26-gost-3410-12-512-paramSetTest",
+   "id-tc26-gost-3410-12-512-paramSetTest",
+   NID_id_tc26_gost_3410_12_512_paramSetTest,9,&(lvalues[6345]),0},
+{"id-tc26-gost-3410-12-512-paramSetA",
+   "id-tc26-gost-3410-12-512-paramSetA",
+   NID_id_tc26_gost_3410_12_512_paramSetA,9,&(lvalues[6354]),0},
+{"id-tc26-gost-3410-12-512-paramSetB",
+   "id-tc26-gost-3410-12-512-paramSetB",
+   NID_id_tc26_gost_3410_12_512_paramSetB,9,&(lvalues[6363]),0},
+{"id-tc26-gost-28147-param-A","id-tc26-gost-28147-param-A",
+   NID_id_tc26_gost_28147_param_A,9,&(lvalues[6372]),0},
 };
 
 static const unsigned int sn_objs[NUM_SN]={
@@ -2877,6 +2920,8 @@ static const unsigned int sn_objs[NUM_SN]={
 815,   /* "gost-mac" */
 811,   /* "gost2001" */
 851,   /* "gost2001cc" */
+963,   /* "gost2012_256" */
+964,   /* "gost2012_512" */
 813,   /* "gost89" */
 814,   /* "gost89-cnt" */
 812,   /* "gost94" */
@@ -3132,6 +3177,16 @@ static const unsigned int sn_objs[NUM_SN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+969,   /* "id-tc26-agreement-gost-3410-12-256" */
+970,   /* "id-tc26-agreement-gost-3410-12-512" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
+967,   /* "id-tc26-hmac-gost-3411-12-256" */
+968,   /* "id-tc26-hmac-gost-3411-12-512" */
+965,   /* "id-tc26-signwithdigest-gost3410-12-256" */
+966,   /* "id-tc26-signwithdigest-gost3410-12-512" */
 676,   /* "identified-organization" */
 461,   /* "info" */
 748,   /* "inhibitAnyPolicy" */
@@ -3521,6 +3576,10 @@ static const unsigned int ln_objs[NUM_LN]={
 850,   /* "GOST 34.10-94 Cryptocom" */
 811,   /* "GOST R 34.10-2001" */
 817,   /* "GOST R 34.10-2001 DH" */
+963,   /* "GOST R 34.10-2012 with 256-bit key" */
+965,   /* "GOST R 34.10-2012 with 34.11-2012 256-bit" */
+966,   /* "GOST R 34.10-2012 with 34.11-2012 512-bit" */
+964,   /* "GOST R 34.10-2012 with 512-bit key" */
 812,   /* "GOST R 34.10-94" */
 818,   /* "GOST R 34.10-94 DH" */
 961,   /* "GOST R 34.11-2012 256-bit length" */
@@ -3533,6 +3592,8 @@ static const unsigned int ln_objs[NUM_LN]={
 852,   /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
 854,   /* "GOST R 3410-2001 Parameter Set Cryptocom" */
 810,   /* "HMAC GOST 34.11-94" */
+967,   /* "HMAC GOST R 34.11-2012 L=32 B=64" */
+968,   /* "HMAC GOST R 34.11-2012 L=64 B=64" */
 432,   /* "Hold Instruction Call Issuer" */
 430,   /* "Hold Instruction Code" */
 431,   /* "Hold Instruction None" */
@@ -3547,6 +3608,8 @@ static const unsigned int ln_objs[NUM_LN]={
 665,   /* "Inherit all" */
 647,   /* "International Organizations" */
 142,   /* "Invalidity Date" */
+969,   /* "Key agreement schemes GOST R 34.10-2012 256-bit key" */
+970,   /* "Key agreement schemes GOST R 34.10-2012 512-bit key" */
 504,   /* "MIME MHS" */
 388,   /* "Mail" */
 383,   /* "Management" */
@@ -4075,6 +4138,10 @@ static const unsigned int ln_objs[NUM_LN]={
 194,   /* "id-smime-spq" */
 250,   /* "id-smime-spq-ets-sqt-unotice" */
 249,   /* "id-smime-spq-ets-sqt-uri" */
+974,   /* "id-tc26-gost-28147-param-A" */
+972,   /* "id-tc26-gost-3410-12-512-paramSetA" */
+973,   /* "id-tc26-gost-3410-12-512-paramSetB" */
+971,   /* "id-tc26-gost-3410-12-512-paramSetTest" */
 34,    /* "idea-cbc" */
 35,    /* "idea-cfb" */
 36,    /* "idea-ecb" */
@@ -4870,8 +4937,16 @@ static const unsigned int obj_objs[NUM_OBJ]={
 851,   /* OBJ_id_GostR3410_2001_cc         1 2 643 2 9 1 5 4 */
 849,   /* OBJ_id_Gost28147_89_cc           1 2 643 2 9 1 6 1 */
 854,   /* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
+963,   /* OBJ_id_tc26_gost3410_12_256      1 2 643 7 1 1 1 1 */
+964,   /* OBJ_id_tc26_gost3410_12_512      1 2 643 7 1 1 1 2 */
 961,   /* OBJ_id_tc26_gost3411_12_256      1 2 643 7 1 1 2 2 */
 962,   /* OBJ_id_tc26_gost3411_12_512      1 2 643 7 1 1 2 3 */
+965,   /* OBJ_id_tc26_signwithdigest_gost3410_12_256 1 2 643 7 1 1 3 2 */
+966,   /* OBJ_id_tc26_signwithdigest_gost3410_12_512 1 2 643 7 1 1 3 3 */
+967,   /* OBJ_id_tc26_hmac_gost_3411_12_256 1 2 643 7 1 1 4 1 */
+968,   /* OBJ_id_tc26_hmac_gost_3411_12_512 1 2 643 7 1 1 4 2 */
+969,   /* OBJ_id_tc26_agreement_gost_3410_12_256 1 2 643 7 1 1 6 1 */
+970,   /* OBJ_id_tc26_agreement_gost_3410_12_512 1 2 643 7 1 1 6 2 */
 186,   /* OBJ_pkcs1                        1 2 840 113549 1 1 */
 27,    /* OBJ_pkcs3                        1 2 840 113549 1 3 */
 187,   /* OBJ_pkcs5                        1 2 840 113549 1 5 */
@@ -5039,6 +5114,10 @@ static const unsigned int obj_objs[NUM_OBJ]={
 439,   /* OBJ_pilotAttributeSyntax         0 9 2342 19200300 100 3 */
 440,   /* OBJ_pilotObjectClass             0 9 2342 19200300 100 4 */
 441,   /* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
+971,   /* OBJ_id_tc26_gost_3410_12_512_paramSetTest 1 2 643 7 1 2 1 2 0 */
+972,   /* OBJ_id_tc26_gost_3410_12_512_paramSetA 1 2 643 7 1 2 1 2 1 */
+973,   /* OBJ_id_tc26_gost_3410_12_512_paramSetB 1 2 643 7 1 2 1 2 2 */
+974,   /* OBJ_id_tc26_gost_28147_param_A   1 2 643 7 1 2 5 1 1 */
 108,   /* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
 112,   /* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
 782,   /* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
diff --git a/crypto/objects/obj_mac.h b/crypto/objects/obj_mac.h
index 70f41d2..c88ae68 100644
--- a/crypto/objects/obj_mac.h
+++ b/crypto/objects/obj_mac.h
@@ -3748,6 +3748,16 @@
 #define NID_id_Gost28147_89_None_KeyMeshing        820
 #define OBJ_id_Gost28147_89_None_KeyMeshing        OBJ_cryptopro,14L,0L
 
+#define SN_id_tc26_gost3410_12_256     "gost2012_256"
+#define LN_id_tc26_gost3410_12_256     "GOST R 34.10-2012 with 256-bit key"
+#define NID_id_tc26_gost3410_12_256        963
+#define OBJ_id_tc26_gost3410_12_256        OBJ_tc_26,1L,1L,1L
+
+#define SN_id_tc26_gost3410_12_512     "gost2012_512"
+#define LN_id_tc26_gost3410_12_512     "GOST R 34.10-2012 with 512-bit key"
+#define NID_id_tc26_gost3410_12_512        964
+#define OBJ_id_tc26_gost3410_12_512        OBJ_tc_26,1L,1L,2L
+
 #define SN_id_tc26_gost3411_12_256     "md_gost12_256"
 #define LN_id_tc26_gost3411_12_256     "GOST R 34.11-2012 256-bit length"
 #define NID_id_tc26_gost3411_12_256        961
@@ -3758,6 +3768,36 @@
 #define NID_id_tc26_gost3411_12_512        962
 #define OBJ_id_tc26_gost3411_12_512        OBJ_tc_26,1L,2L,3L
 
+#define SN_id_tc26_signwithdigest_gost3410_12_256      "id-tc26-signwithdigest-gost3410-12-256"
+#define LN_id_tc26_signwithdigest_gost3410_12_256      "GOST R 34.10-2012 with 34.11-2012 256-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_256     965
+#define OBJ_id_tc26_signwithdigest_gost3410_12_256     OBJ_tc_26,1L,3L,2L
+
+#define SN_id_tc26_signwithdigest_gost3410_12_512      "id-tc26-signwithdigest-gost3410-12-512"
+#define LN_id_tc26_signwithdigest_gost3410_12_512      "GOST R 34.10-2012 with 34.11-2012 512-bit"
+#define NID_id_tc26_signwithdigest_gost3410_12_512     966
+#define OBJ_id_tc26_signwithdigest_gost3410_12_512     OBJ_tc_26,1L,3L,3L
+
+#define SN_id_tc26_hmac_gost_3411_12_256       "id-tc26-hmac-gost-3411-12-256"
+#define LN_id_tc26_hmac_gost_3411_12_256       "HMAC GOST R 34.11-2012 L=32 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_256      967
+#define OBJ_id_tc26_hmac_gost_3411_12_256      OBJ_tc_26,1L,4L,1L
+
+#define SN_id_tc26_hmac_gost_3411_12_512       "id-tc26-hmac-gost-3411-12-512"
+#define LN_id_tc26_hmac_gost_3411_12_512       "HMAC GOST R 34.11-2012 L=64 B=64"
+#define NID_id_tc26_hmac_gost_3411_12_512      968
+#define OBJ_id_tc26_hmac_gost_3411_12_512      OBJ_tc_26,1L,4L,2L
+
+#define SN_id_tc26_agreement_gost_3410_12_256      "id-tc26-agreement-gost-3410-12-256"
+#define LN_id_tc26_agreement_gost_3410_12_256      "Key agreement schemes GOST R 34.10-2012 256-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_256     969
+#define OBJ_id_tc26_agreement_gost_3410_12_256     OBJ_tc_26,1L,6L,1L
+
+#define SN_id_tc26_agreement_gost_3410_12_512      "id-tc26-agreement-gost-3410-12-512"
+#define LN_id_tc26_agreement_gost_3410_12_512      "Key agreement schemes GOST R 34.10-2012 512-bit key"
+#define NID_id_tc26_agreement_gost_3410_12_512     970
+#define OBJ_id_tc26_agreement_gost_3410_12_512     OBJ_tc_26,1L,6L,2L
+
 #define SN_id_GostR3411_94_TestParamSet        "id-GostR3411-94-TestParamSet"
 #define NID_id_GostR3411_94_TestParamSet       821
 #define OBJ_id_GostR3411_94_TestParamSet       OBJ_cryptopro,30L,0L
@@ -3870,6 +3910,22 @@
 #define NID_id_GostR3410_94_bBis       848
 #define OBJ_id_GostR3410_94_bBis       OBJ_id_GostR3410_94,4L
 
+#define SN_id_tc26_gost_3410_12_512_paramSetTest       "id-tc26-gost-3410-12-512-paramSetTest"
+#define NID_id_tc26_gost_3410_12_512_paramSetTest      971
+#define OBJ_id_tc26_gost_3410_12_512_paramSetTest      OBJ_tc_26,2L,1L,2L,0L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetA      "id-tc26-gost-3410-12-512-paramSetA"
+#define NID_id_tc26_gost_3410_12_512_paramSetA     972
+#define OBJ_id_tc26_gost_3410_12_512_paramSetA     OBJ_tc_26,2L,1L,2L,1L
+
+#define SN_id_tc26_gost_3410_12_512_paramSetB      "id-tc26-gost-3410-12-512-paramSetB"
+#define NID_id_tc26_gost_3410_12_512_paramSetB     973
+#define OBJ_id_tc26_gost_3410_12_512_paramSetB     OBJ_tc_26,2L,1L,2L,2L
+
+#define SN_id_tc26_gost_28147_param_A      "id-tc26-gost-28147-param-A"
+#define NID_id_tc26_gost_28147_param_A     974
+#define OBJ_id_tc26_gost_28147_param_A     OBJ_tc_26,2L,5L,1L,1L
+
 #define SN_id_Gost28147_89_cc      "id-Gost28147-89-cc"
 #define LN_id_Gost28147_89_cc      "GOST 28147-89 Cryptocom ParamSet"
 #define NID_id_Gost28147_89_cc     849
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 0010bf8..d65d512 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -960,3 +960,15 @@ md_gost12_256      959
 md_gost12_512      960
 id_tc26_gost3411_12_256        961
 id_tc26_gost3411_12_512        962
+id_tc26_gost3410_12_256        963
+id_tc26_gost3410_12_512        964
+id_tc26_signwithdigest_gost3410_12_256     965
+id_tc26_signwithdigest_gost3410_12_512     966
+id_tc26_hmac_gost_3411_12_256      967
+id_tc26_hmac_gost_3411_12_512      968
+id_tc26_agreement_gost_3410_12_256     969
+id_tc26_agreement_gost_3410_12_512     970
+id_tc26_gost_3410_12_512_paramSetTest      971
+id_tc26_gost_3410_12_512_paramSetA     972
+id_tc26_gost_3410_12_512_paramSetB     973
+id_tc26_gost_28147_param_A     974
diff --git a/crypto/objects/obj_xref.h b/crypto/objects/obj_xref.h
index cfd628a..4bebb0d 100644
--- a/crypto/objects/obj_xref.h
+++ b/crypto/objects/obj_xref.h
@@ -49,13 +49,15 @@ static const nid_triple sigoid_srt[] =
    {NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf},
    {NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf},
+   {NID_id_tc26_signwithdigest_gost3410_12_256, NID_id_tc26_gost3411_12_256, NID_id_tc26_gost3410_12_256},
+   {NID_id_tc26_signwithdigest_gost3410_12_512, NID_id_tc26_gost3411_12_512, NID_id_tc26_gost3410_12_512},
    };
 
 static const nid_triple * const sigoid_srt_xref[] =
    {
    &sigoid_srt[29],
-   &sigoid_srt[17],
    &sigoid_srt[18],
+   &sigoid_srt[17],
    &sigoid_srt[0],
    &sigoid_srt[1],
    &sigoid_srt[7],
@@ -93,5 +95,7 @@ static const nid_triple * const sigoid_srt_xref[] =
    &sigoid_srt[26],
    &sigoid_srt[27],
    &sigoid_srt[28],
+   &sigoid_srt[40],
+   &sigoid_srt[41],
    };
 
diff --git a/crypto/objects/obj_xref.txt b/crypto/objects/obj_xref.txt
index 19c9422..094a204 100644
--- a/crypto/objects/obj_xref.txt
+++ b/crypto/objects/obj_xref.txt
@@ -44,6 +44,8 @@ id_GostR3411_94_with_GostR3410_2001   id_GostR3411_94 id_GostR3410_2001
 id_GostR3411_94_with_GostR3410_94  id_GostR3411_94 id_GostR3410_94
 id_GostR3411_94_with_GostR3410_94_cc   id_GostR3411_94 id_GostR3410_94_cc
 id_GostR3411_94_with_GostR3410_2001_cc id_GostR3411_94 id_GostR3410_2001_cc
+id_tc26_signwithdigest_gost3410_12_256 id_tc26_gost3411_12_256 id_tc26_gost3410_12_256
+id_tc26_signwithdigest_gost3410_12_512 id_tc26_gost3411_12_512 id_tc26_gost3410_12_512
 # ECDH KDFs and their corresponding message digests and schemes
 dhSinglePass_stdDH_sha1kdf_scheme      sha1    dh_std_kdf
 dhSinglePass_stdDH_sha224kdf_scheme        sha224  dh_std_kdf
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index a61f8d7..bc4f56c 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1181,10 +1181,20 @@ cryptopro 14 1      : id-Gost28147-89-CryptoPro-KeyMeshing
 cryptopro 14 0     : id-Gost28147-89-None-KeyMeshing
 
 # TC-26 GOST OIDs
+!Cname id-tc26-gost3410-12-256
+tc-26 1 1 1  : gost2012_256 : GOST R 34.10-2012 with 256-bit key
+!Cname id-tc26-gost3410-12-512
+tc-26 1 1 2  : gost2012_512 : GOST R 34.10-2012 with 512-bit key
 !Cname id-tc26-gost3411-12-256
 tc-26 1 2 2  : md_gost12_256 : GOST R 34.11-2012 256-bit length
 !Cname id-tc26-gost3411-12-512
 tc-26 1 2 3  : md_gost12_512 : GOST R 34.11-2012 512-bit length
+tc-26 1 3 2  : id-tc26-signwithdigest-gost3410-12-256 : GOST R 34.10-2012 with 34.11-2012 256-bit
+tc-26 1 3 3  : id-tc26-signwithdigest-gost3410-12-512 : GOST R 34.10-2012 with 34.11-2012 512-bit
+tc-26 1 4 1  : id-tc26-hmac-gost-3411-12-256 : HMAC GOST R 34.11-2012 L=32 B=64
+tc-26 1 4 2  : id-tc26-hmac-gost-3411-12-512 : HMAC GOST R 34.11-2012 L=64 B=64
+tc-26 1 6 1     : id-tc26-agreement-gost-3410-12-256 : Key agreement schemes GOST R 34.10-2012 256-bit key
+tc-26 1 6 2  : id-tc26-agreement-gost-3410-12-512 :    Key agreement schemes GOST R 34.10-2012 512-bit key
 
 # GOST parameter set OIDs
 
@@ -1223,6 +1233,13 @@ id-GostR3410-94 2    : id-GostR3410-94-aBis
 id-GostR3410-94 3  : id-GostR3410-94-b
 id-GostR3410-94 4  : id-GostR3410-94-bBis
 
+# TC-26 GOST parameter set OIDs
+
+tc-26 2 1 2 0      : id-tc26-gost-3410-12-512-paramSetTest
+tc-26 2 1 2 1      : id-tc26-gost-3410-12-512-paramSetA
+tc-26 2 1 2 2      : id-tc26-gost-3410-12-512-paramSetB
+tc-26 2 5 1 1       : id-tc26-gost-28147-param-A
+
 # Cryptocom LTD GOST OIDs
 
 cryptocom 1 6 1        : id-Gost28147-89-cc    : GOST 28147-89 Cryptocom ParamSet
diff --git a/engines/ccgost/README.gost b/engines/ccgost/README.gost
index b8eb56e..000774f 100644
--- a/engines/ccgost/README.gost
+++ b/engines/ccgost/README.gost
@@ -14,7 +14,12 @@ GOST R 34.10-94 and GOST R 34.10-2001 - digital signature algorithms.
    256 bit private keys. Public keys are 1024 bit for 94 and 512 bit for
    2001 (which is elliptic-curve based). Key exchange algorithms
    (VKO R 34.10) are supported on these keys too.
-  
+
+GOST R 34.10-2012 - digital signature algorithm.
+   Consists of 2 versions with 256 bit and 512 bit private keys.
+   Both are based on elliptic curve and have public keys of 512 bit
+   and 1024 bit respectively.
+
 GOST R 34.11-94  Message digest algorithm. 256-bit hash value
 
 GOST R 34.11-2012 Message digest algorithm. Has versions with
@@ -108,6 +113,8 @@ USAGE WITH COMMAND LINE openssl UTILITY
   are supported by
    gost94: 0,A,B,C,D,XA,XB,XC
    gost2001: 0,A,B,C,XA,XB
+        gost2012-256: 0,A,B,C,XA,XB
+        gost2012-512: A,B
   You can also use numeric representation of OID as to destinate
   paramset.
 
diff --git a/engines/ccgost/gost2001.c b/engines/ccgost/gost2001.c
index dacd82d..4424b63 100644
--- a/engines/ccgost/gost2001.c
+++ b/engines/ccgost/gost2001.c
@@ -31,14 +31,12 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig);
  * Also fils DSA->q field with copy of EC_GROUP order field to make
  * DSA_size function work
  */
-int fill_GOST2001_params(EC_KEY *eckey, int nid)
+void fill_GOST_EC_params(EC_KEY *eckey, R3410_2001_params *params)
    {
-   R3410_2001_params *params = R3410_2001_paramset;
    EC_GROUP *grp=NULL;
    BIGNUM *p=NULL,*q=NULL,*a=NULL,*b=NULL,*x=NULL,*y=NULL;
    EC_POINT *P=NULL;
    BN_CTX *ctx=BN_CTX_new();
-   int ok=0;
   
    BN_CTX_start(ctx);
    p=BN_CTX_get(ctx);
@@ -47,12 +45,6 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    x=BN_CTX_get(ctx);
    y=BN_CTX_get(ctx);
    q=BN_CTX_get(ctx);
-   while (params->nid!=NID_undef && params->nid != nid) params++;
-   if (params->nid == NID_undef)
-       {
-       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
-       goto err;
-       }  
    BN_hex2bn(&p,params->p);
    BN_hex2bn(&a,params->a);
    BN_hex2bn(&b,params->b);
@@ -76,15 +68,44 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
    EC_GROUP_set_curve_name(grp,params->nid);
 
    EC_KEY_set_group(eckey,grp);
-   ok=1;
-   err:
    EC_POINT_free(P);
    EC_GROUP_free(grp);
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
-   return ok;
-   }  
+   }
 
+int fill_GOST2001_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2001_paramset;
+
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }
+
+// paramset selection is exactly the same
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid)
+   {
+   return fill_GOST2001_params(eckey, nid);
+   }
+
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid)
+   {
+   R3410_2001_params *params = R3410_2012_512_paramset;
+   while (params->nid!=NID_undef && params->nid != nid) params++;
+   if (params->nid == NID_undef)
+       {
+       GOSTerr(GOST_F_FILL_GOST2001_PARAMS,GOST_R_UNSUPPORTED_PARAMETER_SET);
+       return 0;
+       }
+   fill_GOST_EC_params(eckey, params);
+   return 1;
+   }
 
 /*
  * Computes gost2001 signature as DSA_SIG structure
@@ -94,7 +115,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid)
 DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    {
    DSA_SIG *newsig = NULL;
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    BIGNUM *order = NULL;
    const EC_GROUP *group;
    const BIGNUM *priv_key;
@@ -102,7 +123,7 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
    EC_POINT *C=NULL;
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);
-   OPENSSL_assert(dlen==32);
+   OPENSSL_assert(dlen==32 || dlen==64);
    newsig=DSA_SIG_new();
    if (!newsig)
        {
@@ -138,7 +159,15 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
                DSA_SIG_free(newsig);
                newsig = NULL;
                goto err;
-               }  
+               }
+           /* To avoid timing information leaking the length of k,
+              compute C*k using an equivalent scalar of fixed bit-length
+           */
+           if (!BN_add(k,k,order)) goto err;
+           if (BN_num_bits(k) <= BN_num_bits(order))
+               {
+               if (!BN_add(k,k,order)) goto err;
+               }
            if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
                {
                GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
@@ -170,7 +199,7 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
 
    newsig->s=BN_dup(s);
    newsig->r=BN_dup(r);
-   err:            
+err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
    EC_POINT_free(C);
@@ -212,7 +241,7 @@ int gost2001_do_verify(const unsigned char *dgst,int dgst_len,
        goto err;
 
        }
-   md = hashsum2bn(dgst);
+   md = hashsum2bn(dgst,dgst_len);
 
    BN_mod(e,md,order,ctx);
 #ifdef DEBUG_SIGN
diff --git a/engines/ccgost/gost_ameth.c b/engines/ccgost/gost_ameth.c
index 2cde1fc..4293bf1 100644
--- a/engines/ccgost/gost_ameth.c
+++ b/engines/ccgost/gost_ameth.c
@@ -20,6 +20,22 @@
 #include "gost_lcl.h"
 #include "e_gost_err.h"
 
+static int md_nid_by_pmeth_nid(int pmeth_nid)
+{
+   switch(pmeth_nid)
+   {
+   case NID_id_GostR3410_94:
+   case NID_id_GostR3410_2001:
+       return NID_id_GostR3411_94;
+   case NID_id_tc26_gost3410_12_256:
+       return NID_id_tc26_gost3411_12_256;
+   case NID_id_tc26_gost3410_12_512:
+       return NID_id_tc26_gost3411_12_512;
+   default:
+       return NID_undef;
+   }
+}
+
 int gost94_nid_by_params(DSA *p)
    {
    R3410_params *gost_params;
@@ -42,6 +58,7 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
    ASN1_STRING *params = ASN1_STRING_new();
    GOST_KEY_PARAMS *gkp = GOST_KEY_PARAMS_new();
    int pkey_param_nid = NID_undef;
+   int hash_param_nid = NID_undef;
 
    if (!params || !gkp)
        {
@@ -55,6 +72,15 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
        {
        case NID_id_GostR3410_2001:
            pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
+           break;
+       case NID_id_tc26_gost3410_12_256:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_256;
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           pkey_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)key)));
+           hash_param_nid = NID_id_tc26_gost3411_12_512;
            break;
        case NID_id_GostR3410_94:
            pkey_param_nid = (int) gost94_nid_by_params(EVP_PKEY_get0((EVP_PKEY *)key));
@@ -65,11 +91,12 @@ static ASN1_STRING  *encode_gost_algor_params(const EVP_PKEY *key)
                ASN1_STRING_free(params);
                params=NULL;
                goto err;
-               }  
+               }          
+           hash_param_nid = NID_id_GostR3411_94_CryptoProParamSet;
            break;
        }  
    gkp->key_params = OBJ_nid2obj(pkey_param_nid);
-   gkp->hash_params = OBJ_nid2obj(NID_id_GostR3411_94_CryptoProParamSet);
+   gkp->hash_params = OBJ_nid2obj(hash_param_nid);
    /*gkp->cipher_params = OBJ_nid2obj(cipher_param_nid);*/
    params->length = i2d_GOST_KEY_PARAMS(gkp, &params->data);
    if (params->length <=0 )
@@ -143,6 +170,29 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg)
            }
        if (!fill_GOST2001_params(ec,param_nid)) return 0;
        }
+       break;
+       case NID_id_tc26_gost3410_12_256:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_256_params(ec,param_nid)) return 0;
+       }
+       break;
+       case NID_id_tc26_gost3410_12_512:
+       {
+       EC_KEY *ec = EVP_PKEY_get0(pkey);
+       if (!ec)
+           {
+           ec = EC_KEY_new();
+           if (!EVP_PKEY_assign(pkey,pkey_nid,ec)) return 0;
+           }
+       if (!fill_GOST2012_512_params(ec,param_nid)) return 0;
+       }
+       break;
        }
 
    return 1;
@@ -166,6 +216,8 @@ static int gost_set_priv_key(EVP_PKEY *pkey,BIGNUM *priv)
        break;
        }  
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0(pkey);
        if (!ec)
@@ -197,6 +249,8 @@ BIGNUM* gost_get0_priv_key(const EVP_PKEY *pkey)
        break;
        }  
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
        {
        EC_KEY *ec = EVP_PKEY_get0((EVP_PKEY *)pkey);
        const BIGNUM* priv;
@@ -224,7 +278,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                PKCS7_SIGNER_INFO_get0_algs((PKCS7_SIGNER_INFO*)arg2,
                    NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -241,7 +295,7 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
                int nid = EVP_PKEY_base_id(pkey);
                CMS_SignerInfo_get0_algs((CMS_SignerInfo *)arg2,
                    NULL, NULL, &alg1, &alg2);
-               X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_id_GostR3411_94),
+               X509_ALGOR_set0(alg1, OBJ_nid2obj(md_nid_by_pmeth_nid(nid)),
                    V_ASN1_NULL, 0);
                if (nid == NID_undef)
                    {
@@ -282,7 +336,10 @@ static int pkey_ctrl_gost(EVP_PKEY *pkey, int op,
            return 1;
 #endif
        case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
-           *(int *)arg2 = NID_id_GostR3411_94;
+           {
+           int nid = EVP_PKEY_base_id(pkey);
+           *(int *)arg2 = md_nid_by_pmeth_nid(nid);
+           }
            return 2;
        }
   
@@ -824,6 +881,16 @@ static int pkey_bits_gost(const EVP_PKEY *pk)
    {
    return 256;
    }
+
+static int pkey_size_gost_512(const EVP_PKEY *pk)
+   {
+   return 128;
+   }
+
+static int pkey_bits_gost_512(const EVP_PKEY *pk)
+   {
+   return 512;
+   }
 /*------------------------ ASN1 METHOD for GOST MAC  -------------------*/
 static void  mackey_free_gost(EVP_PKEY *pk)
    {
@@ -872,7 +939,8 @@ static int gost94_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int d
    return 1;
 }  
 
-static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+//generic version for all EC-based GOST 34.10: 2001, 2012-256, 2012-512
+static int gost_ec_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen, void (*fill_params(EC_KEY*,int)), int meth_nid) {
    ASN1_OBJECT *obj=NULL;
    int nid;
    EC_KEY *ec = EVP_PKEY_get0(pkey);
@@ -884,15 +952,23 @@ static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int
    if (!ec)
        {
        ec = EC_KEY_new();
-       if (!EVP_PKEY_assign(pkey,NID_id_GostR3410_2001,ec)) return 0;
+       if (!EVP_PKEY_assign(pkey,meth_nid,ec)) return 0;
        }  
-   if (!fill_GOST2001_params(ec, nid)) return 0;
+   if (!fill_params(ec, nid)) return 0;
    return 1;
 }  
 
+static int gost2001_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2001_params, NID_id_GostR3410_2001);
+}  
 
+static int gost2012_256_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_256_params, NID_id_tc26_gost3410_12_256);
+}
 
-
+static int gost2012_512_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) {
+   return gost_ec_param_decode(pkey, pder, derlen, &fill_GOST2012_512_params, NID_id_tc26_gost3410_12_512);
+}
 
 /* ----------------------------------------------------------------------*/
 int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pemstr, const char* info)
@@ -936,6 +1012,40 @@ int register_ameth_gost (int nid, EVP_PKEY_ASN1_METHOD **ameth, const char* pems
   
            EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_256_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost, pkey_bits_gost);
+  
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_asn1_set_free (*ameth, pkey_free_gost01);
+           EVP_PKEY_asn1_set_private (*ameth,
+               priv_decode_gost, priv_encode_gost,
+               priv_print_gost01);
+
+           EVP_PKEY_asn1_set_param (*ameth,
+               gost2012_512_param_decode, gost2001_param_encode,
+               param_missing_gost01, param_copy_gost01,
+               param_cmp_gost01, param_print_gost01);
+           EVP_PKEY_asn1_set_public (*ameth,
+               pub_decode_gost01, pub_encode_gost01,
+               pub_cmp_gost01, pub_print_gost01,
+               pkey_size_gost_512, pkey_bits_gost_512);
+  
+           EVP_PKEY_asn1_set_ctrl (*ameth, pkey_ctrl_gost);
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_asn1_set_free(*ameth, mackey_free_gost);
            EVP_PKEY_asn1_set_ctrl(*ameth,mac_ctrl_gost);  
diff --git a/engines/ccgost/gost_eng.c b/engines/ccgost/gost_eng.c
index dc6bd72..977b5b3 100644
--- a/engines/ccgost/gost_eng.c
+++ b/engines/ccgost/gost_eng.c
@@ -40,15 +40,20 @@ static int gost_digest_nids[] =
     NID_id_tc26_gost3411_12_256,NID_id_tc26_gost3411_12_512,0};
 
 static int gost_pkey_meth_nids[] =
-   {NID_id_GostR3410_94,
-    NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
+   {NID_id_GostR3410_94, NID_id_GostR3410_2001,
+    NID_id_tc26_gost3410_12_256,NID_id_tc26_gost3410_12_512,
+    NID_id_Gost28147_89_MAC, 0};
 
 static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
-    *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2001 = NULL,
+   *pmeth_GostR3410_2012_256 = NULL,
+   *pmeth_GostR3410_2012_512 = NULL,
    *pmeth_Gost28147_MAC = NULL;
 
 static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
    *ameth_GostR3410_2001 = NULL,
+   *ameth_GostR3410_2012_256 = NULL,
+   *ameth_GostR3410_2012_512 = NULL,
    *ameth_Gost28147_MAC = NULL;
 
 
@@ -68,9 +73,13 @@ static int gost_engine_destroy(ENGINE *e)
 
    pmeth_GostR3410_94 = NULL;
    pmeth_GostR3410_2001 = NULL;
+   pmeth_GostR3410_2012_256 = NULL;
+   pmeth_GostR3410_2012_512 = NULL;
    pmeth_Gost28147_MAC = NULL;
    ameth_GostR3410_94 = NULL;
    ameth_GostR3410_2001 = NULL;
+   ameth_GostR3410_2012_256 = NULL;
+   ameth_GostR3410_2012_512 = NULL;
    ameth_Gost28147_MAC = NULL;
    return 1;
    }
@@ -130,11 +139,17 @@ static int bind_gost (ENGINE *e,const char *id)
 
    if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
    if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_256, &ameth_GostR3410_2012_256,
+       "GOST2012-256", "GOST R 34.10-2012 256bit")) goto end;
+   if (!register_ameth_gost(NID_id_tc26_gost3410_12_512, &ameth_GostR3410_2012_512,
+       "GOST2012-512", "GOST R 34.10-2012 512bit")) goto end;
    if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
        "GOST-MAC", "GOST 28147-89 MAC")) goto end;
 
    if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
    if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_256, &pmeth_GostR3410_2012_256, 0)) goto end;
+   if (!register_pmeth_gost(NID_id_tc26_gost3410_12_512, &pmeth_GostR3410_2012_512, 0)) goto end;
    if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
        goto end;
    if ( ! ENGINE_register_ciphers(e)
@@ -229,7 +244,7 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
    if (!pmeth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }
 
    switch (nid)
@@ -237,6 +252,8 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
        case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1;
+       case NID_id_tc26_gost3410_12_256: *pmeth = pmeth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *pmeth = pmeth_GostR3410_2012_512; return 1;
        default:;
        }
   
@@ -247,17 +264,19 @@ static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
 static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
    const int **nids, int nid)
    {
+
    if (!ameth)
        {
        *nids = gost_pkey_meth_nids;
-       return 3;
+       return 5;
        }
    switch (nid)
        {
        case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
        case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
        case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1;
-  
+       case NID_id_tc26_gost3410_12_256: *ameth = ameth_GostR3410_2012_256; return 1;
+       case NID_id_tc26_gost3410_12_512: *ameth = ameth_GostR3410_2012_512; return 1;
        default:;
        }
   
diff --git a/engines/ccgost/gost_lcl.h b/engines/ccgost/gost_lcl.h
index 90c262d..7d0b526 100644
--- a/engines/ccgost/gost_lcl.h
+++ b/engines/ccgost/gost_lcl.h
@@ -185,6 +185,8 @@ int pkey_gost94_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
 /* Internal functions for signature algorithms */
 int fill_GOST94_params(DSA *dsa,int nid);
 int fill_GOST2001_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_256_params(EC_KEY *eckey, int nid);
+int fill_GOST2012_512_params(EC_KEY *eckey, int nid);
 int gost_sign_keygen(DSA *dsa) ;
 int gost2001_keygen(EC_KEY *ec) ;
 
@@ -200,7 +202,7 @@ int gost94_compute_public(DSA *dsa) ;
 /*============== miscellaneous functions============================= */
 /* from gost_sign.c */
 /* Convert GOST R 34.11 hash sum to bignum according to standard */
-BIGNUM *hashsum2bn(const unsigned char *dgst) ;
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen) ;
 /* Store bignum in byte array of given length, prepending by zeros
  * if nesseccary */
 int store_bignum(BIGNUM *bn, unsigned char *buf,int len);
diff --git a/engines/ccgost/gost_params.c b/engines/ccgost/gost_params.c
index 40fc343..6fcb3dc 100644
--- a/engines/ccgost/gost_params.c
+++ b/engines/ccgost/gost_params.c
@@ -196,3 +196,42 @@ R3410_2001_params R3410_2001_paramset[]={
    { 0,NULL,NULL,NULL,NULL,NULL,NULL
    }
 };
+
+R3410_2001_params R3410_2012_512_paramset[]={
+   /*1.2.643.7.1.2.1.2.1*/
+   {NID_id_tc26_gost_3410_12_512_paramSetA,
+   /* A */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",
+   /* B */
+   "E8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265"
+"EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",
+   /* P */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",
+   /* Q */
+   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2"
+"7E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",
+   /* X */
+   "3",
+   /* Y */
+   "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921D"
+"F1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4"
+   },
+   /*1.2.643.7.1.2.1.2.2*/
+   {NID_id_tc26_gost_3410_12_512_paramSetB,
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006C",
+   "687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3"
+"E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116",
+   "80000000000000000000000000000000000000000000000000000000000000000"
+"00000000000000000000000000000000000000000000000000000000000006F",
+   "80000000000000000000000000000000000000000000000000000000000000014"
+"9A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD",
+   "2",
+   "1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335D"
+"CB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD"
+   },
+   { 0,NULL,NULL,NULL,NULL,NULL,NULL
+   }
+};
\ No newline at end of file
diff --git a/engines/ccgost/gost_params.h b/engines/ccgost/gost_params.h
index 4c3f556..3a1c6e0 100644
--- a/engines/ccgost/gost_params.h
+++ b/engines/ccgost/gost_params.h
@@ -30,5 +30,6 @@ typedef struct R3410_2001 {
 } R3410_2001_params;
 
 extern R3410_2001_params R3410_2001_paramset[];
+extern R3410_2001_params R3410_2012_512_paramset[];
 
 #endif
diff --git a/engines/ccgost/gost_pmeth.c b/engines/ccgost/gost_pmeth.c
index 3189798..f73cae5 100644
--- a/engines/ccgost/gost_pmeth.c
+++ b/engines/ccgost/gost_pmeth.c
@@ -33,6 +33,8 @@ static int pkey_gost_init(EVP_PKEY_CTX *ctx)
          data->sign_param_nid = gost94_nid_by_params(EVP_PKEY_get0(pkey));
          break;
        case NID_id_GostR3410_2001:
+       case NID_id_tc26_gost3410_12_256:
+       case NID_id_tc26_gost3410_12_512:
           data->sign_param_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(EVP_PKEY_get0((EVP_PKEY *)pkey)));
        break;
        default:
@@ -54,9 +56,10 @@ static int pkey_gost_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
    src_data = EVP_PKEY_CTX_get_data(src);
    dst_data = EVP_PKEY_CTX_get_data(dst);
    *dst_data = *src_data;
-   if (src_data -> shared_ukm) {
+   if (src_data->shared_ukm)
+       {
        dst_data->shared_ukm=NULL;
-   }  
+       }  
    return 1;
    }
 
@@ -72,11 +75,17 @@ static void pkey_gost_cleanup (EVP_PKEY_CTX *ctx)
 static int pkey_gost_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
    {
    struct gost_pmeth_data *pctx = (struct gost_pmeth_data*)EVP_PKEY_CTX_get_data(ctx);
+   int base_id;
+   int md_type;
    switch (type)
        {
        case EVP_PKEY_CTRL_MD:
        {
-       if (EVP_MD_type((const EVP_MD *)p2) != NID_id_GostR3411_94)
+       base_id = EVP_PKEY_base_id(EVP_PKEY_CTX_get0_pkey(ctx));
+       md_type = EVP_MD_type((const EVP_MD *)p2);
+       if (((base_id == NID_id_GostR3410_94 || base_id == NID_id_GostR3410_2001) && md_type != NID_id_GostR3411_94)
+           || (base_id == NID_id_tc26_gost3410_12_256 && md_type != NID_id_tc26_gost3411_12_256)
+           || (base_id == NID_id_tc26_gost3410_12_512 && md_type != NID_id_tc26_gost3411_12_512))
            {
            GOSTerr(GOST_F_PKEY_GOST_CTRL, GOST_R_INVALID_DIGEST_TYPE);
            return 0;
@@ -268,6 +277,63 @@ static int pkey_gost_ctrl01_str(EVP_PKEY_CTX *ctx,
    return -2;
    }
 
+static int pkey_gost_ctrl12_256_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+{
+   return pkey_gost_ctrl01_str(ctx, type, value);
+}
+
+static int pkey_gost_ctrl12_512_str(EVP_PKEY_CTX *ctx,
+   const char *type, const char *value)
+   {
+   int param_nid=0;
+   printf("CTL %s %s \n", type, value);
+   if(!strcmp(type, param_ctrl_string))
+       {
+       if (!value)
+           {
+           return 0;
+           }
+       if (strlen(value) == 1)
+           {
+           switch(toupper((unsigned char)value[0]))
+               {
+               case 'A':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetA;
+                   break;  
+               case 'B':
+                   param_nid = NID_id_tc26_gost_3410_12_512_paramSetB;
+                   break;
+               default:
+                   return 0;
+                   break;
+               }
+           }
+       else
+           {
+           R3410_2001_params *p = R3410_2012_512_paramset;
+           param_nid = OBJ_txt2nid(value);
+           if (param_nid == NID_undef)
+               {
+               return 0;
+               }
+           for (;p->nid != NID_undef;p++)
+               {
+               if (p->nid == param_nid) break;
+               }          
+           if (p->nid == NID_undef)
+               {
+               GOSTerr(GOST_F_PKEY_GOST_CTRL01_STR,
+                   GOST_R_INVALID_PARAMSET);
+               return 0;
+               }
+           }
+
+       return pkey_gost_ctrl(ctx, EVP_PKEY_CTRL_GOST_PARAMSET,
+           param_nid, NULL);
+       }
+   return -2;
+   }
 /* --------------------- key generation  --------------------------------*/
 
 static int pkey_gost_paramgen_init(EVP_PKEY_CTX *ctx) {
@@ -303,8 +369,11 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
                GOST_R_NO_PARAMETERS_SET);
            return 0;
        }
-   if (!ec)    
+   if (!ec)
+       {
        ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
    if (!fill_GOST2001_params(ec,data->sign_param_nid))
        {
        EC_KEY_free(ec);
@@ -314,6 +383,54 @@ static int pkey_gost01_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }
 
+static int pkey_gost12_256_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)
+       {
+       ec = EC_KEY_new();
+       if (!ec) return 0;
+       }
+   if (!fill_GOST2012_256_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_256,ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
+   EC_KEY *ec=NULL;
+
+   if (data->sign_param_nid == NID_undef)
+       {
+       GOSTerr(GOST_F_PKEY_GOST01_PARAMGEN,
+           GOST_R_NO_PARAMETERS_SET);
+       return 0;
+       }
+   if (!ec)    
+       ec = EC_KEY_new();
+   if(!fill_GOST2012_512_params(ec,data->sign_param_nid))
+       {
+       EC_KEY_free(ec);
+       return 0;
+       }
+  
+   EVP_PKEY_assign(pkey,NID_id_tc26_gost3410_12_512,ec);
+   return 1;
+   }
+
 /* Generates Gost_R3410_94_cp key */
 static int pkey_gost94cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    {
@@ -334,6 +451,23 @@ static int pkey_gost01cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
    return 1;
    }
 
+static int pkey_gost12_256_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_256_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }
+
+static int pkey_gost12_512_cp_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+   {
+   EC_KEY *ec;
+    if (!pkey_gost12_512_paramgen(ctx,pkey)) return 0;
+   ec = EVP_PKEY_get0(pkey);
+   gost2001_keygen(ec);
+   return 1;
+   }
 
 
 /* ----------- sign callbacks --------------------------------------*/
@@ -363,17 +497,25 @@ static int pkey_gost01_cp_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *si
    DSA_SIG *unpacked_sig=NULL;
    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx);
    if (!siglen) return 0;
+   // GOST-2012 signature can be 512 or 1024 bits long
+   const EC_GROUP *group = EC_KEY_get0_group(EVP_PKEY_get0(pkey));
+
+   int pkey_len = EC_GROUP_get_degree(group)/8;
    if (!sig)
        {
-       *siglen= 64; /* better to check size of curve order*/
+       *siglen = pkey_len*2;
        return 1;
        }  
+   if (tbs_len != pkey_len)
+       {
+       return 0;
+       }
    unpacked_sig = gost2001_do_sign(tbs,tbs_len,EVP_PKEY_get0(pkey));
    if (!unpacked_sig)
        {
        return 0;
        }
-   return pack_sign_cp(unpacked_sig,32,sig,siglen);
+   return pack_sign_cp(unpacked_sig,pkey_len,sig,siglen);
    }
 
 /* ------------------- verify callbacks ---------------------------*/
@@ -600,7 +742,7 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost94_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost94_paramgen);  
            break;
-       case NID_id_GostR3410_2001:
+       case NID_id_GostR3410_2001:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl01_str);
            EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
            EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
@@ -614,6 +756,34 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth,int flags)
                pkey_gost_derive_init, pkey_gost2001_derive);
            EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost01_paramgen);  
            break;
+       case NID_id_tc26_gost3410_12_256:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_256_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_256_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_256_paramgen);  
+           break;
+       case NID_id_tc26_gost3410_12_512:
+           EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_ctrl, pkey_gost_ctrl12_512_str);
+           EVP_PKEY_meth_set_sign(*pmeth, NULL, pkey_gost01_cp_sign);
+           EVP_PKEY_meth_set_verify(*pmeth, NULL, pkey_gost01_cp_verify);
+
+           EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost12_512_cp_keygen);
+
+           EVP_PKEY_meth_set_encrypt(*pmeth,
+               pkey_gost_encrypt_init, pkey_GOST01cp_encrypt);
+           EVP_PKEY_meth_set_decrypt(*pmeth, NULL, pkey_GOST01cp_decrypt);
+           EVP_PKEY_meth_set_derive(*pmeth,
+               pkey_gost_derive_init, pkey_gost2001_derive);
+           EVP_PKEY_meth_set_paramgen(*pmeth, pkey_gost_paramgen_init,pkey_gost12_512_paramgen);  
+           break;
        case NID_id_Gost28147_89_MAC:
            EVP_PKEY_meth_set_ctrl(*pmeth,pkey_gost_mac_ctrl, pkey_gost_mac_ctrl_str);
            EVP_PKEY_meth_set_signctx(*pmeth,pkey_gost_mac_signctx_init, pkey_gost_mac_signctx);
diff --git a/engines/ccgost/gost_sign.c b/engines/ccgost/gost_sign.c
index 4095654..3f3902c 100644
--- a/engines/ccgost/gost_sign.c
+++ b/engines/ccgost/gost_sign.c
@@ -52,7 +52,7 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst,int dlen, DSA *dsa)
    {
    BIGNUM *k=NULL,*tmp=NULL,*tmp2=NULL;
    DSA_SIG *newsig = DSA_SIG_new();
-   BIGNUM *md = hashsum2bn(dgst);
+   BIGNUM *md = hashsum2bn(dgst,dlen);
    /* check if H(M) mod q is zero */
    BN_CTX *ctx=BN_CTX_new();
    BN_CTX_start(ctx);
@@ -149,7 +149,7 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len,
        GOSTerr(GOST_F_GOST_DO_VERIFY,GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
        return 0;
        }
-   md=hashsum2bn(dgst);
+   md=hashsum2bn(dgst,dgst_len);
   
    tmp=BN_CTX_get(ctx);
    v=BN_CTX_get(ctx);
@@ -279,15 +279,16 @@ DSA_SIG *unpack_cp_signature(const unsigned char *sig,size_t siglen)
    }
 
 /* Convert little-endian byte array into bignum */
-BIGNUM *hashsum2bn(const unsigned char *dgst)
+BIGNUM *hashsum2bn(const unsigned char *dgst,int dlen)
    {
-   unsigned char buf[32];
+   unsigned char buf[64];    
    int i;
-   for (i=0;i<32;i++)
+    OPENSSL_assert(dlen==32 || dlen == 64);
+   for (i=0;i<dlen;i++)
        {
-       buf[31-i]=dgst[i];
+       buf[dlen-1-i]=dgst[i];
        }
-   return getbnfrombuf(buf,32);
+   return getbnfrombuf(buf,dlen);
    }
 
 /* Convert byte buffer to bignum, skipping leading zeros*/
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Andrey Kulikov
In reply to this post by Dmitry Olshansky

Дмитрий, а есть ли у вас планы по внедрению  TLS, основанного на новых ГОСТах, в OpenSSL ?
Сам собирался занятся этим в начале лета, после отпуска.
С вашей помощью, теперь, это совсем тривиально должно получиться.

Можно скооперироваться как-нибудь.
Если вы, конечно, всё сами не сделаете до этого. :-)
Reply | Threaded
Open this post in threaded view
|

Re: [openssl.org #3328] [PATCH] Support for GOST R 34.10-2012 digital signature algorithm

Dmitry Olshansky
On 28.04.2014 16:49, Andrey Kulikov wrote:
>
> Дмитрий, а есть ли у вас планы по внедрению  TLS, основанного на новых
> ГОСТах, в OpenSSL ?
> Сам собирался занятся этим в начале лета, после отпуска.
> С вашей помощью, теперь, это совсем тривиально должно получиться.
>
> Можно скооперироваться как-нибудь.
> Если вы, конечно, всё сами не сделаете до этого. :-)

I thought it wasn't customary to use Russian on a public mail list ;)
Anyhow, indeed the last missing piece of new GOST support is TLS
and I have plans to add that with 3rd patch.

I believe it should be straight-forward:
- add a new key exchange (VKO 34.10-2012) that simply uses HMAC of new
hash instead of GOST 34.11-94
- twiddle with registration of new cipher-suites in libssl

Any help is welcome, e.g. pull requests for my openssl fork.

--
Dmitry Olshansky
Systems Engineer
Demos llc.

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [hidden email]
Automated List Manager                           [hidden email]