aes.c

来自「Advanced encryption system of NIST( 美国国家」· C语言 代码 · 共 1,366 行 · 第 1/5 页

C
1,366
字号
0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41, 0x67b35a1d, 0xdb9252d2, 
0x10e93356, 0xd66d1347, 0xd79a8c61, 0xa1377a0c, 0xf8598e14, 0x13eb893c, 
0xa9ceee27, 0x61b735c9, 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 
0x141879ce, 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db, 
0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3, 0xe2bc0c25, 
0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3, 0xb4d89ce4, 0x566490c1, 
0xcb7b6184, 0x32d570b6, 0x6c48745c, 0xb8d04257};

static const ULONG InvTable3[256] = {
0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab, 0x1ff1459d, 
0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76, 0x889176cc, 0xf5254c02, 
0x4ffcd7e5, 0xc5d7cb2a, 0x26804435, 0xb58fa362, 0xde495ab1, 0x25671bba, 
0x45980eea, 0x5de1c0fe, 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 
0x03e75f8f, 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174, 
0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58, 0x27dd71b9, 
0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace, 0x63184adf, 0xe582311a, 
0x97603351, 0x62457f53, 0xb1e07764, 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 
0x70586848, 0x8f19fd45, 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 
0xe3578f1f, 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837, 
0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf, 0xa792b479, 
0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05, 0xd11f6234, 0xc48afea6, 
0x349d532e, 0xa2a055f3, 0x0532e18a, 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 
0x5e069f71, 0xbd51106e, 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 
0x91b58d54, 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd, 
0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19, 0x79dbeec8, 
0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000, 0x09838680, 0x3248ed2b, 
0x1eac7011, 0x6c4e725a, 0xfdfbff0e, 0x0f563885, 0x3d1ed5ae, 0x3627392d, 
0x0a64d90f, 0x6821a65c, 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 
0xb4d296ee, 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12, 
0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09, 0xf2adc78b, 
0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775, 0xeebbdd99, 0xa3fd607f, 
0xf79f2601, 0x5cbcf572, 0x44c53b66, 0x5b347efb, 0x8b762943, 0xcbdcc623, 
0xb668fced, 0xb863f1e4, 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 
0x857d244a, 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2, 
0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894, 0x472264e9, 
0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033, 0x87c74e49, 0xd9c1d138, 
0x8cfea2ca, 0x98360bd4, 0xa6cf81f5, 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 
0x2ce49d3a, 0x500d9278, 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 
0x2e5ef739, 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225, 
0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826, 0x6ef41859, 
0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff, 0x2108cfbc, 0xefe6e815, 
0xbad99be7, 0x4ace366f, 0xead4099f, 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 
0xc63094a5, 0x35c066a2, 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 
0xf14a9804, 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef, 
0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c, 0x467f5165, 
0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b, 0xb35a1d67, 0x9252d2db, 
0xe9335610, 0x6d1347d6, 0x9a8c61d7, 0x377a0ca1, 0x598e14f8, 0xeb893c13, 
0xceee27a9, 0xb735c961, 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 
0x1879ce14, 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44, 
0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d, 0xbc0c25e2, 
0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c, 0xd89ce4b4, 0x6490c156, 
0x7b6184cb, 0xd570b632, 0x48745c6c, 0xd04257b8};
#endif /* AES_COMPACT */

int IsBigEndian;

#ifdef AES_VERBOSE
int ROUND;
#endif


/******************************************************************************/
/* AES Private Kernel Functions */

inline UCHAR xtime (unsigned int f);
static inline UCHAR xplus1time (unsigned int f);
inline UCHAR polymul (unsigned int f, unsigned int g);
inline void MixColumns (AESSTATE State, int Nb);
inline void InvMixColumns (AESSTATE State, int Nb);
static inline void ShiftRows (AESSTATE State, int Nb);
static inline void InvShiftRows (AESSTATE State, int Nb);
inline void SubBytes (AESSTATE State, int Nb);
inline void InvSubBytes (AESSTATE State, int Nb);
inline void AddRoundKey (AESSTATE State, AESROUNDKEY RoundKey, int Nb);
static inline void Round (AESSTATE State, AESROUNDKEY RoundKey, int Nb);
static inline void FinalRound (AESSTATE State, AESROUNDKEY RoundKey, int Nb);
static inline void InvRound (AESSTATE State, AESROUNDKEY RoundKey, int Nb);
static inline void InvFinalRound (AESSTATE State, AESROUNDKEY RoundKey, int Nb);

/* Functions for purging security critical data */
static inline void ZeroUchar (UCHAR *a);
static inline void Zero2Uchar (UCHAR *a, UCHAR *b);
static inline void Zero4Uchar (UCHAR *a, UCHAR *b, UCHAR *c, UCHAR *d);
static inline void ZeroUlong (ULONG *a);
static inline void Zero2Ulong (ULONG *a, ULONG *b);
static inline void Zero4Ulong (ULONG *a, ULONG *b, ULONG *c, ULONG *d);
static inline void ZeroUcharArray (UCHAR *a, int Len);

/* Test of Endianness */
static void TestEndian(int *IsBigEndian);

#ifdef AES_VERBOSE
static inline void PrintState (char * step, AESSTATE State, int Nb);
#endif /* AES_VERBOSE? */


/******************************************************************************/
/*                                                                            */
/*  Function:   Key Schedule                                                  */
/*  Syntax:     int                                                           */
/*              AESKeySched_l (AESKEYSCHED *CookedKey, AESKEY RawKey,         */
/*                    int KeyLength, int BlkLength, int DFlag, int mode);     */
/*  Input:      AESKEY RawKey (Key vector provided by user)                   */
/*              int KeyLength (Length of user key in bit: 128, 192, 256)      */
/*              int BlkLength (Length of plaintext/cipherblocks in bit)       */
/*              int DFlag (Encipher/decipher mode AES_ENC, AES_DEC)           */
/*              int mode (Mode of operation AES_ECB, AES_CBC)                 */
/*  Output:     AESKEYSCHED *CookedKey (Keyschedule)                          */
/*  Returns:    E_AES_OK if everything is O.K.                                */
/*              E_AES_DIRECTION if DFlag != AES_ENC or AES_DEC                */
/*              E_AES_MODE if mode != AES_ECB or AES_CBC                      */
/*              E_AES_KEYLENGTH if KeyLength != 128, 192 or 256               */
/*                                                                            */
/******************************************************************************/
int __FLINT_API 
AESKeySched_l (AESKEYSCHED *CookedKey, AESKEY RawKey, int KeyLength, 
                                  int BlkLength, int DFlag, int mode)
{
  if ((DFlag != AES_ENC) && (DFlag != AES_DEC))
    {
#if defined AES_VERBOSE
      fprintf (stderr, "AES_ERR_DIRECTION in line %d\n", __LINE__);
#endif
      return AES_ERR_DIRECTION;
    }

  if ((KeyLength != 128) && (KeyLength != 192) && (KeyLength != 256))
    {
#if defined AES_VERBOSE
      fprintf (stderr, "AES_ERR_KEYLENGTH in line %d\n", __LINE__);
#endif
      return AES_ERR_KEYLENGTH;
    }

  if ((BlkLength != 128) && (BlkLength != 192) && (BlkLength != 256))
    {
#ifdef AES_VERBOSE
      fprintf (stderr, "AES_ERR_BLKLENGTH in line %d\n", __LINE__);
#endif
      return AES_ERR_BLKLENGTH;
    }

  switch (DFlag)
    {
      case AES_ENC:
        AESKeyExpansion (CookedKey->ExpandedKey, RawKey, KeyLength, BlkLength);
        break;
      case AES_DEC:
        AESInvKeyExpansion (CookedKey->ExpandedKey, RawKey, KeyLength, BlkLength);
        break;
      default:
        return AES_ERR_MODE;
    }

  CookedKey->mode = mode; 
  CookedKey->KeyLength = KeyLength; 
  CookedKey->BlkLength = BlkLength; 
  CookedKey->DFlag = DFlag; 
  return AES_OK;
}


/******************************************************************************/
/*                                                                            */
/*  Function:   Initialization of AES routines                                */
/*  Syntax:     int                                                           */
/*              AESInit_l (AESWORKSPACE *ws, int mode, int BlkLength,         */
/*                       AESBLOCK IV, AESKEYSCHED *CookedKey, AESKEY RawKey,  */
/*                       int KeyLength, int DFlag);                           */
/*  Input:      int mode (Mode of operation AES_ECB, AES_CBC)                 */
/*              int BlkLength (Length of plaintext/cipherblocks in bit)       */
/*              AESBLOCK IV (Initialization vector for CBC mode operation,    */
/*                           IV may be NULL for ECB mode)                     */
/*              AESKEY RawKey (Key vector provided by user)                   */
/*              int KeyLength (Length of user key in bit: 128, 192, 256)      */
/*              int DFlag (Encipher/decipher mode AES_ENC, AES_DEC)           */
/*  Output:     AESWORKSPACE *ws (Initialized buffer)                         */
/*              AESKEYSCHED *CookedKey (Keyschedule)                          */
/*  Returns:    E_AES_OK if everything is O.K.                                */
/*              E_AES_DIRECTION if DFlag != AES_ENC or AES_DEC                */
/*              E_AES_MODE if mode != AES_ECB or AES_CBC                      */
/*              E_AES_KEYLENGTH if KeyLength != 128, 192 or 256               */
/*              E_AES_BLKLENGTH if BlkLength != 128, 192 or 256               */
/*                                                                            */
/******************************************************************************/
int __FLINT_API
AESInit_l (AESWORKSPACE *ws, int mode, int BlkLength, AESBLOCK IV, 
           AESKEYSCHED *CookedKey, AESKEY RawKey, int KeyLength, int DFlag)
{
  int col, col4, Nb;
  if ((mode != AES_CBC) && (mode != AES_ECB))
    {
#ifdef AES_TEST
      fprintf (stderr, "AES_ERR_MODE in line %d\n", __LINE__);
#endif
      return AES_ERR_MODE;
    }

  if ((BlkLength != 128) && (BlkLength != 192) && (BlkLength != 256))
    {
#ifdef AES_TEST
      fprintf (stderr, "AES_ERR_BLKLENGTH in line %d\n", __LINE__);
#endif
      return AES_ERR_BLKLENGTH;
    }

  if ((KeyLength != 128) && (KeyLength != 192) && (KeyLength != 256))
    {
#ifdef AES_TEST
      fprintf (stderr, "AES_ERR_KEYLENGTH in line %d\n", __LINE__);
#endif
      return AES_ERR_KEYLENGTH;
    }

  if ((DFlag != AES_ENC) && (DFlag != AES_DEC))
    {
#ifdef AES_TEST
      fprintf (stderr, "AES_ERR_DIRECTION in line %d\n", __LINE__);
#endif
      return AES_ERR_DIRECTION;
    }

  TestEndian (&IsBigEndian);

  ws->mode = mode;
  ws->BlkLength = BlkLength;
  Nb = BlkLength/32;

  AESKeySched (CookedKey, RawKey, KeyLength, BlkLength, DFlag, mode);

  if (ws->mode == AES_CBC)
    {
      switch (CookedKey->DFlag)
        {
          case AES_ENC:
            for (col = col4 = 0; col < Nb; col++, col4+=4)
              {
                ws->State[col] = UC2UL(&IV[col4]);
              }
            break;
          case AES_DEC:
            for (col = col4 = 0; col < Nb; col++, col4+=4)
              {
                ws->Block[col] = UC2UL(&IV[col4]);
              }
            break;
        }
    }

  return AES_OK;
}
  

/******************************************************************************/
/*                                                                            */
/*  Function:   AES encryption and decryption with support for ECB/CBC modes  */
/*              Processing of several portions of text by subsequent calls to */
/*              AESCrypt_l is supported for ECB and CBC mode                  */
/*              If not #defined AES_COMPACT fast table lookup is performed    */
/*  Syntax:     int                                                           */
/*              AESCrypt_l (AESBLOCK OutBlock, AESWORKSPACE *ws,              */
/*                          AESKEYSCHED *ks, AESBLOCK InBlock, int InLength); */
/*  Input:      AESWORKSPACE *ws (Initialized buffer)                         */
/*              AESKEYSCHED *ks (Initialized Keyschedule)                     */
/*              AESBLOCK InBlock (Plaintext/Ciphertext)                       */
/*              int InLength (Length of InBlock in bytes                      */
/*                            InLength = 0 mod BlkLength/8 given in AESInit_l */
/*  Output:     AESBLOCK OutBlock (Ciphertext/Plaintext)                      */
/*  Returns:    E_AES_OK if everything is O.K.                                */
/*              E_AES_DIRECTION if DFlag differs in ws and ks                 */
/*              E_AES_MODE if mode differs in ws and ks                       */
/*              E_AES_KEYLENGTH if KeyLength given in ks != 128, 192 or 256   */
/*              E_AES_BLKLENGTH if BlkLength differs in ws and ks             */
/*                                                                            */

⌨️ 快捷键说明

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