diff -r 675a964f4eb5 -r 35751d3474b7 crypto/weakcryptospi/test/tplugins/src/rijndaelimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crypto/weakcryptospi/test/tplugins/src/rijndaelimpl.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,490 @@ +/* +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "rijndaelimpl.h" +#include "keys.h" + +#include "rijndaeltables.h" +#include "../../../source/common/inlines.h" +#include "pluginconfig.h" +#include "symmetriccipherimpl.h" +#include + +using namespace SoftwareCrypto; + +const TUint KAESKeyBytes128 = 16; +const TUint KAESKeyBytes192 = 24; +const TUint KAESKeyBytes256 = 32; +const TUint KAESBlockBytes = 16; + +/* CRijndaelmpl*/ +CRijndaelImpl::CRijndaelImpl( + TUid aCryptoMode, + TUid aOperationMode, + TUid aPadding, + TUid aImplementationUid) : + CSymmetricBlockCipherImpl(KAESBlockBytes, aCryptoMode, aOperationMode, aPadding), + iImplementationUid(aImplementationUid) + { + } + +CRijndaelImpl* CRijndaelImpl::NewL(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, + TUid aPadding, TUid aImplementationUid) + { + CRijndaelImpl* self = CRijndaelImpl::NewLC(aKey, aCryptoMode, aOperationMode, + aPadding, aImplementationUid); + CleanupStack::Pop(self); + return self; + } + +CRijndaelImpl* CRijndaelImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, + TUid aPadding, TUid aImplementationUid) + { + CRijndaelImpl* self = new(ELeave) CRijndaelImpl(aCryptoMode, aOperationMode, aPadding, + aImplementationUid); + CleanupStack::PushL(self); + self->ConstructL(aKey); + + const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid); + TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyContent.Size()) - keyContent.Size()); + return self; + } + +CRijndaelImpl::~CRijndaelImpl() + { + // make sure key information isn't visible to other processes if the + // page is reused. + Mem::FillZ(&iK, sizeof(iK)); + } + +void CRijndaelImpl::ConstructL(const CKey& aKey) + { + CSymmetricBlockCipherImpl::ConstructL(aKey); + SetKeySchedule(); + } + +CExtendedCharacteristics* CRijndaelImpl::CreateExtendedCharacteristicsL() + { + // All Symbian software plug-ins have unlimited concurrency, cannot be reserved + // for exclusive use and are not CERTIFIED to be standards compliant. + return CExtendedCharacteristics::NewL(KMaxTInt, EFalse); + } + +const CExtendedCharacteristics* CRijndaelImpl::GetExtendedCharacteristicsL() + { + return CRijndaelImpl::CreateExtendedCharacteristicsL(); + } + +TUid CRijndaelImpl::ImplementationUid() const + { + return iImplementationUid; + } + +TBool CRijndaelImpl::IsValidKeyLength(TInt aKeyBytes) const + { + switch(aKeyBytes) + { + case KAESKeyBytes128: + case KAESKeyBytes192: + case KAESKeyBytes256: + return ETrue; + default: + return EFalse; + } + } + +void CRijndaelImpl::SetKeySchedule() + { + iRounds = iKeyBytes/4 + 6; + if (iCryptoMode.iUid == KCryptoModeEncrypt) + { + SetEncryptKeySchedule(*iKey, &iK[0]); + } + else + { + ASSERT(iCryptoMode.iUid == KCryptoModeDecrypt); + SetDecryptKeySchedule(*iKey, &iK[0]); + } + } + +void CRijndaelImpl::TransformEncrypt( + TUint8* aBuffer, + TUint aNumBlocks) + { + for (TInt i = 0; i < aNumBlocks; ++i) + { + ModeEncryptStart(aBuffer); + + TUint32 s0, s1, s2, s3, t0, t1, t2, t3; + const TUint32* rk = &iK[0]; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + GetBlockBigEndian(aBuffer, s0, s1, s2, s3); + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + /* + * Nr - 1 full rounds: + */ + TUint r = iRounds >> 1; + FOREVER + { + t0 = + RIJNDAEL_TABLE::Te0[GETBYTE(s0, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(s1, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(s2, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(s3, 0)] ^ + rk[4]; + t1 = + RIJNDAEL_TABLE::Te0[GETBYTE(s1, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(s2, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(s3, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(s0, 0)] ^ + rk[5]; + t2 = + RIJNDAEL_TABLE::Te0[GETBYTE(s2, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(s3, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(s0, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(s1, 0)] ^ + rk[6]; + t3 = + RIJNDAEL_TABLE::Te0[GETBYTE(s3, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(s0, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(s1, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(s2, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) + break; + + s0 = + RIJNDAEL_TABLE::Te0[GETBYTE(t0, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(t1, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(t2, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(t3, 0)] ^ + rk[0]; + s1 = + RIJNDAEL_TABLE::Te0[GETBYTE(t1, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(t2, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(t3, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(t0, 0)] ^ + rk[1]; + s2 = + RIJNDAEL_TABLE::Te0[GETBYTE(t2, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(t3, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(t0, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(t1, 0)] ^ + rk[2]; + s3 = + RIJNDAEL_TABLE::Te0[GETBYTE(t3, 3)] ^ + RIJNDAEL_TABLE::Te1[GETBYTE(t0, 2)] ^ + RIJNDAEL_TABLE::Te2[GETBYTE(t1, 1)] ^ + RIJNDAEL_TABLE::Te3[GETBYTE(t2, 0)] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + + s0 = + (RIJNDAEL_TABLE::Te4[GETBYTE(t0, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (RIJNDAEL_TABLE::Te4[GETBYTE(t1, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t0, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (RIJNDAEL_TABLE::Te4[GETBYTE(t2, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (RIJNDAEL_TABLE::Te4[GETBYTE(t3, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(t2, 0)] & 0x000000ff) ^ + rk[3]; + + PutBlockBigEndian(aBuffer, s0, s1, s2, s3); + ModeEncryptEnd(aBuffer); + aBuffer += KAESBlockBytes; + } + } + +void CRijndaelImpl::TransformDecrypt( + TUint8* aBuffer, + TUint aNumBlocks) + { + for (TInt i = 0; i < aNumBlocks; ++i) + { + ModeDecryptStart(aBuffer); + + TUint32 s0, s1, s2, s3, t0, t1, t2, t3; + const TUint32* rk = &iK[0]; + + /* + * map byte array block to cipher state + * and add initial round key: + */ + GetBlockBigEndian(aBuffer, s0, s1, s2, s3); + + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + /* + * Nr - 1 full rounds: + */ + TUint r = iRounds >> 1; + FOREVER + { + t0 = + RIJNDAEL_TABLE::Td0[GETBYTE(s0, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(s3, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(s2, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(s1, 0)] ^ + rk[4]; + t1 = + RIJNDAEL_TABLE::Td0[GETBYTE(s1, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(s0, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(s3, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(s2, 0)] ^ + rk[5]; + t2 = + RIJNDAEL_TABLE::Td0[GETBYTE(s2, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(s1, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(s0, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(s3, 0)] ^ + rk[6]; + t3 = + RIJNDAEL_TABLE::Td0[GETBYTE(s3, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(s2, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(s1, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(s0, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) + break; + + s0 = + RIJNDAEL_TABLE::Td0[GETBYTE(t0, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(t3, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(t2, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(t1, 0)] ^ + rk[0]; + s1 = + RIJNDAEL_TABLE::Td0[GETBYTE(t1, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(t0, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(t3, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(t2, 0)] ^ + rk[1]; + s2 = + RIJNDAEL_TABLE::Td0[GETBYTE(t2, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(t1, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(t0, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(t3, 0)] ^ + rk[2]; + s3 = + RIJNDAEL_TABLE::Td0[GETBYTE(t3, 3)] ^ + RIJNDAEL_TABLE::Td1[GETBYTE(t2, 2)] ^ + RIJNDAEL_TABLE::Td2[GETBYTE(t1, 1)] ^ + RIJNDAEL_TABLE::Td3[GETBYTE(t0, 0)] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (RIJNDAEL_TABLE::Td4[GETBYTE(t0, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (RIJNDAEL_TABLE::Td4[GETBYTE(t1, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t2, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (RIJNDAEL_TABLE::Td4[GETBYTE(t2, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (RIJNDAEL_TABLE::Td4[GETBYTE(t3, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Td4[GETBYTE(t0, 0)] & 0x000000ff) ^ + rk[3]; + PutBlockBigEndian(aBuffer, s0, s1, s2, s3); + ModeDecryptEnd(aBuffer); + aBuffer += KAESBlockBytes; + } + } + +void CRijndaelImpl::SetEncryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule) + { + TUint keySize = aKey.Length(); + TUint32 temp; + TUint32* rk = aKeySchedule; + + TUint i = 0; + + GetUserKeyBigEndian(rk, keySize/4, &aKey[0], keySize); + + switch(keySize) + { + case (KAESKeyBytes128): + { + FOREVER + { + temp = rk[3]; + rk[4] = rk[0] ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^ + RIJNDAEL_TABLE::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 (KAESKeyBytes192): + { + FOREVER + { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^ + RIJNDAEL_TABLE::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 (KAESKeyBytes256): + { + FOREVER + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^ + RIJNDAEL_TABLE::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] ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0xff000000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^ + (RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^ + (RIJNDAEL_TABLE::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; + + default: + assert(0); // Shouldn't get here, keeps compiler happy + } + } + +void CRijndaelImpl::SetDecryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule) + { + SetEncryptKeySchedule(aKey, aKeySchedule); + + TUint i, j; + TUint32* rk = aKeySchedule; + TUint32 temp; + + // invert the order of the round keys + for (i = 0, j = 4*iRounds; 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 < iRounds; i++) + { + rk += 4; + rk[0] = + RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 3)] & 0xff] ^ + RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 2)] & 0xff] ^ + RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 1)] & 0xff] ^ + RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 0)] & 0xff]; + rk[1] = + RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 3)] & 0xff] ^ + RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 2)] & 0xff] ^ + RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 1)] & 0xff] ^ + RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 0)] & 0xff]; + rk[2] = + RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 3)] & 0xff] ^ + RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 2)] & 0xff] ^ + RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 1)] & 0xff] ^ + RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 0)] & 0xff]; + rk[3] = + RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 3)] & 0xff] ^ + RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 2)] & 0xff] ^ + RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 1)] & 0xff] ^ + RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 0)] & 0xff]; + } + }