|
1 /* |
|
2 * Copyright (c) 2005 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 "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: Key management daemon extra module. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32math.h> |
|
20 |
|
21 #include "ikev1extra.h" |
|
22 |
|
23 //////////////////////////////////////////////////////////////7 |
|
24 // |
|
25 // Global functions |
|
26 // |
|
27 //Puts the data in the descriptor into a TInt64 |
|
28 TInt Desc8ToTInt64(const TDesC8 &aLifetime, TInt64 &aTime) |
|
29 { |
|
30 TUint32 high,low; |
|
31 |
|
32 //Seconds lifetime |
|
33 //TAttrib_II *attr_II = aProp->iAttrList->At(0); //presume only 1 transform for each proposal |
|
34 TUint len = aLifetime.Length(); |
|
35 TInt high_len = 0; |
|
36 if (len > 0) |
|
37 { |
|
38 if (len > sizeof(aTime)) |
|
39 { |
|
40 //LogError(_L("Phase_II Lifetime(sec) Overflowed Setting to maximum value")); |
|
41 aTime = MAKE_TINT64(KMaxTInt,KMaxTUint); |
|
42 return KErrOverflow; |
|
43 } |
|
44 else |
|
45 { |
|
46 if (len <= sizeof(TUint)) |
|
47 high = 0; |
|
48 else |
|
49 { |
|
50 high_len = len - sizeof(TUint); |
|
51 Mem::Copy(&high, aLifetime.Ptr(), high_len); //The first total_length - sizeof(TUint) bytes |
|
52 high = ByteOrder::Swap32(high); |
|
53 high = high >> (sizeof(TUint)*8 - len*8); //To set the correct value (shift in bits) |
|
54 len = sizeof(TUint); //remaining length |
|
55 } |
|
56 |
|
57 Mem::Copy(&low, aLifetime.Ptr() + high_len , len); |
|
58 low = ByteOrder::Swap32(low); |
|
59 low = low >> (sizeof(TUint)*8 - len*8); //To set the correct value (shift in bits) |
|
60 aTime = MAKE_TINT64(high,low ); |
|
61 } |
|
62 } |
|
63 else |
|
64 aTime = 0; |
|
65 |
|
66 return KErrNone; |
|
67 } |
|
68 |
|
69 //Creates an addr. mask of aPrefixLen length |
|
70 void PrefixMask(TInetAddr &anAddr, TInt aPrefixLen, TInt aFamily) |
|
71 { |
|
72 if (aFamily == STATIC_CAST(TInt, KAfInet)) |
|
73 { |
|
74 TUint32 addr = 0; |
|
75 if ( aPrefixLen ) { |
|
76 addr = INET_ADDR(255,255,255,255); |
|
77 addr <<= 32 - aPrefixLen; |
|
78 } |
|
79 anAddr.SetAddress(addr); |
|
80 anAddr.SetFamily(KAfInet); |
|
81 } |
|
82 else //KAfInet6 |
|
83 anAddr.PrefixMask(aPrefixLen); //This method only works for IPv6 |
|
84 |
|
85 } |
|
86 |
|
87 TInt PrefixLen(TInetAddr& anAddr) |
|
88 { |
|
89 TIp6Addr ip6addr = anAddr.Ip6Address(); |
|
90 TInt length; |
|
91 TInt i; |
|
92 |
|
93 switch (anAddr.Family()) |
|
94 { |
|
95 case KAfInet: |
|
96 TReal bit; |
|
97 TInt err; |
|
98 TInt mask8; |
|
99 |
|
100 length = 32; |
|
101 |
|
102 for (i = 0; i < length; i++) |
|
103 { |
|
104 err = Math::Pow(bit,2,i % 8); |
|
105 if (err != KErrNone) |
|
106 return err; |
|
107 mask8 = ip6addr.u.iAddr8[(TInt)(i/8)] & (TInt)bit; |
|
108 if (mask8 == (TInt)bit) //The bit is 1 |
|
109 break; |
|
110 } |
|
111 |
|
112 return length - i;//length of the mask |
|
113 |
|
114 case KAfInet6: |
|
115 i = 3; // index to a n-bit chunk of an address |
|
116 length = 128; // first assumption on length of the prefix |
|
117 |
|
118 // start counting the 32 bit zero chunks from end |
|
119 while (ip6addr.u.iAddr32[i] == 0) |
|
120 { |
|
121 length -= 32; |
|
122 if (--i < 0) |
|
123 return 0; // zero length prefix |
|
124 } |
|
125 |
|
126 // switch to 16 bit chunks |
|
127 i = i * 2 + 1; |
|
128 if (ip6addr.u.iAddr16[i] == 0) |
|
129 { |
|
130 length -= 16; |
|
131 i--; |
|
132 } |
|
133 |
|
134 // switch to 8 bit chunks |
|
135 i = i * 2 + 1; |
|
136 if (ip6addr.u.iAddr8[i] == 0) |
|
137 { |
|
138 length -= 8; |
|
139 i--; |
|
140 } |
|
141 |
|
142 // switch to 1 bit chunks |
|
143 { |
|
144 TUint8 octet = ip6addr.u.iAddr8[i]; |
|
145 for (i = 1; (octet & i) == 0; i <<= 1) |
|
146 length--; |
|
147 } |
|
148 |
|
149 return length; |
|
150 |
|
151 default: |
|
152 return KErrNotSupported; |
|
153 } |
|
154 } |
|
155 |
|
156 |
|
157 |
|
158 //////////////////////////////////////////////////////////////////////////////////// |
|
159 // |
|
160 //class TAttrib |
|
161 // |
|
162 //aIsRelaxed indicates theat the lifetimes won't be compared |
|
163 TInt TAttrib::Compare(TAttrib& aAttr, TBool aIsRelaxed) |
|
164 { |
|
165 if (iTransformID != aAttr.iTransformID) |
|
166 return KErrTransformID; |
|
167 if (iEncrAlg != aAttr.iEncrAlg) |
|
168 return KErrEncrAlg; |
|
169 if (iHashAlg != aAttr.iHashAlg) |
|
170 return KErrHashAlg; |
|
171 if (iAuthMethod != aAttr.iAuthMethod) |
|
172 return KErrAuthMethod; |
|
173 if (iGroupDesc != aAttr.iGroupDesc) |
|
174 return KErrGroupDesc; |
|
175 if ((iGroupType != aAttr.iGroupType) && |
|
176 (!(iGroupType == 0) && (aAttr.iGroupType == MODP))) //MODP is the default type so is the same as 0 |
|
177 return KErrGroupType; |
|
178 if (iGroupPrime.Compare(aAttr.iGroupPrime)!=0) |
|
179 return KErrGroupPrime; |
|
180 if (iGroupGen1.Compare(aAttr.iGroupGen1)!=0) |
|
181 return KErrGroupGen1; |
|
182 if (iGroupGen2.Compare(aAttr.iGroupGen2)!=0) |
|
183 return KErrGroupGen2; |
|
184 if (iGroupCurveA.Compare(aAttr.iGroupCurveA)!=0) |
|
185 return KErrGroupCurveA; |
|
186 if (iGroupCurveB.Compare(aAttr.iGroupCurveB)!=0) |
|
187 return KErrGroupCurveB; |
|
188 if (iPRF != aAttr.iPRF) |
|
189 return KErrPRF; |
|
190 if (iKeyLength != aAttr.iKeyLength) |
|
191 { |
|
192 if ( iEncrAlg != AES_CBC ) |
|
193 return KErrKeyLength; |
|
194 else |
|
195 { |
|
196 if ( !( aIsRelaxed && (iKeyLength == 128) && (aAttr.iKeyLength == 0)) ) |
|
197 return KErrKeyLength; |
|
198 } |
|
199 |
|
200 } |
|
201 if (iFieldSize != aAttr.iFieldSize) |
|
202 return KErrFieldSize; |
|
203 if (iGroupOrder.Compare(aAttr.iGroupOrder)!=0) |
|
204 return KErrGroupOrder; |
|
205 |
|
206 if (!aIsRelaxed) //If relaxed lifetimes don't need to match |
|
207 { |
|
208 if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0) |
|
209 return KErrLifeTime; |
|
210 if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0) |
|
211 return KErrLifeSize; |
|
212 } |
|
213 return KErrNone; |
|
214 } |
|
215 |
|
216 // |
|
217 //class CTransModifierList : public CArrayPtr<TTransModifier> |
|
218 // |
|
219 CTransModifierList::CTransModifierList(TInt aGranularity) : CArrayPtrFlat<TTransModifier>(aGranularity) |
|
220 { |
|
221 |
|
222 } |
|
223 |
|
224 CTransModifierList::~CTransModifierList() |
|
225 { |
|
226 ResetAndDestroy(); |
|
227 } |
|
228 |
|
229 // |
|
230 //class TAttrib_II |
|
231 // |
|
232 TAttrib_II::TAttrib_II() |
|
233 { |
|
234 iTransformNum=0; |
|
235 iTransformID=0; |
|
236 iGroupDesc=0; |
|
237 iEncMode=0; |
|
238 iAuthAlg=0; |
|
239 iKeyLength=0; |
|
240 iKeyRounds=0; |
|
241 iComprDicSize=0; |
|
242 }; |
|
243 |
|
244 TInt TAttrib_II::Compare(TAttrib_II& aAttr, TBool aRelaxed) |
|
245 { |
|
246 TBuf8<MAX_ALG_DATA> iComprPrivAlg; |
|
247 |
|
248 // if (iTransformNum != aAttr.iTransformNum) //Transform number |
|
249 // return KErrTransformNum; // Test retired |
|
250 if ( iTransformID != aAttr.iTransformID ) //Transform ID |
|
251 return KErrTransformID; |
|
252 |
|
253 if ((iGroupDesc != aAttr.iGroupDesc) && |
|
254 (!(iGroupDesc == 0) && (aAttr.iGroupDesc == MODP_768))) //OAKLEY GROUP |
|
255 return KErrGroupDesc; |
|
256 if (iEncMode != aAttr.iEncMode) //Encapsulation Mode |
|
257 return KErrEncMode; |
|
258 if (iAuthAlg != aAttr.iAuthAlg) //HMAC |
|
259 return KErrAuthAlg; |
|
260 |
|
261 if (iKeyLength != aAttr.iKeyLength) |
|
262 { |
|
263 if ( iTransformID != ESP_AES_CBC ) |
|
264 return KErrKeyLength; |
|
265 else |
|
266 { |
|
267 if (!( ((iKeyLength == 128) && (aAttr.iKeyLength == 0) ) |
|
268 || |
|
269 ((iKeyLength == 0) && (aAttr.iKeyLength == 128) ) )) |
|
270 return KErrKeyLength; |
|
271 } |
|
272 } |
|
273 |
|
274 if (iKeyRounds != aAttr.iKeyRounds) |
|
275 { |
|
276 if ( iTransformID != ESP_AES_CBC ) |
|
277 return KErrKeyRounds; |
|
278 if ( (iKeyRounds != 0 || aAttr.iKeyRounds != 10) // 10 AES default rounds |
|
279 && |
|
280 (iKeyRounds != 10 || aAttr.iKeyRounds != 0) ) |
|
281 return KErrKeyRounds; |
|
282 } |
|
283 if (iComprDicSize != aAttr.iComprDicSize) //Compress Dictionary size |
|
284 return KErrComprDicSize; |
|
285 if (iComprPrivAlg.Compare(aAttr.iComprPrivAlg)!=0) |
|
286 return KErrComprPrivAlg; |
|
287 |
|
288 if (!aRelaxed) |
|
289 { |
|
290 if (iLifeDurationSecs.Compare(aAttr.iLifeDurationSecs)!=0) |
|
291 return KErrLifeTime; |
|
292 if (iLifeDurationKBytes.Compare(aAttr.iLifeDurationKBytes)!=0) |
|
293 return KErrLifeSize; |
|
294 } |
|
295 return KErrNone; |
|
296 } |
|
297 |
|
298 void TAttrib_II::Copy(TAttrib_II &aAttr) |
|
299 { |
|
300 iTransformNum = aAttr.iTransformNum; //Transform number |
|
301 iTransformID = aAttr.iTransformID; //Transform ID |
|
302 iLifeDurationSecs.Copy(aAttr.iLifeDurationSecs); |
|
303 iLifeDurationKBytes.Copy(aAttr.iLifeDurationKBytes); |
|
304 iGroupDesc = aAttr.iGroupDesc; //OAKLEY GROUP |
|
305 iEncMode = aAttr.iEncMode; //Encapsulation Mode |
|
306 iAuthAlg = aAttr.iAuthAlg; //HMAC |
|
307 iKeyLength = aAttr.iKeyLength; |
|
308 iKeyRounds = aAttr.iKeyRounds; |
|
309 iComprDicSize = aAttr.iComprDicSize; //Compress Dictionary size |
|
310 iComprPrivAlg.Copy(aAttr.iComprPrivAlg); |
|
311 } |
|
312 |
|
313 // |
|
314 //class CAttrib_IIList |
|
315 // |
|
316 |
|
317 CAttrib_IIList::CAttrib_IIList(TInt aGranularity) : CArrayPtrFlat<TAttrib_II>(aGranularity) |
|
318 { |
|
319 |
|
320 } |
|
321 |
|
322 CAttrib_IIList::~CAttrib_IIList() |
|
323 { |
|
324 ResetAndDestroy(); |
|
325 } |
|
326 |
|
327 // |
|
328 //class CProposal_II |
|
329 // |
|
330 |
|
331 void CProposal_II::ConstructL(TInt aGranularity) |
|
332 { |
|
333 iAttrList = new (ELeave) CAttrib_IIList(aGranularity); //Default to granularity 1 |
|
334 } |
|
335 |
|
336 CProposal_II::~CProposal_II() |
|
337 { |
|
338 delete iAttrList; |
|
339 } |
|
340 |
|
341 //Compares that aProp matches with one of the sets of attributes of this proposal and the Protocol |
|
342 //aRelaxed indicates if the comparison includes the lifetimes or not. |
|
343 //Returns KErrNotFound if no match or the transf num (>=0) if match |
|
344 TInt CProposal_II::Match(CProposal_II *aRemoteProp, TBool aRelaxed, TInt* aLocalNbr ) |
|
345 { |
|
346 |
|
347 if (iProtocol != aRemoteProp->iProtocol) |
|
348 return KErrPropProtocol; |
|
349 |
|
350 TInt ret = KErrNoTransforms; |
|
351 TInt i, j, count2; |
|
352 TInt count = iAttrList->Count(); |
|
353 // |
|
354 // Compare all transforms in the peer proposal to the all local proposals defined |
|
355 // |
|
356 for (i = 0; i < count ; i++) |
|
357 { |
|
358 j = 0; |
|
359 count2 = aRemoteProp->iAttrList->Count(); |
|
360 |
|
361 for (j = 0; j < count2 ; j++) |
|
362 { |
|
363 ret = iAttrList->At(i)->Compare(*aRemoteProp->iAttrList->At(j), aRelaxed); |
|
364 if (ret == KErrNone) { |
|
365 if ( aLocalNbr ) |
|
366 *aLocalNbr = i; |
|
367 return j; |
|
368 } |
|
369 } |
|
370 } |
|
371 //No matching set of attributes |
|
372 return ret; //return the last error |
|
373 } |
|
374 |
|
375 |
|
376 |
|
377 // |
|
378 //class CProposal_IIList |
|
379 // |
|
380 |
|
381 CProposal_IIList::CProposal_IIList(TInt aGranularity) : CArrayPtrFlat<CProposal_II>(aGranularity) |
|
382 { |
|
383 |
|
384 } |
|
385 |
|
386 CProposal_IIList::~CProposal_IIList() |
|
387 { |
|
388 ResetAndDestroy(); |
|
389 } |
|
390 |
|
391 //IMPORTANT: assume all the proposals in this have the same number so they are AND'd |
|
392 //If more than one proposal number in this the method won't work |
|
393 //aTransArray contains the num of transform matching for each proposal |
|
394 //Returns the Remote proposal num that matches (>=0) or an error (<0, see list) |
|
395 TInt CProposal_IIList::MultiMatchL(CProposal_IIList *aRemoteProp, TBool aRelaxed, CTransModifierList *aTransArray) |
|
396 { |
|
397 CProposal_II *rem_prop; //remote proposal |
|
398 TInt trans_num = KErrNoRemoteProposals; |
|
399 TInt local_num; |
|
400 TInt i1 = 0, i2; |
|
401 TInt prop_numII = aRemoteProp->At(0)->iProposalNum; //Proposed by the peer |
|
402 |
|
403 if ( Count() == 0 ) |
|
404 return KErrNoLocalProposals; |
|
405 |
|
406 CProposal_II *prop1 = At(0); //First proposal in this |
|
407 TInt count2 = aRemoteProp->Count(); |
|
408 TTransModifier *tmodif; |
|
409 |
|
410 //loop through the remote proposals list. The local is restarted for every new remote proposal num. |
|
411 for ( i2 = 0; i2 < count2 ; i2++ ) |
|
412 { |
|
413 rem_prop = aRemoteProp->At(i2); |
|
414 |
|
415 if ( rem_prop->iProposalNum == prop_numII ) |
|
416 { |
|
417 // Find matching transform from proposal |
|
418 trans_num = prop1->Match(rem_prop, aRelaxed, &local_num); |
|
419 |
|
420 if ( trans_num >= 0 ) //There's a match |
|
421 { |
|
422 tmodif = new (ELeave) TTransModifier(); |
|
423 CleanupStack::PushL(tmodif); |
|
424 tmodif->iPropNum = prop1->iProposalNum; // Store local proposal number |
|
425 tmodif->iTransNum = trans_num; // Store remote transform index in proposal |
|
426 tmodif->iReplayWindowLength = prop1->iReplayWindowLength; //to update SAD correctly |
|
427 tmodif->iReducedLifeSecs.Set(prop1->iAttrList->At(local_num)->iLifeDurationSecs); |
|
428 tmodif->iReducedLifeKBytes.Set(prop1->iAttrList->At(local_num)->iLifeDurationKBytes); |
|
429 aTransArray->AppendL(tmodif); //add to the array and go for the next |
|
430 CleanupStack::Pop(); //tmodif safe |
|
431 if ( (i1 + 1) < Count() ) //still proposals left in 'this' list |
|
432 { |
|
433 prop1 = At(i1++); |
|
434 if ( (i2 + 1) == count2 ) //last proposal |
|
435 return KErrPropNumberMismatch; //No match because more local than remote proposals |
|
436 continue; |
|
437 } |
|
438 |
|
439 if (i2 < (count2 - 1)) |
|
440 { |
|
441 //No more local proposals and still remote left |
|
442 if (aRemoteProp->At(i2+1)->iProposalNum == prop_numII) |
|
443 { //num mismatch begin again the local proposals loop |
|
444 i1 = 0; |
|
445 prop1 = At(0); //First proposal in this |
|
446 aTransArray->Reset(); //Empties all the array because the current match is not valid |
|
447 for (i2++; i2 < count2 ; i2++) //go for next remote proposal and |
|
448 { |
|
449 rem_prop = aRemoteProp->At(i2); |
|
450 if (rem_prop->iProposalNum != prop_numII) |
|
451 { |
|
452 prop_numII = rem_prop->iProposalNum; //new proposal number to consider |
|
453 i2--; //To fetch the correct proposal at the begining of the external loop |
|
454 break; //next number found break the loop |
|
455 } |
|
456 } |
|
457 continue; //Main loop continues |
|
458 } |
|
459 } |
|
460 |
|
461 break; //Loop finished. Acceptable proposal found ! |
|
462 } |
|
463 else //No transform matches so proposals lists don't match |
|
464 { //look for the next remote proposal group (number) |
|
465 i1 = 0; |
|
466 prop1 = At(0); //First proposal in this |
|
467 aTransArray->Reset(); //Empties all the array because the current match is not valid |
|
468 i2++; //next proposal |
|
469 if (i2 == count2) |
|
470 return trans_num; //Error in the last transform |
|
471 for (; i2 < count2 ; i2++) |
|
472 { |
|
473 rem_prop = aRemoteProp->At(i2); |
|
474 if ( rem_prop->iProposalNum != prop_numII ) |
|
475 { |
|
476 prop_numII = rem_prop->iProposalNum; //new proposal number to consider |
|
477 i2--; //To fetch the correct proposal at the begining of the external loop |
|
478 break; //next number found break the loop |
|
479 } |
|
480 } |
|
481 continue; //Main loop continues |
|
482 } |
|
483 } |
|
484 else //New group of AND'd remote proposals |
|
485 { |
|
486 i1 = 0; |
|
487 prop1 = At(0); |
|
488 prop_numII = rem_prop->iProposalNum; //new proposal num |
|
489 aTransArray->Reset(); //Empties all the array |
|
490 i2 --; //To fetch the correct proposal at the begining of the external loop |
|
491 } |
|
492 |
|
493 } |
|
494 |
|
495 if ( trans_num >= 0 ) |
|
496 { |
|
497 return prop_numII; //Remote proposal num that matches |
|
498 } |
|
499 //Otherwise fails the comparison |
|
500 return trans_num; //No match. Returns last error in a transform |
|
501 } |