cryptoplugins/cryptospiplugins/source/softwarecrypto/symmetriccipherimpl.h
changeset 19 cd501b96611d
equal deleted inserted replaced
15:da2ae96f639b 19:cd501b96611d
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #ifndef	__SYMMETRICCIPHERIMPL_H__
       
    20 #define	__SYMMETRICCIPHERIMPL_H__
       
    21 
       
    22 /**
       
    23 @file 
       
    24 @internalComponent
       
    25 @released
       
    26 */
       
    27 
       
    28 #include <e32base.h>
       
    29 #include <e32cmn.h>
       
    30 #include <cryptospi/cryptospidef.h>
       
    31 #include <padding.h>
       
    32 #include "symmetriccipherplugin.h"
       
    33 
       
    34 /** The maximum block size supported (in bytes) */
       
    35 const TUint KMaxBlockSizeSupported = 32;
       
    36 
       
    37 /**
       
    38 Abstract base class for symmetric cipher plug-ins.
       
    39 */
       
    40 namespace SoftwareCrypto
       
    41 	{
       
    42 	using namespace CryptoSpi;
       
    43 		
       
    44 	NONSHARABLE_CLASS(CSymmetricCipherImpl) : public CBase, public MSymmetricCipher
       
    45 		{
       
    46 	public:
       
    47 		/**
       
    48 		Implemented by each cipher subclass to determine whether the
       
    49 		specified key length is valid for that cipher.
       
    50 		This is called by ConstructL and SetKeyL
       
    51 		@param aKeyLength The key length in bytes to verify.
       
    52 		*/
       
    53 		virtual TBool IsValidKeyLength(TInt aKeyBytes) const = 0;
       
    54 		
       
    55 		/**
       
    56 		Helper function implemented by concrete cipher sub-class that 
       
    57 		allows GetCharacteristicsL to return the correct characteristics object.
       
    58 		@return The implemention uid
       
    59 		*/
       
    60 		virtual TUid ImplementationUid() const = 0;
       
    61 		
       
    62 		/**
       
    63 		Gets the strength of the current key, needed to check whether the cipher
       
    64 		may operate if strong cryptography is not enabled.
       
    65 		@return The strength of the current key
       
    66 		*/
       
    67 		virtual TInt GetKeyStrength() const;
       
    68 		
       
    69 				
       
    70 		// Override MPlugin virtual functions
       
    71 		void Close();
       
    72 		TAny* GetExtension(TUid aExtensionId);
       
    73 		void GetCharacteristicsL(const TCharacteristics*& aPluginCharacteristics);
       
    74 		// End of MPlugin
       
    75 		
       
    76 		// Override MSymmetricCipherBase virtual functions 
       
    77 		TInt KeySize() const;
       
    78 						
       
    79 		/// Destructor
       
    80 		~CSymmetricCipherImpl();
       
    81 
       
    82 	protected:
       
    83 		
       
    84 		//Constructor
       
    85 		CSymmetricCipherImpl();
       
    86 		
       
    87 		/**
       
    88 		Second phase of construction. Always call ConstructL in the super-class
       
    89 		if your override this method.
       
    90 		
       
    91 		@param aKey The key to initialise the cipher with.
       
    92 		*/
       
    93 		virtual void ConstructL(const CKey& aKey);		
       
    94 		
       
    95 		/**
       
    96 		Extracts the raw symmetric key from a generic key object. The buffer
       
    97 		is placed on the cleanup stack.
       
    98 		
       
    99 		@param aKey The key object
       
   100 		@return A buffer containing the raw key value
       
   101 		*/
       
   102 		HBufC8* ExtractKeyDataLC(const CKey& aKey) const;	
       
   103 	
       
   104 		/**
       
   105 		Zeros a buffer before deleting it to ensure that
       
   106 		the contents will not be visible to another process if the page
       
   107 		is re-used.
       
   108 		@param aBuffer The pointer (possibly null) to the buffer to delete. This
       
   109 		is set to null after deletion.
       
   110 		*/
       
   111 		void SecureDelete(HBufC8*& aBuffer);		
       
   112 					
       
   113 		/**
       
   114 		Extracts the raw key from aKey and sets iKey and iKeyBytes
       
   115 		The key length is also checked to meet export restrictions and
       
   116 		to ensure that it is appropriate for the cipher.
       
   117 		@param aKey The key
       
   118 		*/
       
   119 		virtual void DoSetKeyL(const CKey& aKey);
       
   120 		
       
   121 			
       
   122 	protected:
       
   123 		/// the key, extracted from a CKey object
       
   124 		HBufC8* iKey;
       
   125 		
       
   126 		/// key size in bytes
       
   127 		TUint iKeyBytes;
       
   128 		
       
   129 		};
       
   130 
       
   131 	NONSHARABLE_CLASS(CSymmetricStreamCipherImpl) : public CSymmetricCipherImpl
       
   132 		{
       
   133 	public:
       
   134 		// Destructor
       
   135 		~CSymmetricStreamCipherImpl();
       
   136 		
       
   137 		// Override MSymmetricCipherBase virtual functions 
       
   138 		TInt BlockSize() const;
       
   139 		void SetKeyL(const CKey& aKey);		// override DoSetKeyL instead
       
   140 		void SetCryptoModeL(TUid aCryptoMode);
       
   141 		void SetOperationModeL(TUid aOperationMode);
       
   142 		void SetPaddingModeL(TUid aPaddingMode);
       
   143 		void SetIvL(const TDesC8& aIv);
       
   144 		TInt MaxOutputLength(TInt aInputLength) const;
       
   145 		TInt MaxFinalOutputLength(TInt aInputLength) const;
       
   146 		// End of MSymmetricCipherBase
       
   147 		
       
   148 		// Override MSymmetricCipher virtual functions
       
   149 		void ProcessL(const TDesC8& aInput, TDes8& aOutput);
       
   150 		void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);						
       
   151 		// End of MSymmetricCipher 
       
   152 	
       
   153 	protected:
       
   154 		// Constructor
       
   155 		CSymmetricStreamCipherImpl();
       
   156 		
       
   157 		// Override CSymmetricCipherImpl virtual functions
       
   158 		virtual void ConstructL(const CKey& aKey);
       
   159 
       
   160 		/**	
       
   161 		Performs an encryption or decryption on supplied data.
       
   162 		@param aData	On input, data to be transformed; 
       
   163 						on return, transformed data.
       
   164 		*/
       
   165 		virtual void DoProcess(TDes8& aData) = 0;
       
   166 		};
       
   167 
       
   168 	NONSHARABLE_CLASS(CSymmetricBlockCipherImpl) : public CSymmetricCipherImpl
       
   169 		{
       
   170 	public:	
       
   171 
       
   172 
       
   173 		/**
       
   174 		This function is invoked by SetKey and SetCryptoMode
       
   175 		allowing the cipher sub-class to rebuild it's key schedule. 
       
   176 		N.B. It is assumed that the key schedule is NOT modified
       
   177 		by TransformEncrypt or TransformDecrypt
       
   178 		*/
       
   179 		virtual void SetKeySchedule() = 0;
       
   180 		
       
   181 		// Override MPlugin virtual functions		
       
   182 		void Reset(); // Always call reset in super-class if you override this
       
   183 		// End of MPlugin virtual functions
       
   184 
       
   185 		// Override MSymmetricCipherBase virtual functions 
       
   186 		TInt BlockSize() const;
       
   187 		void SetKeyL(const CKey& aKey);  				// override DoSetKeyL instead
       
   188 		void SetCryptoModeL(TUid aCryptoMode);			// override DoSetCryptoModeL instead
       
   189 		void SetOperationModeL(TUid aOperationMode);	// override DoSetOperationMode instead		
       
   190 		void SetPaddingModeL(TUid aPaddingMode);		// override DoSetPaddingModeL instead
       
   191 		void SetIvL(const TDesC8& aIv);
       
   192 		
       
   193 		TInt MaxOutputLength(TInt aInputLength) const;
       
   194 		TInt MaxFinalOutputLength(TInt aInputLength) const;
       
   195 		// End of MSymmetricCipherBase
       
   196 
       
   197 		// Override MSymmetricCipher virtual functions
       
   198 		void ProcessL(const TDesC8& aInput, TDes8& aOutput);
       
   199 		void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);						
       
   200 		// End of MSymmetricCipher
       
   201 
       
   202 		/// Destructor
       
   203 		~CSymmetricBlockCipherImpl();		
       
   204 	protected:	
       
   205 		/**
       
   206 		Constructor
       
   207 		@param aBlockBytes The block size in bytes
       
   208 		@param aOperationMode The mode of operation e.g. CBC
       
   209 		@param aCryptoMode Whether to encrypt or decrypt
       
   210 		*/
       
   211 		CSymmetricBlockCipherImpl(
       
   212 			TUint8 aBlockBytes,
       
   213 			TUid aOperationMode,
       
   214 			TUid aCryptoMode,
       
   215 			TUid aPaddingMode);
       
   216 			
       
   217 		// Override CSymmetricCipherImpl virtual functions
       
   218 		virtual void ConstructL(const CKey& aKey);
       
   219 
       
   220 		/**
       
   221 		Validates and sets the crypto mode (iCryptoMode)
       
   222 		@param aCryptoMode The crypto mode
       
   223 		*/	
       
   224 		virtual void DoSetCryptoModeL(TUid aCryptoMode);
       
   225 		
       
   226 		/**
       
   227 		Validates and sets the operation mode (iOperationMode)
       
   228 		@param aOperationMode The operation mode
       
   229 		*/
       
   230 		virtual void DoSetOperationModeL(TUid aOperationMode);
       
   231 		
       
   232 		/**
       
   233 		Validates and sets the padding mode (iPaddingMode & iPadding)
       
   234 		@param aPadding The desired padding mode
       
   235 		*/
       
   236 		virtual void DoSetPaddingModeL(TUid aPadding);
       
   237 		
       
   238 		void DoSetIvL(const TDesC8& aIv);
       
   239 
       
   240 		inline void ModeEncryptStart(TUint8* aBuffer);
       
   241 		inline void ModeEncryptEnd(TUint8* aBuffer);
       
   242 		inline void ModeDecryptStart(TUint8* aBuffer);
       
   243 		inline void ModeDecryptEnd(TUint8* aBuffer);
       
   244 
       
   245 	private:
       
   246 	
       
   247 		/**
       
   248 		Encrypts a number of blocks of data
       
   249 		
       
   250 		@param aBuffer The buffer containing exactly aNumBlocks of data to destructively encrypt
       
   251 		@param aNumBlocks The number of blocks of data to encrypt
       
   252 		*/
       
   253 		virtual void TransformEncrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;
       
   254 		
       
   255 		/**
       
   256 		Decrypts a number of blocks of data
       
   257 				
       
   258 		@param aBuffer The buffer containing exactly aNumBlocks of data to destructively decrypt
       
   259 		@param aNumBlocks The number of blocks of data to decrypt
       
   260 		*/
       
   261 		virtual void TransformDecrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;		
       
   262 			
       
   263 		/// Pad the last block and encrypt
       
   264 		void DoProcessFinalEncryptL(const TDesC8& aInput, TDes8& aOutput);
       
   265 		
       
   266 		/// Decrypt and unpad the last block
       
   267 		void DoProcessFinalDecryptL(const TDesC8& aInput, TDes8& aOutput);		
       
   268 		
       
   269 		inline void Transform(TUint8* aBuffer, TUint aNumBlocks);
       
   270 
       
   271 		void ProcessCtrL(const TDesC8& aInput, TDes8& aOutput);
       
   272 		
       
   273 	protected:
       
   274 	
       
   275 		/// block size in bytes, current largest block size is 16 bytes (AES)
       
   276 		TUint8 iBlockBytes;	
       
   277 		/// encryption or decryption
       
   278 		TUid iCryptoMode;		
       
   279 		/// The block cipher mode e.g. ECB, CBC
       
   280 		TUid iOperationMode;
       
   281 		/// the current padding scheme
       
   282 		TUid iPaddingMode;
       
   283 		
       
   284 		/// the initialisation vector
       
   285 		RBuf8 iIv;
       
   286 		
       
   287 		/// current padding scheme implementation
       
   288 		CPadding* iPadding;
       
   289 		/// buffer to store blocks
       
   290 		RBuf8 iInputStore;
       
   291 		/// buffer to store input / output of padding
       
   292 		RBuf8 iPaddingBlock;
       
   293 
       
   294 		/// The current block of cipher text - for CBC 
       
   295 		TUint32* iCurrentCipherText;	
       
   296 		/// A pointer to the current block of cipher text
       
   297 		TUint8* iCurrentCipherTextPtr;		
       
   298 		
       
   299 		/** Used in both CBC and CTR mode. In CBC mode it stores the result of the last transform. In CTR mode 
       
   300 		it stores the counter.*/
       
   301 		TUint32* iRegister;	
       
   302 		/** A pointer to iRegister.*/
       
   303 		TUint8* iRegisterPtr;			
       
   304 		
       
   305 		/** Used in CTR mode to buffer plaintext during encryption.*/
       
   306 		HBufC8* iBufferedPlaintext;
       
   307 		/** Pointer to manipulate iBufferedPlaintext.*/
       
   308 		TPtr8 iBufferedPlaintextPtr;
       
   309 		
       
   310 		/** CTR mode behaves like a stream cipher allowing arbitrary sized inputs to the encryption/decryption functions. 
       
   311 		When handling an input whose length is not a multiple of the blocksize iCtrUnusedKeystream is used to buffer
       
   312 		the unused portions of keystream for use in the next call. Cleared in Reset().*/
       
   313 		HBufC8* iCtrUnusedKeystream;
       
   314 		/** Pointer to manipulate iCtrUnusedKeystream.*/
       
   315 		TPtr8 iCtrUnusedKeystreamPtr;
       
   316 		};
       
   317 
       
   318 
       
   319 	inline void CSymmetricBlockCipherImpl::Transform(TUint8* aBuffer, TUint aNumBlocks)
       
   320 		{				
       
   321 		if (iCryptoMode.iUid == KCryptoModeEncrypt)	//if in CTR mode always in crypto mode encrypt
       
   322 			{				
       
   323 			TransformEncrypt(aBuffer, aNumBlocks);
       
   324 			}
       
   325 		else if (iCryptoMode.iUid == KCryptoModeDecrypt)
       
   326 			{				
       
   327 			TransformDecrypt(aBuffer, aNumBlocks);
       
   328 			}
       
   329 		else 
       
   330 			{
       
   331 			ASSERT(EFalse);
       
   332 			}
       
   333 		}
       
   334 			
       
   335 	inline void CSymmetricBlockCipherImpl::ModeEncryptStart(TUint8* aBuffer)
       
   336 		{
       
   337 		if (iOperationMode.iUid == KOperationModeCBC)
       
   338 			{			
       
   339 			for (TInt i = 0; i < iBlockBytes; ++i)
       
   340 				{
       
   341 				aBuffer[i] ^= iRegisterPtr[i];
       
   342 				}					
       
   343 			}
       
   344 		else if (iOperationMode.iUid == KOperationModeCTR)
       
   345 			{
       
   346 			iBufferedPlaintextPtr.Copy(aBuffer, iBlockBytes);
       
   347 			Mem::Copy(aBuffer, iRegister, iBlockBytes);				
       
   348 			}
       
   349 		}		
       
   350 	
       
   351 	inline void CSymmetricBlockCipherImpl::ModeEncryptEnd(TUint8* aBuffer)
       
   352 		{				
       
   353 		if (iOperationMode.iUid == KOperationModeCBC)
       
   354 			{
       
   355 			for (TInt i = 0; i < iBlockBytes; ++i)
       
   356 				{
       
   357 				iRegisterPtr[i] = aBuffer[i]; 
       
   358 				}													
       
   359 			}
       
   360 		else if (iOperationMode.iUid == KOperationModeCTR)
       
   361 			{
       
   362 			//XOR the plaintext with the keystream and increment counter
       
   363 			for (TInt i = 0; i < iBlockBytes; ++i)
       
   364 				{
       
   365 				aBuffer[i] ^= iBufferedPlaintextPtr[i]; 
       
   366 				}
       
   367 			for (TInt i = iBlockBytes - 1; i >= 0; --i)
       
   368 				{
       
   369 				if (++(iRegisterPtr[i]) != 0) break;				
       
   370 				}
       
   371 			}										
       
   372 		}		
       
   373 
       
   374 	inline void CSymmetricBlockCipherImpl::ModeDecryptStart(TUint8* aBuffer)
       
   375 		{
       
   376 		__ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 1));
       
   377 		if (iOperationMode.iUid == KOperationModeCBC)
       
   378 			{			
       
   379 			for (TInt i = 0; i < iBlockBytes; ++i)
       
   380 				{
       
   381 				iCurrentCipherTextPtr[i] = aBuffer[i];
       
   382 				}
       
   383 			}
       
   384 		}
       
   385 
       
   386 	inline void CSymmetricBlockCipherImpl::ModeDecryptEnd(TUint8* aBuffer)
       
   387 		{
       
   388 		__ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 2));		
       
   389 		if (iOperationMode.iUid == KOperationModeCBC)
       
   390 			{			
       
   391 			// xor the output with the previous cipher text
       
   392 			for (TInt i = 0; i < iBlockBytes; ++i)
       
   393 				{
       
   394 				aBuffer[i] ^= iRegisterPtr[i];
       
   395 				iRegisterPtr[i] = iCurrentCipherTextPtr[i];
       
   396 				}
       
   397 			}	
       
   398 		}		
       
   399 	}						
       
   400 
       
   401 #endif	//	__SYMMETRICCIPHERIMPL_H__