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 666