]>
Commit | Line | Data |
---|---|---|
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | } |