NetworkPkg/HttpDxe: Handle the large data request via HTTPS channel.

Cc: Karunakar P <karunakarp@amiindia.co.in>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Karunakar p <karunakarp@amiindia.co.in>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
This commit is contained in:
Jiaxin Wu 2018-03-15 18:38:58 +08:00
parent cb3350ec62
commit 07bd82d42b
3 changed files with 113 additions and 41 deletions

View File

@ -1,7 +1,7 @@
/** @file /** @file
Miscellaneous routines for HttpDxe driver. Miscellaneous routines for HttpDxe driver.
Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR> Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -1476,50 +1476,87 @@ HttpTransmitTcp (
EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP6_IO_TOKEN *Tx6Token; EFI_TCP6_IO_TOKEN *Tx6Token;
EFI_TCP6_PROTOCOL *Tcp6; EFI_TCP6_PROTOCOL *Tcp6;
UINT8 *Buffer; UINT8 *TlsRecord;
UINTN BufferSize; UINT16 PayloadSize;
NET_FRAGMENT TempFragment; NET_FRAGMENT TempFragment;
NET_FRAGMENT Fragment;
UINTN RecordCount;
UINTN RemainingLen;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
Buffer = NULL; TlsRecord = NULL;
PayloadSize = 0;
TempFragment.Len = 0; TempFragment.Len = 0;
TempFragment.Bulk = NULL; TempFragment.Bulk = NULL;
Fragment.Len = 0;
Fragment.Bulk = NULL;
RecordCount = 0;
RemainingLen = 0;
// //
// Need to encrypt data. // Need to encrypt data.
// //
if (HttpInstance->UseHttps) { if (HttpInstance->UseHttps) {
// //
// Build BufferOut data // Allocate enough buffer for each TLS plaintext records.
// //
BufferSize = sizeof (TLS_RECORD_HEADER) + TxStringLen; TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);
Buffer = AllocateZeroPool (BufferSize); if (TlsRecord == NULL) {
if (Buffer == NULL) {
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
return Status; return Status;
} }
((TLS_RECORD_HEADER *) Buffer)->ContentType = TlsContentTypeApplicationData;
((TLS_RECORD_HEADER *) Buffer)->Version.Major = HttpInstance->TlsConfigData.Version.Major;
((TLS_RECORD_HEADER *) Buffer)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;
((TLS_RECORD_HEADER *) Buffer)->Length = (UINT16) (TxStringLen);
CopyMem (Buffer + sizeof (TLS_RECORD_HEADER), TxString, TxStringLen);
//
// Encrypt Packet.
//
Status = TlsProcessMessage (
HttpInstance,
Buffer,
BufferSize,
EfiTlsEncrypt,
&TempFragment
);
FreePool (Buffer);
if (EFI_ERROR (Status)) { //
return Status; // Allocate enough buffer for all TLS ciphertext records.
//
RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;
Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));
if (Fragment.Bulk == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
} }
//
// Encrypt each TLS plaintext records.
//
RemainingLen = TxStringLen;
while (RemainingLen != 0) {
PayloadSize = (UINT16) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);
((TLS_RECORD_HEADER *) TlsRecord)->ContentType = TlsContentTypeApplicationData;
((TLS_RECORD_HEADER *) TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;
((TLS_RECORD_HEADER *) TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;
((TLS_RECORD_HEADER *) TlsRecord)->Length = PayloadSize;
CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);
Status = TlsProcessMessage (
HttpInstance,
TlsRecord,
TLS_RECORD_HEADER_LENGTH + PayloadSize,
EfiTlsEncrypt,
&TempFragment
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Record the processed/encrypted Packet.
//
CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);
Fragment.Len += TempFragment.Len;
FreePool (TempFragment.Bulk);
TempFragment.Len = 0;
TempFragment.Bulk = NULL;
RemainingLen -= (UINTN) PayloadSize;
ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);
}
FreePool (TlsRecord);
TlsRecord = NULL;
} }
if (!HttpInstance->LocalAddressIsIPv6) { if (!HttpInstance->LocalAddressIsIPv6) {
@ -1527,9 +1564,9 @@ HttpTransmitTcp (
Tx4Token = &Wrap->TcpWrap.Tx4Token; Tx4Token = &Wrap->TcpWrap.Tx4Token;
if (HttpInstance->UseHttps) { if (HttpInstance->UseHttps) {
Tx4Token->Packet.TxData->DataLength = TempFragment.Len; Tx4Token->Packet.TxData->DataLength = Fragment.Len;
Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;
Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;
} else { } else {
Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen; Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
@ -1542,7 +1579,7 @@ HttpTransmitTcp (
Status = Tcp4->Transmit (Tcp4, Tx4Token); Status = Tcp4->Transmit (Tcp4, Tx4Token);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status)); DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
return Status; goto ON_ERROR;
} }
} else { } else {
@ -1550,9 +1587,9 @@ HttpTransmitTcp (
Tx6Token = &Wrap->TcpWrap.Tx6Token; Tx6Token = &Wrap->TcpWrap.Tx6Token;
if (HttpInstance->UseHttps) { if (HttpInstance->UseHttps) {
Tx6Token->Packet.TxData->DataLength = TempFragment.Len; Tx6Token->Packet.TxData->DataLength = Fragment.Len;
Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = TempFragment.Len; Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;
Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TempFragment.Bulk; Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;
} else { } else {
Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen; Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen; Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;
@ -1565,10 +1602,26 @@ HttpTransmitTcp (
Status = Tcp6->Transmit (Tcp6, Tx6Token); Status = Tcp6->Transmit (Tcp6, Tx6Token);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status)); DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
return Status; goto ON_ERROR;
} }
} }
return Status;
ON_ERROR:
if (HttpInstance->UseHttps) {
if (TlsRecord != NULL) {
FreePool (TlsRecord);
TlsRecord = NULL;
}
if (Fragment.Bulk != NULL) {
FreePool (Fragment.Bulk);
Fragment.Bulk = NULL;
}
}
return Status; return Status;
} }

View File

@ -951,7 +951,7 @@ TlsReceiveOnePdu (
// //
// Allocate buffer to receive one TLS header. // Allocate buffer to receive one TLS header.
// //
Len = sizeof (TLS_RECORD_HEADER); Len = TLS_RECORD_HEADER_LENGTH;
PduHdr = NetbufAlloc (Len); PduHdr = NetbufAlloc (Len);
if (PduHdr == NULL) { if (PduHdr == NULL) {
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
@ -1391,11 +1391,19 @@ TlsCloseSession (
Process one message according to the CryptMode. Process one message according to the CryptMode.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure. @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@param[in] Message Pointer to the message buffer needed to processed. @param[in] Message Pointer to the message buffer needed to processed.
If ProcessMode is EfiTlsEncrypt, the message contain the TLS
header and plain text TLS APP payload.
If ProcessMode is EfiTlsDecrypt, the message contain the TLS
header and cipher text TLS APP payload.
@param[in] MessageSize Pointer to the message buffer size. @param[in] MessageSize Pointer to the message buffer size.
@param[in] ProcessMode Process mode. @param[in] ProcessMode Process mode.
@param[in, out] Fragment Only one Fragment returned after the Message is @param[in, out] Fragment Only one Fragment returned after the Message is
processed successfully. processed successfully.
If ProcessMode is EfiTlsEncrypt, the fragment contain the TLS
header and cipher text TLS APP payload.
If ProcessMode is EfiTlsDecrypt, the fragment contain the TLS
header and plain text TLS APP payload.
@retval EFI_SUCCESS Message is processed successfully. @retval EFI_SUCCESS Message is processed successfully.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
@ -1498,6 +1506,9 @@ TlsProcessMessage (
ON_EXIT: ON_EXIT:
if (OriginalFragmentTable != NULL) { if (OriginalFragmentTable != NULL) {
if( FragmentTable == OriginalFragmentTable) {
FragmentTable = NULL;
}
FreePool (OriginalFragmentTable); FreePool (OriginalFragmentTable);
OriginalFragmentTable = NULL; OriginalFragmentTable = NULL;
} }
@ -1682,7 +1693,7 @@ HttpsReceive (
return Status; return Status;
} }
CopyMem (BufferIn, TempFragment.Bulk + sizeof (TLS_RECORD_HEADER), BufferInSize); CopyMem (BufferIn, TempFragment.Bulk + TLS_RECORD_HEADER_LENGTH, BufferInSize);
// //
// Free the buffer in TempFragment. // Free the buffer in TempFragment.

View File

@ -1,7 +1,7 @@
/** @file /** @file
The header files of miscellaneous routines specific to Https for HttpDxe driver. The header files of miscellaneous routines specific to Https for HttpDxe driver.
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR> Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -217,11 +217,19 @@ TlsCloseSession (
Process one message according to the CryptMode. Process one message according to the CryptMode.
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure. @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
@param[in] Message Pointer to the message buffer needed to processed. @param[in] Message Pointer to the message buffer needed to processed.
If ProcessMode is EfiTlsEncrypt, the message contain the TLS
header and plain text TLS APP payload.
If ProcessMode is EfiTlsDecrypt, the message contain the TLS
header and cipher text TLS APP payload.
@param[in] MessageSize Pointer to the message buffer size. @param[in] MessageSize Pointer to the message buffer size.
@param[in] ProcessMode Process mode. @param[in] ProcessMode Process mode.
@param[in, out] Fragment Only one Fragment returned after the Message is @param[in, out] Fragment Only one Fragment returned after the Message is
processed successfully. processed successfully.
If ProcessMode is EfiTlsEncrypt, the fragment contain the TLS
header and cipher text TLS APP payload.
If ProcessMode is EfiTlsDecrypt, the fragment contain the TLS
header and plain text TLS APP payload.
@retval EFI_SUCCESS Message is processed successfully. @retval EFI_SUCCESS Message is processed successfully.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.