]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IpSecDxe/IpSecDriver.c
NetworkPkg: Fix hang issue after system reconnected when IPSec has set up
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
1 /** @file
2 Driver Binding Protocol for IPsec Driver.
3
4 Copyright (c) 2009 - 2015, 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 <Library/BaseCryptLib.h>
17
18 #include "IpSecConfigImpl.h"
19 #include "IkeService.h"
20 #include "IpSecDebug.h"
21
22 /**
23 Test to see if this driver supports ControllerHandle. This is the worker function
24 for IpSec4(6)DriverbindingSupported.
25
26 @param[in] This Protocol instance pointer.
27 @param[in] ControllerHandle Handle of device to test.
28 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
29 device to start.
30 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
31
32 @retval EFI_SUCCES This driver supports this device.
33 @retval EFI_ALREADY_STARTED This driver is already running on this device.
34 @retval other This driver does not support this device.
35
36 **/
37 EFI_STATUS
38 EFIAPI
39 IpSecSupported (
40 IN EFI_DRIVER_BINDING_PROTOCOL *This,
41 IN EFI_HANDLE ControllerHandle,
42 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
43 IN UINT8 IpVersion
44 )
45 {
46 EFI_STATUS Status;
47 EFI_GUID *UdpServiceBindingGuid;
48
49 if (IpVersion == IP_VERSION_4) {
50 UdpServiceBindingGuid = &gEfiUdp4ServiceBindingProtocolGuid;
51 } else {
52 UdpServiceBindingGuid = &gEfiUdp6ServiceBindingProtocolGuid;
53 }
54
55 Status = gBS->OpenProtocol (
56 ControllerHandle,
57 UdpServiceBindingGuid,
58 NULL,
59 This->DriverBindingHandle,
60 ControllerHandle,
61 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
62 );
63 if (EFI_ERROR (Status)) {
64 return EFI_UNSUPPORTED;
65 }
66 return EFI_SUCCESS;
67 }
68
69 /**
70 Start this driver on ControllerHandle. This is the worker function
71 for IpSec4(6)DriverbindingStart.
72
73 @param[in] This Protocol instance pointer.
74 @param[in] ControllerHandle Handle of device to bind driver to.
75 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
76 device to start.
77 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
78
79 @retval EFI_SUCCES This driver is added to ControllerHandle
80 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
81 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
82 Currently not implemented.
83 @retval other This driver does not support this device
84
85 **/
86 EFI_STATUS
87 EFIAPI
88 IpSecStart (
89 IN EFI_DRIVER_BINDING_PROTOCOL *This,
90 IN EFI_HANDLE ControllerHandle,
91 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
92 IN UINT8 IpVersion
93 )
94 {
95 EFI_IPSEC2_PROTOCOL *IpSec;
96 EFI_STATUS Status;
97 IPSEC_PRIVATE_DATA *Private;
98
99 //
100 // Ipsec protocol should be installed when load image.
101 //
102 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
103
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
109
110 if (IpVersion == IP_VERSION_4) {
111 //
112 // Try to open a udp4 io for input.
113 //
114 Status = gBS->OpenProtocol (
115 ControllerHandle,
116 &gEfiUdp4ServiceBindingProtocolGuid,
117 NULL,
118 This->DriverBindingHandle,
119 ControllerHandle,
120 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
121 );
122
123 if (!EFI_ERROR (Status)) {
124 Status = IkeOpenInputUdp4 (Private, ControllerHandle, This->DriverBindingHandle);
125 }
126 } else {
127 //
128 // Try to open a udp6 io for input.
129 //
130 Status = gBS->OpenProtocol (
131 ControllerHandle,
132 &gEfiUdp6ServiceBindingProtocolGuid,
133 NULL,
134 This->DriverBindingHandle,
135 ControllerHandle,
136 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
137 );
138
139 if (!EFI_ERROR (Status)) {
140 Status = IkeOpenInputUdp6 (Private, ControllerHandle, This->DriverBindingHandle);
141 }
142 }
143
144 if (EFI_ERROR (Status)) {
145 return EFI_DEVICE_ERROR;
146 }
147 return EFI_SUCCESS;
148 }
149
150 /**
151 Stop this driver on ControllerHandle. This is the worker function
152 for IpSec4(6)DriverbindingStop.
153
154 @param[in] This Protocol instance pointer.
155 @param[in] ControllerHandle Handle of a device to stop the driver on.
156 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
157 children is zero, stop the entire bus driver.
158 @param[in] ChildHandleBuffer List of Child Handles to Stop.
159 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
160
161 @retval EFI_SUCCES This driver removed ControllerHandle.
162 @retval other This driver was not removed from this device.
163
164 **/
165 EFI_STATUS
166 EFIAPI
167 IpSecStop (
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,
169 IN EFI_HANDLE ControllerHandle,
170 IN UINTN NumberOfChildren,
171 IN EFI_HANDLE *ChildHandleBuffer,
172 IN UINT8 IpVersion
173 )
174 {
175 EFI_IPSEC2_PROTOCOL *IpSec;
176 EFI_STATUS Status;
177 IPSEC_PRIVATE_DATA *Private;
178 IKE_UDP_SERVICE *UdpSrv;
179 LIST_ENTRY *Entry;
180 LIST_ENTRY *Next;
181 IKEV2_SA_SESSION *Ikev2SaSession;
182
183 //
184 // Locate ipsec protocol to get private data.
185 //
186 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
187
188 if (EFI_ERROR (Status)) {
189 return Status;
190 }
191
192 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);
193
194 //
195 // The SAs are shared by both IP4 and IP6 stack. So we skip the cleanup
196 // and leave the SAs unchanged if the other IP stack is still running.
197 //
198 if ((IpVersion == IP_VERSION_4 && Private->Udp6Num ==0) ||
199 (IpVersion == IP_VERSION_6 && Private->Udp4Num ==0)) {
200 //
201 // If IKEv2 SAs are under establishing, delete it directly.
202 //
203 if (!IsListEmpty (&Private->Ikev2SessionList)) {
204 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Ikev2SessionList) {
205 Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
206 RemoveEntryList (&Ikev2SaSession->BySessionTable);
207 Ikev2SaSessionFree (Ikev2SaSession);
208 }
209 }
210
211 //
212 // Delete established IKEv2 SAs.
213 //
214 if (!IsListEmpty (&Private->Ikev2EstablishedList)) {
215 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Ikev2EstablishedList) {
216 Ikev2SaSession = IKEV2_SA_SESSION_BY_SESSION (Entry);
217 RemoveEntryList (&Ikev2SaSession->BySessionTable);
218 Ikev2SaSessionFree (Ikev2SaSession);
219 }
220 }
221 }
222
223 if (IpVersion == IP_VERSION_4) {
224 //
225 // If has udp4 io opened on the controller, close and free it.
226 //
227 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {
228
229 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
230 //
231 // Find the right udp service which installed on the appointed nic handle.
232 //
233 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
234 UdpIoFreeIo (UdpSrv->Input);
235 UdpSrv->Input = NULL;
236 }
237
238 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
239 UdpIoFreeIo (UdpSrv->Output);
240 UdpSrv->Output = NULL;
241 }
242
243 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
244 RemoveEntryList (&UdpSrv->List);
245 FreePool (UdpSrv);
246 ASSERT (Private->Udp4Num > 0);
247 Private->Udp4Num--;
248 }
249 }
250 } else {
251 //
252 // If has udp6 io opened on the controller, close and free it.
253 //
254 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {
255
256 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);
257 //
258 // Find the right udp service which installed on the appointed nic handle.
259 //
260 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {
261 UdpIoFreeIo (UdpSrv->Input);
262 UdpSrv->Input = NULL;
263 }
264
265 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {
266 UdpIoFreeIo (UdpSrv->Output);
267 UdpSrv->Output = NULL;
268 }
269
270 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {
271 RemoveEntryList (&UdpSrv->List);
272 FreePool (UdpSrv);
273 ASSERT (Private->Udp6Num > 0);
274 Private->Udp6Num--;
275 }
276 }
277 }
278
279 return EFI_SUCCESS;
280 }
281
282 /**
283 Test to see if this driver supports ControllerHandle.
284
285 @param[in] This Protocol instance pointer.
286 @param[in] ControllerHandle Handle of device to test.
287 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
288 device to start.
289
290 @retval EFI_SUCCES This driver supports this device.
291 @retval EFI_ALREADY_STARTED This driver is already running on this device.
292 @retval other This driver does not support this device.
293
294 **/
295 EFI_STATUS
296 EFIAPI
297 IpSec4DriverBindingSupported (
298 IN EFI_DRIVER_BINDING_PROTOCOL *This,
299 IN EFI_HANDLE ControllerHandle,
300 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
301 )
302 {
303 return IpSecSupported (
304 This,
305 ControllerHandle,
306 RemainingDevicePath,
307 IP_VERSION_4
308 );
309 }
310
311 /**
312 Start this driver on ControllerHandle.
313
314 @param[in] This Protocol instance pointer.
315 @param[in] ControllerHandle Handle of device to bind driver to.
316 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
317 device to start.
318
319 @retval EFI_SUCCES This driver is added to ControllerHandle
320 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
321 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
322 Currently not implemented.
323 @retval other This driver does not support this device
324
325 **/
326 EFI_STATUS
327 EFIAPI
328 IpSec4DriverBindingStart (
329 IN EFI_DRIVER_BINDING_PROTOCOL *This,
330 IN EFI_HANDLE ControllerHandle,
331 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
332 )
333 {
334 return IpSecStart (
335 This,
336 ControllerHandle,
337 RemainingDevicePath,
338 IP_VERSION_4
339 );
340 }
341
342 /**
343 Stop this driver on ControllerHandle.
344
345 @param[in] This Protocol instance pointer.
346 @param[in] ControllerHandle Handle of a device to stop the driver on.
347 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
348 children is zero, stop the entire bus driver.
349 @param[in] ChildHandleBuffer List of Child Handles to Stop.
350
351 @retval EFI_SUCCES This driver removed ControllerHandle.
352 @retval other This driver was not removed from this device.
353
354 **/
355 EFI_STATUS
356 EFIAPI
357 IpSec4DriverBindingStop (
358 IN EFI_DRIVER_BINDING_PROTOCOL *This,
359 IN EFI_HANDLE ControllerHandle,
360 IN UINTN NumberOfChildren,
361 IN EFI_HANDLE *ChildHandleBuffer
362 )
363 {
364 return IpSecStop (
365 This,
366 ControllerHandle,
367 NumberOfChildren,
368 ChildHandleBuffer,
369 IP_VERSION_4
370 );
371 }
372
373 /**
374 Test to see if this driver supports ControllerHandle.
375
376 @param[in] This Protocol instance pointer.
377 @param[in] ControllerHandle Handle of device to test.
378 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
379 device to start.
380
381 @retval EFI_SUCCES This driver supports this device.
382 @retval EFI_ALREADY_STARTED This driver is already running on this device.
383 @retval other This driver does not support this device.
384
385 **/
386 EFI_STATUS
387 EFIAPI
388 IpSec6DriverBindingSupported (
389 IN EFI_DRIVER_BINDING_PROTOCOL *This,
390 IN EFI_HANDLE ControllerHandle,
391 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
392 )
393 {
394 return IpSecSupported (
395 This,
396 ControllerHandle,
397 RemainingDevicePath,
398 IP_VERSION_6
399 );
400 }
401
402 /**
403 Start this driver on ControllerHandle.
404
405 @param[in] This Protocol instance pointer.
406 @param[in] ControllerHandle Handle of device to bind driver to.
407 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
408 device to start.
409
410 @retval EFI_SUCCES This driver is added to ControllerHandle
411 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
412 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
413 Currently not implemented.
414 @retval other This driver does not support this device
415
416 **/
417 EFI_STATUS
418 EFIAPI
419 IpSec6DriverBindingStart (
420 IN EFI_DRIVER_BINDING_PROTOCOL *This,
421 IN EFI_HANDLE ControllerHandle,
422 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
423 )
424 {
425 return IpSecStart (
426 This,
427 ControllerHandle,
428 RemainingDevicePath,
429 IP_VERSION_6
430 );
431 }
432
433 /**
434 Stop this driver on ControllerHandle.
435
436 @param[in] This Protocol instance pointer.
437 @param[in] ControllerHandle Handle of a device to stop the driver on.
438 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of
439 children is zero, stop the entire bus driver.
440 @param[in] ChildHandleBuffer List of Child Handles to Stop.
441
442 @retval EFI_SUCCES This driver removed ControllerHandle.
443 @retval other This driver was not removed from this device.
444
445 **/
446 EFI_STATUS
447 EFIAPI
448 IpSec6DriverBindingStop (
449 IN EFI_DRIVER_BINDING_PROTOCOL *This,
450 IN EFI_HANDLE ControllerHandle,
451 IN UINTN NumberOfChildren,
452 IN EFI_HANDLE *ChildHandleBuffer
453 )
454 {
455 return IpSecStop (
456 This,
457 ControllerHandle,
458 NumberOfChildren,
459 ChildHandleBuffer,
460 IP_VERSION_6
461 );
462 }
463
464 EFI_DRIVER_BINDING_PROTOCOL gIpSec4DriverBinding = {
465 IpSec4DriverBindingSupported,
466 IpSec4DriverBindingStart,
467 IpSec4DriverBindingStop,
468 0xa,
469 NULL,
470 NULL
471 };
472
473 EFI_DRIVER_BINDING_PROTOCOL gIpSec6DriverBinding = {
474 IpSec6DriverBindingSupported,
475 IpSec6DriverBindingStart,
476 IpSec6DriverBindingStop,
477 0xa,
478 NULL,
479 NULL
480 };
481
482 /**
483 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.
484
485 @param[in] Event Event whose notification function is being invoked.
486 @param[in] Context Pointer to the notification function's context.
487
488 **/
489 VOID
490 EFIAPI
491 IpSecCleanupAllSa (
492 IN EFI_EVENT Event,
493 IN VOID *Context
494 )
495 {
496 IPSEC_PRIVATE_DATA *Private;
497 Private = (IPSEC_PRIVATE_DATA *) Context;
498 Private->IsIPsecDisabling = TRUE;
499 IkeDeleteAllSas (Private, TRUE);
500 }
501
502 /**
503 This is the declaration of an EFI image entry point. This entry point is
504 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
505 both device drivers and bus drivers.
506
507 The entry point for IPsec driver which installs the driver binding,
508 component name protocol, IPsec Config protcolon, and IPsec protocol in
509 its ImageHandle.
510
511 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
512 @param[in] SystemTable A pointer to the EFI System Table.
513
514 @retval EFI_SUCCESS The operation completed successfully.
515 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.
516 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
517 @retval Others The operation is failed.
518
519 **/
520 EFI_STATUS
521 EFIAPI
522 IpSecDriverEntryPoint (
523 IN EFI_HANDLE ImageHandle,
524 IN EFI_SYSTEM_TABLE *SystemTable
525 )
526 {
527 EFI_STATUS Status;
528 IPSEC_PRIVATE_DATA *Private;
529 EFI_IPSEC2_PROTOCOL *IpSec;
530
531 //
532 // Check whether ipsec protocol has already been installed.
533 //
534 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);
535
536 if (!EFI_ERROR (Status)) {
537 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));
538 Status = EFI_ALREADY_STARTED;
539 goto ON_EXIT;
540 }
541
542 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);
543
544 if (EFI_ERROR (Status)) {
545 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));
546 goto ON_EXIT;
547 }
548
549 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));
550
551 if (Private == NULL) {
552 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));
553 Status = EFI_OUT_OF_RESOURCES;
554 goto ON_EXIT;
555 }
556 //
557 // Create disable event to cleanup all SA when ipsec disabled by user.
558 //
559 Status = gBS->CreateEvent (
560 EVT_NOTIFY_SIGNAL,
561 TPL_CALLBACK,
562 IpSecCleanupAllSa,
563 Private,
564 &mIpSecInstance.DisabledEvent
565 );
566 if (EFI_ERROR (Status)) {
567 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));
568 goto ON_FREE_PRIVATE;
569 }
570
571 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;
572 Private->ImageHandle = ImageHandle;
573 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));
574
575 //
576 // Initilize Private's members. Thess members is used for IKE.
577 //
578 InitializeListHead (&Private->Udp4List);
579 InitializeListHead (&Private->Udp6List);
580 InitializeListHead (&Private->Ikev1SessionList);
581 InitializeListHead (&Private->Ikev1EstablishedList);
582 InitializeListHead (&Private->Ikev2SessionList);
583 InitializeListHead (&Private->Ikev2EstablishedList);
584
585 RandomSeed (NULL, 0);
586 //
587 // Initialize the ipsec config data and restore it from variable.
588 //
589 Status = IpSecConfigInitialize (Private);
590 if (EFI_ERROR (Status)) {
591 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));
592 goto ON_CLOSE_EVENT;
593 }
594 //
595 // Install ipsec protocol which is used by ip driver to process ipsec header.
596 //
597 Status = gBS->InstallMultipleProtocolInterfaces (
598 &Private->Handle,
599 &gEfiIpSec2ProtocolGuid,
600 &Private->IpSec,
601 NULL
602 );
603 if (EFI_ERROR (Status)) {
604 goto ON_UNINSTALL_CONFIG;
605 }
606
607 Status = EfiLibInstallDriverBindingComponentName2 (
608 ImageHandle,
609 SystemTable,
610 &gIpSec4DriverBinding,
611 ImageHandle,
612 &gIpSecComponentName,
613 &gIpSecComponentName2
614 );
615 if (EFI_ERROR (Status)) {
616 goto ON_UNINSTALL_IPSEC;
617 }
618
619 Status = EfiLibInstallDriverBindingComponentName2 (
620 ImageHandle,
621 SystemTable,
622 &gIpSec6DriverBinding,
623 NULL,
624 &gIpSecComponentName,
625 &gIpSecComponentName2
626 );
627 if (EFI_ERROR (Status)) {
628 goto ON_UNINSTALL_IPSEC4_DB;
629 }
630
631 return Status;
632
633 ON_UNINSTALL_IPSEC4_DB:
634 gBS->UninstallMultipleProtocolInterfaces (
635 ImageHandle,
636 &gEfiDriverBindingProtocolGuid,
637 &gIpSec4DriverBinding,
638 &gEfiComponentName2ProtocolGuid,
639 &gIpSecComponentName2,
640 &gEfiComponentNameProtocolGuid,
641 &gIpSecComponentName,
642 NULL
643 );
644
645 ON_UNINSTALL_IPSEC:
646 gBS->UninstallProtocolInterface (
647 Private->Handle,
648 &gEfiIpSec2ProtocolGuid,
649 &Private->IpSec
650 );
651 ON_UNINSTALL_CONFIG:
652 gBS->UninstallProtocolInterface (
653 Private->Handle,
654 &gEfiIpSecConfigProtocolGuid,
655 &Private->IpSecConfig
656 );
657 ON_CLOSE_EVENT:
658 gBS->CloseEvent (mIpSecInstance.DisabledEvent);
659 mIpSecInstance.DisabledEvent = NULL;
660 ON_FREE_PRIVATE:
661 FreePool (Private);
662 ON_EXIT:
663 return Status;
664 }
665