os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/rijndaelimpl.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include "rijndaelimpl.h"
    20 #include "keys.h"
    21 
    22 #include "rijndaeltables.h"
    23 #include "common/inlines.h"
    24 #include "pluginconfig.h"
    25 #include "symmetriccipherimpl.h"
    26 #include <cryptostrength.h>
    27 
    28 using namespace SoftwareCrypto;
    29 
    30 const TUint KAESKeyBytes128 = 16;
    31 const TUint KAESKeyBytes192 = 24;
    32 const TUint KAESKeyBytes256 = 32;
    33 const TUint KAESBlockBytes = 16;
    34 
    35 /* CRijndaelmpl*/
    36 CRijndaelImpl::CRijndaelImpl(
    37 	TUid aCryptoMode,
    38 	TUid aOperationMode,
    39 	TUid aPadding) :
    40 	CSymmetricBlockCipherImpl(KAESBlockBytes, aCryptoMode, aOperationMode, aPadding)
    41 	{
    42 	}
    43 
    44 CRijndaelImpl* CRijndaelImpl::NewL(const CKey& aKey, TUid aCryptoMode,	TUid aOperationMode, TUid aPadding)
    45 	{
    46 	CRijndaelImpl* self = CRijndaelImpl::NewLC(aKey, aCryptoMode, aOperationMode, aPadding);
    47 	CleanupStack::Pop(self);
    48 	return self;
    49 	}
    50 	
    51 CRijndaelImpl* CRijndaelImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
    52 	{
    53 	CRijndaelImpl* self = new(ELeave) CRijndaelImpl(aCryptoMode, aOperationMode, aPadding);
    54 	CleanupStack::PushL(self);
    55 	self->ConstructL(aKey);
    56 	
    57 	const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid);
    58 	TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyContent.Size()) - keyContent.Size());
    59 	return self;
    60 	}
    61 		
    62 CRijndaelImpl::~CRijndaelImpl()
    63 	{
    64 	// make sure key information isn't visible to other processes if the
    65 	// page is reused.
    66 	Mem::FillZ(&iK, sizeof(iK));
    67 	}
    68 	
    69 void CRijndaelImpl::ConstructL(const CKey& aKey)
    70 	{
    71 	CSymmetricBlockCipherImpl::ConstructL(aKey);			
    72 	SetKeySchedule();
    73 	}
    74 
    75 CExtendedCharacteristics* CRijndaelImpl::CreateExtendedCharacteristicsL()
    76 	{
    77 	// All Symbian software plug-ins have unlimited concurrency, cannot be reserved
    78 	// for exclusive use and are not CERTIFIED to be standards compliant.
    79 	return CExtendedCharacteristics::NewL(KMaxTInt, EFalse);
    80 	}
    81 
    82 const CExtendedCharacteristics* CRijndaelImpl::GetExtendedCharacteristicsL()
    83 	{
    84 	return CRijndaelImpl::CreateExtendedCharacteristicsL();
    85 	}
    86 
    87 TUid CRijndaelImpl::ImplementationUid() const
    88 	{
    89 	return KCryptoPluginAesUid;
    90 	}
    91 	
    92 TBool CRijndaelImpl::IsValidKeyLength(TInt aKeyBytes) const
    93 	{
    94 	switch(aKeyBytes)
    95 		{
    96 		case KAESKeyBytes128:
    97 		case KAESKeyBytes192:
    98 		case KAESKeyBytes256:
    99 			return ETrue;
   100 		default:
   101 			return EFalse;
   102 		}			
   103 	}
   104 	
   105 void CRijndaelImpl::SetKeySchedule()
   106 	{
   107 	iRounds = iKeyBytes/4 + 6;
   108 	if (iCryptoMode.iUid == KCryptoModeEncrypt)
   109 		{
   110 		SetEncryptKeySchedule(*iKey, &iK[0]);
   111 		}
   112 	else 
   113 		{
   114 		ASSERT(iCryptoMode.iUid == KCryptoModeDecrypt);
   115 		SetDecryptKeySchedule(*iKey, &iK[0]);
   116 		}	
   117 	}	
   118 
   119 void CRijndaelImpl::TransformEncrypt(
   120 	TUint8* aBuffer, 
   121 	TUint aNumBlocks)
   122 	{
   123 	for (TInt i = 0; i < aNumBlocks; ++i)
   124 		{		
   125 		ModeEncryptStart(aBuffer);
   126 			
   127 		TUint32 s0, s1, s2, s3, t0, t1, t2, t3;
   128 		const TUint32* rk = &iK[0];
   129 
   130 	/*
   131 	 *	map byte array block to cipher state
   132 	 *	and add initial round key:
   133 	*/
   134 		GetBlockBigEndian(aBuffer, s0, s1, s2, s3);
   135 		s0 ^= rk[0];
   136 		s1 ^= rk[1];
   137 		s2 ^= rk[2];
   138 		s3 ^= rk[3];
   139 	/*
   140 	 *	Nr - 1 full rounds:
   141 	*/
   142 	    TUint r = iRounds >> 1;
   143 		FOREVER
   144 			{
   145 	        t0 =
   146 	            RIJNDAEL_TABLE::Te0[GETBYTE(s0, 3)] ^
   147 	            RIJNDAEL_TABLE::Te1[GETBYTE(s1, 2)] ^
   148 	            RIJNDAEL_TABLE::Te2[GETBYTE(s2, 1)] ^
   149 	            RIJNDAEL_TABLE::Te3[GETBYTE(s3, 0)] ^
   150 	            rk[4];
   151 	        t1 =
   152 	            RIJNDAEL_TABLE::Te0[GETBYTE(s1, 3)] ^
   153 	            RIJNDAEL_TABLE::Te1[GETBYTE(s2, 2)] ^
   154 	            RIJNDAEL_TABLE::Te2[GETBYTE(s3, 1)] ^
   155 	            RIJNDAEL_TABLE::Te3[GETBYTE(s0, 0)] ^
   156 	            rk[5];
   157 	        t2 =
   158 	            RIJNDAEL_TABLE::Te0[GETBYTE(s2, 3)] ^
   159 	            RIJNDAEL_TABLE::Te1[GETBYTE(s3, 2)] ^
   160 	            RIJNDAEL_TABLE::Te2[GETBYTE(s0, 1)] ^
   161 	            RIJNDAEL_TABLE::Te3[GETBYTE(s1, 0)] ^
   162 	            rk[6];
   163 	        t3 =
   164 	            RIJNDAEL_TABLE::Te0[GETBYTE(s3, 3)] ^
   165 	            RIJNDAEL_TABLE::Te1[GETBYTE(s0, 2)] ^
   166 	            RIJNDAEL_TABLE::Te2[GETBYTE(s1, 1)] ^
   167 	            RIJNDAEL_TABLE::Te3[GETBYTE(s2, 0)] ^
   168 	            rk[7];
   169 
   170 	        rk += 8;
   171 	        if (--r == 0) 
   172 				break;
   173 	        
   174 	        s0 =
   175 	            RIJNDAEL_TABLE::Te0[GETBYTE(t0, 3)] ^
   176 	            RIJNDAEL_TABLE::Te1[GETBYTE(t1, 2)] ^
   177 	            RIJNDAEL_TABLE::Te2[GETBYTE(t2, 1)] ^
   178 	            RIJNDAEL_TABLE::Te3[GETBYTE(t3, 0)] ^
   179 	            rk[0];
   180 	        s1 =
   181 	            RIJNDAEL_TABLE::Te0[GETBYTE(t1, 3)] ^
   182 	            RIJNDAEL_TABLE::Te1[GETBYTE(t2, 2)] ^
   183 	            RIJNDAEL_TABLE::Te2[GETBYTE(t3, 1)] ^
   184 	            RIJNDAEL_TABLE::Te3[GETBYTE(t0, 0)] ^
   185 	            rk[1];
   186 	        s2 =
   187 	            RIJNDAEL_TABLE::Te0[GETBYTE(t2, 3)] ^
   188 	            RIJNDAEL_TABLE::Te1[GETBYTE(t3, 2)] ^
   189 	            RIJNDAEL_TABLE::Te2[GETBYTE(t0, 1)] ^
   190 	            RIJNDAEL_TABLE::Te3[GETBYTE(t1, 0)] ^
   191 	            rk[2];
   192 	        s3 =
   193 	            RIJNDAEL_TABLE::Te0[GETBYTE(t3, 3)] ^
   194 	            RIJNDAEL_TABLE::Te1[GETBYTE(t0, 2)] ^
   195 	            RIJNDAEL_TABLE::Te2[GETBYTE(t1, 1)] ^
   196 	            RIJNDAEL_TABLE::Te3[GETBYTE(t2, 0)] ^
   197 	            rk[3];
   198 			}
   199 	/*
   200 	 *	apply last round and
   201 	 *	map cipher state to byte array block:
   202 	*/
   203 
   204 		s0 =
   205 			(RIJNDAEL_TABLE::Te4[GETBYTE(t0, 3)] & 0xff000000) ^
   206 			(RIJNDAEL_TABLE::Te4[GETBYTE(t1, 2)] & 0x00ff0000) ^
   207 			(RIJNDAEL_TABLE::Te4[GETBYTE(t2, 1)] & 0x0000ff00) ^
   208 			(RIJNDAEL_TABLE::Te4[GETBYTE(t3, 0)] & 0x000000ff) ^
   209 			rk[0];
   210 		s1 =
   211 			(RIJNDAEL_TABLE::Te4[GETBYTE(t1, 3)] & 0xff000000) ^
   212 			(RIJNDAEL_TABLE::Te4[GETBYTE(t2, 2)] & 0x00ff0000) ^
   213 			(RIJNDAEL_TABLE::Te4[GETBYTE(t3, 1)] & 0x0000ff00) ^
   214 			(RIJNDAEL_TABLE::Te4[GETBYTE(t0, 0)] & 0x000000ff) ^
   215 			rk[1];
   216 		s2 =
   217 			(RIJNDAEL_TABLE::Te4[GETBYTE(t2, 3)] & 0xff000000) ^
   218 			(RIJNDAEL_TABLE::Te4[GETBYTE(t3, 2)] & 0x00ff0000) ^
   219 			(RIJNDAEL_TABLE::Te4[GETBYTE(t0, 1)] & 0x0000ff00) ^
   220 			(RIJNDAEL_TABLE::Te4[GETBYTE(t1, 0)] & 0x000000ff) ^
   221 			rk[2];
   222 		s3 =
   223 			(RIJNDAEL_TABLE::Te4[GETBYTE(t3, 3)] & 0xff000000) ^
   224 			(RIJNDAEL_TABLE::Te4[GETBYTE(t0, 2)] & 0x00ff0000) ^
   225 			(RIJNDAEL_TABLE::Te4[GETBYTE(t1, 1)] & 0x0000ff00) ^
   226 			(RIJNDAEL_TABLE::Te4[GETBYTE(t2, 0)] & 0x000000ff) ^
   227 			rk[3];
   228 
   229 		PutBlockBigEndian(aBuffer, s0, s1, s2, s3);
   230 		ModeEncryptEnd(aBuffer);
   231 		aBuffer += KAESBlockBytes;
   232 		}
   233 	}
   234 
   235 void CRijndaelImpl::TransformDecrypt(
   236 	TUint8* aBuffer,
   237 	TUint aNumBlocks)
   238 	{
   239 	for (TInt i = 0; i < aNumBlocks; ++i)
   240 		{		
   241 		ModeDecryptStart(aBuffer);
   242 		
   243 		TUint32 s0, s1, s2, s3, t0, t1, t2, t3;
   244 	    const TUint32* rk = &iK[0];
   245 
   246 	/*
   247 	 *	map byte array block to cipher state
   248 	 *	and add initial round key:
   249 	*/
   250 		GetBlockBigEndian(aBuffer, s0, s1, s2, s3);
   251 
   252 		s0 ^= rk[0];
   253 		s1 ^= rk[1];
   254 		s2 ^= rk[2];
   255 		s3 ^= rk[3];
   256 	/*
   257 	 *	Nr - 1 full rounds:
   258 	*/
   259 	    TUint r = iRounds >> 1;
   260 	    FOREVER
   261 			{
   262 	        t0 =
   263 	            RIJNDAEL_TABLE::Td0[GETBYTE(s0, 3)] ^
   264 	            RIJNDAEL_TABLE::Td1[GETBYTE(s3, 2)] ^
   265 	            RIJNDAEL_TABLE::Td2[GETBYTE(s2, 1)] ^
   266 	            RIJNDAEL_TABLE::Td3[GETBYTE(s1, 0)] ^
   267 	            rk[4];
   268 	        t1 =
   269 	            RIJNDAEL_TABLE::Td0[GETBYTE(s1, 3)] ^
   270 	            RIJNDAEL_TABLE::Td1[GETBYTE(s0, 2)] ^
   271 	            RIJNDAEL_TABLE::Td2[GETBYTE(s3, 1)] ^
   272 	            RIJNDAEL_TABLE::Td3[GETBYTE(s2, 0)] ^
   273 	            rk[5];
   274 	        t2 =
   275 	            RIJNDAEL_TABLE::Td0[GETBYTE(s2, 3)] ^
   276 	            RIJNDAEL_TABLE::Td1[GETBYTE(s1, 2)] ^
   277 	            RIJNDAEL_TABLE::Td2[GETBYTE(s0, 1)] ^
   278 	            RIJNDAEL_TABLE::Td3[GETBYTE(s3, 0)] ^
   279 	            rk[6];
   280 	        t3 =
   281 	            RIJNDAEL_TABLE::Td0[GETBYTE(s3, 3)] ^
   282 	            RIJNDAEL_TABLE::Td1[GETBYTE(s2, 2)] ^
   283 	            RIJNDAEL_TABLE::Td2[GETBYTE(s1, 1)] ^
   284 	            RIJNDAEL_TABLE::Td3[GETBYTE(s0, 0)] ^
   285 	            rk[7];
   286 
   287 	        rk += 8;
   288 	        if (--r == 0)
   289 	            break;
   290 	        
   291 	        s0 =
   292 	            RIJNDAEL_TABLE::Td0[GETBYTE(t0, 3)] ^
   293 	            RIJNDAEL_TABLE::Td1[GETBYTE(t3, 2)] ^
   294 	            RIJNDAEL_TABLE::Td2[GETBYTE(t2, 1)] ^
   295 	            RIJNDAEL_TABLE::Td3[GETBYTE(t1, 0)] ^
   296 	            rk[0];
   297 	        s1 =
   298 	            RIJNDAEL_TABLE::Td0[GETBYTE(t1, 3)] ^
   299 	            RIJNDAEL_TABLE::Td1[GETBYTE(t0, 2)] ^
   300 	            RIJNDAEL_TABLE::Td2[GETBYTE(t3, 1)] ^
   301 	            RIJNDAEL_TABLE::Td3[GETBYTE(t2, 0)] ^
   302 	            rk[1];
   303 	        s2 =
   304 	            RIJNDAEL_TABLE::Td0[GETBYTE(t2, 3)] ^
   305 	            RIJNDAEL_TABLE::Td1[GETBYTE(t1, 2)] ^
   306 	            RIJNDAEL_TABLE::Td2[GETBYTE(t0, 1)] ^
   307 	            RIJNDAEL_TABLE::Td3[GETBYTE(t3, 0)] ^
   308 	            rk[2];
   309 	        s3 =
   310 	            RIJNDAEL_TABLE::Td0[GETBYTE(t3, 3)] ^
   311 	            RIJNDAEL_TABLE::Td1[GETBYTE(t2, 2)] ^
   312 	            RIJNDAEL_TABLE::Td2[GETBYTE(t1, 1)] ^
   313 	            RIJNDAEL_TABLE::Td3[GETBYTE(t0, 0)] ^
   314 	            rk[3];
   315 			}
   316 	/*
   317 	 *	apply last round and
   318 	 *	map cipher state to byte array block:
   319 	*/
   320 	   	s0 =
   321 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t0, 3)] & 0xff000000) ^
   322 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t3, 2)] & 0x00ff0000) ^
   323 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t2, 1)] & 0x0000ff00) ^
   324 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t1, 0)] & 0x000000ff) ^
   325 	   		rk[0];
   326 	   	s1 =
   327 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t1, 3)] & 0xff000000) ^
   328 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t0, 2)] & 0x00ff0000) ^
   329 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t3, 1)] & 0x0000ff00) ^
   330 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t2, 0)] & 0x000000ff) ^
   331 	   		rk[1];
   332 	   	s2 =
   333 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t2, 3)] & 0xff000000) ^
   334 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t1, 2)] & 0x00ff0000) ^
   335 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t0, 1)] & 0x0000ff00) ^
   336 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t3, 0)] & 0x000000ff) ^
   337 	   		rk[2];
   338 	   	s3 =
   339 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t3, 3)] & 0xff000000) ^
   340 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t2, 2)] & 0x00ff0000) ^
   341 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t1, 1)] & 0x0000ff00) ^
   342 	   		(RIJNDAEL_TABLE::Td4[GETBYTE(t0, 0)] & 0x000000ff) ^
   343 	   		rk[3];		
   344 		PutBlockBigEndian(aBuffer, s0, s1, s2, s3);
   345 		ModeDecryptEnd(aBuffer);
   346 		aBuffer += KAESBlockBytes;
   347 		}
   348 	}
   349 
   350 void CRijndaelImpl::SetEncryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
   351 	{		
   352 	TUint keySize = aKey.Length();
   353 	TUint32 temp; 
   354 	TUint32* rk = aKeySchedule;
   355 
   356 	TUint i = 0;
   357 
   358 	GetUserKeyBigEndian(rk, keySize/4, &aKey[0], keySize);
   359 
   360 	switch(keySize)
   361 		{
   362 		case (KAESKeyBytes128):
   363 			{
   364 			FOREVER
   365 				{
   366 				temp  = rk[3];
   367 				rk[4] = rk[0] ^
   368 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^
   369 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
   370 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
   371 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
   372 					RIJNDAEL_TABLE::rcon[i];
   373 				rk[5] = rk[1] ^ rk[4];
   374 				rk[6] = rk[2] ^ rk[5];
   375 				rk[7] = rk[3] ^ rk[6];
   376 				if (++i == 10)
   377 					break;
   378 				rk += 4;
   379 				}
   380 			}
   381 		break;
   382 
   383 		case (KAESKeyBytes192):
   384 			{
   385 			FOREVER
   386 				{
   387 				temp = rk[ 5];
   388 				rk[ 6] = rk[ 0] ^
   389 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^
   390 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
   391 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
   392 					(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
   393 					RIJNDAEL_TABLE::rcon[i];
   394 				rk[ 7] = rk[ 1] ^ rk[ 6];
   395 				rk[ 8] = rk[ 2] ^ rk[ 7];
   396 				rk[ 9] = rk[ 3] ^ rk[ 8];
   397 				if (++i == 8)
   398 					break;
   399 				rk[10] = rk[ 4] ^ rk[ 9];
   400 				rk[11] = rk[ 5] ^ rk[10];
   401 				rk += 6;
   402 				}
   403 			}
   404 		break;
   405 
   406 		case (KAESKeyBytes256):
   407 			{
   408 			FOREVER
   409 				{
   410         		temp = rk[ 7];
   411         		rk[ 8] = rk[ 0] ^
   412         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0xff000000) ^
   413         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x00ff0000) ^
   414         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x0000ff00) ^
   415         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0x000000ff) ^
   416         			RIJNDAEL_TABLE::rcon[i];
   417         		rk[ 9] = rk[ 1] ^ rk[ 8];
   418         		rk[10] = rk[ 2] ^ rk[ 9];
   419         		rk[11] = rk[ 3] ^ rk[10];
   420 				if (++i == 7)
   421 					break;
   422         		temp = rk[11];
   423         		rk[12] = rk[ 4] ^
   424         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 3)] & 0xff000000) ^
   425         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 2)] & 0x00ff0000) ^
   426         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 1)] & 0x0000ff00) ^
   427         			(RIJNDAEL_TABLE::Te4[GETBYTE(temp, 0)] & 0x000000ff);
   428         		rk[13] = rk[ 5] ^ rk[12];
   429         		rk[14] = rk[ 6] ^ rk[13];
   430         		rk[15] = rk[ 7] ^ rk[14];
   431 
   432 				rk += 8;
   433 				}
   434 			}
   435 		break;
   436 
   437 		default:
   438 			assert(0);	//	Shouldn't get here, keeps compiler happy
   439 		}
   440 	}
   441 
   442 void CRijndaelImpl::SetDecryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
   443 	{
   444 	SetEncryptKeySchedule(aKey, aKeySchedule);
   445 
   446 	TUint i, j;
   447 	TUint32* rk = aKeySchedule;
   448 	TUint32 temp;
   449 
   450 	// invert the order of the round keys 
   451 	for (i = 0, j = 4*iRounds; i < j; i += 4, j -= 4)
   452 		{
   453 		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
   454 		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
   455 		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
   456 		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
   457 		}
   458 
   459 	// apply the inverse MixColumn transform to all round keys but the first and the last
   460 	for (i = 1; i < iRounds; i++)
   461 		{
   462 		rk += 4;
   463 		rk[0] =
   464 			RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 3)] & 0xff] ^
   465 			RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 2)] & 0xff] ^
   466 			RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 1)] & 0xff] ^
   467 			RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[0], 0)] & 0xff];
   468 		rk[1] =
   469 			RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 3)] & 0xff] ^
   470 			RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 2)] & 0xff] ^
   471 			RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 1)] & 0xff] ^
   472 			RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[1], 0)] & 0xff];
   473 		rk[2] =
   474 			RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 3)] & 0xff] ^
   475 			RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 2)] & 0xff] ^
   476 			RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 1)] & 0xff] ^
   477 			RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[2], 0)] & 0xff];
   478 		rk[3] =
   479 			RIJNDAEL_TABLE::Td0[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 3)] & 0xff] ^
   480 			RIJNDAEL_TABLE::Td1[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 2)] & 0xff] ^
   481 			RIJNDAEL_TABLE::Td2[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 1)] & 0xff] ^
   482 			RIJNDAEL_TABLE::Td3[RIJNDAEL_TABLE::Te4[GETBYTE(rk[3], 0)] & 0xff];
   483 		}
   484 	}