Skip to content

Commit

Permalink
[Cherry-Pick] PixieFail Security Patches for TCBZ451 and TCB4542 (#801)
Browse files Browse the repository at this point in the history
## Description

Cherry-picked from
[release/202311](#799)

This fixes the remaining two issues from PixieFail.

See
https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
for more detailed information on:

1. CVE 2023-45236 (TCBZ4541)
2. CVE 2023-45237 (TCBZ4542)

- [ ] Impacts functionality?
- [X] Impacts security?
  - Fixes vulnerabilities identified by Pixie Fail
- Updates the ISN generation to follow the
[specification](https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1)
- Replaces all instances of NET_RANDOM with the random number generator
provided by the platform.
- [X] Breaking change?
- Yes this depends on the Hash2ServiceProtocol. A platform must publish
these in order for these patches to work.
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This was tested on a physical platform by PXEBooting and performing TCP
Connections through DFCI

## Integration Instructions

Ensure the platform publishes the HASH 2 Protocol.

---------

Signed-off-by: Doug Flick <dougflick@microsoft.com>
  • Loading branch information
Flickdm committed Apr 10, 2024
1 parent 400c75b commit a5f6b68
Show file tree
Hide file tree
Showing 31 changed files with 717 additions and 125 deletions.
9 changes: 8 additions & 1 deletion NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
Expand Up @@ -189,6 +189,13 @@ Dhcp4CreateService (
{
DHCP_SERVICE *DhcpSb;
EFI_STATUS Status;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

*Service = NULL;
DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
Expand All @@ -203,7 +210,7 @@ Dhcp4CreateService (
DhcpSb->Image = ImageHandle;
InitializeListHead (&DhcpSb->Children);
DhcpSb->DhcpState = Dhcp4Stopped;
DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
DhcpSb->Xid = Random;
CopyMem (
&DhcpSb->ServiceBinding,
&mDhcp4ServiceBindingTemplate,
Expand Down
9 changes: 8 additions & 1 deletion NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
Expand Up @@ -123,6 +123,13 @@ Dhcp6CreateService (
{
DHCP6_SERVICE *Dhcp6Srv;
EFI_STATUS Status;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

*Service = NULL;
Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
Expand All @@ -147,7 +154,7 @@ Dhcp6CreateService (
Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
Dhcp6Srv->Controller = Controller;
Dhcp6Srv->Image = ImageHandle;
Dhcp6Srv->Xid = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
Dhcp6Srv->Xid = (0xffffff & Random);

CopyMem (
&Dhcp6Srv->ServiceBinding,
Expand Down
9 changes: 8 additions & 1 deletion NetworkPkg/DnsDxe/DnsDhcp.c
Expand Up @@ -277,6 +277,7 @@ GetDns4ServerFromDhcp4 (
EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;
BOOLEAN IsDone;
UINTN Index;
UINT32 Random;

Image = Instance->Service->ImageHandle;
Controller = Instance->Service->ControllerHandle;
Expand All @@ -292,6 +293,12 @@ GetDns4ServerFromDhcp4 (
Data = NULL;
InterfaceInfo = NULL;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));

ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));
Expand Down Expand Up @@ -467,7 +474,7 @@ GetDns4ServerFromDhcp4 (

Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);

Token.Packet->Dhcp4.Header.Xid = HTONL (NET_RANDOM (NetRandomInitSeed ()));
Token.Packet->Dhcp4.Header.Xid = Random;

Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);

Expand Down
10 changes: 9 additions & 1 deletion NetworkPkg/DnsDxe/DnsImpl.c
Expand Up @@ -1963,6 +1963,14 @@ ConstructDNSQuery (
NET_FRAGMENT Frag;
DNS_HEADER *DnsHeader;
DNS_QUERY_SECTION *DnsQuery;
EFI_STATUS Status;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

//
// Messages carried by UDP are restricted to 512 bytes (not counting the IP
Expand All @@ -1977,7 +1985,7 @@ ConstructDNSQuery (
// Fill header
//
DnsHeader = (DNS_HEADER *)Frag.Bulk;
DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed ());
DnsHeader->Identification = (UINT16)Random;
DnsHeader->Flags.Uint16 = 0x0000;
DnsHeader->Flags.Bits.RD = 1;
DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
Expand Down
9 changes: 8 additions & 1 deletion NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
Expand Up @@ -951,6 +951,7 @@ HttpBootDhcp6Sarr (
UINT32 OptCount;
UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
EFI_STATUS Status;
UINT32 Random;

Dhcp6 = Private->Dhcp6;
ASSERT (Dhcp6 != NULL);
Expand All @@ -961,6 +962,12 @@ HttpBootDhcp6Sarr (
OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
ASSERT (OptCount > 0);

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
if (Retransmit == NULL) {
return EFI_OUT_OF_RESOURCES;
Expand All @@ -976,7 +983,7 @@ HttpBootDhcp6Sarr (
Config.IaInfoEvent = NULL;
Config.RapidCommit = FALSE;
Config.ReconfigureAccept = FALSE;
Config.IaDescriptor.IaId = NET_RANDOM (NetRandomInitSeed ());
Config.IaDescriptor.IaId = Random;
Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
Config.SolicitRetransmission = Retransmit;
Retransmit->Irt = 4;
Expand Down
18 changes: 13 additions & 5 deletions NetworkPkg/IScsiDxe/IScsiCHAP.c
Expand Up @@ -576,16 +576,24 @@ IScsiCHAPToSendReq (
//
// CHAP_I=<I>
//
IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
if (EFI_ERROR (Status)) {
break;
}

AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
//
// CHAP_C=<C>
//
IScsiGenRandom (
(UINT8 *)AuthData->OutChallenge,
AuthData->Hash->DigestSize
);
Status = IScsiGenRandom (
(UINT8 *)AuthData->OutChallenge,
AuthData->Hash->DigestSize
);
if (EFI_ERROR (Status)) {
break;
}

BinToHexStatus = IScsiBinToHex (
(UINT8 *)AuthData->OutChallenge,
AuthData->Hash->DigestSize,
Expand Down
13 changes: 5 additions & 8 deletions NetworkPkg/IScsiDxe/IScsiMisc.c
Expand Up @@ -474,20 +474,17 @@ IScsiNetNtoi (
@param[in, out] Rand The buffer to contain random numbers.
@param[in] RandLength The length of the Rand buffer.
@retval EFI_SUCCESS on success
@retval others on error
**/
VOID
EFI_STATUS
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
)
{
UINT32 Random;

while (RandLength > 0) {
Random = NET_RANDOM (NetRandomInitSeed ());
*Rand++ = (UINT8)(Random);
RandLength--;
}
return PseudoRandom (Rand, RandLength);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion NetworkPkg/IScsiDxe/IScsiMisc.h
Expand Up @@ -202,8 +202,11 @@ IScsiNetNtoi (
@param[in, out] Rand The buffer to contain random numbers.
@param[in] RandLength The length of the Rand buffer.
@retval EFI_SUCCESS on success
@retval others on error
**/
VOID
EFI_STATUS
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
Expand Down
37 changes: 25 additions & 12 deletions NetworkPkg/Include/Library/NetLib.h
Expand Up @@ -539,8 +539,6 @@ extern EFI_IPv4_ADDRESS mZeroIp4Addr;
#define TICKS_PER_MS 10000U
#define TICKS_PER_SECOND 10000000U

#define NET_RANDOM(Seed) ((UINT32) ((UINT32) (Seed) * 1103515245UL + 12345) % 4294967295UL)

/**
Extract a UINT32 from a byte stream.
Expand Down Expand Up @@ -579,20 +577,35 @@ NetPutUint32 (
IN UINT32 Data
);

/**
Initialize a random seed using current time and monotonic count.
/*
Generate a Random output data given a length.
Get current time and monotonic count first. Then initialize a random seed
based on some basic mathematics operation on the hour, day, minute, second,
nanosecond and year of the current time and the monotonic count value.
@param[out] Output - The buffer to store the generated random data.
@param[in] OutputLength - The length of the output buffer.
@return The random seed initialized with current time.
@retval EFI_SUCCESS On Success
@retval EFI_INVALID_PARAMETER Pointer is null or size is zero
@retval EFI_NOT_FOUND RNG protocol not found
@Retval Others Error from RngProtocol->GetRNG()
*/
EFI_STATUS
EFIAPI
PseudoRandom (
OUT VOID *Output,
IN UINTN OutputLength
);

**/
UINT32
/*
Generate a 32-bit pseudo-random number.
@param[out] Output - The buffer to store the generated random number.
@return EFI_SUCCESS on success, error code on failure.
*/
EFI_STATUS
EFIAPI
NetRandomInitSeed (
VOID
PseudoRandomU32 (
OUT UINT32 *Output
);

#define NET_LIST_USER_STRUCT(Entry, Type, Field) \
Expand Down
9 changes: 8 additions & 1 deletion NetworkPkg/Ip4Dxe/Ip4Driver.c
Expand Up @@ -549,11 +549,18 @@ Ip4DriverBindingStart (
EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
UINTN Index;
IP4_CONFIG2_DATA_ITEM *DataItem;
UINT32 Random;

IpSb = NULL;
Ip4Cfg2 = NULL;
DataItem = NULL;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

//
// Test for the Ip4 service binding protocol
//
Expand Down Expand Up @@ -653,7 +660,7 @@ Ip4DriverBindingStart (
//
// Initialize the IP4 ID
//
mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
mIp4Id = (UINT16)Random;

return Status;

Expand Down
9 changes: 8 additions & 1 deletion NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
Expand Up @@ -2283,6 +2283,13 @@ Ip6ConfigInitInstance (
UINTN Index;
UINT16 IfIndex;
IP6_CONFIG_DATA_ITEM *DataItem;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);

Expand Down Expand Up @@ -2388,7 +2395,7 @@ Ip6ConfigInitInstance (
// The NV variable is not set, so generate a random IAID, and write down the
// fresh new configuration as the NV variable now.
//
Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
Instance->IaId = Random;

for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << ((Index << 3) & 31));
Expand Down
15 changes: 13 additions & 2 deletions NetworkPkg/Ip6Dxe/Ip6Driver.c
Expand Up @@ -316,7 +316,11 @@ Ip6CreateService (
IpSb->CurHopLimit = IP6_HOP_LIMIT;
IpSb->LinkMTU = IP6_MIN_LINK_MTU;
IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
Ip6UpdateReachableTime (IpSb);
Status = Ip6UpdateReachableTime (IpSb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}

//
// RFC4861 RETRANS_TIMER: 1,000 milliseconds
//
Expand Down Expand Up @@ -516,11 +520,18 @@ Ip6DriverBindingStart (
EFI_STATUS Status;
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
IP6_CONFIG_DATA_ITEM *DataItem;
UINT32 Random;

IpSb = NULL;
Ip6Cfg = NULL;
DataItem = NULL;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

//
// Test for the Ip6 service binding protocol
//
Expand Down Expand Up @@ -656,7 +667,7 @@ Ip6DriverBindingStart (
//
// Initialize the IP6 ID
//
mIp6Id = NET_RANDOM (NetRandomInitSeed ());
mIp6Id = Random;

return EFI_SUCCESS;

Expand Down
10 changes: 9 additions & 1 deletion NetworkPkg/Ip6Dxe/Ip6If.c
Expand Up @@ -89,6 +89,14 @@ Ip6SetAddress (
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
UINT64 Delay;
IP6_DELAY_JOIN_LIST *DelayNode;
EFI_STATUS Status;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);

Expand Down Expand Up @@ -164,7 +172,7 @@ Ip6SetAddress (
// Thus queue the address to be processed in Duplicate Address Detection module
// after the delay time (in milliseconds).
//
Delay = (UINT64)NET_RANDOM (NetRandomInitSeed ());
Delay = (UINT64)Random;
Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
Delay = RShiftU64 (Delay, 32);

Expand Down
12 changes: 10 additions & 2 deletions NetworkPkg/Ip6Dxe/Ip6Mld.c
Expand Up @@ -725,7 +725,15 @@ Ip6UpdateDelayTimer (
IN OUT IP6_MLD_GROUP *Group
)
{
UINT32 Delay;
UINT32 Delay;
EFI_STATUS Status;
UINT32 Random;

Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
return Status;
}

//
// If the Query packet specifies a Maximum Response Delay of zero, perform timer
Expand All @@ -744,7 +752,7 @@ Ip6UpdateDelayTimer (
// is less than the remaining value of the running timer.
//
if ((Group->DelayTimer == 0) || (Delay < Group->DelayTimer)) {
Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
Group->DelayTimer = Delay / 4294967295UL * Random;
}

return EFI_SUCCESS;
Expand Down

0 comments on commit a5f6b68

Please sign in to comment.