|
1 /* |
|
2 * Copyright (c) 2007-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 "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: Stream class implementation for ISAKMP |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "ikev1isakmpstream.h" |
|
20 #include "ikemsgheader.h" |
|
21 #include "ikev1negotiation.h" |
|
22 #include "ikedebug.h" |
|
23 #include "ikev1trans.h" |
|
24 #include "ikecalist.h" |
|
25 #include "ikecaelem.h" |
|
26 #include "ikepolparser.h" |
|
27 #include "ikev1crypto.h" |
|
28 #include "ikev1pkiservice.h" |
|
29 #include "ikev1private.h" |
|
30 #include "ikepkiutils.h" |
|
31 #include "ikev1natdiscovery.h" |
|
32 |
|
33 // |
|
34 // TIkev1IsakmpStream |
|
35 // |
|
36 |
|
37 TIkev1IsakmpStream::TIkev1IsakmpStream( MIkeDebug& aDebug ) |
|
38 : iDebug( aDebug ) |
|
39 { |
|
40 } |
|
41 |
|
42 void TIkev1IsakmpStream::IsakmpInit(CIkev1Negotiation *aSession) |
|
43 { |
|
44 ThdrISAKMP hdr; |
|
45 |
|
46 iError = EFalse; |
|
47 iNegotiation = aSession; //stores it to avoid passing it for all the functions |
|
48 DEBUG_LOG(_L("[HDR]")); |
|
49 hdr.SetCookieI(iNegotiation->iCookie_I); |
|
50 hdr.SetCookieR(iNegotiation->iCookie_R); |
|
51 hdr.SetPayload(0); //Is set later through the pointer iNextPayload |
|
52 hdr.SetVersion(0x10); //MAJOR=1 MINOR=0 |
|
53 hdr.SetExchange(iNegotiation->iExchange); |
|
54 hdr.SetFlags(iNegotiation->iFlags); |
|
55 if ((iNegotiation->iExchange == ISAKMP_EXCHANGE_ID) || (iNegotiation->iExchange == ISAKMP_EXCHANGE_AGGR)) |
|
56 hdr.SetMessageId(0); |
|
57 else //QUICK mode ,INFORMATIONAL Mode or Transaction exchange |
|
58 hdr.SetMessageId(iNegotiation->iMessageId); |
|
59 |
|
60 iBuf.SetLength(0); //Set correctly when sending SendL() |
|
61 iBuf.Copy((TUint8 *)&hdr, sizeof(hdr)); //Always called the first so not Append |
|
62 iNextPayload = (TUint8 *)(iBuf.Ptr() + 16); //saves the adress. |
|
63 //Will be filled by the next called function |
|
64 } |
|
65 |
|
66 |
|
67 void TIkev1IsakmpStream::IsakmpSa() |
|
68 { |
|
69 TSAISAKMP sa; |
|
70 DEBUG_LOG(_L("[SA]")); |
|
71 sa.SetPayload(0); //Not proposal or transform RFC. After reserved is already 0 |
|
72 sa.SetDOI(iNegotiation->iDOI); //Always the same. Otherwise should be the one contained in CIkev1Negotiation |
|
73 sa.SetSIT(IPSEC_SIT_IDENTITY_ONLY); //That means no Labeled Domain Identifier |
|
74 |
|
75 *iNextPayload = ISAKMP_PAYLOAD_SA; //Fills the previous payload next field |
|
76 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
77 //Will be filled by the next called function |
|
78 |
|
79 TUint16 pos=(TUint16)iBuf.Length(); //save the position to know the total size later and insert it |
|
80 iBuf.SetLength(pos + sizeof(sa)); //leave room to insert later the proposal |
|
81 //including the SPI |
|
82 IsakmpProposal(); |
|
83 sa.SetLength((TUint16)(iBuf.Length() - pos)); |
|
84 TBuf8<sizeof(sa)> aux; |
|
85 aux.Append((TUint8 *)&sa, sizeof(sa)); |
|
86 iBuf.Replace(pos,aux.Length(),aux); |
|
87 |
|
88 } |
|
89 |
|
90 //SPI not included yet. |
|
91 //Sends msg stage 2. Should be used for phase 2 as well |
|
92 void TIkev1IsakmpStream::IsakmpProposal() |
|
93 { |
|
94 TProposalISAKMP proposal; |
|
95 TUint16 pos = 0; |
|
96 TUint8 next_payload = ISAKMP_PAYLOAD_T; // default: more than one transform |
|
97 |
|
98 if (iNegotiation->iPhase == PHASE_I) |
|
99 { |
|
100 TProposal *prop; |
|
101 |
|
102 if (iNegotiation->iRole==INITIATOR) |
|
103 { |
|
104 prop=&iNegotiation->iProposal_I; |
|
105 } |
|
106 else |
|
107 { |
|
108 prop=&iNegotiation->iChosenProposal_I; |
|
109 } |
|
110 proposal.SetPayload(ISAKMP_PAYLOAD_NONE); //Only one proposal |
|
111 proposal.SetNum(prop->iProposalNum); |
|
112 proposal.SetProtocol(prop->iProtocol); |
|
113 proposal.SetSPISize(0); |
|
114 proposal.SetNumTrans(prop->iNumTransforms); |
|
115 pos=(TUint16)iBuf.Length(); //save the position to insert later |
|
116 //including the SPI |
|
117 iBuf.SetLength(pos + sizeof(proposal)); //leave room to insert later the proposal |
|
118 TAttrib *attr=prop->iAttrList; |
|
119 for (TInt i=0; i < proposal.GetNumTrans(); i++) //Adds all the transforms |
|
120 { |
|
121 if ( !attr->iNext ) |
|
122 next_payload = ISAKMP_PAYLOAD_NONE; // Last trasnform |
|
123 IsakmpTransform((TUint8 *)attr, next_payload); |
|
124 attr=attr->iNext; |
|
125 } |
|
126 proposal.SetLength((TUint16)(iBuf.Length() - pos)); |
|
127 TBuf8<sizeof(proposal) + MAX_SPI_SIZE> aux; |
|
128 aux.Append((TUint8 *)&proposal, sizeof(proposal)); |
|
129 //aux.Append(prop->iSPI); //insert the SPI |
|
130 iBuf.Replace(pos,aux.Length(),aux); |
|
131 return; |
|
132 } |
|
133 |
|
134 //PHASE_II |
|
135 TAttrib_II *attr_II=NULL; |
|
136 CProposal_IIList *propII_List = NULL; |
|
137 CProposal_II *propII = NULL; |
|
138 TBuf8<MAX_SPI_SIZE> SPI; |
|
139 TInt i, index = 0; |
|
140 TUint32 in_spi; |
|
141 TUint8 num_transforms; |
|
142 CArrayFixFlat<TSPINode> *list = iNegotiation->iInboundSPIList; |
|
143 |
|
144 if (iNegotiation->iRole==INITIATOR) |
|
145 propII_List = iNegotiation->iProposal_IIList; |
|
146 else //RESPONDER |
|
147 { |
|
148 for (index = 0; index < list->Count(); index++) |
|
149 { |
|
150 if (list->At(index).iPropNum == iNegotiation->iProposalNum) |
|
151 break; |
|
152 } |
|
153 propII_List = iNegotiation->iChosenProp_IIList; |
|
154 } |
|
155 |
|
156 TInt count = propII_List->Count(); |
|
157 |
|
158 for (i = 0; i < count; i++) |
|
159 { |
|
160 propII = propII_List->At(i); |
|
161 //Choose the correct SPI |
|
162 if (iNegotiation->iRole==INITIATOR) |
|
163 SPI = propII->iSPI; |
|
164 else //RESPONDER |
|
165 { |
|
166 in_spi = list->At(index).iSPI; |
|
167 SPI.Copy((TUint8 *)&in_spi, sizeof(TUint32)); |
|
168 index++; |
|
169 } |
|
170 |
|
171 if (i == count - 1) //Last proposal |
|
172 proposal.SetPayload(ISAKMP_PAYLOAD_NONE); |
|
173 else //There are more |
|
174 proposal.SetPayload(ISAKMP_PAYLOAD_P); |
|
175 |
|
176 num_transforms = propII->iNumTransforms; |
|
177 proposal.SetNum(propII->iProposalNum); |
|
178 proposal.SetProtocol(propII->iProtocol); |
|
179 proposal.SetNumTrans(num_transforms); |
|
180 proposal.SetSPISize((TUint8)SPI.Length()); //The chosen contains the inbound SPI |
|
181 pos=(TUint16)iBuf.Length(); //save the position to insert later |
|
182 iBuf.SetLength(pos + sizeof(proposal) + proposal.GetSPISize()); //leave room to insert later the proposal |
|
183 //including the SPI |
|
184 for (TInt j = 0; j < num_transforms; j++) //Adds all the transforms |
|
185 { |
|
186 attr_II = propII->iAttrList->At(j); |
|
187 if ( (num_transforms - j) == 1 ) |
|
188 next_payload = ISAKMP_PAYLOAD_NONE; // Last trasnform |
|
189 IsakmpTransform((TUint8 *)attr_II, next_payload); |
|
190 } |
|
191 proposal.SetLength((TUint16)(iBuf.Length() - pos)); |
|
192 TBuf8<sizeof(proposal) + MAX_SPI_SIZE> aux; |
|
193 aux.Append((TUint8 *)&proposal, sizeof(proposal)); |
|
194 aux.Append(SPI); //insert the SPI |
|
195 iBuf.Replace(pos, aux.Length(), aux); |
|
196 |
|
197 } |
|
198 |
|
199 } |
|
200 |
|
201 //Transform data received as TUint8 to allow both TAttrib and TAttrib_II |
|
202 void TIkev1IsakmpStream::IsakmpTransform(TUint8 *aTransform, TUint8 aNextPayload) |
|
203 { |
|
204 TTransformISAKMP transf; |
|
205 |
|
206 //transf.SetNum(1);//SHOULD BE the selected transform but Linux doesn't let it use it!!! |
|
207 if (iNegotiation->iPhase == PHASE_I) |
|
208 { |
|
209 TAttrib *attr=(TAttrib *)aTransform; |
|
210 transf.SetNum(attr->iTransformNum); |
|
211 transf.SetID(attr->iTransformID); |
|
212 transf.SetPayload(aNextPayload); |
|
213 } |
|
214 else //PHASE_II |
|
215 { |
|
216 TAttrib_II *attr_II=(TAttrib_II *)aTransform; |
|
217 transf.SetNum(attr_II->iTransformNum); |
|
218 transf.SetID(attr_II->iTransformID); |
|
219 transf.SetPayload(aNextPayload); |
|
220 } |
|
221 |
|
222 TInt pos=iBuf.Length(); //save the position to insert later |
|
223 iBuf.SetLength(pos + sizeof(transf)); //leave room to insert later |
|
224 IsakmpAttrib(aTransform); |
|
225 transf.SetLength((TUint16)(iBuf.Length() - pos)); |
|
226 TBuf8<sizeof(transf)> aux; |
|
227 aux.Append((TUint8 *)&transf, sizeof(transf)); |
|
228 iBuf.Replace(pos,aux.Length(),aux); |
|
229 } |
|
230 |
|
231 |
|
232 //Creates a data payload with the desired SA attributes. either Phase I or II |
|
233 void TIkev1IsakmpStream::IsakmpAttrib(TUint8 *aTransform) |
|
234 { |
|
235 if (iNegotiation->iPhase == PHASE_I) |
|
236 IsakmpAttrib1((TAttrib *)aTransform); |
|
237 else //PHASE_II |
|
238 IsakmpAttrib2((TAttrib_II *)aTransform); |
|
239 } |
|
240 |
|
241 //Phase_I attributes |
|
242 void TIkev1IsakmpStream::IsakmpAttrib1(TAttrib *aTransform) |
|
243 { |
|
244 TDataISAKMP attr; |
|
245 TUint length; |
|
246 TUint16 val; |
|
247 TAttrib trans; |
|
248 |
|
249 trans=*aTransform; |
|
250 |
|
251 val=trans.iEncrAlg; |
|
252 if (val != 0) |
|
253 { |
|
254 attr.SetBasic(ETrue); |
|
255 attr.SetType(OAKLEY_ATTR_TYPE_ENCR_ALG); |
|
256 attr.SetValue(val); |
|
257 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
258 } |
|
259 |
|
260 val=trans.iHashAlg; |
|
261 if (val != 0) |
|
262 { |
|
263 attr.SetBasic(ETrue); |
|
264 attr.SetType(OAKLEY_ATTR_TYPE_HASH_ALG); |
|
265 attr.SetValue(val); |
|
266 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
267 } |
|
268 |
|
269 val=CTransNegotiation::GetAuthMethod(trans.iAuthMethod, trans.iXauthUsed, trans.iRole); |
|
270 if (val != 0) |
|
271 { |
|
272 attr.SetBasic(ETrue); |
|
273 attr.SetType(OAKLEY_ATTR_TYPE_AUTH_METH); |
|
274 attr.SetValue(val); |
|
275 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
276 } |
|
277 |
|
278 val=trans.iGroupDesc; |
|
279 if (val != 0) |
|
280 { |
|
281 attr.SetBasic(ETrue); |
|
282 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_DESC); |
|
283 attr.SetValue(val); |
|
284 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
285 } |
|
286 |
|
287 val=trans.iGroupType; |
|
288 if (val != 0) |
|
289 { |
|
290 attr.SetBasic(ETrue); |
|
291 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_TYPE); |
|
292 attr.SetValue(val); |
|
293 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
294 } |
|
295 |
|
296 length=trans.iGroupPrime.Length(); |
|
297 if (length!=0) |
|
298 { |
|
299 attr.SetBasic(EFalse); |
|
300 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_PRIME); |
|
301 attr.SetLength((TUint16)(length)); |
|
302 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
303 iBuf.Append(trans.iGroupPrime); |
|
304 } |
|
305 |
|
306 length=trans.iGroupGen1.Length(); |
|
307 if (length!=0) |
|
308 { |
|
309 attr.SetBasic(EFalse); |
|
310 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_GEN1); |
|
311 attr.SetLength((TUint16)(length)); |
|
312 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
313 iBuf.Append(trans.iGroupGen1); |
|
314 } |
|
315 |
|
316 length=trans.iGroupGen2.Length(); |
|
317 if (length!=0) |
|
318 { |
|
319 attr.SetBasic(EFalse); |
|
320 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_GEN2); |
|
321 attr.SetLength((TUint16)(length)); |
|
322 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
323 iBuf.Append(trans.iGroupGen2); |
|
324 } |
|
325 |
|
326 length=trans.iGroupCurveA.Length(); |
|
327 if (length!=0) |
|
328 { |
|
329 attr.SetBasic(EFalse); |
|
330 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_CRVA); |
|
331 attr.SetLength((TUint16)(length)); |
|
332 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
333 iBuf.Append(trans.iGroupCurveA); |
|
334 } |
|
335 |
|
336 length=trans.iGroupCurveB.Length(); |
|
337 if (length!=0) |
|
338 { |
|
339 attr.SetBasic(EFalse); |
|
340 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_CRVB); |
|
341 attr.SetLength((TUint16)(length)); |
|
342 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
343 iBuf.Append(trans.iGroupCurveB); |
|
344 } |
|
345 |
|
346 length=trans.iLifeDurationSecs.Length(); |
|
347 if (length!=0) |
|
348 { |
|
349 attr.SetBasic(ETrue); |
|
350 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); |
|
351 attr.SetValue(SECONDS); |
|
352 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
353 |
|
354 attr.SetBasic(EFalse); |
|
355 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); |
|
356 attr.SetLength((TUint16)(length)); |
|
357 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
358 iBuf.Append(trans.iLifeDurationSecs); |
|
359 |
|
360 } |
|
361 |
|
362 length=trans.iLifeDurationKBytes.Length(); |
|
363 if (length!=0) |
|
364 { |
|
365 attr.SetBasic(ETrue); |
|
366 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); |
|
367 attr.SetValue(KBYTES); |
|
368 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
369 |
|
370 attr.SetBasic(EFalse); |
|
371 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); |
|
372 attr.SetLength((TUint16)(length)); |
|
373 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
374 iBuf.Append(trans.iLifeDurationKBytes); |
|
375 |
|
376 } |
|
377 |
|
378 val=trans.iPRF; |
|
379 if (val != 0) |
|
380 { |
|
381 attr.SetBasic(ETrue); |
|
382 attr.SetType(OAKLEY_ATTR_TYPE_PRF); |
|
383 attr.SetValue(val); |
|
384 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
385 } |
|
386 |
|
387 val=trans.iKeyLength; |
|
388 if (val != 0) |
|
389 { |
|
390 attr.SetBasic(ETrue); |
|
391 attr.SetType(OAKLEY_ATTR_TYPE_KEY_LEN); |
|
392 attr.SetValue(val); |
|
393 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
394 } |
|
395 |
|
396 val=trans.iFieldSize; |
|
397 if (val != 0) |
|
398 { |
|
399 attr.SetBasic(ETrue); |
|
400 attr.SetType(OAKLEY_ATTR_TYPE_FIELD_SIZE); |
|
401 attr.SetValue(val); |
|
402 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
403 } |
|
404 |
|
405 length=trans.iGroupOrder.Length(); |
|
406 if (length!=0) |
|
407 { |
|
408 attr.SetBasic(EFalse); |
|
409 attr.SetType(OAKLEY_ATTR_TYPE_GROUP_ORDER); |
|
410 attr.SetLength((TUint16)(sizeof(attr)+length)); |
|
411 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
412 iBuf.Append(trans.iGroupOrder); |
|
413 } |
|
414 } |
|
415 |
|
416 |
|
417 //Phase_II attributes |
|
418 void TIkev1IsakmpStream::IsakmpAttrib2(TAttrib_II *aTransform) |
|
419 { |
|
420 TDataISAKMP attr; |
|
421 TUint length; |
|
422 TUint16 val; |
|
423 |
|
424 TAttrib_II trans=*aTransform; |
|
425 length=trans.iLifeDurationSecs.Length(); |
|
426 if (length!=0) |
|
427 { |
|
428 attr.SetBasic(ETrue); |
|
429 attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); |
|
430 attr.SetValue(SECONDS); |
|
431 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
432 |
|
433 attr.SetBasic(EFalse); |
|
434 attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); |
|
435 attr.SetLength((TUint16)length); |
|
436 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
437 iBuf.Append(trans.iLifeDurationSecs.Ptr(),trans.iLifeDurationSecs.Length()); |
|
438 |
|
439 |
|
440 } |
|
441 |
|
442 length=trans.iLifeDurationKBytes.Length(); |
|
443 if (length!=0) |
|
444 { |
|
445 attr.SetBasic(ETrue); |
|
446 attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); |
|
447 attr.SetValue(KBYTES); |
|
448 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
449 |
|
450 attr.SetBasic(EFalse); |
|
451 attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); |
|
452 attr.SetLength((TUint16)length); |
|
453 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
454 iBuf.Append(trans.iLifeDurationKBytes.Ptr(),trans.iLifeDurationKBytes.Length()); |
|
455 |
|
456 } |
|
457 |
|
458 if (iNegotiation->iPFS) |
|
459 { //Only sent if PFS in use. The same used in Phase I |
|
460 val = trans.iGroupDesc; |
|
461 if (val != 0) |
|
462 { |
|
463 attr.SetBasic(ETrue); |
|
464 attr.SetType(DOI_ATTR_TYPE_GROUP_DESC); |
|
465 attr.SetValue(val); |
|
466 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
467 } |
|
468 } |
|
469 |
|
470 val=trans.iEncMode; |
|
471 if (val != 0) |
|
472 { |
|
473 // |
|
474 // If ESP UDP encapsulation required (because of NAT device in between) |
|
475 // modify encapsulation type code values |
|
476 // |
|
477 if ( iNegotiation->iNAT_D_Flags ) { |
|
478 if ( val == DOI_TUNNEL ) |
|
479 val = UDP_ENC_TUNNEL; |
|
480 else val = UDP_ENC_TRANSPORT; |
|
481 } |
|
482 attr.SetBasic(ETrue); |
|
483 attr.SetType(DOI_ATTR_TYPE_ENC_MODE); |
|
484 attr.SetValue(val); |
|
485 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
486 } |
|
487 |
|
488 val=trans.iAuthAlg; |
|
489 if (val != 0) |
|
490 { |
|
491 attr.SetBasic(ETrue); |
|
492 attr.SetType(DOI_ATTR_TYPE_AUTH_ALG); |
|
493 attr.SetValue(val); |
|
494 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
495 } |
|
496 |
|
497 val=trans.iKeyLength; |
|
498 if (val != 0) |
|
499 { |
|
500 attr.SetBasic(ETrue); |
|
501 attr.SetType(DOI_ATTR_TYPE_KEY_LEN); |
|
502 attr.SetValue(val); |
|
503 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
504 } |
|
505 |
|
506 val=trans.iKeyRounds; |
|
507 if (val != 0) |
|
508 { |
|
509 attr.SetBasic(ETrue); |
|
510 attr.SetType(DOI_ATTR_TYPE_KEY_ROUNDS); |
|
511 attr.SetValue(val); |
|
512 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
513 } |
|
514 |
|
515 val=trans.iComprDicSize; |
|
516 if (val != 0) |
|
517 { |
|
518 attr.SetBasic(ETrue); |
|
519 attr.SetType(DOI_ATTR_TYPE_COMP_DIC_SIZE); |
|
520 attr.SetValue(val); |
|
521 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
522 } |
|
523 |
|
524 length=trans.iComprPrivAlg.Length(); |
|
525 if (length!=0) |
|
526 { |
|
527 attr.SetBasic(EFalse); |
|
528 attr.SetType(DOI_ATTR_TYPE_COMP_PRIV_ALG); |
|
529 attr.SetLength((TUint16)(length)); |
|
530 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
531 iBuf.Append(trans.iComprPrivAlg); |
|
532 } |
|
533 |
|
534 } |
|
535 |
|
536 |
|
537 //Adds the key payload to the buffer |
|
538 void TIkev1IsakmpStream::IsakmpKeyL() |
|
539 { |
|
540 TKeyISAKMP key_payload; |
|
541 |
|
542 if (!iNegotiation->ComputeDHPublicValueL()) //Computes the required key values. Needed to ComputeKeys |
|
543 return; //No key payload generated |
|
544 TPtrC8 key_ptr(iNegotiation->iOwnPublicKey_ptr); |
|
545 TInt PadLth = 0; |
|
546 TInt ModLth = iNegotiation->iOwnKeys->ModulusLength(); |
|
547 if ( ModLth > key_ptr.Length() ) |
|
548 { |
|
549 PadLth = ModLth - key_ptr.Length(); |
|
550 DEBUG_LOG(_L("[KE(filled)]")); |
|
551 } |
|
552 DEBUG_LOG(_L("[KE]")); |
|
553 key_payload.SetLength((TUint16)(sizeof(key_payload) + ModLth)); |
|
554 *iNextPayload = ISAKMP_PAYLOAD_KE; //Fills the previous payload next field |
|
555 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
556 //Will be filled by the next called function |
|
557 iBuf.Append((TUint8 *)&key_payload, sizeof(key_payload)); |
|
558 if ( PadLth ) |
|
559 { |
|
560 TChar zero(0); |
|
561 iBuf.AppendFill(zero, PadLth); //Fill prepending zero bits to DH public value |
|
562 } |
|
563 iBuf.Append(key_ptr); //variable size DH public value |
|
564 } |
|
565 |
|
566 void TIkev1IsakmpStream::IsakmpOwnIdentL() |
|
567 { |
|
568 IsakmpIdentL(ETrue); |
|
569 } |
|
570 |
|
571 void TIkev1IsakmpStream::IsakmpPeerIdentL() |
|
572 { |
|
573 IsakmpIdentL(EFalse); |
|
574 } |
|
575 |
|
576 void TIkev1IsakmpStream::IsakmpIdentL(TBool aIsOwn) |
|
577 { |
|
578 TIdentISAKMP id_payload; |
|
579 |
|
580 TBuf8<256> buf; //Max size for FQDN or DER ASN1 DN |
|
581 // (buf should be allocated from heap !!) |
|
582 TUint32 num; |
|
583 const TUint8 *pnum; |
|
584 |
|
585 //DOI IPSEC |
|
586 if (iNegotiation->iPhase == PHASE_I) |
|
587 id_payload.SetProtocol(KProtocolInetUdp); |
|
588 else |
|
589 id_payload.SetProtocol(iNegotiation->iIDProtocol); //defined when receiving the acquire (INIT) or when receiveind the ID payload (RESP) |
|
590 |
|
591 if (aIsOwn) //Own ID! |
|
592 { |
|
593 if (iNegotiation->iPhase == PHASE_I) |
|
594 { |
|
595 DEBUG_LOG(_L("[IDi]")); |
|
596 Isakmp_Phase1_IdL(buf, id_payload); |
|
597 } |
|
598 else //PHASE_II |
|
599 { |
|
600 DEBUG_LOG(_L("[IDci]")); |
|
601 id_payload.SetIDType(iNegotiation->iLocalIDType_II); |
|
602 |
|
603 id_payload.SetPort(iNegotiation->iIDLocalPort); //defined when receiving the acquire (INIT) or when receiveind the ID payload (RESP) |
|
604 |
|
605 switch (iNegotiation->iLocalIDType_II) |
|
606 { |
|
607 case ID_IPV4_ADDR: |
|
608 id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 |
|
609 num = ByteOrder::Swap32(iNegotiation->iLocalAddr1_ID_II.Address());//Put in network order |
|
610 pnum= (TUint8*)# |
|
611 buf.Append(pnum,sizeof(TUint32)); |
|
612 break; |
|
613 case ID_IPV6_ADDR: |
|
614 if (iNegotiation->iLocalAddr.IsV4Mapped()) |
|
615 { |
|
616 id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 |
|
617 id_payload.SetIDType(ID_IPV4_ADDR); |
|
618 num = ByteOrder::Swap32(iNegotiation->iLocalAddr.Address());//Put in network order |
|
619 pnum= (TUint8*)# |
|
620 buf.Append(pnum,sizeof(TUint32)); |
|
621 } |
|
622 else |
|
623 { |
|
624 id_payload.SetLength((TUint16)(sizeof(id_payload) + 16)); //IPV6 size is 16 |
|
625 pnum = &iNegotiation->iLocalAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
626 buf.Append(pnum, 16); |
|
627 } |
|
628 break; |
|
629 case ID_IPV4_ADDR_SUBNET: |
|
630 id_payload.SetLength((TUint16)(sizeof(id_payload) + 2*sizeof(TUint32))); //IPV4 addr TInt32 |
|
631 num = ByteOrder::Swap32(iNegotiation->iLocalAddr1_ID_II.Address());//Put in network order |
|
632 pnum= (TUint8*)# |
|
633 buf.Append(pnum,sizeof(TUint32)); |
|
634 num = ByteOrder::Swap32(iNegotiation->iLocalAddr2_ID_II.Address());//Put in network order |
|
635 pnum= (TUint8*)# |
|
636 buf.Append(pnum,sizeof(TUint32)); |
|
637 break; |
|
638 case ID_IPV6_ADDR_SUBNET: |
|
639 id_payload.SetLength((TUint16)(sizeof(id_payload) + 32)); //one IPV6 addr size is 16 |
|
640 pnum = &iNegotiation->iLocalAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
641 buf.Append(pnum, 16); |
|
642 pnum = &iNegotiation->iLocalAddr2_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
643 buf.Append(pnum, 16); |
|
644 break; |
|
645 //No need for a default. Must be controlled way before when acquire or IDs received |
|
646 } |
|
647 } |
|
648 } |
|
649 else //Peer Id. |
|
650 { |
|
651 if (iNegotiation->iPhase == PHASE_I) |
|
652 { |
|
653 DEBUG_LOG(_L("[IDr]")); |
|
654 Isakmp_Phase1_IdL(buf, id_payload); |
|
655 } |
|
656 else //PHASE_II |
|
657 { |
|
658 DEBUG_LOG(_L("[IDcr]")); |
|
659 id_payload.SetIDType(iNegotiation->iRemoteIDType_II); |
|
660 |
|
661 id_payload.SetPort(iNegotiation->iIDRemotePort); //defined when receiving the acquire (INIT) or when receiving the ID payload (RESP) |
|
662 |
|
663 switch (iNegotiation->iRemoteIDType_II) |
|
664 { |
|
665 case ID_IPV4_ADDR: |
|
666 id_payload.SetLength((TUint16)(sizeof(id_payload) + sizeof(TUint32))); //IPV4 addr TInt32 |
|
667 num = ByteOrder::Swap32(iNegotiation->iRemoteAddr1_ID_II.Address());//Put in network order |
|
668 pnum= (TUint8*)# |
|
669 buf.Append(pnum,sizeof(TUint32)); |
|
670 break; |
|
671 case ID_IPV6_ADDR: |
|
672 id_payload.SetLength((TUint16)(sizeof(id_payload) + 16)); //IPV6 size is 16 |
|
673 pnum = &iNegotiation->iRemoteAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
674 buf.Append(pnum, 16); |
|
675 break; |
|
676 case ID_IPV4_ADDR_SUBNET: |
|
677 id_payload.SetLength((TUint16)(sizeof(id_payload) + 2*sizeof(TUint32))); //IPV4 addr TInt32 |
|
678 num = ByteOrder::Swap32(iNegotiation->iRemoteAddr1_ID_II.Address());//Put in network order |
|
679 pnum= (TUint8*)# |
|
680 buf.Append(pnum,sizeof(TUint32)); |
|
681 num = ByteOrder::Swap32(iNegotiation->iRemoteAddr2_ID_II.Address());//Put in network order |
|
682 pnum= (TUint8*)# |
|
683 buf.Append(pnum,sizeof(TUint32)); |
|
684 break; |
|
685 case ID_IPV6_ADDR_SUBNET: |
|
686 id_payload.SetLength((TUint16)(sizeof(id_payload) + 32)); //one IPV6 addr size is 16 |
|
687 pnum = &iNegotiation->iRemoteAddr1_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
688 buf.Append(pnum, 16); |
|
689 pnum = &iNegotiation->iRemoteAddr2_ID_II.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
690 buf.Append(pnum, 16); |
|
691 break; |
|
692 default: |
|
693 DEBUG_LOG(_L("Bad Remote Phase_II ID type")); |
|
694 iNegotiation->SetFinished(); |
|
695 return; |
|
696 //No need for a default. Must be controlled way before when acquire or IDs received |
|
697 } |
|
698 } |
|
699 } |
|
700 *iNextPayload = ISAKMP_PAYLOAD_ID; //Fills the previous payload next field |
|
701 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. |
|
702 //Will be filled by the next called function |
|
703 iBuf.Append((TUint8 *)&id_payload, sizeof(id_payload)); |
|
704 iBuf.Append(buf); //variable size |
|
705 |
|
706 //stores the payload to be used in HASH_R/I computation (Only for phase I) |
|
707 if ((iNegotiation->iPhase == PHASE_I) && (aIsOwn)) |
|
708 { |
|
709 TUint8 *p_ident=iNextPayload+sizeof(TPayloadISAKMP); //Data field |
|
710 |
|
711 iNegotiation->iOwnIdentPayloadSize=id_payload.GetLength()-sizeof(TPayloadISAKMP); //without the generic part! |
|
712 |
|
713 if (iNegotiation->iOwnIdentPayload) //in case it contains info |
|
714 { |
|
715 delete iNegotiation->iOwnIdentPayload; |
|
716 iNegotiation->iOwnIdentPayload = NULL; |
|
717 } |
|
718 iNegotiation->iOwnIdentPayload = new (ELeave) TUint8[iNegotiation->iOwnIdentPayloadSize]; //Generic payload NOT included |
|
719 Mem::Copy(iNegotiation->iOwnIdentPayload,p_ident,iNegotiation->iOwnIdentPayloadSize); |
|
720 } |
|
721 |
|
722 } |
|
723 |
|
724 void TIkev1IsakmpStream::Isakmp_Phase1_IdL(TDes8& aIdData, TIdentISAKMP& aIdPayload) |
|
725 { |
|
726 if ( iNegotiation->iNAT_D_Flags ) |
|
727 aIdPayload.SetPort(0); |
|
728 else aIdPayload.SetPort(IKE_PORT); |
|
729 |
|
730 TBool IdOk = EFalse; |
|
731 TUint8 IdType = iNegotiation->iHostData->iIdType; |
|
732 if (IdType == ID_USER_FQDN || IdType == ID_DER_ASN1_DN) |
|
733 { |
|
734 if (!iNegotiation->iOwnCert) //If not yet read |
|
735 { |
|
736 iNegotiation->ReadOwnCertL(); |
|
737 } |
|
738 } |
|
739 if ( iNegotiation->iOwnCert && iNegotiation->iPkiService ) |
|
740 { |
|
741 // |
|
742 // Priority 1 : Use IKE identity based on local certificate |
|
743 // |
|
744 TPtrC8 Cert(iNegotiation->iOwnCert->Des()); |
|
745 HBufC8* CertIdBfr = IkePkiUtils::GetIdentityFromCertL(IdType, Cert); |
|
746 if ( CertIdBfr ) |
|
747 { |
|
748 if ( CertIdBfr->Des().Length() <= aIdData.MaxLength() ) |
|
749 { |
|
750 aIdData.Copy(CertIdBfr->Des()); |
|
751 if ( IdType == 0 ) |
|
752 IdType = ID_DER_ASN1_DN; |
|
753 IdOk = ETrue; |
|
754 } |
|
755 delete CertIdBfr; |
|
756 } |
|
757 } |
|
758 |
|
759 if ( !IdOk ) |
|
760 { |
|
761 // |
|
762 // Priority 2 : Use identity defined in policy |
|
763 // |
|
764 TInt DataLength = iNegotiation->iHostData->iFQDN.Length(); |
|
765 IdType = iNegotiation->iHostData->iIdType; |
|
766 if ( ( DataLength > 0 ) && ( DataLength <= aIdData.MaxLength()) ) |
|
767 { |
|
768 if ( (IdType != ID_KEY_ID) && (IdType != ID_USER_FQDN) && (IdType != ID_FQDN) ) |
|
769 IdType = ID_KEY_ID; |
|
770 aIdData.Copy(iNegotiation->iHostData->iFQDN); |
|
771 IdOk = ETrue; |
|
772 } |
|
773 } |
|
774 |
|
775 if ( !IdOk ) |
|
776 { |
|
777 // |
|
778 // Priority 3 : Build local id from own IP address |
|
779 // |
|
780 TUint32 num; |
|
781 const TUint8 *pnum; |
|
782 if ((iNegotiation->iLocalAddr.Family() == KAfInet) || iNegotiation->iLocalAddr.IsV4Mapped() ) |
|
783 { |
|
784 IdType = ID_IPV4_ADDR; |
|
785 num = ByteOrder::Swap32(iNegotiation->iLocalAddr.Address());//Put in network order |
|
786 pnum = (TUint8*)# |
|
787 aIdData.Copy(pnum, sizeof(TUint32)); |
|
788 } |
|
789 else |
|
790 { |
|
791 IdType = ID_IPV6_ADDR; |
|
792 pnum = &iNegotiation->iLocalAddr.Ip6Address().u.iAddr8[0]; //Address in a bytestream |
|
793 aIdData.Copy(pnum, 16); |
|
794 } |
|
795 } |
|
796 |
|
797 aIdPayload.SetLength((TUint16)(sizeof(aIdPayload) + aIdData.Length())); |
|
798 aIdPayload.SetIDType(IdType); |
|
799 |
|
800 } |
|
801 |
|
802 |
|
803 |
|
804 void TIkev1IsakmpStream::IsakmpCertificateL() |
|
805 { |
|
806 TCertificateISAKMP *cert; |
|
807 |
|
808 if (!iNegotiation->iSendCert) //Set by a received cert request or ourselves if initiator |
|
809 return; |
|
810 |
|
811 if (!iNegotiation->iOwnCert) //If not yet read |
|
812 { |
|
813 if (!iNegotiation->ReadOwnCertL()) |
|
814 { |
|
815 iNegotiation->SetFinished(); |
|
816 return; |
|
817 } |
|
818 } |
|
819 DEBUG_LOG(_L("[CERT]")); |
|
820 *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field |
|
821 cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); |
|
822 iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function |
|
823 |
|
824 TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data |
|
825 |
|
826 cert_ptr.Copy(iNegotiation->iOwnCert->Des()); |
|
827 cert->SetReserved(0); |
|
828 cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); |
|
829 cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) |
|
830 iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added |
|
831 if ( iNegotiation->iICA2 ) |
|
832 { |
|
833 DEBUG_LOG(_L("[Level 2 INTERMEDIATE CERT]")); |
|
834 *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field |
|
835 cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); |
|
836 iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function |
|
837 |
|
838 TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data |
|
839 |
|
840 cert_ptr.Copy(iNegotiation->iICA2->Des()); |
|
841 cert->SetReserved(0); |
|
842 cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); |
|
843 cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) |
|
844 iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added |
|
845 } |
|
846 if ( iNegotiation->iICA1 ) |
|
847 { |
|
848 DEBUG_LOG(_L("[Level 1 INTERMEDIATE CERT]")); |
|
849 *iNextPayload = ISAKMP_PAYLOAD_CERT; //Fills the previous payload next field |
|
850 cert = (TCertificateISAKMP*)(iBuf.Ptr() + iBuf.Length()); |
|
851 iNextPayload = (TUint8 *)cert;//saves the adress.Will be filled by the next called function |
|
852 |
|
853 TPtr8 cert_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the Cert. Data |
|
854 |
|
855 cert_ptr.Copy(iNegotiation->iICA1->Des()); |
|
856 cert->SetReserved(0); |
|
857 cert->SetLength((TUint16)(TCertificateISAKMP::Size() + cert_ptr.Size())); |
|
858 cert->SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) |
|
859 iBuf.SetLength(iBuf.Length() + TCertificateISAKMP::Size() + cert_ptr.Size()); //The new info just added |
|
860 } |
|
861 } |
|
862 |
|
863 |
|
864 void TIkev1IsakmpStream::IsakmpCertificateReqL() |
|
865 { |
|
866 if ( !iNegotiation->iPkiService || !iNegotiation->iPkiService->CaList()) |
|
867 return; |
|
868 CIkeCaList* CaList = iNegotiation->iPkiService->CaList(); |
|
869 TCertificateReqISAKMP cert_req; |
|
870 CX509Certificate *ca_cert; |
|
871 TInt count = CaList->Count(); |
|
872 TInt i = 0; |
|
873 |
|
874 while ( i < count ) { |
|
875 |
|
876 DEBUG_LOG(_L("[CR]")); |
|
877 ca_cert = CaList->At(i)->Certificate(); |
|
878 *iNextPayload = ISAKMP_PAYLOAD_CR; //Fills the previous payload next field |
|
879 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. Will be filled by the next called function |
|
880 TPtr8 certreq_data_ptr((TUint8 *)iBuf.Ptr() + iBuf.Length() + TCertificateReqISAKMP::Size(), 0, iBuf.MaxLength() - iBuf.Length()); //Pointer to the CertReq. Data |
|
881 IkePkiUtils::GetCertSubjectNameDERL(ca_cert, certreq_data_ptr); |
|
882 cert_req.SetLength((TUint16)(TCertificateReqISAKMP::Size() + certreq_data_ptr.Size())); |
|
883 cert_req.SetEncoding(iNegotiation->iEncoding); //If responder the same as initiator, otherwise any? (now only X509) |
|
884 iBuf.Append((TUint8 *)&cert_req, TCertificateReqISAKMP::Size()); |
|
885 iBuf.SetLength(iBuf.Length()+ certreq_data_ptr.Size()); |
|
886 |
|
887 i ++; |
|
888 } |
|
889 |
|
890 iNegotiation->iCertRequested = ETrue; |
|
891 } |
|
892 |
|
893 |
|
894 void TIkev1IsakmpStream::IsakmpHashL() |
|
895 { |
|
896 DEBUG_LOG(_L("[HASH]")); |
|
897 THashISAKMP hash_payload; |
|
898 TBuf8<ISAKMP_HASH_SIZE> hash; |
|
899 TUint8 exchange = ThdrISAKMP::Ptr(iBuf)->GetExchange(); |
|
900 switch (exchange) |
|
901 { |
|
902 case ISAKMP_EXCHANGE_ID: //Main mode |
|
903 case ISAKMP_EXCHANGE_AGGR: //Main mode |
|
904 *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field |
|
905 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. |
|
906 |
|
907 if (iNegotiation->iRole==INITIATOR) |
|
908 { |
|
909 DEBUG_LOG(_L("[HASH_I]")); |
|
910 iNegotiation->ComputeHash1L(hash); //Must be done after Isakmp_IDENT to have the correct Id payload |
|
911 hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); |
|
912 iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); |
|
913 //iBuf.Append(iNegotiation->iHASH_I,iNegotiation->iHASH_ILen); |
|
914 iBuf.Append(hash); |
|
915 |
|
916 } |
|
917 else //RESP |
|
918 { |
|
919 DEBUG_LOG(_L("[HASH_R]")); |
|
920 iNegotiation->ComputeHashrL(hash); //Must be done after Isakmp_IDENT to have the correct Id payload |
|
921 hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); |
|
922 iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); |
|
923 //iBuf.Append(iNegotiation->iHASH_R,iNegotiation->iHASH_RLen); |
|
924 iBuf.Append(hash); |
|
925 } |
|
926 break; |
|
927 |
|
928 case IKE_QUICK_MODE: |
|
929 *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field |
|
930 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the adress. |
|
931 switch (iNegotiation->iStage) |
|
932 { |
|
933 case 1://Require 2-stage hash payload construction |
|
934 case 2: |
|
935 case 4: |
|
936 iHash_pos=iBuf.Length(); //Saves the pos to put the payload later in Isakmp_HASH_cont |
|
937 //Leaves free space for the buffer |
|
938 iBuf.SetLength(iBuf.Length() + sizeof(THashISAKMP) + iNegotiation->HashLength()); |
|
939 break; |
|
940 default: //stage 3 |
|
941 DEBUG_LOG(_L("[HASH(3)]")); |
|
942 iNegotiation->ComputeHash2L(hash, iNegotiation->iStage); |
|
943 hash_payload.SetLength((TUint16)(hash.Length() + sizeof(THashISAKMP))); |
|
944 iBuf.Append((TUint8 *)&hash_payload, sizeof(hash_payload)); |
|
945 iBuf.Append(hash); //Puts the hash in the correct position. iHashPos fills by Isakmp_HASH() |
|
946 } |
|
947 break; |
|
948 |
|
949 case ISAKMP_EXCHANGE_INFO: |
|
950 case ISAKMP_EXCHANGE_TRANSACT: |
|
951 *iNextPayload = ISAKMP_PAYLOAD_HASH; //Fills the previous payload next field |
|
952 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
953 iHash_pos = iBuf.Length(); //Saves the pos to put the payload later in Isakmp_HASH_cont |
|
954 //Leaves free space for the buffer |
|
955 iBuf.SetLength(iBuf.Length() + sizeof(THashISAKMP) + iNegotiation->HashLength()); |
|
956 break; |
|
957 |
|
958 default: |
|
959 DEBUG_LOG(_L("ISAKMP_HASH payload build error")); |
|
960 iNegotiation->SetFinished(); |
|
961 } |
|
962 } |
|
963 |
|
964 //Insert the hash in the designed position. Only Phase_II stage 1 or 2 |
|
965 void TIkev1IsakmpStream::IsakmpHashContL() |
|
966 { |
|
967 THashISAKMP hash; |
|
968 TBuf8<ISAKMP_HASH_SIZE> tmp_hash; |
|
969 |
|
970 //to put the correct next_payload value we check in the buffer because the next |
|
971 //payload will have updated the value there |
|
972 THashISAKMP *fake_hdr=(THashISAKMP *)(iBuf.Ptr() + iHash_pos); |
|
973 hash.SetPayload(fake_hdr->GetPayload()); |
|
974 TInt hash_len=sizeof(THashISAKMP) + iNegotiation->HashLength(); |
|
975 hash.SetLength((TUint16)hash_len); |
|
976 tmp_hash.Copy((TUint8 *)&hash,sizeof(hash)); |
|
977 iBuf.Replace(iHash_pos, tmp_hash.Length(),tmp_hash); |
|
978 iHash_pos += tmp_hash.Length(); |
|
979 |
|
980 TUint8 *hashMsg=((TUint8 *)iBuf.Ptr() + sizeof(ThdrISAKMP) + hash_len); //Msg to hash |
|
981 TInt hashMsgLen= iBuf.Length()- sizeof(ThdrISAKMP) - hash_len; |
|
982 switch (iNegotiation->iExchange) |
|
983 { |
|
984 case IKE_QUICK_MODE: |
|
985 if (iNegotiation->iStage != 4) |
|
986 iNegotiation->ComputeHash2L(tmp_hash, iNegotiation->iStage, hashMsg, hashMsgLen); |
|
987 else //Send CONNECT message is informational although in Quick mode |
|
988 iNegotiation->ComputeHashInfL(tmp_hash, hashMsg, hashMsgLen); |
|
989 break; |
|
990 case ISAKMP_EXCHANGE_INFO: |
|
991 case ISAKMP_EXCHANGE_TRANSACT: |
|
992 iNegotiation->ComputeHashInfL(tmp_hash, hashMsg, hashMsgLen); |
|
993 break; |
|
994 default: |
|
995 DEBUG_LOG(_L("ISAKMP_HASH_contL")); |
|
996 iNegotiation->SetFinished(); |
|
997 } |
|
998 iBuf.Replace(iHash_pos,tmp_hash.Length(),tmp_hash); //Puts the hash in the correct position. iHashPos fills by Isakmp_HASH() |
|
999 } |
|
1000 |
|
1001 void TIkev1IsakmpStream::IsakmpSignatureL() |
|
1002 { |
|
1003 TSignatureISAKMP sig; |
|
1004 TBuf8<ISAKMP_HASH_SIZE> hash; |
|
1005 |
|
1006 DEBUG_LOG(_L("[SIG]")); |
|
1007 if ( !iNegotiation->iPkiService ) |
|
1008 return; |
|
1009 |
|
1010 //DSS only allows SHA1 as hash |
|
1011 TUint16 tmp = iNegotiation->iChosenProposal_I.iAttrList->iHashAlg; //save the value to compute the hash with SHA1 if using DSS |
|
1012 |
|
1013 //First computes hash |
|
1014 if (iNegotiation->iRole==INITIATOR) |
|
1015 { |
|
1016 iNegotiation->ComputeHash1L(hash); //Must be done after Isakmp_IDENT to have the correct Id payload |
|
1017 } |
|
1018 else |
|
1019 { |
|
1020 iNegotiation->ComputeHashrL(hash); //Must be done after Isakmp_IDENT to have the correct Id payload |
|
1021 } |
|
1022 iNegotiation->iChosenProposal_I.iAttrList->iHashAlg = tmp; //Restore the value after computing the hash |
|
1023 |
|
1024 *iNextPayload = ISAKMP_PAYLOAD_SIG; //Fills the previous payload next field |
|
1025 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1026 //Will be filled by the next called function |
|
1027 TSignatureISAKMP *p_sig=(TSignatureISAKMP *)(iBuf.Ptr() + iBuf.Length()); //To update the payload size later |
|
1028 iBuf.Append((TUint8 *)&sig, sizeof(sig)); |
|
1029 |
|
1030 TPtr8 sig_data_ptr((TUint8 *)(iBuf.Ptr() + iBuf.Length()), iBuf.MaxLength() - iBuf.Length()); |
|
1031 |
|
1032 DEBUG_LOG1(_L("sig_data_ptr length=%d"), sig_data_ptr.Length()); |
|
1033 if ( iNegotiation->iPkiService->Ikev1SignatureL(iNegotiation->iPeerTrustedCA->Des(), |
|
1034 iNegotiation->iHostData, |
|
1035 hash, sig_data_ptr) == 0 ) |
|
1036 { |
|
1037 DEBUG_LOG(_L("Signature Computation failed!")); |
|
1038 } |
|
1039 |
|
1040 DEBUG_LOG(_L("Signature")); |
|
1041 iBuf.SetLength(iBuf.Length() + sig_data_ptr.Length()); //updates the buffer size |
|
1042 p_sig->SetLength((TUint16)(sizeof(sig) + sig_data_ptr.Length())); //Puts the correct length in the buffer |
|
1043 } |
|
1044 |
|
1045 //Adds the Nonce payload to the buffer |
|
1046 void TIkev1IsakmpStream::IsakmpNonce() |
|
1047 { |
|
1048 TNonceISAKMP nonce_payload; |
|
1049 |
|
1050 //iNegotiation->ComputeNonce(); //Nonce to be sent |
|
1051 nonce_payload.SetLength((TUint16)(sizeof(nonce_payload) + OAKLEY_DEFAULT_NONCE_SIZE)); |
|
1052 *iNextPayload = ISAKMP_PAYLOAD_NONCE; //Fills the previous payload next field |
|
1053 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1054 //Will be filled by the next called function |
|
1055 iBuf.Append((TUint8 *)&nonce_payload, sizeof(nonce_payload)); |
|
1056 if (iNegotiation->iRole==INITIATOR) |
|
1057 { |
|
1058 DEBUG_LOG(_L("[NONCE_I]")); |
|
1059 iBuf.Append(iNegotiation->iNONCE_I); //variable size |
|
1060 } |
|
1061 else |
|
1062 { |
|
1063 DEBUG_LOG(_L("[NONCE_R]")); |
|
1064 iBuf.Append(iNegotiation->iNONCE_R); //variable size |
|
1065 } |
|
1066 |
|
1067 } |
|
1068 |
|
1069 //Adds the Notification payload to the buffer |
|
1070 void TIkev1IsakmpStream::IsakmpNotification(TUint16 aType, TUint8 aProtocol, TUint8* aNotifData, TInt aDataLth) |
|
1071 { |
|
1072 TNotificationISAKMP notif; |
|
1073 |
|
1074 TBuf8<2*ISAKMP_COOKIE_SIZE> spi; |
|
1075 |
|
1076 spi.Copy(iNegotiation->iCookie_I); |
|
1077 spi.Append(iNegotiation->iCookie_R); |
|
1078 |
|
1079 DEBUG_LOG(_L("[NOT]")); |
|
1080 *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field |
|
1081 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1082 TUint16 length = (TUint16)(sizeof(notif) + spi.Length() + aDataLth); |
|
1083 |
|
1084 notif.SetLength(length); |
|
1085 notif.SetDOI(iNegotiation->iDOI); |
|
1086 notif.SetProtocol(aProtocol); |
|
1087 notif.SetSPISize((TUint8)spi.Length()); |
|
1088 notif.SetMsgType(aType); |
|
1089 //Will be filled by the next called function |
|
1090 iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header |
|
1091 iBuf.Append(spi); //insert the SPI |
|
1092 |
|
1093 if ( aNotifData && aDataLth ) |
|
1094 iBuf.Append(aNotifData, aDataLth); //Add Notification data |
|
1095 |
|
1096 } |
|
1097 |
|
1098 //Adds the Notification payload to the buffer |
|
1099 void TIkev1IsakmpStream::IsakmpReplayStatus(TUint8 aProtocol, TUint32 aSPI, TUint8 aReplayWindowLength) |
|
1100 { |
|
1101 TNotificationISAKMP notif; |
|
1102 TUint32 data; |
|
1103 |
|
1104 DEBUG_LOG(_L("[NOT]")); |
|
1105 *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field |
|
1106 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1107 notif.SetLength((TUint16)(sizeof(notif) + sizeof(aSPI) + sizeof(data))); //No Notification Data yet!!! |
|
1108 notif.SetDOI(iNegotiation->iDOI); |
|
1109 notif.SetProtocol(aProtocol); |
|
1110 notif.SetSPISize(sizeof(aSPI)); //No SPI sent |
|
1111 notif.SetMsgType(DOI_REPLAY_STATUS); |
|
1112 //Will be filled by the next called function |
|
1113 iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header |
|
1114 iBuf.Append((TUint8 *)&aSPI, sizeof(aSPI)); //Insert the SPI |
|
1115 |
|
1116 // Notification Data: 0 if replay detection disabled |
|
1117 // 1 if replay detection enabled |
|
1118 |
|
1119 if (aReplayWindowLength > 0) |
|
1120 data = ByteOrder::Swap32(1); |
|
1121 else |
|
1122 data = 0; |
|
1123 iBuf.Append((TUint8 *)&data, sizeof(data)); |
|
1124 |
|
1125 } |
|
1126 |
|
1127 //Adds the Notification payload to the buffer |
|
1128 void TIkev1IsakmpStream::IsakmpResponderLifetime(TUint8 aProtocol, TUint32 aSPI, const TDesC8 &aLifetime, const TDesC8 &aLifesize) |
|
1129 { |
|
1130 TNotificationISAKMP notif; |
|
1131 TDataISAKMP attr; |
|
1132 |
|
1133 DEBUG_LOG(_L("[NOT]")); |
|
1134 *iNextPayload = ISAKMP_PAYLOAD_NOTIF; //Fills the previous payload next field |
|
1135 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1136 |
|
1137 //Notification payload + spi + attribs lifetype and life value |
|
1138 TInt attrlen = 0; |
|
1139 if (aLifetime.Length() > 0) |
|
1140 attrlen = 2*sizeof(attr) + aLifetime.Length(); |
|
1141 if (aLifesize.Length() > 0) |
|
1142 attrlen += 2*sizeof(attr) + aLifesize.Length(); |
|
1143 if (attrlen == 0) //No lifevalues to send |
|
1144 return; |
|
1145 |
|
1146 notif.SetLength((TUint16)(sizeof(notif) + sizeof(aSPI) + attrlen)); |
|
1147 notif.SetDOI(iNegotiation->iDOI); |
|
1148 notif.SetProtocol(aProtocol); |
|
1149 notif.SetSPISize(sizeof(aSPI)); //No SPI sent |
|
1150 notif.SetMsgType(DOI_RESPONDER_LIFETIME); |
|
1151 //Will be filled by the next called function |
|
1152 iBuf.Append((TUint8 *)¬if, sizeof(notif)); //Header |
|
1153 iBuf.Append((TUint8 *)&aSPI, sizeof(aSPI)); //Insert the SPI |
|
1154 |
|
1155 //Lifetime |
|
1156 if (aLifetime.Length() > 0) |
|
1157 { |
|
1158 //LifeType |
|
1159 attr.SetBasic(ETrue); |
|
1160 attr.SetType(DOI_ATTR_TYPE_LIFE_TYPE); |
|
1161 attr.SetValue(SECONDS); |
|
1162 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1163 |
|
1164 //Life Value |
|
1165 attr.SetBasic(EFalse); |
|
1166 attr.SetType(DOI_ATTR_TYPE_LIFE_DUR); |
|
1167 attr.SetLength((TUint16)(aLifetime.Length())); |
|
1168 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1169 iBuf.Append(aLifetime); |
|
1170 } |
|
1171 |
|
1172 //Lifesize |
|
1173 if (aLifesize.Length() > 0) |
|
1174 { |
|
1175 //LifeType |
|
1176 attr.SetBasic(ETrue); |
|
1177 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_TYPE); |
|
1178 attr.SetValue(KBYTES); |
|
1179 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1180 |
|
1181 //Life Value |
|
1182 attr.SetBasic(EFalse); |
|
1183 attr.SetType(OAKLEY_ATTR_TYPE_LIFE_DUR); |
|
1184 attr.SetLength((TUint16)(aLifesize.Length())); |
|
1185 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1186 iBuf.Append(aLifesize); |
|
1187 } |
|
1188 } |
|
1189 |
|
1190 |
|
1191 //Only send 1 SPI for the ISAKMP SA, AH or ESP |
|
1192 void TIkev1IsakmpStream::IsakmpDelete(TDesC8 &aSPI, TUint8 aProtocol) |
|
1193 { |
|
1194 TDeleteISAKMP delete_payload; |
|
1195 |
|
1196 DEBUG_LOG(_L("[DEL]")); |
|
1197 |
|
1198 *iNextPayload = ISAKMP_PAYLOAD_D; //Fills the previous payload next field |
|
1199 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1200 |
|
1201 delete_payload.SetLength((TUint16)(sizeof(delete_payload) + aSPI.Length())); //No Notification Data yet!!! |
|
1202 delete_payload.SetDOI(iNegotiation->iDOI); |
|
1203 delete_payload.SetProtocol(aProtocol); |
|
1204 delete_payload.SetSPISize((TUint8)aSPI.Length()); |
|
1205 delete_payload.SetNumSPI(1); |
|
1206 |
|
1207 iBuf.Append((TUint8 *)&delete_payload, sizeof(delete_payload)); //Header |
|
1208 iBuf.Append(aSPI); //insert the SPI |
|
1209 } |
|
1210 |
|
1211 //Adds the Vendor ID payload to the buffer |
|
1212 void TIkev1IsakmpStream::IsakmpVendorId(TInt aID_Type, |
|
1213 TUint8 *aICOOKIE, |
|
1214 TUint8 *aRCOOKIE, |
|
1215 TInetAddr &aLocalAddr, |
|
1216 TUint8 *aGenericVidData, TInt aGenericVidLth ) |
|
1217 { |
|
1218 |
|
1219 *iNextPayload = ISAKMP_PAYLOAD_VID; //Fills the previous payload next field |
|
1220 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length()); |
|
1221 |
|
1222 if ( (aID_Type == IETF_NATT_VENDOR_ID || aID_Type == IETF_RFC_NATT_VENDOR_ID) && aGenericVidData ) { |
|
1223 TVendorISAKMP vendor_payload; |
|
1224 vendor_payload.SetLength((TUint16)(sizeof(vendor_payload) + aGenericVidLth)); |
|
1225 iBuf.Append((TUint8 *)&vendor_payload, sizeof(vendor_payload)); //Header |
|
1226 iBuf.Append(aGenericVidData, aGenericVidLth); //Data |
|
1227 return; |
|
1228 } |
|
1229 /*-------------------------------------------------------- |
|
1230 * |
|
1231 * If an expanded Vendor Id required build it, otherwise |
|
1232 * use "old" style" short Vendor Id, |
|
1233 * |
|
1234 *--------------------------------------------------------*/ |
|
1235 TBool ExpandedVID; |
|
1236 |
|
1237 if ( aID_Type == EXPANDED_VENDOR_ID ) |
|
1238 ExpandedVID = ETrue; |
|
1239 else ExpandedVID = EFalse; |
|
1240 |
|
1241 TInt payload_lth = ConstructVendorId(ExpandedVID, |
|
1242 aICOOKIE, |
|
1243 aRCOOKIE, |
|
1244 aLocalAddr, |
|
1245 (TVendorISAKMP*)iNextPayload); |
|
1246 iBuf.SetLength(iBuf.Length() + payload_lth); //The new info just added |
|
1247 |
|
1248 } |
|
1249 |
|
1250 |
|
1251 void TIkev1IsakmpStream::IsakmpChre(TUint16 aLAMType, TUint16 aAttr1, HBufC8 *aBfr1, |
|
1252 TUint16 aAttr2, HBufC8 *aBfr2, TUint16 aAttr3, HBufC8 *aBfr3) |
|
1253 { |
|
1254 TCHREISAKMP chre_payload; |
|
1255 |
|
1256 DEBUG_LOG(_L("[CHRE]")); |
|
1257 |
|
1258 *iNextPayload = ISAKMP_PAYLOAD_CHRE; //Fills the previous payload next field |
|
1259 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1260 /*---------------------------------------------------- |
|
1261 * Fill generic payload header fields (except length) |
|
1262 *----------------------------------------------------*/ |
|
1263 chre_payload.SetLAMtype(aLAMType); |
|
1264 chre_payload.SetCHREReserved(); |
|
1265 TInt pos = iBuf.Length(); //save the position to insert later |
|
1266 iBuf.SetLength(pos + sizeof(chre_payload)); //leave room to insert later |
|
1267 |
|
1268 /*---------------------------------------------------- |
|
1269 * Store CHRE payload attribute data |
|
1270 *----------------------------------------------------*/ |
|
1271 if ( aAttr1 !=0 ) |
|
1272 IsakmpChreAttrib(aAttr1, aBfr1); |
|
1273 if ( aAttr2 !=0 ) |
|
1274 IsakmpChreAttrib(aAttr2, aBfr2); |
|
1275 if ( aAttr3 !=0 ) |
|
1276 IsakmpChreAttrib(aAttr3, aBfr3); |
|
1277 /*---------------------------------------------------- |
|
1278 * Store correct payload length |
|
1279 *----------------------------------------------------*/ |
|
1280 chre_payload.SetLength((TUint16)(iBuf.Length() - pos)); |
|
1281 TBuf8<sizeof(chre_payload)> aux; |
|
1282 aux.Append((TUint8 *)&chre_payload, sizeof(chre_payload)); |
|
1283 iBuf.Replace(pos, aux.Length(), aux); |
|
1284 } |
|
1285 |
|
1286 void TIkev1IsakmpStream::IsakmpChreAttrib(TUint16 aType, HBufC8 *aBfr) |
|
1287 { |
|
1288 /*---------------------------------------------------- |
|
1289 * Store CHRE payload attribute data (variable length) |
|
1290 *----------------------------------------------------*/ |
|
1291 TDataISAKMP attr; |
|
1292 TUint length; |
|
1293 attr.SetBasic(EFalse); |
|
1294 attr.SetType(aType); |
|
1295 if ( aBfr ) |
|
1296 length = aBfr->Length(); |
|
1297 else length = 0; |
|
1298 attr.SetLength((TUint16)length); |
|
1299 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1300 if ( length ) |
|
1301 iBuf.Append(aBfr->Ptr(),length); |
|
1302 } |
|
1303 |
|
1304 |
|
1305 void TIkev1IsakmpStream::IsakmpIntnet(TUint32 aIpv4Addr) |
|
1306 { |
|
1307 /*---------------------------------------------------------- |
|
1308 * Build inititor (=client) private Internal Address payload |
|
1309 * Payload contains only PRI_INTERNAL_ADDRESS attribute coded |
|
1310 * as a basic attribute with value 0. |
|
1311 *---------------------------------------------------------*/ |
|
1312 TINTNETISAKMP intnet_payload; |
|
1313 TDataISAKMP attr; |
|
1314 |
|
1315 DEBUG_LOG(_L("[IA]")); |
|
1316 |
|
1317 *iNextPayload = ISAKMP_INT_NETWORK; //Fills the previous payload next field |
|
1318 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1319 |
|
1320 intnet_payload.SetLength((TUint16)(sizeof(intnet_payload) + |
|
1321 (2 + 2))); //basic attribute |
|
1322 iBuf.Append((TUint8 *)&intnet_payload, |
|
1323 sizeof(intnet_payload)); //Payload Header |
|
1324 attr.SetBasic(ETrue); |
|
1325 attr.SetType(PRI_INTERNAL_ADDRESS); |
|
1326 attr.SetValue((TUint16)aIpv4Addr); |
|
1327 iBuf.Append((TUint8 *)&attr, sizeof(attr)); |
|
1328 |
|
1329 } |
|
1330 |
|
1331 void TIkev1IsakmpStream::IsakmpNatD(TBool aRfcNatt, TDesC8 &aHash) |
|
1332 { |
|
1333 /*------------------------------------------------------------ |
|
1334 * Build NAT-D related to NAT discovery. |
|
1335 * Payload data is a hash data defined as follows: |
|
1336 * HASH = HASH(CKY-I | CKY-R | IP | Port) |
|
1337 * using the negotiated HASH algorithm |
|
1338 *---------------------------------------------------------*/ |
|
1339 TNATDISAKMP nat_d_payload; |
|
1340 |
|
1341 DEBUG_LOG(_L("[NAT_D]")); |
|
1342 |
|
1343 if ( aRfcNatt ) |
|
1344 *iNextPayload = IETF_RFC_NAT_DISCOVERY; //Fills the previous payload next field |
|
1345 else |
|
1346 *iNextPayload = IETF_NAT_DISCOVERY; //Fills the previous payload next field |
|
1347 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1348 |
|
1349 nat_d_payload.SetLength((TUint16)(sizeof(nat_d_payload) + aHash.Length())); |
|
1350 iBuf.Append((TUint8 *)&nat_d_payload, sizeof(nat_d_payload)); //Header |
|
1351 iBuf.Append(aHash); //Data |
|
1352 |
|
1353 } |
|
1354 |
|
1355 void TIkev1IsakmpStream::IsakmpAttributes(TUint8 aMsgType, TUint16 aIdentifier, TDesC8 &aAttributes) |
|
1356 { |
|
1357 /*------------------------------------------------------------ |
|
1358 * Build Attributes payload. (used with config-mode and XAUTH) |
|
1359 *---------------------------------------------------------*/ |
|
1360 TAttributeISAKMP attr_payload; |
|
1361 attr_payload.SetCfgMsgType(aMsgType); |
|
1362 attr_payload.SetReservedField(); |
|
1363 attr_payload.SetIdentifier(aIdentifier); |
|
1364 |
|
1365 DEBUG_LOG(_L("[ATTR]")); |
|
1366 |
|
1367 *iNextPayload = ISAKMP_PAYLOAD_ATTRIBUTES; //Fills the previous payload next field |
|
1368 iNextPayload = (TUint8 *)(iBuf.Ptr() + iBuf.Length());//saves the address. |
|
1369 |
|
1370 attr_payload.SetLength((TUint16)(sizeof(attr_payload) + aAttributes.Length())); |
|
1371 iBuf.Append((TUint8 *)&attr_payload, sizeof(attr_payload)); //Header |
|
1372 iBuf.Append(aAttributes); //Data |
|
1373 } |