blob: 8e2c794dc3da9be2aea5677d594c681935b96837 [file] [log] [blame]
qianouyang9166f842010-12-31 10:43:54 +00001/** @file
2 Provide IPsec Key Exchange (IKE) service general interfaces.
qianouyang6cf92302011-11-23 10:31:04 +00003
sfu568795812013-04-25 01:33:43 +00004 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
qianouyang9166f842010-12-31 10:43:54 +00005
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 "IkeService.h"
17#include "IpSecConfigImpl.h"
18#include "Ikev2/Utility.h"
19
20IKE_EXCHANGE_INTERFACE *mIkeExchange[] = {
21 &mIkev1Exchange,
22 &mIkev2Exchange
23};
24
25EFI_UDP4_CONFIG_DATA mUdp4Conf = {
26 FALSE,
27 FALSE,
28 FALSE,
29 TRUE,
30 //
31 // IO parameters
32 //
33 0,
34 64,
35 FALSE,
36 0,
37 1000000,
38 FALSE,
lzeng14ce68d3b2012-10-11 02:15:23 +000039 {{0,0,0,0}},
40 {{0,0,0,0}},
qianouyang9166f842010-12-31 10:43:54 +000041 IKE_DEFAULT_PORT,
lzeng14ce68d3b2012-10-11 02:15:23 +000042 {{0,0,0,0}},
qianouyang9166f842010-12-31 10:43:54 +000043 0
44};
45
46EFI_UDP6_CONFIG_DATA mUdp6Conf = {
47 FALSE,
48 FALSE,
49 TRUE,
50 //
51 // IO parameters
52 //
53 0,
54 128,
55 0,
56 1000000,
57 //Access Point
lzeng14ce68d3b2012-10-11 02:15:23 +000058 {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
qianouyang9166f842010-12-31 10:43:54 +000059 IKE_DEFAULT_PORT,
lzeng14ce68d3b2012-10-11 02:15:23 +000060 {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}},
qianouyang9166f842010-12-31 10:43:54 +000061 0
62};
63
64/**
65 Check if the NIC handle is binded to a Udp service.
66
67 @param[in] Private Pointer of IPSEC_PRIVATE_DATA.
xdu276389e12011-01-21 08:00:22 +000068 @param[in] Handle The Handle of the NIC card.
qianouyang9166f842010-12-31 10:43:54 +000069 @param[in] IpVersion The version of the IP stack.
70
71 @return a pointer of IKE_UDP_SERVICE.
72
73**/
74IKE_UDP_SERVICE *
75IkeLookupUdp (
76 IN IPSEC_PRIVATE_DATA *Private,
77 IN EFI_HANDLE Handle,
78 IN UINT8 IpVersion
79 )
80{
81 LIST_ENTRY *Head;
82 LIST_ENTRY *Entry;
83 LIST_ENTRY *Next;
84 IKE_UDP_SERVICE *Udp;
85
86 Udp = NULL;
87 Head = (IpVersion == IP_VERSION_4) ? &Private->Udp4List : &Private->Udp6List;
88
89 NET_LIST_FOR_EACH_SAFE (Entry, Next, Head) {
90
91 Udp = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
92 //
93 // Find the right udp service which installed on the appointed NIC handle.
94 //
95 if (Handle == Udp->NicHandle) {
96 break;
97 } else {
98 Udp = NULL;
99 }
100 }
101
102 return Udp;
103}
104
105/**
106 Configure a UDPIO's UDP4 instance.
qianouyang6cf92302011-11-23 10:31:04 +0000107
108 This fuction is called by the UdpIoCreateIo() to configures a
qianouyang9166f842010-12-31 10:43:54 +0000109 UDP4 instance.
qianouyang6cf92302011-11-23 10:31:04 +0000110
qianouyang9166f842010-12-31 10:43:54 +0000111 @param[in] UdpIo The UDP_IO to be configured.
112 @param[in] Context User-defined data when calling UdpIoCreateIo().
qianouyang6cf92302011-11-23 10:31:04 +0000113
qianouyang9166f842010-12-31 10:43:54 +0000114 @retval EFI_SUCCESS The configuration succeeded.
115 @retval Others The UDP4 instance fails to configure.
116
117**/
118EFI_STATUS
jljusten1d8fa5e2011-01-03 03:17:20 +0000119EFIAPI
qianouyang9166f842010-12-31 10:43:54 +0000120IkeConfigUdp4 (
121 IN UDP_IO *UdpIo,
122 IN VOID *Context
123 )
124{
125 EFI_UDP4_CONFIG_DATA Udp4Cfg;
126 EFI_UDP4_PROTOCOL *Udp4;
127
128 ZeroMem (&Udp4Cfg, sizeof (EFI_UDP4_CONFIG_DATA));
129
130 Udp4 = UdpIo->Protocol.Udp4;
131 CopyMem (
132 &Udp4Cfg,
133 &mUdp4Conf,
134 sizeof (EFI_UDP4_CONFIG_DATA)
135 );
136
137 if (Context != NULL) {
138 //
139 // Configure udp4 io with local default address.
140 //
141 Udp4Cfg.UseDefaultAddress = TRUE;
142 }
143
144 return Udp4->Configure (Udp4, &Udp4Cfg);
145}
146
147/**
148 Configure a UDPIO's UDP6 instance.
qianouyang6cf92302011-11-23 10:31:04 +0000149
150 This fuction is called by the UdpIoCreateIo()to configure a
qianouyang9166f842010-12-31 10:43:54 +0000151 UDP6 instance.
qianouyang6cf92302011-11-23 10:31:04 +0000152
qianouyang9166f842010-12-31 10:43:54 +0000153 @param[in] UdpIo The UDP_IO to be configured.
154 @param[in] Context User-defined data when calling UdpIoCreateIo().
qianouyang6cf92302011-11-23 10:31:04 +0000155
qianouyang9166f842010-12-31 10:43:54 +0000156 @retval EFI_SUCCESS The configuration succeeded.
157 @retval Others The configuration fails.
158
159**/
160EFI_STATUS
jljusten1d8fa5e2011-01-03 03:17:20 +0000161EFIAPI
qianouyang9166f842010-12-31 10:43:54 +0000162IkeConfigUdp6 (
163 IN UDP_IO *UdpIo,
164 IN VOID *Context
165 )
166{
167 EFI_UDP6_PROTOCOL *Udp6;
168 EFI_UDP6_CONFIG_DATA Udp6Cfg;
169
170 ZeroMem (&Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
171
172 Udp6 = UdpIo->Protocol.Udp6;
173 CopyMem (
174 &Udp6Cfg,
175 &mUdp6Conf,
176 sizeof (EFI_UDP6_CONFIG_DATA)
177 );
178
179 if (Context != NULL) {
180 //
181 // Configure instance with a destination address to start source address
182 // selection, and then get the configure data from the mode data to store
183 // the source address.
184 //
185 CopyMem (
186 &Udp6Cfg.RemoteAddress,
187 Context,
188 sizeof (EFI_IPv6_ADDRESS)
189 );
190 }
191
192 return Udp6->Configure (Udp6, &Udp6Cfg);
193}
194
195/**
196 Open and configure the related output UDPIO for IKE packet sending.
qianouyang6cf92302011-11-23 10:31:04 +0000197
198 If the UdpService is not configured, this fuction calls UdpIoCreatIo() to
qianouyang9166f842010-12-31 10:43:54 +0000199 create UDPIO to bind this UdpService for IKE packet sending. If the UdpService
200 has already been configured, then return.
qianouyang6cf92302011-11-23 10:31:04 +0000201
qianouyang9166f842010-12-31 10:43:54 +0000202 @param[in] UdpService The UDP_IO to be configured.
203 @param[in] RemoteIp User-defined data when calling UdpIoCreateIo().
qianouyang6cf92302011-11-23 10:31:04 +0000204
qianouyang9166f842010-12-31 10:43:54 +0000205 @retval EFI_SUCCESS The configuration is successful.
206 @retval Others The configuration fails.
207
208**/
209EFI_STATUS
210IkeOpenOutputUdp (
211 IN IKE_UDP_SERVICE *UdpService,
212 IN EFI_IP_ADDRESS *RemoteIp
213 )
214{
215 EFI_STATUS Status;
216 EFI_IP4_CONFIG_PROTOCOL *Ip4Cfg;
217 EFI_IP4_IPCONFIG_DATA *Ip4CfgData;
218 UINTN BufSize;
219 EFI_IP6_MODE_DATA Ip6ModeData;
220 EFI_UDP6_PROTOCOL *Udp6;
221
222 Status = EFI_SUCCESS;
223 Ip4CfgData = NULL;
224 BufSize = 0;
225
226 //
227 // Check whether the input and output udp io are both configured.
228 //
229 if (UdpService->IsConfigured) {
230 goto ON_EXIT;
231 }
232
233 if (UdpService->IpVersion == UDP_IO_UDP4_VERSION) {
234 //
235 // Handle ip4config protocol to get local default address.
236 //
237 Status = gBS->HandleProtocol (
238 UdpService->NicHandle,
239 &gEfiIp4ConfigProtocolGuid,
240 (VOID **) &Ip4Cfg
241 );
242
243 if (EFI_ERROR (Status)) {
244 goto ON_EXIT;
245 }
246
247 Status = Ip4Cfg->GetData (Ip4Cfg, &BufSize, NULL);
248
249 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
250 goto ON_EXIT;
251 }
252
253 Ip4CfgData = AllocateZeroPool (BufSize);
254
255 if (Ip4CfgData == NULL) {
256 Status = EFI_OUT_OF_RESOURCES;
257 goto ON_EXIT;
258 }
259
260 Status = Ip4Cfg->GetData (Ip4Cfg, &BufSize, Ip4CfgData);
261 if (EFI_ERROR (Status)) {
262 goto ON_EXIT;
263 }
264
265 CopyMem (
266 &UdpService->DefaultAddress.v4,
267 &Ip4CfgData->StationAddress,
268 sizeof (EFI_IPv4_ADDRESS)
269 );
270
271 //
272 // Create udp4 io for output with local default address.
273 //
274 UdpService->Output = UdpIoCreateIo (
275 UdpService->NicHandle,
276 UdpService->ImageHandle,
277 IkeConfigUdp4,
278 UDP_IO_UDP4_VERSION,
279 &UdpService->DefaultAddress
280 );
281
282 if (UdpService->Output == NULL) {
283 Status = EFI_OUT_OF_RESOURCES;
284 goto ON_EXIT;
285 }
286
287 } else {
288 //
289 // Create udp6 io for output with remote address.
290 //
291 UdpService->Output = UdpIoCreateIo (
292 UdpService->NicHandle,
293 UdpService->ImageHandle,
294 IkeConfigUdp6,
295 UDP_IO_UDP6_VERSION,
296 RemoteIp
297 );
298
299 if (UdpService->Output == NULL) {
300 Status = EFI_OUT_OF_RESOURCES;
301 goto ON_EXIT;
302 }
303 //
304 // Get ip6 mode data to get the result of source address selection.
305 //
306 ZeroMem (&Ip6ModeData, sizeof (EFI_IP6_MODE_DATA));
307
308 Udp6 = UdpService->Output->Protocol.Udp6;
309 Status = Udp6->GetModeData (Udp6, NULL, &Ip6ModeData, NULL, NULL);
310
311 if (EFI_ERROR (Status)) {
312 UdpIoFreeIo (UdpService->Output);
313 goto ON_EXIT;
314 }
315 //
316 // Reconfigure udp6 io without remote address.
317 //
318 Udp6->Configure (Udp6, NULL);
319 Status = IkeConfigUdp6 (UdpService->Output, NULL);
320
321 //
322 // Record the selected source address for ipsec process later.
323 //
324 CopyMem (
325 &UdpService->DefaultAddress.v6,
326 &Ip6ModeData.ConfigData.StationAddress,
327 sizeof (EFI_IPv6_ADDRESS)
328 );
329 }
330
331 UdpService->IsConfigured = TRUE;
332
333ON_EXIT:
334 if (Ip4CfgData != NULL) {
335 FreePool (Ip4CfgData);
336 }
337
338 return Status;
339}
340
341/**
342 Open and configure a UDPIO of Udp4 for IKE packet receiving.
qianouyang6cf92302011-11-23 10:31:04 +0000343
344 This function is called at the IPsecDriverBinding start. IPsec create a UDP4 and
qianouyang9166f842010-12-31 10:43:54 +0000345 UDP4 IO for each NIC handle.
qianouyang6cf92302011-11-23 10:31:04 +0000346
qianouyang9166f842010-12-31 10:43:54 +0000347 @param[in] Private Point to IPSEC_PRIVATE_DATA
348 @param[in] Controller Handler for NIC card.
sfu568795812013-04-25 01:33:43 +0000349 @param[in] ImageHandle The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
qianouyang6cf92302011-11-23 10:31:04 +0000350
qianouyang9166f842010-12-31 10:43:54 +0000351 @retval EFI_SUCCESS The Operation is successful.
352 @retval EFI_OUT_OF_RESOURCE The required system resource can't be allocated.
qianouyang6cf92302011-11-23 10:31:04 +0000353
qianouyang9166f842010-12-31 10:43:54 +0000354**/
355EFI_STATUS
356IkeOpenInputUdp4 (
357 IN IPSEC_PRIVATE_DATA *Private,
sfu568795812013-04-25 01:33:43 +0000358 IN EFI_HANDLE Controller,
359 IN EFI_HANDLE ImageHandle
qianouyang9166f842010-12-31 10:43:54 +0000360 )
361{
362 IKE_UDP_SERVICE *Udp4Srv;
363
364 //
365 // Check whether udp4 io of the controller has already been opened.
366 //
367 Udp4Srv = IkeLookupUdp (Private, Controller, IP_VERSION_4);
368
369 if (Udp4Srv != NULL) {
370 return EFI_ALREADY_STARTED;
371 }
372
373 Udp4Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
374
375 if (Udp4Srv == NULL) {
376 return EFI_OUT_OF_RESOURCES;
377 }
378 //
379 // Create udp4 io for iutput.
380 //
381 Udp4Srv->Input = UdpIoCreateIo (
382 Controller,
sfu568795812013-04-25 01:33:43 +0000383 ImageHandle,
qianouyang9166f842010-12-31 10:43:54 +0000384 IkeConfigUdp4,
385 UDP_IO_UDP4_VERSION,
386 NULL
387 );
388
389 if (Udp4Srv->Input == NULL) {
390 FreePool (Udp4Srv);
391 return EFI_OUT_OF_RESOURCES;
392 }
393
394 Udp4Srv->NicHandle = Controller;
sfu568795812013-04-25 01:33:43 +0000395 Udp4Srv->ImageHandle = ImageHandle;
qianouyang9166f842010-12-31 10:43:54 +0000396 Udp4Srv->ListHead = &(Private->Udp4List);
397 Udp4Srv->IpVersion = UDP_IO_UDP4_VERSION;
398 Udp4Srv->IsConfigured = FALSE;
399
400 ZeroMem (&Udp4Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
401
402 //
403 // Insert the udp4 io into the list and increase the count.
404 //
405 InsertTailList (&Private->Udp4List, &Udp4Srv->List);
406
407 Private->Udp4Num++;
408
409 UdpIoRecvDatagram (Udp4Srv->Input, IkeDispatch, Udp4Srv, 0);
410
411 return EFI_SUCCESS;
412}
413
414/**
415 Open and configure a UDPIO of Udp6 for IKE packet receiving.
qianouyang6cf92302011-11-23 10:31:04 +0000416
qianouyang9166f842010-12-31 10:43:54 +0000417 This function is called at the IPsecDriverBinding start. IPsec create a UDP6 and UDP6
418 IO for each NIC handle.
qianouyang6cf92302011-11-23 10:31:04 +0000419
qianouyang9166f842010-12-31 10:43:54 +0000420 @param[in] Private Point to IPSEC_PRIVATE_DATA
421 @param[in] Controller Handler for NIC card.
sfu568795812013-04-25 01:33:43 +0000422 @param[in] ImageHandle The handle that contains the EFI_DRIVER_BINDING_PROTOCOL instance.
qianouyang6cf92302011-11-23 10:31:04 +0000423
qianouyang9166f842010-12-31 10:43:54 +0000424 @retval EFI_SUCCESS The Operation is successful.
425 @retval EFI_OUT_OF_RESOURCE The required system resource can't be allocated.
qianouyang6cf92302011-11-23 10:31:04 +0000426
qianouyang9166f842010-12-31 10:43:54 +0000427**/
428EFI_STATUS
429IkeOpenInputUdp6 (
430 IN IPSEC_PRIVATE_DATA *Private,
sfu568795812013-04-25 01:33:43 +0000431 IN EFI_HANDLE Controller,
432 IN EFI_HANDLE ImageHandle
qianouyang9166f842010-12-31 10:43:54 +0000433 )
434{
435 IKE_UDP_SERVICE *Udp6Srv;
436
437 Udp6Srv = IkeLookupUdp (Private, Controller, IP_VERSION_6);
438
439 if (Udp6Srv != NULL) {
440 return EFI_ALREADY_STARTED;
441 }
442
443 Udp6Srv = AllocateZeroPool (sizeof (IKE_UDP_SERVICE));
444
445 if (Udp6Srv == NULL) {
446 return EFI_OUT_OF_RESOURCES;
447 }
448 //
449 // Create udp6 io for input.
450 //
451 Udp6Srv->Input = UdpIoCreateIo (
452 Controller,
sfu568795812013-04-25 01:33:43 +0000453 ImageHandle,
qianouyang9166f842010-12-31 10:43:54 +0000454 IkeConfigUdp6,
455 UDP_IO_UDP6_VERSION,
456 NULL
457 );
458
459 if (Udp6Srv->Input == NULL) {
460 FreePool (Udp6Srv);
461 return EFI_OUT_OF_RESOURCES;
462 }
463
464 Udp6Srv->NicHandle = Controller;
sfu568795812013-04-25 01:33:43 +0000465 Udp6Srv->ImageHandle = ImageHandle;
qianouyang9166f842010-12-31 10:43:54 +0000466 Udp6Srv->ListHead = &(Private->Udp6List);
467 Udp6Srv->IpVersion = UDP_IO_UDP6_VERSION;
468 Udp6Srv->IsConfigured = FALSE;
469
470 ZeroMem (&Udp6Srv->DefaultAddress, sizeof (EFI_IP_ADDRESS));
471
472 //
473 // Insert the udp6 io into the list and increase the count.
474 //
475 InsertTailList (&Private->Udp6List, &Udp6Srv->List);
476
477 Private->Udp6Num++;
478
479 UdpIoRecvDatagram (Udp6Srv->Input, IkeDispatch, Udp6Srv, 0);
480
481 return EFI_SUCCESS;
482}
483
484/**
485 The general interface of starting IPsec Key Exchange.
qianouyang6cf92302011-11-23 10:31:04 +0000486
qianouyang9166f842010-12-31 10:43:54 +0000487 This function is called when a IKE negotiation to start getting a Key.
qianouyang6cf92302011-11-23 10:31:04 +0000488
489 @param[in] UdpService Point to IKE_UDP_SERVICE which will be used for
qianouyang9166f842010-12-31 10:43:54 +0000490 IKE packet sending.
491 @param[in] SpdEntry Point to the SPD entry related to the IKE negotiation.
492 @param[in] RemoteIp Point to EFI_IP_ADDRESS related to the IKE negotiation.
qianouyang6cf92302011-11-23 10:31:04 +0000493
qianouyang9166f842010-12-31 10:43:54 +0000494 @retval EFI_SUCCESS The Operation is successful.
495 @retval EFI_ACCESS_DENIED No related PAD entry was found.
496 @retval EFI_INVALID_PARAMETER The IKE version is not supported.
qianouyang6cf92302011-11-23 10:31:04 +0000497
qianouyang9166f842010-12-31 10:43:54 +0000498**/
499EFI_STATUS
500IkeNegotiate (
501 IN IKE_UDP_SERVICE *UdpService,
502 IN IPSEC_SPD_ENTRY *SpdEntry,
503 IN EFI_IP_ADDRESS *RemoteIp
504 )
505{
506 EFI_STATUS Status;
507 UINT8 *IkeSaSession;
508 IKE_EXCHANGE_INTERFACE *Exchange;
509 IPSEC_PRIVATE_DATA *Private;
510 IPSEC_PAD_ENTRY *PadEntry;
511 UINT8 IkeVersion;
512
513 Private = (UdpService->IpVersion == IP_VERSION_4) ?
514 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
515 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
516
517 //
518 // Try to open udp io for output if it hasn't.
519 //
520 Status = IkeOpenOutputUdp (UdpService, RemoteIp);
521 if (EFI_ERROR (Status)) {
522 return Status;
523 }
524 //
525 // Try to find the IKE SA session in the IKEv1 and IKEv2 established SA session list.
qianouyang6cf92302011-11-23 10:31:04 +0000526 //
527 IkeSaSession = (UINT8 *) Ikev2SaSessionLookup (&Private->Ikev2EstablishedList, RemoteIp);
qianouyang9166f842010-12-31 10:43:54 +0000528
529
530 if (IkeSaSession == NULL) {
531 //
532 // Find the pad entry by the remote ip address.
533 //
534 PadEntry = IpSecLookupPadEntry (UdpService->IpVersion, RemoteIp);
535 if (PadEntry == NULL) {
536 return EFI_ACCESS_DENIED;
537 }
538 //
539 // Determine the IKE exchange instance by the auth protocol in pad entry.
540 //
541 ASSERT (PadEntry->Data->AuthProtocol < EfiIPsecAuthProtocolMaximum);
542 if (PadEntry->Data->AuthProtocol == EfiIPsecAuthProtocolIKEv1) {
543 return EFI_INVALID_PARAMETER;
544 }
545 Exchange = mIkeExchange[PadEntry->Data->AuthProtocol];
546 //
547 // Start the main mode stage to negotiate IKE SA.
548 //
549 Status = Exchange->NegotiateSa (UdpService, SpdEntry, PadEntry, RemoteIp);
550 } else {
551 //
552 // Determine the IKE exchange instance by the IKE version in IKE SA session.
553 //
554 IkeVersion = IkeGetVersionFromSession (IkeSaSession);
555 if (IkeVersion != 2) {
556 return EFI_INVALID_PARAMETER;
557 }
qianouyang6cf92302011-11-23 10:31:04 +0000558
qianouyang9166f842010-12-31 10:43:54 +0000559 Exchange = mIkeExchange[IkeVersion - 1];
560 //
561 // Start the quick mode stage to negotiate child SA.
562 //
563 Status = Exchange->NegotiateChildSa (IkeSaSession, SpdEntry, NULL);
564 }
565
566 return Status;
567}
568
569/**
570 The generic interface when receive a IKE packet.
qianouyang6cf92302011-11-23 10:31:04 +0000571
qianouyang9166f842010-12-31 10:43:54 +0000572 This function is called when UDP IO receives a IKE packet.
qianouyang6cf92302011-11-23 10:31:04 +0000573
qianouyang9166f842010-12-31 10:43:54 +0000574 @param[in] Packet Point to received IKE packet.
qianouyang6cf92302011-11-23 10:31:04 +0000575 @param[in] EndPoint Point to UDP_END_POINT which contains the information of
qianouyang9166f842010-12-31 10:43:54 +0000576 Remote IP and Port.
577 @param[in] IoStatus The Status of Recieve Token.
578 @param[in] Context Point to data passed from the caller.
qianouyang6cf92302011-11-23 10:31:04 +0000579
qianouyang9166f842010-12-31 10:43:54 +0000580**/
581VOID
jljusten1d8fa5e2011-01-03 03:17:20 +0000582EFIAPI
qianouyang9166f842010-12-31 10:43:54 +0000583IkeDispatch (
584 IN NET_BUF *Packet,
585 IN UDP_END_POINT *EndPoint,
586 IN EFI_STATUS IoStatus,
587 IN VOID *Context
588 )
589{
590 IPSEC_PRIVATE_DATA *Private;
591 IKE_PACKET *IkePacket;
592 IKE_HEADER *IkeHdr;
593 IKE_UDP_SERVICE *UdpService;
594 IKE_EXCHANGE_INTERFACE *Exchange;
595 EFI_STATUS Status;
596
597 UdpService = (IKE_UDP_SERVICE *) Context;
598 IkePacket = NULL;
599 Private = (UdpService->IpVersion == IP_VERSION_4) ?
600 IPSEC_PRIVATE_DATA_FROM_UDP4LIST(UdpService->ListHead) :
601 IPSEC_PRIVATE_DATA_FROM_UDP6LIST(UdpService->ListHead);
602
603 if (EFI_ERROR (IoStatus)) {
604 goto ON_EXIT;
605 }
606 //
607 // Check whether the ipsec is enabled or not.
608 //
609 if (Private->IpSec.DisabledFlag == TRUE) {
610 goto ON_EXIT;
611 }
612
613 if (EndPoint->RemotePort != IKE_DEFAULT_PORT) {
614 goto ON_EXIT;
615 }
616
617 //
618 // Build IKE packet from the received netbuf.
619 //
620 IkePacket = IkePacketFromNetbuf (Packet);
621
622 if (IkePacket == NULL) {
623 goto ON_EXIT;
624 }
625 //
626 // Get the remote address from the IKE packet.
627 //
628 if (UdpService->IpVersion == IP_VERSION_4) {
629 *(UINT32 *) IkePacket->RemotePeerIp.Addr = HTONL ((*(UINT32 *) EndPoint->RemoteAddr.Addr));
630 } else {
631 CopyMem (
632 &IkePacket->RemotePeerIp,
633 NTOHLLL (&EndPoint->RemoteAddr.v6),
634 sizeof (EFI_IPv6_ADDRESS)
635 );
636 }
637 //
638 // Try to open udp io for output if hasn't.
639 //
640 Status = IkeOpenOutputUdp (UdpService, &IkePacket->RemotePeerIp);
641
642 if (EFI_ERROR (Status)) {
643 goto ON_EXIT;
644 }
645
646 IkeHdr = IkePacket->Header;
647
648 //
649 // Determine the IKE exchange instance by the IKE version in IKE header.
650 //
651 if (IKE_MAJOR_VERSION (IkeHdr->Version) == 2) {
652 Exchange = mIkeExchange[IKE_MAJOR_VERSION (IkeHdr->Version) - 1];
653 } else {
654 goto ON_EXIT;
655 }
656
657 switch (IkeHdr->ExchangeType) {
658 case IKE_XCG_TYPE_IDENTITY_PROTECT:
659 case IKE_XCG_TYPE_SA_INIT:
660 case IKE_XCG_TYPE_AUTH:
661 Exchange->HandleSa (UdpService, IkePacket);
662 break;
663
664 case IKE_XCG_TYPE_QM:
665 case IKE_XCG_TYPE_CREATE_CHILD_SA:
666 Exchange->HandleChildSa (UdpService, IkePacket);
667 break;
668
669 case IKE_XCG_TYPE_INFO:
670 case IKE_XCG_TYPE_INFO2:
671 Exchange->HandleInfo (UdpService, IkePacket);
672 break;
673
674 default:
675 break;
676 }
677
678ON_EXIT:
679 if (IkePacket != NULL) {
680 IkePacketFree (IkePacket);
681 }
682
683 if (Packet != NULL) {
684 NetbufFree (Packet);
685 }
686
687 UdpIoRecvDatagram (UdpService->Input, IkeDispatch, UdpService, 0);
688
689 return ;
690}
691
692/**
693 Delete all established IKE SAs and related Child SAs.
qianouyang6cf92302011-11-23 10:31:04 +0000694
695 This function is the subfunction of the IpSecCleanupAllSa(). It first calls
696 IkeDeleteChildSa() to delete all Child SAs then send out the related
qianouyang9166f842010-12-31 10:43:54 +0000697 Information packet.
698
qianouyang6cf92302011-11-23 10:31:04 +0000699 @param[in] Private Pointer of the IPSEC_PRIVATE_DATA
qianouyang4b0f5772011-12-05 03:17:15 +0000700 @param[in] IsDisableIpsec Indicate whether needs to disable IPsec.
qianouyang9166f842010-12-31 10:43:54 +0000701
702**/
703VOID
704IkeDeleteAllSas (
qianouyang6cf92302011-11-23 10:31:04 +0000705 IN IPSEC_PRIVATE_DATA *Private,
706 IN BOOLEAN IsDisableIpsec
qianouyang9166f842010-12-31 10:43:54 +0000707 )
708{
709 LIST_ENTRY *Entry;
710 LIST_ENTRY *NextEntry;
711 IKEV2_SA_SESSION *Ikev2SaSession;
712 UINT8 Value;
713 EFI_STATUS Status;
714 IKE_EXCHANGE_INTERFACE *Exchange;
715 UINT8 IkeVersion;
716
717 Exchange = NULL;
718
719 //
720 // If the IKEv1 is supported, first deal with the Ikev1Estatblished list.
721 //
722
723 //
724 // If IKEv2 SAs are under establishing, delete it directly.
725 //
726 if (!IsListEmpty (&Private->Ikev2SessionList)) {
727 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Ikev2SessionList) {
qianouyang6cf92302011-11-23 10:31:04 +0000728 Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
qianouyang9166f842010-12-31 10:43:54 +0000729 RemoveEntryList (Entry);
730 Ikev2SaSessionFree (Ikev2SaSession);
731 }
732 }
qianouyang6cf92302011-11-23 10:31:04 +0000733
qianouyang9166f842010-12-31 10:43:54 +0000734 //
735 // If there is no existing established IKE SA, set the Ipsec DisableFlag to TRUE
736 // and turn off the IsIPsecDisabling flag.
737 //
qianouyang6cf92302011-11-23 10:31:04 +0000738 if (IsListEmpty (&Private->Ikev2EstablishedList) && IsDisableIpsec) {
qianouyang9166f842010-12-31 10:43:54 +0000739 Value = IPSEC_STATUS_DISABLED;
740 Status = gRT->SetVariable (
741 IPSECCONFIG_STATUS_NAME,
742 &gEfiIpSecConfigProtocolGuid,
743 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
744 sizeof (Value),
745 &Value
746 );
747 if (!EFI_ERROR (Status)) {
748 Private->IpSec.DisabledFlag = TRUE;
749 Private->IsIPsecDisabling = FALSE;
750 return ;
751 }
752 }
753
754 //
755 // Delete established IKEv2 SAs.
756 //
757 if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
758 for (Entry = Private->Ikev2EstablishedList.ForwardLink; Entry != &Private->Ikev2EstablishedList;) {
759 Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
760 Entry = Entry->ForwardLink;
qianouyang6cf92302011-11-23 10:31:04 +0000761
qianouyang9166f842010-12-31 10:43:54 +0000762 Ikev2SaSession->SessionCommon.State = IkeStateSaDeleting;
763
764 //
765 // Call for Information Exchange.
766 //
767 IkeVersion = IkeGetVersionFromSession ((UINT8*)Ikev2SaSession);
768 if (IkeVersion == 2) {
769 Exchange = mIkeExchange[IkeVersion - 1];
770 Exchange->NegotiateInfo((UINT8*)Ikev2SaSession, NULL);
qianouyang6cf92302011-11-23 10:31:04 +0000771 }
qianouyang9166f842010-12-31 10:43:54 +0000772 }
773 }
qianouyang6cf92302011-11-23 10:31:04 +0000774
qianouyang9166f842010-12-31 10:43:54 +0000775}
776
777
778