--- /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>.
+*/