|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485" xml:lang="en"><title>Symmetric |
|
13 ciphers -- HowTo</title><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <ul> |
|
15 <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> |
|
16 <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> |
|
17 <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> |
|
18 <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> |
|
19 </ul> |
|
20 <section id="GUID-119D039F-4624-5464-AA17-BBAB18A8D3CD"><title>How do I use |
|
21 the symmetric cipher framework? </title> <ul> |
|
22 <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> |
|
23 <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> |
|
24 <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> |
|
25 </ul> <p id="GUID-21BCC641-FEE9-55FA-84E9-FF1EE425309F"><b> An introduction |
|
26 to the symmetric cipher framework </b> </p> <p>The symmetric cipher framework |
|
27 collates the behaviour of all symmetric ciphers under one interface: <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref>. |
|
28 This interface is intended to represent one direction of one instance of any |
|
29 symmetric cipher. One direction means either encryption or decryption, but |
|
30 not both. </p> <p id="GUID-DFE76D85-7AD6-5B96-906B-98B3F63B88B7"><b> CSymmetricCipher |
|
31 interface basics </b> </p> <ul> |
|
32 <li id="GUID-200B0A58-EA9D-5BC7-8EDF-625B2C43BE72"><p> <b> Block ciphers</b> -- |
|
33 Here one must create an underlying transformation (<xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita"><apiname>CBlockTransformation</apiname></xref>) |
|
34 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>) |
|
35 from that. </p> </li> |
|
36 <li id="GUID-4D3532BB-58B1-5BF1-9253-B1FEE5917053"><p> <b> Stream ciphers</b> -- |
|
37 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>. |
|
38 They require no intermediate container class. </p> </li> |
|
39 </ul> <p>The following code illustrates the creation of a buffered AES ECB |
|
40 encryptor and an ARC4 stream cipher. </p> <codeblock id="GUID-278C21E0-E3E1-5575-9C37-9530F08BB227" xml:space="preserve"> |
|
41 CBlockTransformation* block = 0; |
|
42 block = CAESEncryptor::NewLC(aKey); |
|
43 CPadding* padding = CPaddingSSLv3::NewLC(KAESBlockSize); //The blocksize of AES (16 bytes) |
|
44 CSymmetricCipher* cipher = CBufferedEncryptor::NewL(block, padding); |
|
45 CleanupStack::Pop(2, block); //padding, block -> both owned by cipher |
|
46 </codeblock> <codeblock id="GUID-AC44907E-CD42-514A-AE39-D1981F3267FA" xml:space="preserve"> |
|
47 CSymmetricCipher* cipher = new(ELeave)CARC4(aKey); |
|
48 CleanupStack::PushL(cipher): |
|
49 </codeblock> <p>After creation, both examples are usable through the <xref href="GUID-F4E08165-A654-3D32-8FED-7ED54BDAD88B.dita"><apiname>CSymmetricCipher</apiname></xref> interface. |
|
50 So, to encrypt with either of the above ciphers one could do: </p> <codeblock id="GUID-BF286466-ABBD-5810-801C-7C455CBE52FD" xml:space="preserve"> |
|
51 HBufC8* output = HBufC8::NewLC(cipher->MaxOutputLength(input.Size())); |
|
52 cipher->Process(input, output); |
|
53 HBufC8* output2 = HBufC8::NewLC(cipher->MaxFinalOutputLength(input2.Size())); |
|
54 cipher->ProcessFinalL(input2, output2); |
|
55 </codeblock> <p>In this example, <codeph>input</codeph> and <codeph>input2</codeph> are |
|
56 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>) |
|
57 are responsible for handling what to do in each specific case. For example, |
|
58 in the case of an encrypting block cipher, <codeph>ProcessFinalL()</codeph> will |
|
59 call the underlying padding system, which will in turn ensure that the overall |
|
60 length of input plaintext is of a suitable length for encryption. For more |
|
61 information on how the values returned from <codeph>MaxOutputLength()</codeph> and <codeph>MaxFinalOutputLength()</codeph> are |
|
62 calculated see <xref href="GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485.dita#GUID-CFF1BCCA-5D07-5B8A-9363-AD11EEEAB485/GUID-3393A9D6-CB78-5740-B250-F9C1C26C59BD">How |
|
63 does buffering work within the symmetric cipher framework?</xref>. </p> <p id="GUID-2018AFFC-09D9-5F99-BACC-8C77504E5CC3"><b>Example code for a symmetric |
|
64 factory class </b> </p> <p>To simplify the process of creating symmetric encryptors |
|
65 and decryptors, it is strongly recommended that applications create a factory |
|
66 that automates the process for them. The following code gives a sample factory |
|
67 that applications might like to use as a reference. It is not supplied as |
|
68 part of the framework as every application has different ways of identifying |
|
69 symmetric cipher suites. </p> <codeblock id="GUID-EF0D121A-1961-5EF7-BA04-5BCE5DC029D4" xml:space="preserve"> |
|
70 CSymmetricCipher* CCipherFactory::BuildEncryptorL( |
|
71 TSymmetricCipherType aType,const TDesC8& aKey,const TDesC8& aIV) |
|
72 { |
|
73 CSymmetricCipher* cipher = NULL; |
|
74 |
|
75 if (aType==ERc4) |
|
76 { |
|
77 cipher = new(ELeave) CARC4(aKey); |
|
78 } |
|
79 else |
|
80 { |
|
81 CBlockTransformation* bT = NULL; |
|
82 switch (aType) |
|
83 { |
|
84 case EDes_cbc: |
|
85 bT = CDESEncryptor::NewL(aKey); |
|
86 break; |
|
87 case EDes_ede3_cbc: |
|
88 bT = C3DESEncryptor::NewL(aKey); |
|
89 break; |
|
90 case ERc2_cbc: |
|
91 bT = CRC2Encryptor::NewL(aKey); |
|
92 break; |
|
93 default: |
|
94 User::Leave(KErrNotSupported); |
|
95 }; |
|
96 CleanupStack::PushL(bT); |
|
97 CBlockTransformation* mode = CModeCBCEncryptor::NewL(bT, aIV); |
|
98 CleanupStack::Pop(bT); // owned by mode |
|
99 CleanupStack::PushL(mode); |
|
100 |
|
101 CPadding* padding = CPaddingSSLv3::NewLC(KBlockSize); //All of these ciphers use 8 byte blocks |
|
102 cipher = CBufferedEncryptor::NewL(mode, padding); |
|
103 CleanupStack::Pop(2, mode); //padding, mode now owned by cipher |
|
104 } |
|
105 return cipher; |
|
106 } |
|
107 </codeblock> <p>Applications creating these factories need to supply an equivalent |
|
108 to the <codeph>TSymmetricCipherType</codeph> enum, which contains the list |
|
109 of identifiers representing the cipher, padding, and mode requirements of |
|
110 the application. </p> <p>Note that a similar <codeph>BuildDecryptorL()</codeph> will |
|
111 also have to be created. </p> <p>Good naming conventions dictate that applications |
|
112 should not pollute the global namespace and either use their own namespace |
|
113 or prefix their factory classes with identifiers that associated it with that |
|
114 specific application. </p> </section> |
|
115 <section id="GUID-71CD8B41-219D-5D07-8C99-47D68668A880"><title>Symmetric Modes </title> <p>When |
|
116 the amount of plaintext to be encrypted is larger than a single block, some |
|
117 method must be employed to specify how subsequent blocks are dependent on |
|
118 previous blocks. The simplest method, known as ECB (Electronic CodeBook), |
|
119 specifies that subsequent blocks are completely independent. Therefore, two |
|
120 identical blocks of plaintext will encrypt to two identical blocks of ciphertext. |
|
121 ECB has significant security drawbacks, thus most applications use more advanced |
|
122 modes in which subsequent blocks are dependent on the ciphertext of previous |
|
123 blocks. The symmetric framework handles these modes through the <xref href="GUID-436C3EBE-FC60-3760-A3BA-D8DF8FA5B8AF.dita"><apiname>CBlockChainingMode</apiname></xref> class, |
|
124 which is a specialization of <xref href="GUID-CFDA5321-EE13-3203-8DED-71E69D4469BD.dita"><apiname>CBlockTransformation</apiname></xref>. The |
|
125 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. |
|
126 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 |
|
127 mode, it is responsible for calling <codeph>Transform()</codeph> on the underlying |
|
128 transformation that it owns and then applying its own chaining mode transformation. </p> <p>The |
|
129 following example shows how to create a buffered AES CBC encryptor. </p> <codeblock id="GUID-A3DFB7C2-D727-553C-9BF9-0E865417DBA3" xml:space="preserve"> |
|
130 CBlockTransformation* basicAesBlock = 0; |
|
131 CBlockTransformation* cbcBlock = 0; |
|
132 basicAesBlock = CAESEncryptor::NewLC(aKey); |
|
133 cbcBlock = CModeCBCEncryptor::NewL(basicAesBlock, iv); |
|
134 CleanupStack::Pop(basicAesBlock); //owned by cbcBlock |
|
135 CleanupStack::PushL(cbcBlock); |
|
136 CPadding* padding = CPaddingSSLv3::NewLC(KAESBlockSize); //The blocksize of AES (16 bytes) |
|
137 CSymmetricCipher* cipher = CBufferedEncryptor::NewL(cbcBlock, padding); |
|
138 CleanupStack::Pop(2, cbcBlock); //padding, cbcBlock -> both owned by cipher |
|
139 </codeblock> </section> |
|
140 <section id="GUID-86CD649D-3611-531A-8D9E-1FCC9728500B"><title>Which symmetric |
|
141 cipher should I use? </title> <p>Generally, when implementing secure comms |
|
142 protocols, the cipher you use will be dictated by the protocol specification. |
|
143 However, if you are writing your own application, you should consider the |
|
144 use of AES (<xref href="GUID-AE1A9AC0-DB79-3C62-AA23-896812F25F14.dita"><apiname>CAESEncryptor</apiname></xref>); this is the cipher recommended |
|
145 by <xref href="http://csrc.nist.gov/cryptval/" scope="external">NIST</xref>. </p> </section> |
|
146 <section id="GUID-3393A9D6-CB78-5740-B250-F9C1C26C59BD"><title>How does buffering |
|
147 work within the symmetric cipher framework? </title> <ul> |
|
148 <li id="GUID-2A87BE74-9F27-5F0A-BA32-706FF5B1861B"><p> <b>Stream ciphers</b> consume |
|
149 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 |
|
150 always the same as the <codeph>aInputLength</codeph> parameter passed in. </p> </li> |
|
151 <li id="GUID-E63F6682-E96F-5AB7-9786-E7F210B321ED"><p> <b>Block ciphers</b> controlled |
|
152 through a <xref href="GUID-65F145BB-CE4B-3BCC-A9FC-5F9107F32488.dita"><apiname>CBufferedTransformation</apiname></xref> operate under the following |
|
153 rules: </p> <ul> |
|
154 <li id="GUID-3D963E44-1D4E-5505-9124-47DF2F145118"><p> <codeph>Process() </codeph> </p> <ul id="GUID-943B86EF-01BD-53CB-B68F-507753850EC4"> |
|
155 <li id="GUID-271426C1-8E3E-5C95-8D55-1C3F2F2FC771"><p>Any previously buffered |
|
156 data is (logically) prepended to <codeph>aInput</codeph>. </p> </li> |
|
157 <li id="GUID-84C9BDF7-6BE5-5D02-9F00-1386F175757F"><p>All whole blocks are |
|
158 transformed and appended to <codeph>aOutput</codeph>. </p> </li> |
|
159 <li id="GUID-80FB971C-FAE8-576D-95A8-2762343B2B74"><p>Any remaining partial |
|
160 blocks, orphaned by the above rule, are buffered. </p> </li> |
|
161 </ul> </li> |
|
162 <li id="GUID-93D49834-2716-5992-9B56-195813C3F4E0"><p> <codeph>ProcessFinalL()</codeph> </p> <ul> |
|
163 <li id="GUID-B5B476B7-EAC3-594C-B613-88900BB99654"><p>Encryption </p> <ol id="GUID-FD8C1EAA-3C8F-5034-ABAA-F4DFB6B2493A"> |
|
164 <li id="GUID-21579114-8456-573A-A79E-F8C84A7AFFCA"><p>Any previously buffered |
|
165 data is (logically) prepended to <codeph>aInput</codeph>. </p> </li> |
|
166 <li id="GUID-1C3199C1-41C1-5524-AD65-52D0F60816C1"><p>All whole block are |
|
167 transformed and appended to <codeph>aOutput</codeph>. </p> </li> |
|
168 <li id="GUID-7DF3B7AB-4C91-5C83-A963-5C18057AC8D3"><p>Any remaining partial |
|
169 blocks are padded with underlying padding system to be block aligned <i>to |
|
170 the padding block size</i>. (In the vast majority of cases, the padding block |
|
171 size is equal to the block cipher block size). </p> </li> |
|
172 <li id="GUID-6709F044-F7D7-5BBD-8816-9829ECBD8F17"><p>The resulting block(s) |
|
173 are transformed and appended to <codeph>aOutput</codeph>. </p> </li> |
|
174 </ol> </li> |
|
175 <li id="GUID-1BD95B71-34F8-57D9-A882-9EE616A82512"><p>Decryption </p> <ol id="GUID-46984F1C-D4CA-5719-8235-CF22A3325B37"> |
|
176 <li id="GUID-3F4DABA6-9CFB-5F05-8B98-6F14CB64EFC4"><p>The input <b>must</b> be |
|
177 a multiple of the block size. </p> </li> |
|
178 <li id="GUID-A555D9FE-3211-521A-903E-5E22FF017FCE"><p>Data is decrypted and |
|
179 unpadded using underlying padding system. </p> </li> |
|
180 <li id="GUID-57C20E84-CF6C-5699-ABF0-D5080D8517A4"><p>Decrypted, unpadded |
|
181 data is appended to <codeph>aOutput</codeph>. </p> </li> |
|
182 </ol> </li> |
|
183 </ul> </li> |
|
184 </ul> </li> |
|
185 </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 |
|
186 as tight an upper bound as possible on the number of bytes that will be returned |
|
187 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 |
|
188 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 |
|
189 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> |
|
190 </conbody></concept> |