diff -ruN openssl-1.0.2d.orig/crypto/objects/obj_dat.h openssl-1.0.2d/crypto/objects/obj_dat.h
--- openssl-1.0.2d.orig/crypto/objects/obj_dat.h	2015-07-09 14:58:05.000000000 +0300
+++ openssl-1.0.2d/crypto/objects/obj_dat.h	2015-07-31 16:42:05.655585723 +0300
@@ -62,9 +62,9 @@
  * [including the GNU Public Licence.]
  */
 
-#define NUM_NID 958
-#define NUM_SN 951
-#define NUM_LN 951
+#define NUM_NID 959
+#define NUM_SN 952
+#define NUM_LN 952
 #define NUM_OBJ 890
 
 static const unsigned char lvalues[6255]={
@@ -2514,6 +2514,7 @@
 	NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0},
 {"jurisdictionC","jurisdictionCountryName",
 	NID_jurisdictionCountryName,11,&(lvalues[6243]),0},
+{"gost89-cbc","gost89-cbc",NID_gost89_cbc,0,NULL,0},
 };
 
 static const unsigned int sn_objs[NUM_SN]={
@@ -2861,6 +2862,7 @@
 811,	/* "gost2001" */
 851,	/* "gost2001cc" */
 813,	/* "gost89" */
+958,	/* "gost89-cbc" */
 814,	/* "gost89-cnt" */
 812,	/* "gost94" */
 850,	/* "gost94cc" */
@@ -3825,6 +3827,7 @@
 509,	/* "generationQualifier" */
 601,	/* "generic cryptogram" */
 99,	/* "givenName" */
+958,	/* "gost89-cbc" */
 814,	/* "gost89-cnt" */
 855,	/* "hmac" */
 780,	/* "hmac-md5" */
diff -ruN openssl-1.0.2d.orig/crypto/objects/objects.txt openssl-1.0.2d/crypto/objects/objects.txt
--- openssl-1.0.2d.orig/crypto/objects/objects.txt	2015-07-09 14:57:15.000000000 +0300
+++ openssl-1.0.2d/crypto/objects/objects.txt	2015-07-31 16:08:14.765263858 +0300
@@ -1169,6 +1169,7 @@
 !Cname id-Gost28147-89
 cryptopro 21		: gost89 		: GOST 28147-89
 			: gost89-cnt
+			: gost89-cbc
 !Cname id-Gost28147-89-MAC
 cryptopro 22		: gost-mac	: GOST 28147-89 MAC
 !Cname id-GostR3411-94-prf
diff -ruN openssl-1.0.2d.orig/crypto/objects/obj_mac.h openssl-1.0.2d/crypto/objects/obj_mac.h
--- openssl-1.0.2d.orig/crypto/objects/obj_mac.h	2015-07-09 14:58:04.000000000 +0300
+++ openssl-1.0.2d/crypto/objects/obj_mac.h	2015-07-31 16:09:22.229739886 +0300
@@ -3716,6 +3716,9 @@
 #define SN_gost89_cnt           "gost89-cnt"
 #define NID_gost89_cnt          814
 
+#define SN_gost89_cbc           "gost89-cbc"
+#define NID_gost89_cbc          958
+
 #define SN_id_Gost28147_89_MAC          "gost-mac"
 #define LN_id_Gost28147_89_MAC          "GOST 28147-89 MAC"
 #define NID_id_Gost28147_89_MAC         815
diff -ruN openssl-1.0.2d.orig/crypto/objects/obj_mac.num openssl-1.0.2d/crypto/objects/obj_mac.num
--- openssl-1.0.2d.orig/crypto/objects/obj_mac.num	2015-07-09 14:58:03.000000000 +0300
+++ openssl-1.0.2d/crypto/objects/obj_mac.num	2015-07-31 16:09:21.213732717 +0300
@@ -955,3 +955,4 @@
 jurisdictionLocalityName		955
 jurisdictionStateOrProvinceName		956
 jurisdictionCountryName		957
+gost89_cbc		958
diff -ruN openssl-1.0.2d.orig/engines/ccgost/e_gost_err.c openssl-1.0.2d/engines/ccgost/e_gost_err.c
--- openssl-1.0.2d.orig/engines/ccgost/e_gost_err.c	2015-07-09 14:53:21.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/e_gost_err.c	2015-07-31 16:11:26.690617784 +0300
@@ -140,6 +140,8 @@
     {ERR_REASON(GOST_R_INVALID_GOST94_PARMSET), "invalid gost94 parmset"},
     {ERR_REASON(GOST_R_INVALID_IV_LENGTH), "invalid iv length"},
     {ERR_REASON(GOST_R_INVALID_MAC_KEY_LENGTH), "invalid mac key length"},
+    {ERR_REASON(GOST_R_INVALID_MAC_KEY_SIZE) ,"invalid mac key size"},
+    {ERR_REASON(GOST_R_INVALID_MAC_SIZE)     ,"invalid mac size"},
     {ERR_REASON(GOST_R_INVALID_PARAMSET), "invalid paramset"},
     {ERR_REASON(GOST_R_KEY_IS_NOT_INITALIZED), "key is not initalized"},
     {ERR_REASON(GOST_R_KEY_IS_NOT_INITIALIZED), "key is not initialized"},
diff -ruN openssl-1.0.2d.orig/engines/ccgost/e_gost_err.h openssl-1.0.2d/engines/ccgost/e_gost_err.h
--- openssl-1.0.2d.orig/engines/ccgost/e_gost_err.h	2015-07-09 14:53:21.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/e_gost_err.h	2015-07-31 16:12:35.423102438 +0300
@@ -132,6 +132,8 @@
 # define GOST_R_INVALID_GOST94_PARMSET                    109
 # define GOST_R_INVALID_IV_LENGTH                         110
 # define GOST_R_INVALID_MAC_KEY_LENGTH                    111
+# define GOST_R_INVALID_MAC_KEY_SIZE                      134
+# define GOST_R_INVALID_MAC_SIZE                          136
 # define GOST_R_INVALID_PARAMSET                          112
 # define GOST_R_KEY_IS_NOT_INITALIZED                     113
 # define GOST_R_KEY_IS_NOT_INITIALIZED                    114
diff -ruN openssl-1.0.2d.orig/engines/ccgost/gost_crypt.c openssl-1.0.2d/engines/ccgost/gost_crypt.c
--- openssl-1.0.2d.orig/engines/ccgost/gost_crypt.c	2015-07-09 14:57:15.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/gost_crypt.c	2015-07-31 16:26:46.833097557 +0300
@@ -21,11 +21,16 @@
 
 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                             const unsigned char *iv, int enc);
+static int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                                const unsigned char *iv, int enc);
 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                                 const unsigned char *iv, int enc);
 /* Handles block of data in CFB mode */
 static int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
                               const unsigned char *in, size_t inl);
+/* Handles block of data in CBC mode */
+static int	gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
+	                           const unsigned char *in, size_t inl);
 /* Handles block of data in CNT mode */
 static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out,
                               const unsigned char *in, size_t inl);
@@ -54,6 +59,24 @@
     NULL,
 };
 
+EVP_CIPHER cipher_gost_cbc =
+    {
+    NID_gost89_cbc,
+    8,/*block_size*/
+    32,/*key_size*/
+    8,/*iv_len */
+    EVP_CIPH_CBC_MODE|
+    EVP_CIPH_CUSTOM_IV| EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT,
+    gost_cipher_init_cbc,
+    gost_cipher_do_cbc,
+    gost_cipher_cleanup,
+    sizeof(struct ossl_gost_cipher_ctx),/* ctx_size */
+    gost89_set_asn1_parameters,
+    gost89_get_asn1_parameters,
+    gost_cipher_ctl,
+    NULL,
+    };
+
 EVP_CIPHER cipher_gost_cpacnt = {
     NID_gost89_cnt,
     1,                          /* block_size */
@@ -222,6 +245,15 @@
                                   EVP_CIPH_CFB_MODE);
 }
 
+/* Initializes EVP_CIPHER_CTX with default values */
+int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+	                     const unsigned char *iv, int enc)
+{
+    return gost_cipher_init_param(ctx, key, iv, enc, NID_undef,
+                                  EVP_CIPH_CBC_MODE);
+}
+
+
 /*
  * Wrapper around gostcrypt function from gost89.c which perform key meshing
  * when nesseccary
@@ -271,6 +303,47 @@
     c->count = c->count % 1024 + 8;
 }
 
+/* GOST encryptoon in CBC mode */
+int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out,
+	const unsigned char *in, size_t inl)
+	{
+	OPENSSL_assert(inl % 8 ==0);
+	unsigned char b[8];
+	const unsigned char *in_ptr=in;
+	unsigned char *out_ptr=out;
+	int i;
+	struct ossl_gost_cipher_ctx *c = ctx->cipher_data;
+	if (ctx->encrypt)
+		{
+		while(inl>0)
+		    {
+			for (i=0;i<8;i++)
+			   {
+				b[i]=ctx->iv[i]^in_ptr[i];
+		     	}
+			gostcrypt(&(c->cctx),b,out_ptr);
+			memcpy(ctx->iv,out_ptr,8);
+			out_ptr+=8;
+			in_ptr+=8;
+			inl-=8;
+		    }
+		}
+	else
+		{
+		while (inl>0) {
+			gostdecrypt(&(c->cctx),in_ptr,b);
+			for (i=0;i<8;i++)
+			    {
+				out_ptr[i]=ctx->iv[i]^b[i];
+			    }
+			memcpy(ctx->iv,in_ptr,8);
+			out_ptr+=8;
+			in_ptr+=8;
+			inl-=8;
+		    }
+	    }
+	return 1;
+	}
 /* GOST encryption in CFB mode */
 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
                        const unsigned char *in, size_t inl)
@@ -509,6 +582,7 @@
     c->count = 0;
     c->bytes_left = 0;
     c->key_meshing = 1;
+    c->dgst_size = 4;
     gost_init(&(c->cctx), &Gost28147_CryptoProParamSetA);
     return 1;
 }
@@ -581,7 +655,7 @@
         }
         mac_block_mesh(c, c->partial_block);
     }
-    get_mac(c->buffer, 32, md);
+    get_mac(c->buffer, 8 * c->dgst_size, md);
     return 1;
 }
 
@@ -594,7 +668,7 @@
     case EVP_MD_CTRL_SET_KEY:
         {
             if (arg != 32) {
-                GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_LENGTH);
+                GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_KEY_SIZE);
                 return 0;
             }
 
@@ -604,6 +678,17 @@
             return 1;
 
         }
+    case EVP_MD_CTRL_MAC_LEN:
+        {
+            if (arg < 1 || arg > 8) {
+                GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE);
+                return 0;
+            }
+            struct ossl_gost_imit_ctx *c = ctx->md_data;
+            c->dgst_size=arg;
+            return 1;
+        }
+
     default:
         return 0;
     }
diff -ruN openssl-1.0.2d.orig/engines/ccgost/gost_eng.c openssl-1.0.2d/engines/ccgost/gost_eng.c
--- openssl-1.0.2d.orig/engines/ccgost/gost_eng.c	2015-06-11 17:44:27.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/gost_eng.c	2015-07-31 16:48:10.322163688 +0300
@@ -33,7 +33,8 @@
 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
                                 const int **nids, int nid);
 
-static int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 };
+static int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 
+                                  NID_gost89_cbc, 0 };
 
 static int gost_digest_nids[] =
     { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 };
@@ -144,6 +145,7 @@
         || !ENGINE_register_pkey_meths(e)
         /* These two actually should go in LIST_ADD command */
         || !EVP_add_cipher(&cipher_gost)
+        || !EVP_add_cipher(&cipher_gost_cbc)
         || !EVP_add_cipher(&cipher_gost_cpacnt)
         || !EVP_add_digest(&digest_gost)
         || !EVP_add_digest(&imit_gost_cpa)
@@ -189,13 +191,15 @@
     int ok = 1;
     if (!cipher) {
         *nids = gost_cipher_nids;
-        return 2;               /* two ciphers are supported */
+        return 3;               /* three ciphers are supported */
     }
 
     if (nid == NID_id_Gost28147_89) {
         *cipher = &cipher_gost;
     } else if (nid == NID_gost89_cnt) {
         *cipher = &cipher_gost_cpacnt;
+    } else if (nid == NID_gost89_cbc) {
+        *cipher = &cipher_gost_cbc;
     } else {
         ok = 0;
         *cipher = NULL;
diff -ruN openssl-1.0.2d.orig/engines/ccgost/gost_lcl.h openssl-1.0.2d/engines/ccgost/gost_lcl.h
--- openssl-1.0.2d.orig/engines/ccgost/gost_lcl.h	2015-06-11 17:44:27.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/gost_lcl.h	2015-07-31 16:50:51.931302131 +0300
@@ -42,7 +42,9 @@
 /* For GOST 28147 MAC */
 # define key_ctrl_string "key"
 # define hexkey_ctrl_string "hexkey"
+# define maclen_ctrl_string "size"
 # define EVP_PKEY_CTRL_GOST_MAC_HEXKEY (EVP_PKEY_ALG_CTRL+3)
+# define EVP_PKEY_CTRL_MAC_LEN (EVP_PKEY_ALG_CTRL+5)
 /* Pmeth internal representation */
 struct gost_pmeth_data {
     int sign_param_nid;         /* Should be set whenever parameters are
@@ -53,7 +55,8 @@
 };
 
 struct gost_mac_pmeth_data {
-    int key_set;
+    short int key_set;
+	short int mac_size;
     EVP_MD *md;
     unsigned char key[32];
 };
@@ -156,6 +159,7 @@
     int key_meshing;
     int bytes_left;
     int key_set;
+	int dgst_size;
 };
 /* Table which maps parameter NID to S-blocks */
 extern struct gost_cipher_info gost_cipher_list[];
@@ -163,9 +167,11 @@
 const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj);
 /* Implementation of GOST 28147-89 cipher in CFB and CNT modes */
 extern EVP_CIPHER cipher_gost;
+extern EVP_CIPHER cipher_gost_cbc;
 extern EVP_CIPHER cipher_gost_cpacnt;
 # define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3)
 # define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4)
+# define EVP_MD_CTRL_MAC_LEN (EVP_MD_CTRL_ALG_CTRL+5)
 /* EVP_PKEY_METHOD key encryption callbacks */
 /* From gost94_keyx.c */
 int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
diff -ruN openssl-1.0.2d.orig/engines/ccgost/gost_pmeth.c openssl-1.0.2d/engines/ccgost/gost_pmeth.c
--- openssl-1.0.2d.orig/engines/ccgost/gost_pmeth.c	2015-07-09 14:57:15.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/gost_pmeth.c	2015-07-31 16:55:31.717259561 +0300
@@ -411,6 +411,7 @@
     if (!data)
         return 0;
     memset(data, 0, sizeof(struct gost_mac_pmeth_data));
+	data->mac_size = 4;
     EVP_PKEY_CTX_set_data(ctx, data);
     return 1;
 }
@@ -490,6 +491,17 @@
             }
             return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key);
         }
+	case EVP_PKEY_CTRL_MAC_LEN:	
+		{
+			if (p1<1 || p1>8)
+				{
+					
+					GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL,GOST_R_INVALID_MAC_SIZE);
+					return 0;
+				}
+				data->mac_size = p1;
+				return 1;
+		}
     }
     return -2;
 }
@@ -521,6 +533,16 @@
         return ret;
 
     }
+	if (!strcmp(type,maclen_ctrl_string)) {
+		char *endptr;
+		long size=strtol(value,&endptr,10);
+		if (*endptr!='\0') {
+			GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR,
+				   GOST_R_INVALID_MAC_SIZE);
+			return 0;
+		}
+		return pkey_gost_mac_ctrl(ctx, EVP_PKEY_CTRL_MAC_LEN,size,NULL);
+	}
     return -2;
 }
 
@@ -546,15 +568,15 @@
 static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
                                  size_t *siglen, EVP_MD_CTX *mctx)
 {
-    unsigned int tmpsiglen = *siglen; /* for platforms where
-                                       * sizeof(int)!=sizeof(size_t) */
     int ret;
+    struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
     if (!sig) {
-        *siglen = 4;
+        *siglen = data->mac_size;
         return 1;
     }
-    ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
-    *siglen = tmpsiglen;
+	mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
+	ret=EVP_DigestFinal_ex(mctx, sig, NULL);
+	*siglen = data->mac_size;
     return ret;
 }
 
diff -ruN openssl-1.0.2d.orig/engines/ccgost/README.gost openssl-1.0.2d/engines/ccgost/README.gost
--- openssl-1.0.2d.orig/engines/ccgost/README.gost	2015-07-09 14:53:21.000000000 +0300
+++ openssl-1.0.2d/engines/ccgost/README.gost	2015-07-31 16:08:14.773263918 +0300
@@ -28,6 +28,8 @@
 	It has 256-bit symmetric key and only 32 bits of MAC value
 	(while HMAC has same key size and value size). 
 
+	Really, this algorithm supports from 8 to 64 bits of the MAC value
+
 	It is implemented as combination of EVP_PKEY type and EVP_MD type.
 
 USAGE OF THESE ALGORITHMS
@@ -198,11 +200,30 @@
  implementation of this mac) and OpenSSL is clever enough to find out
  this.
 
+ Following mac options are supported:
+
+ key:(32 bytes of key)
+
+ hexkey:(64 hexadecimal digits of key)
+
+ Engine support calculation of mac with size different from default 32
+ bits. You can set mac size to any value from 1 to 8 bytes using
+
+ -sigopt size:(number from 1 to 8 - mac size in bytes)
+
+ (dgst command uses different EVP_PKEY_CTX for initialization and for
+  finalization of MAC. Option of first are set via -macopt, and for
+  second via -sigopt. Key should be set during initialization and size
+  during finalization. If you use API functions
+  EVP_DigestSignInit/EVP_DigestSignFinal, you can set both options at
+  the same time).
+
  Encryption with GOST 28147 CFB mode
  openssl enc -gost89 -out encrypted-file -in plain-text-file -k <passphrase>  
  Encryption with GOST 28147 CNT mode
  openssl enc -gost89-cnt -out encrypted-file -in plain-text-file -k <passphrase>
-
+ Encryption with GOST 28147 CBC mode
+ openssl enc -gost89-cbc -out encrypted-file -in plain-text-file -k <passphrase>
 
 6. Encrypting private keys and PKCS12
 
@@ -221,6 +242,7 @@
 
  openssl speed -evp gost89
  openssl speed -evp gost89-cnt
+ openssl speed -evp gost89-cbc
 
 
 PROGRAMMING INTERFACES DETAILS
