crypto/weakcrypto/docs/symmetric.dox
changeset 0 2c201484c85f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypto/weakcrypto/docs/symmetric.dox	Wed Jul 08 11:25:26 2009 +0100
@@ -0,0 +1,215 @@
+/**
+@page symmetric_ciphers Symmetric Cipher
+
+- @ref symmetricWhat
+- @ref symmetricHow
+- @ref symmetricModes
+- @ref symmetricWhich
+- @ref symmetricBuffering
+
+<hr>
+
+@section symmetricWhat What are symmetric ciphers?
+
+In an informal setting, symmetric ciphers can be thought of as a mapping of some
+plaintext to ciphertext, via some well-known transformation function, dependent
+on a secret key.  There are two basic types of symmetric ciphers:
+	- Stream ciphers -- These map an n-bit stream of plaintext to a n-bit stream of 
+	  ciphertext.
+	- Block ciphers -- These map m n-bit blocks of plaintext to m n-bit blocks
+	  of ciphertext.  Because the base unit of transformation is the n-bit
+	  block, messages that are not exactly divisible by n must be padded (\c CPadding) 
+	  to allow for their encryption.  Optionally, instead of padding out a
+	  plaintext message to fit in a block, block ciphers allow buffering of
+	  partial input blocks until the remainder of the block is given as input.
+	  (@ref symmetricBuffering).  Finally, block ciphers have a concept of modes
+	  (@ref symmetricModes) that provide a mechanism for making subsequent
+	  blocks dependent on some number of previous blocks.
+
+<hr>
+@section symmetricHow How do I use the symmetric cipher framework?
+
+- @ref symmetricHowIntro
+- @ref symmetricHowInterface
+- @ref symmetricHowFactory
+
+@subsection symmetricHowIntro An introduction to the symmetric cipher framework.
+The symmetric cipher framework collates the behaviour of all symmetric ciphers
+under one interface: \c CSymmetricCipher.  This interface is intended to represent
+one direction of one instance of any symmetric cipher.  One direction means
+either encryption or decryption, but not both.
+	  
+@subsection symmetricHowInterface CSymmetricCipher interface basics.
+- Block ciphers -- Here one must create an underlying transformation (\c
+  CBlockTransformation) and create a \c CBufferedTransformation (which is an
+  \c CSymmetricCipher) from that.  
+- Stream ciphers -- These have no concept of buffering and are treated as
+  specialisations of \c CSymmetricCipher.  They require no intermediate container
+  class.  
+	  
+The following code illustrates the creation of a buffered AES ECB encryptor and an
+ARC4 stream cipher.  
+
+@code
+CBlockTransformation* block = 0;
+block = CAESEncryptor::NewLC(aKey);
+CPadding* padding = CPaddingSSLv3::NewLC(KAESBlockSize); //The blocksize of AES (16 bytes)
+CSymmetricCipher* cipher = CBufferedEncryptor::NewL(block, padding);
+CleanupStack::Pop(2, block); //padding, block -> both owned by cipher
+@endcode
+
+@code
+CSymmetricCipher* cipher = new(ELeave)TARC4(aKey);
+CleanupStack::PushL(cipher):
+@endcode
+
+After creation, both examples are usable through the \c CSymmetricCipher interface.
+So, to encrypt with either of the above ciphers one could do:
+
+@code
+HBufC8* output = HBufC8::NewLC(cipher->MaxOutputLength(input.Size()));
+cipher->Process(input, output);
+HBufC8* output2 = HBufC8::NewLC(cipher->MaxFinalOutputLength(input2.Size()));
+cipher->ProcessFinalL(input2, output2);
+@endcode
+
+In this example, \c input and \c input2 are two arbitrary, finite length descriptors.
+The derived implementations of \c CSymmetricCipher (\c CBufferedEncryptor / \c CBufferedDecryptor
+and \c CStreamCipher) are responsible for handling what to do in each specific
+case.  For example, in the case of an encrypting block cipher, \c ProcessFinalL()
+will call the underlying padding system, which will in turn ensure that the
+overall length of input plaintext is of a suitable length for encryption. For more
+information on how the values returned from \c MaxOutputLength() and
+\c MaxFinalOutputLength() are calculated see @ref symmetricBuffering.
+
+@subsection symmetricHowFactory Example code for a symmetric factory class.
+
+To simplify the process of creating symmetric encryptors and decryptors, it is
+strongly recommended that applications create a factory that automates the
+process for them.  The following code gives a sample factory that applications
+might like to use as a reference.  It is not supplied as part of the framework
+as every application has different ways of identifying symmetric cipher suites.
+
+@code
+CSymmetricCipher* CCipherFactory::BuildEncryptorL(
+	TSymmetricCipherType aType,const TDesC8& aKey,const TDesC8& aIV)
+	{
+	CSymmetricCipher* cipher = NULL;
+
+	if (aType==ERc4)
+		{
+		cipher = new(ELeave) TARC4(aKey);
+		}
+	else
+		{
+		CBlockTransformation* bT = NULL;
+		switch (aType)
+			{
+			case EDes_cbc:
+				bT = CDESEncryptor::NewL(aKey);
+				break;
+			case EDes_ede3_cbc:
+				bT = C3DESEncryptor::NewL(aKey);
+				break;
+			case ERc2_cbc:
+				bT = CRC2Encryptor::NewL(aKey);
+				break;
+			default:
+				User::Leave(KErrNotSupported);
+			};
+		CleanupStack::PushL(bT);
+		CBlockTransformation* mode = CModeCBCEncryptor::NewL(bT, aIV);
+		CleanupStack::Pop(bT);	//	owned by mode
+		CleanupStack::PushL(mode);
+	 
+		CPadding* padding = CPaddingSSLv3::NewLC(KBlockSize); //All of these ciphers use 8 byte blocks
+		cipher = CBufferedEncryptor::NewL(mode, padding);
+		CleanupStack::Pop(2, mode);	//padding, mode	now owned by cipher
+		}
+	return cipher;
+	}
+@endcode
+
+Applications creating these factories need to supply an equivalent to the
+\c TSymmetricCipherType enum which contains the list of identifiers representing
+the cipher, padding, and mode requirements of the application.  
+
+Note that a similar \c BuildDecryptorL() will also have to be created.
+
+Good naming conventions dictate that applications should not pollute the
+global namespace and either use their own namespace or prefix their factory
+classes with identifiers that associated it with that specific application.
+	 
+<hr>
+@section symmetricModes Symmetric Modes
+
+When the amount of plaintext to be encrypted is larger than a single block, some
+method must be employed to specify how subsequent blocks are dependent on
+previous blocks.  The simplest method, known as ECB (Electronic CodeBook),
+specifies that subsequent blocks are completely independent.  Therefore, two
+identical blocks of plaintext will encrypt to two identical blocks of
+ciphertext.  ECB has significant security drawbacks, thus most applications use
+more advanced modes in which subsequent blocks are dependent on the ciphertext
+of previous blocks.  The symmetric framework handles these modes through the
+\c CBlockChainingMode class, which is a specialisation of \c CBlockTransformation.
+The idea is that one gives an implementation of a \c CBlockChainingMode another
+\c CBlockTransformation (\c CAESEncryptor, for instance) and then performs all
+operations on the \c CBlockChainingMode instance.  When
+<code>CBlockTransformation::Transform()</code> is called on the mode it is responsible for
+calling \c Transform() on the underlying transformation that it owns and then
+applying its own chaining mode transformation.
+
+The following example shows how to create a buffered AES CBC encryptor.
+
+@code
+CBlockTransformation* basicAesBlock = 0;
+CBlockTransformation* cbcBlock = 0;
+basicAesBlock = CAESEncryptor::NewLC(aKey);
+cbcBlock = CModeCBCEncryptor::NewL(basicAesBlock, iv);
+CleanupStack::Pop(basicAesBlock); //owned by cbcBlock
+CleanupStack::PushL(cbcBlock);
+CPadding* padding = CPaddingSSLv3::NewLC(KAESBlockSize); //The blocksize of AES (16 bytes)
+CSymmetricCipher* cipher = CBufferedEncryptor::NewL(cbcBlock, padding);
+CleanupStack::Pop(2, cbcBlock); //padding, cbcBlock -> both owned by cipher
+@endcode
+
+<hr>
+@section symmetricWhich Which symmetric cipher should I use?  
+Generally, when implementing secure comms protocols, the cipher you use will be
+dictated by the protocol specification.  However, if you are writing your own
+application you should consider the use of AES (CAESEncryptor).  This is the
+cipher recommended by <A HREF="http://csrc.nist.gov/cryptval/">NIST</A>.
+
+<hr>
+@section symmetricBuffering How does buffering work within the symmetric cipher framework?  
+
+- Stream ciphers consume all content they are given.  That is, the value
+  returned from <code>CSymmetricCipher::MaxOutputLength()</code> is always the same as the
+  \c aInputLength parameter passed in.
+- Block ciphers controlled through a \c CBufferedTransformation operate under the
+  following rules:
+  	- \c Process()
+		-# Any previously buffered data is (logically) prepended to \c aInput.
+		-# All whole blocks are transformed and appended to \c aOutput.
+		-# Any remaining partial blocks, orphaned by the the above rule, are
+		buffered.
+	- \c ProcessFinalL()
+		- Encryption
+			-# Any previously buffered data is (logically) prepended to \c aInput.
+			-# All whole block are transformed and appended to \c aOutput.
+			-# Any remaining partial blocks are padded with underlying padding
+			system to be block aligned <I>to the padding block size</I>. (In the
+			vast majority of cases, the padding block size is equal to the
+			block cipher block size).
+			-# The resulting block(s) are transformed and appended to \c aOutput.
+		- Decryption
+			-# The input <b>must</b> be a multiple of the block size.
+			-# Data is decrypted and unpadded using underlying padding system.
+			-# Decrypted, unpadded data is appended to \c aOutput.
+
+In all cases <code>CSymmetricCipher::MaxOutputLength()</code> returns as tight an upper bound
+as possible on the number of bytes that will be returned by a call to
+<code>CSymmetricCipher::Process()</code> with a specified number of input bytes.
+Correspondingly, <code>CSymmetricCipher::MaxFinalOutputLength()</code> returns a similar
+bound but for a pending call to <code>CSymmetricCipher::ProcessFinalL()</code>.
+*/