]> 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). 
 
+       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 @@ Russian clients and RSA/DSA ciphersuites for foreign clients.
  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 @@ accessed by cipher-specific functions, only via generic evp interface
 
  openssl speed -evp gost89
  openssl speed -evp gost89-cnt
+ openssl speed -evp gost89-cbc
 
 
 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_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"},
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_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
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_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,
@@ -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 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);
@@ -58,6 +63,24 @@ EVP_CIPHER cipher_gost = {
     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 */
@@ -277,6 +300,15 @@ int gost_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                                   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
@@ -326,6 +358,47 @@ static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf)
     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)
@@ -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->dgst_size = 4;
     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);
     }
-    get_mac(c->buffer, 32, md);
+    get_mac(c->buffer, 8 * c->dgst_size, md);
     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) {
-                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;
             }
 
@@ -699,6 +773,17 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr)
             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;
     }
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_gost89_cbc,
     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)
+        || !EVP_add_cipher(&cipher_gost_cbc)
         || !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;
-        return 3;               /* three ciphers are supported */
+        return 4;               /* three ciphers are supported */
     }
 
     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;
+    } else if (nid == NID_gost89_cbc) {
+        *cipher = &cipher_gost_cbc;
     } 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"
+# 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
@@ -69,7 +71,8 @@ struct gost_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];
 };
@@ -184,6 +187,7 @@ struct ossl_gost_imit_ctx {
     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[];
@@ -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;
+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)
+# 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,
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));
+       data->mac_size = 4;
     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);
         }
+       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;
 }
@@ -584,6 +596,16 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx,
         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;
 }
 
@@ -624,6 +646,7 @@ static int pkey_gost_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
 {
     unsigned int tmpsiglen;
     int ret;
+       struct gost_mac_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
 
     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) {
-        *siglen = 4;
+        *siglen = data->mac_size;
         return 1;
     }
+
+       mctx->digest->md_ctrl(mctx, EVP_MD_CTRL_MAC_LEN, data->mac_size, NULL);
     ret = EVP_DigestFinal_ex(mctx, sig, &tmpsiglen);
-    *siglen = tmpsiglen;
+    *siglen = data->mac_size;
     return ret;
 }