NetworkPkg: Convert files to CRLF line ending
[mirror_edk2.git] / NetworkPkg / TlsDxe / TlsDriver.c
1 /** @file\r
2   The Driver Binding and Service Binding Protocol for TlsDxe driver.\r
3 \r
4   Copyright (c) 2016, 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
16 #include "TlsImpl.h"\r
17 \r
18 EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = {\r
19   TlsServiceBindingCreateChild,\r
20   TlsServiceBindingDestroyChild\r
21 };\r
22 \r
23 /**\r
24   Release all the resources used by the TLS instance.\r
25 \r
26   @param[in]  Instance        The TLS instance data.\r
27 \r
28 **/\r
29 VOID\r
30 TlsCleanInstance (\r
31   IN TLS_INSTANCE           *Instance\r
32   )\r
33 {\r
34   if (Instance != NULL) {\r
35     if (Instance->TlsConn != NULL) {\r
36       TlsFree (Instance->TlsConn);\r
37     }\r
38 \r
39     FreePool (Instance);\r
40   }\r
41 }\r
42 \r
43 /**\r
44   Create the TLS instance and initialize it.\r
45 \r
46   @param[in]  Service              The pointer to the TLS service.\r
47   @param[out] Instance             The pointer to the TLS instance.\r
48 \r
49   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.\r
50   @retval EFI_SUCCESS            The TLS instance is created.\r
51 \r
52 **/\r
53 EFI_STATUS\r
54 TlsCreateInstance (\r
55   IN  TLS_SERVICE         *Service,\r
56   OUT TLS_INSTANCE        **Instance\r
57   )\r
58 {\r
59   TLS_INSTANCE            *TlsInstance;\r
60 \r
61   *Instance = NULL;\r
62 \r
63   TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE));\r
64   if (TlsInstance == NULL) {\r
65     return EFI_OUT_OF_RESOURCES;\r
66   }\r
67 \r
68   TlsInstance->Signature = TLS_INSTANCE_SIGNATURE;\r
69   InitializeListHead (&TlsInstance->Link);\r
70   TlsInstance->InDestroy = FALSE;\r
71   TlsInstance->Service   = Service;\r
72 \r
73   CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls));\r
74   CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig));\r
75 \r
76   TlsInstance->TlsSessionState = EfiTlsSessionNotStarted;\r
77 \r
78   *Instance = TlsInstance;\r
79 \r
80   return EFI_SUCCESS;\r
81 }\r
82 \r
83 /**\r
84   Release all the resources used by the TLS service binding instance.\r
85 \r
86   @param[in]  Service        The TLS service data.\r
87 \r
88 **/\r
89 VOID\r
90 TlsCleanService (\r
91   IN TLS_SERVICE     *Service\r
92   )\r
93 {\r
94   if (Service != NULL) {\r
95     if (Service->TlsCtx != NULL) {\r
96       TlsCtxFree (Service->TlsCtx);\r
97     }\r
98 \r
99     FreePool (Service);\r
100   }\r
101 }\r
102 \r
103 /**\r
104   Create then initialize a TLS service.\r
105 \r
106   @param[in]  Image                  ImageHandle of the TLS driver\r
107   @param[out] Service                The service for TLS driver\r
108 \r
109   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the service.\r
110   @retval EFI_SUCCESS            The service is created for the driver.\r
111 \r
112 **/\r
113 EFI_STATUS\r
114 TlsCreateService (\r
115   IN  EFI_HANDLE            Image,\r
116   OUT TLS_SERVICE           **Service\r
117   )\r
118 {\r
119   TLS_SERVICE            *TlsService;\r
120 \r
121   ASSERT (Service != NULL);\r
122 \r
123   *Service = NULL;\r
124 \r
125   //\r
126   // Allocate a TLS Service Data\r
127   //\r
128   TlsService = AllocateZeroPool (sizeof (TLS_SERVICE));\r
129   if (TlsService == NULL) {\r
130     return EFI_OUT_OF_RESOURCES;\r
131   }\r
132 \r
133   //\r
134   // Initialize TLS Service Data\r
135   //\r
136   TlsService->Signature        = TLS_SERVICE_SIGNATURE;\r
137   CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding));\r
138   TlsService->TlsChildrenNum   = 0;\r
139   InitializeListHead (&TlsService->TlsChildrenList);\r
140   TlsService->ImageHandle      = Image;\r
141 \r
142   *Service = TlsService;\r
143 \r
144   return EFI_SUCCESS;\r
145 }\r
146 \r
147 /**\r
148   Unloads an image.\r
149 \r
150   @param[in]  ImageHandle           Handle that identifies the image to be unloaded.\r
151 \r
152   @retval EFI_SUCCESS           The image has been unloaded.\r
153   @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.\r
154 \r
155 **/\r
156 EFI_STATUS\r
157 EFIAPI\r
158 TlsUnload (\r
159   IN EFI_HANDLE  ImageHandle\r
160   )\r
161 {\r
162   EFI_STATUS                      Status;\r
163   UINTN                           HandleNum;\r
164   EFI_HANDLE                      *HandleBuffer;\r
165   UINT32                          Index;\r
166   EFI_SERVICE_BINDING_PROTOCOL    *ServiceBinding;\r
167   TLS_SERVICE                     *TlsService;\r
168 \r
169   HandleBuffer   = NULL;\r
170   ServiceBinding = NULL;\r
171   TlsService     = NULL;\r
172 \r
173   //\r
174   // Locate all the handles with Tls service binding protocol.\r
175   //\r
176   Status = gBS->LocateHandleBuffer (\r
177                   ByProtocol,\r
178                   &gEfiTlsServiceBindingProtocolGuid,\r
179                   NULL,\r
180                   &HandleNum,\r
181                   &HandleBuffer\r
182                   );\r
183   if (EFI_ERROR (Status)) {\r
184     return Status;\r
185   }\r
186 \r
187   for (Index = 0; Index < HandleNum; Index++) {\r
188     //\r
189     // Firstly, find ServiceBinding interface\r
190     //\r
191     Status = gBS->OpenProtocol (\r
192                     HandleBuffer[Index],\r
193                     &gEfiTlsServiceBindingProtocolGuid,\r
194                     (VOID **) &ServiceBinding,\r
195                     ImageHandle,\r
196                     NULL,\r
197                     EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
198                     );\r
199     if (EFI_ERROR (Status)) {\r
200       return Status;\r
201     }\r
202 \r
203     TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding);\r
204 \r
205     //\r
206     // Then, uninstall ServiceBinding interface\r
207     //\r
208     Status = gBS->UninstallMultipleProtocolInterfaces (\r
209                     HandleBuffer[Index],\r
210                     &gEfiTlsServiceBindingProtocolGuid, ServiceBinding,\r
211                     NULL\r
212                     );\r
213     if (EFI_ERROR (Status)) {\r
214       return Status;\r
215     }\r
216 \r
217     TlsCleanService (TlsService);\r
218   }\r
219 \r
220   if (HandleBuffer != NULL) {\r
221     FreePool (HandleBuffer);\r
222   }\r
223 \r
224   return EFI_SUCCESS;\r
225 }\r
226 \r
227 /**\r
228   This is the declaration of an EFI image entry point. This entry point is\r
229   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
230   both device drivers and bus drivers.\r
231 \r
232   @param  ImageHandle           The firmware allocated handle for the UEFI image.\r
233   @param  SystemTable           A pointer to the EFI System Table.\r
234 \r
235   @retval EFI_SUCCESS           The operation completed successfully.\r
236   @retval Others                An unexpected error occurred.\r
237 **/\r
238 EFI_STATUS\r
239 EFIAPI\r
240 TlsDriverEntryPoint (\r
241   IN EFI_HANDLE        ImageHandle,\r
242   IN EFI_SYSTEM_TABLE  *SystemTable\r
243   )\r
244 {\r
245   EFI_STATUS             Status;\r
246 \r
247   TLS_SERVICE            *TlsService;\r
248 \r
249   //\r
250   // Create TLS Service\r
251   //\r
252   Status = TlsCreateService (ImageHandle, &TlsService);\r
253   if (EFI_ERROR (Status)) {\r
254     return Status;\r
255   }\r
256 \r
257   ASSERT (TlsService != NULL);\r
258 \r
259   //\r
260   // Initializes the OpenSSL library.\r
261   //\r
262   TlsInitialize ();\r
263 \r
264   //\r
265   // Create a new SSL_CTX object as framework to establish TLS/SSL enabled\r
266   // connections. TLS 1.0 is used as the default version.\r
267   //\r
268   TlsService->TlsCtx = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR);\r
269   if (TlsService->TlsCtx == NULL) {\r
270     FreePool (TlsService);\r
271     return EFI_ABORTED;\r
272   }\r
273 \r
274   //\r
275   // Install the TlsServiceBinding Protocol onto Handle\r
276   //\r
277   Status = gBS->InstallMultipleProtocolInterfaces (\r
278                   &TlsService->Handle,\r
279                   &gEfiTlsServiceBindingProtocolGuid,\r
280                   &TlsService->ServiceBinding,\r
281                   NULL\r
282                   );\r
283   if (EFI_ERROR (Status)) {\r
284     goto ON_CLEAN_SERVICE;\r
285   }\r
286 \r
287   return Status;\r
288 \r
289 ON_CLEAN_SERVICE:\r
290   TlsCleanService (TlsService);\r
291 \r
292   return Status;\r
293 }\r
294 \r
295 /**\r
296   Creates a child handle and installs a protocol.\r
297 \r
298   The CreateChild() function installs a protocol on ChildHandle.\r
299   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
300   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
301 \r
302   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
303   @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
304                          then a new handle is created. If it is a pointer to an existing UEFI handle,\r
305                          then the protocol is added to the existing UEFI handle.\r
306 \r
307   @retval EFI_SUCCES            The protocol was added to ChildHandle.\r
308   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
309   @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create\r
310                                 the child.\r
311   @retval other                 The child handle was not created.\r
312 \r
313 **/\r
314 EFI_STATUS\r
315 EFIAPI\r
316 TlsServiceBindingCreateChild (\r
317   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
318   IN EFI_HANDLE                    *ChildHandle\r
319   )\r
320 {\r
321   TLS_SERVICE         *TlsService;\r
322   TLS_INSTANCE        *TlsInstance;\r
323   EFI_STATUS           Status;\r
324   EFI_TPL              OldTpl;\r
325 \r
326   if ((This == NULL) || (ChildHandle == NULL)) {\r
327     return EFI_INVALID_PARAMETER;\r
328   }\r
329 \r
330   TlsService = TLS_SERVICE_FROM_THIS (This);\r
331 \r
332   Status = TlsCreateInstance (TlsService, &TlsInstance);\r
333   if (EFI_ERROR (Status)) {\r
334     return Status;\r
335   }\r
336 \r
337   ASSERT (TlsInstance != NULL);\r
338 \r
339   //\r
340   // Create a new TLS connection object.\r
341   //\r
342   TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx);\r
343   if (TlsInstance->TlsConn == NULL) {\r
344     Status = EFI_ABORTED;\r
345     goto ON_ERROR;\r
346   }\r
347 \r
348   //\r
349   // Set default ConnectionEnd to EfiTlsClient\r
350   //\r
351   Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient);\r
352   if (EFI_ERROR (Status)) {\r
353     goto ON_ERROR;\r
354   }\r
355 \r
356   //\r
357   // Install TLS protocol and configuration protocol onto ChildHandle\r
358   //\r
359   Status = gBS->InstallMultipleProtocolInterfaces (\r
360                   ChildHandle,\r
361                   &gEfiTlsProtocolGuid,\r
362                   &TlsInstance->Tls,\r
363                   &gEfiTlsConfigurationProtocolGuid,\r
364                   &TlsInstance->TlsConfig,\r
365                   NULL\r
366                   );\r
367   if (EFI_ERROR (Status)) {\r
368     goto ON_ERROR;\r
369   }\r
370 \r
371   TlsInstance->ChildHandle = *ChildHandle;\r
372 \r
373   //\r
374   // Add it to the TLS service's child list.\r
375   //\r
376   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
377 \r
378   InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link);\r
379   TlsService->TlsChildrenNum++;\r
380 \r
381   gBS->RestoreTPL (OldTpl);\r
382 \r
383   return EFI_SUCCESS;\r
384 \r
385 ON_ERROR:\r
386   TlsCleanInstance (TlsInstance);\r
387   return Status;\r
388 }\r
389 \r
390 /**\r
391   Destroys a child handle with a protocol installed on it.\r
392 \r
393   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
394   that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
395   last protocol on ChildHandle, then ChildHandle is destroyed.\r
396 \r
397   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
398   @param  ChildHandle Handle of the child to destroy.\r
399 \r
400   @retval EFI_SUCCES            The protocol was removed from ChildHandle.\r
401   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.\r
402   @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
403   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
404                                 because its services are being used.\r
405   @retval other                 The child handle was not destroyed.\r
406 \r
407 **/\r
408 EFI_STATUS\r
409 EFIAPI\r
410 TlsServiceBindingDestroyChild (\r
411   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
412   IN EFI_HANDLE                    ChildHandle\r
413   )\r
414 {\r
415   TLS_SERVICE                    *TlsService;\r
416   TLS_INSTANCE                   *TlsInstance;\r
417 \r
418   EFI_TLS_PROTOCOL               *Tls;\r
419   EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig;\r
420   EFI_STATUS                     Status;\r
421   EFI_TPL                        OldTpl;\r
422 \r
423   if ((This == NULL) || (ChildHandle == NULL)) {\r
424     return EFI_INVALID_PARAMETER;\r
425   }\r
426 \r
427   TlsService = TLS_SERVICE_FROM_THIS (This);\r
428 \r
429   //\r
430   // Find TLS protocol interface installed in ChildHandle\r
431   //\r
432   Status = gBS->OpenProtocol (\r
433                   ChildHandle,\r
434                   &gEfiTlsProtocolGuid,\r
435                   (VOID **) &Tls,\r
436                   TlsService->ImageHandle,\r
437                   NULL,\r
438                   EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
439                   );\r
440   if (EFI_ERROR (Status)) {\r
441     return Status;\r
442   }\r
443 \r
444   //\r
445   // Find TLS configuration protocol interface installed in ChildHandle\r
446   //\r
447   Status = gBS->OpenProtocol (\r
448                   ChildHandle,\r
449                   &gEfiTlsConfigurationProtocolGuid,\r
450                   (VOID **) &TlsConfig,\r
451                   TlsService->ImageHandle,\r
452                   NULL,\r
453                   EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
454                   );\r
455   if (EFI_ERROR (Status)) {\r
456     return Status;\r
457   }\r
458 \r
459   TlsInstance  = TLS_INSTANCE_FROM_PROTOCOL (Tls);\r
460 \r
461   if (TlsInstance->Service != TlsService) {\r
462     return EFI_INVALID_PARAMETER;\r
463   }\r
464 \r
465   if (TlsInstance->InDestroy) {\r
466     return EFI_SUCCESS;\r
467   }\r
468 \r
469   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
470 \r
471   TlsInstance->InDestroy = TRUE;\r
472 \r
473   //\r
474   // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle.\r
475   //\r
476   Status = gBS->UninstallMultipleProtocolInterfaces (\r
477                   ChildHandle,\r
478                   &gEfiTlsProtocolGuid,\r
479                   Tls,\r
480                   &gEfiTlsConfigurationProtocolGuid,\r
481                   TlsConfig,\r
482                   NULL\r
483                   );\r
484   if (EFI_ERROR (Status)) {\r
485     return Status;\r
486   }\r
487 \r
488   RemoveEntryList (&TlsInstance->Link);\r
489   TlsService->TlsChildrenNum--;\r
490 \r
491   gBS->RestoreTPL (OldTpl);\r
492 \r
493   TlsCleanInstance (TlsInstance);\r
494 \r
495   return EFI_SUCCESS;\r
496 }\r
497 \r