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