]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IpSecDxe/IpSecDriver.c
Before decrypting the packet, Ipsec will check if the inbound protected packet is...
[mirror_edk2.git] / NetworkPkg / IpSecDxe / IpSecDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Driver Binding Protocol for IPsec Driver.\r
3\r
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
9166f840 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
192 //\r
193 // If has udp4 io opened on the controller, close and free it.\r
194 //\r
195 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp4List) {\r
196\r
197 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);\r
198 //\r
199 // Find the right udp service which installed on the appointed nic handle.\r
200 //\r
201 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {\r
202 UdpIoFreeIo (UdpSrv->Input);\r
203 UdpSrv->Input = NULL;\r
204 }\r
205\r
206 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {\r
207 UdpIoFreeIo (UdpSrv->Output);\r
208 UdpSrv->Output = NULL;\r
209 }\r
210\r
211 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {\r
212 RemoveEntryList (&UdpSrv->List);\r
213 FreePool (UdpSrv);\r
214 ASSERT (Private->Udp4Num > 0);\r
215 Private->Udp4Num--;\r
216 }\r
217 }\r
218 //\r
219 // If has udp6 io opened on the controller, close and free it.\r
220 //\r
221 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Private->Udp6List) {\r
222\r
223 UdpSrv = IPSEC_UDP_SERVICE_FROM_LIST (Entry);\r
224 //\r
225 // Find the right udp service which installed on the appointed nic handle.\r
226 //\r
227 if (UdpSrv->Input != NULL && ControllerHandle == UdpSrv->Input->UdpHandle) {\r
228 UdpIoFreeIo (UdpSrv->Input);\r
229 UdpSrv->Input = NULL;\r
230 }\r
231\r
232 if (UdpSrv->Output != NULL && ControllerHandle == UdpSrv->Output->UdpHandle) {\r
233 UdpIoFreeIo (UdpSrv->Output);\r
234 UdpSrv->Output = NULL;\r
235 }\r
236\r
237 if (UdpSrv->Input == NULL && UdpSrv->Output == NULL) {\r
238 RemoveEntryList (&UdpSrv->List);\r
239 FreePool (UdpSrv);\r
240 ASSERT (Private->Udp6Num > 0);\r
241 Private->Udp6Num--;\r
242 }\r
243 }\r
244\r
245 return EFI_SUCCESS;\r
a3bcde70
HT
246}\r
247\r
248EFI_DRIVER_BINDING_PROTOCOL gIpSecDriverBinding = {\r
249 IpSecDriverBindingSupported,\r
250 IpSecDriverBindingStart,\r
251 IpSecDriverBindingStop,\r
252 0xa,\r
253 NULL,\r
254 NULL\r
255};\r
256\r
257/**\r
258 This is a callback function when the mIpSecInstance.DisabledEvent is signaled.\r
9166f840 259 \r
a3bcde70 260 @param[in] Event Event whose notification function is being invoked.\r
9166f840 261 @param[in] Context Pointer to the notification function's context. \r
a3bcde70
HT
262\r
263**/\r
264VOID\r
265EFIAPI\r
266IpSecCleanupAllSa (\r
267 IN EFI_EVENT Event,\r
268 IN VOID *Context\r
269 )\r
270{\r
271 IPSEC_PRIVATE_DATA *Private;\r
9166f840 272 Private = (IPSEC_PRIVATE_DATA *) Context;\r
273 Private->IsIPsecDisabling = TRUE;\r
274 IkeDeleteAllSas (Private);\r
a3bcde70
HT
275}\r
276\r
277/**\r
278 This is the declaration of an EFI image entry point. This entry point is\r
279 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including\r
280 both device drivers and bus drivers.\r
9166f840 281 \r
282 The entry point for IPsec driver which installs the driver binding, \r
a3bcde70
HT
283 component name protocol, IPsec Config protcolon, and IPsec protocol in\r
284 its ImageHandle.\r
285\r
286 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
287 @param[in] SystemTable A pointer to the EFI System Table.\r
288\r
289 @retval EFI_SUCCESS The operation completed successfully.\r
290 @retval EFI_ALREADY_STARTED The IPsec driver has been already loaded.\r
291 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
9166f840 292 @retval Others The operation is failed. \r
a3bcde70
HT
293\r
294**/\r
295EFI_STATUS\r
296EFIAPI\r
297IpSecDriverEntryPoint (\r
298 IN EFI_HANDLE ImageHandle,\r
299 IN EFI_SYSTEM_TABLE *SystemTable\r
300 )\r
301{\r
302 EFI_STATUS Status;\r
303 IPSEC_PRIVATE_DATA *Private;\r
0a7294f7 304 EFI_IPSEC2_PROTOCOL *IpSec;\r
a3bcde70
HT
305\r
306 //\r
307 // Check whether ipsec protocol has already been installed.\r
308 //\r
0a7294f7 309 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **) &IpSec);\r
a3bcde70
HT
310\r
311 if (!EFI_ERROR (Status)) {\r
312 DEBUG ((DEBUG_WARN, "_ModuleEntryPoint: IpSec has been already loaded\n"));\r
313 Status = EFI_ALREADY_STARTED;\r
314 goto ON_EXIT;\r
315 }\r
316\r
317 Status = gBS->LocateProtocol (&gEfiDpcProtocolGuid, NULL, (VOID **) &mDpc);\r
318\r
319 if (EFI_ERROR (Status)) {\r
320 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to locate EfiDpcProtocol\n"));\r
321 goto ON_EXIT;\r
322 }\r
323\r
324 Private = AllocateZeroPool (sizeof (IPSEC_PRIVATE_DATA));\r
325\r
326 if (Private == NULL) {\r
327 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to allocate private data\n"));\r
328 Status = EFI_OUT_OF_RESOURCES;\r
329 goto ON_EXIT;\r
330 }\r
331 //\r
9166f840 332 // Create disable event to cleanup all SA when ipsec disabled by user.\r
a3bcde70
HT
333 //\r
334 Status = gBS->CreateEvent (\r
335 EVT_NOTIFY_SIGNAL,\r
336 TPL_CALLBACK,\r
337 IpSecCleanupAllSa,\r
338 Private,\r
339 &mIpSecInstance.DisabledEvent\r
340 );\r
341 if (EFI_ERROR (Status)) {\r
342 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to create disable event\n"));\r
343 goto ON_FREE_PRIVATE;\r
344 }\r
345\r
346 Private->Signature = IPSEC_PRIVATE_DATA_SIGNATURE;\r
347 Private->ImageHandle = ImageHandle;\r
0a7294f7 348 CopyMem (&Private->IpSec, &mIpSecInstance, sizeof (EFI_IPSEC2_PROTOCOL));\r
9166f840 349 \r
a3bcde70
HT
350 //\r
351 // Initilize Private's members. Thess members is used for IKE.\r
352 //\r
353 InitializeListHead (&Private->Udp4List);\r
354 InitializeListHead (&Private->Udp6List);\r
355 InitializeListHead (&Private->Ikev1SessionList);\r
356 InitializeListHead (&Private->Ikev1EstablishedList);\r
357 InitializeListHead (&Private->Ikev2SessionList);\r
358 InitializeListHead (&Private->Ikev2EstablishedList);\r
9166f840 359 \r
360 RandomSeed (NULL, 0);\r
a3bcde70
HT
361 //\r
362 // Initialize the ipsec config data and restore it from variable.\r
363 //\r
364 Status = IpSecConfigInitialize (Private);\r
365 if (EFI_ERROR (Status)) {\r
366 DEBUG ((DEBUG_ERROR, "_ModuleEntryPoint: Failed to initialize IpSecConfig\n"));\r
367 goto ON_CLOSE_EVENT;\r
368 }\r
369 //\r
370 // Install ipsec protocol which is used by ip driver to process ipsec header.\r
371 //\r
372 Status = gBS->InstallMultipleProtocolInterfaces (\r
373 &Private->Handle,\r
0a7294f7 374 &gEfiIpSec2ProtocolGuid,\r
a3bcde70
HT
375 &Private->IpSec,\r
376 NULL\r
377 );\r
378 if (EFI_ERROR (Status)) {\r
379 goto ON_UNINSTALL_CONFIG;\r
380 }\r
381\r
382 Status = EfiLibInstallDriverBindingComponentName2 (\r
383 ImageHandle,\r
384 SystemTable,\r
385 &gIpSecDriverBinding,\r
386 ImageHandle,\r
387 &gIpSecComponentName,\r
388 &gIpSecComponentName2\r
389 );\r
390 if (EFI_ERROR (Status)) {\r
9166f840 391 goto ON_UNINSTALL_IPSEC;\r
a3bcde70 392 }\r
9166f840 393 \r
a3bcde70
HT
394 return Status;\r
395\r
9166f840 396ON_UNINSTALL_IPSEC:\r
397 gBS->UninstallProtocolInterface (\r
398 Private->Handle,\r
0a7294f7 399 &gEfiIpSec2ProtocolGuid,\r
9166f840 400 &Private->IpSec\r
401 );\r
a3bcde70
HT
402ON_UNINSTALL_CONFIG:\r
403 gBS->UninstallProtocolInterface (\r
404 Private->Handle,\r
405 &gEfiIpSecConfigProtocolGuid,\r
406 &Private->IpSecConfig\r
407 );\r
408ON_CLOSE_EVENT:\r
409 gBS->CloseEvent (mIpSecInstance.DisabledEvent);\r
410 mIpSecInstance.DisabledEvent = NULL;\r
411ON_FREE_PRIVATE:\r
412 FreePool (Private);\r
413ON_EXIT:\r
414 return Status;\r
415}\r
416\r