|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <e32cmn.h> |
|
17 |
|
18 #include "ipseccrypto.h" |
|
19 #include <networking/ipsecerr.h> |
|
20 |
|
21 #include <des.h> |
|
22 #include <3des.h> |
|
23 #include <rijndael.h> |
|
24 #include <hash.h> |
|
25 |
|
26 #include "keys.h" |
|
27 #include "cryptospidef.h" |
|
28 #include "cryptosymmetriccipherapi.h" |
|
29 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
30 #include "ruleselector.h" |
|
31 #include "plugincharacteristics.h" |
|
32 #include "cryptospistateapi.h" |
|
33 #include "cryptoparams.h" |
|
34 #include "cryptomacapi.h" |
|
35 using namespace CryptoSpi; |
|
36 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |
|
37 |
|
38 #define DES_CBLOCK_SIZE 8 |
|
39 #define AES_CBLOCK_SIZE 16 |
|
40 |
|
41 |
|
42 #define SHA_DIGEST_LENGTH 20 |
|
43 #define MD5_DIGEST_LENGTH 16 |
|
44 #define SHA_CBLOCK 64 |
|
45 #define MD5_CBLOCK 64 |
|
46 |
|
47 // |
|
48 |
|
49 class CMessageDigestSymbian : public CMessageDigestCrypto |
|
50 /** |
|
51 * Generic Hash engine wrapper |
|
52 */ |
|
53 { |
|
54 public: |
|
55 CMessageDigestSymbian(CMessageDigest *aDigest); |
|
56 virtual void Init(); |
|
57 virtual void Update(const TDesC8& aMessage); |
|
58 virtual void Final(TDes8& aDigest); |
|
59 static void FillinInfoSha1(TAlgorithmDesc &anEntry); |
|
60 static void FillinInfoMd5(TAlgorithmDesc &anEntry); |
|
61 ~CMessageDigestSymbian(); |
|
62 private: |
|
63 CMessageDigest *iDigest; |
|
64 }; |
|
65 |
|
66 CMessageDigestSymbian::CMessageDigestSymbian(CMessageDigest *aDigest) : iDigest(aDigest) |
|
67 { |
|
68 ASSERT(aDigest); |
|
69 } |
|
70 |
|
71 void CMessageDigestSymbian::Init() |
|
72 { |
|
73 ASSERT(iDigest); |
|
74 iDigest->Reset(); |
|
75 } |
|
76 |
|
77 void CMessageDigestSymbian::Update(const TDesC8& aMessage) |
|
78 { |
|
79 ASSERT(iDigest); |
|
80 iDigest->Update(aMessage); |
|
81 } |
|
82 |
|
83 void CMessageDigestSymbian::Final(TDes8& aDigest) |
|
84 { |
|
85 ASSERT(iDigest); |
|
86 aDigest.Copy(iDigest->Final()); |
|
87 } |
|
88 |
|
89 CMessageDigestSymbian::~CMessageDigestSymbian() |
|
90 { |
|
91 delete iDigest; |
|
92 } |
|
93 |
|
94 |
|
95 // |
|
96 |
|
97 // CProtocolEay::AlgorithmList + algorithm specific FillinInfo's |
|
98 // |
|
99 // return descriptions of the algorithms supported by this module |
|
100 // |
|
101 static void FillinInfoDescbc(TAlgorithmDesc &anEntry) |
|
102 { |
|
103 anEntry.iName = KIpsecName_DES_CBC; |
|
104 anEntry.iAlgType = EAlgorithmClass_Cipher; |
|
105 anEntry.iMinBits = 64; |
|
106 anEntry.iMaxBits = 64; |
|
107 anEntry.iBlock = DES_CBLOCK_SIZE; |
|
108 anEntry.iVector = 8; |
|
109 } |
|
110 |
|
111 static void FillinInfo3Descbc(TAlgorithmDesc &anEntry) |
|
112 { |
|
113 anEntry.iName = KIpsecName_3DES_CBC; |
|
114 anEntry.iAlgType = EAlgorithmClass_Cipher; |
|
115 anEntry.iMinBits = 3*64; |
|
116 anEntry.iMaxBits = 3*64; |
|
117 anEntry.iBlock = DES_CBLOCK_SIZE; |
|
118 anEntry.iVector = 8; |
|
119 } |
|
120 |
|
121 |
|
122 static void FillinInfoAescbc(TAlgorithmDesc &anEntry) |
|
123 { |
|
124 anEntry.iName = KIpsecName_AES_CBC; |
|
125 anEntry.iAlgType = EAlgorithmClass_Cipher; |
|
126 anEntry.iMinBits = 128; |
|
127 anEntry.iMaxBits = 256; |
|
128 anEntry.iBlock = AES_CBLOCK_SIZE; |
|
129 anEntry.iVector = 16; |
|
130 } |
|
131 |
|
132 static void FillinInfoAesctr(TAlgorithmDesc &anEntry) |
|
133 { |
|
134 anEntry.iName = KIpsecName_AES_CTR; |
|
135 anEntry.iAlgType = EAlgorithmClass_Cipher; |
|
136 anEntry.iMinBits = 128; |
|
137 anEntry.iMaxBits = 256; |
|
138 anEntry.iBlock = AES_CBLOCK_SIZE; |
|
139 anEntry.iVector = 16; // NOTE : Value set to 16 to be compliant to the current crypto implementation |
|
140 // which expects the IVSize to be 16. Will have to be updated (to 8) once the fix is |
|
141 // completed at the crypto layer |
|
142 } |
|
143 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
144 static void FillinInfoAesXcbcMac96(TAlgorithmDesc &anEntry) |
|
145 { |
|
146 anEntry.iName = KIpsecName_AES_XCBC_MAC; |
|
147 anEntry.iAlgType = EAlgorithmClass_Mac; |
|
148 anEntry.iMinBits = 96; |
|
149 anEntry.iMaxBits = 128; |
|
150 anEntry.iBlock = AES_CBLOCK_SIZE; |
|
151 anEntry.iVector = 16; |
|
152 } |
|
153 #endif |
|
154 |
|
155 void CMessageDigestSymbian::FillinInfoSha1(TAlgorithmDesc &anEntry) |
|
156 { |
|
157 anEntry.iName = KIpsecName_SHA1; |
|
158 anEntry.iAlgType = EAlgorithmClass_Digest; |
|
159 anEntry.iMinBits = SHA_DIGEST_LENGTH * 8; |
|
160 anEntry.iMaxBits = SHA_DIGEST_LENGTH * 8; |
|
161 anEntry.iBlock = SHA_CBLOCK; |
|
162 anEntry.iVector = SHA_DIGEST_LENGTH; |
|
163 } |
|
164 |
|
165 void CMessageDigestSymbian::FillinInfoMd5(TAlgorithmDesc &anEntry) |
|
166 { |
|
167 anEntry.iName = KIpsecName_MD5; |
|
168 anEntry.iAlgType = EAlgorithmClass_Digest; |
|
169 anEntry.iMinBits = MD5_DIGEST_LENGTH * 8; |
|
170 anEntry.iMaxBits = MD5_DIGEST_LENGTH * 8; |
|
171 anEntry.iBlock = MD5_CBLOCK; |
|
172 anEntry.iVector = MD5_DIGEST_LENGTH; |
|
173 } |
|
174 |
|
175 |
|
176 TUint CProtocolEay::AlgorithmList(TAlgorithmDesc *&aList) |
|
177 { |
|
178 aList = new TAlgorithmDesc[EAlgorithm_Max]; |
|
179 if (aList == NULL) |
|
180 { |
|
181 return EAlgorithm_Max; |
|
182 } |
|
183 |
|
184 CMessageDigestSymbian::FillinInfoSha1(aList[EAlgorithm_Sha1]); |
|
185 CMessageDigestSymbian::FillinInfoMd5(aList[EAlgorithm_Md5]); |
|
186 FillinInfoDescbc(aList[EAlgorithm_Descbc]); |
|
187 FillinInfo3Descbc(aList[EAlgorithm_3Descbc]); |
|
188 FillinInfoAescbc(aList[EAlgorithm_Aescbc]); |
|
189 FillinInfoAesctr(aList[EAlgorithm_Aesctr]); |
|
190 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
191 FillinInfoAesXcbcMac96(aList[EAlgorithm_AesXcbcMac96]); |
|
192 #endif |
|
193 return EAlgorithm_Max; |
|
194 } |
|
195 |
|
196 // |
|
197 // Instantiate a Cipher algorithm |
|
198 // |
|
199 CryptoSpi::CSymmetricCipher* CProtocolEay::SymmetricCipherL(TUint aAlg, const TDesC8 &aKey) |
|
200 { |
|
201 CryptoSpi::CSymmetricCipher *enc = NULL; |
|
202 TUid operModeUid = CryptoSpi::KOperationModeCBCUid; |
|
203 TUid algUid = CryptoSpi::KAesUid; |
|
204 TUid cryptoModeUid = CryptoSpi::KCryptoModeEncryptUid; |
|
205 TUid paddingModeUid = CryptoSpi::KPaddingModeNoneUid; |
|
206 switch(aAlg) |
|
207 { |
|
208 case EAlgorithm_Descbc: |
|
209 algUid = CryptoSpi::KDesUid; |
|
210 break; |
|
211 case EAlgorithm_3Descbc: |
|
212 algUid = CryptoSpi::K3DesUid; |
|
213 break; |
|
214 case EAlgorithm_Aescbc: |
|
215 algUid = CryptoSpi::KAesUid; |
|
216 break; |
|
217 case EAlgorithm_Aesctr: |
|
218 algUid = CryptoSpi::KAesUid; |
|
219 operModeUid = CryptoSpi::KOperationModeCTRUid;; |
|
220 break; |
|
221 default: |
|
222 User::Leave(EIpsec_UnknownCipherNumber); |
|
223 } |
|
224 // Initialize the Encryptor |
|
225 CryptoSpi::TKeyProperty keyProperty = {algUid, KNullUid, CryptoSpi::KSymmetricKeyUid, CryptoSpi::KNonEmbeddedKeyUid}; |
|
226 CryptoSpi::CCryptoParams* keyParam =CryptoSpi::CCryptoParams::NewLC(); |
|
227 keyParam->AddL(aKey, CryptoSpi::KSymmetricKeyParameterUid); |
|
228 CryptoSpi::CKey *key=CryptoSpi::CKey::NewLC(keyProperty, *keyParam); |
|
229 TRAPD(res, CryptoSpi::CSymmetricCipherFactory::CreateSymmetricCipherL |
|
230 ( |
|
231 enc, |
|
232 algUid, |
|
233 *key, |
|
234 cryptoModeUid, |
|
235 operModeUid, |
|
236 paddingModeUid, |
|
237 NULL)); |
|
238 CleanupStack::PopAndDestroy(key); |
|
239 CleanupStack::PopAndDestroy(keyParam); |
|
240 if (res != KErrNone) |
|
241 { |
|
242 // SetKey takes place implicit to the CreateSymmetricCipherL() factory call. If there is any issue with the key |
|
243 // we would get KErrNotSupported which we need to map to EIpsec_BadCipherKey |
|
244 if (res == KErrNotSupported) |
|
245 { |
|
246 User::Leave(EIpsec_BadCipherKey); |
|
247 } |
|
248 User::Leave(res); |
|
249 } |
|
250 return enc; |
|
251 } |
|
252 |
|
253 // |
|
254 // CProtocolEay::MessageDigest |
|
255 // Instantiate a Message Digest algorithm |
|
256 // |
|
257 CMessageDigestCrypto* CProtocolEay::MessageDigest(TUint aAlg) |
|
258 { |
|
259 CMessageDigest *digest = NULL; |
|
260 // Instead of CSHA1 and CMD5, we should have TSHA1 and TMD5 |
|
261 // to be used as member classes, and the TRAP below would |
|
262 // not be needed -- or at least, should have non-leaving |
|
263 // New available! |
|
264 TRAP_IGNORE( |
|
265 switch (aAlg) |
|
266 { |
|
267 case EAlgorithm_Sha1: |
|
268 digest = CSHA1::NewL(); |
|
269 break; |
|
270 case EAlgorithm_Md5: |
|
271 digest = CMD5::NewL(); |
|
272 break; |
|
273 default: |
|
274 break; |
|
275 } |
|
276 ); |
|
277 if (digest == NULL) |
|
278 return NULL; // No Engine available: out of memory or bad call. |
|
279 CMessageDigestSymbian *wrapper = new CMessageDigestSymbian(digest); |
|
280 if (wrapper == NULL) |
|
281 delete digest; // Out of memory |
|
282 return wrapper; |
|
283 } |
|
284 |
|
285 #ifdef SYMBIAN_IPSEC_VOIP_SUPPORT |
|
286 CMac* CProtocolEay::GetMacImplementationL(const TDesC8& aKey) |
|
287 { |
|
288 //create rule based selector for filtering the desired MAC interface plug-ins. |
|
289 CSelectionRules* rules = CSelectionRules::NewL(); |
|
290 CleanupStack::PushL(rules); |
|
291 CSelectionRuleContent* rule = NULL; |
|
292 const long i=0; |
|
293 CCryptoParam* ruleValueParam = CCryptoIntParam::NewL(0, KMacModeTypeUid); |
|
294 |
|
295 TUid id={KAlgorithmCipherAesXcbcMac96}; |
|
296 rule = CSelectionRuleContent::NewL(KMacInterfaceUid,id, ruleValueParam,EOpEqual,ETrue); |
|
297 rules->AddSelectionRuleL(rule); |
|
298 CRuleSelector* ruleSelector = CRuleSelector::NewL(rules); |
|
299 CleanupStack::Pop(rules); |
|
300 CleanupStack::PushL(ruleSelector); |
|
301 CCryptoSpiStateApi::SetSelector(ruleSelector); |
|
302 // Create & Set the key |
|
303 TKeyProperty keyProperty = {KAesUid, KNullUid, KSymmetricKey,KNonEmbeddedKeyUid}; |
|
304 CCryptoParams* keyParam =CCryptoParams::NewLC(); |
|
305 keyParam->AddL(aKey, KSymmetricKeyParameterUid); |
|
306 CKey* uniKey=CKey::NewLC(keyProperty, *keyParam); |
|
307 //Retrieve a Synchronous MAC Factory Object and use AES-XCBC-MAC-96 or any other MACalgorithm. |
|
308 CMac* macImpl =NULL; |
|
309 TRAPD(err,CMacFactory::CreateMacL(macImpl, KAesXcbcMac96Uid,*uniKey, NULL)); |
|
310 //cleanup uniKey and keyParam. |
|
311 CleanupStack::PopAndDestroy(2,keyParam); |
|
312 CCryptoSpiStateApi::UnsetSelector(); |
|
313 CleanupStack::PopAndDestroy(ruleSelector); |
|
314 return macImpl; |
|
315 } |
|
316 |
|
317 HBufC8* CProtocolEay::RetrieveMacValueL(CMac *aMac, const TDesC8& aSourceData ) |
|
318 { |
|
319 |
|
320 //Retrieve the 8bit mac value |
|
321 HBufC8* macValue = HBufC8::NewLC(16); |
|
322 TPtr8 macPtr = macValue->Des(); |
|
323 //Copy the mac content into the heap based descriptor |
|
324 macPtr.Copy(aMac->MacL(aSourceData)); |
|
325 CleanupStack::PopAndDestroy(macValue); |
|
326 return macValue; |
|
327 } |
|
328 #endif // SYMBIAN_IPSEC_VOIP_SUPPORT |