diff src/win32/7zip/7z/C/Aes.c @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/C/Aes.c	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,262 @@
     1.4 +/* Aes.c -- AES encryption / decryption
     1.5 +2008-08-05
     1.6 +Igor Pavlov
     1.7 +Public domain */
     1.8 +
     1.9 +#include "Aes.h"
    1.10 +#include "CpuArch.h"
    1.11 +
    1.12 +static UInt32 T[256 * 4];
    1.13 +static Byte Sbox[256] = {
    1.14 +  0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    1.15 +  0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    1.16 +  0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    1.17 +  0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    1.18 +  0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    1.19 +  0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    1.20 +  0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    1.21 +  0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    1.22 +  0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    1.23 +  0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    1.24 +  0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    1.25 +  0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    1.26 +  0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    1.27 +  0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    1.28 +  0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    1.29 +  0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
    1.30 +
    1.31 +static UInt32 D[256 * 4];
    1.32 +static Byte InvS[256];
    1.33 +
    1.34 +static Byte Rcon[11] = { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
    1.35 +
    1.36 +#define xtime(x) ((((x) << 1) ^ (((x) & 0x80) != 0 ? 0x1B : 0)) & 0xFF)
    1.37 +
    1.38 +#define Ui32(a0, a1, a2, a3) ((UInt32)(a0) | ((UInt32)(a1) << 8) | ((UInt32)(a2) << 16) | ((UInt32)(a3) << 24))
    1.39 +
    1.40 +#define gb0(x) ( (x)          & 0xFF)
    1.41 +#define gb1(x) (((x) >> ( 8)) & 0xFF)
    1.42 +#define gb2(x) (((x) >> (16)) & 0xFF)
    1.43 +#define gb3(x) (((x) >> (24)) & 0xFF)
    1.44 +
    1.45 +void AesGenTables(void)
    1.46 +{
    1.47 +  unsigned i;
    1.48 +  for (i = 0; i < 256; i++)
    1.49 +    InvS[Sbox[i]] = (Byte)i;
    1.50 +  for (i = 0; i < 256; i++)
    1.51 +  {
    1.52 +    {
    1.53 +      UInt32 a1 = Sbox[i];
    1.54 +      UInt32 a2 = xtime(a1);
    1.55 +      UInt32 a3 = xtime(a1) ^ a1;
    1.56 +      T[        i] = Ui32(a2, a1, a1, a3);
    1.57 +      T[0x100 + i] = Ui32(a3, a2, a1, a1);
    1.58 +      T[0x200 + i] = Ui32(a1, a3, a2, a1);
    1.59 +      T[0x300 + i] = Ui32(a1, a1, a3, a2);
    1.60 +    }
    1.61 +    {
    1.62 +      UInt32 a1 = InvS[i];
    1.63 +      UInt32 a2 = xtime(a1);
    1.64 +      UInt32 a4 = xtime(a2);
    1.65 +      UInt32 a8 = xtime(a4);
    1.66 +      UInt32 a9 = a8 ^ a1;
    1.67 +      UInt32 aB = a8 ^ a2 ^ a1;
    1.68 +      UInt32 aD = a8 ^ a4 ^ a1;
    1.69 +      UInt32 aE = a8 ^ a4 ^ a2;
    1.70 +      D[        i] = Ui32(aE, a9, aD, aB);
    1.71 +      D[0x100 + i] = Ui32(aB, aE, a9, aD);
    1.72 +      D[0x200 + i] = Ui32(aD, aB, aE, a9);
    1.73 +      D[0x300 + i] = Ui32(a9, aD, aB, aE);
    1.74 +    }
    1.75 +  }
    1.76 +}
    1.77 +
    1.78 +#define HT(i, x, s) (T + (x << 8))[gb ## x(s[(i + x) & 3])]
    1.79 +#define HT4(m, i, s, p) m[i] = \
    1.80 +    HT(i, 0, s) ^ \
    1.81 +    HT(i, 1, s) ^ \
    1.82 +    HT(i, 2, s) ^ \
    1.83 +    HT(i, 3, s) ^ w[p + i]
    1.84 +/* such order (2031) in HT16 is for VC6/K8 speed optimization) */
    1.85 +#define HT16(m, s, p) \
    1.86 +    HT4(m, 2, s, p); \
    1.87 +    HT4(m, 0, s, p); \
    1.88 +    HT4(m, 3, s, p); \
    1.89 +    HT4(m, 1, s, p); \
    1.90 +
    1.91 +#define FT(i, x) Sbox[gb ## x(m[(i + x) & 3])]
    1.92 +#define FT4(i) dest[i] = Ui32(FT(i, 0), FT(i, 1), FT(i, 2), FT(i, 3)) ^ w[i];
    1.93 +
    1.94 +#define HD(i, x, s) (D + (x << 8))[gb ## x(s[(i - x) & 3])]
    1.95 +#define HD4(m, i, s, p) m[i] = \
    1.96 +    HD(i, 0, s) ^ \
    1.97 +    HD(i, 1, s) ^ \
    1.98 +    HD(i, 2, s) ^ \
    1.99 +    HD(i, 3, s) ^ w[p + i];
   1.100 +/* such order (0231) in HD16 is for VC6/K8 speed optimization) */
   1.101 +#define HD16(m, s, p) \
   1.102 +    HD4(m, 0, s, p); \
   1.103 +    HD4(m, 2, s, p); \
   1.104 +    HD4(m, 3, s, p); \
   1.105 +    HD4(m, 1, s, p); \
   1.106 +
   1.107 +#define FD(i, x) InvS[gb ## x(m[(i - x) & 3])]
   1.108 +#define FD4(i) dest[i] = Ui32(FD(i, 0), FD(i, 1), FD(i, 2), FD(i, 3)) ^ w[i];
   1.109 +
   1.110 +void Aes_SetKeyEncode(CAes *p, const Byte *key, unsigned keySize)
   1.111 +{
   1.112 +  unsigned i, wSize;
   1.113 +  UInt32 *w;
   1.114 +  keySize /= 4;
   1.115 +  p->numRounds2 = keySize / 2 + 3;
   1.116 +
   1.117 +  wSize = (p->numRounds2 * 2 + 1) * 4;
   1.118 +  w = p->rkey;
   1.119 +
   1.120 +  for (i = 0; i < keySize; i++, key += 4)
   1.121 +    w[i] = Ui32(key[0], key[1], key[2], key[3]);
   1.122 +
   1.123 +  for (; i < wSize; i++)
   1.124 +  {
   1.125 +    UInt32 t = w[i - 1];
   1.126 +    unsigned rem = i % keySize;
   1.127 +    if (rem == 0)
   1.128 +      t = Ui32(Sbox[gb1(t)] ^ Rcon[i / keySize], Sbox[gb2(t)], Sbox[gb3(t)], Sbox[gb0(t)]);
   1.129 +    else if (keySize > 6 && rem == 4)
   1.130 +      t = Ui32(Sbox[gb0(t)], Sbox[gb1(t)], Sbox[gb2(t)], Sbox[gb3(t)]);
   1.131 +    w[i] = w[i - keySize] ^ t;
   1.132 +  }
   1.133 +}
   1.134 +
   1.135 +void Aes_SetKeyDecode(CAes *p, const Byte *key, unsigned keySize)
   1.136 +{
   1.137 +  unsigned i, num;
   1.138 +  UInt32 *w;
   1.139 +  Aes_SetKeyEncode(p, key, keySize);
   1.140 +  num = p->numRounds2 * 8 - 4;
   1.141 +  w = p->rkey + 4;
   1.142 +  for (i = 0; i < num; i++)
   1.143 +  {
   1.144 +    UInt32 r = w[i];
   1.145 +    w[i] =
   1.146 +      D[        Sbox[gb0(r)]] ^
   1.147 +      D[0x100 + Sbox[gb1(r)]] ^
   1.148 +      D[0x200 + Sbox[gb2(r)]] ^
   1.149 +      D[0x300 + Sbox[gb3(r)]];
   1.150 +  }
   1.151 +}
   1.152 +
   1.153 +static void AesEncode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2)
   1.154 +{
   1.155 +  UInt32 s[4];
   1.156 +  UInt32 m[4];
   1.157 +  s[0] = src[0] ^ w[0];
   1.158 +  s[1] = src[1] ^ w[1];
   1.159 +  s[2] = src[2] ^ w[2];
   1.160 +  s[3] = src[3] ^ w[3];
   1.161 +  w += 4;
   1.162 +  for (;;)
   1.163 +  {
   1.164 +    HT16(m, s, 0);
   1.165 +    if (--numRounds2 == 0)
   1.166 +      break;
   1.167 +    HT16(s, m, 4);
   1.168 +    w += 8;
   1.169 +  }
   1.170 +  w += 4;
   1.171 +  FT4(0); FT4(1); FT4(2); FT4(3);
   1.172 +}
   1.173 +
   1.174 +static void AesDecode32(UInt32 *dest, const UInt32 *src, const UInt32 *w, unsigned numRounds2)
   1.175 +{
   1.176 +  UInt32 s[4];
   1.177 +  UInt32 m[4];
   1.178 +  w += numRounds2 * 8;
   1.179 +  s[0] = src[0] ^ w[0];
   1.180 +  s[1] = src[1] ^ w[1];
   1.181 +  s[2] = src[2] ^ w[2];
   1.182 +  s[3] = src[3] ^ w[3];
   1.183 +  for (;;)
   1.184 +  {
   1.185 +    w -= 8;
   1.186 +    HD16(m, s, 4);
   1.187 +    if (--numRounds2 == 0)
   1.188 +      break;
   1.189 +    HD16(s, m, 0);
   1.190 +  }
   1.191 +  FD4(0); FD4(1); FD4(2); FD4(3);
   1.192 +}
   1.193 +
   1.194 +void Aes_Encode32(const CAes *p, UInt32 *dest, const UInt32 *src)
   1.195 +{
   1.196 +  AesEncode32(dest, src, p->rkey, p->numRounds2);
   1.197 +}
   1.198 +
   1.199 +void Aes_Decode32(const CAes *p, UInt32 *dest, const UInt32 *src)
   1.200 +{
   1.201 +  AesDecode32(dest, src, p->rkey, p->numRounds2);
   1.202 +}
   1.203 +
   1.204 +void AesCbc_Init(CAesCbc *p, const Byte *iv)
   1.205 +{
   1.206 +  unsigned i;
   1.207 +  for (i = 0; i < 4; i++)
   1.208 +    p->prev[i] = GetUi32(iv + i * 4);
   1.209 +}
   1.210 +
   1.211 +SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size)
   1.212 +{
   1.213 +  SizeT i;
   1.214 +  if (size == 0)
   1.215 +    return 0;
   1.216 +  if (size < AES_BLOCK_SIZE)
   1.217 +    return AES_BLOCK_SIZE;
   1.218 +  size -= AES_BLOCK_SIZE;
   1.219 +  for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE)
   1.220 +  {
   1.221 +    p->prev[0] ^= GetUi32(data);
   1.222 +    p->prev[1] ^= GetUi32(data + 4);
   1.223 +    p->prev[2] ^= GetUi32(data + 8);
   1.224 +    p->prev[3] ^= GetUi32(data + 12);
   1.225 +    
   1.226 +    AesEncode32(p->prev, p->prev, p->aes.rkey, p->aes.numRounds2);
   1.227 +    
   1.228 +    SetUi32(data,      p->prev[0]);
   1.229 +    SetUi32(data + 4,  p->prev[1]);
   1.230 +    SetUi32(data + 8,  p->prev[2]);
   1.231 +    SetUi32(data + 12, p->prev[3]);
   1.232 +  }
   1.233 +  return i;
   1.234 +}
   1.235 +
   1.236 +SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size)
   1.237 +{
   1.238 +  SizeT i;
   1.239 +  UInt32 in[4], out[4];
   1.240 +  if (size == 0)
   1.241 +    return 0;
   1.242 +  if (size < AES_BLOCK_SIZE)
   1.243 +    return AES_BLOCK_SIZE;
   1.244 +  size -= AES_BLOCK_SIZE;
   1.245 +  for (i = 0; i <= size; i += AES_BLOCK_SIZE, data += AES_BLOCK_SIZE)
   1.246 +  {
   1.247 +    in[0] = GetUi32(data);
   1.248 +    in[1] = GetUi32(data + 4);
   1.249 +    in[2] = GetUi32(data + 8);
   1.250 +    in[3] = GetUi32(data + 12);
   1.251 +    
   1.252 +    AesDecode32(out, in, p->aes.rkey, p->aes.numRounds2);
   1.253 +    
   1.254 +    SetUi32(data,      p->prev[0] ^ out[0]);
   1.255 +    SetUi32(data + 4,  p->prev[1] ^ out[1]);
   1.256 +    SetUi32(data + 8,  p->prev[2] ^ out[2]);
   1.257 +    SetUi32(data + 12, p->prev[3] ^ out[3]);
   1.258 +    
   1.259 +    p->prev[0] = in[0];
   1.260 +    p->prev[1] = in[1];
   1.261 +    p->prev[2] = in[2];
   1.262 +    p->prev[3] = in[3];
   1.263 +  }
   1.264 +  return i;
   1.265 +}