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 via email to