?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // hashplay framework
  2. // (c) 2022 lvd^mhm
  3.  
  4. /*
  5.     This file is part of hashplay framework.
  6.  
  7.     hashplay framework is free software:
  8.     you can redistribute it and/or modify it under the terms of
  9.     the GNU General Public License as published by
  10.     the Free Software Foundation, either version 3 of the License, or
  11.     (at your option) any later version.
  12.  
  13.     hashplay framework is distributed in the hope that
  14.     it will be useful, but WITHOUT ANY WARRANTY; without even
  15.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16.     See the GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with hashplay framework.
  20.     If not, see <http://www.gnu.org/licenses/>.
  21. */
  22.  
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <assert.h>
  28.  
  29. #include "hash-common.h"
  30. #include "sphash-opt.h"
  31.  
  32.  
  33. #define DIGEST_SIZE 8
  34.  
  35. #define BLK_SIZE 32
  36.  
  37. static const uint32_t x0 = 0x01180011; // hex-encoded numbers 71680, 70908, 69888
  38. static const uint32_t y0 = 0x4fc11100; //
  39.  
  40.  
  41. // instantiate speck_uint32_t_8_29
  42.  
  43.  
  44.  
  45.  
  46. #define ROL(w,n) (((w)<<(n))|((w)>>32-(n)))
  47.  
  48. #define ROUND(x,y,k)           \
  49.         do {                   \
  50.                 x = ROL(x,24); \
  51.                 x += y;        \
  52.                 x ^= k;        \
  53.                 y = ROL(y,3);  \
  54.                 y ^= x;        \
  55.         } while(0)
  56.  
  57.  
  58.  
  59.  
  60. struct my_sphash
  61. {
  62.         uint64_t pos;
  63.  
  64.         uint8_t buf[BLK_SIZE];
  65.  
  66.         uint32_t state[2];
  67. };
  68.  
  69.  
  70. static void sphash_compress( const uint32_t * m, uint32_t * state)
  71. {
  72.         uint32_t x,y;
  73.         uint32_t k,k1,k2,k3,k4,k5,k6,k7;
  74.  
  75.         x = state[0];
  76.         y = state[1];
  77.  
  78.         //speck_encrypt_uint32_t_8_29(tmp,m);
  79.         k = m[0];
  80.         k1 = m[1];
  81.         k2 = m[2];
  82.         k3 = m[3];
  83.         k4 = m[4];
  84.         k5 = m[5];
  85.         k6 = m[6];
  86.         k7 = m[7];
  87.  
  88.         ROUND(x,y,k); ROUND(k1,k, 0);
  89.         ROUND(x,y,k); ROUND(k2,k, 1);
  90.         ROUND(x,y,k); ROUND(k3,k, 2);
  91.         ROUND(x,y,k); ROUND(k4,k, 3);
  92.         ROUND(x,y,k); ROUND(k5,k, 4);
  93.         ROUND(x,y,k); ROUND(k6,k, 5);
  94.         ROUND(x,y,k); ROUND(k7,k, 6);
  95.  
  96.         ROUND(x,y,k); ROUND(k1,k, 7);
  97.         ROUND(x,y,k); ROUND(k2,k, 8);
  98.         ROUND(x,y,k); ROUND(k3,k, 9);
  99.         ROUND(x,y,k); ROUND(k4,k,10);
  100.         ROUND(x,y,k); ROUND(k5,k,11);
  101.         ROUND(x,y,k); ROUND(k6,k,12);
  102.         ROUND(x,y,k); ROUND(k7,k,13);
  103.        
  104.         ROUND(x,y,k); ROUND(k1,k,14);
  105.         ROUND(x,y,k); ROUND(k2,k,15);
  106.         ROUND(x,y,k); ROUND(k3,k,16);
  107.         ROUND(x,y,k); ROUND(k4,k,17);
  108.         ROUND(x,y,k); ROUND(k5,k,18);
  109.         ROUND(x,y,k); ROUND(k6,k,19);
  110.         ROUND(x,y,k); ROUND(k7,k,20);
  111.        
  112.         ROUND(x,y,k); ROUND(k1,k,21);
  113.         ROUND(x,y,k); ROUND(k2,k,22);
  114.         ROUND(x,y,k); ROUND(k3,k,23);
  115.         ROUND(x,y,k); ROUND(k4,k,24);
  116.         ROUND(x,y,k); ROUND(k5,k,25);
  117.         ROUND(x,y,k); ROUND(k6,k,26);
  118.         ROUND(x,y,k); ROUND(k7,k,27);
  119.        
  120.         ROUND(x,y,k);
  121.  
  122.         state[0] += x;
  123.         state[1] += y;
  124. }
  125.  
  126.  
  127.  
  128. static inline size_t my_min(size_t a, size_t b)
  129. {
  130.         if( a<=b ) return a; else return b;
  131. }
  132.  
  133. struct hash_iface * make_sphash_opt(void)
  134. {
  135.         static const char name[]="speck-based hash: sphash64, optimized impl.";
  136.  
  137.         struct hash_iface * hash = malloc(sizeof(struct hash_iface));
  138.         if( !hash )
  139.         {
  140.                 fprintf(stderr,"%s: %d, %s: can't allocate memory for hash_iface!\n",__FILE__,__LINE__,__func__);
  141.                 exit(1);
  142.         }
  143.  
  144.         hash->hash_specific_data = NULL;
  145.  
  146.         hash->name = name;
  147.  
  148.         hash->hash_init     = &sphash_opt_hash_init;
  149.         hash->hash_start    = &sphash_opt_hash_start;
  150.         hash->hash_addbytes = &sphash_opt_hash_addbytes;
  151.         hash->hash_getsize  = &sphash_opt_hash_getsize;
  152.         hash->hash_result   = &sphash_opt_hash_result;
  153.         hash->hash_deinit   = &sphash_opt_hash_deinit;
  154.  
  155.         return hash;
  156. }
  157.  
  158. int    sphash_opt_hash_init    (struct hash_iface * hash)
  159. {
  160.         struct my_sphash * sphash = (struct my_sphash *)malloc(sizeof(struct my_sphash));
  161.        
  162.         if( !sphash )
  163.         {
  164.                 fprintf(stderr,"%s: %d, %s: can't allocate memory for struct my_sphash!\n",__FILE__,__LINE__,__func__);
  165.                 exit(1);
  166.         }
  167.  
  168.         hash->hash_specific_data = (void *)sphash;
  169.  
  170.         return 1;
  171. }
  172.  
  173. void   sphash_opt_hash_deinit  (struct hash_iface * hash)
  174. {
  175.         struct my_sphash * sphash = (struct my_sphash *)hash->hash_specific_data;
  176.        
  177.         if( !sphash )
  178.         {
  179.                 fprintf(stderr,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__,__LINE__,__func__);
  180.                 exit(1);
  181.         }
  182.  
  183.         free(sphash);
  184.        
  185.         hash->hash_specific_data = NULL;
  186. }
  187.  
  188. size_t sphash_opt_hash_getsize (struct hash_iface * hash)
  189. {
  190.         return DIGEST_SIZE;
  191. }
  192.  
  193. int    sphash_opt_hash_start   (struct hash_iface * hash)
  194. {
  195.         struct my_sphash * sphash = (struct my_sphash *)hash->hash_specific_data;
  196.        
  197.         if( !sphash )
  198.         {
  199.                 fprintf(stderr,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__,__LINE__,__func__);
  200.                 exit(1);
  201.         }
  202.  
  203.         sphash->pos = 0;
  204.  
  205.         for(int i=0;i<BLK_SIZE;i++)
  206.                 sphash->buf[i] = 0;
  207.  
  208.         sphash->state[0] = x0;
  209.         sphash->state[1] = y0;
  210.  
  211.         return 1;
  212. }
  213.  
  214. int    sphash_opt_hash_addbytes(struct hash_iface * hash, const uint8_t * message, size_t size)
  215. {
  216.         struct my_sphash * sphash = (struct my_sphash *)hash->hash_specific_data;
  217.        
  218.         if( !sphash )
  219.         {
  220.                 fprintf(stderr,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__,__LINE__,__func__);
  221.                 exit(1);
  222.         }
  223.  
  224.         const uint8_t * ptr = message;
  225.         size_t remaining_size = size;
  226.  
  227.  
  228.         while( remaining_size > 0 )
  229.         {
  230.                 // do full buffers
  231.                 if( !(sphash->pos & (BLK_SIZE-1)) )
  232.                 {
  233.                         if( remaining_size>=BLK_SIZE )
  234.                         {
  235.                                 sphash_compress( (uint32_t *)ptr, sphash->state );
  236.  
  237.                                 sphash->pos += BLK_SIZE;
  238.                                 ptr += BLK_SIZE;
  239.                                 remaining_size -= BLK_SIZE;
  240.  
  241.                                 continue;
  242.                         }
  243.                 }
  244.  
  245.  
  246.                 // otherwise fill with all available data up to the end of buffer, if possible
  247.                 size_t size_to_add = my_min( (BLK_SIZE-(sphash->pos & (BLK_SIZE-1))), remaining_size );
  248.  
  249.                 do
  250.                 {
  251.                         sphash->buf[sphash->pos & (BLK_SIZE-1)] = *ptr;
  252.  
  253.                         ptr++;
  254.                         sphash->pos++;
  255.                         remaining_size--;
  256.  
  257.                 } while( (--size_to_add) );
  258.  
  259.                 if( !(sphash->pos & (BLK_SIZE-1)) )
  260.                         sphash_compress( (uint32_t *)sphash->buf, sphash->state );
  261.         }
  262.  
  263.         return 1;
  264. }
  265.  
  266. int    sphash_opt_hash_result  (struct hash_iface * hash, uint8_t * result)
  267. {
  268.         struct my_sphash * sphash = (struct my_sphash *)hash->hash_specific_data;
  269.        
  270.         if( !sphash )
  271.         {
  272.                 fprintf(stderr,"%s: %d, %s: hash_specific_data was NULL!\n",__FILE__,__LINE__,__func__);
  273.                 exit(1);
  274.         }
  275.  
  276.  
  277.         /*
  278.          * We're gonna using Nandi padding rule, as per following paper:
  279.          *
  280.          * ===
  281.          * Nandi M. (2009) Characterizing Padding Rules of MD Hash Functions Preserving Collision Security.
  282.          * In: Boyd C., González Nieto J. (eds) Information Security and Privacy. ACISP 2009.
  283.          * Lecture Notes in Computer Science, vol 5594. Springer, Berlin, Heidelberg.
  284.          * https://doi.org/10.1007/978-3-642-02620-1_12
  285.          *
  286.          * also https://eprint.iacr.org/2009/325.pdf
  287.          * or use sci-hub.
  288.          * ===
  289.          *
  290.          * Specifically, the padding is as per section 3.2, remark 2, s=16
  291.          */
  292.  
  293.  
  294.         uint8_t padding[BLK_SIZE+8]; // suitable for up to 4 chunks of 16 bits, total 4*15 = 60 bits
  295.                                      // for length IN BLOCKS. Block is BLK_SIZE (min 32 bytes), so
  296.                                      // 2^64 / 32 = 2^59.
  297.  
  298.         for(int i=0;i<sizeof(padding);i++)
  299.                 padding[i]=0;
  300.        
  301.         uint64_t blk_size = (sphash->pos+BLK_SIZE-1)/BLK_SIZE; // number of blocks incl. partially filled last one
  302.  
  303.         int num_chunks = 1;
  304.         uint64_t t = blk_size;
  305.         while( t>>=15 ) num_chunks++;
  306.  
  307.         // fill length part of padding
  308.         t = blk_size;
  309.         for(int i=num_chunks-1;i>=0;i--)
  310.         {
  311.                 uint16_t chunk = (t & 0x7FFF) | (i ? 0x8000 : 0);
  312.  
  313.                 padding[BLK_SIZE+i*2  ] = chunk>>8;
  314.                 padding[BLK_SIZE+i*2+1] = chunk & 0xFF;
  315.  
  316.                 t>>=15;
  317.         }
  318.  
  319.  
  320.  
  321.  
  322.  
  323.         int num_pad_bytes = (BLK_SIZE-2*num_chunks) - (sphash->pos & (BLK_SIZE-1));
  324.  
  325.         if( num_pad_bytes<=0 ) num_pad_bytes += BLK_SIZE;
  326.  
  327.         padding[BLK_SIZE-num_pad_bytes] = 0x80;
  328.  
  329.         sphash_opt_hash_addbytes(hash, &padding[BLK_SIZE-num_pad_bytes], 2*num_chunks+num_pad_bytes);
  330.  
  331.         assert( !(sphash->pos & (BLK_SIZE-1)) );
  332.  
  333.  
  334.         for(int i=0;i<DIGEST_SIZE/4;i++)
  335.         {
  336.                 *(((uint32_t *)result)+i) = sphash->state[i];
  337.         }
  338.  
  339.         return 1;
  340. }
  341.  
  342.