Symbian3/SDK/Source/GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485" xml:lang="en"><title>Symmetric
ciphers -- HowTo</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<ul>
<li id="GUID-0B38AF7B-D5D7-5A06-865D-76F056634C2A"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-119D039F-4624-5464-AA17-BBAB18A8D3CD">How do I use the symmetric cipher framework?</xref>  </p> </li>
<li id="GUID-6B472E69-7101-5AC2-B91C-E6FB3FEA067E"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-71CD8B41-219D-5D07-8C99-47D68668A880">Symmetric Modes</xref>  </p> </li>
<li id="GUID-3D8DF8E4-8839-51DB-9223-99931F01A7EB"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-86CD649D-3611-531A-8D9E-1FCC9728500B">Which symmetric cipher should I use?</xref>  </p> </li>
<li id="GUID-24318339-1B08-5CAF-8EE6-C512DA548670"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-3393A9D6-CB78-5740-B250-F9C1C26C59BD">How does buffering work within the symmetric cipher framework?</xref>  </p> </li>
</ul>
<section id="GUID-119D039F-4624-5464-AA17-BBAB18A8D3CD"><title>How do I use
the symmetric cipher framework? </title> <ul>
<li id="GUID-78AC1C88-612F-5D55-B357-497D637F20E1"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-21BCC641-FEE9-55FA-84E9-FF1EE425309F">An introduction to the symmetric cipher framework</xref>  </p> </li>
<li id="GUID-769B5855-9DA2-5E32-9270-B8F63D39366A"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-DFE76D85-7AD6-5B96-906B-98B3F63B88B7"><apiname>CSymmetricCipher</apiname> interface basics</xref>  </p> </li>
<li id="GUID-6EC9722D-DC7E-5DF8-A55F-D308C92DEC73"><p> <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-2018AFFC-09D9-5F99-BACC-8C77504E5CC3">Example code for a symmetric factory class</xref>  </p> </li>
</ul> <p id="GUID-21BCC641-FEE9-55FA-84E9-FF1EE425309F"><b> An introduction
to the symmetric cipher framework </b> </p> <p>The symmetric cipher framework
collates the behaviour of all symmetric ciphers under one interface: <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref>.
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. </p> <p id="GUID-DFE76D85-7AD6-5B96-906B-98B3F63B88B7"><b> CSymmetricCipher
interface basics </b> </p> <ul>
<li id="GUID-200B0A58-EA9D-5BC7-8EDF-625B2C43BE72"><p> <b> Block ciphers</b> --
Here one must create an underlying transformation (<xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita"><apiname>CBlockTransformation</apiname></xref>)
and create a <xref href="GUID-65F145BB-CE4B-3BCC-A9FC-5F9107F32488.dita"><apiname>CBufferedTransformation</apiname></xref> (which is an <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref>)
from that. </p> </li>
<li id="GUID-4D3532BB-58B1-5BF1-9253-B1FEE5917053"><p> <b> Stream ciphers</b> --
These have no concept of buffering and are treated as specializations of <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref>.
They require no intermediate container class. </p> </li>
</ul> <p>The following code illustrates the creation of a buffered AES ECB
encryptor and an ARC4 stream cipher. </p> <codeblock id="GUID-278C21E0-E3E1-5575-9C37-9530F08BB227" xml:space="preserve">
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 -&gt; both owned by cipher
</codeblock> <codeblock id="GUID-AC44907E-CD42-514A-AE39-D1981F3267FA" xml:space="preserve">
CSymmetricCipher* cipher = new(ELeave)CARC4(aKey);
CleanupStack::PushL(cipher):
</codeblock> <p>After creation, both examples are usable through the <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref> interface.
So, to encrypt with either of the above ciphers one could do: </p> <codeblock id="GUID-BF286466-ABBD-5810-801C-7C455CBE52FD" xml:space="preserve">
HBufC8* output = HBufC8::NewLC(cipher-&gt;MaxOutputLength(input.Size()));
cipher-&gt;Process(input, output);
HBufC8* output2 = HBufC8::NewLC(cipher-&gt;MaxFinalOutputLength(input2.Size()));
cipher-&gt;ProcessFinalL(input2, output2);
</codeblock> <p>In this example, <codeph>input</codeph> and <codeph>input2</codeph> are
two arbitrary, finite length descriptors. The derived implementations of <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref> (<xref href="GUID-8251F03D-D816-386E-A23A-947EEC6C8BC6.dita"><apiname>CBufferedEncryptor</apiname></xref> / <xref href="GUID-01CAF2BA-9120-304C-A488-5882CBD23EBC.dita"><apiname>CBufferedDecryptor</apiname></xref> and <xref href="GUID-40EFC716-0990-3C90-893E-43B3E6821C75.dita"><apiname>CStreamCipher</apiname></xref>)
are responsible for handling what to do in each specific case. For example,
in the case of an encrypting block cipher, <codeph>ProcessFinalL()</codeph> 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 <codeph>MaxOutputLength()</codeph> and <codeph>MaxFinalOutputLength()</codeph> are
calculated see <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-3393A9D6-CB78-5740-B250-F9C1C26C59BD">How
does buffering work within the symmetric cipher framework?</xref>. </p> <p id="GUID-2018AFFC-09D9-5F99-BACC-8C77504E5CC3"><b>Example code for a symmetric
factory class </b> </p> <p>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. </p> <codeblock id="GUID-EF0D121A-1961-5EF7-BA04-5BCE5DC029D4" xml:space="preserve">
CSymmetricCipher* CCipherFactory::BuildEncryptorL(
    TSymmetricCipherType aType,const TDesC8&amp; aKey,const TDesC8&amp; aIV)
    {
    CSymmetricCipher* cipher = NULL;

    if (aType==ERc4)
        {
        cipher = new(ELeave) CARC4(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;
    }
</codeblock> <p>Applications creating these factories need to supply an equivalent
to the <codeph>TSymmetricCipherType</codeph> enum, which contains the list
of identifiers representing the cipher, padding, and mode requirements of
the application. </p> <p>Note that a similar <codeph>BuildDecryptorL()</codeph> will
also have to be created. </p> <p>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. </p> </section>
<section id="GUID-71CD8B41-219D-5D07-8C99-47D68668A880"><title>Symmetric Modes </title> <p>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 <xref href="GUID-436C3EBE-FC60-3760-A3BA-D8DF8FA5B8AF.dita"><apiname>CBlockChainingMode</apiname></xref> class,
which is a specialization of <xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita"><apiname>CBlockTransformation</apiname></xref>. The
idea is that one gives an implementation of a <xref href="GUID-436C3EBE-FC60-3760-A3BA-D8DF8FA5B8AF.dita"><apiname>CBlockChainingMode</apiname></xref> another <xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita"><apiname>CBlockTransformation</apiname></xref> (<xref href="GUID-AE1A9AC0-DB79-3C62-AA23-896812F25F14.dita"><apiname>CAESEncryptor</apiname></xref>, for instance) and then performs all operations on the <xref href="GUID-436C3EBE-FC60-3760-A3BA-D8DF8FA5B8AF.dita"><apiname>CBlockChainingMode</apiname></xref> instance.
When <xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita#GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD/GUID-A4F36BDB-5FB3-3082-B362-30A59D13B104"><apiname>CBlockTransformation::Transform()</apiname></xref> is called on the
mode, it is responsible for calling <codeph>Transform()</codeph> on the underlying
transformation that it owns and then applying its own chaining mode transformation. </p> <p>The
following example shows how to create a buffered AES CBC encryptor. </p> <codeblock id="GUID-A3DFB7C2-D727-553C-9BF9-0E865417DBA3" xml:space="preserve">
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 -&gt; both owned by cipher
</codeblock> </section>
<section id="GUID-86CD649D-3611-531A-8D9E-1FCC9728500B"><title>Which symmetric
cipher should I use? </title> <p>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 (<xref href="GUID-AE1A9AC0-DB79-3C62-AA23-896812F25F14.dita"><apiname>CAESEncryptor</apiname></xref>); this is the cipher recommended
by <xref href="http://csrc.nist.gov/cryptval/" scope="external">NIST</xref>. </p> </section>
<section id="GUID-3393A9D6-CB78-5740-B250-F9C1C26C59BD"><title>How does buffering
work within the symmetric cipher framework? </title> <ul>
<li id="GUID-2A87BE74-9F27-5F0A-BA32-706FF5B1861B"><p> <b>Stream ciphers</b> consume
all content they are given. That is, the value returned from <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita#GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B/GUID-31976831-1620-3396-8E91-BBF934D4167D"><apiname>CSymmetricCipher::MaxOutputLength()</apiname></xref> is
always the same as the <codeph>aInputLength</codeph> parameter passed in. </p> </li>
<li id="GUID-E63F6682-E96F-5AB7-9786-E7F210B321ED"><p> <b>Block ciphers</b> controlled
through a <xref href="GUID-65F145BB-CE4B-3BCC-A9FC-5F9107F32488.dita"><apiname>CBufferedTransformation</apiname></xref> operate under the following
rules: </p> <ul>
<li id="GUID-3D963E44-1D4E-5505-9124-47DF2F145118"><p> <codeph>Process() </codeph>  </p> <ul id="GUID-943B86EF-01BD-53CB-B68F-507753850EC4">
<li id="GUID-271426C1-8E3E-5C95-8D55-1C3F2F2FC771"><p>Any previously buffered
data is (logically) prepended to <codeph>aInput</codeph>. </p> </li>
<li id="GUID-84C9BDF7-6BE5-5D02-9F00-1386F175757F"><p>All whole blocks are
transformed and appended to <codeph>aOutput</codeph>. </p> </li>
<li id="GUID-80FB971C-FAE8-576D-95A8-2762343B2B74"><p>Any remaining partial
blocks, orphaned by the above rule, are buffered. </p> </li>
</ul> </li>
<li id="GUID-93D49834-2716-5992-9B56-195813C3F4E0"><p> <codeph>ProcessFinalL()</codeph>  </p> <ul>
<li id="GUID-B5B476B7-EAC3-594C-B613-88900BB99654"><p>Encryption </p> <ol id="GUID-FD8C1EAA-3C8F-5034-ABAA-F4DFB6B2493A">
<li id="GUID-21579114-8456-573A-A79E-F8C84A7AFFCA"><p>Any previously buffered
data is (logically) prepended to <codeph>aInput</codeph>. </p> </li>
<li id="GUID-1C3199C1-41C1-5524-AD65-52D0F60816C1"><p>All whole block are
transformed and appended to <codeph>aOutput</codeph>. </p> </li>
<li id="GUID-7DF3B7AB-4C91-5C83-A963-5C18057AC8D3"><p>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). </p> </li>
<li id="GUID-6709F044-F7D7-5BBD-8816-9829ECBD8F17"><p>The resulting block(s)
are transformed and appended to <codeph>aOutput</codeph>. </p> </li>
</ol> </li>
<li id="GUID-1BD95B71-34F8-57D9-A882-9EE616A82512"><p>Decryption </p> <ol id="GUID-46984F1C-D4CA-5719-8235-CF22A3325B37">
<li id="GUID-3F4DABA6-9CFB-5F05-8B98-6F14CB64EFC4"><p>The input <b>must</b> be
a multiple of the block size. </p> </li>
<li id="GUID-A555D9FE-3211-521A-903E-5E22FF017FCE"><p>Data is decrypted and
unpadded using underlying padding system. </p> </li>
<li id="GUID-57C20E84-CF6C-5699-ABF0-D5080D8517A4"><p>Decrypted, unpadded
data is appended to <codeph>aOutput</codeph>. </p> </li>
</ol> </li>
</ul> </li>
</ul> </li>
</ul> <p>In all cases <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita#GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B/GUID-31976831-1620-3396-8E91-BBF934D4167D"><apiname>CSymmetricCipher::MaxOutputLength()</apiname></xref> returns
as tight an upper bound as possible on the number of bytes that will be returned
by a call to <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita#GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B/GUID-97E4F631-9CD5-3295-A22C-AAA5A4708FE9"><apiname>CSymmetricCipher::Process()</apiname></xref> with a specified
number of input bytes. Correspondingly, <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita#GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B/GUID-3675861D-0520-3F85-BA2B-AA3CF1964483"><apiname>CSymmetricCipher::MaxFinalOutputLength()</apiname></xref> returns
a similar bound but for a pending call to <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita#GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B/GUID-BE38C96D-F071-3385-8C7D-09BA4FC44432"><apiname>CSymmetricCipher::ProcessFinalL()</apiname></xref>. </p> </section>
</conbody></concept>