Update contrib.
2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Software Mac Implementation
25 #include "pluginconfig.h"
26 #include <cryptospi/cryptomacapi.h>
28 * Headers from CryptoSpi framework
30 #include <cryptospi/cryptospidef.h>
32 using namespace SoftwareCrypto;
33 using namespace CryptoSpi;
36 * Constants used to generate Key1, Key2 and Key3
38 const TUint8 K1Constant[] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
39 const TUint8 K2Constant[] = {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
40 const TUint8 K3Constant[] = {0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
42 const TInt KAesXcbcMac96Size = 12;
45 CCMacImpl* CCMacImpl::NewL(const CKey& aKey, CSymmetricCipher* aSymmetricCipher, TInt32 aAlgorithmUid)
47 CCMacImpl* self = CCMacImpl::NewLC(aKey, aSymmetricCipher, aAlgorithmUid);
48 CleanupStack::Pop(self);
52 CCMacImpl* CCMacImpl::NewLC(const CKey& aKey, CSymmetricCipher* aSymmetricCipher, TInt32 aAlgorithmUid)
54 CCMacImpl* self = NULL;
55 TRAPD(err, self = new (ELeave) CCMacImpl(aSymmetricCipher));
58 delete aSymmetricCipher;
61 CleanupStack::PushL(self);
62 self->ConstructL(aKey, aAlgorithmUid);
66 CKey* CCMacImpl::Create128bitKeyL(const CKey& aKey)
68 TBuf8<KMacBlockSize> keybuffer;
69 CryptoSpi::CKey* key = NULL;
71 const TDesC8& keyContent=aKey.GetTDesC8L(CryptoSpi::KSymmetricKeyParameterUid);
73 if( (TUint32)keyContent.Size() > KMacBlockSize)
76 CryptoSpi::CCryptoParams* keyParams = CryptoSpi::CCryptoParams::NewLC();
77 keybuffer.SetLength(KMacBlockSize);
79 // 'keybuffer' is the key with 128 zero bits.
80 keyParams->AddL(keybuffer, CryptoSpi::KSymmetricKeyParameterUid);
81 key=CryptoSpi::CKey::NewLC(aKey.KeyProperty(),*keyParams);
82 // evaluate final key data.
84 CleanupStack::PopAndDestroy(2, keyParams);
85 keybuffer.Copy(FinalL(keyContent));
86 // 'keybuffer' contains the final key data.
90 keybuffer.Copy(keyContent);
92 for (i=keybuffer.Size();i<KMacBlockSize;++i)
96 // 'keybuffer' contains the final key data.
99 // create a new CKey instance and assign it to iKey using 'keybuffer'.
100 CryptoSpi::CCryptoParams* keyParams = CryptoSpi::CCryptoParams::NewLC();
101 keyParams->AddL(keybuffer, CryptoSpi::KSymmetricKeyParameterUid);
102 key=CryptoSpi::CKey::NewL(aKey.KeyProperty(),*keyParams);
103 CleanupStack::PopAndDestroy(keyParams);
105 // 'key' will contain the final CKey instance.
109 void CCMacImpl::SetKeyL(const CKey& aKey)
111 const TPtrC8 KeyConstant1(K1Constant, KMacBlockSize);
112 const TPtrC8 KeyConstant2(K2Constant, KMacBlockSize);
113 const TPtrC8 KeyConstant3(K3Constant, KMacBlockSize);
115 // Initialize the cipher class to encrypt Keyconstants to generate additional keys.
116 if (iImplementationUid == CryptoSpi::KAlgorithmCipherAesXcbcPrf128)
118 // RFC 4434: keys that were not equal in length to 128 bits will no longer be
119 // rejected but instead will be made 128 bits for AES-XCBC-PRF-128 Algorithm only.
120 CryptoSpi::CKey* key = Create128bitKeyL(aKey);
121 CleanupStack::PushL(key);
122 iCipherImpl->SetKeyL(*key);
123 CleanupStack::PopAndDestroy(key);
127 iCipherImpl->SetKeyL(aKey);
129 iCipherImpl->SetCryptoModeL(CryptoSpi::KCryptoModeEncryptUid);
130 iCipherImpl->SetOperationModeL(CryptoSpi::KOperationModeNoneUid);
132 // cipher class expects the output buffer to be empty.
137 // aKey is used to generate Key1, Key2 and Key3.
138 // Where Key1 = encrypt KeyConstant1 with aKey
139 // Where Key2 = encrypt KeyConstant2 with aKey
140 // Where Key3 = encrypt KeyConstant3 with aKey
142 // Key1 is used to encrypt the data whereas
143 // Key2 and Key3 is used to XOR with the last
145 iCipherImpl->ProcessFinalL(KeyConstant1, iKey1);
146 iCipherImpl->ProcessFinalL(KeyConstant2, iKey2);
147 iCipherImpl->ProcessFinalL(KeyConstant3, iKey3);
149 // Create CKey instance with key1
150 CCryptoParams* keyParam =CCryptoParams::NewLC();
151 keyParam->AddL(iKey1, CryptoSpi::KSymmetricKeyParameterUid);
155 iKey=CKey::NewL(aKey.KeyProperty(), *keyParam);
156 // Initialize the cipher class for MAC calculation.
157 iCipherImpl->SetKeyL(*iKey);
158 iCipherImpl->SetOperationModeL(CryptoSpi::KOperationModeCBCUid);
159 Mem::FillZ(iE, sizeof(iE));
160 iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize));
162 CleanupStack::PopAndDestroy(keyParam);
165 CCMacImpl::~CCMacImpl()
171 CCMacImpl::CCMacImpl(const CCMacImpl& aCCMacImpl)
173 iImplementationUid = aCCMacImpl.iImplementationUid;
174 iKey1.Copy(aCCMacImpl.iKey1);
175 iKey2.Copy(aCCMacImpl.iKey2);
176 iKey3.Copy(aCCMacImpl.iKey3);
178 (void)Mem::Copy(iE, aCCMacImpl.iE, sizeof(iE));
179 (void)Mem::Copy(iData, aCCMacImpl.iData, sizeof(iData));
181 iCurrentTotalLength = aCCMacImpl.iCurrentTotalLength;
184 const CExtendedCharacteristics* CCMacImpl::GetExtendedCharacteristicsL()
186 return iCipherImpl->GetExtendedCharacteristicsL();
189 CCMacImpl::CCMacImpl(CryptoSpi::CSymmetricCipher* aSymmetricCipher)
191 iCipherImpl = aSymmetricCipher;
192 aSymmetricCipher = NULL;
193 iMacValue.SetLength(KMacBlockSize);
196 void CCMacImpl::ConstructL(const CKey& aKey, TInt32 aAlgorithmUid)
198 iImplementationUid = aAlgorithmUid;
200 switch(aAlgorithmUid)
202 case CryptoSpi::KAlgorithmCipherAesXcbcMac96:
203 case CryptoSpi::KAlgorithmCipherAesXcbcPrf128:
210 User::Leave(KErrNotSupported);
216 * Takes the message and XOR it with iData.
218 * @param aKey 128bit key. This key will be XORed with iData.
219 * @param aOutput The result of the XOR operation will be copied to this.
220 * Its length should be 128bit (16bytes).
223 void CCMacImpl::XORKeyWithData(const TDesC8& aKey, TDes8& aOutput)
225 for (TInt i = 0; i < KMacBlockSize; ++i)
227 aOutput[i] = iData[i] ^ aKey[i];
232 * This function is used to pad message M to make the total message
233 * length multiple of block size (128bit). The last block M[n] will be
234 * padded with a single "1" bit followed by the number of "0" bits required
235 * to increase M[n]'s size to 128 bits (Block Size).
237 * Used in AES-XCBC-MAC-96 and AES-XCBC-PRF-128 Mac algorithms.
239 void CCMacImpl::PadMessage()
241 if(iCurrentTotalLength < KMacBlockSize)
243 iData[iCurrentTotalLength] = 0x80;
244 Mem::FillZ(iData + iCurrentTotalLength+1, KMacBlockSize - iCurrentTotalLength - 1);
248 void CCMacImpl::Reset()
250 Mem::FillZ(iE,sizeof(iE));
251 iCurrentTotalLength =0;
252 // record for Reset, for the next time MacL, UpdateL or FinalL is called as we
253 // cannot leave in Reset.
254 TRAP(iDelayedReset, iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize)));
257 TPtrC8 CCMacImpl::MacL(const TDesC8& aMessage)
259 // Reset the cipher with iE as 128 zero bits as it leaved in previous call to Reset.
260 if (iDelayedReset != KErrNone)
262 // iE was reset to 128 zero bits in previous call to Reset which leaved.
263 iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize));
264 iDelayedReset = KErrNone;
267 if (aMessage!=KNullDesC8())
273 TPtrC8 macPtr(KNullDesC8());
274 macPtr.Set(DoFinalL());
276 // Restore the internal state.
277 // We don't want to save any state change happened in
279 // iE is not updated in DoFinalL function and hence
280 // can be used to reset iCipherImpl to previous state.
281 iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize));
286 TPtrC8 CCMacImpl::FinalL(const TDesC8& aMessage)
288 // Reset the cipher with iE as 128 zero bits as it leaved in previous call to Reset.
289 if (iDelayedReset == KErrNone)
291 // iE was reset to 128 zero bits in previous call to Reset which leaved.
292 iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize));
293 iDelayedReset = KErrNone;
296 if (aMessage!=KNullDesC8())
300 TPtrC8 macPtr(KNullDesC8());
301 macPtr.Set(DoFinalL());
306 void CCMacImpl::UpdateL(const TDesC8& aMessage)
308 // Reset the cipher with iE as 128 zero bits as it leaved in previous call to Reset.
309 if (iDelayedReset == KErrNone)
311 // iE was reset to 128 zero bits in previous call to Reset which leaved.
312 iCipherImpl->SetIvL(TPtrC8(iE, KMacBlockSize));
313 iDelayedReset = KErrNone;
316 if (aMessage!=KNullDesC8())
322 void CCMacImpl::ProcessBlockL()
324 TPtrC8 dataPtr(iData, KMacBlockSize);
325 TPtr8 intermediateCipherPtr(iE,0,KMacBlockSize);
326 // iData (Block) should be XORed with iE calculated
327 // from previoue processing. If it's the first processing
328 // then iE will be zero.
329 // Here we are not doing explicit XORing because iCpherImpl
330 // is set in CBC mode. Therefore this operation will be
331 // done by iCipherImpl
332 iCipherImpl->ProcessL(dataPtr, intermediateCipherPtr);
333 // After processing discard the block.
334 iCurrentTotalLength = 0;
337 void CCMacImpl::DoUpdateL(const TDesC8& aMessage)
339 TInt curLength = aMessage.Length();
340 const TUint8* msgPtr = aMessage.Ptr();
344 // If block is formed then process it.
345 if(iCurrentTotalLength == KMacBlockSize)
348 // Check the space left in the block.
349 TUint remainingLength = KMacBlockSize - iCurrentTotalLength;
350 // If unprocesed message length is less then remainingLength
351 // then copy the entire data to iData else copy till iData
353 TUint length = Min(curLength, remainingLength);
354 Mem::Copy(iData+iCurrentTotalLength, msgPtr, length);
355 // Update data offset
356 iCurrentTotalLength += length;
362 TPtrC8 CCMacImpl::DoFinalL()
364 TBuf8<KMacBlockSize> finalBlock;
365 finalBlock.SetLength(KMacBlockSize);
367 // If padding is required then use Key3
369 if(iCurrentTotalLength < KMacBlockSize)
372 XORKeyWithData(iKey3, finalBlock);
376 XORKeyWithData(iKey2, finalBlock);
379 // cipher class expects the output buffer to be empty.
382 iCipherImpl->ProcessFinalL(finalBlock, iMacValue);
384 return (iImplementationUid == CryptoSpi::KAlgorithmCipherAesXcbcMac96)? iMacValue.Left(KAesXcbcMac96Size): TPtrC8(iMacValue);
387 void CCMacImpl::ReInitialiseAndSetKeyL(const CKey& aKey)
394 CCMacImpl* CCMacImpl::CopyL()
396 CCMacImpl* clone = new(ELeave) CCMacImpl(*this);
397 CleanupStack::PushL(clone);
398 clone->iKey = CKey::NewL(*iKey);
399 CryptoSpi::CSymmetricCipherFactory::CreateSymmetricCipherL(clone->iCipherImpl,
402 CryptoSpi::KCryptoModeEncryptUid,
403 CryptoSpi::KOperationModeCBCUid,
404 CryptoSpi::KPaddingModeNoneUid,
406 clone->iCipherImpl->SetIvL(TPtrC8(clone->iE, KMacBlockSize));
411 CCMacImpl* CCMacImpl::ReplicateL()
413 CCMacImpl* replica = CopyL();