os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/symmetriccipherimpl.h
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoplugins/cryptospiplugins/source/softwarecrypto/symmetriccipherimpl.h Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,401 @@
1.4 +/*
1.5 +* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#ifndef __SYMMETRICCIPHERIMPL_H__
1.23 +#define __SYMMETRICCIPHERIMPL_H__
1.24 +
1.25 +/**
1.26 +@file
1.27 +@internalComponent
1.28 +@released
1.29 +*/
1.30 +
1.31 +#include <e32base.h>
1.32 +#include <e32cmn.h>
1.33 +#include <cryptospi/cryptospidef.h>
1.34 +#include <padding.h>
1.35 +#include "symmetriccipherplugin.h"
1.36 +
1.37 +/** The maximum block size supported (in bytes) */
1.38 +const TUint KMaxBlockSizeSupported = 32;
1.39 +
1.40 +/**
1.41 +Abstract base class for symmetric cipher plug-ins.
1.42 +*/
1.43 +namespace SoftwareCrypto
1.44 + {
1.45 + using namespace CryptoSpi;
1.46 +
1.47 + NONSHARABLE_CLASS(CSymmetricCipherImpl) : public CBase, public MSymmetricCipher
1.48 + {
1.49 + public:
1.50 + /**
1.51 + Implemented by each cipher subclass to determine whether the
1.52 + specified key length is valid for that cipher.
1.53 + This is called by ConstructL and SetKeyL
1.54 + @param aKeyLength The key length in bytes to verify.
1.55 + */
1.56 + virtual TBool IsValidKeyLength(TInt aKeyBytes) const = 0;
1.57 +
1.58 + /**
1.59 + Helper function implemented by concrete cipher sub-class that
1.60 + allows GetCharacteristicsL to return the correct characteristics object.
1.61 + @return The implemention uid
1.62 + */
1.63 + virtual TUid ImplementationUid() const = 0;
1.64 +
1.65 + /**
1.66 + Gets the strength of the current key, needed to check whether the cipher
1.67 + may operate if strong cryptography is not enabled.
1.68 + @return The strength of the current key
1.69 + */
1.70 + virtual TInt GetKeyStrength() const;
1.71 +
1.72 +
1.73 + // Override MPlugin virtual functions
1.74 + void Close();
1.75 + TAny* GetExtension(TUid aExtensionId);
1.76 + void GetCharacteristicsL(const TCharacteristics*& aPluginCharacteristics);
1.77 + // End of MPlugin
1.78 +
1.79 + // Override MSymmetricCipherBase virtual functions
1.80 + TInt KeySize() const;
1.81 +
1.82 + /// Destructor
1.83 + ~CSymmetricCipherImpl();
1.84 +
1.85 + protected:
1.86 +
1.87 + //Constructor
1.88 + CSymmetricCipherImpl();
1.89 +
1.90 + /**
1.91 + Second phase of construction. Always call ConstructL in the super-class
1.92 + if your override this method.
1.93 +
1.94 + @param aKey The key to initialise the cipher with.
1.95 + */
1.96 + virtual void ConstructL(const CKey& aKey);
1.97 +
1.98 + /**
1.99 + Extracts the raw symmetric key from a generic key object. The buffer
1.100 + is placed on the cleanup stack.
1.101 +
1.102 + @param aKey The key object
1.103 + @return A buffer containing the raw key value
1.104 + */
1.105 + HBufC8* ExtractKeyDataLC(const CKey& aKey) const;
1.106 +
1.107 + /**
1.108 + Zeros a buffer before deleting it to ensure that
1.109 + the contents will not be visible to another process if the page
1.110 + is re-used.
1.111 + @param aBuffer The pointer (possibly null) to the buffer to delete. This
1.112 + is set to null after deletion.
1.113 + */
1.114 + void SecureDelete(HBufC8*& aBuffer);
1.115 +
1.116 + /**
1.117 + Extracts the raw key from aKey and sets iKey and iKeyBytes
1.118 + The key length is also checked to meet export restrictions and
1.119 + to ensure that it is appropriate for the cipher.
1.120 + @param aKey The key
1.121 + */
1.122 + virtual void DoSetKeyL(const CKey& aKey);
1.123 +
1.124 +
1.125 + protected:
1.126 + /// the key, extracted from a CKey object
1.127 + HBufC8* iKey;
1.128 +
1.129 + /// key size in bytes
1.130 + TUint iKeyBytes;
1.131 +
1.132 + };
1.133 +
1.134 + NONSHARABLE_CLASS(CSymmetricStreamCipherImpl) : public CSymmetricCipherImpl
1.135 + {
1.136 + public:
1.137 + // Destructor
1.138 + ~CSymmetricStreamCipherImpl();
1.139 +
1.140 + // Override MSymmetricCipherBase virtual functions
1.141 + TInt BlockSize() const;
1.142 + void SetKeyL(const CKey& aKey); // override DoSetKeyL instead
1.143 + void SetCryptoModeL(TUid aCryptoMode);
1.144 + void SetOperationModeL(TUid aOperationMode);
1.145 + void SetPaddingModeL(TUid aPaddingMode);
1.146 + void SetIvL(const TDesC8& aIv);
1.147 + TInt MaxOutputLength(TInt aInputLength) const;
1.148 + TInt MaxFinalOutputLength(TInt aInputLength) const;
1.149 + // End of MSymmetricCipherBase
1.150 +
1.151 + // Override MSymmetricCipher virtual functions
1.152 + void ProcessL(const TDesC8& aInput, TDes8& aOutput);
1.153 + void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);
1.154 + // End of MSymmetricCipher
1.155 +
1.156 + protected:
1.157 + // Constructor
1.158 + CSymmetricStreamCipherImpl();
1.159 +
1.160 + // Override CSymmetricCipherImpl virtual functions
1.161 + virtual void ConstructL(const CKey& aKey);
1.162 +
1.163 + /**
1.164 + Performs an encryption or decryption on supplied data.
1.165 + @param aData On input, data to be transformed;
1.166 + on return, transformed data.
1.167 + */
1.168 + virtual void DoProcess(TDes8& aData) = 0;
1.169 + };
1.170 +
1.171 + NONSHARABLE_CLASS(CSymmetricBlockCipherImpl) : public CSymmetricCipherImpl
1.172 + {
1.173 + public:
1.174 +
1.175 +
1.176 + /**
1.177 + This function is invoked by SetKey and SetCryptoMode
1.178 + allowing the cipher sub-class to rebuild it's key schedule.
1.179 + N.B. It is assumed that the key schedule is NOT modified
1.180 + by TransformEncrypt or TransformDecrypt
1.181 + */
1.182 + virtual void SetKeySchedule() = 0;
1.183 +
1.184 + // Override MPlugin virtual functions
1.185 + void Reset(); // Always call reset in super-class if you override this
1.186 + // End of MPlugin virtual functions
1.187 +
1.188 + // Override MSymmetricCipherBase virtual functions
1.189 + TInt BlockSize() const;
1.190 + void SetKeyL(const CKey& aKey); // override DoSetKeyL instead
1.191 + void SetCryptoModeL(TUid aCryptoMode); // override DoSetCryptoModeL instead
1.192 + void SetOperationModeL(TUid aOperationMode); // override DoSetOperationMode instead
1.193 + void SetPaddingModeL(TUid aPaddingMode); // override DoSetPaddingModeL instead
1.194 + void SetIvL(const TDesC8& aIv);
1.195 +
1.196 + TInt MaxOutputLength(TInt aInputLength) const;
1.197 + TInt MaxFinalOutputLength(TInt aInputLength) const;
1.198 + // End of MSymmetricCipherBase
1.199 +
1.200 + // Override MSymmetricCipher virtual functions
1.201 + void ProcessL(const TDesC8& aInput, TDes8& aOutput);
1.202 + void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);
1.203 + // End of MSymmetricCipher
1.204 +
1.205 + /// Destructor
1.206 + ~CSymmetricBlockCipherImpl();
1.207 + protected:
1.208 + /**
1.209 + Constructor
1.210 + @param aBlockBytes The block size in bytes
1.211 + @param aOperationMode The mode of operation e.g. CBC
1.212 + @param aCryptoMode Whether to encrypt or decrypt
1.213 + */
1.214 + CSymmetricBlockCipherImpl(
1.215 + TUint8 aBlockBytes,
1.216 + TUid aOperationMode,
1.217 + TUid aCryptoMode,
1.218 + TUid aPaddingMode);
1.219 +
1.220 + // Override CSymmetricCipherImpl virtual functions
1.221 + virtual void ConstructL(const CKey& aKey);
1.222 +
1.223 + /**
1.224 + Validates and sets the crypto mode (iCryptoMode)
1.225 + @param aCryptoMode The crypto mode
1.226 + */
1.227 + virtual void DoSetCryptoModeL(TUid aCryptoMode);
1.228 +
1.229 + /**
1.230 + Validates and sets the operation mode (iOperationMode)
1.231 + @param aOperationMode The operation mode
1.232 + */
1.233 + virtual void DoSetOperationModeL(TUid aOperationMode);
1.234 +
1.235 + /**
1.236 + Validates and sets the padding mode (iPaddingMode & iPadding)
1.237 + @param aPadding The desired padding mode
1.238 + */
1.239 + virtual void DoSetPaddingModeL(TUid aPadding);
1.240 +
1.241 + void DoSetIvL(const TDesC8& aIv);
1.242 +
1.243 + inline void ModeEncryptStart(TUint8* aBuffer);
1.244 + inline void ModeEncryptEnd(TUint8* aBuffer);
1.245 + inline void ModeDecryptStart(TUint8* aBuffer);
1.246 + inline void ModeDecryptEnd(TUint8* aBuffer);
1.247 +
1.248 + private:
1.249 +
1.250 + /**
1.251 + Encrypts a number of blocks of data
1.252 +
1.253 + @param aBuffer The buffer containing exactly aNumBlocks of data to destructively encrypt
1.254 + @param aNumBlocks The number of blocks of data to encrypt
1.255 + */
1.256 + virtual void TransformEncrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;
1.257 +
1.258 + /**
1.259 + Decrypts a number of blocks of data
1.260 +
1.261 + @param aBuffer The buffer containing exactly aNumBlocks of data to destructively decrypt
1.262 + @param aNumBlocks The number of blocks of data to decrypt
1.263 + */
1.264 + virtual void TransformDecrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;
1.265 +
1.266 + /// Pad the last block and encrypt
1.267 + void DoProcessFinalEncryptL(const TDesC8& aInput, TDes8& aOutput);
1.268 +
1.269 + /// Decrypt and unpad the last block
1.270 + void DoProcessFinalDecryptL(const TDesC8& aInput, TDes8& aOutput);
1.271 +
1.272 + inline void Transform(TUint8* aBuffer, TUint aNumBlocks);
1.273 +
1.274 + void ProcessCtrL(const TDesC8& aInput, TDes8& aOutput);
1.275 +
1.276 + protected:
1.277 +
1.278 + /// block size in bytes, current largest block size is 16 bytes (AES)
1.279 + TUint8 iBlockBytes;
1.280 + /// encryption or decryption
1.281 + TUid iCryptoMode;
1.282 + /// The block cipher mode e.g. ECB, CBC
1.283 + TUid iOperationMode;
1.284 + /// the current padding scheme
1.285 + TUid iPaddingMode;
1.286 +
1.287 + /// the initialisation vector
1.288 + RBuf8 iIv;
1.289 +
1.290 + /// current padding scheme implementation
1.291 + CPadding* iPadding;
1.292 + /// buffer to store blocks
1.293 + RBuf8 iInputStore;
1.294 + /// buffer to store input / output of padding
1.295 + RBuf8 iPaddingBlock;
1.296 +
1.297 + /// The current block of cipher text - for CBC
1.298 + TUint32* iCurrentCipherText;
1.299 + /// A pointer to the current block of cipher text
1.300 + TUint8* iCurrentCipherTextPtr;
1.301 +
1.302 + /** Used in both CBC and CTR mode. In CBC mode it stores the result of the last transform. In CTR mode
1.303 + it stores the counter.*/
1.304 + TUint32* iRegister;
1.305 + /** A pointer to iRegister.*/
1.306 + TUint8* iRegisterPtr;
1.307 +
1.308 + /** Used in CTR mode to buffer plaintext during encryption.*/
1.309 + HBufC8* iBufferedPlaintext;
1.310 + /** Pointer to manipulate iBufferedPlaintext.*/
1.311 + TPtr8 iBufferedPlaintextPtr;
1.312 +
1.313 + /** CTR mode behaves like a stream cipher allowing arbitrary sized inputs to the encryption/decryption functions.
1.314 + When handling an input whose length is not a multiple of the blocksize iCtrUnusedKeystream is used to buffer
1.315 + the unused portions of keystream for use in the next call. Cleared in Reset().*/
1.316 + HBufC8* iCtrUnusedKeystream;
1.317 + /** Pointer to manipulate iCtrUnusedKeystream.*/
1.318 + TPtr8 iCtrUnusedKeystreamPtr;
1.319 + };
1.320 +
1.321 +
1.322 + inline void CSymmetricBlockCipherImpl::Transform(TUint8* aBuffer, TUint aNumBlocks)
1.323 + {
1.324 + if (iCryptoMode.iUid == KCryptoModeEncrypt) //if in CTR mode always in crypto mode encrypt
1.325 + {
1.326 + TransformEncrypt(aBuffer, aNumBlocks);
1.327 + }
1.328 + else if (iCryptoMode.iUid == KCryptoModeDecrypt)
1.329 + {
1.330 + TransformDecrypt(aBuffer, aNumBlocks);
1.331 + }
1.332 + else
1.333 + {
1.334 + ASSERT(EFalse);
1.335 + }
1.336 + }
1.337 +
1.338 + inline void CSymmetricBlockCipherImpl::ModeEncryptStart(TUint8* aBuffer)
1.339 + {
1.340 + if (iOperationMode.iUid == KOperationModeCBC)
1.341 + {
1.342 + for (TInt i = 0; i < iBlockBytes; ++i)
1.343 + {
1.344 + aBuffer[i] ^= iRegisterPtr[i];
1.345 + }
1.346 + }
1.347 + else if (iOperationMode.iUid == KOperationModeCTR)
1.348 + {
1.349 + iBufferedPlaintextPtr.Copy(aBuffer, iBlockBytes);
1.350 + Mem::Copy(aBuffer, iRegister, iBlockBytes);
1.351 + }
1.352 + }
1.353 +
1.354 + inline void CSymmetricBlockCipherImpl::ModeEncryptEnd(TUint8* aBuffer)
1.355 + {
1.356 + if (iOperationMode.iUid == KOperationModeCBC)
1.357 + {
1.358 + for (TInt i = 0; i < iBlockBytes; ++i)
1.359 + {
1.360 + iRegisterPtr[i] = aBuffer[i];
1.361 + }
1.362 + }
1.363 + else if (iOperationMode.iUid == KOperationModeCTR)
1.364 + {
1.365 + //XOR the plaintext with the keystream and increment counter
1.366 + for (TInt i = 0; i < iBlockBytes; ++i)
1.367 + {
1.368 + aBuffer[i] ^= iBufferedPlaintextPtr[i];
1.369 + }
1.370 + for (TInt i = iBlockBytes - 1; i >= 0; --i)
1.371 + {
1.372 + if (++(iRegisterPtr[i]) != 0) break;
1.373 + }
1.374 + }
1.375 + }
1.376 +
1.377 + inline void CSymmetricBlockCipherImpl::ModeDecryptStart(TUint8* aBuffer)
1.378 + {
1.379 + __ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 1));
1.380 + if (iOperationMode.iUid == KOperationModeCBC)
1.381 + {
1.382 + for (TInt i = 0; i < iBlockBytes; ++i)
1.383 + {
1.384 + iCurrentCipherTextPtr[i] = aBuffer[i];
1.385 + }
1.386 + }
1.387 + }
1.388 +
1.389 + inline void CSymmetricBlockCipherImpl::ModeDecryptEnd(TUint8* aBuffer)
1.390 + {
1.391 + __ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 2));
1.392 + if (iOperationMode.iUid == KOperationModeCBC)
1.393 + {
1.394 + // xor the output with the previous cipher text
1.395 + for (TInt i = 0; i < iBlockBytes; ++i)
1.396 + {
1.397 + aBuffer[i] ^= iRegisterPtr[i];
1.398 + iRegisterPtr[i] = iCurrentCipherTextPtr[i];
1.399 + }
1.400 + }
1.401 + }
1.402 + }
1.403 +
1.404 +#endif // __SYMMETRICCIPHERIMPL_H__