sl@0: /* sl@0: * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "3desimpl.h" sl@0: sl@0: #include "destables.h" sl@0: #include "common/inlines.h" sl@0: #include "des.inl" sl@0: #include "pluginconfig.h" sl@0: #include "symmetriccipherimpl.h" sl@0: #include sl@0: sl@0: using namespace SoftwareCrypto; sl@0: sl@0: /* C3DesImpl */ sl@0: C3DesImpl::C3DesImpl( sl@0: TUid aCryptoMode, sl@0: TUid aOperationMode, sl@0: TUid aPadding) : sl@0: CDesImpl(KDesBlockBytes, aCryptoMode, aOperationMode, aPadding) sl@0: { sl@0: } sl@0: sl@0: C3DesImpl* C3DesImpl::NewL(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding) sl@0: { sl@0: C3DesImpl* self = C3DesImpl::NewLC(aKey, aCryptoMode, aOperationMode, aPadding); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: C3DesImpl* C3DesImpl::NewLC(const CKey& aKey, TUid aCryptoMode, TUid aOperationMode, TUid aPadding) sl@0: { sl@0: C3DesImpl* self = new(ELeave) C3DesImpl(aCryptoMode, aOperationMode, aPadding); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aKey); sl@0: sl@0: const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid); sl@0: TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyContent.Size()) - keyContent.Size()); sl@0: return self; sl@0: } sl@0: sl@0: C3DesImpl::~C3DesImpl() sl@0: { sl@0: // make sure key information isn't visible to other processes if the sl@0: // page is reused. sl@0: Mem::FillZ(&iK1, sizeof(iK1)); sl@0: Mem::FillZ(&iK2, sizeof(iK2)); sl@0: Mem::FillZ(&iK3, sizeof(iK3)); sl@0: } sl@0: sl@0: void C3DesImpl::ConstructL(const CKey& aKey) sl@0: { sl@0: CDesImpl::ConstructL(aKey); sl@0: SetKeySchedule(); sl@0: } sl@0: sl@0: CExtendedCharacteristics* C3DesImpl::CreateExtendedCharacteristicsL() sl@0: { sl@0: // All Symbian software plug-ins have unlimited concurrency, cannot be reserved sl@0: // for exclusive use and are not CERTIFIED to be standards compliant. sl@0: return CExtendedCharacteristics::NewL(KMaxTInt, EFalse); sl@0: } sl@0: sl@0: const CExtendedCharacteristics* C3DesImpl::GetExtendedCharacteristicsL() sl@0: { sl@0: return C3DesImpl::CreateExtendedCharacteristicsL(); sl@0: } sl@0: sl@0: TUid C3DesImpl::ImplementationUid() const sl@0: { sl@0: return KCryptoPlugin3DesUid; sl@0: } sl@0: sl@0: TBool C3DesImpl::IsValidKeyLength(TInt aKeyBytes) const sl@0: { sl@0: return (aKeyBytes == K3DesKeyBytes); sl@0: } sl@0: sl@0: TInt C3DesImpl::GetKeyStrength() const sl@0: { sl@0: // Exclude parity bits from each subkey sl@0: return BytesToBits(K3DesKeyBytes - (3 * 8)); sl@0: } sl@0: sl@0: void C3DesImpl::TransformEncrypt( sl@0: TUint8* aBuffer, sl@0: TUint aNumBlocks) sl@0: { sl@0: for (TInt i = 0; i < aNumBlocks; ++i) sl@0: { sl@0: ModeEncryptStart(aBuffer); sl@0: sl@0: TUint32 l, r; sl@0: // Split the block into 2 word-sized big endian portions sl@0: GetBlockBigEndian(aBuffer, l, r); sl@0: sl@0: IPerm(l,r); sl@0: // The mode is applied to the entire operation and NOT sl@0: // for each DES transform sl@0: TUid opMode = iOperationMode; sl@0: iOperationMode = KOperationModeECBUid; sl@0: DoTransform(l, r, iK1); sl@0: DoTransform(r, l, iK2); sl@0: DoTransform(l, r, iK3); sl@0: iOperationMode = opMode; sl@0: FPerm(l,r); sl@0: sl@0: // Put the portions back into the block as little endian sl@0: PutBlockBigEndian(aBuffer, r, l); sl@0: ModeEncryptEnd(aBuffer); sl@0: aBuffer += KDesBlockBytes; sl@0: } sl@0: } sl@0: sl@0: void C3DesImpl::TransformDecrypt( sl@0: TUint8* aBuffer, sl@0: const TUint aNumBlocks) sl@0: { sl@0: for (TInt i = 0; i < aNumBlocks; ++i) sl@0: { sl@0: ModeDecryptStart(aBuffer); sl@0: sl@0: TUint32 l, r; sl@0: // Split the block into 2 word-sized big endian portions sl@0: GetBlockBigEndian(aBuffer, l, r); sl@0: sl@0: IPerm(l,r); sl@0: sl@0: // The mode is applied to the entire operation and NOT sl@0: // for each DES transform sl@0: TUid opMode = iOperationMode; sl@0: iOperationMode = KOperationModeECBUid; sl@0: DoTransform(l, r, iK1); sl@0: DoTransform(r, l, iK2); sl@0: DoTransform(l, r, iK3); sl@0: iOperationMode = opMode; sl@0: FPerm(l,r); sl@0: sl@0: // Put the portions back into the block as little endian sl@0: PutBlockBigEndian(aBuffer, r, l); sl@0: ModeDecryptEnd(aBuffer); sl@0: aBuffer += K3DesBlockBytes; sl@0: } sl@0: } sl@0: sl@0: void C3DesImpl::SetKeySchedule() sl@0: { sl@0: if (iCryptoMode.iUid == KCryptoModeEncrypt) sl@0: { sl@0: // Encrypt -> Decrypt -> Encrypt sl@0: // Encryptor key sl@0: SetEncryptKeySchedule(iKey->Mid(0, KDesKeyBytes), iK1); sl@0: sl@0: // Decryptor key sl@0: SetDecryptKeySchedule(iKey->Mid(KDesKeyBytes, 2 * KDesKeyBytes), iK2); sl@0: sl@0: // Encryptor key sl@0: SetEncryptKeySchedule(iKey->Mid(2 * KDesKeyBytes), iK3); sl@0: } sl@0: else sl@0: { sl@0: // Decrypt -> Encrypt -> Decrypt sl@0: // Key order is reversed ! sl@0: sl@0: ASSERT(iCryptoMode.iUid == KCryptoModeDecrypt); sl@0: // Decryptor key sl@0: SetDecryptKeySchedule(iKey->Mid(0, KDesKeyBytes), iK3); sl@0: sl@0: // Encryptor key sl@0: SetEncryptKeySchedule(iKey->Mid(KDesKeyBytes, 2 * KDesKeyBytes), iK2); sl@0: sl@0: // Decryptor key sl@0: SetDecryptKeySchedule(iKey->Mid(2 * KDesKeyBytes), iK1); sl@0: } sl@0: }