Advertisement
Guest User

Untitled

a guest
May 25th, 2012
4,653
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.06 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4.  
  5. //------------------------------------------------------------------------------
  6. static inline uint32_t load_le32( const uint8_t *p )
  7. {
  8.     uint32_t x = 0;
  9.     x |= ( uint32_t ) p[ 3 ] << 24;
  10.     x |= ( uint32_t ) p[ 2 ] << 16;
  11.     x |= ( uint32_t ) p[ 1 ] <<  8;
  12.     x |= ( uint32_t ) p[ 0 ];
  13.     return x;
  14. }
  15.  
  16. //------------------------------------------------------------------------------
  17. static inline uint64_t load_le64( const uint8_t *p, int n = 8 )
  18. {
  19.     uint64_t x = 0;
  20.     switch ( n ) {
  21.     case 8: x |= ( uint64_t ) p[ 7 ] << 56;
  22.     case 7: x |= ( uint64_t ) p[ 6 ] << 48;
  23.     case 6: x |= ( uint64_t ) p[ 5 ] << 40;
  24.     case 5: x |= ( uint64_t ) p[ 4 ] << 32;
  25.     case 4: x |= ( uint64_t ) p[ 3 ] << 24;
  26.     case 3: x |= ( uint64_t ) p[ 2 ] << 16;
  27.     case 2: x |= ( uint64_t ) p[ 1 ] <<  8;
  28.     case 1: x |= ( uint64_t ) p[ 0 ];
  29.     }
  30.     return x;
  31. }
  32.  
  33. //------------------------------------------------------------------------------
  34. static inline uint32_t load_be32( const uint8_t *p )
  35. {
  36.     uint32_t x = 0;
  37.     x |= ( uint32_t ) p[ 3 ];
  38.     x |= ( uint32_t ) p[ 2 ] <<  8;
  39.     x |= ( uint32_t ) p[ 1 ] << 16;
  40.     x |= ( uint32_t ) p[ 0 ] << 24;
  41.     return x;
  42. }
  43.  
  44. //------------------------------------------------------------------------------
  45. static inline uint64_t load_be64( const uint8_t *p, int n = 8 )
  46. {
  47.     uint64_t x = 0;
  48.     switch ( n ) {
  49.     case 8: x |= ( uint64_t ) p[ 7 ];
  50.     case 7: x |= ( uint64_t ) p[ 6 ] <<  8;
  51.     case 6: x |= ( uint64_t ) p[ 5 ] << 16;
  52.     case 5: x |= ( uint64_t ) p[ 4 ] << 24;
  53.     case 4: x |= ( uint64_t ) p[ 3 ] << 32;
  54.     case 3: x |= ( uint64_t ) p[ 2 ] << 40;
  55.     case 2: x |= ( uint64_t ) p[ 1 ] << 48;
  56.     case 1: x |= ( uint64_t ) p[ 0 ] << 56;
  57.     }
  58.     return x;
  59. }
  60.  
  61. //------------------------------------------------------------------------------
  62. static inline void store_be64( uint64_t x, uint8_t *p, int n = 8 )
  63. {
  64.     switch ( n ) {
  65.     case 8: p[ 7 ] = ( x );
  66.     case 7: p[ 6 ] = ( x >>  8 );
  67.     case 6: p[ 5 ] = ( x >> 16 );
  68.     case 5: p[ 4 ] = ( x >> 24 );
  69.     case 4: p[ 3 ] = ( x >> 32 );
  70.     case 3: p[ 2 ] = ( x >> 40 );
  71.     case 2: p[ 1 ] = ( x >> 48 );
  72.     case 1: p[ 0 ] = ( x >> 56 );
  73.     }
  74. }
  75.  
  76. //------------------------------------------------------------------------------
  77. static inline void store_le64( uint64_t x, uint8_t *p, int n = 8 )
  78. {
  79.     switch ( n ) {
  80.     case 8: p[ 7 ] = ( x >> 56 );
  81.     case 7: p[ 6 ] = ( x >> 48 );
  82.     case 6: p[ 5 ] = ( x >> 40 );
  83.     case 5: p[ 4 ] = ( x >> 32 );
  84.     case 4: p[ 3 ] = ( x >> 24 );
  85.     case 3: p[ 2 ] = ( x >> 16 );
  86.     case 2: p[ 1 ] = ( x >>  8 );
  87.     case 1: p[ 0 ] = ( x );
  88.     }
  89. }
  90.  
  91. //------------------------------------------------------------------------------
  92. static inline void store_le32( uint32_t x, uint8_t *p )
  93. {
  94.     p[ 3 ] = ( x >> 24 );
  95.     p[ 2 ] = ( x >> 16 );
  96.     p[ 1 ] = ( x >>  8 );
  97.     p[ 0 ] = ( x );
  98. }
  99.  
  100. //------------------------------------------------------------------------------
  101. static inline uint64_t reverse64( uint64_t x )
  102. {
  103.     x = ( ( x & 0xff00ff00ff00ff00LL ) >>  8 ) | ( ( x & 0x00ff00ff00ff00ffLL ) <<  8 );
  104.     x = ( ( x & 0xffff0000ffff0000LL ) >> 16 ) | ( ( x & 0x0000ffff0000ffffLL ) << 16 );
  105.     return ( x >> 32 ) | ( x << 32 );
  106. }
  107.  
  108. //------------------------------------------------------------------------------
  109. static inline uint32_t reverse32( uint32_t x )
  110. {
  111.     x = ( ( x & 0xff00ff00 ) >>  8 ) | ( ( x & 0x00ff00ff ) <<  8 );
  112.     return ( x >> 16 ) | ( x << 16 );
  113. }
  114.  
  115. //------------------------------------------------------------------------------
  116. static inline int bitcount( uint32_t x )
  117. {
  118.     x = ( x & 0x55555555 ) + ( ( x & 0xaaaaaaaa ) >> 1 );
  119.     x = ( x & 0x33333333 ) + ( ( x & 0xcccccccc ) >> 2 );
  120.     x = ( x & 0x0f0f0f0f ) + ( ( x & 0xf0f0f0f0 ) >> 4 );
  121.     x = ( x & 0x00ff00ff ) + ( ( x & 0xff00ff00 ) >> 8 );
  122.     x = ( x & 0x0000ffff ) + ( ( x & 0xffff0000 ) >> 16 );
  123.     return x;
  124. }
  125.  
  126. //------------------------------------------------------------------------------
  127. static inline int parity( uint32_t x )
  128. {
  129.     x ^= x >> 16;
  130.     x ^= x >> 8;
  131.     x ^= x >> 4;
  132.     x ^= x >> 2;
  133.     x ^= x >> 1;
  134.     return x & 1;
  135. }
  136.  
  137. //==============================================================================
  138. static uint32_t sbox40( uint32_t x )
  139. {
  140.     static const uint8_t sbox[ 256 ] = {
  141.         /* 察しろ */
  142.     };
  143.  
  144.     return ( ( sbox[ 0xff & ( x >> 24 ) ] << 24 ) |
  145.              ( sbox[ 0xff & ( x >> 16 ) ] << 16 ) |
  146.              ( sbox[ 0xff & ( x >>  8 ) ] <<  8 ) |
  147.              ( sbox[ 0xff & ( x ) ] ) );
  148. }
  149.  
  150. //------------------------------------------------------------------------------
  151. static uint32_t round00( uint32_t x, uint32_t k, uint8_t flavor )
  152. {
  153.     uint16_t salt = ( flavor & 2 ) ? 0x5353 : 0;
  154.     x = ( 0xffff & ( x + k + salt ) ) | ( ( x >> 16 ) + ( k >> 16 ) + salt ) << 16;
  155.     x = ( ( x & 0xf0f0f0f0 ) >> 4 ) | ( ( x & 0x0f0f0f0f ) << 4 );
  156.     k = ( k << 1 ) | ( k >> 31 );
  157.     x = ( parity( x & k ) ) ? x ^ ~k : x;
  158.     x = ( flavor & 1 ) ?
  159.         ( x & 0xaa55aa55 ) | ( ( x & 0x55005500 ) >> 7 ) | ( ( x & 0x00aa00aa ) << 7 ):
  160.         ( x & 0x55aa55aa ) | ( ( x & 0xaa00aa00 ) >> 9 ) | ( ( x & 0x00550055 ) << 9 );
  161.     x = ( x & 0x00ffff00 ) | ( x >> 24 ) | ( x << 24 );
  162.     x = x ^ ( ( x << 24 ) | ( x >> 8 ) ) ^ ( ( x << 25 ) | ( x >> 7 ) );
  163.    
  164.     return x;
  165. }
  166.  
  167. //------------------------------------------------------------------------------
  168. static uint32_t round40( uint32_t x, uint32_t k )
  169. {
  170.     x  = sbox40( x ^ k );
  171.     x ^= ( ( x & 0x007f007f ) <<  9 ) | ( ( x & 0x00800080 ) <<  1 );
  172.     x ^= ( ( x & 0x7f007f00 ) >>  7 ) | ( ( x & 0x80008000 ) >> 15 );
  173.     x  = ( x << 8 ) | ( x >> 24 );
  174.     x ^= ( ( x & 0x3f003f00 ) >>  6 ) | ( ( x & 0xc000c000 ) >> 14 );
  175.     x ^= ( ( x & 0x003f003f ) << 10 ) | ( ( x & 0x00c000c0 ) <<  2 );
  176.     x  = ( x >> 8 ) | ( x << 24 );
  177.     return x;
  178. }
  179.  
  180. //------------------------------------------------------------------------------
  181. static uint64_t block00( uint64_t block, const uint32_t kext[ 4 ],
  182.                          uint8_t /*protocol*/, bool encrypt )
  183. {
  184.     const static uint8_t flavor[ 8 ][ 16 ] = {
  185.         { 1, 0, 1, 2, 2, 2, 0, 2, 1, 3, 0, 2, 1, 0, 0, 1 },
  186.         { 3, 2, 0, 2, 2, 0, 3, 0, 3, 1, 3, 3, 0, 1, 0, 1 },
  187.         { 2, 0, 0, 1, 1, 3, 3, 1, 0, 1, 2, 0, 1, 0, 1, 0 },
  188.         { 2, 3, 0, 1, 0, 0, 3, 1, 3, 1, 1, 3, 1, 0, 0, 2 },
  189.         { 2, 3, 3, 2, 1, 3, 1, 2, 1, 2, 3, 1, 2, 0, 0, 1 },
  190.         { 2, 2, 3, 3, 1, 3, 2, 2, 3, 1, 0, 2, 0, 0, 1, 1 },
  191.         { 1, 3, 1, 2, 2, 0, 1, 0, 3, 3, 3, 1, 0, 2, 2, 2 },
  192.         { 1, 2, 0, 2, 0, 0, 3, 1, 1, 3, 1, 2, 2, 2, 0, 1 }
  193.     };
  194.    
  195.     uint32_t left = block >> 32, right = block;
  196.     if ( encrypt ) {
  197.         for ( int r = 0; r < 16; ) {
  198.             left  ^= round00( right, kext[ r & 3 ], flavor[ 0 ][ r ] ); r++;
  199.             right ^= round00( left,  kext[ r & 3 ], flavor[ 0 ][ r ] ); r++;
  200.         }
  201.     } else {
  202.         for ( int r = 15; r >= 0; ) {
  203.             left  ^= round00( right, kext[ r & 3 ], flavor[ 0 ][ r ] ); r--;
  204.             right ^= round00( left,  kext[ r & 3 ], flavor[ 0 ][ r ] ); r--;
  205.         }
  206.     }
  207.    
  208.     return ( ( uint64_t ) right << 32 ) | left;
  209. }
  210.  
  211. //------------------------------------------------------------------------------
  212. static uint64_t block40( uint64_t block, const uint32_t kext[ 16 ],
  213.                          uint8_t protocol, bool encrypt )
  214. {
  215.     uint64_t salt = ( protocol & 0x0c ) ? 0xfbe852461acd3970LL : 0xd34c027be8579632LL;
  216.    
  217.     block += salt;
  218.     uint32_t left = block >> 32, right = block;
  219.     if ( encrypt ) {
  220.         for ( int r = 0; r < 16; ) {
  221.             right ^= round40( left,  kext[ r ] ); r++;
  222.             left  ^= round40( right, kext[ r ] ); r++;
  223.         }
  224.     } else {
  225.         for ( int r = 15; r >= 0; ) {
  226.             right ^= round40( left,  kext[ r ] ); r--;
  227.             left  ^= round40( right, kext[ r ] ); r--;
  228.         }
  229.     }
  230.     block = ( ( uint64_t ) right << 32 ) | left;
  231.     block -= salt;
  232.  
  233.     return block;
  234. }
  235.  
  236. //------------------------------------------------------------------------------
  237. static void keysched00( uint64_t key, uint32_t kext[ 4 ], uint8_t protocol )
  238. {
  239.     kext[ 0 ] = key >> 32;
  240.     kext[ 1 ] = key;
  241.     kext[ 2 ] = 0x08090a0b;
  242.     kext[ 3 ] = 0x0c0d0e0f;
  243.    
  244.     uint32_t chain = ( protocol & 0x0c )? 0x84e5c4e7 : 0x6aa32b6f;
  245.     for ( int i = 0; i < 8; i++ ) {
  246.         kext[ i & 3 ] = chain = round00( kext[ i & 3 ], chain, 0 );
  247.     }
  248. }
  249.  
  250. //------------------------------------------------------------------------------
  251. static void keysched40( uint64_t key, uint32_t kext[ 16 ], uint8_t /*protocol*/ )
  252. {
  253.     // key ~ 01234567; left ~ 6420; right ~ 7531;
  254.     key = ( ( key & 0x00ffff0000ffff00LL ) |
  255.             ( key & 0xff000000ff000000LL ) >> 24 |
  256.             ( key & 0x000000ff000000ffLL ) << 24 );
  257.     key = ( ( key & 0x0000ffffffff0000LL ) |
  258.             ( key & 0xffff000000000000LL ) >> 48 |
  259.             ( key & 0x000000000000ffffLL ) << 48 );
  260.  
  261.     uint32_t left  = key >> 32;
  262.     uint32_t right = key;
  263.    
  264.     for ( int i = 0; i < 16 ; i++ ) {
  265.         uint32_t s = sbox40( right );
  266.         s = ( ( 0x00ffff00 & ( s ^ left ) ) |
  267.               ( 0xff0000ff & ( ( s & 0xff0000ff ) + ( left & 0xff0000ff ) ) ) );
  268.         left  = right;
  269.         right = ( s >> 8 ) | ( s << 24 );
  270.         kext[ i ] = s;
  271.     }
  272. }
  273.  
  274. //------------------------------------------------------------------------------
  275. static void cipher00( uint8_t *out, const uint8_t *in, uint32_t len,
  276.                       uint64_t key, uint8_t protocol, bool encrypt )
  277. {
  278.     uint32_t kext[ 4 ];
  279.     keysched00( key, kext, protocol );
  280.    
  281.     uint64_t chain = 0xfe27199919690911LL;
  282.     if ( encrypt ) {
  283.         while ( len >= 8 ) {
  284.             uint64_t plain = load_be64( in );
  285.             uint64_t crypt = block00( plain ^ chain, kext, protocol, true );
  286.             store_be64( crypt, out );
  287.             chain = crypt;
  288.             in += 8; out += 8; len -= 8;
  289.         }
  290.     } else {
  291.         while ( len >= 8 ) {
  292.             uint64_t crypt = load_be64( in );
  293.             uint64_t plain = block00( crypt, kext, protocol, false ) ^ chain;
  294.             store_be64( plain, out );
  295.             chain = crypt;
  296.             in += 8; out += 8; len -= 8;
  297.         }
  298.     }
  299.     if ( len > 0 ) {
  300.         chain = block00( chain, kext, protocol, true );
  301.         store_be64( load_be64( in, len ) ^ chain, out, len );
  302.     }
  303. }
  304.  
  305. //------------------------------------------------------------------------------
  306. static void cipher40( uint8_t *out, const uint8_t *in, uint32_t len,
  307.                       uint64_t key, uint8_t protocol, bool encrypt )
  308. {
  309.     uint32_t kext[ 16 ];
  310.     keysched40( key, kext, protocol );
  311.  
  312.     uint64_t chain = 0x11096919991927feLL;
  313.     if ( encrypt ) {
  314.         while ( len >= 8 ) {
  315.             uint64_t plain = load_le64( in );
  316.             uint64_t crypt = block40( plain ^ chain, kext, protocol, true );
  317.             store_le64( crypt, out );
  318.             chain = crypt;
  319.             in += 8; out += 8; len -= 8;
  320.         }
  321.     } else {
  322.         while ( len >= 8 ) {
  323.             uint64_t crypt = load_le64( in );
  324.             uint64_t plain = block40( crypt, kext, protocol, false ) ^ chain;
  325.             store_le64( plain, out );
  326.             chain = crypt;
  327.             in += 8; out += 8; len -= 8;
  328.         }
  329.     }
  330.     if ( len > 0 ) {
  331.         chain = block40( chain, kext, protocol, true );
  332.         store_le64( load_le64( in, len ) ^ chain, out, len );
  333.     }
  334. }
  335.  
  336. //------------------------------------------------------------------------------
  337. static uint32_t digest00( uint64_t key, const uint8_t *in, uint32_t len,
  338.                           uint8_t /*protocol*/ )
  339. {
  340.     uint64_t mac = 0;
  341.     while ( len >= 8 ) {
  342.         mac ^= load_be64( in );
  343.         mac ^= ( uint64_t )round00( mac, key >> 32, 3 ) << 32;
  344.         mac ^= ( uint64_t )round00( mac >> 32, key, 3 );
  345.         in += 8; len -= 8;
  346.     }
  347.     if ( len > 0 ) {
  348.         mac ^= load_be64( in, len );
  349.         mac ^= ( uint64_t )round00( mac, key >> 32, 3 ) << 32;
  350.         mac ^= ( uint64_t )round00( mac >> 32, key, 3 );
  351.     }
  352.    
  353.     return mac;
  354. }
  355.  
  356. //------------------------------------------------------------------------------
  357. static uint32_t digest40( uint64_t key, const uint8_t *in, uint32_t len,
  358.                           uint8_t protocol )
  359. {
  360.     key = reverse64( key );
  361.     key += ( uint64_t )( ( len + 7 ) / 8 * 2 + 2 ) << 32;
  362.    
  363.     uint64_t salt = ( protocol & 0x0c ) ? 0xfbe852461acd3970LL : 0xd34c027be8579632LL;
  364.     uint32_t mac = salt;
  365.    
  366.     mac += round40( key, mac );
  367.     while ( len >= 8 ) {
  368.         uint64_t text = load_le64( in );
  369.         mac += round40( text, mac );
  370.         mac += round40( text >> 32, mac );
  371.         in += 8; len -= 8;
  372.     }
  373.     if ( len > 0 ) {
  374.         uint64_t text = load_le64( in, len );
  375.         mac += round40( text, mac );
  376.         mac += round40( text >> 32, mac );
  377.     }
  378.     mac += round40( ( salt >> 32 ) + ( key >> 32 ), mac );
  379.    
  380.     return reverse32( mac );
  381. }
  382.  
  383. //==============================================================================
  384. void encrypt( uint8_t *out, const uint8_t *in, uint32_t len,
  385.               uint64_t key, uint8_t protocol )
  386. {
  387.     if ( protocol & 0x40 ) {
  388.         cipher40( out, in, len, key, protocol, true );
  389.     } else {
  390.         cipher00( out, in, len, key, protocol, true );
  391.     }
  392. }
  393.  
  394. //------------------------------------------------------------------------------
  395. void decrypt( uint8_t *out, const uint8_t *in, uint32_t len,
  396.               uint64_t key, uint8_t protocol )
  397. {
  398.     if ( protocol & 0x40 ) {
  399.         cipher40( out, in, len, key, protocol, false );
  400.     } else {
  401.         cipher00( out, in, len, key, protocol, false );
  402.     }
  403. }
  404.  
  405. //------------------------------------------------------------------------------
  406. uint32_t digest( uint8_t protocol, uint64_t key, const uint8_t *in, uint32_t len )
  407. {
  408.     uint32_t mac;
  409.     if ( protocol & 0x40 ) {
  410.         mac = digest40( key, in, len, protocol );
  411.     } else {
  412.         mac = digest00( key, in, len, protocol );
  413.     }
  414.     return mac;
  415. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement