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