Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- //------------------------------------------------------------------------------
- static inline uint32_t load_le32( const uint8_t *p )
- {
- uint32_t x = 0;
- x |= ( uint32_t ) p[ 3 ] << 24;
- x |= ( uint32_t ) p[ 2 ] << 16;
- x |= ( uint32_t ) p[ 1 ] << 8;
- x |= ( uint32_t ) p[ 0 ];
- return x;
- }
- //------------------------------------------------------------------------------
- static inline uint64_t load_le64( const uint8_t *p, int n = 8 )
- {
- uint64_t x = 0;
- switch ( n ) {
- case 8: x |= ( uint64_t ) p[ 7 ] << 56;
- case 7: x |= ( uint64_t ) p[ 6 ] << 48;
- case 6: x |= ( uint64_t ) p[ 5 ] << 40;
- case 5: x |= ( uint64_t ) p[ 4 ] << 32;
- case 4: x |= ( uint64_t ) p[ 3 ] << 24;
- case 3: x |= ( uint64_t ) p[ 2 ] << 16;
- case 2: x |= ( uint64_t ) p[ 1 ] << 8;
- case 1: x |= ( uint64_t ) p[ 0 ];
- }
- return x;
- }
- //------------------------------------------------------------------------------
- static inline uint32_t load_be32( const uint8_t *p )
- {
- uint32_t x = 0;
- x |= ( uint32_t ) p[ 3 ];
- x |= ( uint32_t ) p[ 2 ] << 8;
- x |= ( uint32_t ) p[ 1 ] << 16;
- x |= ( uint32_t ) p[ 0 ] << 24;
- return x;
- }
- //------------------------------------------------------------------------------
- static inline uint64_t load_be64( const uint8_t *p, int n = 8 )
- {
- uint64_t x = 0;
- switch ( n ) {
- case 8: x |= ( uint64_t ) p[ 7 ];
- case 7: x |= ( uint64_t ) p[ 6 ] << 8;
- case 6: x |= ( uint64_t ) p[ 5 ] << 16;
- case 5: x |= ( uint64_t ) p[ 4 ] << 24;
- case 4: x |= ( uint64_t ) p[ 3 ] << 32;
- case 3: x |= ( uint64_t ) p[ 2 ] << 40;
- case 2: x |= ( uint64_t ) p[ 1 ] << 48;
- case 1: x |= ( uint64_t ) p[ 0 ] << 56;
- }
- return x;
- }
- //------------------------------------------------------------------------------
- static inline void store_be64( uint64_t x, uint8_t *p, int n = 8 )
- {
- switch ( n ) {
- case 8: p[ 7 ] = ( x );
- case 7: p[ 6 ] = ( x >> 8 );
- case 6: p[ 5 ] = ( x >> 16 );
- case 5: p[ 4 ] = ( x >> 24 );
- case 4: p[ 3 ] = ( x >> 32 );
- case 3: p[ 2 ] = ( x >> 40 );
- case 2: p[ 1 ] = ( x >> 48 );
- case 1: p[ 0 ] = ( x >> 56 );
- }
- }
- //------------------------------------------------------------------------------
- static inline void store_le64( uint64_t x, uint8_t *p, int n = 8 )
- {
- switch ( n ) {
- case 8: p[ 7 ] = ( x >> 56 );
- case 7: p[ 6 ] = ( x >> 48 );
- case 6: p[ 5 ] = ( x >> 40 );
- case 5: p[ 4 ] = ( x >> 32 );
- case 4: p[ 3 ] = ( x >> 24 );
- case 3: p[ 2 ] = ( x >> 16 );
- case 2: p[ 1 ] = ( x >> 8 );
- case 1: p[ 0 ] = ( x );
- }
- }
- //------------------------------------------------------------------------------
- static inline void store_le32( uint32_t x, uint8_t *p )
- {
- p[ 3 ] = ( x >> 24 );
- p[ 2 ] = ( x >> 16 );
- p[ 1 ] = ( x >> 8 );
- p[ 0 ] = ( x );
- }
- //------------------------------------------------------------------------------
- static inline uint64_t reverse64( uint64_t x )
- {
- x = ( ( x & 0xff00ff00ff00ff00LL ) >> 8 ) | ( ( x & 0x00ff00ff00ff00ffLL ) << 8 );
- x = ( ( x & 0xffff0000ffff0000LL ) >> 16 ) | ( ( x & 0x0000ffff0000ffffLL ) << 16 );
- return ( x >> 32 ) | ( x << 32 );
- }
- //------------------------------------------------------------------------------
- static inline uint32_t reverse32( uint32_t x )
- {
- x = ( ( x & 0xff00ff00 ) >> 8 ) | ( ( x & 0x00ff00ff ) << 8 );
- return ( x >> 16 ) | ( x << 16 );
- }
- //------------------------------------------------------------------------------
- static inline int bitcount( uint32_t x )
- {
- x = ( x & 0x55555555 ) + ( ( x & 0xaaaaaaaa ) >> 1 );
- x = ( x & 0x33333333 ) + ( ( x & 0xcccccccc ) >> 2 );
- x = ( x & 0x0f0f0f0f ) + ( ( x & 0xf0f0f0f0 ) >> 4 );
- x = ( x & 0x00ff00ff ) + ( ( x & 0xff00ff00 ) >> 8 );
- x = ( x & 0x0000ffff ) + ( ( x & 0xffff0000 ) >> 16 );
- return x;
- }
- //------------------------------------------------------------------------------
- static inline int parity( uint32_t x )
- {
- x ^= x >> 16;
- x ^= x >> 8;
- x ^= x >> 4;
- x ^= x >> 2;
- x ^= x >> 1;
- return x & 1;
- }
- //==============================================================================
- static uint32_t sbox40( uint32_t x )
- {
- static const uint8_t sbox[ 256 ] = {
- /* 察しろ */
- };
- return ( ( sbox[ 0xff & ( x >> 24 ) ] << 24 ) |
- ( sbox[ 0xff & ( x >> 16 ) ] << 16 ) |
- ( sbox[ 0xff & ( x >> 8 ) ] << 8 ) |
- ( sbox[ 0xff & ( x ) ] ) );
- }
- //------------------------------------------------------------------------------
- static uint32_t round00( uint32_t x, uint32_t k, uint8_t flavor )
- {
- uint16_t salt = ( flavor & 2 ) ? 0x5353 : 0;
- x = ( 0xffff & ( x + k + salt ) ) | ( ( x >> 16 ) + ( k >> 16 ) + salt ) << 16;
- x = ( ( x & 0xf0f0f0f0 ) >> 4 ) | ( ( x & 0x0f0f0f0f ) << 4 );
- k = ( k << 1 ) | ( k >> 31 );
- x = ( parity( x & k ) ) ? x ^ ~k : x;
- x = ( flavor & 1 ) ?
- ( x & 0xaa55aa55 ) | ( ( x & 0x55005500 ) >> 7 ) | ( ( x & 0x00aa00aa ) << 7 ):
- ( x & 0x55aa55aa ) | ( ( x & 0xaa00aa00 ) >> 9 ) | ( ( x & 0x00550055 ) << 9 );
- x = ( x & 0x00ffff00 ) | ( x >> 24 ) | ( x << 24 );
- x = x ^ ( ( x << 24 ) | ( x >> 8 ) ) ^ ( ( x << 25 ) | ( x >> 7 ) );
- return x;
- }
- //------------------------------------------------------------------------------
- static uint32_t round40( uint32_t x, uint32_t k )
- {
- x = sbox40( x ^ k );
- x ^= ( ( x & 0x007f007f ) << 9 ) | ( ( x & 0x00800080 ) << 1 );
- x ^= ( ( x & 0x7f007f00 ) >> 7 ) | ( ( x & 0x80008000 ) >> 15 );
- x = ( x << 8 ) | ( x >> 24 );
- x ^= ( ( x & 0x3f003f00 ) >> 6 ) | ( ( x & 0xc000c000 ) >> 14 );
- x ^= ( ( x & 0x003f003f ) << 10 ) | ( ( x & 0x00c000c0 ) << 2 );
- x = ( x >> 8 ) | ( x << 24 );
- return x;
- }
- //------------------------------------------------------------------------------
- static uint64_t block00( uint64_t block, const uint32_t kext[ 4 ],
- uint8_t /*protocol*/, bool encrypt )
- {
- const static uint8_t flavor[ 8 ][ 16 ] = {
- { 1, 0, 1, 2, 2, 2, 0, 2, 1, 3, 0, 2, 1, 0, 0, 1 },
- { 3, 2, 0, 2, 2, 0, 3, 0, 3, 1, 3, 3, 0, 1, 0, 1 },
- { 2, 0, 0, 1, 1, 3, 3, 1, 0, 1, 2, 0, 1, 0, 1, 0 },
- { 2, 3, 0, 1, 0, 0, 3, 1, 3, 1, 1, 3, 1, 0, 0, 2 },
- { 2, 3, 3, 2, 1, 3, 1, 2, 1, 2, 3, 1, 2, 0, 0, 1 },
- { 2, 2, 3, 3, 1, 3, 2, 2, 3, 1, 0, 2, 0, 0, 1, 1 },
- { 1, 3, 1, 2, 2, 0, 1, 0, 3, 3, 3, 1, 0, 2, 2, 2 },
- { 1, 2, 0, 2, 0, 0, 3, 1, 1, 3, 1, 2, 2, 2, 0, 1 }
- };
- uint32_t left = block >> 32, right = block;
- if ( encrypt ) {
- for ( int r = 0; r < 16; ) {
- left ^= round00( right, kext[ r & 3 ], flavor[ 0 ][ r ] ); r++;
- right ^= round00( left, kext[ r & 3 ], flavor[ 0 ][ r ] ); r++;
- }
- } else {
- for ( int r = 15; r >= 0; ) {
- left ^= round00( right, kext[ r & 3 ], flavor[ 0 ][ r ] ); r--;
- right ^= round00( left, kext[ r & 3 ], flavor[ 0 ][ r ] ); r--;
- }
- }
- return ( ( uint64_t ) right << 32 ) | left;
- }
- //------------------------------------------------------------------------------
- static uint64_t block40( uint64_t block, const uint32_t kext[ 16 ],
- uint8_t protocol, bool encrypt )
- {
- uint64_t salt = ( protocol & 0x0c ) ? 0xfbe852461acd3970LL : 0xd34c027be8579632LL;
- block += salt;
- uint32_t left = block >> 32, right = block;
- if ( encrypt ) {
- for ( int r = 0; r < 16; ) {
- right ^= round40( left, kext[ r ] ); r++;
- left ^= round40( right, kext[ r ] ); r++;
- }
- } else {
- for ( int r = 15; r >= 0; ) {
- right ^= round40( left, kext[ r ] ); r--;
- left ^= round40( right, kext[ r ] ); r--;
- }
- }
- block = ( ( uint64_t ) right << 32 ) | left;
- block -= salt;
- return block;
- }
- //------------------------------------------------------------------------------
- static void keysched00( uint64_t key, uint32_t kext[ 4 ], uint8_t protocol )
- {
- kext[ 0 ] = key >> 32;
- kext[ 1 ] = key;
- kext[ 2 ] = 0x08090a0b;
- kext[ 3 ] = 0x0c0d0e0f;
- uint32_t chain = ( protocol & 0x0c )? 0x84e5c4e7 : 0x6aa32b6f;
- for ( int i = 0; i < 8; i++ ) {
- kext[ i & 3 ] = chain = round00( kext[ i & 3 ], chain, 0 );
- }
- }
- //------------------------------------------------------------------------------
- static void keysched40( uint64_t key, uint32_t kext[ 16 ], uint8_t /*protocol*/ )
- {
- // key ~ 01234567; left ~ 6420; right ~ 7531;
- key = ( ( key & 0x00ffff0000ffff00LL ) |
- ( key & 0xff000000ff000000LL ) >> 24 |
- ( key & 0x000000ff000000ffLL ) << 24 );
- key = ( ( key & 0x0000ffffffff0000LL ) |
- ( key & 0xffff000000000000LL ) >> 48 |
- ( key & 0x000000000000ffffLL ) << 48 );
- uint32_t left = key >> 32;
- uint32_t right = key;
- for ( int i = 0; i < 16 ; i++ ) {
- uint32_t s = sbox40( right );
- s = ( ( 0x00ffff00 & ( s ^ left ) ) |
- ( 0xff0000ff & ( ( s & 0xff0000ff ) + ( left & 0xff0000ff ) ) ) );
- left = right;
- right = ( s >> 8 ) | ( s << 24 );
- kext[ i ] = s;
- }
- }
- //------------------------------------------------------------------------------
- static void cipher00( uint8_t *out, const uint8_t *in, uint32_t len,
- uint64_t key, uint8_t protocol, bool encrypt )
- {
- uint32_t kext[ 4 ];
- keysched00( key, kext, protocol );
- uint64_t chain = 0xfe27199919690911LL;
- if ( encrypt ) {
- while ( len >= 8 ) {
- uint64_t plain = load_be64( in );
- uint64_t crypt = block00( plain ^ chain, kext, protocol, true );
- store_be64( crypt, out );
- chain = crypt;
- in += 8; out += 8; len -= 8;
- }
- } else {
- while ( len >= 8 ) {
- uint64_t crypt = load_be64( in );
- uint64_t plain = block00( crypt, kext, protocol, false ) ^ chain;
- store_be64( plain, out );
- chain = crypt;
- in += 8; out += 8; len -= 8;
- }
- }
- if ( len > 0 ) {
- chain = block00( chain, kext, protocol, true );
- store_be64( load_be64( in, len ) ^ chain, out, len );
- }
- }
- //------------------------------------------------------------------------------
- static void cipher40( uint8_t *out, const uint8_t *in, uint32_t len,
- uint64_t key, uint8_t protocol, bool encrypt )
- {
- uint32_t kext[ 16 ];
- keysched40( key, kext, protocol );
- uint64_t chain = 0x11096919991927feLL;
- if ( encrypt ) {
- while ( len >= 8 ) {
- uint64_t plain = load_le64( in );
- uint64_t crypt = block40( plain ^ chain, kext, protocol, true );
- store_le64( crypt, out );
- chain = crypt;
- in += 8; out += 8; len -= 8;
- }
- } else {
- while ( len >= 8 ) {
- uint64_t crypt = load_le64( in );
- uint64_t plain = block40( crypt, kext, protocol, false ) ^ chain;
- store_le64( plain, out );
- chain = crypt;
- in += 8; out += 8; len -= 8;
- }
- }
- if ( len > 0 ) {
- chain = block40( chain, kext, protocol, true );
- store_le64( load_le64( in, len ) ^ chain, out, len );
- }
- }
- //------------------------------------------------------------------------------
- static uint32_t digest00( uint64_t key, const uint8_t *in, uint32_t len,
- uint8_t /*protocol*/ )
- {
- uint64_t mac = 0;
- while ( len >= 8 ) {
- mac ^= load_be64( in );
- mac ^= ( uint64_t )round00( mac, key >> 32, 3 ) << 32;
- mac ^= ( uint64_t )round00( mac >> 32, key, 3 );
- in += 8; len -= 8;
- }
- if ( len > 0 ) {
- mac ^= load_be64( in, len );
- mac ^= ( uint64_t )round00( mac, key >> 32, 3 ) << 32;
- mac ^= ( uint64_t )round00( mac >> 32, key, 3 );
- }
- return mac;
- }
- //------------------------------------------------------------------------------
- static uint32_t digest40( uint64_t key, const uint8_t *in, uint32_t len,
- uint8_t protocol )
- {
- key = reverse64( key );
- key += ( uint64_t )( ( len + 7 ) / 8 * 2 + 2 ) << 32;
- uint64_t salt = ( protocol & 0x0c ) ? 0xfbe852461acd3970LL : 0xd34c027be8579632LL;
- uint32_t mac = salt;
- mac += round40( key, mac );
- while ( len >= 8 ) {
- uint64_t text = load_le64( in );
- mac += round40( text, mac );
- mac += round40( text >> 32, mac );
- in += 8; len -= 8;
- }
- if ( len > 0 ) {
- uint64_t text = load_le64( in, len );
- mac += round40( text, mac );
- mac += round40( text >> 32, mac );
- }
- mac += round40( ( salt >> 32 ) + ( key >> 32 ), mac );
- return reverse32( mac );
- }
- //==============================================================================
- void encrypt( uint8_t *out, const uint8_t *in, uint32_t len,
- uint64_t key, uint8_t protocol )
- {
- if ( protocol & 0x40 ) {
- cipher40( out, in, len, key, protocol, true );
- } else {
- cipher00( out, in, len, key, protocol, true );
- }
- }
- //------------------------------------------------------------------------------
- void decrypt( uint8_t *out, const uint8_t *in, uint32_t len,
- uint64_t key, uint8_t protocol )
- {
- if ( protocol & 0x40 ) {
- cipher40( out, in, len, key, protocol, false );
- } else {
- cipher00( out, in, len, key, protocol, false );
- }
- }
- //------------------------------------------------------------------------------
- uint32_t digest( uint8_t protocol, uint64_t key, const uint8_t *in, uint32_t len )
- {
- uint32_t mac;
- if ( protocol & 0x40 ) {
- mac = digest40( key, in, len, protocol );
- } else {
- mac = digest00( key, in, len, protocol );
- }
- return mac;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement