]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/Ikev2/Exchange.c
Before decrypting the packet, Ipsec will check if the inbound protected packet is...
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Exchange.c
CommitLineData
9166f840 1/** @file\r
2 The general interfaces of the IKEv2.\r
3\r
4 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Utility.h"\r
17#include "IpSecDebug.h"\r
18#include "IkeService.h"\r
19#include "IpSecConfigImpl.h"\r
20\r
21/**\r
22 General interface to intialize a IKEv2 negotiation.\r
23\r
24 @param[in] UdpService Point to Udp Servcie used for the IKE packet sending.\r
25 @param[in] SpdEntry Point to SPD entry related to this IKE negotiation.\r
26 @param[in] PadEntry Point to PAD entry related to this IKE negotiation.\r
27 @param[in] RemoteIp Point to IP Address which the remote peer to negnotiate.\r
28\r
29 @retval EFI_SUCCESS The operation is successful.\r
30 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
31 @retval EFI_INVALID_PARAMETER If UdpService or RemoteIp is NULL.\r
32 @return Others The operation is failed.\r
33\r
34**/\r
35EFI_STATUS\r
36Ikev2NegotiateSa (\r
37 IN IKE_UDP_SERVICE *UdpService,\r
38 IN IPSEC_SPD_ENTRY *SpdEntry,\r
39 IN IPSEC_PAD_ENTRY *PadEntry,\r
40 IN EFI_IP_ADDRESS *RemoteIp\r
41 )\r
42{\r
43 IPSEC_PRIVATE_DATA *Private;\r
44 IKEV2_SA_SESSION *IkeSaSession;\r
45 IKEV2_SESSION_COMMON *SessionCommon;\r
46 IKEV2_PACKET_HANDLER Handler;\r
47 IKE_PACKET *IkePacket;\r
48 EFI_STATUS Status;\r
49 \r
50 if (UdpService == NULL || RemoteIp == NULL) {\r
51 return EFI_INVALID_PARAMETER;\r
52 }\r
53\r
54 IkePacket = NULL;\r
55 Private = (UdpService->IpVersion == IP_VERSION_4) ?\r
56 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
57 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
58\r
59 //\r
60 // Lookup the remote ip address in the processing IKE SA session list.\r
61 //\r
62 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, RemoteIp);\r
63 if (IkeSaSession != NULL) {\r
64 //\r
65 // Drop the packet if already in process.\r
66 //\r
67 return EFI_SUCCESS;\r
68 }\r
69 \r
70 //\r
71 // Create a new IkeSaSession and initiate the common parameters.\r
72 //\r
73 IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
74 if (IkeSaSession == NULL) {\r
75 return EFI_OUT_OF_RESOURCES;\r
76 }\r
77\r
78 //\r
79 // Set the specific parameters and state(IKE_STATE_INIT).\r
80 //\r
81 IkeSaSession->Spd = SpdEntry;\r
82 IkeSaSession->Pad = PadEntry; \r
83 SessionCommon = &IkeSaSession->SessionCommon;\r
84 SessionCommon->IsInitiator = TRUE;\r
85 SessionCommon->State = IkeStateInit;\r
86 //\r
87 // TODO: Get the prefer DH Group from the IPsec Configuration, after the IPsecconfig application update\r
88 // to support it.\r
89 //\r
90 SessionCommon->PreferDhGroup = IKEV2_TRANSFORM_ID_DH_1024MODP;\r
91 \r
92 CopyMem (\r
93 &SessionCommon->RemotePeerIp,\r
94 RemoteIp,\r
95 sizeof (EFI_IP_ADDRESS)\r
96 );\r
97 \r
98 CopyMem (\r
99 &SessionCommon->LocalPeerIp,\r
100 &UdpService->DefaultAddress,\r
101 sizeof (EFI_IP_ADDRESS)\r
102 );\r
103\r
104 IKEV2_DUMP_STATE (SessionCommon->State, IkeStateInit);\r
105\r
106 //\r
107 // Initiate the SAD data of the IkeSaSession.\r
108 //\r
109 IkeSaSession->SaData = Ikev2InitializeSaData (SessionCommon);\r
110 if (IkeSaSession->SaData == NULL) {\r
111 Status = EFI_OUT_OF_RESOURCES;\r
112 goto ON_ERROR;\r
113 }\r
114\r
115 //\r
116 // Generate an IKE request packet and send it out.\r
117 //\r
118 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][SessionCommon->State];\r
119 IkePacket = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
120 if (IkePacket == NULL) {\r
121 Status = EFI_OUT_OF_RESOURCES;\r
122 goto ON_ERROR;\r
123 }\r
124\r
125 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SessionCommon, IkePacket, 0);\r
126\r
127 if (EFI_ERROR (Status)) {\r
128 goto ON_ERROR;\r
129 }\r
130\r
131 //\r
132 // Insert the current IkeSaSession into the processing IKE SA list.\r
133 //\r
134 Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, RemoteIp);\r
135\r
136 return EFI_SUCCESS;\r
137\r
138ON_ERROR:\r
139\r
140 if (IkePacket != NULL) {\r
141 IkePacketFree (IkePacket);\r
142 }\r
143 Ikev2SaSessionFree (IkeSaSession);\r
144 return Status;\r
145}\r
146\r
147/**\r
148 It is general interface to negotiate the Child SA.\r
149\r
150 There are three situations which will invoke this function. First, create a CHILD \r
151 SA if the input Context is NULL. Second, rekeying the existing IKE SA if the Context \r
152 is a IKEv2_SA_SESSION. Third, rekeying the existing CHILD SA if the context is a \r
153 IKEv2_CHILD_SA_SESSION.\r
154\r
155 @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
156 @param[in] SpdEntry Pointer to IPSEC_SPD_ENTRY related to this operation.\r
157 @param[in] Context The data pass from the caller.\r
158 \r
159 @retval EFI_SUCCESS The operation is successful.\r
160 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
161 @retval EFI_UNSUPPORTED The condition is not support yet.\r
162 @return Others The operation is failed.\r
163\r
164**/\r
165EFI_STATUS\r
166Ikev2NegotiateChildSa (\r
167 IN UINT8 *IkeSaSession,\r
168 IN IPSEC_SPD_ENTRY *SpdEntry,\r
169 IN UINT8 *Context\r
170 )\r
171{\r
172 EFI_STATUS Status;\r
173 IKEV2_SA_SESSION *SaSession;\r
174 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
175 IKEV2_SESSION_COMMON *ChildSaCommon;\r
176 IKE_PACKET *IkePacket;\r
177 IKE_UDP_SERVICE *UdpService;\r
178\r
179 SaSession = (IKEV2_SA_SESSION*) IkeSaSession;\r
180 UdpService = SaSession->SessionCommon.UdpService;\r
181 IkePacket = NULL;\r
182\r
183 //\r
184 // 1. Create another child SA session if context is null.\r
185 // 2. Rekeying the IKE SA session if the context is IKE SA session.\r
186 // 3. Rekeying the child SA session if the context is child SA session.\r
187 //\r
188 if (Context == NULL) {\r
189 //\r
190 // Create a new ChildSaSession and initiate the common parameters.\r
191 //\r
192 ChildSaSession = Ikev2ChildSaSessionAlloc (UdpService, SaSession);\r
193\r
194 if (ChildSaSession == NULL) {\r
195 return EFI_OUT_OF_RESOURCES;\r
196 }\r
197\r
198 //\r
199 // Set the specific parameters and state as IKE_STATE_CREATE_CHILD.\r
200 //\r
201 ChildSaSession->Spd = SpdEntry;\r
202 ChildSaCommon = &ChildSaSession->SessionCommon;\r
203 ChildSaCommon->IsInitiator = TRUE;\r
204 ChildSaCommon->State = IkeStateCreateChild;\r
205\r
206 IKEV2_DUMP_STATE (ChildSaCommon->State, IkeStateCreateChild);\r
207\r
208 if (SpdEntry->Selector->NextLayerProtocol != EFI_IPSEC_ANY_PROTOCOL) {\r
209 ChildSaSession->ProtoId = SpdEntry->Selector->NextLayerProtocol;\r
210 }\r
211\r
212 if (SpdEntry->Selector->LocalPort != EFI_IPSEC_ANY_PORT) {\r
213 ChildSaSession->LocalPort = SpdEntry->Selector->LocalPort;\r
214 }\r
215\r
216 if (SpdEntry->Selector->RemotePort != EFI_IPSEC_ANY_PORT) {\r
217 ChildSaSession->RemotePort = SpdEntry->Selector->RemotePort;\r
218 }\r
219 //\r
220 // Initiate the SAD data parameters of the ChildSaSession.\r
221 //\r
222 ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
223 if (ChildSaSession->SaData == NULL) {\r
224 Status = EFI_OUT_OF_RESOURCES;\r
225 goto ON_ERROR;\r
226 }\r
227 //\r
228 // Generate an IKE request packet and send it out.\r
229 //\r
230 IkePacket = mIkev2CreateChild.Generator ((UINT8 *) ChildSaSession, NULL);\r
231\r
232 if (IkePacket == NULL) {\r
233 Status = EFI_OUT_OF_RESOURCES;\r
234 goto ON_ERROR;\r
235 }\r
236\r
237 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) ChildSaCommon, IkePacket, 0);\r
238\r
239 if (EFI_ERROR (Status)) {\r
240 goto ON_ERROR;\r
241 }\r
242 \r
243 //\r
244 // Insert the ChildSaSession into processing child SA list.\r
245 //\r
246 Ikev2ChildSaSessionInsert (&SaSession->ChildSaSessionList, ChildSaSession);\r
247 } else {\r
248 //\r
249 // TODO: Rekeying IkeSaSession or ChildSaSession, NOT support yet.\r
250 //\r
251 // Rekey IkeSa, set IkeSaSession->State and pass over IkeSaSession\r
252 // Rekey ChildSa, set ChildSaSession->State and pass over ChildSaSession\r
253 //\r
254 return EFI_UNSUPPORTED;\r
255 }\r
256\r
257 return EFI_SUCCESS;\r
258\r
259ON_ERROR:\r
260\r
261 if (ChildSaSession->SaData != NULL) {\r
262 FreePool (ChildSaSession->SaData);\r
263 }\r
264\r
265 if (ChildSaSession->SessionCommon.TimeoutEvent != NULL) {\r
266 gBS->CloseEvent (ChildSaSession->SessionCommon.TimeoutEvent);\r
267 }\r
268\r
269 if (IkePacket != NULL) {\r
270 IkePacketFree (IkePacket);\r
271 }\r
272\r
273 Ikev2ChildSaSessionFree (ChildSaSession);\r
274 return Status;\r
275}\r
276\r
277/**\r
278 It is general interface to start the Information Exchange.\r
279\r
280 There are three situations which will invoke this function. First, deliver a Delete Information\r
281 to delete the IKE SA if the input Context is NULL and the state of related IkeSaSeesion's is on \r
282 deleting.Second, deliver a Notify Information without the contents if the input Context is NULL. \r
283 Third, deliver a Notify Information if the input Context is not NULL.\r
284\r
285 @param[in] IkeSaSession Pointer to IKEv2_SA_SESSION related to this operation.\r
286 @param[in] Context Data passed by caller.\r
287\r
288 @retval EFI_SUCCESS The operation is successful.\r
289 @retval EFI_OUT_OF_RESOURCES The required system resource can't be allocated.\r
290 @retval EFI_UNSUPPORTED The condition is not support yet.\r
291 @return Otherwise The operation is failed.\r
292\r
293**/\r
294EFI_STATUS\r
295Ikev2NegotiateInfo (\r
296 IN UINT8 *IkeSaSession,\r
297 IN UINT8 *Context\r
298 )\r
299{\r
300 \r
301 EFI_STATUS Status;\r
302 IKEV2_SA_SESSION *Ikev2SaSession;\r
303 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
304 IKEV2_SESSION_COMMON *SaCommon;\r
305 IKE_PACKET *IkePacket;\r
306 IKE_UDP_SERVICE *UdpService;\r
307 LIST_ENTRY *Entry;\r
308 LIST_ENTRY *NextEntry;\r
309\r
310 Ikev2SaSession = (IKEV2_SA_SESSION *) IkeSaSession;\r
311 UdpService = Ikev2SaSession->SessionCommon.UdpService;\r
312 SaCommon = &Ikev2SaSession->SessionCommon;\r
313 IkePacket = NULL;\r
314 Status = EFI_SUCCESS;\r
315\r
316 //\r
317 // Delete the IKE SA.\r
318 //\r
319 if (Ikev2SaSession->SessionCommon.State == IkeStateSaDeleting && Context == NULL) {\r
320\r
321 //\r
322 // The IKE SA Session should be initiator if it triggers the deleting.\r
323 //\r
324 Ikev2SaSession->SessionCommon.IsInitiator = TRUE;\r
325\r
326 //\r
327 // Generate Information Packet which contains the Delete Payload.\r
328 //\r
329 IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);\r
330 if (IkePacket == NULL) {\r
331 Status = EFI_OUT_OF_RESOURCES;\r
332 goto ON_ERROR;\r
333 }\r
334\r
335 //\r
336 // Send out the Packet\r
337 //\r
338 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);\r
339\r
340 if (EFI_ERROR (Status)) {\r
341 goto ON_ERROR;\r
342 }\r
343 } else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {\r
344 //\r
345 // Iterate all Deleting Child SAs.\r
346 //\r
347 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {\r
348 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);\r
349 ChildSaSession->SessionCommon.State = IkeStateSaDeleting;\r
350\r
351 //\r
352 // Generate Information Packet which contains the Child SA Delete Payload.\r
353 //\r
354 IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);\r
355 if (IkePacket == NULL) {\r
356 Status = EFI_OUT_OF_RESOURCES;\r
357 goto ON_ERROR;\r
358 }\r
359\r
360 //\r
361 // Send out the Packet\r
362 //\r
363 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);\r
364\r
365 if (EFI_ERROR (Status)) {\r
366 goto ON_ERROR;\r
367 }\r
368 }\r
369 } else if (Context == NULL) {\r
370 //\r
371 // TODO: Deliver null notification message.\r
372 //\r
373 } else if (Context != NULL) {\r
374 //\r
375 // TODO: Send out the Information Exchange which contains the Notify Payload.\r
376 //\r
377 }\r
378ON_ERROR:\r
379 if (IkePacket != NULL) {\r
380 IkePacketFree (IkePacket);\r
381 }\r
382 return Status;\r
383\r
384}\r
385\r
386/**\r
387 The general interface when received a IKEv2 packet for the IKE SA establishing.\r
388\r
389 This function first find the related IKE SA Session according to the IKE packet's \r
390 remote IP. Then call the corresponding function to handle this IKE packet according\r
391 to the related IKE SA Session's State. \r
392\r
393 @param[in] UdpService Pointer of related UDP Service.\r
394 @param[in] IkePacket Data passed by caller.\r
395\r
396**/\r
397VOID\r
398Ikev2HandleSa (\r
399 IN IKE_UDP_SERVICE *UdpService,\r
400 IN IKE_PACKET *IkePacket\r
401 )\r
402{\r
403 EFI_STATUS Status;\r
404 IKEV2_SA_SESSION *IkeSaSession;\r
405 IKEV2_CHILD_SA_SESSION *ChildSaSession;\r
406 IKEV2_SESSION_COMMON *IkeSaCommon;\r
407 IKEV2_SESSION_COMMON *ChildSaCommon;\r
408 IKEV2_PACKET_HANDLER Handler;\r
409 IKE_PACKET *Reply;\r
410 IPSEC_PAD_ENTRY *PadEntry;\r
411 IPSEC_PRIVATE_DATA *Private;\r
412 BOOLEAN IsNewSession;\r
413\r
414 Private = (UdpService->IpVersion == IP_VERSION_4) ? \r
415 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
416 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
417\r
418 ChildSaSession = NULL;\r
419 ChildSaCommon = NULL;\r
420 \r
421 //\r
422 // Lookup the remote ip address in the processing IKE SA session list.\r
423 //\r
424 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
425 IsNewSession = FALSE;\r
426\r
427 if (IkeSaSession == NULL) {\r
428 //\r
429 // Lookup the remote ip address in the pad.\r
430 //\r
431 PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);\r
432 if (PadEntry == NULL) {\r
433 //\r
434 // Drop the packet if no pad entry matched, this is the request from RFC 4301.\r
435 //\r
436 return ;\r
437 }\r
438\r
439 //\r
440 // Create a new IkeSaSession and initiate the common parameters.\r
441 //\r
442 IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);\r
443 if (IkeSaSession == NULL) {\r
444 return;\r
445 }\r
446 IkeSaSession->Pad = PadEntry;\r
447 IkeSaCommon = &IkeSaSession->SessionCommon;\r
448 IkeSaCommon->IsInitiator = FALSE;\r
449 IkeSaCommon->State = IkeStateInit;\r
450\r
451 IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);\r
452\r
453 CopyMem (\r
454 &IkeSaCommon->RemotePeerIp,\r
455 &IkePacket->RemotePeerIp,\r
456 sizeof (EFI_IP_ADDRESS)\r
457 );\r
458\r
459 CopyMem (\r
460 &IkeSaCommon->LocalPeerIp,\r
461 &UdpService->DefaultAddress,\r
462 sizeof (EFI_IP_ADDRESS)\r
463 );\r
464 \r
465 IsNewSession = TRUE;\r
466 }\r
467\r
468 //\r
469 // Validate the IKE packet header.\r
470 //\r
471 Status = Ikev2ValidateHeader (IkeSaSession, IkePacket->Header);\r
472 if (EFI_ERROR (Status)) {\r
473 //\r
474 // Drop the packet if invalid IKE header.\r
475 //\r
476 goto ON_ERROR;\r
477 }\r
478\r
479 //\r
480 // Decode all the payloads in the IKE packet.\r
481 //\r
482 IkeSaCommon = &IkeSaSession->SessionCommon;\r
483 Status = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);\r
484 if (EFI_ERROR (Status)) {\r
485 goto ON_ERROR;\r
486 }\r
487\r
488 //\r
489 // Try to reate the first ChildSa Session of that IkeSaSession.\r
490 // If the IkeSaSession is responder, here will create the first ChildSaSession.\r
491 //\r
492 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
493 //\r
494 // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
495 //\r
496 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&\r
497 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
498\r
499 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
500 ChildSaCommon = &ChildSaSession->SessionCommon;\r
501 }\r
502\r
503 //\r
504 // Parse the IKE request packet according to the auth method and current state.\r
505 //\r
506 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
507 Status = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
508 if (EFI_ERROR (Status)) {\r
509 goto ON_ERROR;\r
510 }\r
511\r
512 //\r
513 // Try to reate the first ChildSa Session of that IkeSaSession.\r
514 // If the IkeSaSession is initiator, here will create the first ChildSaSession.\r
515 //\r
516 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {\r
517 //\r
518 // Generate a piggyback child SA in IKE_STATE_AUTH state.\r
519 //\r
520 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) && \r
521 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));\r
522 \r
523 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);\r
524 ChildSaCommon = &ChildSaSession->SessionCommon;\r
525\r
526 //\r
527 // Initialize the SA data for Child SA.\r
528 // \r
529 ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);\r
530 }\r
531\r
532 //\r
533 // Generate the IKE response packet and send it out if not established.\r
534 //\r
535 if (IkeSaCommon->State != IkeStateIkeSaEstablished) {\r
536 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];\r
537 Reply = Handler.Generator ((UINT8 *) IkeSaSession, NULL);\r
538 if (Reply == NULL) {\r
539 goto ON_ERROR;\r
540 }\r
541\r
542 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);\r
543 if (EFI_ERROR (Status)) {\r
544 goto ON_ERROR;\r
545 }\r
546 if (!IkeSaCommon->IsInitiator) {\r
547 IkeSaCommon->State ++;\r
548 IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);\r
549 }\r
550 }\r
551\r
552 //\r
553 // Insert the new IkeSaSession into the Private processing IkeSaSession List.\r
554 //\r
555 if (IsNewSession) {\r
556 Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);\r
557 }\r
558\r
559 //\r
560 // Register the IkeSaSession and remove it from processing list.\r
561 //\r
562 if (IkeSaCommon->State == IkeStateIkeSaEstablished) {\r
563\r
564 //\r
565 // Remove the Established IKE SA Session from the IKE SA Session Negotiating list\r
566 // and insert it into IKE SA Session Established list.\r
567 //\r
568 Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);\r
569 Ikev2SaSessionReg (IkeSaSession, Private);\r
570\r
571 //\r
572 // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList\r
573 // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA \r
574 // into SAD.\r
575 //\r
576 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);\r
577 Ikev2ChildSaSessionRemove (\r
578 &IkeSaSession->ChildSaSessionList,\r
579 ChildSaSession->LocalPeerSpi,\r
580 IKEV2_ESTABLISHING_CHILDSA_LIST\r
581 );\r
582 Ikev2ChildSaSessionReg (ChildSaSession, Private);\r
583 }\r
584\r
585 return ;\r
586\r
587ON_ERROR:\r
588 if (ChildSaSession != NULL) {\r
589 //\r
590 // Remove the ChildSa from the list (Established list or Negotiating list).\r
591 //\r
592 RemoveEntryList (&ChildSaSession->ByIkeSa);\r
593 Ikev2ChildSaSessionFree (ChildSaSession);\r
594 }\r
595\r
596 if (IsNewSession && IkeSaSession != NULL) {\r
597 //\r
598 // Remove the IkeSa from the list (Established list or Negotiating list).\r
599 //\r
600 if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&\r
601 !IsListEmpty (&IkeSaSession->BySessionTable\r
602 )){\r
603 RemoveEntryList (&IkeSaSession->BySessionTable);\r
604 }\r
605 Ikev2SaSessionFree (IkeSaSession);\r
606 }\r
607\r
608 return ;\r
609}\r
610\r
611/**\r
612\r
613 The general interface when received a IKEv2 packet for the IKE Child SA establishing \r
614 or IKE SA/CHILD SA rekeying.\r
615\r
616 This function first find the related IKE SA Session according to the IKE packet's \r
617 remote IP. Then call the corresponding function to handle this IKE packet according\r
618 to the related IKE Child Session's State. \r
619\r
620 @param[in] UdpService Pointer of related UDP Service.\r
621 @param[in] IkePacket Data passed by caller.\r
622\r
623**/\r
624VOID\r
625Ikev2HandleChildSa (\r
626 IN IKE_UDP_SERVICE *UdpService,\r
627 IN IKE_PACKET *IkePacket\r
628 )\r
629{\r
630 EFI_STATUS Status;\r
631 IKEV2_SA_SESSION *IkeSaSession;\r
632 IKEV2_CREATE_CHILD_REQUEST_TYPE RequestType;\r
633 IKE_PACKET *Reply;\r
634 IPSEC_PRIVATE_DATA *Private;\r
635 \r
636 Private = (UdpService->IpVersion == IP_VERSION_4) ? \r
637 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :\r
638 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
639\r
640 Reply = NULL;\r
641\r
642 //\r
643 // Lookup the remote ip address in the processing IKE SA session list.\r
644 //\r
645 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
646\r
647 if (IkeSaSession == NULL) {\r
648 //\r
649 // Drop the packet if no IKE SA associated.\r
650 //\r
651 return ;\r
652 }\r
653\r
654 //\r
655 // Validate the IKE packet header.\r
656 //\r
657 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
658 //\r
659 // Drop the packet if invalid IKE header.\r
660 //\r
661 return;\r
662 }\r
663\r
664 //\r
665 // Decode all the payloads in the IKE packet.\r
666 //\r
667 Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
668 if (EFI_ERROR (Status)) {\r
669 return;\r
670 }\r
671\r
672 //\r
673 // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.\r
674 // \r
675 RequestType = Ikev2ChildExchangeRequestType (IkePacket);\r
676\r
677 switch (RequestType) {\r
678 case IkeRequestTypeCreateChildSa:\r
679 case IkeRequestTypeRekeyChildSa: \r
680 case IkeRequestTypeRekeyIkeSa: \r
681 //\r
682 // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so\r
683 // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a \r
684 // Notify payload of type NO_ADDITIONAL_SAS.\r
685 //\r
686 Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);\r
687 if (EFI_ERROR (Status)) { \r
688 goto ON_REPLY;\r
689 }\r
690\r
691 default:\r
692 //\r
693 // No support.\r
694 //\r
695 return ;\r
696 }\r
697 \r
698ON_REPLY:\r
699 //\r
700 // Generate the reply packet if needed and send it out.\r
701 //\r
702 if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {\r
703 Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);\r
704 if (Reply != NULL) {\r
705 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);\r
706 if (EFI_ERROR (Status)) {\r
707 //\r
708 // Delete Reply payload.\r
709 //\r
710 if (Reply != NULL) {\r
711 IkePacketFree (Reply);\r
712 }\r
713 }\r
714 }\r
715 } \r
716 return ;\r
717}\r
718\r
719/**\r
720\r
721 It is general interface to handle IKEv2 information Exchange.\r
722 \r
723 @param[in] UdpService Point to IKE UPD Service related to this information exchange. \r
724 @param[in] IkePacket The IKE packet to be parsed.\r
725\r
726**/\r
727VOID\r
728Ikev2HandleInfo (\r
729 IN IKE_UDP_SERVICE *UdpService,\r
730 IN IKE_PACKET *IkePacket\r
731 )\r
732{\r
733 EFI_STATUS Status;\r
734 IKEV2_SESSION_COMMON *SessionCommon;\r
735 IKEV2_SA_SESSION *IkeSaSession;\r
736 IPSEC_PRIVATE_DATA *Private;\r
737\r
738 Private = (UdpService->IpVersion == IP_VERSION_4) ? \r
739 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) : \r
740 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);\r
741\r
742 //\r
743 // Lookup the remote ip address in the processing IKE SA session list.\r
744 //\r
745 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);\r
746 \r
747 if (IkeSaSession == NULL) {\r
748 //\r
749 // Drop the packet if no IKE SA associated.\r
750 //\r
751 return ;\r
752 }\r
753 //\r
754 // Validate the IKE packet header.\r
755 //\r
756 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {\r
757 \r
758 //\r
759 // Drop the packet if invalid IKE header.\r
760 //\r
761 return;\r
762 } \r
763\r
764 SessionCommon = &IkeSaSession->SessionCommon;\r
765\r
766 //\r
767 // Decode all the payloads in the IKE packet.\r
768 //\r
769 Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);\r
770 if (EFI_ERROR (Status)) {\r
771 return;\r
772 }\r
773\r
774 Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);\r
775\r
776 if (EFI_ERROR (Status)) {\r
777 //\r
778 // Drop the packet if fail to parse.\r
779 //\r
780 return;\r
781 } \r
782}\r
783\r
784IKE_EXCHANGE_INTERFACE mIkev1Exchange = {
785 1,
786 NULL, //Ikev1NegotiateSa\r
787 NULL, //Ikev1NegotiateChildSa\r
788 NULL,
789 NULL, //Ikev1HandleSa,\r
790 NULL, //Ikev1HandleChildSa\r
791 NULL, //Ikev1HandleInfo\r
792};\r
793\r
794IKE_EXCHANGE_INTERFACE mIkev2Exchange = {\r
795 2,\r
796 Ikev2NegotiateSa,\r
797 Ikev2NegotiateChildSa,\r
798 Ikev2NegotiateInfo,\r
799 Ikev2HandleSa,\r
800 Ikev2HandleChildSa,\r
801 Ikev2HandleInfo\r
802};\r
803\r