summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiaxin Wu <jiaxin.wu@intel.com>2016-12-14 10:44:07 +0800
committerJiaxin Wu <jiaxin.wu@intel.com>2016-12-22 20:33:28 +0800
commit7e1f2209b03fdc51ba506686f74cfcb491b23ec3 (patch)
treec945fd6cbed75b2f13286ac608009f7165a6900c
parent9396cdfeaa7a053093c9d0a1f13ef6d672dfaa9f (diff)
downloadedk2-7e1f2209b03fdc51ba506686f74cfcb491b23ec3.tar.gz
edk2-7e1f2209b03fdc51ba506686f74cfcb491b23ec3.tar.bz2
edk2-7e1f2209b03fdc51ba506686f74cfcb491b23ec3.zip
NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL
v3: * Typo fix and code refine. * Rename the internal macros and function: TLS_INSTANCE_FROM_PROTOCOL_THIS -> TLS_INSTANCE_FROM_PROTOCOL TLS_INSTANCE_FROM_CONFIGURATION_THIS -> TLS_INSTANCE_FROM_CONFIGURATION TlsEcryptPacket -> TlsEncryptPacket v2: * Refine the TlsEcryptPacket/TlsDecryptPacket function according the community feedback. This patch is the implementation of EFI TLS Service Binding Protocol, EFI TLS Protocol and EFI TLS Configuration Protocol Interfaces. Cc: Ye Ting <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Cc: Zhang Lubo <lubo.zhang@intel.com> Cc: Long Qin <qin.long@intel.com> Cc: Thomas Palmer <thomas.palmer@hpe.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com>
-rw-r--r--NetworkPkg/TlsDxe/TlsConfigProtocol.c152
-rw-r--r--NetworkPkg/TlsDxe/TlsDriver.c496
-rw-r--r--NetworkPkg/TlsDxe/TlsDriver.h237
-rw-r--r--NetworkPkg/TlsDxe/TlsDxe.inf65
-rw-r--r--NetworkPkg/TlsDxe/TlsDxe.uni25
-rw-r--r--NetworkPkg/TlsDxe/TlsDxeExtra.uni18
-rw-r--r--NetworkPkg/TlsDxe/TlsImpl.c326
-rw-r--r--NetworkPkg/TlsDxe/TlsImpl.h315
-rw-r--r--NetworkPkg/TlsDxe/TlsProtocol.c632
9 files changed, 2266 insertions, 0 deletions
diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
new file mode 100644
index 0000000000..5292433da3
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
@@ -0,0 +1,152 @@
+/** @file
+ Implementation of EFI TLS Configuration Protocol Interfaces.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol = {
+ TlsConfigurationSetData,
+ TlsConfigurationGetData
+};
+
+/**
+ Set TLS configuration data.
+
+ The SetData() function sets TLS configuration to non-volatile storage or volatile
+ storage.
+
+ @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+ @param[in] DataType Configuration data type.
+ @param[in] Data Pointer to configuration data.
+ @param[in] DataSize Total size of configuration data.
+
+ @retval EFI_SUCCESS The TLS configuration data is set successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Data is NULL.
+ DataSize is 0.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+ IN EFI_TLS_CONFIGURATION_PROTOCOL *This,
+ IN EFI_TLS_CONFIG_DATA_TYPE DataType,
+ IN VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ if (This == NULL || Data == NULL || DataSize == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_CONFIGURATION (This);
+
+ switch (DataType) {
+ case EfiTlsConfigDataTypeCACertificate:
+ Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeHostPublicCert:
+ Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeHostPrivateKey:
+ Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeCertRevocationList:
+ Status = TlsSetCertRevocationList (Data, DataSize);
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Get TLS configuration data.
+
+ The GetData() function gets TLS configuration.
+
+ @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+ @param[in] DataType Configuration data type.
+ @param[in, out] Data Pointer to configuration data.
+ @param[in, out] DataSize Total size of configuration data. On input, it means
+ the size of Data buffer. On output, it means the size
+ of copied Data buffer if EFI_SUCCESS, and means the
+ size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+ @retval EFI_SUCCESS The TLS configuration data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSize is not zero.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_NOT_FOUND The TLS configuration data is not found.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+ IN EFI_TLS_CONFIGURATION_PROTOCOL *This,
+ IN EFI_TLS_CONFIG_DATA_TYPE DataType,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataSize
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_CONFIGURATION (This);
+
+ switch (DataType) {
+ case EfiTlsConfigDataTypeCACertificate:
+ Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeHostPublicCert:
+ Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeHostPrivateKey:
+ Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+ break;
+ case EfiTlsConfigDataTypeCertRevocationList:
+ Status = TlsGetCertRevocationList (Data, DataSize);
+ break;
+ default:
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c
new file mode 100644
index 0000000000..38bf5993ce
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.c
@@ -0,0 +1,496 @@
+/** @file
+ The Driver Binding and Service Binding Protocol for TlsDxe driver.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = {
+ TlsServiceBindingCreateChild,
+ TlsServiceBindingDestroyChild
+};
+
+/**
+ Release all the resources used by the TLS instance.
+
+ @param[in] Instance The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+ IN TLS_INSTANCE *Instance
+ )
+{
+ if (Instance != NULL) {
+ if (Instance->TlsConn != NULL) {
+ TlsFree (Instance->TlsConn);
+ }
+
+ FreePool (Instance);
+ }
+}
+
+/**
+ Create the TLS instance and initialize it.
+
+ @param[in] Service The pointer to the TLS service.
+ @param[out] Instance The pointer to the TLS instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+ IN TLS_SERVICE *Service,
+ OUT TLS_INSTANCE **Instance
+ )
+{
+ TLS_INSTANCE *TlsInstance;
+
+ *Instance = NULL;
+
+ TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE));
+ if (TlsInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TlsInstance->Signature = TLS_INSTANCE_SIGNATURE;
+ InitializeListHead (&TlsInstance->Link);
+ TlsInstance->InDestroy = FALSE;
+ TlsInstance->Service = Service;
+
+ CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls));
+ CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig));
+
+ TlsInstance->TlsSessionState = EfiTlsSessionNotStarted;
+
+ *Instance = TlsInstance;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release all the resources used by the TLS service binding instance.
+
+ @param[in] Service The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+ IN TLS_SERVICE *Service
+ )
+{
+ if (Service != NULL) {
+ if (Service->TlsCtx != NULL) {
+ TlsCtxFree (Service->TlsCtx);
+ }
+
+ FreePool (Service);
+ }
+}
+
+/**
+ Create then initialize a TLS service.
+
+ @param[in] Image ImageHandle of the TLS driver
+ @param[out] Service The service for TLS driver
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the service.
+ @retval EFI_SUCCESS The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+ IN EFI_HANDLE Image,
+ OUT TLS_SERVICE **Service
+ )
+{
+ TLS_SERVICE *TlsService;
+
+ ASSERT (Service != NULL);
+
+ *Service = NULL;
+
+ //
+ // Allocate a TLS Service Data
+ //
+ TlsService = AllocateZeroPool (sizeof (TLS_SERVICE));
+ if (TlsService == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize TLS Service Data
+ //
+ TlsService->Signature = TLS_SERVICE_SIGNATURE;
+ CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding));
+ TlsService->TlsChildrenNum = 0;
+ InitializeListHead (&TlsService->TlsChildrenList);
+ TlsService->ImageHandle = Image;
+
+ *Service = TlsService;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ UINT32 Index;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ TLS_SERVICE *TlsService;
+
+ HandleBuffer = NULL;
+ ServiceBinding = NULL;
+ TlsService = NULL;
+
+ //
+ // Locate all the handles with Tls service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiTlsServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleNum; Index++) {
+ //
+ // Firstly, find ServiceBinding interface
+ //
+ Status = gBS->OpenProtocol (
+ HandleBuffer[Index],
+ &gEfiTlsServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding);
+
+ //
+ // Then, uninstall ServiceBinding interface
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ HandleBuffer[Index],
+ &gEfiTlsServiceBindingProtocolGuid, ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TlsCleanService (TlsService);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ TLS_SERVICE *TlsService;
+
+ //
+ // Create TLS Service
+ //
+ Status = TlsCreateService (ImageHandle, &TlsService);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (TlsService != NULL);
+
+ //
+ // Initializes the OpenSSL library.
+ //
+ TlsInitialize ();
+
+ //
+ // Create a new SSL_CTX object as framework to establish TLS/SSL enabled
+ // connections. TLS 1.0 is used as the default version.
+ //
+ TlsService->TlsCtx = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR);
+ if (TlsService->TlsCtx == NULL) {
+ FreePool (TlsService);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Install the TlsServiceBinding Protocol onto Handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &TlsService->Handle,
+ &gEfiTlsServiceBindingProtocolGuid,
+ &TlsService->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_CLEAN_SERVICE;
+ }
+
+ return Status;
+
+ON_CLEAN_SERVICE:
+ TlsCleanService (TlsService);
+
+ return Status;
+}
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child.
+ @retval other The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ )
+{
+ TLS_SERVICE *TlsService;
+ TLS_INSTANCE *TlsInstance;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TlsService = TLS_SERVICE_FROM_THIS (This);
+
+ Status = TlsCreateInstance (TlsService, &TlsInstance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (TlsInstance != NULL);
+
+ //
+ // Create a new TLS connection object.
+ //
+ TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx);
+ if (TlsInstance->TlsConn == NULL) {
+ Status = EFI_ABORTED;
+ goto ON_ERROR;
+ }
+
+ //
+ // Set default ConnectionEnd to EfiTlsClient
+ //
+ Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Install TLS protocol and configuration protocol onto ChildHandle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiTlsProtocolGuid,
+ &TlsInstance->Tls,
+ &gEfiTlsConfigurationProtocolGuid,
+ &TlsInstance->TlsConfig,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ TlsInstance->ChildHandle = *ChildHandle;
+
+ //
+ // Add it to the TLS service's child list.
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link);
+ TlsService->TlsChildrenNum++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ TlsCleanInstance (TlsInstance);
+ return Status;
+}
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param ChildHandle Handle of the child to destroy.
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ TLS_SERVICE *TlsService;
+ TLS_INSTANCE *TlsInstance;
+
+ EFI_TLS_PROTOCOL *Tls;
+ EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TlsService = TLS_SERVICE_FROM_THIS (This);
+
+ //
+ // Find TLS protocol interface installed in ChildHandle
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiTlsProtocolGuid,
+ (VOID **) &Tls,
+ TlsService->ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Find TLS configuration protocol interface installed in ChildHandle
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiTlsConfigurationProtocolGuid,
+ (VOID **) &TlsConfig,
+ TlsService->ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TlsInstance = TLS_INSTANCE_FROM_PROTOCOL (Tls);
+
+ if (TlsInstance->Service != TlsService) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (TlsInstance->InDestroy) {
+ return EFI_SUCCESS;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ TlsInstance->InDestroy = TRUE;
+
+ //
+ // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiTlsProtocolGuid,
+ Tls,
+ &gEfiTlsConfigurationProtocolGuid,
+ TlsConfig,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ RemoveEntryList (&TlsInstance->Link);
+ TlsService->TlsChildrenNum--;
+
+ gBS->RestoreTPL (OldTpl);
+
+ TlsCleanInstance (TlsInstance);
+
+ return EFI_SUCCESS;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.h b/NetworkPkg/TlsDxe/TlsDriver.h
new file mode 100644
index 0000000000..a9e55ba752
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.h
@@ -0,0 +1,237 @@
+/** @file
+ Header file of the Driver Binding and Service Binding Protocol for TlsDxe driver.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_TLS_DRIVER_H__
+#define __EFI_TLS_DRIVER_H__
+
+#include <Uefi.h>
+
+//
+// Driver Protocols
+//
+#include <Protocol/ServiceBinding.h>
+
+//
+// Driver Version
+//
+#define TLS_VERSION 0x00000000
+
+#define TLS_SERVICE_SIGNATURE SIGNATURE_32 ('T', 'L', 'S', 'S')
+
+#define TLS_INSTANCE_SIGNATURE SIGNATURE_32 ('T', 'L', 'S', 'I')
+
+///
+/// TLS Service Data
+///
+typedef struct _TLS_SERVICE TLS_SERVICE;
+
+///
+/// TLS Instance Data
+///
+typedef struct _TLS_INSTANCE TLS_INSTANCE;
+
+
+struct _TLS_SERVICE {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ UINT16 TlsChildrenNum;
+ LIST_ENTRY TlsChildrenList;
+
+ //
+ // Handle to install TlsServiceBinding protocol.
+ //
+ EFI_HANDLE Handle;
+ EFI_HANDLE ImageHandle;
+
+ //
+ // Main SSL Context object which is created by a server or client once per program
+ // life-time and which holds mainly default values for the SSL object which are later
+ // created for the connections.
+ //
+ VOID *TlsCtx;
+};
+
+struct _TLS_INSTANCE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ BOOLEAN InDestroy;
+
+ TLS_SERVICE *Service;
+ EFI_HANDLE ChildHandle;
+
+ EFI_TLS_PROTOCOL Tls;
+ EFI_TLS_CONFIGURATION_PROTOCOL TlsConfig;
+
+ EFI_TLS_SESSION_STATE TlsSessionState;
+
+ //
+ // Main SSL Connection which is created by a server or a client
+ // per established connection.
+ //
+ VOID *TlsConn;
+};
+
+
+#define TLS_SERVICE_FROM_THIS(a) \
+ CR (a, TLS_SERVICE, ServiceBinding, TLS_SERVICE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_PROTOCOL(a) \
+ CR (a, TLS_INSTANCE, Tls, TLS_INSTANCE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_CONFIGURATION(a) \
+ CR (a, TLS_INSTANCE, TlsConfig, TLS_INSTANCE_SIGNATURE)
+
+
+/**
+ Release all the resources used by the TLS instance.
+
+ @param[in] Instance The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+ IN TLS_INSTANCE *Instance
+ );
+
+/**
+ Create the TLS instance and initialize it.
+
+ @param[in] Service The pointer to the TLS service.
+ @param[out] Instance The pointer to the TLS instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+ IN TLS_SERVICE *Service,
+ OUT TLS_INSTANCE **Instance
+ );
+
+/**
+ Release all the resources used by the TLS service binding instance.
+
+ @param[in] Service The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+ IN TLS_SERVICE *Service
+ );
+
+/**
+ Create then initialize a TLS service.
+
+ @param[in] Image ImageHandle of the TLS driver
+ @param[out] Service The service for TLS driver
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the service.
+ @retval EFI_SUCCESS The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+ IN EFI_HANDLE Image,
+ OUT TLS_SERVICE **Service
+ );
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child.
+ @retval other The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param ChildHandle Handle of the child to destroy.
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsDxe.inf b/NetworkPkg/TlsDxe/TlsDxe.inf
new file mode 100644
index 0000000000..dba3257203
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+# EFI TLS Configuration Protocol.
+#
+# This module produces EFI TLS (Transport Layer Security) Protocol and EFI TLS
+# Service Binding Protocol, to provide TLS services.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TlsDxe
+ FILE_GUID = 3aceb0c0-3c72-11e4-9a56-74d435052646
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = TlsDriverEntryPoint
+ UNLOAD_IMAGE = TlsUnload
+ MODULE_UNI_FILE = TlsDxe.uni
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[Sources]
+ TlsDriver.h
+ TlsDriver.c
+ TlsProtocol.c
+ TlsConfigProtocol.c
+ TlsImpl.h
+ TlsImpl.c
+
+[LibraryClasses]
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ BaseLib
+ UefiLib
+ DebugLib
+ NetLib
+ BaseCryptLib
+ TlsLib
+
+[Protocols]
+ gEfiTlsServiceBindingProtocolGuid ## PRODUCES
+ gEfiTlsProtocolGuid ## PRODUCES
+ gEfiTlsConfigurationProtocolGuid ## PRODUCES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ TlsDxeExtra.uni
diff --git a/NetworkPkg/TlsDxe/TlsDxe.uni b/NetworkPkg/TlsDxe/TlsDxe.uni
new file mode 100644
index 0000000000..98c41ca7c5
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.uni
@@ -0,0 +1,25 @@
+// /** @file
+// This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+// EFI TLS Configuration Protocol.
+//
+// This module produces EFI TLS (Transport Layer Security) Protocol, EFI TLS
+// Service Binding Protocol, and EFI TLS Configuration Protocol to provide TLS
+// services.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "UEFI TLS service"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol to provide EFI TLS services."
+
diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
new file mode 100644
index 0000000000..a38582a887
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
@@ -0,0 +1,18 @@
+// /** @file
+// TlsDxe Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php.
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"EFI TLS DXE Driver"
diff --git a/NetworkPkg/TlsDxe/TlsImpl.c b/NetworkPkg/TlsDxe/TlsImpl.c
new file mode 100644
index 0000000000..bb71bd8dfd
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.c
@@ -0,0 +1,326 @@
+/** @file
+ The Miscellaneous Routines for TlsDxe driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TlsImpl.h"
+
+/**
+ Encrypt the message listed in fragment.
+
+ @param[in] TlsInstance The pointer to the TLS instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment.
+ On input these fragments contain the TLS header and
+ plain text TLS payload;
+ On output these fragments contain the TLS header and
+ cipher text TLS payload.
+ @param[in] FragmentCount Number of fragment.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ABORTED TLS session state is incorrect.
+ @retval Others Other errors as indicated.
+**/
+EFI_STATUS
+TlsEncryptPacket (
+ IN TLS_INSTANCE *TlsInstance,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 BytesCopied;
+ UINT32 BufferInSize;
+ UINT8 *BufferIn;
+ UINT8 *BufferInPtr;
+ TLS_RECORD_HEADER *RecordHeaderIn;
+ UINT16 ThisPlainMessageSize;
+ TLS_RECORD_HEADER *TempRecordHeader;
+ UINT16 ThisMessageSize;
+ UINT32 BufferOutSize;
+ UINT8 *BufferOut;
+ INTN Ret;
+
+ Status = EFI_SUCCESS;
+ BytesCopied = 0;
+ BufferInSize = 0;
+ BufferIn = NULL;
+ BufferInPtr = NULL;
+ RecordHeaderIn = NULL;
+ TempRecordHeader = NULL;
+ BufferOutSize = 0;
+ BufferOut = NULL;
+ Ret = 0;
+
+ //
+ // Calculate the size according to the fragment table.
+ //
+ for (Index = 0; Index < *FragmentCount; Index++) {
+ BufferInSize += (*FragmentTable)[Index].FragmentLength;
+ }
+
+ //
+ // Allocate buffer for processing data.
+ //
+ BufferIn = AllocateZeroPool (BufferInSize);
+ if (BufferIn == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ //
+ // Copy all TLS plain record header and payload into BufferIn.
+ //
+ for (Index = 0; Index < *FragmentCount; Index++) {
+ CopyMem (
+ (BufferIn + BytesCopied),
+ (*FragmentTable)[Index].FragmentBuffer,
+ (*FragmentTable)[Index].FragmentLength
+ );
+ BytesCopied += (*FragmentTable)[Index].FragmentLength;
+ }
+
+ BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+ if (BufferOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ //
+ // Parsing buffer.
+ //
+ BufferInPtr = BufferIn;
+ TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+ while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+ RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+
+ if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ERROR;
+ }
+
+ ThisPlainMessageSize = RecordHeaderIn->Length;
+
+ TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize);
+
+ Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize);
+
+ if (Ret > 0) {
+ ThisMessageSize = (UINT16) Ret;
+ } else {
+ //
+ // No data was successfully encrypted, continue to encrypt other messages.
+ //
+ DEBUG ((EFI_D_WARN, "TlsEncryptPacket: No data read from TLS object.\n"));
+
+ ThisMessageSize = 0;
+ }
+
+ BufferOutSize += ThisMessageSize;
+
+ BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize;
+ TempRecordHeader += ThisMessageSize;
+ }
+
+ FreePool (BufferIn);
+ BufferIn = NULL;
+
+ //
+ // The caller will be responsible to handle the original fragment table.
+ //
+ *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+ if (*FragmentTable == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ (*FragmentTable)[0].FragmentBuffer = BufferOut;
+ (*FragmentTable)[0].FragmentLength = BufferOutSize;
+ *FragmentCount = 1;
+
+ return Status;
+
+ERROR:
+
+ if (BufferIn != NULL) {
+ FreePool (BufferIn);
+ BufferIn = NULL;
+ }
+
+ if (BufferOut != NULL) {
+ FreePool (BufferOut);
+ BufferOut = NULL;
+ }
+
+ return Status;
+}
+
+/**
+ Decrypt the message listed in fragment.
+
+ @param[in] TlsInstance The pointer to the TLS instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment.
+ On input these fragments contain the TLS header and
+ cipher text TLS payload;
+ On output these fragments contain the TLS header and
+ plain text TLS payload.
+ @param[in] FragmentCount Number of fragment.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ABORTED TLS session state is incorrect.
+ @retval Others Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+ IN TLS_INSTANCE *TlsInstance,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 BytesCopied;
+ UINT8 *BufferIn;
+ UINT32 BufferInSize;
+ UINT8 *BufferInPtr;
+ TLS_RECORD_HEADER *RecordHeaderIn;
+ UINT16 ThisCipherMessageSize;
+ TLS_RECORD_HEADER *TempRecordHeader;
+ UINT16 ThisPlainMessageSize;
+ UINT8 *BufferOut;
+ UINT32 BufferOutSize;
+ INTN Ret;
+
+ Status = EFI_SUCCESS;
+ BytesCopied = 0;
+ BufferIn = NULL;
+ BufferInSize = 0;
+ BufferInPtr = NULL;
+ RecordHeaderIn = NULL;
+ TempRecordHeader = NULL;
+ BufferOut = NULL;
+ BufferOutSize = 0;
+ Ret = 0;
+
+ //
+ // Calculate the size according to the fragment table.
+ //
+ for (Index = 0; Index < *FragmentCount; Index++) {
+ BufferInSize += (*FragmentTable)[Index].FragmentLength;
+ }
+
+ //
+ // Allocate buffer for processing data
+ //
+ BufferIn = AllocateZeroPool (BufferInSize);
+ if (BufferIn == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ //
+ // Copy all TLS plain record header and payload to BufferIn
+ //
+ for (Index = 0; Index < *FragmentCount; Index++) {
+ CopyMem (
+ (BufferIn + BytesCopied),
+ (*FragmentTable)[Index].FragmentBuffer,
+ (*FragmentTable)[Index].FragmentLength
+ );
+ BytesCopied += (*FragmentTable)[Index].FragmentLength;
+ }
+
+ BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+ if (BufferOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ //
+ // Parsing buffer. Received packet may have multiple TLS record messages.
+ //
+ BufferInPtr = BufferIn;
+ TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+ while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+ RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+
+ if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ERROR;
+ }
+
+ ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
+
+ Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize);
+ if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) {
+ TlsInstance->TlsSessionState = EfiTlsSessionError;
+ Status = EFI_ABORTED;
+ goto ERROR;
+ }
+
+ Ret = 0;
+ Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE - BufferOutSize);
+
+ if (Ret > 0) {
+ ThisPlainMessageSize = (UINT16) Ret;
+ } else {
+ //
+ // No data was successfully decrypted, continue to decrypt other messages.
+ //
+ DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n"));
+
+ ThisPlainMessageSize = 0;
+ }
+
+ CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN);
+ TempRecordHeader->Length = ThisPlainMessageSize;
+ BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize;
+
+ BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize;
+ TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize;
+ }
+
+ FreePool (BufferIn);
+ BufferIn = NULL;
+
+ //
+ // The caller will be responsible to handle the original fragment table
+ //
+ *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+ if (*FragmentTable == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ERROR;
+ }
+
+ (*FragmentTable)[0].FragmentBuffer = BufferOut;
+ (*FragmentTable)[0].FragmentLength = BufferOutSize;
+ *FragmentCount = 1;
+
+ return Status;
+
+ERROR:
+
+ if (BufferIn != NULL) {
+ FreePool (BufferIn);
+ BufferIn = NULL;
+ }
+
+ if (BufferOut != NULL) {
+ FreePool (BufferOut);
+ BufferOut = NULL;
+ }
+
+ return Status;
+}
diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h
new file mode 100644
index 0000000000..71b1bdb7dc
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.h
@@ -0,0 +1,315 @@
+/** @file
+ Header file of Miscellaneous Routines for TlsDxe driver.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_TLS_IMPL_H__
+#define __EFI_TLS_IMPL_H__
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/NetLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/TlsLib.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/Tls.h>
+#include <Protocol/TlsConfig.h>
+
+#include <IndustryStandard/Tls1.h>
+
+#include "TlsDriver.h"
+
+//
+// Protocol instances
+//
+extern EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding;
+extern EFI_TLS_PROTOCOL mTlsProtocol;
+extern EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol;
+
+#define RECORD_HEADER_LEN 5 /// ContentType(1) + Version(2) + Length(2)
+
+#define MAX_BUFFER_SIZE 32768
+
+/**
+ Encrypt the message listed in fragment.
+
+ @param[in] TlsInstance The pointer to the TLS instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment.
+ On input these fragments contain the TLS header and
+ plain text TLS payload;
+ On output these fragments contain the TLS header and
+ cipher text TLS payload.
+ @param[in] FragmentCount Number of fragment.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ABORTED TLS session state is incorrect.
+ @retval Others Other errors as indicated.
+**/
+EFI_STATUS
+TlsEncryptPacket (
+ IN TLS_INSTANCE *TlsInstance,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount
+ );
+
+/**
+ Decrypt the message listed in fragment.
+
+ @param[in] TlsInstance The pointer to the TLS instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment.
+ On input these fragments contain the TLS header and
+ cipher text TLS payload;
+ On output these fragments contain the TLS header and
+ plain text TLS payload.
+ @param[in] FragmentCount Number of fragment.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ABORTED TLS session state is incorrect.
+ @retval Others Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+ IN TLS_INSTANCE *TlsInstance,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount
+ );
+
+/**
+ Set TLS session data.
+
+ The SetSessionData() function set data for a new TLS session. All session data should
+ be set before BuildResponsePacket() invoked.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] DataType TLS session data type.
+ @param[in] Data Pointer to session data.
+ @param[in] DataSize Total size of session data.
+
+ @retval EFI_SUCCESS The TLS session data is set successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Data is NULL.
+ DataSize is 0.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_ACCESS_DENIED If the DataType is one of below:
+ EfiTlsClientRandom
+ EfiTlsServerRandom
+ EfiTlsKeyMaterial
+ @retval EFI_NOT_READY Current TLS session state is NOT
+ EfiTlsSessionStateNotStarted.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+ IN EFI_TLS_PROTOCOL *This,
+ IN EFI_TLS_SESSION_DATA_TYPE DataType,
+ IN VOID *Data,
+ IN UINTN DataSize
+ );
+
+/**
+ Get TLS session data.
+
+ The GetSessionData() function return the TLS session information.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] DataType TLS session data type.
+ @param[in, out] Data Pointer to session data.
+ @param[in, out] DataSize Total size of session data. On input, it means
+ the size of Data buffer. On output, it means the size
+ of copied Data buffer if EFI_SUCCESS, and means the
+ size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+ @retval EFI_SUCCESS The TLS session data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSize is not zero.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_NOT_FOUND The TLS session data is not found.
+ @retval EFI_NOT_READY The DataType is not ready in current session state.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+ IN EFI_TLS_PROTOCOL *This,
+ IN EFI_TLS_SESSION_DATA_TYPE DataType,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataSize
+ );
+
+/**
+ Build response packet according to TLS state machine. This function is only valid for
+ alert, handshake and change_cipher_spec content type.
+
+ The BuildResponsePacket() function builds TLS response packet in response to the TLS
+ request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+ RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+ will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+ NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+ session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+ NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+ session has errors and the response packet needs to be Alert message based on error
+ type.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL
+ means TLS need initiate the TLS session and response
+ packet need to be ClientHello.
+ @param[in] RequestSize Packet size in bytes for the most recently received TLS
+ packet. 0 is only valid when RequestBuffer is NULL.
+ @param[out] Buffer Pointer to the buffer to hold the built packet.
+ @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is
+ the buffer size provided by the caller. On output, it
+ is the buffer size in fact needed to contain the
+ packet.
+
+ @retval EFI_SUCCESS The required TLS packet is built successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ RequestBuffer is NULL but RequestSize is NOT 0.
+ RequestSize is 0 but RequestBuffer is NOT NULL.
+ BufferSize is NULL.
+ Buffer is NULL if *BufferSize is not zero.
+ @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet.
+ @retval EFI_NOT_READY Current TLS session state is NOT ready to build
+ ResponsePacket.
+ @retval EFI_ABORTED Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+ IN EFI_TLS_PROTOCOL *This,
+ IN UINT8 *RequestBuffer, OPTIONAL
+ IN UINTN RequestSize, OPTIONAL
+ OUT UINT8 *Buffer, OPTIONAL
+ IN OUT UINTN *BufferSize
+ );
+
+/**
+ Decrypt or encrypt TLS packet during session. This function is only valid after
+ session connected and for application_data content type.
+
+ The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take
+ responsible to handle the original FragmentTable while
+ it may be reallocated in TLS driver. If CryptMode is
+ EfiTlsEncrypt, on input these fragments contain the TLS
+ header and plain text TLS APP payload; on output these
+ fragments contain the TLS header and cipher text TLS
+ APP payload. If CryptMode is EfiTlsDecrypt, on input
+ these fragments contain the TLS header and cipher text
+ TLS APP payload; on output these fragments contain the
+ TLS header and plain text TLS APP payload.
+ @param[in] FragmentCount Number of fragment.
+ @param[in] CryptMode Crypt mode.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ FragmentTable is NULL.
+ FragmentCount is NULL.
+ CryptoMode is invalid.
+ @retval EFI_NOT_READY Current TLS session state is NOT
+ EfiTlsSessionDataTransferring.
+ @retval EFI_ABORTED Something wrong decryption the message. TLS session
+ status will become EfiTlsSessionError. The caller need
+ call BuildResponsePacket() to generate Error Alert
+ message and send it out.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+ IN EFI_TLS_PROTOCOL *This,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount,
+ IN EFI_TLS_CRYPT_MODE CryptMode
+ );
+
+/**
+ Set TLS configuration data.
+
+ The SetData() function sets TLS configuration to non-volatile storage or volatile
+ storage.
+
+ @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+ @param[in] DataType Configuration data type.
+ @param[in] Data Pointer to configuration data.
+ @param[in] DataSize Total size of configuration data.
+
+ @retval EFI_SUCCESS The TLS configuration data is set successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Data is NULL.
+ DataSize is 0.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+ IN EFI_TLS_CONFIGURATION_PROTOCOL *This,
+ IN EFI_TLS_CONFIG_DATA_TYPE DataType,
+ IN VOID *Data,
+ IN UINTN DataSize
+ );
+
+/**
+ Get TLS configuration data.
+
+ The GetData() function gets TLS configuration.
+
+ @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+ @param[in] DataType Configuration data type.
+ @param[in, out] Data Pointer to configuration data.
+ @param[in, out] DataSize Total size of configuration data. On input, it means
+ the size of Data buffer. On output, it means the size
+ of copied Data buffer if EFI_SUCCESS, and means the
+ size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+ @retval EFI_SUCCESS The TLS configuration data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSize is not zero.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_NOT_FOUND The TLS configuration data is not found.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+ IN EFI_TLS_CONFIGURATION_PROTOCOL *This,
+ IN EFI_TLS_CONFIG_DATA_TYPE DataType,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataSize
+ );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsProtocol.c b/NetworkPkg/TlsDxe/TlsProtocol.c
new file mode 100644
index 0000000000..ee1c496239
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsProtocol.c
@@ -0,0 +1,632 @@
+/** @file
+ Implementation of EFI TLS Protocol Interfaces.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_PROTOCOL mTlsProtocol = {
+ TlsSetSessionData,
+ TlsGetSessionData,
+ TlsBuildResponsePacket,
+ TlsProcessPacket
+};
+
+/**
+ Set TLS session data.
+
+ The SetSessionData() function set data for a new TLS session. All session data should
+ be set before BuildResponsePacket() invoked.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] DataType TLS session data type.
+ @param[in] Data Pointer to session data.
+ @param[in] DataSize Total size of session data.
+
+ @retval EFI_SUCCESS The TLS session data is set successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ Data is NULL.
+ DataSize is 0.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_ACCESS_DENIED If the DataType is one of below:
+ EfiTlsClientRandom
+ EfiTlsServerRandom
+ EfiTlsKeyMaterial
+ @retval EFI_NOT_READY Current TLS session state is NOT
+ EfiTlsSessionStateNotStarted.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+ IN EFI_TLS_PROTOCOL *This,
+ IN EFI_TLS_SESSION_DATA_TYPE DataType,
+ IN VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+ UINT16 *CipherId;
+ UINTN Index;
+
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+ CipherId = NULL;
+
+ if (This == NULL || Data == NULL || DataSize == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_PROTOCOL (This);
+
+ if (DataType != EfiTlsSessionState && Instance->TlsSessionState != EfiTlsSessionNotStarted){
+ Status = EFI_NOT_READY;
+ goto ON_EXIT;
+ }
+
+ switch (DataType) {
+ //
+ // Session Configuration
+ //
+ case EfiTlsVersion:
+ if (DataSize != sizeof (EFI_TLS_VERSION)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor);
+ break;
+ case EfiTlsConnectionEnd:
+ if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));
+ break;
+ case EfiTlsCipherList:
+ CipherId = AllocatePool (DataSize);
+ if (CipherId == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) {
+ *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));
+ }
+
+ Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER));
+
+ FreePool (CipherId);
+ break;
+ case EfiTlsCompressionMethod:
+ //
+ // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the
+ // record protocol will not be compressed.
+ // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html
+ // The TLS RFC does however not specify compression methods or their corresponding identifiers,
+ // so there is currently no compatible way to integrate compression with unknown peers.
+ // It is therefore currently not recommended to integrate compression into applications.
+ // Applications for non-public use may agree on certain compression methods.
+ // Using different compression methods with the same identifier will lead to connection failure.
+ //
+ for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) {
+ Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ break;
+ case EfiTlsExtensionData:
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ case EfiTlsVerifyMethod:
+ if (DataSize != sizeof (EFI_TLS_VERIFY)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));
+ break;
+ case EfiTlsSessionID:
+ if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = TlsSetSessionId (
+ Instance->TlsConn,
+ ((EFI_TLS_SESSION_ID *) Data)->Data,
+ ((EFI_TLS_SESSION_ID *) Data)->Length
+ );
+ break;
+ case EfiTlsSessionState:
+ if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;
+ break;
+ //
+ // Session information
+ //
+ case EfiTlsClientRandom:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ case EfiTlsServerRandom:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ case EfiTlsKeyMaterial:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ //
+ // Unsupported type.
+ //
+ default:
+ Status = EFI_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Get TLS session data.
+
+ The GetSessionData() function return the TLS session information.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] DataType TLS session data type.
+ @param[in, out] Data Pointer to session data.
+ @param[in, out] DataSize Total size of session data. On input, it means
+ the size of Data buffer. On output, it means the size
+ of copied Data buffer if EFI_SUCCESS, and means the
+ size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+ @retval EFI_SUCCESS The TLS session data is got successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ DataSize is NULL.
+ Data is NULL if *DataSize is not zero.
+ @retval EFI_UNSUPPORTED The DataType is unsupported.
+ @retval EFI_NOT_FOUND The TLS session data is not found.
+ @retval EFI_NOT_READY The DataType is not ready in current session state.
+ @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+ IN EFI_TLS_PROTOCOL *This,
+ IN EFI_TLS_SESSION_DATA_TYPE DataType,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataSize
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_PROTOCOL (This);
+
+ if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&
+ (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||
+ DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {
+ Status = EFI_NOT_READY;
+ goto ON_EXIT;
+ }
+
+ switch (DataType) {
+ case EfiTlsVersion:
+ if (*DataSize < sizeof (EFI_TLS_VERSION)) {
+ *DataSize = sizeof (EFI_TLS_VERSION);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_VERSION);
+ *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));
+ break;
+ case EfiTlsConnectionEnd:
+ if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {
+ *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+ *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);
+ break;
+ case EfiTlsCipherList:
+ //
+ // Get the current session cipher suite.
+ //
+ if (*DataSize < sizeof (EFI_TLS_CIPHER)) {
+ *DataSize = sizeof (EFI_TLS_CIPHER);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof(EFI_TLS_CIPHER);
+ Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);
+ *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));
+ break;
+ case EfiTlsCompressionMethod:
+ //
+ // Get the current session compression method.
+ //
+ if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {
+ *DataSize = sizeof (EFI_TLS_COMPRESSION);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_COMPRESSION);
+ Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data);
+ break;
+ case EfiTlsExtensionData:
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ case EfiTlsVerifyMethod:
+ if (*DataSize < sizeof (EFI_TLS_VERIFY)) {
+ *DataSize = sizeof (EFI_TLS_VERIFY);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_VERIFY);
+ *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);
+ break;
+ case EfiTlsSessionID:
+ if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {
+ *DataSize = sizeof (EFI_TLS_SESSION_ID);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_SESSION_ID);
+ Status = TlsGetSessionId (
+ Instance->TlsConn,
+ ((EFI_TLS_SESSION_ID *) Data)->Data,
+ &(((EFI_TLS_SESSION_ID *) Data)->Length)
+ );
+ break;
+ case EfiTlsSessionState:
+ if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {
+ *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+ CopyMem (Data, &Instance->TlsSessionState, *DataSize);
+ break;
+ case EfiTlsClientRandom:
+ if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+ *DataSize = sizeof (EFI_TLS_RANDOM);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_RANDOM);
+ TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);
+ break;
+ case EfiTlsServerRandom:
+ if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+ *DataSize = sizeof (EFI_TLS_RANDOM);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_RANDOM);
+ TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);
+ break;
+ case EfiTlsKeyMaterial:
+ if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {
+ *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+ *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+ Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);
+ break;
+ //
+ // Unsupported type.
+ //
+ default:
+ Status = EFI_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Build response packet according to TLS state machine. This function is only valid for
+ alert, handshake and change_cipher_spec content type.
+
+ The BuildResponsePacket() function builds TLS response packet in response to the TLS
+ request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+ RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+ will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+ NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+ session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+ NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+ session has errors and the response packet needs to be Alert message based on error
+ type.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL
+ means TLS need initiate the TLS session and response
+ packet need to be ClientHello.
+ @param[in] RequestSize Packet size in bytes for the most recently received TLS
+ packet. 0 is only valid when RequestBuffer is NULL.
+ @param[out] Buffer Pointer to the buffer to hold the built packet.
+ @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is
+ the buffer size provided by the caller. On output, it
+ is the buffer size in fact needed to contain the
+ packet.
+
+ @retval EFI_SUCCESS The required TLS packet is built successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ RequestBuffer is NULL but RequestSize is NOT 0.
+ RequestSize is 0 but RequestBuffer is NOT NULL.
+ BufferSize is NULL.
+ Buffer is NULL if *BufferSize is not zero.
+ @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet.
+ @retval EFI_NOT_READY Current TLS session state is NOT ready to build
+ ResponsePacket.
+ @retval EFI_ABORTED Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+ IN EFI_TLS_PROTOCOL *This,
+ IN UINT8 *RequestBuffer, OPTIONAL
+ IN UINTN RequestSize, OPTIONAL
+ OUT UINT8 *Buffer, OPTIONAL
+ IN OUT UINTN *BufferSize
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ if ((This == NULL) || (BufferSize == NULL) ||
+ (RequestBuffer == NULL && RequestSize != 0) ||
+ (RequestBuffer != NULL && RequestSize == 0) ||
+ (Buffer == NULL && *BufferSize !=0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_PROTOCOL (This);
+
+ if(RequestBuffer == NULL && RequestSize == 0) {
+ switch (Instance->TlsSessionState) {
+ case EfiTlsSessionNotStarted:
+ //
+ // ClientHello.
+ //
+ Status = TlsDoHandshake (
+ Instance->TlsConn,
+ NULL,
+ 0,
+ Buffer,
+ BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // *BufferSize should not be zero when ClientHello.
+ //
+ if (*BufferSize == 0) {
+ Status = EFI_ABORTED;
+ goto ON_EXIT;
+ }
+
+ Instance->TlsSessionState = EfiTlsSessionHandShaking;
+
+ break;
+ case EfiTlsSessionClosing:
+ //
+ // TLS session will be closed and response packet needs to be CloseNotify.
+ //
+ Status = TlsCloseNotify (
+ Instance->TlsConn,
+ Buffer,
+ BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // *BufferSize should not be zero when build CloseNotify message.
+ //
+ if (*BufferSize == 0) {
+ Status = EFI_ABORTED;
+ goto ON_EXIT;
+ }
+
+ break;
+ case EfiTlsSessionError:
+ //
+ // TLS session has errors and the response packet needs to be Alert
+ // message based on error type.
+ //
+ Status = TlsHandleAlert (
+ Instance->TlsConn,
+ NULL,
+ 0,
+ Buffer,
+ BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ break;
+ default:
+ //
+ // Current TLS session state is NOT ready to build ResponsePacket.
+ //
+ Status = EFI_NOT_READY;
+ }
+ } else {
+ //
+ // 1. Received packet may have multiple TLS record messages.
+ // 2. One TLS record message may have multiple handshake protocol.
+ // 3. Some errors may be happened in handshake.
+ // TlsDoHandshake() can handle all of those cases.
+ //
+ if (TlsInHandshake (Instance->TlsConn)) {
+ Status = TlsDoHandshake (
+ Instance->TlsConn,
+ RequestBuffer,
+ RequestSize,
+ Buffer,
+ BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ if (!TlsInHandshake (Instance->TlsConn)) {
+ Instance->TlsSessionState = EfiTlsSessionDataTransferring;
+ }
+ } else {
+ //
+ // Must be alert message, Decrypt it and build the ResponsePacket.
+ //
+ ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT);
+
+ Status = TlsHandleAlert (
+ Instance->TlsConn,
+ RequestBuffer,
+ RequestSize,
+ Buffer,
+ BufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ Instance->TlsSessionState = EfiTlsSessionError;
+ }
+
+ goto ON_EXIT;
+ }
+ }
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Decrypt or encrypt TLS packet during session. This function is only valid after
+ session connected and for application_data content type.
+
+ The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+ @param[in] This Pointer to the EFI_TLS_PROTOCOL instance.
+ @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take
+ responsible to handle the original FragmentTable while
+ it may be reallocated in TLS driver. If CryptMode is
+ EfiTlsEncrypt, on input these fragments contain the TLS
+ header and plain text TLS APP payload; on output these
+ fragments contain the TLS header and cipher text TLS
+ APP payload. If CryptMode is EfiTlsDecrypt, on input
+ these fragments contain the TLS header and cipher text
+ TLS APP payload; on output these fragments contain the
+ TLS header and plain text TLS APP payload.
+ @param[in] FragmentCount Number of fragment.
+ @param[in] CryptMode Crypt mode.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL.
+ FragmentTable is NULL.
+ FragmentCount is NULL.
+ CryptoMode is invalid.
+ @retval EFI_NOT_READY Current TLS session state is NOT
+ EfiTlsSessionDataTransferring.
+ @retval EFI_ABORTED Something wrong decryption the message. TLS session
+ status will become EfiTlsSessionError. The caller need
+ call BuildResponsePacket() to generate Error Alert
+ message and send it out.
+ @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+ IN EFI_TLS_PROTOCOL *This,
+ IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
+ IN UINT32 *FragmentCount,
+ IN EFI_TLS_CRYPT_MODE CryptMode
+ )
+{
+ EFI_STATUS Status;
+ TLS_INSTANCE *Instance;
+
+ EFI_TPL OldTpl;
+
+ Status = EFI_SUCCESS;
+
+ if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = TLS_INSTANCE_FROM_PROTOCOL (This);
+
+ if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {
+ Status = EFI_NOT_READY;
+ goto ON_EXIT;
+ }
+
+ //
+ // Packet sent or received may have multiple TLS record messages (Application data type).
+ // So,on input these fragments contain the TLS header and TLS APP payload;
+ // on output these fragments also contain the TLS header and TLS APP payload.
+ //
+ switch (CryptMode) {
+ case EfiTlsEncrypt:
+ Status = TlsEncryptPacket (Instance, FragmentTable, FragmentCount);
+ break;
+ case EfiTlsDecrypt:
+ Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}