os/security/cryptoservices/certificateandkeymgmt/tasn1/testsequence.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.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* Implementation for testing sequence object encoding/decoding
sl@0
    16
*
sl@0
    17
*/
sl@0
    18
sl@0
    19
sl@0
    20
#include "testsequence.h"
sl@0
    21
#include "tasn1normaltest.h"
sl@0
    22
#include <asn1enc.h>
sl@0
    23
#include <asn1dec.h>
sl@0
    24
#include <e32math.h>
sl@0
    25
#include <e32cons.h>
sl@0
    26
sl@0
    27
#include <bigint.h>
sl@0
    28
sl@0
    29
CTestSequence* CTestSequence::NewL(CASN1NormalTest &aASN1Action)
sl@0
    30
	{
sl@0
    31
	CTestSequence* test = new (ELeave) CTestSequence(aASN1Action);
sl@0
    32
	return test;
sl@0
    33
	}
sl@0
    34
sl@0
    35
CTestSequence::CTestSequence(CASN1NormalTest &aASN1Action) : CTestBase(aASN1Action)
sl@0
    36
	{
sl@0
    37
	};
sl@0
    38
sl@0
    39
sl@0
    40
void CTestSequence::GetName(TDes& aBuf)
sl@0
    41
	{
sl@0
    42
	aBuf.Copy(_L("Test Sequence"));
sl@0
    43
	}
sl@0
    44
sl@0
    45
void CTestSequence::FillParameterArray(void)
sl@0
    46
	{
sl@0
    47
	iParameters->Append(CTestParameter::EInt);
sl@0
    48
	iParameters->Append(CTestParameter::EInt);
sl@0
    49
	}
sl@0
    50
sl@0
    51
sl@0
    52
TBool CTestSequence::PerformTest(CConsoleBase& aConsole, const TInt &aTestDepth, const TInt &aTestSize, const TInt &aTestNumber, const TInt &aTotalTests)
sl@0
    53
	{
sl@0
    54
	iObjectsEncoded = 1;
sl@0
    55
	CASN1EncBase* encoder = MakeSequenceEncoderLC(aTestDepth, 0, aTestSize);
sl@0
    56
	
sl@0
    57
	// Prepare a buffer
sl@0
    58
	TInt totalLength = encoder->LengthDER();
sl@0
    59
	HBufC8* buf = HBufC8::NewMaxLC(totalLength);
sl@0
    60
	TPtr8 tBuf = buf->Des();
sl@0
    61
	
sl@0
    62
	// Write into the buffer
sl@0
    63
	TUint writeLength = 0;
sl@0
    64
	encoder->WriteDERL(tBuf, writeLength);
sl@0
    65
sl@0
    66
	// Check number of objects in buffer reads OK and matches what we hoped
sl@0
    67
	TInt objectsRead = ReadAndCountL(tBuf);
sl@0
    68
	if (objectsRead != iObjectsEncoded)
sl@0
    69
		{
sl@0
    70
		aConsole.Write(_L("ERROR! Encoded sequence object count mismatch\n"));
sl@0
    71
		iASN1Action.ReportProgressL(KErrASN1EncodingError, aTestNumber, aTotalTests);
sl@0
    72
		CleanupStack::PopAndDestroy(2); // buf, encoder
sl@0
    73
		return(EFalse);
sl@0
    74
		}
sl@0
    75
	else
sl@0
    76
		{	
sl@0
    77
		iASN1Action.ReportProgressL(KErrNone, aTestNumber, aTotalTests);
sl@0
    78
		CleanupStack::PopAndDestroy(2); // buf, encoder
sl@0
    79
		return(ETrue);
sl@0
    80
		}
sl@0
    81
	}
sl@0
    82
sl@0
    83
sl@0
    84
CASN1EncSequence* CTestSequence::MakeSequenceEncoderLC(TInt aMaxDepth, 
sl@0
    85
													   TInt aMinSize, 
sl@0
    86
													   TInt aMaxSize)
sl@0
    87
	{
sl@0
    88
	__ASSERT_ALWAYS(aMaxDepth > 0, User::Leave(KErrArgument));
sl@0
    89
	__ASSERT_ALWAYS(aMinSize >= 0, User::Leave(KErrArgument));
sl@0
    90
	__ASSERT_ALWAYS(aMinSize <= aMaxSize, User::Leave(KErrArgument));
sl@0
    91
sl@0
    92
	CASN1EncSequence* encoder = CASN1EncSequence::NewLC();
sl@0
    93
sl@0
    94
	TUint targetSize = aMinSize + (Math::Random() % (aMaxSize + 1 - aMinSize));
sl@0
    95
	TUint size = 0;
sl@0
    96
	while (size < targetSize)
sl@0
    97
		{
sl@0
    98
		const TInt KMaxChildType = 3;
sl@0
    99
		const TInt childTypes = aMaxDepth > 1 ? KMaxChildType + 1 : KMaxChildType;
sl@0
   100
		const TInt childType = (Math::Random() >> 5) % childTypes;
sl@0
   101
		CASN1EncBase* child = 0;
sl@0
   102
		CASN1EncSequence* seqEnc = 0;
sl@0
   103
		switch (childType)
sl@0
   104
			{
sl@0
   105
			case 0:
sl@0
   106
				child = CASN1EncInt::NewLC(Math::Random());
sl@0
   107
				break;
sl@0
   108
			case 1:
sl@0
   109
				{
sl@0
   110
				RInteger i = RInteger::NewRandomL(1234, TInteger::EAllBitsRandom);
sl@0
   111
				CleanupStack::PushL(i);
sl@0
   112
				CASN1EncBigInt* encInt = CASN1EncBigInt::NewLC(i);
sl@0
   113
				CleanupStack::Pop(); // encInt
sl@0
   114
				CleanupStack::PopAndDestroy(&i); // a deep copy of the info is taken
sl@0
   115
				CleanupStack::PushL(encInt);
sl@0
   116
				child = encInt;
sl@0
   117
				break;
sl@0
   118
				}
sl@0
   119
				case 2:
sl@0
   120
				child = CASN1EncNull::NewLC();
sl@0
   121
				break;
sl@0
   122
			case KMaxChildType:
sl@0
   123
				// last case must be for next-level sequence encoder
sl@0
   124
				seqEnc = MakeSequenceEncoderLC(aMaxDepth - 1, aMinSize, aMaxSize);
sl@0
   125
				child = seqEnc;
sl@0
   126
				break;
sl@0
   127
			default:
sl@0
   128
				User::Leave(KErrNotSupported);
sl@0
   129
				break;
sl@0
   130
			}
sl@0
   131
		
sl@0
   132
		if (child)
sl@0
   133
			{
sl@0
   134
			encoder->AddChildL(child);
sl@0
   135
			CleanupStack::Pop(); // child
sl@0
   136
			++iObjectsEncoded;
sl@0
   137
			++size;
sl@0
   138
sl@0
   139
			// If we've just added a sequence, want to test ability to add things to a sequence
sl@0
   140
			// *that is itself a child*, to check size changes propagate upwards to parent
sl@0
   141
			if (seqEnc)
sl@0
   142
				{
sl@0
   143
				child = CASN1EncInt::NewLC(Math::Random());
sl@0
   144
sl@0
   145
				seqEnc->AddChildL(child);
sl@0
   146
				CleanupStack::Pop(); // child
sl@0
   147
				++iObjectsEncoded;
sl@0
   148
				seqEnc = 0;
sl@0
   149
				}
sl@0
   150
			}
sl@0
   151
		}
sl@0
   152
	
sl@0
   153
	return encoder;
sl@0
   154
	}
sl@0
   155
sl@0
   156
sl@0
   157
TInt CTestSequence::ReadAndCountL(const TDesC8& aBuf)
sl@0
   158
	{
sl@0
   159
	TInt result = 1;
sl@0
   160
	
sl@0
   161
	TASN1DecGeneric decoder(aBuf);
sl@0
   162
	decoder.InitL();
sl@0
   163
sl@0
   164
	TInt bufLength = aBuf.Length();
sl@0
   165
	TInt readLength = decoder.LengthDER();
sl@0
   166
sl@0
   167
	__ASSERT_ALWAYS(bufLength >= readLength, User::Leave(KErrCorrupt));
sl@0
   168
	if (bufLength > readLength)
sl@0
   169
		{
sl@0
   170
		// Read the remainder of this buffer too
sl@0
   171
		result += ReadAndCountL(aBuf.Mid(readLength));
sl@0
   172
		}
sl@0
   173
sl@0
   174
	if (decoder.Encoding()[0] & 0x20		// Tagged as constructed
sl@0
   175
		&& decoder.LengthDERContent() > 0) 
sl@0
   176
		{
sl@0
   177
		// Read objects from inside the sequence too
sl@0
   178
		result += ReadAndCountL(decoder.GetContentDER());
sl@0
   179
		}
sl@0
   180
sl@0
   181
	return result;
sl@0
   182
	}
sl@0
   183
sl@0
   184
TBool CTestSequence::PerformTestsL(CConsoleBase& aConsole)
sl@0
   185
	{
sl@0
   186
	// Keep these two coprime to maximise combinations
sl@0
   187
	const TInt KMaxSize = 11;
sl@0
   188
	const TInt KMaxDepth = 10;
sl@0
   189
	CTestParameter* test;
sl@0
   190
	TInt totalTests, currentTest=0;
sl@0
   191
	TInt maxDepth;
sl@0
   192
	TInt maxSize;
sl@0
   193
sl@0
   194
	if(!CountTests(totalTests)) return(EFalse);
sl@0
   195
sl@0
   196
	for(TInt pos = 0; pos < iValues->Count(); pos++)
sl@0
   197
		{
sl@0
   198
		test = (*iValues)[pos];
sl@0
   199
		switch(test->GetType())
sl@0
   200
			{
sl@0
   201
			case CTestParameter::EInt :
sl@0
   202
				{
sl@0
   203
				CIntTestParameter *intTest = REINTERPRET_CAST(CIntTestParameter*, test);
sl@0
   204
sl@0
   205
				// Get the encoder and decoder
sl@0
   206
				maxDepth = intTest->Value();
sl@0
   207
				test = (*iValues)[++pos];
sl@0
   208
				if(test->GetType() != CTestParameter::EInt)
sl@0
   209
					{
sl@0
   210
					User::Leave(KErrNotSupported);
sl@0
   211
					}
sl@0
   212
				intTest = REINTERPRET_CAST(CIntTestParameter*, test);
sl@0
   213
				maxSize = intTest->Value();
sl@0
   214
				if(!PerformTest(aConsole, maxDepth, maxSize, currentTest, totalTests))
sl@0
   215
					{
sl@0
   216
					return(EFalse);
sl@0
   217
					}
sl@0
   218
				currentTest++;
sl@0
   219
				break;
sl@0
   220
				}
sl@0
   221
			case CTestParameter::ERandom :
sl@0
   222
				{
sl@0
   223
				CRandomTestParameter *randomTest = REINTERPRET_CAST(CRandomTestParameter*, test);
sl@0
   224
				// Get the encoder and decoder
sl@0
   225
sl@0
   226
				for(TInt test = 0; test <= randomTest->Interations(); test++)
sl@0
   227
					{
sl@0
   228
sl@0
   229
					// Get the encoder and decoder
sl@0
   230
					maxDepth = (test % KMaxDepth) + 1;
sl@0
   231
					maxSize = test % KMaxSize;
sl@0
   232
sl@0
   233
					currentTest++;
sl@0
   234
					// Don't do the too-big combinations (too slow)
sl@0
   235
					if (maxDepth +  maxSize > 14) continue;
sl@0
   236
					if(!PerformTest(aConsole, maxDepth, maxSize, currentTest, totalTests))
sl@0
   237
						{
sl@0
   238
						return(EFalse);
sl@0
   239
						}
sl@0
   240
					}
sl@0
   241
				break;
sl@0
   242
				}
sl@0
   243
			default:
sl@0
   244
				{
sl@0
   245
				return EFalse;
sl@0
   246
				}
sl@0
   247
			}
sl@0
   248
		}
sl@0
   249
	iASN1Action.ReportProgressL(KErrNone, totalTests, totalTests);
sl@0
   250
	return(ETrue);
sl@0
   251
	}