(root)/
libxcrypt-4.4.36/
lib/
alg-gost3411-2012-core.c
       1  /*
       2   * Copyright (c) 2013, Alexey Degtyarev <alexey@renatasystems.org>.
       3   * All rights reserved.
       4   *
       5   * GOST R 34.11-2012 core and API functions.
       6   *
       7   * $Id$
       8   */
       9  
      10  #include "crypt-port.h"
      11  
      12  #if INCLUDE_gost_yescrypt
      13  
      14  #include "alg-gost3411-2012-core.h"
      15  
      16  #pragma GCC diagnostic ignored "-Wcast-align"
      17  
      18  #define BSWAP64(x) \
      19      (((x & 0xFF00000000000000ULL) >> 56) | \
      20       ((x & 0x00FF000000000000ULL) >> 40) | \
      21       ((x & 0x0000FF0000000000ULL) >> 24) | \
      22       ((x & 0x000000FF00000000ULL) >>  8) | \
      23       ((x & 0x00000000FF000000ULL) <<  8) | \
      24       ((x & 0x0000000000FF0000ULL) << 24) | \
      25       ((x & 0x000000000000FF00ULL) << 40) | \
      26       ((x & 0x00000000000000FFULL) << 56))
      27  
      28  void
      29  GOST34112012Cleanup(GOST34112012Context *CTX)
      30  {
      31      explicit_bzero(CTX, sizeof (GOST34112012Context));
      32  }
      33  
      34  void
      35  GOST34112012Init(GOST34112012Context *CTX, const unsigned int digest_size)
      36  {
      37      unsigned int i;
      38  
      39      memset(CTX, 0, sizeof (GOST34112012Context));
      40      CTX->digest_size = digest_size;
      41  
      42      for (i = 0; i < 8; i++)
      43      {
      44          if (digest_size == 256)
      45              CTX->h.QWORD[i] = 0x0101010101010101ULL;
      46          else
      47              CTX->h.QWORD[i] = 0x00ULL;
      48      }
      49  }
      50  
      51  static inline void
      52  pad(GOST34112012Context *CTX)
      53  {
      54      if (CTX->bufsize < sizeof CTX->buffer)
      55      {
      56          memset (CTX->buffer + CTX->bufsize, 0,
      57                  sizeof(CTX->buffer) - CTX->bufsize);
      58          CTX->buffer[CTX->bufsize] = 0x01;
      59      }
      60  }
      61  
      62  static inline void
      63  add512(const uint512_u *x, const uint512_u *y, uint512_u *r)
      64  {
      65  #ifndef __GOST3411_BIG_ENDIAN__
      66      unsigned int CF;
      67      unsigned int i;
      68  
      69      CF = 0;
      70      for (i = 0; i < 8; i++)
      71      {
      72          const unsigned long long left = x->QWORD[i];
      73          unsigned long long sum;
      74  
      75          sum = left + y->QWORD[i] + CF;
      76          if (sum != left)
      77              CF = (sum < left);
      78          r->QWORD[i] = sum;
      79      }
      80  #else
      81      const unsigned char *xp, *yp;
      82      unsigned char *rp;
      83      unsigned int i;
      84      int buf;
      85  
      86      xp = (const unsigned char *) &x[0];
      87      yp = (const unsigned char *) &y[0];
      88      rp = (unsigned char *) &r[0];
      89  
      90      buf = 0;
      91      for (i = 0; i < 64; i++)
      92      {
      93          buf = xp[i] + yp[i] + (buf >> 8);
      94          rp[i] = (unsigned char) (buf & 0xFF);
      95      }
      96  #endif
      97  }
      98  
      99  static void
     100  g(uint512_u *h, const uint512_u *N, const unsigned char *m)
     101  {
     102  #ifdef __GOST3411_HAS_SSE2__
     103      __m128i xmm0, xmm2, xmm4, xmm6; /* XMMR0-quadruple */
     104      __m128i xmm1, xmm3, xmm5, xmm7; /* XMMR1-quadruple */
     105      unsigned int i;
     106  
     107      LOAD(N, xmm0, xmm2, xmm4, xmm6);
     108      XLPS128M(h, xmm0, xmm2, xmm4, xmm6);
     109  
     110      LOAD(m, xmm1, xmm3, xmm5, xmm7);
     111      XLPS128R(xmm0, xmm2, xmm4, xmm6, xmm1, xmm3, xmm5, xmm7);
     112  
     113      for (i = 0; i < 11; i++)
     114          ROUND128(i, xmm0, xmm2, xmm4, xmm6, xmm1, xmm3, xmm5, xmm7);
     115  
     116      XLPS128M((&C[11]), xmm0, xmm2, xmm4, xmm6);
     117      X128R(xmm0, xmm2, xmm4, xmm6, xmm1, xmm3, xmm5, xmm7);
     118  
     119      X128M(h, xmm0, xmm2, xmm4, xmm6);
     120      X128M(m, xmm0, xmm2, xmm4, xmm6);
     121  
     122      UNLOAD(h, xmm0, xmm2, xmm4, xmm6);
     123  
     124      /* Restore the Floating-point status on the CPU */
     125      _mm_empty();
     126  #else
     127      uint512_u Ki, data;
     128      unsigned int i;
     129  
     130      XLPS(h, N, (&data));
     131  
     132      /* Starting E() */
     133      Ki = data;
     134      XLPS((&Ki), ((const uint512_u *) &m[0]), (&data));
     135  
     136      for (i = 0; i < 11; i++)
     137          ROUND(i, (&Ki), (&data));
     138  
     139      XLPS((&Ki), (&C[11]), (&Ki));
     140      X((&Ki), (&data), (&data));
     141      /* E() done */
     142  
     143      X((&data), h, (&data));
     144      X((&data), ((const uint512_u *) &m[0]), h);
     145  #endif
     146  }
     147  
     148  static inline void
     149  stage2(GOST34112012Context *CTX, const unsigned char *data)
     150  {
     151      uint512_u m;
     152  
     153      memcpy(&m, data, sizeof(m));
     154      g(&(CTX->h), &(CTX->N), (const unsigned char *)&m);
     155  
     156      add512(&(CTX->N), &buffer512, &(CTX->N));
     157      add512(&(CTX->Sigma), &m, &(CTX->Sigma));
     158  }
     159  
     160  static inline void
     161  stage3(GOST34112012Context *CTX)
     162  {
     163      uint512_u buf = {{ 0 }};
     164  
     165  #ifndef __GOST3411_BIG_ENDIAN__
     166      buf.QWORD[0] = CTX->bufsize << 3;
     167  #else
     168      buf.QWORD[0] = BSWAP64(CTX->bufsize << 3);
     169  #endif
     170  
     171      pad(CTX);
     172  
     173      g(&(CTX->h), &(CTX->N), (const unsigned char *) &(CTX->buffer));
     174  
     175      add512(&(CTX->N), &buf, &(CTX->N));
     176      add512(&(CTX->Sigma), (const uint512_u *) &CTX->buffer[0],
     177             &(CTX->Sigma));
     178  
     179      g(&(CTX->h), &buffer0, (const unsigned char *) &(CTX->N));
     180  
     181      g(&(CTX->h), &buffer0, (const unsigned char *) &(CTX->Sigma));
     182      memcpy(&(CTX->hash), &(CTX->h), sizeof (uint512_u));
     183  }
     184  
     185  void
     186  GOST34112012Update(GOST34112012Context *CTX, const unsigned char *data, size_t len)
     187  {
     188      size_t chunksize;
     189  
     190      if (CTX->bufsize) {
     191          chunksize = 64 - CTX->bufsize;
     192          if (chunksize > len)
     193              chunksize = len;
     194  
     195          memcpy(&CTX->buffer[CTX->bufsize], data, chunksize);
     196  
     197          CTX->bufsize += chunksize;
     198          len -= chunksize;
     199          data += chunksize;
     200  
     201          if (CTX->bufsize == 64)
     202          {
     203              stage2(CTX, CTX->buffer);
     204  
     205              CTX->bufsize = 0;
     206          }
     207      }
     208  
     209      while (len > 63)
     210      {
     211          stage2(CTX, data);
     212  
     213          data += 64;
     214          len  -= 64;
     215      }
     216  
     217      if (len) {
     218          memcpy(&CTX->buffer, data, len);
     219          CTX->bufsize = len;
     220      }
     221  }
     222  
     223  void
     224  GOST34112012Final(GOST34112012Context *CTX, unsigned char *digest)
     225  {
     226      stage3(CTX);
     227  
     228      CTX->bufsize = 0;
     229  
     230      if (CTX->digest_size == 256)
     231          memcpy(digest, &(CTX->hash.QWORD[4]), 32);
     232      else
     233          memcpy(digest, &(CTX->hash.QWORD[0]), 64);
     234  
     235      GOST34112012Cleanup(CTX);
     236  }
     237  
     238  #endif /* INCLUDE_gost_yescrypt */