Skip to content
Snippets Groups Projects
28147_89.c 6.17 KiB
/** @file 
 * @brief   28147-89
 *
 * @copyright InfoTeCS. All rights reserved.
 */

#include "28147_89.h"

/** @brief     int32
 *
 * @param[in] input   4 
 * @return int32 
 */
static unsigned int uint8ToUint32(unsigned char* input)
{
     unsigned int r = ( (input[3]) | (input[2]<<8) | (input[1]<<16) | (input[0]<<24));
     return r;
}

/** @brief  int32   
 *
 * @param[in] input int32 
 * @param[out] output   4 
 */
static void uint32ToUint8(unsigned int input, unsigned char* output)
{
     int i;
     for(i = 0; i < 4; ++i)
     {
          output[3-i] = ( ( input >> (8*i) ) & 0x000000ff );
     }
}


/** @brief    id-tc26-gost-28147-param-Z OID: 1.2.643.7.1.2.5.1.1 */
unsigned char p[8][16] =
{
     {0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1},
     {0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf},
     {0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0},
     {0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb},
     {0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc},
     {0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0},
     {0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7},
     {0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2}

};

/** @brief      */
unsigned char kEncRoundKey[32] = 
{
     0, 4, 8, 12, 16, 20, 24, 28, 0, 4, 8, 12, 16, 20, 24, 28, 0, 4, 8, 12, 16, 20, 24, 28, 28, 24, 20, 16, 12, 8, 4, 0
};

/** @brief      */
unsigned char kDecRoundKey[32] = 
{
     0, 4, 8, 12, 16, 20, 24, 28, 28, 24, 20, 16, 12, 8, 4, 0, 28, 24, 20, 16, 12, 8, 4, 0, 28, 24, 20, 16, 12, 8, 4, 0
};

unsigned int DLL_IMPORT funcT(unsigned int a, printout_uint_array print)
{
     unsigned int res = 0;

     res ^=   p[ 0 ][ a & 0x0000000f ];
     res ^= ( p[ 1 ][ ( ( a & 0x000000f0 ) >>  4 ) ] << 4 );
     res ^= ( p[ 2 ][ ( ( a & 0x00000f00 ) >>  8 ) ] << 8 );
     res ^= ( p[ 3 ][ ( ( a & 0x0000f000 ) >> 12 ) ] << 12 );
     res ^= ( p[ 4 ][ ( ( a & 0x000f0000 ) >> 16 ) ] << 16 );
     res ^= ( p[ 5 ][ ( ( a & 0x00f00000 ) >> 20 ) ] << 20 );
     res ^= ( p[ 6 ][ ( ( a & 0x0f000000 ) >> 24 ) ] << 24 );
     res ^= ( p[ 7 ][ ( ( a & 0xf0000000 ) >> 28 ) ] << 28 );

     if(print)
     {
          print("funcT: a: ", &a, 1);
          print("funcT: output: ", &res, 1);
     }

     return res;
}

unsigned int DLL_IMPORT funcG(unsigned int a, unsigned int k, printout_uint_array print)
{
     
     unsigned int c = a + k;
     unsigned int tmp = funcT(c, print);
     unsigned int r = (tmp<<11) | (tmp >> 21);

     if(print)
     {
          print("funcG: a: ", &a, 1);
          print("funcG: k: ", &k, 1);
          print("funcG: output: ", &r, 1);
     }

     return r;
}

void DLL_IMPORT Round(unsigned int* a1, unsigned int* a0, unsigned int k, printout_uint_array print)
{
     unsigned int a;
     unsigned int tmp;

     if(print)
     {
          print("Round: input a1: ", a1, 1);
          print("Round: input a0: ", a0, 1);
          print("Round: k: ", &k, 1);
     }

     a = *a0;
     tmp = funcG(*a0, k, print);
    
     *a0 = *a1 ^ tmp;
     *a1 = a;

     if(print)
     {
          print("Round: output a1: ", a1, 1);
          print("Round: output a0: ", a0, 1);
     }
}

void DLL_IMPORT RoundShtrih(unsigned int* a1, unsigned int* a0, unsigned int k, printout_uint_array print)
{
     unsigned int tmp;

     if(print)
     {
          print("RoundShtrih: input a1: ", a1, 1);
          print("RoundShtrih: input a0: ", a0, 1);
          print("RoundShtrih: k: ", &k, 1);
     }

     tmp = funcG(*a0, k, print);
     *a1 ^= tmp;

     if(print)
     {
          print("RoundShtrih: output a1: ", a1, 1);
          print("RoundShtrih: output a0: ", a0, 1);
     }
}

int DLL_IMPORT CryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, unsigned char* keyIndex, printout_uint_array print)
{
     unsigned int a1 = uint8ToUint32(input);
     unsigned int a0 = uint8ToUint32(input + 4);
     int i;

     if(print)
     {
          print("CryptBlock: input a1:", &a1, 1);
          print("CryptBlock: input a0:", &a0, 1);
     }

     
     for(i = 0; i < 31; ++i)
     {
          Round(&a1, &a0, uint8ToUint32(key + keyIndex[i]), print);
     }

     RoundShtrih(&a1, &a0, uint8ToUint32(key + keyIndex[31]), print);

     if(print)
     {
          print("CryptBlock: output a1:", &a1, 1);
          print("CryptBlock: output a0:", &a0, 1);
     }

     uint32ToUint8(a1, output);
     uint32ToUint8(a0, output+4);

     return 0;
}

int DLL_IMPORT EncryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print)
{
     return CryptBlock(input, output, key, kEncRoundKey, print);
}

int DLL_IMPORT DecryptBlock(unsigned char* input, unsigned char* output, unsigned char* key, printout_uint_array print)
{
     return CryptBlock(input, output, key, kDecRoundKey, print);
}

int DLL_IMPORT Encrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint)
{
     if( !input || !output || !key )
     {
          if(print)
               print("Encrypt_89: internal error!", 0, 0);
          return -1;
     }

     if(EncryptBlock(input, output, key, print_uint))
         return -1;

     if(print)
     {
          print("Encrypt_89: plain text: ", input, 8);
          print("Encrypt_89: chipher text: ", output, 8);
     }

     return 0;
}

int DLL_IMPORT Decrypt_89(unsigned char* input, unsigned char* output, unsigned char* key, printout_byte_array print, printout_uint_array print_uint)
{
     if( !input || !output || !key )
     {
          if(print)
               print("Decrypt_89: internal error!", 0, 0);
          return -1;
     }

     if(DecryptBlock(input, output, key, print_uint))
          return -1;

     if(print)
     {
          print("Encrypt_89: chipher text: ", input, 8);
          print("Encrypt_89: plain text: ", output, 8);
     }
     
     return 0;
}