NetworkPkg/TlsDxe: verify DataSize for EfiTlsCipherList

TlsSetSessionData() shouldn't just ignore an incomplete EFI_TLS_CIPHER
element at the end of "Data":

- Generally speaking, malformed input for a security API is best rejected
  explicitly.

- Specifically speaking, the size of EFI_TLS_CIPHER is 2 bytes. If
  DataSize is 1 on input, then the initial check for (DataSize == 0) will
  fail, but then TlsSetCipherList() will be called with CipherNum=0.

Return EFI_INVALID_PARAMETER from TlsSetSessionData() if "Data" doesn't
contain a whole number of EFI_TLS_CIPHER elements. While at it, introduce
the dedicated variable CipherCount.

Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=915
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Long Qin <qin.long@intel.com>
Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com>
This commit is contained in:
Laszlo Ersek 2018-03-31 16:04:10 +02:00
parent 344d057a2b
commit 44eb974081
1 changed files with 10 additions and 2 deletions

View File

@ -38,6 +38,7 @@ EFI_TLS_PROTOCOL mTlsProtocol = {
This is NULL. This is NULL.
Data is NULL. Data is NULL.
DataSize is 0. DataSize is 0.
DataSize is invalid for DataType.
@retval EFI_UNSUPPORTED The DataType is unsupported. @retval EFI_UNSUPPORTED The DataType is unsupported.
@retval EFI_ACCESS_DENIED If the DataType is one of below: @retval EFI_ACCESS_DENIED If the DataType is one of below:
EfiTlsClientRandom EfiTlsClientRandom
@ -59,6 +60,7 @@ TlsSetSessionData (
EFI_STATUS Status; EFI_STATUS Status;
TLS_INSTANCE *Instance; TLS_INSTANCE *Instance;
UINT16 *CipherId; UINT16 *CipherId;
UINTN CipherCount;
UINTN Index; UINTN Index;
EFI_TPL OldTpl; EFI_TPL OldTpl;
@ -100,17 +102,23 @@ TlsSetSessionData (
Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data)); Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));
break; break;
case EfiTlsCipherList: case EfiTlsCipherList:
if (DataSize % sizeof (EFI_TLS_CIPHER) != 0) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
CipherId = AllocatePool (DataSize); CipherId = AllocatePool (DataSize);
if (CipherId == NULL) { if (CipherId == NULL) {
Status = EFI_OUT_OF_RESOURCES; Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT; goto ON_EXIT;
} }
for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) { CipherCount = DataSize / sizeof (EFI_TLS_CIPHER);
for (Index = 0; Index < CipherCount; Index++) {
*(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index)); *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));
} }
Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER)); Status = TlsSetCipherList (Instance->TlsConn, CipherId, CipherCount);
FreePool (CipherId); FreePool (CipherId);
break; break;