]> www.wagner.pp.ru Git - openssl-gost/engine.git/commitdiff
Added CBC mode for gost and contril command to set size of MAC (from 1 to 8 bytes)
authorVictor Wagner <vitus@wagner.pp.ru>
Sun, 23 Aug 2015 12:31:58 +0000 (15:31 +0300)
committerVictor Wagner <vitus@wagner.pp.ru>
Sun, 23 Aug 2015 12:31:58 +0000 (15:31 +0300)
README.gost
e_gost_err.c
e_gost_err.h
gost_crypt.c
gost_eng.c
gost_lcl.h
gost_pmeth.c

index abc5a9b7ca67c070b61b41c1b1e4e6f0ea54efa4..3a48d9568db125d636571deb2e11cb0ec672dcda 100644 (file)
@@ -28,6 +28,8 @@ GOST 28147-89 MAC mode. Message authentication code. While most MAC
        It has 256-bit symmetric key and only 32 bits of MAC value
        (while HMAC has same key size and value size). 
 
        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
        It is implemented as combination of EVP_PKEY type and EVP_MD type.
 
 USAGE OF THESE ALGORITHMS
@@ -198,11 +200,30 @@ Russian clients and RSA/DSA ciphersuites for foreign clients.
  implementation of this mac) and OpenSSL is clever enough to find out
  this.
 
  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 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
 
 
 6. Encrypting private keys and PKCS12
 
@@ -221,6 +242,7 @@ accessed by cipher-specific functions, only via generic evp interface
 
  openssl speed -evp gost89
  openssl speed -evp gost89-cnt
 
  openssl speed -evp gost89
  openssl speed -evp gost89-cnt
+ openssl speed -evp gost89-cbc
 
 
 PROGRAMMING INTERFACES DETAILS
 
 
 PROGRAMMING INTERFACES DETAILS
index c641c60200c2ae543a6ae131e31a2b83c7fb841c..376d18b830ba1c2c136ead2ea5e35377b240b3fb 100644 (file)
@@ -139,6 +139,8 @@ static ERR_STRING_DATA GOST_str_reasons[] = {
     {ERR_REASON(GOST_R_INVALID_DIGEST_TYPE), "invalid digest type"},
     {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_DIGEST_TYPE), "invalid digest type"},
     {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"},
     {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"},
index 5e7e8e44686879dfa6f464741d0e6089a3966626..b2d9a4feae285f6ca66f4d0d4aec3dd068b3a99c 100644 (file)
@@ -132,6 +132,8 @@ void ERR_GOST_error(int function, int reason, char *file, int line);
 # define GOST_R_INVALID_DIGEST_TYPE                       110
 # define GOST_R_INVALID_IV_LENGTH                         111
 # define GOST_R_INVALID_MAC_KEY_LENGTH                    112
 # define GOST_R_INVALID_DIGEST_TYPE                       110
 # define GOST_R_INVALID_IV_LENGTH                         111
 # define GOST_R_INVALID_MAC_KEY_LENGTH                    112
+# define GOST_R_INVALID_MAC_KEY_SIZE                      145
+# define GOST_R_INVALID_MAC_SIZE                          146
 # define GOST_R_INVALID_PARAMSET                          113
 # define GOST_R_KEY_IS_NOT_INITALIZED                     114
 # define GOST_R_KEY_IS_NOT_INITIALIZED                    115
 # define GOST_R_INVALID_PARAMSET                          113
 # define GOST_R_KEY_IS_NOT_INITALIZED                     114
 # define GOST_R_KEY_IS_NOT_INITIALIZED                    115
index 668e881be38a1c7be8966336c2653a38c122ddba..d1e8113b4159fb63d37d4d4d511a5bf23b6e20e1 100644 (file)
@@ -22,6 +22,8 @@
 
 static int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                             const unsigned char *iv, int enc);
 
 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);
 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
 static int gost_cipher_init_cpa(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                                 const unsigned char *iv, int enc);
 static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
@@ -30,6 +32,9 @@ static int gost_cipher_init_cp_12(EVP_CIPHER_CTX *ctx,
 /* 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 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);
 /* 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);
@@ -58,6 +63,24 @@ EVP_CIPHER cipher_gost = {
     NULL,
 };
 
     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 */
 EVP_CIPHER cipher_gost_cpacnt = {
     NID_gost89_cnt,
     1,                          /* block_size */
@@ -277,6 +300,15 @@ int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                                   EVP_CIPH_CFB_MODE);
 }
 
                                   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
 /*
  * Wrapper around gostcrypt function from gost89.c which perform key meshing
  * when nesseccary
@@ -326,6 +358,47 @@ static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf)
     c->count = c->count % 1024 + 8;
 }
 
     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)
 /* GOST encryption in CFB mode */
 int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out,
                        const unsigned char *in, size_t inl)
@@ -594,6 +667,7 @@ static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block)
     c->count = 0;
     c->bytes_left = 0;
     c->key_meshing = 1;
     c->count = 0;
     c->bytes_left = 0;
     c->key_meshing = 1;
+    c->dgst_size = 4;
     gost_init(&(c->cctx), block);
     return 1;
 }
     gost_init(&(c->cctx), block);
     return 1;
 }
@@ -676,7 +750,7 @@ int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md)
         }
         mac_block_mesh(c, c->partial_block);
     }
         }
         mac_block_mesh(c, c->partial_block);
     }
-    get_mac(c->buffer, 32, md);
+    get_mac(c->buffer, 8 * c->dgst_size, md);
     return 1;
 }
 
     return 1;
 }
 
@@ -689,7 +763,7 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
     case EVP_MD_CTRL_SET_KEY:
         {
             if (arg != 32) {
     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;
             }
 
                 return 0;
             }
 
@@ -699,6 +773,17 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
             return 1;
 
         }
             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;
     }
     default:
         return 0;
     }
index 9df6a74da9ad420c6e0f06189a56be2d012946bd..86d1a05b7e586767469d8ced1032c588a8240dea 100644 (file)
@@ -37,6 +37,7 @@ static int gost_cipher_nids[] = {
     NID_id_Gost28147_89,
     NID_gost89_cnt,
     NID_gost89_cnt_12,
     NID_id_Gost28147_89,
     NID_gost89_cnt,
     NID_gost89_cnt_12,
+    NID_gost89_cbc,
     0
 };
 
     0
 };
 
@@ -186,6 +187,7 @@ static int bind_gost(ENGINE *e, const char *id)
         || !ENGINE_register_pkey_meths(e)
         /* These two actually should go in LIST_ADD command */
         || !EVP_add_cipher(&cipher_gost)
         || !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_cipher(&cipher_gost_cpcnt_12)
         || !EVP_add_digest(&digest_gost)
         || !EVP_add_cipher(&cipher_gost_cpacnt)
         || !EVP_add_cipher(&cipher_gost_cpcnt_12)
         || !EVP_add_digest(&digest_gost)
@@ -238,7 +240,7 @@ static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
     int ok = 1;
     if (!cipher) {
         *nids = gost_cipher_nids;
     int ok = 1;
     if (!cipher) {
         *nids = gost_cipher_nids;
-        return 3;               /* three ciphers are supported */
+        return 4;               /* three ciphers are supported */
     }
 
     if (nid == NID_id_Gost28147_89) {
     }
 
     if (nid == NID_id_Gost28147_89) {
@@ -247,6 +249,8 @@ static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
         *cipher = &cipher_gost_cpacnt;
     } else if (nid == NID_gost89_cnt_12) {
         *cipher = &cipher_gost_cpcnt_12;
         *cipher = &cipher_gost_cpacnt;
     } else if (nid == NID_gost89_cnt_12) {
         *cipher = &cipher_gost_cpcnt_12;
+    } else if (nid == NID_gost89_cbc) {
+        *cipher = &cipher_gost_cbc;
     } else {
         ok = 0;
         *cipher = NULL;
     } else {
         ok = 0;
         *cipher = NULL;
index 4e1c4ea26cd16c69a3c5074156354842881350a9..b89c453f4ae94303d47b84cd1c9e9582def06ed5 100644 (file)
@@ -58,7 +58,9 @@ int register_pmeth_gost(int id, EVP_PKEY_METHOD **pmeth, int flags);
 /* For GOST 28147 MAC */
 # define key_ctrl_string "key"
 # define hexkey_ctrl_string "hexkey"
 /* 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_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
 /* Pmeth internal representation */
 struct gost_pmeth_data {
     int sign_param_nid;         /* Should be set whenever parameters are
@@ -69,7 +71,8 @@ struct gost_pmeth_data {
 };
 
 struct gost_mac_pmeth_data {
 };
 
 struct gost_mac_pmeth_data {
-    int key_set;
+    short int key_set;
+       short int mac_size;
     EVP_MD *md;
     unsigned char key[32];
 };
     EVP_MD *md;
     unsigned char key[32];
 };
@@ -184,6 +187,7 @@ struct ossl_gost_imit_ctx {
     int key_meshing;
     int bytes_left;
     int key_set;
     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[];
 };
 /* Table which maps parameter NID to S-blocks */
 extern struct gost_cipher_info gost_cipher_list[];
@@ -191,10 +195,12 @@ extern struct gost_cipher_info gost_cipher_list[];
 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;
 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;
 extern EVP_CIPHER cipher_gost_cpcnt_12;
 # define EVP_MD_CTRL_KEY_LEN (EVP_MD_CTRL_ALG_CTRL+3)
 # define EVP_MD_CTRL_SET_KEY (EVP_MD_CTRL_ALG_CTRL+4)
 extern EVP_CIPHER cipher_gost_cpacnt;
 extern EVP_CIPHER cipher_gost_cpcnt_12;
 # 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 gost_ec_keyx.c */
 int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
 /* EVP_PKEY_METHOD key encryption callbacks */
 /* From gost_ec_keyx.c */
 int pkey_GOST_ECcp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out,
index a8252172dbb304722c9a6044bbc8d19f5849bb09..896dabb1a1146155ed88500b86db77ce63f636ff 100644 (file)
@@ -470,6 +470,7 @@ static int pkey_gost_mac_init(EVP_PKEY_CTX *ctx)
     if (!data)
         return 0;
     memset(data, 0, sizeof(*data));
     if (!data)
         return 0;
     memset(data, 0, sizeof(*data));
+       data->mac_size = 4;
     EVP_PKEY_CTX_set_data(ctx, data);
     return 1;
 }
     EVP_PKEY_CTX_set_data(ctx, data);
     return 1;
 }
@@ -553,6 +554,17 @@ static int pkey_gost_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
             }
             return mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_SET_KEY, 32, key);
         }
             }
             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;
 }
     }
     return -2;
 }
@@ -584,6 +596,16 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
         return ret;
 
     }
         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;
 }
 
     return -2;
 }
 
@@ -624,6 +646,7 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
 {
     unsigned int tmpsiglen;
     int ret;
 {
     unsigned int tmpsiglen;
     int ret;
+       struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
 
     if (!siglen)
         return 0;
 
     if (!siglen)
         return 0;
@@ -631,11 +654,13 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
                                  * sizeof(size_t) */
 
     if (!sig) {
                                  * sizeof(size_t) */
 
     if (!sig) {
-        *siglen = 4;
+        *siglen = data->mac_size;
         return 1;
     }
         return 1;
     }
+
+       mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
-    *siglen = tmpsiglen;
+    *siglen = data->mac_size;
     return ret;
 }
 
     return ret;
 }