📄 aes.cpp
字号:
/* aes.cpp
*
* Copyright (C) 2003 Sawtooth Consulting Ltd.
*
* This file is part of yaSSL, an SSL implementation written by Todd A Ouska
* (todd at yassl.com, see www.yassl.com).
*
* yaSSL 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.
*
* There are special exceptions to the terms and conditions of the GPL as it
* is applied to yaSSL. View the full text of the exception in the file
* FLOSS-EXCEPTIONS in the directory of this software distribution.
*
* yaSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/* C++ based on Wei Dai's aes.cpp from CryptoPP */
/* x86 asm original */
#if defined(TAOCRYPT_KERNEL_MODE)
#define DO_TAOCRYPT_KERNEL_MODE
#endif // only some modules now support this
#include "runtime.hpp"
#include "aes.hpp"
namespace TaoCrypt {
#if defined(DO_AES_ASM)
// ia32 optimized version
void AES::Process(byte* out, const byte* in, word32 sz)
{
if (!isMMX) {
Mode_BASE::Process(out, in, sz);
return;
}
word32 blocks = sz / BLOCK_SIZE;
if (mode_ == ECB)
while (blocks--) {
if (dir_ == ENCRYPTION)
AsmEncrypt(in, out, (void*)Te0);
else
AsmDecrypt(in, out, (void*)Td0);
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
else if (mode_ == CBC)
if (dir_ == ENCRYPTION)
while (blocks--) {
r_[0] ^= *(word32*)in;
r_[1] ^= *(word32*)(in + 4);
r_[2] ^= *(word32*)(in + 8);
r_[3] ^= *(word32*)(in + 12);
AsmEncrypt((byte*)r_, (byte*)r_, (void*)Te0);
memcpy(out, r_, BLOCK_SIZE);
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
else
while (blocks--) {
AsmDecrypt(in, out, (void*)Td0);
*(word32*)out ^= r_[0];
*(word32*)(out + 4) ^= r_[1];
*(word32*)(out + 8) ^= r_[2];
*(word32*)(out + 12) ^= r_[3];
memcpy(r_, in, BLOCK_SIZE);
out += BLOCK_SIZE;
in += BLOCK_SIZE;
}
}
#endif // DO_AES_ASM
void AES::SetKey(const byte* userKey, word32 keylen, CipherDir /*dummy*/)
{
assert( (keylen == 16) || (keylen == 24) || (keylen == 32) );
rounds_ = keylen/4 + 6;
word32 temp, *rk = key_;
unsigned int i=0;
GetUserKey(BigEndianOrder, rk, keylen/4, userKey, keylen);
switch(keylen)
{
case 16:
while (true)
{
temp = rk[3];
rk[4] = rk[0] ^
(Te4[GETBYTE(temp, 2)] & 0xff000000) ^
(Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
(Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
(Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
rcon_[i];
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10)
break;
rk += 4;
}
break;
case 24:
while (true) // for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack
{
temp = rk[ 5];
rk[ 6] = rk[ 0] ^
(Te4[GETBYTE(temp, 2)] & 0xff000000) ^
(Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
(Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
(Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
rcon_[i];
rk[ 7] = rk[ 1] ^ rk[ 6];
rk[ 8] = rk[ 2] ^ rk[ 7];
rk[ 9] = rk[ 3] ^ rk[ 8];
if (++i == 8)
break;
rk[10] = rk[ 4] ^ rk[ 9];
rk[11] = rk[ 5] ^ rk[10];
rk += 6;
}
break;
case 32:
while (true)
{
temp = rk[ 7];
rk[ 8] = rk[ 0] ^
(Te4[GETBYTE(temp, 2)] & 0xff000000) ^
(Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
(Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
(Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
rcon_[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
if (++i == 7)
break;
temp = rk[11];
rk[12] = rk[ 4] ^
(Te4[GETBYTE(temp, 3)] & 0xff000000) ^
(Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
(Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
(Te4[GETBYTE(temp, 0)] & 0x000000ff);
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
rk += 8;
}
break;
}
if (dir_ == DECRYPTION)
{
unsigned int i, j;
rk = key_;
/* invert the order of the round keys: */
for (i = 0, j = 4*rounds_; i < j; i += 4, j -= 4) {
temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
}
// apply the inverse MixColumn transform to all round keys but the
// first and the last:
for (i = 1; i < rounds_; i++) {
rk += 4;
rk[0] =
Td0[Te4[GETBYTE(rk[0], 3)] & 0xff] ^
Td1[Te4[GETBYTE(rk[0], 2)] & 0xff] ^
Td2[Te4[GETBYTE(rk[0], 1)] & 0xff] ^
Td3[Te4[GETBYTE(rk[0], 0)] & 0xff];
rk[1] =
Td0[Te4[GETBYTE(rk[1], 3)] & 0xff] ^
Td1[Te4[GETBYTE(rk[1], 2)] & 0xff] ^
Td2[Te4[GETBYTE(rk[1], 1)] & 0xff] ^
Td3[Te4[GETBYTE(rk[1], 0)] & 0xff];
rk[2] =
Td0[Te4[GETBYTE(rk[2], 3)] & 0xff] ^
Td1[Te4[GETBYTE(rk[2], 2)] & 0xff] ^
Td2[Te4[GETBYTE(rk[2], 1)] & 0xff] ^
Td3[Te4[GETBYTE(rk[2], 0)] & 0xff];
rk[3] =
Td0[Te4[GETBYTE(rk[3], 3)] & 0xff] ^
Td1[Te4[GETBYTE(rk[3], 2)] & 0xff] ^
Td2[Te4[GETBYTE(rk[3], 1)] & 0xff] ^
Td3[Te4[GETBYTE(rk[3], 0)] & 0xff];
}
}
}
void AES::ProcessAndXorBlock(const byte* in, const byte* xOr, byte* out) const
{
if (dir_ == ENCRYPTION)
encrypt(in, xOr, out);
else
decrypt(in, xOr, out);
}
typedef BlockGetAndPut<word32, BigEndian> gpBlock;
void AES::encrypt(const byte* inBlock, const byte* xorBlock,
byte* outBlock) const
{
word32 s0, s1, s2, s3;
word32 t0, t1, t2, t3;
const word32 *rk = key_;
/*
* map byte array block to cipher state
* and add initial round key:
*/
gpBlock::Get(inBlock)(s0)(s1)(s2)(s3);
s0 ^= rk[0];
s1 ^= rk[1];
s2 ^= rk[2];
s3 ^= rk[3];
/*
* Nr - 1 full rounds:
*/
unsigned int r = rounds_ >> 1;
for (;;) {
t0 =
Te0[GETBYTE(s0, 3)] ^
Te1[GETBYTE(s1, 2)] ^
Te2[GETBYTE(s2, 1)] ^
Te3[GETBYTE(s3, 0)] ^
rk[4];
t1 =
Te0[GETBYTE(s1, 3)] ^
Te1[GETBYTE(s2, 2)] ^
Te2[GETBYTE(s3, 1)] ^
Te3[GETBYTE(s0, 0)] ^
rk[5];
t2 =
Te0[GETBYTE(s2, 3)] ^
Te1[GETBYTE(s3, 2)] ^
Te2[GETBYTE(s0, 1)] ^
Te3[GETBYTE(s1, 0)] ^
rk[6];
t3 =
Te0[GETBYTE(s3, 3)] ^
Te1[GETBYTE(s0, 2)] ^
Te2[GETBYTE(s1, 1)] ^
Te3[GETBYTE(s2, 0)] ^
rk[7];
rk += 8;
if (--r == 0) {
break;
}
s0 =
Te0[GETBYTE(t0, 3)] ^
Te1[GETBYTE(t1, 2)] ^
Te2[GETBYTE(t2, 1)] ^
Te3[GETBYTE(t3, 0)] ^
rk[0];
s1 =
Te0[GETBYTE(t1, 3)] ^
Te1[GETBYTE(t2, 2)] ^
Te2[GETBYTE(t3, 1)] ^
Te3[GETBYTE(t0, 0)] ^
rk[1];
s2 =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -