/***************************************************************************
                          protosupport.cpp  -  description
                             -------------------
    begin                : Fri Mar 7 2003
    copyright            : (C) 2003 by Giorgio A.
    email                : openc6@hotmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#define WORD_WRITE(ptr,value) do { *ptr = (unsigned char)((value & 0xff00) >> 8); ptr++; \
*ptr = (unsigned char)(value & 0x00ff) ; ptr++; } while (0)

#include "protosupport.h"

extern "C"
  {
    #include "blowfish.h"
    #include "md5.h"
    #include <string.h>
  }

static void generateKey(unsigned char *pDest,unsigned char const *pSorg)
{
  struct md5_context ctx;

  md5_starts( &ctx );
  md5_update( &ctx, (uint8 *) pSorg, strlen((char *)pSorg));
  md5_finish( &ctx, pDest );
}

void encodeMD5Key(const char *StrCode,unsigned char *StrKeyServer,unsigned char *StrDest,bool isPsw)
{
  const unsigned char Strtemp[]="ANOCI";
  unsigned char tt[30];

  if (isPsw)
    {
      int y = strlen((char*)StrCode);
      memcpy(tt,StrCode,y);
      tt[y] = StrKeyServer[0];
      tt[y+1] = StrKeyServer[2];
      tt[y+2] =0;
    }
  else
    {
      memcpy(tt,Strtemp,5);
      tt[5] = StrCode[strlen((char *)StrCode)-1];
      tt[6] = StrCode[0];
      tt[7] = StrKeyServer[4];
      tt[8] = StrKeyServer[2];
      tt[9] = 0;
    }

    generateKey(reinterpret_cast<unsigned char*>(StrDest),tt);

  for(unsigned int i=0; i < 16 ;i++)
    {
      StrDest[i] = (StrDest[i] % 0x5E)+0x20;
    }
}

void xorCode(unsigned char *pSorg,unsigned char *pDest,unsigned char *pKeyOrd,int len)
{
  for(int i=0; i < len ; i++)
    {
      pDest[i]=pSorg[i]^pKeyOrd[i % 7];
    }
}

void orderServerKey(unsigned char *dest,unsigned char const *source)
{
  const unsigned int step = source[5] % 7;
  int i=1;

  dest[0]=source[0];
  while (i < 8)
    {
      dest[i] = source[(i*step) % 7];
      i++;
    }
}

void blowFishEncode(int len,unsigned char *source,int len_key,unsigned char* init)
{
  BLOWFISH_CTX ctx;
  unsigned long lvalue,rvalue;

  Blowfish_Init(&ctx,init,len_key);

  for (int i=0; i < (len / 8); i++)
    {
      lvalue = *source << 24 | *(source+1) << 16 | +*(source+2) << 8 | *(source+3);
      rvalue = *(source+4) << 24 | *(source+5) << 16 | +*(source+6) << 8 | *(source+7);

      Blowfish_Encrypt(&ctx,&lvalue,&rvalue);
      WORD_WRITE(source,lvalue >> 16);
      WORD_WRITE(source,lvalue & 0x0000ffff);
      WORD_WRITE(source,rvalue >> 16);
      WORD_WRITE(source,rvalue & 0x0000ffff);
    }
}

void blowFishDecode(int len,unsigned char *source,int len_key,unsigned char* init)
{
  BLOWFISH_CTX ctx;
  unsigned long lvalue,rvalue;

  Blowfish_Init(&ctx,init,len_key);

  for (int i=0; i < (len / 8); i++)
    {
      lvalue = *source << 24 | *(source+1) << 16 | +*(source+2) << 8 | *(source+3);
      rvalue = *(source+4) << 24 | *(source+5) << 16 | +*(source+6) << 8 | *(source+7);

      Blowfish_Decrypt(&ctx,&lvalue,&rvalue);
      WORD_WRITE(source,lvalue >> 16);
      WORD_WRITE(source,lvalue & 0x0000ffff);
      WORD_WRITE(source,rvalue >> 16);
      WORD_WRITE(source,rvalue & 0x0000ffff);
    }
}


void encodeNewMd5Key(unsigned char *md5Key,unsigned char const *key)
{
  unsigned char new_key[19];
  const unsigned char init_pattern[10]=
    {
      0x4a,0x4e,0x42,0x55,0x25,0x5e,0x26,0x43,0x29,0x25
    };

  memcpy(new_key,key,8);
  memcpy(new_key+8,init_pattern,10);
  new_key[18]=0;

  generateKey(md5Key,new_key);

  for(unsigned int l=0; l< 16 ;l++)
    {
      md5Key[l] = (md5Key[l] % 0x5E)+0x20;
    }
}