]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/Ikev2/Exchange.c
Add IPsec/Ikev2 support.
[mirror_edk2.git] / NetworkPkg / IpSecDxe / Ikev2 / Exchange.c
1 /** @file
2 The general interfaces of the IKEv2.
3
4 Copyright (c) 2010, 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 // The IKE SA Session should be initiator if it triggers the deleting.
323 //
324 Ikev2SaSession->SessionCommon.IsInitiator = TRUE;
325
326 //
327 // Generate Information Packet which contains the Delete Payload.
328 //
329 IkePacket = mIkev2Info.Generator ((UINT8 *) Ikev2SaSession, NULL);
330 if (IkePacket == NULL) {
331 Status = EFI_OUT_OF_RESOURCES;
332 goto ON_ERROR;
333 }
334
335 //
336 // Send out the Packet
337 //
338 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) SaCommon, IkePacket, 0);
339
340 if (EFI_ERROR (Status)) {
341 goto ON_ERROR;
342 }
343 } else if (!IsListEmpty (&Ikev2SaSession->DeleteSaList)) {
344 //
345 // Iterate all Deleting Child SAs.
346 //
347 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Ikev2SaSession->DeleteSaList) {
348 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_DEL_SA (Entry);
349 ChildSaSession->SessionCommon.State = IkeStateSaDeleting;
350
351 //
352 // Generate Information Packet which contains the Child SA Delete Payload.
353 //
354 IkePacket = mIkev2Info.Generator ((UINT8 *) ChildSaSession, NULL);
355 if (IkePacket == NULL) {
356 Status = EFI_OUT_OF_RESOURCES;
357 goto ON_ERROR;
358 }
359
360 //
361 // Send out the Packet
362 //
363 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &ChildSaSession->SessionCommon, IkePacket, 0);
364
365 if (EFI_ERROR (Status)) {
366 goto ON_ERROR;
367 }
368 }
369 } else if (Context == NULL) {
370 //
371 // TODO: Deliver null notification message.
372 //
373 } else if (Context != NULL) {
374 //
375 // TODO: Send out the Information Exchange which contains the Notify Payload.
376 //
377 }
378 ON_ERROR:
379 if (IkePacket != NULL) {
380 IkePacketFree (IkePacket);
381 }
382 return Status;
383
384 }
385
386 /**
387 The general interface when received a IKEv2 packet for the IKE SA establishing.
388
389 This function first find the related IKE SA Session according to the IKE packet's
390 remote IP. Then call the corresponding function to handle this IKE packet according
391 to the related IKE SA Session's State.
392
393 @param[in] UdpService Pointer of related UDP Service.
394 @param[in] IkePacket Data passed by caller.
395
396 **/
397 VOID
398 Ikev2HandleSa (
399 IN IKE_UDP_SERVICE *UdpService,
400 IN IKE_PACKET *IkePacket
401 )
402 {
403 EFI_STATUS Status;
404 IKEV2_SA_SESSION *IkeSaSession;
405 IKEV2_CHILD_SA_SESSION *ChildSaSession;
406 IKEV2_SESSION_COMMON *IkeSaCommon;
407 IKEV2_SESSION_COMMON *ChildSaCommon;
408 IKEV2_PACKET_HANDLER Handler;
409 IKE_PACKET *Reply;
410 IPSEC_PAD_ENTRY *PadEntry;
411 IPSEC_PRIVATE_DATA *Private;
412 BOOLEAN IsNewSession;
413
414 Private = (UdpService->IpVersion == IP_VERSION_4) ?
415 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
416 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
417
418 ChildSaSession = NULL;
419 ChildSaCommon = NULL;
420
421 //
422 // Lookup the remote ip address in the processing IKE SA session list.
423 //
424 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
425 IsNewSession = FALSE;
426
427 if (IkeSaSession == NULL) {
428 //
429 // Lookup the remote ip address in the pad.
430 //
431 PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, &IkePacket->RemotePeerIp);
432 if (PadEntry == NULL) {
433 //
434 // Drop the packet if no pad entry matched, this is the request from RFC 4301.
435 //
436 return ;
437 }
438
439 //
440 // Create a new IkeSaSession and initiate the common parameters.
441 //
442 IkeSaSession = Ikev2SaSessionAlloc (Private, UdpService);
443 if (IkeSaSession == NULL) {
444 return;
445 }
446 IkeSaSession->Pad = PadEntry;
447 IkeSaCommon = &IkeSaSession->SessionCommon;
448 IkeSaCommon->IsInitiator = FALSE;
449 IkeSaCommon->State = IkeStateInit;
450
451 IKEV2_DUMP_STATE (IkeSaCommon->State, IkeStateInit);
452
453 CopyMem (
454 &IkeSaCommon->RemotePeerIp,
455 &IkePacket->RemotePeerIp,
456 sizeof (EFI_IP_ADDRESS)
457 );
458
459 CopyMem (
460 &IkeSaCommon->LocalPeerIp,
461 &UdpService->DefaultAddress,
462 sizeof (EFI_IP_ADDRESS)
463 );
464
465 IsNewSession = TRUE;
466 }
467
468 //
469 // Validate the IKE packet header.
470 //
471 Status = Ikev2ValidateHeader (IkeSaSession, IkePacket->Header);
472 if (EFI_ERROR (Status)) {
473 //
474 // Drop the packet if invalid IKE header.
475 //
476 goto ON_ERROR;
477 }
478
479 //
480 // Decode all the payloads in the IKE packet.
481 //
482 IkeSaCommon = &IkeSaSession->SessionCommon;
483 Status = Ikev2DecodePacket (IkeSaCommon, IkePacket, IkeSessionTypeIkeSa);
484 if (EFI_ERROR (Status)) {
485 goto ON_ERROR;
486 }
487
488 //
489 // Try to reate the first ChildSa Session of that IkeSaSession.
490 // If the IkeSaSession is responder, here will create the first ChildSaSession.
491 //
492 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
493 //
494 // Generate a piggyback child SA in IKE_STATE_AUTH state.
495 //
496 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
497 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
498
499 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
500 ChildSaCommon = &ChildSaSession->SessionCommon;
501 }
502
503 //
504 // Parse the IKE request packet according to the auth method and current state.
505 //
506 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
507 Status = Handler.Parser ((UINT8 *)IkeSaSession, IkePacket);
508 if (EFI_ERROR (Status)) {
509 goto ON_ERROR;
510 }
511
512 //
513 // Try to reate the first ChildSa Session of that IkeSaSession.
514 // If the IkeSaSession is initiator, here will create the first ChildSaSession.
515 //
516 if (IkeSaCommon->State == IkeStateAuth && IsListEmpty(&IkeSaSession->ChildSaSessionList)) {
517 //
518 // Generate a piggyback child SA in IKE_STATE_AUTH state.
519 //
520 ASSERT (IsListEmpty (&IkeSaSession->ChildSaSessionList) &&
521 IsListEmpty (&IkeSaSession->ChildSaEstablishSessionList));
522
523 ChildSaSession = Ikev2ChildSaSessionCreate (IkeSaSession, UdpService);
524 ChildSaCommon = &ChildSaSession->SessionCommon;
525
526 //
527 // Initialize the SA data for Child SA.
528 //
529 ChildSaSession->SaData = Ikev2InitializeSaData (ChildSaCommon);
530 }
531
532 //
533 // Generate the IKE response packet and send it out if not established.
534 //
535 if (IkeSaCommon->State != IkeStateIkeSaEstablished) {
536 Handler = mIkev2Initial[IkeSaSession->Pad->Data->AuthMethod][IkeSaCommon->State];
537 Reply = Handler.Generator ((UINT8 *) IkeSaSession, NULL);
538 if (Reply == NULL) {
539 goto ON_ERROR;
540 }
541
542 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) IkeSaCommon, Reply, 0);
543 if (EFI_ERROR (Status)) {
544 goto ON_ERROR;
545 }
546 if (!IkeSaCommon->IsInitiator) {
547 IkeSaCommon->State ++;
548 IKEV2_DUMP_STATE (IkeSaCommon->State - 1, IkeSaCommon->State);
549 }
550 }
551
552 //
553 // Insert the new IkeSaSession into the Private processing IkeSaSession List.
554 //
555 if (IsNewSession) {
556 Ikev2SaSessionInsert (&Private->Ikev2SessionList, IkeSaSession, &IkePacket->RemotePeerIp);
557 }
558
559 //
560 // Register the IkeSaSession and remove it from processing list.
561 //
562 if (IkeSaCommon->State == IkeStateIkeSaEstablished) {
563
564 //
565 // Remove the Established IKE SA Session from the IKE SA Session Negotiating list
566 // and insert it into IKE SA Session Established list.
567 //
568 Ikev2SaSessionRemove (&Private->Ikev2SessionList, &IkePacket->RemotePeerIp);
569 Ikev2SaSessionReg (IkeSaSession, Private);
570
571 //
572 // Remove the Established Child SA Session from the IkeSaSession->ChildSaSessionList
573 // ,insert it into IkeSaSession->ChildSaEstablishSessionList and save this Child SA
574 // into SAD.
575 //
576 ChildSaSession = IKEV2_CHILD_SA_SESSION_BY_IKE_SA (IkeSaSession->ChildSaSessionList.BackLink);
577 Ikev2ChildSaSessionRemove (
578 &IkeSaSession->ChildSaSessionList,
579 ChildSaSession->LocalPeerSpi,
580 IKEV2_ESTABLISHING_CHILDSA_LIST
581 );
582 Ikev2ChildSaSessionReg (ChildSaSession, Private);
583 }
584
585 return ;
586
587 ON_ERROR:
588 if (ChildSaSession != NULL) {
589 //
590 // Remove the ChildSa from the list (Established list or Negotiating list).
591 //
592 RemoveEntryList (&ChildSaSession->ByIkeSa);
593 Ikev2ChildSaSessionFree (ChildSaSession);
594 }
595
596 if (IsNewSession && IkeSaSession != NULL) {
597 //
598 // Remove the IkeSa from the list (Established list or Negotiating list).
599 //
600 if ((&IkeSaSession->BySessionTable)->ForwardLink != NULL &&
601 !IsListEmpty (&IkeSaSession->BySessionTable
602 )){
603 RemoveEntryList (&IkeSaSession->BySessionTable);
604 }
605 Ikev2SaSessionFree (IkeSaSession);
606 }
607
608 return ;
609 }
610
611 /**
612
613 The general interface when received a IKEv2 packet for the IKE Child SA establishing
614 or IKE SA/CHILD SA rekeying.
615
616 This function first find the related IKE SA Session according to the IKE packet's
617 remote IP. Then call the corresponding function to handle this IKE packet according
618 to the related IKE Child Session's State.
619
620 @param[in] UdpService Pointer of related UDP Service.
621 @param[in] IkePacket Data passed by caller.
622
623 **/
624 VOID
625 Ikev2HandleChildSa (
626 IN IKE_UDP_SERVICE *UdpService,
627 IN IKE_PACKET *IkePacket
628 )
629 {
630 EFI_STATUS Status;
631 IKEV2_SA_SESSION *IkeSaSession;
632 IKEV2_CREATE_CHILD_REQUEST_TYPE RequestType;
633 IKE_PACKET *Reply;
634 IPSEC_PRIVATE_DATA *Private;
635
636 Private = (UdpService->IpVersion == IP_VERSION_4) ?
637 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
638 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
639
640 Reply = NULL;
641
642 //
643 // Lookup the remote ip address in the processing IKE SA session list.
644 //
645 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
646
647 if (IkeSaSession == NULL) {
648 //
649 // Drop the packet if no IKE SA associated.
650 //
651 return ;
652 }
653
654 //
655 // Validate the IKE packet header.
656 //
657 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
658 //
659 // Drop the packet if invalid IKE header.
660 //
661 return;
662 }
663
664 //
665 // Decode all the payloads in the IKE packet.
666 //
667 Status = Ikev2DecodePacket (&IkeSaSession->SessionCommon, IkePacket, IkeSessionTypeIkeSa);
668 if (EFI_ERROR (Status)) {
669 return;
670 }
671
672 //
673 // Get the request type: CreateChildSa/RekeyChildSa/RekeyIkeSa.
674 //
675 RequestType = Ikev2ChildExchangeRequestType (IkePacket);
676
677 switch (RequestType) {
678 case IkeRequestTypeCreateChildSa:
679 case IkeRequestTypeRekeyChildSa:
680 case IkeRequestTypeRekeyIkeSa:
681 //
682 // Parse the IKE request packet. Not support CREATE_CHILD_SA exchange yet, so
683 // only EFI_UNSUPPORTED will be returned and that will trigger a reply with a
684 // Notify payload of type NO_ADDITIONAL_SAS.
685 //
686 Status = mIkev2CreateChild.Parser ((UINT8 *) IkeSaSession, IkePacket);
687 if (EFI_ERROR (Status)) {
688 goto ON_REPLY;
689 }
690
691 default:
692 //
693 // No support.
694 //
695 return ;
696 }
697
698 ON_REPLY:
699 //
700 // Generate the reply packet if needed and send it out.
701 //
702 if (IkePacket->Header->Flags != IKE_HEADER_FLAGS_RESPOND) {
703 Reply = mIkev2CreateChild.Generator ((UINT8 *) IkeSaSession, &IkePacket->Header->MessageId);
704 if (Reply != NULL) {
705 Status = Ikev2SendIkePacket (UdpService, (UINT8 *) &(IkeSaSession->SessionCommon), Reply, 0);
706 if (EFI_ERROR (Status)) {
707 //
708 // Delete Reply payload.
709 //
710 if (Reply != NULL) {
711 IkePacketFree (Reply);
712 }
713 }
714 }
715 }
716 return ;
717 }
718
719 /**
720
721 It is general interface to handle IKEv2 information Exchange.
722
723 @param[in] UdpService Point to IKE UPD Service related to this information exchange.
724 @param[in] IkePacket The IKE packet to be parsed.
725
726 **/
727 VOID
728 Ikev2HandleInfo (
729 IN IKE_UDP_SERVICE *UdpService,
730 IN IKE_PACKET *IkePacket
731 )
732 {
733 EFI_STATUS Status;
734 IKEV2_SESSION_COMMON *SessionCommon;
735 IKEV2_SA_SESSION *IkeSaSession;
736 IPSEC_PRIVATE_DATA *Private;
737
738 Private = (UdpService->IpVersion == IP_VERSION_4) ?
739 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
740 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
741
742 //
743 // Lookup the remote ip address in the processing IKE SA session list.
744 //
745 IkeSaSession = Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, &IkePacket->RemotePeerIp);
746
747 if (IkeSaSession == NULL) {
748 //
749 // Drop the packet if no IKE SA associated.
750 //
751 return ;
752 }
753 //
754 // Validate the IKE packet header.
755 //
756 if (!Ikev2ValidateHeader (IkeSaSession, IkePacket->Header)) {
757
758 //
759 // Drop the packet if invalid IKE header.
760 //
761 return;
762 }
763
764 SessionCommon = &IkeSaSession->SessionCommon;
765
766 //
767 // Decode all the payloads in the IKE packet.
768 //
769 Status = Ikev2DecodePacket (SessionCommon, IkePacket, IkeSessionTypeIkeSa);
770 if (EFI_ERROR (Status)) {
771 return;
772 }
773
774 Status = mIkev2Info.Parser ((UINT8 *)IkeSaSession, IkePacket);
775
776 if (EFI_ERROR (Status)) {
777 //
778 // Drop the packet if fail to parse.
779 //
780 return;
781 }
782 }
783
784 IKE_EXCHANGE_INTERFACE mIkev1Exchange = {
785 1,
786 NULL, //Ikev1NegotiateSa
787 NULL, //Ikev1NegotiateChildSa
788 NULL,
789 NULL, //Ikev1HandleSa,
790 NULL, //Ikev1HandleChildSa
791 NULL, //Ikev1HandleInfo
792 };
793
794 IKE_EXCHANGE_INTERFACE mIkev2Exchange = {
795 2,
796 Ikev2NegotiateSa,
797 Ikev2NegotiateChildSa,
798 Ikev2NegotiateInfo,
799 Ikev2HandleSa,
800 Ikev2HandleChildSa,
801 Ikev2HandleInfo
802 };
803