Home | History | Annotate | Download | only in IpSecDxe
      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