⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aes.c

📁 这个通用的Bootloader可以支持大部分具有自编程功能、带有Boot区和UART串口的AVR单片机(主要是Mega系列)。如果是多串口的单片机
💻 C
字号:
/*

                           e Y8b    Y8b YV4.08P888 88e
                          d8b Y8b    Y8b Y888P 888 888D
                         d888b Y8b    Y8b Y8P  888 88"
                        d888WuHan8b    Y8b Y   888 b,
                       d8888888b Y8b    Y8P    888 88b,
           8888 8888       ,e,                                  888
           8888 888820088e  " Y8b Y888P ,e e, 888,8, dP"Y ,"Y88b888
           8888 8888888 88b888 Y8b Y8P d88 88b888 " C88b "8" 888888
           8888 8888888 888888  Y8b "  888   ,888    Y88D,ee 888888
           'Y88 88P'888 888888   Y8P    "YeeP"888   d,dP "88 888888
   888 88b,                    d8  888                     888
   888 88P' e88 88e  e88 88e  d88  888 e88 88e  ,"Y88b e88 888 ,e e, 888,8,
   888 8K  d888 888bd888 8Shaoziyang88d888 888b"8" 888d888 888d88 88b888 "
   888 88b,Y888 888PY888 888P 888  888Y888 888P,ee 888Y888 888888   ,888
   888 88P' "88 88"  "88 88"  888  888 "88 88" "88 888 "88 888 "YeeP"888


  Project:       AVR 通用 BootLoader
  File:          aes.c
                 aes ( Rijndael ) 128/256 位密钥加密算法
                 基于 AVR231 的 aes 子程序
                 针对 avr 8 位单片机和GCC编译器进行了优化
  Version:       1.0

  Compiler:      WinAVR 20071221 + AVR Studio 4.14.589

  Author:        Shaoziyang
                 Shaoziyang@gmail.com
                 http://avrubd.googlepages.com
                 http://groups.google.com/group/avrub?hl=en

  Date:          2008.6

  See readme.htm to get more information.

*/


//使用 OPT_MODE 进行代码大小优化或者运行速度优化
//OPT_SPEED 可以提高解密速度 20% 以上
#define OPT_SIZE  1
#define OPT_SPEED 2

#define OPT_MODE  OPT_SIZE

#define BPOLY 0x1b          //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1).
#define BLOCKSIZE 16        //!< 数据块大小(字节).

#ifndef AES_128
#define AES_128   2
#endif

#ifndef AES_256
#define AES_256   3
#endif

#ifndef Algorithm
#define Algorithm AES_128
#endif

#if (Algorithm == AES_128)
  #define ROUNDS 10         //循环次数
  #define KEYLENGTH 16      //密钥长度
#elif (Algorithm == AES_256)
  #define ROUNDS 14
  #define KEYLENGTH 32
#else
#error "Unknow encrypt algorithm!"
#endif


unsigned char block1[256];  //工作区1
unsigned char block2[256];  //工作区2
unsigned char tempbuf[256]; //临时缓冲区
unsigned char chain[16];    //密钥块链

unsigned char *powTbl;      //!< Final location of exponentiation lookup table.
unsigned char *logTbl;      //!< Final location of logarithm lookup table.
unsigned char *sBox;        //!< Final location of s-box.
unsigned char *sBoxInv;     //!< Final location of inverse s-box.
unsigned char *expandedKey; //!< Final location of expanded key.


void CalcPowLog(unsigned char *powTbl, unsigned char *logTbl)
{
  unsigned char i = 0;
  unsigned char t = 1;

  do {
    // Use 0x03 as root for exponentiation and logarithms.
    powTbl[i] = t;
    logTbl[t] = i;
    i++;

    // Muliply t by 3 in GF(2^8).
    t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0);
  }while( t != 1 ); // Cyclic properties ensure that i < 255.

  powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc.
}

void CalcSBox( unsigned char * sBox )
{
  unsigned char i, rot;
  unsigned char temp;
  unsigned char result;

  // Fill all entries of sBox[].
  i = 0;
  do {
    //Inverse in GF(2^8).
    if( i > 0 ) 
    {
      temp = powTbl[ 255 - logTbl[i] ];
    } 
    else 
    {
      temp = 0;
    }

    // Affine transformation in GF(2).
    result = temp ^ 0x63; // Start with adding a vector in GF(2).
    for( rot = 4; rot > 0; rot-- )
    {
      // Rotate left.
      temp = (temp<<1) | (temp>>7);

      // Add rotated byte in GF(2).
      result ^= temp;
    }

    // Put result in table.
    sBox[i] = result;
  } while( ++i != 0 );
}

void CalcSBoxInv( unsigned char * sBox, unsigned char * sBoxInv )
{
  unsigned char i = 0;
  unsigned char j = 0;

  // Iterate through all elements in sBoxInv using  i.
  do {
    // Search through sBox using j.
    do {
      // Check if current j is the inverse of current i.
      if( sBox[j] == i )
      {
        // If so, set sBoxInc and indicate search finished.
        sBoxInv[i] = j;
        j = 255;
      }
    } while( ++j != 0 );
  } while( ++i != 0 );
}

#if OPT_MODE == OPT_SIZE
void CalcCols(unsigned char *col)
{
  unsigned char i;

  for(i = 4; i > 0; i--)
  {
    *col = (*col << 1) ^ (*col & 0x80 ? BPOLY : 0);
    col++;
  }
}
#endif

void InvMixColumn( unsigned char * column )
{
  unsigned char r[4];

  r[0] = column[1] ^ column[2] ^ column[3];
  r[1] = column[0] ^ column[2] ^ column[3];
  r[2] = column[0] ^ column[1] ^ column[3];
  r[3] = column[0] ^ column[1] ^ column[2];

#if OPT_MODE == OPT_SIZE
  CalcCols(column);
#else
  column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
  column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
  column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
  column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
#endif

  r[0] ^= column[0] ^ column[1];
  r[1] ^= column[1] ^ column[2];
  r[2] ^= column[2] ^ column[3];
  r[3] ^= column[0] ^ column[3];

#if OPT_MODE == OPT_SIZE
  CalcCols(column);
#else
  column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
  column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
  column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
  column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
#endif

  r[0] ^= column[0] ^ column[2];
  r[1] ^= column[1] ^ column[3];
  r[2] ^= column[0] ^ column[2];
  r[3] ^= column[1] ^ column[3];

#if OPT_MODE == OPT_SIZE
  CalcCols(column);
#else
  column[0] = (column[0] << 1) ^ (column[0] & 0x80 ? BPOLY : 0);
  column[1] = (column[1] << 1) ^ (column[1] & 0x80 ? BPOLY : 0);
  column[2] = (column[2] << 1) ^ (column[2] & 0x80 ? BPOLY : 0);
  column[3] = (column[3] << 1) ^ (column[3] & 0x80 ? BPOLY : 0);
#endif

  column[0] ^= column[1] ^ column[2] ^ column[3];
  r[0] ^= column[0];
  r[1] ^= column[0];
  r[2] ^= column[0];
  r[3] ^= column[0];
  
  column[0] = r[0];
  column[1] = r[1];
  column[2] = r[2];
  column[3] = r[3];
}

void SubBytes( unsigned char * bytes, unsigned char count )
{
  do {
    *bytes = sBox[ *bytes ]; // Substitute every byte in state.
    bytes++;
  } while( --count );
}

void InvSubBytesAndXOR( unsigned char * bytes, unsigned char * key, unsigned char count )
{
  do {
    // *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key.
    *bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed.
    bytes++;
    key++;
  } while( --count );
}

void InvShiftRows( unsigned char * state )
{
  unsigned char temp;          
  // Note: State is arranged column by column.

#if OPT_MODE == OPT_SIZE
  unsigned char i, j;

  for(i = 3; i > 0; i--)
  {
    for(j = i; j > 0; j--)
    {
      temp = state[i + 3 * 4];
      state[i + 3 * 4] = state[i + 2 * 4];
      state[i + 2 * 4] = state[i + 1 * 4];
      state[i + 1 * 4] = state[i + 0 * 4];
      state[i + 0 * 4] = temp;
    }
  }
#else
  // Cycle second row right one time.
  temp = state[ 1 + 3*4 ];
  state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
  state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
  state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
  state[ 1 + 0*4 ] = temp;

  // Cycle third row right two times.
  temp = state[ 2 + 0*4 ];
  state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
  state[ 2 + 2*4 ] = temp;
  temp = state[ 2 + 1*4 ];
  state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
  state[ 2 + 3*4 ] = temp;

  // Cycle fourth row right three times, ie. left once.
  temp = state[ 3 + 0*4 ];
  state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
  state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
  state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
  state[ 3 + 3*4 ] = temp;
#endif
}

void XORBytes( unsigned char * bytes1, unsigned char * bytes2, unsigned char count )
{
  do {
    *bytes1 ^= *bytes2; // Add in GF(2), ie. XOR.
    bytes1++;
    bytes2++;
  } while( --count );
}

void CopyBytes( unsigned char * to, unsigned char * from, unsigned char count )
{
  do {
    *to = *from;
    to++;
    from++;
  } while( --count );
}

void KeyExpansion( unsigned char * expandedKey )
{
  unsigned char temp[4], t;
  unsigned char i;
  unsigned char Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant.

  const unsigned char * key = DecryptKey;

  // Copy key to start of expanded key.
  CopyBytes(expandedKey, (unsigned char *)key, KEYLENGTH);
  expandedKey += KEYLENGTH;

  // Prepare last 4 bytes of key in temp.
  CopyBytes(temp, (unsigned char *)key + KEYLENGTH - 4, 4);

  // Expand key.
  i = KEYLENGTH;
  while( i < BLOCKSIZE*(ROUNDS+1) ) 
  {
    // Are we at the start of a multiple of the key size?
    if( (i % KEYLENGTH) == 0 )
    {
      // Cycle left once.
      t = temp[0];
      temp[0] = temp[1];
      temp[1] = temp[2];
      temp[2] = temp[3];
      temp[3] = t;
      SubBytes( temp, 4 ); // Substitute each byte.
      XORBytes( temp, Rcon, 4 ); // Add constant in GF(2).
      *Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0);
    }

    // Keysize larger than 24 bytes, ie. larger that 192 bits?
    #if KEYLENGTH > 24
    // Are we right past a block size?
    else if( (i % KEYLENGTH) == BLOCKSIZE ) {
      SubBytes( temp, 4 ); // Substitute each byte.
    }
    #endif

    // Add bytes in GF(2) one KEYLENGTH away.
    XORBytes( temp, expandedKey - KEYLENGTH, 4 );

    // Copy result to current 4 bytes.
    *(expandedKey++) = temp[0];
    *(expandedKey++) = temp[1];
    *(expandedKey++) = temp[2];
    *(expandedKey++) = temp[3];

    i += 4; // Next 4 bytes.
  }
}

void InvCipher( unsigned char * block, unsigned char * expandedKey )
{
  unsigned char i, j;
  unsigned char round = ROUNDS-1;
  expandedKey += BLOCKSIZE * ROUNDS;

  XORBytes( block, expandedKey, 16 );
  expandedKey -= BLOCKSIZE;

  do {
    InvShiftRows( block );
    InvSubBytesAndXOR( block, expandedKey, 16 );
    expandedKey -= BLOCKSIZE;
    for(i = 4, j = 0; i > 0; i--, j+=4)
      InvMixColumn( block + j );
  } while( --round );

  InvShiftRows( block );
  InvSubBytesAndXOR( block, expandedKey, 16 );
}

void aesDecInit(void)
{
  unsigned char i;
  
  for(i = 0; i < 16; i++)
    chain[i] = 0;
    
  powTbl = block1;
  logTbl = block2;
  CalcPowLog( powTbl, logTbl );

  sBox = tempbuf;
  CalcSBox( sBox );

  expandedKey = block1;
  KeyExpansion( expandedKey );

  sBoxInv = block2; // Must be block2.
  CalcSBoxInv( sBox, sBoxInv );
}

#define DecryptInit()     aesDecInit()

//解密数据块
void DecryptBlock(unsigned char *buf, unsigned int nSize)
{
  unsigned int n;

  for(n = nSize; n > 0; n -= 16)
  {
    CopyBytes( tempbuf, buf, BLOCKSIZE );
    InvCipher( buf, expandedKey );
    XORBytes( buf, chain, BLOCKSIZE );
    CopyBytes( chain, tempbuf, BLOCKSIZE );
    buf += 16;
  }
}

//销毁密钥
void DestroyKey()
{
  unsigned char i;

#if (Algorithm == AES_128)
  for(i = 16; i > 0; i--)
#else
  for(i = 32; i > 0; i--)
#endif
  {
    DecryptKey[i - 1] = 0;
  }
}

//end of file

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -