os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4_plugin/h4cipherimpl.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) 2007-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
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
/**
sl@0
    20
 @file
sl@0
    21
 @internalComponent
sl@0
    22
 @released
sl@0
    23
*/
sl@0
    24
#include "h4cipherimpl.h"
sl@0
    25
sl@0
    26
#include <e32def.h>
sl@0
    27
#include <cryptostrength.h>
sl@0
    28
#include <cryptospi/cryptospidef.h>
sl@0
    29
#include "keys.h"
sl@0
    30
#include <cryptospi/plugincharacteristics.h>
sl@0
    31
#include "pluginconfig.h"
sl@0
    32
#include <cryptopanic.h>
sl@0
    33
#include <securityerr.h>
sl@0
    34
#include "keyhandle.h"
sl@0
    35
sl@0
    36
using namespace HwCrypto;
sl@0
    37
sl@0
    38
#define BytesToBits(byteCount) (byteCount*8)
sl@0
    39
sl@0
    40
//
sl@0
    41
// Implementation of Symmetric Cipher class
sl@0
    42
//
sl@0
    43
CH4CipherImpl::CH4CipherImpl(TUint8 aBlockBytes,
sl@0
    44
							 TUid aCryptoMode,
sl@0
    45
							 TUid aOperationMode,
sl@0
    46
							 TUid aPaddingMode) 
sl@0
    47
	: iBlockBytes(aBlockBytes),
sl@0
    48
	  iCryptoMode(aCryptoMode),
sl@0
    49
	  iOperationMode(aOperationMode),
sl@0
    50
	  iPaddingMode(aPaddingMode)
sl@0
    51
	{
sl@0
    52
	}
sl@0
    53
sl@0
    54
void CH4CipherImpl::ConstructL(const CKey& aKey) 
sl@0
    55
	{
sl@0
    56
	SetKeyL(aKey);		
sl@0
    57
	SetOperationModeL(iOperationMode);
sl@0
    58
	SetCryptoModeL(iCryptoMode);	
sl@0
    59
	SetPaddingModeL(iPaddingMode);
sl@0
    60
	
sl@0
    61
	iPartialBlock.ReAllocL(iBlockBytes);
sl@0
    62
	iPaddingBlock.ReAllocL(iBlockBytes);
sl@0
    63
	
sl@0
    64
	iIv.ReAllocL(iBlockBytes);
sl@0
    65
	//	iIv.SetLength(iBlockBytes);
sl@0
    66
	//	TRandom::RandomL(iIv);
sl@0
    67
	}
sl@0
    68
	
sl@0
    69
CExtendedCharacteristics* CH4CipherImpl::CreateExtendedCharacteristicsL()
sl@0
    70
	{
sl@0
    71
	// All Symbian software plug-ins have unlimited concurrency, cannot be reserved
sl@0
    72
	// for exclusive use and are not CERTIFIED to be standards compliant.		
sl@0
    73
sl@0
    74
	//	return CExtendedCharacteristics::NewL(KMaxTInt, iStandardsConformance, EFalse);	
sl@0
    75
	return 0;	
sl@0
    76
	}
sl@0
    77
sl@0
    78
CH4CipherImpl::~CH4CipherImpl()
sl@0
    79
	{			
sl@0
    80
	delete iPadding;
sl@0
    81
	iIv.Close();
sl@0
    82
	iPartialBlock.Close();
sl@0
    83
	iPaddingBlock.Close();	
sl@0
    84
sl@0
    85
	delete iKey;	
sl@0
    86
	iStandardsConformance.Close();	
sl@0
    87
	}
sl@0
    88
		
sl@0
    89
void CH4CipherImpl::Close()
sl@0
    90
	{
sl@0
    91
	delete this;
sl@0
    92
	}
sl@0
    93
	
sl@0
    94
TAny* CH4CipherImpl::GetExtension(TUid /*aExtensionId*/) 
sl@0
    95
	{
sl@0
    96
	return 0;
sl@0
    97
	}
sl@0
    98
	
sl@0
    99
void CH4CipherImpl::GetCharacteristicsL(const TAny*& aPluginCharacteristics)
sl@0
   100
	{
sl@0
   101
	TInt numCiphers = sizeof(KSymmetricCipherCharacteristics)/sizeof(TSymmetricCipherCharacteristics*);
sl@0
   102
	TInt32 implUid = ImplementationUid().iUid;
sl@0
   103
	for (TInt i = 0; i < numCiphers; ++i)
sl@0
   104
		{
sl@0
   105
		if (KSymmetricCipherCharacteristics[i]->cmn.iImplementationUID == implUid)
sl@0
   106
			{
sl@0
   107
			aPluginCharacteristics = KSymmetricCipherCharacteristics[i];
sl@0
   108
			break;
sl@0
   109
			}
sl@0
   110
		}	
sl@0
   111
	}
sl@0
   112
sl@0
   113
sl@0
   114
void CH4CipherImpl::Reset()
sl@0
   115
	{
sl@0
   116
	iPartialBlock.Zero();
sl@0
   117
	iPaddingBlock.Zero();
sl@0
   118
	
sl@0
   119
	// Reconfigure h/w based on iCryptoMode/iOperationMode/iKey/iIv
sl@0
   120
	TRAP_IGNORE(DoSetupL());
sl@0
   121
	iNeedToSetupHw = EFalse;
sl@0
   122
	}	
sl@0
   123
sl@0
   124
sl@0
   125
TInt CH4CipherImpl::GetKeyStrength() const
sl@0
   126
	{
sl@0
   127
	return BytesToBits(iKey->Length());
sl@0
   128
	}
sl@0
   129
	
sl@0
   130
HBufC8* CH4CipherImpl::ExtractKeyDataLC(const CKey& aKey) const
sl@0
   131
	{
sl@0
   132
	const TDesC8& keyContent = aKey.GetTDesC8L(KSymmetricKeyParameterUid);
sl@0
   133
	return keyContent.AllocLC();
sl@0
   134
	}
sl@0
   135
sl@0
   136
TInt CH4CipherImpl::KeySize() const
sl@0
   137
	{
sl@0
   138
	// return key size in BITS
sl@0
   139
	return BytesToBits(iKeyBytes);
sl@0
   140
	}
sl@0
   141
sl@0
   142
void CH4CipherImpl::SetKeyL(const CKey& aKey)
sl@0
   143
	{
sl@0
   144
	HBufC8* key = ExtractKeyDataLC(aKey);
sl@0
   145
	TInt keyLength(key->Length());
sl@0
   146
	
sl@0
   147
	const TKeyProperty &keyProps = aKey.KeyProperty();
sl@0
   148
sl@0
   149
	if(keyProps.iKeyType != KSymmetricKeyUid)
sl@0
   150
		{
sl@0
   151
		User::Leave(KErrArgument);
sl@0
   152
		}
sl@0
   153
sl@0
   154
	if(keyProps.iKeyAttribute == KNonEmbeddedKeyUid)
sl@0
   155
		{
sl@0
   156
		// Not an embedded key, so key is the actual key data and we
sl@0
   157
		// can therefore check its strength...
sl@0
   158
		TCrypto::IsSymmetricWeakEnoughL(BytesToBits(keyLength));
sl@0
   159
		if (! IsValidKeyLength(keyLength))
sl@0
   160
			{
sl@0
   161
			User::Leave(KErrNotSupported);
sl@0
   162
			}
sl@0
   163
		}
sl@0
   164
		
sl@0
   165
	delete iKey;	
sl@0
   166
	CleanupStack::Pop(key);
sl@0
   167
	iKey = key;
sl@0
   168
	iKeyBytes = keyLength;
sl@0
   169
sl@0
   170
	// H/W needs reconfiguring
sl@0
   171
	iNeedToSetupHw = ETrue;
sl@0
   172
	}	
sl@0
   173
sl@0
   174
TInt CH4CipherImpl::BlockSize() const
sl@0
   175
	{
sl@0
   176
	// return block size in BITS
sl@0
   177
	return BytesToBits(iBlockBytes);
sl@0
   178
	}
sl@0
   179
sl@0
   180
void CH4CipherImpl::SetCryptoModeL(TUid aCryptoMode)
sl@0
   181
	{
sl@0
   182
	switch (aCryptoMode.iUid)
sl@0
   183
		{
sl@0
   184
		case KCryptoModeEncrypt:
sl@0
   185
		case KCryptoModeDecrypt:
sl@0
   186
			break;
sl@0
   187
		default:
sl@0
   188
			User::Leave(KErrNotSupported);
sl@0
   189
		}
sl@0
   190
	iCryptoMode = aCryptoMode;		
sl@0
   191
	// H/W needs reconfiguring
sl@0
   192
	iNeedToSetupHw = ETrue;
sl@0
   193
	}
sl@0
   194
sl@0
   195
void CH4CipherImpl::SetOperationModeL(TUid aOperationMode)
sl@0
   196
	{
sl@0
   197
	switch (aOperationMode.iUid)
sl@0
   198
		{
sl@0
   199
		case KOperationModeNone:
sl@0
   200
		case KOperationModeECB:
sl@0
   201
		case KOperationModeCBC:
sl@0
   202
			break;
sl@0
   203
		default:
sl@0
   204
			User::Leave(KErrNotSupported);
sl@0
   205
		}
sl@0
   206
	iOperationMode = aOperationMode;		
sl@0
   207
	// H/W needs reconfiguring
sl@0
   208
	iNeedToSetupHw = ETrue;
sl@0
   209
	}
sl@0
   210
sl@0
   211
void CH4CipherImpl::SetPaddingModeL(TUid aPaddingMode)
sl@0
   212
	{
sl@0
   213
	if(!iPadding || (aPaddingMode != iPaddingMode))
sl@0
   214
		{
sl@0
   215
		CPadding* padding(0);
sl@0
   216
		switch (aPaddingMode.iUid)
sl@0
   217
			{
sl@0
   218
			case KPaddingModeNone:
sl@0
   219
				padding = CPaddingNone::NewL(iBlockBytes);
sl@0
   220
				break;
sl@0
   221
			case KPaddingModeSSLv3:
sl@0
   222
			padding = CPaddingSSLv3::NewL(iBlockBytes);
sl@0
   223
			break;
sl@0
   224
			case KPaddingModePKCS7:
sl@0
   225
				padding = CPaddingPKCS7::NewL(iBlockBytes);
sl@0
   226
				break;
sl@0
   227
			default:
sl@0
   228
				User::Leave(KErrNotSupported);
sl@0
   229
			}
sl@0
   230
		delete iPadding;
sl@0
   231
		iPadding = padding;
sl@0
   232
		iPaddingMode = aPaddingMode;
sl@0
   233
		}
sl@0
   234
	
sl@0
   235
	// H/W needs reconfiguring
sl@0
   236
	iNeedToSetupHw = ETrue;
sl@0
   237
	}
sl@0
   238
	
sl@0
   239
void CH4CipherImpl::SetIvL(const TDesC8& aIv)
sl@0
   240
	{
sl@0
   241
	if (iOperationMode.iUid != KOperationModeCBC)
sl@0
   242
		{
sl@0
   243
		User::Leave(KErrNotSupported);
sl@0
   244
		}
sl@0
   245
sl@0
   246
	if (aIv.Length() != iBlockBytes) 
sl@0
   247
		{
sl@0
   248
		User::Leave(KErrArgument);
sl@0
   249
		}
sl@0
   250
	iIv = aIv;	
sl@0
   251
sl@0
   252
	// H/W needs reconfiguring
sl@0
   253
	iNeedToSetupHw = ETrue;
sl@0
   254
	}
sl@0
   255
sl@0
   256
sl@0
   257
sl@0
   258
	
sl@0
   259
	
sl@0
   260
sl@0
   261
sl@0
   262
sl@0
   263
sl@0
   264
TInt CH4CipherImpl::MaxOutputLength(TInt aInputLength) const
sl@0
   265
	{	
sl@0
   266
	// The maximum output length required for Process is equal to the
sl@0
   267
	// size of the number of whole input blocks available.
sl@0
   268
	//
sl@0
   269
	// The block bytes is a power of two so we can use this to avoid
sl@0
   270
	// doing a real mod operation
sl@0
   271
	TUint partialBlockLength(iPartialBlock.Length());
sl@0
   272
	return (partialBlockLength + aInputLength) & ~TUint32(iBlockBytes - 1);
sl@0
   273
	}	
sl@0
   274
sl@0
   275
TInt CH4CipherImpl::MaxFinalOutputLength(TInt aInputLength) const
sl@0
   276
	{
sl@0
   277
	if (iCryptoMode.iUid == KCryptoModeEncrypt)
sl@0
   278
		{
sl@0
   279
		return iPadding->MaxPaddedLength(iPartialBlock.Length() + aInputLength);
sl@0
   280
		}
sl@0
   281
	else
sl@0
   282
		{
sl@0
   283
		return iPadding->MaxUnPaddedLength(aInputLength + iPartialBlock.Length());
sl@0
   284
		}
sl@0
   285
	}
sl@0
   286
sl@0
   287
sl@0
   288
sl@0
   289
void CH4CipherImpl::ProcessL(const TDesC8& aInput, TDes8& aOutput)
sl@0
   290
	{
sl@0
   291
	if(iNeedToSetupHw)
sl@0
   292
		{
sl@0
   293
		// Reconfigure h/w based on iCryptoMode/iOperationMode/iKey/iIv
sl@0
   294
		DoSetupL();
sl@0
   295
		iNeedToSetupHw = EFalse;
sl@0
   296
		}
sl@0
   297
sl@0
   298
	TInt inputLength(aInput.Length());	
sl@0
   299
	if (MaxOutputLength(inputLength) > aOutput.MaxLength())
sl@0
   300
		{
sl@0
   301
		User::Leave(KErrOverflow);
sl@0
   302
		}	
sl@0
   303
sl@0
   304
	TInt partialBlockLength(iPartialBlock.Length()); // partial data written to h/w last time
sl@0
   305
	TUint32 totalInput = partialBlockLength + inputLength;
sl@0
   306
	
sl@0
   307
	// Pass new data to h/w driver
sl@0
   308
	DoWriteL(aInput.Ptr(), inputLength);
sl@0
   309
sl@0
   310
	if(totalInput < iBlockBytes)
sl@0
   311
		{
sl@0
   312
		// Keep a copy of the partial block which is inside the h/w
sl@0
   313
		// driver in case we need to calculate pad for it later...
sl@0
   314
		if(inputLength) iPartialBlock.Append(aInput);
sl@0
   315
		// Not enough written yet for more data to be available yet.
sl@0
   316
		return;
sl@0
   317
		}
sl@0
   318
	else
sl@0
   319
		{
sl@0
   320
		// We have completed the previous partial block so we no
sl@0
   321
		// longer need to keep a copy of it
sl@0
   322
		iPartialBlock.Zero();
sl@0
   323
		// Work out length of partial block at end of current data
sl@0
   324
		TUint32 trailing = TUint32(partialBlockLength + inputLength) & TUint32(iBlockBytes - 1);
sl@0
   325
		// Keep a copy of the partial block data
sl@0
   326
		if(trailing) iPartialBlock.Append(aInput.Right(trailing));
sl@0
   327
		}
sl@0
   328
sl@0
   329
	//
sl@0
   330
	// Work out how much data is available for reading.
sl@0
   331
	//
sl@0
   332
	// The h/w processes data a block at a time, and we only ever read
sl@0
   333
	// a multiple of the block size so the available data will always
sl@0
   334
	// be a multiple of the blocksize.
sl@0
   335
sl@0
   336
	TUint32 availableData = totalInput & ~TUint32(iBlockBytes - 1);
sl@0
   337
	if (availableData)
sl@0
   338
		{
sl@0
   339
		// Read available data
sl@0
   340
		DoReadL(aOutput, availableData);
sl@0
   341
		}
sl@0
   342
	}
sl@0
   343
sl@0
   344
void CH4CipherImpl::ProcessFinalL(const TDesC8& aInput, TDes8& aOutput)
sl@0
   345
	{
sl@0
   346
	if(iNeedToSetupHw)
sl@0
   347
		{
sl@0
   348
		// Reconfigure h/w based on iCryptoMode/iOperationMode/iKey/iIv
sl@0
   349
		DoSetupL();
sl@0
   350
		iNeedToSetupHw = EFalse;
sl@0
   351
		}
sl@0
   352
sl@0
   353
	if(MaxFinalOutputLength(aInput.Length()) > aOutput.MaxLength() - aOutput.Length())
sl@0
   354
		{
sl@0
   355
		User::Leave(KErrOverflow);
sl@0
   356
		}
sl@0
   357
sl@0
   358
sl@0
   359
	if(iCryptoMode.iUid == KCryptoModeEncrypt)
sl@0
   360
		{
sl@0
   361
		// process everything up to the last (possibly empty block)
sl@0
   362
		ProcessL(aInput, aOutput);
sl@0
   363
sl@0
   364
		// pad the plaintext
sl@0
   365
		iPaddingBlock.Zero();
sl@0
   366
		iPadding->PadL(iPartialBlock, iPaddingBlock);
sl@0
   367
sl@0
   368
		TUint32 padLength = iPaddingBlock.Length();
sl@0
   369
		// Make sure pad worked
sl@0
   370
		if(padLength & TUint32(iBlockBytes-1))
sl@0
   371
			{
sl@0
   372
			User::Leave(KErrInvalidPadding);
sl@0
   373
			}
sl@0
   374
	
sl@0
   375
		if(padLength > 0)
sl@0
   376
			{
sl@0
   377
			// Padding created
sl@0
   378
sl@0
   379
			// We have already written iPartialBlock data to the h/w
sl@0
   380
			// so skip those bytes which are in the pad.
sl@0
   381
			TUint32 partialLength = iPartialBlock.Length();
sl@0
   382
			if(partialLength)
sl@0
   383
				{
sl@0
   384
				// Make sure the pad algorithm did not change the bytes at
sl@0
   385
				// the start of the block....
sl@0
   386
				if(iPaddingBlock.Left(partialLength) != iPartialBlock)
sl@0
   387
					{
sl@0
   388
					User::Leave(KErrInvalidPadding);
sl@0
   389
					}
sl@0
   390
				}
sl@0
   391
			// Pass new data to h/w driver
sl@0
   392
			DoWriteL(iPaddingBlock.Ptr() + partialLength, padLength - partialLength);
sl@0
   393
sl@0
   394
			// Have now written an exact multiple of blocks to h/w so clear partial
sl@0
   395
			iPartialBlock.Zero();
sl@0
   396
sl@0
   397
			// Read data
sl@0
   398
			DoReadL(aOutput, padLength);
sl@0
   399
			}
sl@0
   400
		}
sl@0
   401
	else
sl@0
   402
		{
sl@0
   403
		// Decrypt
sl@0
   404
sl@0
   405
		// Input length (including inputstore) must be a multiple of the 
sl@0
   406
		// block size in length
sl@0
   407
		if ((aInput.Length() + iPartialBlock.Length()) & (iBlockBytes - 1)) 
sl@0
   408
			{
sl@0
   409
			User::Leave(KErrArgument);
sl@0
   410
			}
sl@0
   411
		
sl@0
   412
		// process everything up to the last (possibly empty block)
sl@0
   413
		ProcessL(aInput, aOutput);
sl@0
   414
		ASSERT(iPartialBlock.Length()==0); // all the blocks should have been decrypted
sl@0
   415
sl@0
   416
		// Retrieve last decrypted block.
sl@0
   417
		iPaddingBlock = aOutput.Right(iBlockBytes);
sl@0
   418
		aOutput.SetLength(aOutput.Length() - iBlockBytes);
sl@0
   419
sl@0
   420
		// Unpad the last block and (re)append to output
sl@0
   421
		iPadding->UnPadL(iPaddingBlock, aOutput);
sl@0
   422
	
sl@0
   423
		iPaddingBlock.Zero();
sl@0
   424
		iPartialBlock.Zero();
sl@0
   425
		}
sl@0
   426
	
sl@0
   427
	}
sl@0
   428
sl@0
   429
sl@0
   430
sl@0
   431
// End of file
sl@0
   432
sl@0
   433