cryptoplugins/cryptospiplugins/source/softwarecrypto/desimpl.cpp
changeset 19 cd501b96611d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cryptoplugins/cryptospiplugins/source/softwarecrypto/desimpl.cpp	Fri Nov 06 13:21:00 2009 +0200
@@ -0,0 +1,249 @@
+/*
+* 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 "desimpl.h"
+
+#include "destables.h"
+#include "common/inlines.h"
+#include "des.inl"
+#include "pluginconfig.h"
+#include "symmetriccipherimpl.h"
+#include <cryptostrength.h>
+
+
+//	bit 0 is left-most in byte
+static const TInt bytebit[] = {0200,0100,040,020,010,04,02,01};
+
+using namespace SoftwareCrypto;
+
+/* CDesImpl */
+CDesImpl::CDesImpl(
+	TUint8 aBlockBytes,
+	TUid aCryptoMode,
+	TUid aOperationMode,
+	TUid aPadding) :
+	CSymmetricBlockCipherImpl(aBlockBytes, aCryptoMode, aOperationMode, aPadding)
+	{
+	}
+
+CDesImpl* CDesImpl::NewL(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
+	{
+	CDesImpl* self = CDesImpl::NewLC(aKey, aCryptoMode, aOperationMode, aPadding);
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+CDesImpl* CDesImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding)
+	{
+	CDesImpl* self = new(ELeave) CDesImpl(KDesBlockBytes, aCryptoMode, aOperationMode, aPadding);
+	CleanupStack::PushL(self);
+	self->ConstructL(aKey);
+	
+	const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid);
+	TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyContent.Size()) - keyContent.Size());
+	return self;
+	}
+		
+CDesImpl::~CDesImpl()
+	{
+	// make sure key information isn't visible to other processes if the
+	// page is reused.
+	Mem::FillZ(&iK, sizeof(iK));
+	}
+	
+void CDesImpl::ConstructL(const CKey& aKey)
+	{
+	CSymmetricBlockCipherImpl::ConstructL(aKey);
+	SetKeySchedule();
+	}		
+	
+CExtendedCharacteristics* CDesImpl::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* CDesImpl::GetExtendedCharacteristicsL()
+	{
+	return CDesImpl::CreateExtendedCharacteristicsL();
+	}
+
+TUid CDesImpl::ImplementationUid() const
+	{
+	return KCryptoPluginDesUid;
+	}
+	
+TBool CDesImpl::IsValidKeyLength(TInt aKeyBytes) const
+	{
+	return (aKeyBytes == KDesKeyBytes);
+	}
+	
+TInt CDesImpl::GetKeyStrength() const
+	{
+	// parity bits are excluded
+	return BytesToBits(KDesKeyBytes - 8);
+	}	
+	
+void CDesImpl::TransformEncrypt(
+	TUint8* aBuffer,
+	TUint aNumBlocks)
+	{
+	for (TInt i = 0; i < aNumBlocks; ++i)
+		{		
+		ModeEncryptStart(aBuffer);
+		TUint32 l, r;
+		// Split the block into 2 word-sized big endian portions
+		GetBlockBigEndian(aBuffer, l, r);
+		IPerm(l,r);
+		DoTransform(l, r, iK);		
+		FPerm(l,r);
+
+		// Put the portions back into the block as little endian
+		PutBlockBigEndian(aBuffer, r, l);
+
+		ModeEncryptEnd(aBuffer);
+		aBuffer += KDesBlockBytes;
+		}
+	}	
+	
+void CDesImpl::TransformDecrypt(
+	TUint8* aBuffer,
+	TUint aNumBlocks)
+	{
+	for (TInt i = 0; i < aNumBlocks; ++i)
+		{		
+		ModeDecryptStart(aBuffer);
+
+		TUint32 l, r;
+		// Split the block into 2 word-sized big endian portions
+		GetBlockBigEndian(aBuffer, l, r);
+
+		IPerm(l,r);
+		DoTransform(l, r, iK);		
+		FPerm(l,r);
+
+		// Put the portions back into the block as little endian
+		PutBlockBigEndian(aBuffer, r, l);
+
+		ModeDecryptEnd(aBuffer);
+		aBuffer += KDesBlockBytes;
+		}
+	}
+
+void CDesImpl::SetKeySchedule()
+	{
+	if (iCryptoMode.iUid == KCryptoModeEncrypt)
+		{
+		SetEncryptKeySchedule(*iKey, iK);
+		}
+	else 
+		{
+		ASSERT(iCryptoMode.iUid == KCryptoModeDecrypt);
+		SetDecryptKeySchedule(*iKey, iK);
+		}	
+	}		
+
+void CDesImpl::DoTransform(TUint32& l, TUint32& r, const TUint32* aKeySchedule)
+	{
+	TInt i = 0;
+	for (; i<8; i++)
+		{
+		TUint32 work = rotrFixed(r, 4U) ^ aKeySchedule[4*i+0];
+		l ^= DES_TABLE::sbox[6][(work) & 0x3f]
+		  ^  DES_TABLE::sbox[4][(work >> 8) & 0x3f]
+		  ^  DES_TABLE::sbox[2][(work >> 16) & 0x3f]
+		  ^  DES_TABLE::sbox[0][(work >> 24) & 0x3f];
+		work = r ^ aKeySchedule[4*i+1];
+		l ^= DES_TABLE::sbox[7][(work) & 0x3f]
+		  ^  DES_TABLE::sbox[5][(work >> 8) & 0x3f]
+		  ^  DES_TABLE::sbox[3][(work >> 16) & 0x3f]
+		  ^  DES_TABLE::sbox[1][(work >> 24) & 0x3f];
+
+		work = rotrFixed(l, 4U) ^ aKeySchedule[4*i+2];
+		r ^= DES_TABLE::sbox[6][(work) & 0x3f]
+		  ^  DES_TABLE::sbox[4][(work >> 8) & 0x3f]
+		  ^  DES_TABLE::sbox[2][(work >> 16) & 0x3f]
+		  ^  DES_TABLE::sbox[0][(work >> 24) & 0x3f];
+		work = l ^ aKeySchedule[4*i+3];
+		r ^= DES_TABLE::sbox[7][(work) & 0x3f]
+		  ^  DES_TABLE::sbox[5][(work >> 8) & 0x3f]
+		  ^  DES_TABLE::sbox[3][(work >> 16) & 0x3f]
+		  ^  DES_TABLE::sbox[1][(work >> 24) & 0x3f];
+		}
+	}	
+
+void CDesImpl::SetEncryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
+	{
+	TInt i=0, j=0, l=0, m=0;
+
+//	Form a byte array from aKey, taking endianess into account (little->big)	
+	TUint8 key[8];								//	For big endian byte array	
+	Mem::Copy(&key, &aKey[0], 8);
+
+	TUint8 buffer[56+56+8];
+	TUint8* const pc1m = &buffer[0];			/* place to modify pc1 into */
+	TUint8* const pcr = pc1m + 56;				/* place to rotate pc1 into */
+	TUint8* const ks = pcr + 56;
+
+	for (j=0; j<56; j++) 
+		{/* convert pc1 to bits of key */
+		l = DES_TABLE::pc1[j]-1;				/* integer bit location  */
+		m = l & 07;								/* find bit              */
+		pc1m[j]=(key[l>>3] &					/* find which key byte l is in */
+			bytebit[m])							/* and which bit of that byte */
+			? (TUint8)1 : (TUint8)0;			/* and store 1-bit result */
+		}
+
+	for (i=0; i<16; i++) 
+		{/* key chunk for each iteration */
+		Mem::FillZ(ks,8);							/* Clear key schedule */
+		for (j=0; j<56; j++)
+		/*	rotate pc1 the right amount */
+			pcr[j] = pc1m[(l=j+DES_TABLE::totrot[i])<(j<28? 28 : 56) ? l: l-28];
+		
+		/* rotate left and right halves independently */
+		
+		for (j=0; j<48; j++)
+			{/* select bits individually */
+			/* check bit that goes to ks[j] */
+			if (pcr[DES_TABLE::pc2[j]-1])
+				{/* mask it in if it's there */
+				l= j % 6;
+				ks[j/6] |= bytebit[l] >> 2;
+				}
+			}
+
+		/* Now convert to odd/even interleaved form for use in F */
+		(*(aKeySchedule+(2*i))) = ((TUint32)ks[0] << 24)
+			| ((TUint32)ks[2] << 16)
+			| ((TUint32)ks[4] << 8)
+			| ((TUint32)ks[6]);
+		
+		(*(aKeySchedule+(2*i+1))) = ((TUint32)ks[1] << 24)
+			| ((TUint32)ks[3] << 16)
+			| ((TUint32)ks[5] << 8)
+			| ((TUint32)ks[7]);
+		}		
+	}
+
+void CDesImpl::SetDecryptKeySchedule(const TDesC8& aKey, TUint32* aKeySchedule)
+	{
+	SetEncryptKeySchedule(aKey, aKeySchedule);
+	ReverseKeySchedule(aKeySchedule);
+	}