LCOV - code coverage report
Current view: top level - cipher - gostr3411-94.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 145 148 98.0 %
Date: 2017-03-02 16:44:37 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /* gostr3411-94.c - GOST R 34.11-94 hash function
       2             :  * Copyright (C) 2012 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser General Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : 
      26             : #include "g10lib.h"
      27             : #include "bithelp.h"
      28             : #include "bufhelp.h"
      29             : #include "cipher.h"
      30             : #include "hash-common.h"
      31             : 
      32             : #include "gost.h"
      33             : 
      34             : #define max(a, b) (((a) > (b)) ? (a) : (b))
      35             : 
      36             : typedef struct {
      37             :   gcry_md_block_ctx_t bctx;
      38             :   GOST28147_context hd;
      39             :   union {
      40             :     u32 h[8];
      41             :     byte result[32];
      42             :   };
      43             :   u32 sigma[8];
      44             :   u32 len;
      45             :   int cryptopro;
      46             : } GOSTR3411_CONTEXT;
      47             : 
      48             : static unsigned int
      49             : transform (void *c, const unsigned char *data, size_t nblks);
      50             : 
      51             : static void
      52        3409 : gost3411_init (void *context, unsigned int flags)
      53             : {
      54        3409 :   GOSTR3411_CONTEXT *hd = context;
      55             : 
      56             :   (void)flags;
      57             : 
      58        3409 :   memset (&hd->hd, 0, sizeof(hd->hd));
      59        3409 :   memset (hd->h, 0, 32);
      60        3409 :   memset (hd->sigma, 0, 32);
      61             : 
      62        3409 :   hd->bctx.nblocks = 0;
      63        3409 :   hd->bctx.count = 0;
      64        3409 :   hd->bctx.blocksize = 32;
      65        3409 :   hd->bctx.bwrite = transform;
      66        3409 :   hd->cryptopro = 0;
      67        3409 : }
      68             : 
      69             : static void
      70        1487 : gost3411_cp_init (void *context, unsigned int flags)
      71             : {
      72        1487 :   GOSTR3411_CONTEXT *hd = context;
      73        1487 :   gost3411_init (context, flags);
      74        1487 :   hd->cryptopro = 1;
      75        1487 : }
      76             : 
      77             : static void
      78     3212820 : do_p (u32 *p, u32 *u, u32 *v)
      79             : {
      80             :   int k;
      81             :   u32 t[8];
      82             : 
      83    28915380 :   for (k = 0; k < 8; k++)
      84    25702560 :     t[k] = u[k] ^ v[k];
      85             : 
      86    16064100 :   for (k = 0; k < 4; k++)
      87             :     {
      88    38553840 :           p[k+0] = ((t[0] >> (8*k)) & 0xff) << 0 |
      89    25702560 :                    ((t[2] >> (8*k)) & 0xff) << 8 |
      90    25702560 :                    ((t[4] >> (8*k)) & 0xff) << 16 |
      91    12851280 :                    ((t[6] >> (8*k)) & 0xff) << 24;
      92    38553840 :           p[k+4] = ((t[1] >> (8*k)) & 0xff) << 0 |
      93    25702560 :                    ((t[3] >> (8*k)) & 0xff) << 8 |
      94    25702560 :                    ((t[5] >> (8*k)) & 0xff) << 16 |
      95    12851280 :                    ((t[7] >> (8*k)) & 0xff) << 24;
      96             :     }
      97     3212820 : }
      98             : 
      99             : static void
     100     3212820 : do_a (u32 *u)
     101             : {
     102             :   u32 t[2];
     103             :   int i;
     104     3212820 :   memcpy(t, u, 2*4);
     105    22489740 :   for (i = 0; i < 6; i++)
     106    19276920 :     u[i] = u[i+2];
     107     3212820 :   u[6] = u[0] ^ t[0];
     108     3212820 :   u[7] = u[1] ^ t[1];
     109     3212820 : }
     110             : /* apply do_a twice: 1 2 3 4 -> 3 4 1^2 2^3 */
     111             : static void
     112     3212820 : do_a2 (u32 *u)
     113             : {
     114             :   u32 t[4];
     115             :   int i;
     116     3212820 :   memcpy (t, u, 16);
     117     3212820 :   memcpy (u, u + 4, 16);
     118     9638460 :   for (i = 0; i < 2; i++)
     119             :     {
     120     6425640 :       u[4+i] = t[i] ^ t[i + 2];
     121     6425640 :       u[6+i] = u[i] ^ t[i + 2];
     122             :     }
     123     3212820 : }
     124             : 
     125             : static void
     126      803205 : do_apply_c2 (u32 *u)
     127             : {
     128      803205 :   u[ 0] ^= 0xff00ff00;
     129      803205 :   u[ 1] ^= 0xff00ff00;
     130      803205 :   u[ 2] ^= 0x00ff00ff;
     131      803205 :   u[ 3] ^= 0x00ff00ff;
     132      803205 :   u[ 4] ^= 0x00ffff00;
     133      803205 :   u[ 5] ^= 0xff0000ff;
     134      803205 :   u[ 6] ^= 0x000000ff;
     135      803205 :   u[ 7] ^= 0xff00ffff;
     136      803205 : }
     137             : 
     138             : #define do_chi_step12(e) \
     139             :   e[6] ^= ((e[6] >> 16) ^ e[7] ^ (e[7] >> 16) ^ e[4] ^ (e[5] >>16)) & 0xffff;
     140             : 
     141             : #define do_chi_step13(e) \
     142             :   e[6] ^= ((e[7] ^ (e[7] >> 16) ^ e[0] ^ (e[4] >> 16) ^ e[6]) & 0xffff) << 16;
     143             : 
     144             : #define do_chi_doublestep(e, i) \
     145             :   e[i] ^= (e[i] >> 16) ^ (e[(i+1)%8] << 16) ^ e[(i+1)%8] ^ (e[(i+1)%8] >> 16) ^ (e[(i+2)%8] << 16) ^ e[(i+6)%8] ^ (e[(i+7)%8] >> 16); \
     146             :   e[i] ^= (e[i] << 16);
     147             : 
     148             : static void
     149      803205 : do_chi_submix12 (u32 *e, u32 *x)
     150             : {
     151      803205 :   e[6] ^= x[0];
     152      803205 :   e[7] ^= x[1];
     153      803205 :   e[0] ^= x[2];
     154      803205 :   e[1] ^= x[3];
     155      803205 :   e[2] ^= x[4];
     156      803205 :   e[3] ^= x[5];
     157      803205 :   e[4] ^= x[6];
     158      803205 :   e[5] ^= x[7];
     159      803205 : }
     160             : 
     161             : static void
     162      803205 : do_chi_submix13 (u32 *e, u32 *x)
     163             : {
     164      803205 :   e[6] ^= (x[0] << 16) | (x[7] >> 16);
     165      803205 :   e[7] ^= (x[1] << 16) | (x[0] >> 16);
     166      803205 :   e[0] ^= (x[2] << 16) | (x[1] >> 16);
     167      803205 :   e[1] ^= (x[3] << 16) | (x[2] >> 16);
     168      803205 :   e[2] ^= (x[4] << 16) | (x[3] >> 16);
     169      803205 :   e[3] ^= (x[5] << 16) | (x[4] >> 16);
     170      803205 :   e[4] ^= (x[6] << 16) | (x[5] >> 16);
     171      803205 :   e[5] ^= (x[7] << 16) | (x[6] >> 16);
     172      803205 : }
     173             : 
     174             : static void
     175      664121 : do_add (u32 *s, u32 *a)
     176             : {
     177      664121 :   u32 carry = 0;
     178             :   int i;
     179             : 
     180     5977089 :   for (i = 0; i < 8; i++)
     181             :     {
     182     5312968 :       u32 op = carry + a[i];
     183     5312968 :       s[i] += op;
     184     5312968 :       carry = (a[i] > op) || (op > s[i]);
     185             :     }
     186      664121 : }
     187             : 
     188             : static unsigned int
     189      803205 : do_hash_step (GOSTR3411_CONTEXT *hd, u32 *h, u32 *m)
     190             : {
     191             :   u32 u[8], v[8];
     192             :   u32 s[8];
     193             :   u32 k[8];
     194             :   unsigned int burn;
     195             :   int i;
     196             : 
     197      803205 :   memcpy (u, h, 32);
     198      803205 :   memcpy (v, m, 32);
     199             : 
     200     4016025 :   for (i = 0; i < 4; i++) {
     201     3212820 :     do_p (k, u, v);
     202             : 
     203     3212820 :     burn = _gcry_gost_enc_data (&hd->hd, k, &s[2*i], &s[2*i+1], h[2*i], h[2*i+1], hd->cryptopro);
     204             : 
     205     3212820 :     do_a (u);
     206     3212820 :     if (i == 1)
     207      803205 :       do_apply_c2 (u);
     208     3212820 :     do_a2 (v);
     209             :   }
     210             : 
     211     4016025 :   for (i = 0; i < 5; i++)
     212             :     {
     213     4016025 :       do_chi_doublestep (s, 0);
     214     4016025 :       do_chi_doublestep (s, 1);
     215     4016025 :       do_chi_doublestep (s, 2);
     216     4016025 :       do_chi_doublestep (s, 3);
     217     4016025 :       do_chi_doublestep (s, 4);
     218             :       /* That is in total 12 + 1 + 61 = 74 = 16 * 4 + 10 rounds */
     219     4016025 :       if (i == 4)
     220      803205 :         break;
     221     3212820 :       do_chi_doublestep (s, 5);
     222     3212820 :       if (i == 0)
     223      803205 :         do_chi_submix12(s, m);
     224     3212820 :       do_chi_step12 (s);
     225     3212820 :       if (i == 0)
     226      803205 :         do_chi_submix13(s, h);
     227     3212820 :       do_chi_step13 (s);
     228     3212820 :       do_chi_doublestep (s, 7);
     229             :     }
     230             : 
     231      803205 :   memcpy (h, s+5, 12);
     232      803205 :   memcpy (h+3, s, 20);
     233             : 
     234             :   return /* burn_stack */ 4 * sizeof(void*) /* func call (ret addr + args) */ +
     235      803205 :                           4 * 32 + 2 * sizeof(int) /* stack */ +
     236             :                           max(burn /* _gcry_gost_enc_one */,
     237             :                               sizeof(void*) * 2 /* do_a2 call */ +
     238             :                               16 + sizeof(int) /* do_a2 stack */ );
     239             : }
     240             : 
     241             : static unsigned int
     242      664121 : transform_blk (void *ctx, const unsigned char *data)
     243             : {
     244      664121 :   GOSTR3411_CONTEXT *hd = ctx;
     245             :   u32 m[8];
     246             :   unsigned int burn;
     247             :   int i;
     248             : 
     249     5977089 :   for (i = 0; i < 8; i++)
     250     5312968 :     m[i] = buf_get_le32(data + i*4);
     251      664121 :   burn = do_hash_step (hd, hd->h, m);
     252      664121 :   do_add (hd->sigma, m);
     253             : 
     254      664121 :   return /* burn_stack */ burn + 3 * sizeof(void*) + 32 + 2 * sizeof(void*);
     255             : }
     256             : 
     257             : 
     258             : static unsigned int
     259      664121 : transform ( void *c, const unsigned char *data, size_t nblks )
     260             : {
     261             :   unsigned int burn;
     262             : 
     263             :   do
     264             :     {
     265      664121 :       burn = transform_blk (c, data);
     266      664121 :       data += 32;
     267             :     }
     268      664121 :   while (--nblks);
     269             : 
     270      240023 :   return burn;
     271             : }
     272             : 
     273             : 
     274             : /*
     275             :    The routine finally terminates the computation and returns the
     276             :    digest.  The handle is prepared for a new cycle, but adding bytes
     277             :    to the handle will the destroy the returned buffer.  Returns: 32
     278             :    bytes with the message the digest.  */
     279             : static void
     280       69542 : gost3411_final (void *context)
     281             : {
     282       69542 :   GOSTR3411_CONTEXT *hd = context;
     283       69542 :   size_t padlen = 0;
     284             :   u32 l[8];
     285             :   int i;
     286             :   MD_NBLOCKS_TYPE nblocks;
     287             : 
     288       69542 :   if (hd->bctx.count > 0)
     289             :     {
     290        2812 :       padlen = 32 - hd->bctx.count;
     291        2812 :       memset (hd->bctx.buf + hd->bctx.count, 0, padlen);
     292        2812 :       hd->bctx.count += padlen;
     293        2812 :       _gcry_md_block_write (hd, NULL, 0); /* flush */;
     294             :     }
     295             : 
     296       69542 :   if (hd->bctx.count != 0)
     297           0 :     return; /* Something went wrong */
     298             : 
     299       69542 :   memset (l, 0, 32);
     300             : 
     301       69542 :   nblocks = hd->bctx.nblocks;
     302       69542 :   if (padlen)
     303             :     {
     304        2812 :       nblocks --;
     305        2812 :       l[0] = 256 - padlen * 8;
     306             :     }
     307       69542 :   l[0] |= nblocks << 8;
     308       69542 :   nblocks >>= 24;
     309             : 
     310       69542 :   for (i = 1; i < 8 && nblocks != 0; i++)
     311             :     {
     312           0 :       l[i] = nblocks;
     313           0 :       nblocks >>= 24;
     314             :     }
     315             : 
     316       69542 :   do_hash_step (hd, hd->h, l);
     317       69542 :   do_hash_step (hd, hd->h, hd->sigma);
     318      625878 :   for (i = 0; i < 8; i++)
     319      556336 :     hd->h[i] = le_bswap32(hd->h[i]);
     320             : }
     321             : 
     322             : static byte *
     323       68030 : gost3411_read (void *context)
     324             : {
     325       68030 :   GOSTR3411_CONTEXT *hd = context;
     326             : 
     327       68030 :   return hd->result;
     328             : }
     329             : 
     330             : static unsigned char asn[6] = /* Object ID is 1.2.643.2.2.3 */
     331             :   { 0x2a, 0x85, 0x03, 0x02, 0x02, 0x03 };
     332             : 
     333             : static gcry_md_oid_spec_t oid_spec_gostr3411[] =
     334             :   {
     335             :     /* iso.member-body.ru.rans.cryptopro.3 (gostR3411-94-with-gostR3410-2001) */
     336             :     { "1.2.643.2.2.3" },
     337             :     /* iso.member-body.ru.rans.cryptopro.9 (gostR3411-94) */
     338             :     { "1.2.643.2.2.9" },
     339             :     {NULL},
     340             :   };
     341             : 
     342             : gcry_md_spec_t _gcry_digest_spec_gost3411_94 =
     343             :   {
     344             :     GCRY_MD_GOSTR3411_94, {0, 0},
     345             :     "GOSTR3411_94", NULL, 0, NULL, 32,
     346             :     gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
     347             :     sizeof (GOSTR3411_CONTEXT)
     348             :   };
     349             : gcry_md_spec_t _gcry_digest_spec_gost3411_cp =
     350             :   {
     351             :     GCRY_MD_GOSTR3411_CP, {0, 0},
     352             :     "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32,
     353             :     gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL,
     354             :     sizeof (GOSTR3411_CONTEXT)
     355             :   };

Generated by: LCOV version 1.13