sl@0: /*
sl@0: * Copyright (c) 2007-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: /**
sl@0:  @file
sl@0:  @internalTechnology
sl@0: */
sl@0:  
sl@0: #include "symmetriccipherctrmodeoutoforderstep.h"
sl@0: 
sl@0: using namespace CryptoSpi;
sl@0: 
sl@0: CSymmetricCipherCtrModeOutOfOrderStep::CSymmetricCipherCtrModeOutOfOrderStep()
sl@0: 	{
sl@0: 	SetTestStepName(KSymmetricCipherCtrModeOutOfOrderStep);
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TVerdict CSymmetricCipherCtrModeOutOfOrderStep::doTestStepPreambleL()
sl@0: 	{
sl@0: 	SetTestStepResult(EPass);
sl@0: 	return TestStepResult();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TVerdict CSymmetricCipherCtrModeOutOfOrderStep::doTestStepL()
sl@0: 	{
sl@0: 	INFO_PRINTF1(_L("*** Symmetric Cipher - Counter mode out of order operation ***"));
sl@0: 	INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
sl@0:   	
sl@0:   	if (TestStepResult() != EPass)
sl@0:   		{
sl@0:   		return TestStepResult();
sl@0:   		}
sl@0:   	
sl@0:   	//Assume failure, unless all is successful
sl@0: 	SetTestStepResult(EFail);
sl@0: 		
sl@0: 	TVariantPtrC operationMode;
sl@0: 		
sl@0: 	CSymmetricCipher* impl = NULL;
sl@0: 	CKey* key = NULL;
sl@0: 	SetupCipherL(EFalse, EFalse, operationMode, impl, key);
sl@0: 	
sl@0: 	INFO_PRINTF1(_L("Plugin loaded."));
sl@0: 	
sl@0: 	CleanupStack::PushL(key);
sl@0: 	CleanupStack::PushL(impl);
sl@0: 
sl@0:   	
sl@0:   	if (TUid(operationMode) != KOperationModeCTRUid)
sl@0:   		{
sl@0:   		ERR_PRINTF2(_L("*** FAIL: This test supports CTR operation mode only and not mode id: %d ***"), (TUid(operationMode)).iUid);
sl@0:   		CleanupStack::PopAndDestroy(2, key);
sl@0:   		INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
sl@0:   		return TestStepResult();
sl@0:   		}
sl@0: 	
sl@0: 	
sl@0: 	HBufC8* plaintext = ReadInPlaintextL();
sl@0: 	CleanupStack::PushL(plaintext);
sl@0: 
sl@0: 		
sl@0: 	TInt blockSize = CtrModeCalcBlockSizeL(*impl)/8;
sl@0: 
sl@0: 	if (plaintext->Length() < ((blockSize * 2) + 1))
sl@0: 		{
sl@0: 		ERR_PRINTF2(_L("*** FAIL: Plaintext argument is not long enough for this test, length(B) = %d ***"), plaintext->Length());
sl@0: 		CleanupStack::PopAndDestroy(3, key);
sl@0: 		INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
sl@0: 		return TestStepResult();
sl@0: 		}
sl@0: 				
sl@0:   	// This will store our calculated version of the ciphertext to compare with that in the .ini file
sl@0:   	TUint8* calculatedCiphertext = new (ELeave) TUint8[plaintext->Length()];
sl@0:   	CleanupStack::PushL(calculatedCiphertext);
sl@0:   	// Ptr to the first block of the calculated ciphertext
sl@0:   	TPtr8 calcCipherPtr1(calculatedCiphertext, blockSize);
sl@0:   	// Ptr to the remaining blocks of the calculated ciphertext
sl@0:   	TPtr8 calcCipherPtr2((calculatedCiphertext + blockSize), (plaintext->Length() - blockSize));
sl@0:   	
sl@0:   	// Ptr to the first block of the .ini file's plaintext
sl@0:   	TPtrC8 knownPlainPtr1(plaintext->Ptr(), blockSize);
sl@0:   	// Ptr to the remaining blocks of the .ini file's plaintext
sl@0:   	TPtrC8 knownPlainPtr2((plaintext->Ptr() + blockSize), (plaintext->Length() - blockSize));
sl@0:   	
sl@0: 	
sl@0: 	HBufC8* iv = ReadInIvL();
sl@0: 	CleanupStack::PushL(iv);
sl@0: 		
sl@0: 	// Increment IV to the value for the second block so we can encrypt blocks 2+ first
sl@0: 	HBufC8* incrementedIv1 = CtrModeIncrementCounterL((*iv));
sl@0: 	CleanupStack::PushL(incrementedIv1);
sl@0: 	
sl@0: 	impl->SetIvL(*incrementedIv1);
sl@0:   	
sl@0:   	
sl@0: 	INFO_PRINTF1(_L("Setup complete.  Encrypting blocks 2+."));
sl@0: 	impl->ProcessL(knownPlainPtr2, calcCipherPtr2);
sl@0: 	
sl@0: 	INFO_PRINTF1(_L("Blocks 2+ encrypted.  Reseting and encrypting block 1."));
sl@0: 	impl->SetIvL((*iv));
sl@0: 	impl->ProcessL(knownPlainPtr1, calcCipherPtr1);
sl@0: 	
sl@0: 	
sl@0: 	HBufC8* knownCiphertext = ReadInCiphertextL();
sl@0: 	CleanupStack::PushL(knownCiphertext);
sl@0: 	
sl@0: 	// Check that calculated ciphertext matches the expected value
sl@0: 	TPtrC8 wholeCalcCiphertext(calculatedCiphertext, (plaintext->Length()));
sl@0: 	if (wholeCalcCiphertext.Compare((*knownCiphertext)) != 0)
sl@0: 		{
sl@0: 		ERR_PRINTF1(_L("*** FAIL: Calculated ciphertext does not match expected value ***"));
sl@0:   		CleanupStack::PopAndDestroy(7, key);
sl@0:   		INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
sl@0:   		return TestStepResult();
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		INFO_PRINTF1(_L("Calculated ciphertext matches the expected value."));
sl@0: 		}
sl@0: 	
sl@0: 	
sl@0: 	// ****  SWITCH TO DECRYPTION NOW  ****
sl@0: 	
sl@0: 	// This will store our calculated version of the plaintext to compare with that in the .ini file
sl@0:   	TUint8* calculatedPlaintext = new (ELeave) TUint8[plaintext->Length()];
sl@0:   	CleanupStack::PushL(calculatedPlaintext);
sl@0:   	// Ptr to the first block of the calculated plaintext
sl@0:   	TPtr8 calcPlainPtr1(calculatedPlaintext, (blockSize * 2));
sl@0:   	// Ptr to the remaining blocks of the calculated plaintext
sl@0:   	TPtr8 calcPlainPtr2((calculatedPlaintext + (blockSize * 2)), (plaintext->Length() - (blockSize * 2)));
sl@0:   	
sl@0:   	// Ptr to the first 2 blocks of the ciphertext
sl@0:   	TPtrC8 knownCipherPtr1(wholeCalcCiphertext.Ptr(), (blockSize * 2));
sl@0:   	// Ptr to the remaining blocks of the ciphertext
sl@0:   	TPtrC8 knownCipherPtr2((wholeCalcCiphertext.Ptr() + (blockSize * 2)), (wholeCalcCiphertext.Length() - (blockSize * 2)));
sl@0: 	
sl@0: 	
sl@0: 	//	Increment IV to the value for the third block so we can decrypt blocks 3+ first
sl@0: 	HBufC8* incrementedIv2 = CtrModeIncrementCounterL(*incrementedIv1);
sl@0: 	CleanupStack::PushL(incrementedIv2);
sl@0: 	impl->SetIvL(*incrementedIv2);
sl@0: 	
sl@0: 	INFO_PRINTF1(_L("Setup complete.  Decrypting blocks 3+."));
sl@0: 	impl->ProcessL(knownCipherPtr2, calcPlainPtr2);
sl@0: 	
sl@0: 	INFO_PRINTF1(_L("Blocks 3+ encrypted.  Reseting and encrypting blocks 1 and 2."));
sl@0: 	impl->SetIvL((*iv));
sl@0: 	impl->ProcessL(knownCipherPtr1, calcPlainPtr1);	
sl@0: 	
sl@0: 	TPtrC8 wholeCalcPlaintext(calculatedPlaintext, (plaintext->Length()));
sl@0: 	
sl@0: 	if (wholeCalcPlaintext.Compare((*plaintext)) != 0)
sl@0: 		{
sl@0: 		ERR_PRINTF1(_L("*** FAIL: Calculated plaintext does not match expected value ***"));
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		INFO_PRINTF1(_L("*** PASS: Calculated plaintext matches the original one ***"));
sl@0: 		SetTestStepResult(EPass);			
sl@0: 		}
sl@0:   	
sl@0:   	CleanupStack::PopAndDestroy(9, key);
sl@0:   	
sl@0: 	INFO_PRINTF2(_L("HEAP CELLS: %d"), User::CountAllocCells());
sl@0: 
sl@0: 	return TestStepResult();
sl@0: 	}
sl@0: 
sl@0: 
sl@0: TVerdict CSymmetricCipherCtrModeOutOfOrderStep::doTestStepPostambleL()
sl@0: 	{
sl@0: 	return TestStepResult();
sl@0: 	}