--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoplugins/cryptospiplugins/source/softwarecrypto/rijndaelimpl.cpp Fri Nov 06 13:21:00 2009 +0200
@@ -0,0 +1,484 @@
+/*
+* 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 "common/inlines.h"
+#include "pluginconfig.h"
+#include "symmetriccipherimpl.h"
+#include <cryptostrength.h>
+
+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) :
+ CSymmetricBlockCipherImpl(KAESBlockBytes, aCryptoMode, aOperationMode, aPadding)
+ {
+ }
+
+CRijndaelImpl* CRijndaelImpl::NewL(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
+ {
+ CRijndaelImpl* self = CRijndaelImpl::NewLC(aKey, aCryptoMode, aOperationMode, aPadding);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CRijndaelImpl* CRijndaelImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
+ {
+ CRijndaelImpl* self = new(ELeave) CRijndaelImpl(aCryptoMode, aOperationMode, aPadding);
+ 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 KCryptoPluginAesUid;
+ }
+
+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];
+ }
+ }