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