]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/IpSecDriver.c
1.Update IPsec driver to set the Transform structure’s Next Payload field to be zero...
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Driver Binding Protocol for IPsec Driver.\r
3\r
6cf9230f 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
a3bcde70
HT
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
9166f840 16#include <Library/BaseCryptLib.h>\r
17\r
a3bcde70 18#include "IpSecConfigImpl.h"\r
9166f840 19#include "IkeService.h"\r
a3bcde70
HT
20#include "IpSecDebug.h"\r
21\r
22/**\r
23 Test to see if this driver supports ControllerHandle.\r
24\r
25 @param[in] This Protocol instance pointer.\r
26 @param[in] ControllerHandle Handle of device to test.\r
27 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
28 device to start.\r
29\r
30 @retval EFI_SUCCES This driver supports this device.\r
31 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
32 @retval other This driver does not support this device.\r
33\r
34**/\r
35EFI_STATUS\r
36EFIAPI\r
37IpSecDriverBindingSupported (\r
38 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
39 IN EFI_HANDLE ControllerHandle,\r
40 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
41 )\r
42{\r
9166f840 43 EFI_STATUS Udp4Status;\r
44 EFI_STATUS Udp6Status;\r
45\r
46 Udp4Status = gBS->OpenProtocol (\r
47 ControllerHandle,\r
48 &gEfiUdp4ServiceBindingProtocolGuid,\r
49 NULL,\r
50 This->DriverBindingHandle,\r
51 ControllerHandle,\r
52 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
53 );\r
54\r
55 Udp6Status = gBS->OpenProtocol (\r
56 ControllerHandle,\r
57 &gEfiUdp6ServiceBindingProtocolGuid,\r
58 NULL,\r
59 This->DriverBindingHandle,\r
60 ControllerHandle,\r
61 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
62 );\r
63\r
a3bcde70 64 //\r
9166f840 65 // The controller with either Udp4Sb or Udp6Sb is supported.\r
a3bcde70 66 //\r
9166f840 67 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {\r
68 return EFI_SUCCESS;\r
69 }\r
70\r
a3bcde70
HT
71 return EFI_UNSUPPORTED;\r
72}\r
73\r
74/**\r
75 Start this driver on ControllerHandle.\r
76\r
77 @param[in] This Protocol instance pointer.\r
78 @param[in] ControllerHandle Handle of device to bind driver to.\r
79 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
80 device to start.\r
81\r
82 @retval EFI_SUCCES This driver is added to ControllerHandle\r
83 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
6cf9230f 84 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.\r
a3bcde70
HT
85 Currently not implemented.\r
86 @retval other This driver does not support this device\r
87\r
88**/\r
89EFI_STATUS\r
90EFIAPI\r
91IpSecDriverBindingStart (\r
92 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
93 IN EFI_HANDLE ControllerHandle,\r
94 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
95 )\r
96{\r
0a7294f7 97 EFI_IPSEC2_PROTOCOL *IpSec;\r
9166f840 98 EFI_STATUS Status;\r
99 EFI_STATUS Udp4Status;\r
100 EFI_STATUS Udp6Status;\r
101 IPSEC_PRIVATE_DATA *Private;\r
102\r
a3bcde70 103 //\r
9166f840 104 // Ipsec protocol should be installed when load image.\r
a3bcde70 105 //\r
0a7294f7 106 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);\r
9166f840 107\r
108 if (EFI_ERROR (Status)) {\r
109 return Status;\r
110 }\r
111\r
112 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);\r
113\r
114 //\r
115 // If udp4 sb is on the controller, try to open a udp4 io for input.\r
116 //\r
117 Udp4Status = gBS->OpenProtocol (\r
118 ControllerHandle,\r
119 &gEfiUdp4ServiceBindingProtocolGuid,\r
120 NULL,\r
121 This->DriverBindingHandle,\r
122 ControllerHandle,\r
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
124 );\r
125\r
126 if (!EFI_ERROR (Udp4Status)) {\r
127 Udp4Status = IkeOpenInputUdp4 (Private, ControllerHandle);\r
128 }\r
129 //\r
130 // If udp6 sb is on the controller, try to open a udp6 io for input.\r
131 //\r
132 Udp6Status = gBS->OpenProtocol (\r
133 ControllerHandle,\r
134 &gEfiUdp6ServiceBindingProtocolGuid,\r
135 NULL,\r
136 This->DriverBindingHandle,\r
137 ControllerHandle,\r
138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
139 );\r
140\r
141 if (!EFI_ERROR (Udp6Status)) {\r
142 Udp6Status = IkeOpenInputUdp6 (Private, ControllerHandle);\r
143 }\r
144\r
145 if (!EFI_ERROR (Udp4Status) || !EFI_ERROR (Udp6Status)) {\r
146 return EFI_SUCCESS;\r
147 }\r
148\r
149 return EFI_DEVICE_ERROR;\r
a3bcde70
HT
150}\r
151\r
152/**\r
153 Stop this driver on ControllerHandle.\r
154\r
155 @param[in] This Protocol instance pointer.\r
156 @param[in] ControllerHandle Handle of a device to stop the driver on.\r
157 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If the number of\r
158 children is zero, stop the entire bus driver.\r
159 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
160\r
161 @retval EFI_SUCCES This driver removed ControllerHandle.\r
162 @retval other This driver was not removed from this device.\r
163\r
164**/\r
165EFI_STATUS\r
166EFIAPI\r
167IpSecDriverBindingStop (\r
168 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
169 IN EFI_HANDLE ControllerHandle,\r
170 IN UINTN NumberOfChildren,\r
171 IN EFI_HANDLE *ChildHandleBuffer\r
172 )\r
173{\r
0a7294f7 174 EFI_IPSEC2_PROTOCOL *IpSec;\r
9166f840 175 EFI_STATUS Status;\r
176 IPSEC_PRIVATE_DATA *Private;\r
177 IKE_UDP_SERVICE *UdpSrv;\r
178 LIST_ENTRY *Entry;\r
179 LIST_ENTRY *Next;\r
180\r
a3bcde70 181 //\r
9166f840 182 // Locate ipsec protocol to get private data.\r
a3bcde70 183 //\r
0a7294f7 184 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);\r
9166f840 185\r
186 if (EFI_ERROR (Status)) {\r
187 return Status;\r
188 }\r
189\r
190 Private = IPSEC_PRIVATE_DATA_FROM_IPSEC (IpSec);\r
191\r
6cf9230f 192 //\r
193 // Delete all SAs before stop Ipsec.\r
194 //\r
195 IkeDeleteAllSas (Private, FALSE);\r
9166f840 196 //\r
197 // If has udp4 io opened on the controller, close and free it.\r
198 //\r
199 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {\r
200\r
201 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);\r
202 //\r
203 // Find the right udp service which installed on the appointed nic handle.\r
204 //\r
205 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {\r
206 UdpIoFreeIo (UdpSrv->Input);\r
207 UdpSrv->Input = NULL;\r
208 }\r
209\r
210 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {\r
211 UdpIoFreeIo (UdpSrv->Output);\r
212 UdpSrv->Output = NULL;\r
213 }\r
214\r
215 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {\r
216 RemoveEntryList (&UdpSrv->List);\r
217 FreePool (UdpSrv);\r
218 ASSERT (Private->Udp4Num > 0);\r
219 Private->Udp4Num--;\r
220 }\r
221 }\r
222 //\r
223 // If has udp6 io opened on the controller, close and free it.\r
224 //\r
225 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {\r
226\r
227 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);\r
228 //\r
229 // Find the right udp service which installed on the appointed nic handle.\r
230 //\r
231 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {\r
232 UdpIoFreeIo (UdpSrv->Input);\r
233 UdpSrv->Input = NULL;\r
234 }\r
235\r
236 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {\r
237 UdpIoFreeIo (UdpSrv->Output);\r
238 UdpSrv->Output = NULL;\r
239 }\r
240\r
241 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {\r
242 RemoveEntryList (&UdpSrv->List);\r
243 FreePool (UdpSrv);\r
244 ASSERT (Private->Udp6Num > 0);\r
245 Private->Udp6Num--;\r
246 }\r
247 }\r
248\r
249 return EFI_SUCCESS;\r
a3bcde70
HT
250}\r
251\r
252EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {\r
253 IpSecDriverBindingSupported,\r
254 IpSecDriverBindingStart,\r
255 IpSecDriverBindingStop,\r
256 0xa,\r
257 NULL,\r
258 NULL\r
259};\r
260\r
261/**\r
262 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.\r
6cf9230f 263\r
a3bcde70 264 @param[in] Event Event whose notification function is being invoked.\r
6cf9230f 265 @param[in] Context Pointer to the notification function's context.\r
a3bcde70
HT
266\r
267**/\r
268VOID\r
269EFIAPI\r
270IpSecCleanupAllSa (\r
271 IN EFI_EVENT Event,\r
272 IN VOID *Context\r
273 )\r
274{\r
275 IPSEC_PRIVATE_DATA *Private;\r
9166f840 276 Private = (IPSEC_PRIVATE_DATA *) Context;\r
277 Private->IsIPsecDisabling = TRUE;\r
6cf9230f 278 IkeDeleteAllSas (Private, TRUE);\r
a3bcde70
HT
279}\r
280\r
281/**\r
282 This is the declaration of an EFI image entry point. This entry point is\r
283 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including\r
284 both device drivers and bus drivers.\r
6cf9230f 285\r
286 The entry point for IPsec driver which installs the driver binding,\r
a3bcde70
HT
287 component name protocol, IPsec Config protcolon, and IPsec protocol in\r
288 its ImageHandle.\r
289\r
290 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
291 @param[in] SystemTable A pointer to the EFI System Table.\r
292\r
293 @retval EFI_SUCCESS The operation completed successfully.\r
294 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.\r
295 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
6cf9230f 296 @retval Others The operation is failed.\r
a3bcde70
HT
297\r
298**/\r
299EFI_STATUS\r
300EFIAPI\r
301IpSecDriverEntryPoint (\r
302 IN EFI_HANDLE ImageHandle,\r
303 IN EFI_SYSTEM_TABLE *SystemTable\r
304 )\r
305{\r
306 EFI_STATUS Status;\r
307 IPSEC_PRIVATE_DATA *Private;\r
0a7294f7 308 EFI_IPSEC2_PROTOCOL *IpSec;\r
a3bcde70
HT
309\r
310 //\r
311 // Check whether ipsec protocol has already been installed.\r
312 //\r
0a7294f7 313 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);\r
a3bcde70
HT
314\r
315 if (!EFI_ERROR (Status)) {\r
316 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));\r
317 Status = EFI_ALREADY_STARTED;\r
318 goto ON_EXIT;\r
319 }\r
320\r
321 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);\r
322\r
323 if (EFI_ERROR (Status)) {\r
324 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));\r
325 goto ON_EXIT;\r
326 }\r
327\r
328 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));\r
329\r
330 if (Private == NULL) {\r
331 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));\r
332 Status = EFI_OUT_OF_RESOURCES;\r
333 goto ON_EXIT;\r
334 }\r
335 //\r
9166f840 336 // Create disable event to cleanup all SA when ipsec disabled by user.\r
a3bcde70
HT
337 //\r
338 Status = gBS->CreateEvent (\r
339 EVT_NOTIFY_SIGNAL,\r
340 TPL_CALLBACK,\r
341 IpSecCleanupAllSa,\r
342 Private,\r
343 &mIpSecInstance.DisabledEvent\r
344 );\r
345 if (EFI_ERROR (Status)) {\r
346 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));\r
347 goto ON_FREE_PRIVATE;\r
348 }\r
349\r
350 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;\r
351 Private->ImageHandle = ImageHandle;\r
0a7294f7 352 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));\r
6cf9230f 353\r
a3bcde70
HT
354 //\r
355 // Initilize Private's members. Thess members is used for IKE.\r
356 //\r
357 InitializeListHead (&Private->Udp4List);\r
358 InitializeListHead (&Private->Udp6List);\r
359 InitializeListHead (&Private->Ikev1SessionList);\r
360 InitializeListHead (&Private->Ikev1EstablishedList);\r
361 InitializeListHead (&Private->Ikev2SessionList);\r
362 InitializeListHead (&Private->Ikev2EstablishedList);\r
6cf9230f 363\r
9166f840 364 RandomSeed (NULL, 0);\r
a3bcde70
HT
365 //\r
366 // Initialize the ipsec config data and restore it from variable.\r
367 //\r
368 Status = IpSecConfigInitialize (Private);\r
369 if (EFI_ERROR (Status)) {\r
370 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));\r
371 goto ON_CLOSE_EVENT;\r
372 }\r
373 //\r
374 // Install ipsec protocol which is used by ip driver to process ipsec header.\r
375 //\r
376 Status = gBS->InstallMultipleProtocolInterfaces (\r
377 &Private->Handle,\r
0a7294f7 378 &gEfiIpSec2ProtocolGuid,\r
a3bcde70
HT
379 &Private->IpSec,\r
380 NULL\r
381 );\r
382 if (EFI_ERROR (Status)) {\r
383 goto ON_UNINSTALL_CONFIG;\r
384 }\r
385\r
386 Status = EfiLibInstallDriverBindingComponentName2 (\r
387 ImageHandle,\r
388 SystemTable,\r
389 &gIpSecDriverBinding,\r
390 ImageHandle,\r
391 &gIpSecComponentName,\r
392 &gIpSecComponentName2\r
393 );\r
394 if (EFI_ERROR (Status)) {\r
9166f840 395 goto ON_UNINSTALL_IPSEC;\r
a3bcde70 396 }\r
6cf9230f 397\r
a3bcde70
HT
398 return Status;\r
399\r
9166f840 400ON_UNINSTALL_IPSEC:\r
401 gBS->UninstallProtocolInterface (\r
402 Private->Handle,\r
0a7294f7 403 &gEfiIpSec2ProtocolGuid,\r
9166f840 404 &Private->IpSec\r
405 );\r
a3bcde70
HT
406ON_UNINSTALL_CONFIG:\r
407 gBS->UninstallProtocolInterface (\r
408 Private->Handle,\r
409 &gEfiIpSecConfigProtocolGuid,\r
410 &Private->IpSecConfig\r
411 );\r
412ON_CLOSE_EVENT:\r
413 gBS->CloseEvent (mIpSecInstance.DisabledEvent);\r
414 mIpSecInstance.DisabledEvent = NULL;\r
415ON_FREE_PRIVATE:\r
416 FreePool (Private);\r
417ON_EXIT:\r
418 return Status;\r
419}\r
420\r