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 18EFI_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**/ 29VOID 30TlsCleanInstance ( 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**/ 53EFI_STATUS 54TlsCreateInstance ( 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**/ 89VOID 90TlsCleanService ( 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**/ 113EFI_STATUS 114TlsCreateService ( 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**/ 156EFI_STATUS 157EFIAPI 158TlsUnload ( 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**/ 238EFI_STATUS 239EFIAPI 240TlsDriverEntryPoint ( 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 289ON_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**/ 314EFI_STATUS 315EFIAPI 316TlsServiceBindingCreateChild ( 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 385ON_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**/ 408EFI_STATUS 409EFIAPI 410TlsServiceBindingDestroyChild ( 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