17
|
1 |
/*
|
|
2 |
* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of the License "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - initial contribution.
|
|
11 |
*
|
|
12 |
* Contributors:
|
|
13 |
*
|
|
14 |
* Description:
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
|
|
19 |
#ifndef __SYMMETRICCIPHERIMPL_H__
|
|
20 |
#define __SYMMETRICCIPHERIMPL_H__
|
|
21 |
|
|
22 |
/**
|
|
23 |
@file
|
|
24 |
@internalComponent
|
|
25 |
@released
|
|
26 |
*/
|
|
27 |
|
|
28 |
#include <e32base.h>
|
|
29 |
#include <e32cmn.h>
|
|
30 |
#include <cryptospi/cryptospidef.h>
|
|
31 |
#include <padding.h>
|
|
32 |
#include "symmetriccipherplugin.h"
|
|
33 |
|
|
34 |
/** The maximum block size supported (in bytes) */
|
|
35 |
const TUint KMaxBlockSizeSupported = 32;
|
|
36 |
|
|
37 |
/**
|
|
38 |
Abstract base class for symmetric cipher plug-ins.
|
|
39 |
*/
|
|
40 |
namespace SoftwareCrypto
|
|
41 |
{
|
|
42 |
using namespace CryptoSpi;
|
|
43 |
|
|
44 |
NONSHARABLE_CLASS(CSymmetricCipherImpl) : public CBase, public MSymmetricCipher
|
|
45 |
{
|
|
46 |
public:
|
|
47 |
/**
|
|
48 |
Implemented by each cipher subclass to determine whether the
|
|
49 |
specified key length is valid for that cipher.
|
|
50 |
This is called by ConstructL and SetKeyL
|
|
51 |
@param aKeyLength The key length in bytes to verify.
|
|
52 |
*/
|
|
53 |
virtual TBool IsValidKeyLength(TInt aKeyBytes) const = 0;
|
|
54 |
|
|
55 |
/**
|
|
56 |
Helper function implemented by concrete cipher sub-class that
|
|
57 |
allows GetCharacteristicsL to return the correct characteristics object.
|
|
58 |
@return The implemention uid
|
|
59 |
*/
|
|
60 |
virtual TUid ImplementationUid() const = 0;
|
|
61 |
|
|
62 |
/**
|
|
63 |
Gets the strength of the current key, needed to check whether the cipher
|
|
64 |
may operate if strong cryptography is not enabled.
|
|
65 |
@return The strength of the current key
|
|
66 |
*/
|
|
67 |
virtual TInt GetKeyStrength() const;
|
|
68 |
|
|
69 |
|
|
70 |
// Override MPlugin virtual functions
|
|
71 |
void Close();
|
|
72 |
TAny* GetExtension(TUid aExtensionId);
|
|
73 |
void GetCharacteristicsL(const TCharacteristics*& aPluginCharacteristics);
|
|
74 |
// End of MPlugin
|
|
75 |
|
|
76 |
// Override MSymmetricCipherBase virtual functions
|
|
77 |
TInt KeySize() const;
|
|
78 |
|
|
79 |
/// Destructor
|
|
80 |
~CSymmetricCipherImpl();
|
|
81 |
|
|
82 |
protected:
|
|
83 |
|
|
84 |
//Constructor
|
|
85 |
CSymmetricCipherImpl();
|
|
86 |
|
|
87 |
/**
|
|
88 |
Second phase of construction. Always call ConstructL in the super-class
|
|
89 |
if your override this method.
|
|
90 |
|
|
91 |
@param aKey The key to initialise the cipher with.
|
|
92 |
*/
|
|
93 |
virtual void ConstructL(const CKey& aKey);
|
|
94 |
|
|
95 |
/**
|
|
96 |
Extracts the raw symmetric key from a generic key object. The buffer
|
|
97 |
is placed on the cleanup stack.
|
|
98 |
|
|
99 |
@param aKey The key object
|
|
100 |
@return A buffer containing the raw key value
|
|
101 |
*/
|
|
102 |
HBufC8* ExtractKeyDataLC(const CKey& aKey) const;
|
|
103 |
|
|
104 |
/**
|
|
105 |
Zeros a buffer before deleting it to ensure that
|
|
106 |
the contents will not be visible to another process if the page
|
|
107 |
is re-used.
|
|
108 |
@param aBuffer The pointer (possibly null) to the buffer to delete. This
|
|
109 |
is set to null after deletion.
|
|
110 |
*/
|
|
111 |
void SecureDelete(HBufC8*& aBuffer);
|
|
112 |
|
|
113 |
/**
|
|
114 |
Extracts the raw key from aKey and sets iKey and iKeyBytes
|
|
115 |
The key length is also checked to meet export restrictions and
|
|
116 |
to ensure that it is appropriate for the cipher.
|
|
117 |
@param aKey The key
|
|
118 |
*/
|
|
119 |
virtual void DoSetKeyL(const CKey& aKey);
|
|
120 |
|
|
121 |
|
|
122 |
protected:
|
|
123 |
/// the key, extracted from a CKey object
|
|
124 |
HBufC8* iKey;
|
|
125 |
|
|
126 |
/// key size in bytes
|
|
127 |
TUint iKeyBytes;
|
|
128 |
|
|
129 |
};
|
|
130 |
|
|
131 |
NONSHARABLE_CLASS(CSymmetricStreamCipherImpl) : public CSymmetricCipherImpl
|
|
132 |
{
|
|
133 |
public:
|
|
134 |
// Destructor
|
|
135 |
~CSymmetricStreamCipherImpl();
|
|
136 |
|
|
137 |
// Override MSymmetricCipherBase virtual functions
|
|
138 |
TInt BlockSize() const;
|
|
139 |
void SetKeyL(const CKey& aKey); // override DoSetKeyL instead
|
|
140 |
void SetCryptoModeL(TUid aCryptoMode);
|
|
141 |
void SetOperationModeL(TUid aOperationMode);
|
|
142 |
void SetPaddingModeL(TUid aPaddingMode);
|
|
143 |
void SetIvL(const TDesC8& aIv);
|
|
144 |
TInt MaxOutputLength(TInt aInputLength) const;
|
|
145 |
TInt MaxFinalOutputLength(TInt aInputLength) const;
|
|
146 |
// End of MSymmetricCipherBase
|
|
147 |
|
|
148 |
// Override MSymmetricCipher virtual functions
|
|
149 |
void ProcessL(const TDesC8& aInput, TDes8& aOutput);
|
|
150 |
void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);
|
|
151 |
// End of MSymmetricCipher
|
|
152 |
|
|
153 |
protected:
|
|
154 |
// Constructor
|
|
155 |
CSymmetricStreamCipherImpl();
|
|
156 |
|
|
157 |
// Override CSymmetricCipherImpl virtual functions
|
|
158 |
virtual void ConstructL(const CKey& aKey);
|
|
159 |
|
|
160 |
/**
|
|
161 |
Performs an encryption or decryption on supplied data.
|
|
162 |
@param aData On input, data to be transformed;
|
|
163 |
on return, transformed data.
|
|
164 |
*/
|
|
165 |
virtual void DoProcess(TDes8& aData) = 0;
|
|
166 |
};
|
|
167 |
|
|
168 |
NONSHARABLE_CLASS(CSymmetricBlockCipherImpl) : public CSymmetricCipherImpl
|
|
169 |
{
|
|
170 |
public:
|
|
171 |
|
|
172 |
|
|
173 |
/**
|
|
174 |
This function is invoked by SetKey and SetCryptoMode
|
|
175 |
allowing the cipher sub-class to rebuild it's key schedule.
|
|
176 |
N.B. It is assumed that the key schedule is NOT modified
|
|
177 |
by TransformEncrypt or TransformDecrypt
|
|
178 |
*/
|
|
179 |
virtual void SetKeySchedule() = 0;
|
|
180 |
|
|
181 |
// Override MPlugin virtual functions
|
|
182 |
void Reset(); // Always call reset in super-class if you override this
|
|
183 |
// End of MPlugin virtual functions
|
|
184 |
|
|
185 |
// Override MSymmetricCipherBase virtual functions
|
|
186 |
TInt BlockSize() const;
|
|
187 |
void SetKeyL(const CKey& aKey); // override DoSetKeyL instead
|
|
188 |
void SetCryptoModeL(TUid aCryptoMode); // override DoSetCryptoModeL instead
|
|
189 |
void SetOperationModeL(TUid aOperationMode); // override DoSetOperationMode instead
|
|
190 |
void SetPaddingModeL(TUid aPaddingMode); // override DoSetPaddingModeL instead
|
|
191 |
void SetIvL(const TDesC8& aIv);
|
|
192 |
|
|
193 |
TInt MaxOutputLength(TInt aInputLength) const;
|
|
194 |
TInt MaxFinalOutputLength(TInt aInputLength) const;
|
|
195 |
// End of MSymmetricCipherBase
|
|
196 |
|
|
197 |
// Override MSymmetricCipher virtual functions
|
|
198 |
void ProcessL(const TDesC8& aInput, TDes8& aOutput);
|
|
199 |
void ProcessFinalL(const TDesC8& aInput, TDes8& aOutput);
|
|
200 |
// End of MSymmetricCipher
|
|
201 |
|
|
202 |
/// Destructor
|
|
203 |
~CSymmetricBlockCipherImpl();
|
|
204 |
protected:
|
|
205 |
/**
|
|
206 |
Constructor
|
|
207 |
@param aBlockBytes The block size in bytes
|
|
208 |
@param aOperationMode The mode of operation e.g. CBC
|
|
209 |
@param aCryptoMode Whether to encrypt or decrypt
|
|
210 |
*/
|
|
211 |
CSymmetricBlockCipherImpl(
|
|
212 |
TUint8 aBlockBytes,
|
|
213 |
TUid aOperationMode,
|
|
214 |
TUid aCryptoMode,
|
|
215 |
TUid aPaddingMode);
|
|
216 |
|
|
217 |
// Override CSymmetricCipherImpl virtual functions
|
|
218 |
virtual void ConstructL(const CKey& aKey);
|
|
219 |
|
|
220 |
/**
|
|
221 |
Validates and sets the crypto mode (iCryptoMode)
|
|
222 |
@param aCryptoMode The crypto mode
|
|
223 |
*/
|
|
224 |
virtual void DoSetCryptoModeL(TUid aCryptoMode);
|
|
225 |
|
|
226 |
/**
|
|
227 |
Validates and sets the operation mode (iOperationMode)
|
|
228 |
@param aOperationMode The operation mode
|
|
229 |
*/
|
|
230 |
virtual void DoSetOperationModeL(TUid aOperationMode);
|
|
231 |
|
|
232 |
/**
|
|
233 |
Validates and sets the padding mode (iPaddingMode & iPadding)
|
|
234 |
@param aPadding The desired padding mode
|
|
235 |
*/
|
|
236 |
virtual void DoSetPaddingModeL(TUid aPadding);
|
|
237 |
|
|
238 |
void DoSetIvL(const TDesC8& aIv);
|
|
239 |
|
|
240 |
inline void ModeEncryptStart(TUint8* aBuffer);
|
|
241 |
inline void ModeEncryptEnd(TUint8* aBuffer);
|
|
242 |
inline void ModeDecryptStart(TUint8* aBuffer);
|
|
243 |
inline void ModeDecryptEnd(TUint8* aBuffer);
|
|
244 |
|
|
245 |
private:
|
|
246 |
|
|
247 |
/**
|
|
248 |
Encrypts a number of blocks of data
|
|
249 |
|
|
250 |
@param aBuffer The buffer containing exactly aNumBlocks of data to destructively encrypt
|
|
251 |
@param aNumBlocks The number of blocks of data to encrypt
|
|
252 |
*/
|
|
253 |
virtual void TransformEncrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;
|
|
254 |
|
|
255 |
/**
|
|
256 |
Decrypts a number of blocks of data
|
|
257 |
|
|
258 |
@param aBuffer The buffer containing exactly aNumBlocks of data to destructively decrypt
|
|
259 |
@param aNumBlocks The number of blocks of data to decrypt
|
|
260 |
*/
|
|
261 |
virtual void TransformDecrypt(TUint8* aBuffer, TUint aNumBlocks) = 0;
|
|
262 |
|
|
263 |
/// Pad the last block and encrypt
|
|
264 |
void DoProcessFinalEncryptL(const TDesC8& aInput, TDes8& aOutput);
|
|
265 |
|
|
266 |
/// Decrypt and unpad the last block
|
|
267 |
void DoProcessFinalDecryptL(const TDesC8& aInput, TDes8& aOutput);
|
|
268 |
|
|
269 |
inline void Transform(TUint8* aBuffer, TUint aNumBlocks);
|
|
270 |
|
|
271 |
void ProcessCtrL(const TDesC8& aInput, TDes8& aOutput);
|
|
272 |
|
|
273 |
protected:
|
|
274 |
|
|
275 |
/// block size in bytes, current largest block size is 16 bytes (AES)
|
|
276 |
TUint8 iBlockBytes;
|
|
277 |
/// encryption or decryption
|
|
278 |
TUid iCryptoMode;
|
|
279 |
/// The block cipher mode e.g. ECB, CBC
|
|
280 |
TUid iOperationMode;
|
|
281 |
/// the current padding scheme
|
|
282 |
TUid iPaddingMode;
|
|
283 |
|
|
284 |
/// the initialisation vector
|
|
285 |
RBuf8 iIv;
|
|
286 |
|
|
287 |
/// current padding scheme implementation
|
|
288 |
CPadding* iPadding;
|
|
289 |
/// buffer to store blocks
|
|
290 |
RBuf8 iInputStore;
|
|
291 |
/// buffer to store input / output of padding
|
|
292 |
RBuf8 iPaddingBlock;
|
|
293 |
|
|
294 |
/// The current block of cipher text - for CBC
|
|
295 |
TUint32* iCurrentCipherText;
|
|
296 |
/// A pointer to the current block of cipher text
|
|
297 |
TUint8* iCurrentCipherTextPtr;
|
|
298 |
|
|
299 |
/** Used in both CBC and CTR mode. In CBC mode it stores the result of the last transform. In CTR mode
|
|
300 |
it stores the counter.*/
|
|
301 |
TUint32* iRegister;
|
|
302 |
/** A pointer to iRegister.*/
|
|
303 |
TUint8* iRegisterPtr;
|
|
304 |
|
|
305 |
/** Used in CTR mode to buffer plaintext during encryption.*/
|
|
306 |
HBufC8* iBufferedPlaintext;
|
|
307 |
/** Pointer to manipulate iBufferedPlaintext.*/
|
|
308 |
TPtr8 iBufferedPlaintextPtr;
|
|
309 |
|
|
310 |
/** CTR mode behaves like a stream cipher allowing arbitrary sized inputs to the encryption/decryption functions.
|
|
311 |
When handling an input whose length is not a multiple of the blocksize iCtrUnusedKeystream is used to buffer
|
|
312 |
the unused portions of keystream for use in the next call. Cleared in Reset().*/
|
|
313 |
HBufC8* iCtrUnusedKeystream;
|
|
314 |
/** Pointer to manipulate iCtrUnusedKeystream.*/
|
|
315 |
TPtr8 iCtrUnusedKeystreamPtr;
|
|
316 |
};
|
|
317 |
|
|
318 |
|
|
319 |
inline void CSymmetricBlockCipherImpl::Transform(TUint8* aBuffer, TUint aNumBlocks)
|
|
320 |
{
|
|
321 |
if (iCryptoMode.iUid == KCryptoModeEncrypt) //if in CTR mode always in crypto mode encrypt
|
|
322 |
{
|
|
323 |
TransformEncrypt(aBuffer, aNumBlocks);
|
|
324 |
}
|
|
325 |
else if (iCryptoMode.iUid == KCryptoModeDecrypt)
|
|
326 |
{
|
|
327 |
TransformDecrypt(aBuffer, aNumBlocks);
|
|
328 |
}
|
|
329 |
else
|
|
330 |
{
|
|
331 |
ASSERT(EFalse);
|
|
332 |
}
|
|
333 |
}
|
|
334 |
|
|
335 |
inline void CSymmetricBlockCipherImpl::ModeEncryptStart(TUint8* aBuffer)
|
|
336 |
{
|
|
337 |
if (iOperationMode.iUid == KOperationModeCBC)
|
|
338 |
{
|
|
339 |
for (TInt i = 0; i < iBlockBytes; ++i)
|
|
340 |
{
|
|
341 |
aBuffer[i] ^= iRegisterPtr[i];
|
|
342 |
}
|
|
343 |
}
|
|
344 |
else if (iOperationMode.iUid == KOperationModeCTR)
|
|
345 |
{
|
|
346 |
iBufferedPlaintextPtr.Copy(aBuffer, iBlockBytes);
|
|
347 |
Mem::Copy(aBuffer, iRegister, iBlockBytes);
|
|
348 |
}
|
|
349 |
}
|
|
350 |
|
|
351 |
inline void CSymmetricBlockCipherImpl::ModeEncryptEnd(TUint8* aBuffer)
|
|
352 |
{
|
|
353 |
if (iOperationMode.iUid == KOperationModeCBC)
|
|
354 |
{
|
|
355 |
for (TInt i = 0; i < iBlockBytes; ++i)
|
|
356 |
{
|
|
357 |
iRegisterPtr[i] = aBuffer[i];
|
|
358 |
}
|
|
359 |
}
|
|
360 |
else if (iOperationMode.iUid == KOperationModeCTR)
|
|
361 |
{
|
|
362 |
//XOR the plaintext with the keystream and increment counter
|
|
363 |
for (TInt i = 0; i < iBlockBytes; ++i)
|
|
364 |
{
|
|
365 |
aBuffer[i] ^= iBufferedPlaintextPtr[i];
|
|
366 |
}
|
|
367 |
for (TInt i = iBlockBytes - 1; i >= 0; --i)
|
|
368 |
{
|
|
369 |
if (++(iRegisterPtr[i]) != 0) break;
|
|
370 |
}
|
|
371 |
}
|
|
372 |
}
|
|
373 |
|
|
374 |
inline void CSymmetricBlockCipherImpl::ModeDecryptStart(TUint8* aBuffer)
|
|
375 |
{
|
|
376 |
__ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 1));
|
|
377 |
if (iOperationMode.iUid == KOperationModeCBC)
|
|
378 |
{
|
|
379 |
for (TInt i = 0; i < iBlockBytes; ++i)
|
|
380 |
{
|
|
381 |
iCurrentCipherTextPtr[i] = aBuffer[i];
|
|
382 |
}
|
|
383 |
}
|
|
384 |
}
|
|
385 |
|
|
386 |
inline void CSymmetricBlockCipherImpl::ModeDecryptEnd(TUint8* aBuffer)
|
|
387 |
{
|
|
388 |
__ASSERT_DEBUG((iOperationMode.iUid != KOperationModeCTR), User::Panic(_L("CSymmetricBlockCipherImpl.h"), 2));
|
|
389 |
if (iOperationMode.iUid == KOperationModeCBC)
|
|
390 |
{
|
|
391 |
// xor the output with the previous cipher text
|
|
392 |
for (TInt i = 0; i < iBlockBytes; ++i)
|
|
393 |
{
|
|
394 |
aBuffer[i] ^= iRegisterPtr[i];
|
|
395 |
iRegisterPtr[i] = iCurrentCipherTextPtr[i];
|
|
396 |
}
|
|
397 |
}
|
|
398 |
}
|
|
399 |
}
|
|
400 |
|
|
401 |
#endif // __SYMMETRICCIPHERIMPL_H__
|