1 From 0cf3620092c1f5d2093e5bfa43ff137b888f18b3 Mon Sep 17 00:00:00 2001
2 From: Doug Flick <dougflick@microsoft.com>
3 Date: Fri, 15 Dec 2023 11:24:43 -0800
4 Subject: [PATCH 01/12] SECURITY PATCH TCBZ4535 - CVE-2023-45230 - Patch
7 NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 39 +++
8 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 411 +++++++++++++++++---------
9 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c | 455 +++++++++++++++++++++--------
10 NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h | 82 +++---
11 4 files changed, 707 insertions(+), 280 deletions(-)
13 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
14 index 0eb9c669b5..b552331767 100644
15 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
16 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
17 @@ -45,6 +45,45 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
18 #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
19 #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
22 +// For more information on DHCP options see RFC 8415, Section 21.1
24 +// The format of DHCP options is:
27 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
28 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 +// | option-code | option-len |
30 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 +// | (option-len octets) |
33 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 +#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
36 +#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
38 +// Combined size of Code and Length
39 +#define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \
40 + DHCP6_SIZE_OF_OPT_LEN)
43 + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4,
44 + "Combined size of Code and Length must be 4 per RFC 8415"
47 +// Offset to the length is just past the code
48 +#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
50 + DHCP6_OPT_LEN_OFFSET (0) == 2,
51 + "Offset of length is + 2 past start of option"
54 +#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
56 + DHCP6_OPT_DATA_OFFSET(0) == 4,
57 + "Offset to option data should be +4 from start of option"
60 #define DHCP6_PACKET_ALL 0
61 #define DHCP6_PACKET_STATEFUL 1
62 #define DHCP6_PACKET_STATELESS 2
63 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
64 index dcd01e6268..1401910950 100644
65 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
66 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
69 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
70 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
71 + Copyright (c) Microsoft Corporation
73 SPDX-License-Identifier: BSD-2-Clause-Patent
77 #include "Dhcp6Impl.h"
78 @@ -930,7 +930,8 @@ Dhcp6SendSolicitMsg (
80 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
82 - return EFI_OUT_OF_RESOURCES;
83 + Status = EFI_OUT_OF_RESOURCES;
87 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
88 @@ -944,54 +945,64 @@ Dhcp6SendSolicitMsg (
89 Cursor = Packet->Dhcp6.Option;
91 Length = HTONS (ClientId->Length);
92 - Cursor = Dhcp6AppendOption (
94 + Status = Dhcp6AppendOption (
97 HTONS (Dhcp6OptClientId),
101 + if (EFI_ERROR (Status)) {
105 - Cursor = Dhcp6AppendETOption (
107 + Status = Dhcp6AppendETOption (
113 + if (EFI_ERROR (Status)) {
117 - Cursor = Dhcp6AppendIaOption (
119 + Status = Dhcp6AppendIaOption (
125 Packet->Dhcp6.Header.MessageType
127 + if (EFI_ERROR (Status)) {
132 // Append user-defined when configurate Dhcp6 service.
134 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
135 UserOpt = Instance->Config->OptionList[Index];
136 - Cursor = Dhcp6AppendOption (
138 + Status = Dhcp6AppendOption (
145 + if (EFI_ERROR (Status)) {
151 - // Determine the size/length of packet.
153 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
154 ASSERT (Packet->Size > Packet->Length + 8);
157 // Callback to user with the packet to be sent and check the user's feedback.
159 Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);
161 if (EFI_ERROR (Status)) {
168 @@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg (
169 Instance->StartTime = 0;
171 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
173 if (EFI_ERROR (Status)) {
180 @@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg (
182 Instance->Config->SolicitRetransmission
195 @@ -1110,7 +1127,8 @@ Dhcp6SendRequestMsg (
197 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
198 if (Packet == NULL) {
199 - return EFI_OUT_OF_RESOURCES;
200 + Status = EFI_OUT_OF_RESOURCES;
204 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
205 @@ -1124,51 +1142,67 @@ Dhcp6SendRequestMsg (
206 Cursor = Packet->Dhcp6.Option;
208 Length = HTONS (ClientId->Length);
209 - Cursor = Dhcp6AppendOption (
211 + Status = Dhcp6AppendOption (
214 HTONS (Dhcp6OptClientId),
218 + if (EFI_ERROR (Status)) {
222 - Cursor = Dhcp6AppendETOption (
224 + Status = Dhcp6AppendETOption (
230 + if (EFI_ERROR (Status)) {
234 - Cursor = Dhcp6AppendOption (
236 + Status = Dhcp6AppendOption (
239 HTONS (Dhcp6OptServerId),
243 + if (EFI_ERROR (Status)) {
247 - Cursor = Dhcp6AppendIaOption (
249 + Status = Dhcp6AppendIaOption (
255 Packet->Dhcp6.Header.MessageType
257 + if (EFI_ERROR (Status)) {
262 // Append user-defined when configurate Dhcp6 service.
264 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
265 UserOpt = Instance->Config->OptionList[Index];
266 - Cursor = Dhcp6AppendOption (
268 + Status = Dhcp6AppendOption (
275 + if (EFI_ERROR (Status)) {
281 - // Determine the size/length of packet.
283 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
284 ASSERT (Packet->Size > Packet->Length + 8);
287 @@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg (
288 Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);
290 if (EFI_ERROR (Status)) {
297 @@ -1194,14 +1227,21 @@ Dhcp6SendRequestMsg (
298 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
300 if (EFI_ERROR (Status)) {
307 // Enqueue the sent packet for the retransmission in case reply timeout.
309 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
321 @@ -1266,7 +1306,8 @@ Dhcp6SendDeclineMsg (
323 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
324 if (Packet == NULL) {
325 - return EFI_OUT_OF_RESOURCES;
326 + Status = EFI_OUT_OF_RESOURCES;
330 Packet->Size = DHCP6_BASE_PACKET_SIZE;
331 @@ -1280,42 +1321,58 @@ Dhcp6SendDeclineMsg (
332 Cursor = Packet->Dhcp6.Option;
334 Length = HTONS (ClientId->Length);
335 - Cursor = Dhcp6AppendOption (
337 + Status = Dhcp6AppendOption (
340 HTONS (Dhcp6OptClientId),
344 + if (EFI_ERROR (Status)) {
348 - Cursor = Dhcp6AppendETOption (
350 + Status = Dhcp6AppendETOption (
356 + if (EFI_ERROR (Status)) {
360 - Cursor = Dhcp6AppendOption (
362 + Status = Dhcp6AppendOption (
365 HTONS (Dhcp6OptServerId),
369 + if (EFI_ERROR (Status)) {
373 - Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);
374 + Status = Dhcp6AppendIaOption (
380 + Packet->Dhcp6.Header.MessageType
382 + if (EFI_ERROR (Status)) {
387 - // Determine the size/length of packet.
389 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
390 ASSERT (Packet->Size > Packet->Length + 8);
393 // Callback to user with the packet to be sent and check the user's feedback.
395 Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);
397 if (EFI_ERROR (Status)) {
404 @@ -1329,16 +1386,22 @@ Dhcp6SendDeclineMsg (
405 Instance->StartTime = 0;
407 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
409 if (EFI_ERROR (Status)) {
416 // Enqueue the sent packet for the retransmission in case reply timeout.
418 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
430 @@ -1399,7 +1462,8 @@ Dhcp6SendReleaseMsg (
432 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
433 if (Packet == NULL) {
434 - return EFI_OUT_OF_RESOURCES;
435 + Status = EFI_OUT_OF_RESOURCES;
439 Packet->Size = DHCP6_BASE_PACKET_SIZE;
440 @@ -1413,45 +1477,61 @@ Dhcp6SendReleaseMsg (
441 Cursor = Packet->Dhcp6.Option;
443 Length = HTONS (ClientId->Length);
444 - Cursor = Dhcp6AppendOption (
446 + Status = Dhcp6AppendOption (
449 HTONS (Dhcp6OptClientId),
453 + if (EFI_ERROR (Status)) {
458 // ServerId is extracted from packet, it's network order.
460 - Cursor = Dhcp6AppendOption (
462 + Status = Dhcp6AppendOption (
465 HTONS (Dhcp6OptServerId),
469 + if (EFI_ERROR (Status)) {
473 - Cursor = Dhcp6AppendETOption (
475 + Status = Dhcp6AppendETOption (
481 + if (EFI_ERROR (Status)) {
485 - Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);
486 + Status = Dhcp6AppendIaOption (
492 + Packet->Dhcp6.Header.MessageType
494 + if (EFI_ERROR (Status)) {
499 - // Determine the size/length of packet
501 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
502 ASSERT (Packet->Size > Packet->Length + 8);
505 // Callback to user with the packet to be sent and check the user's feedback.
507 Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);
509 if (EFI_ERROR (Status)) {
516 @@ -1461,16 +1541,22 @@ Dhcp6SendReleaseMsg (
517 Instance->IaCb.Ia->State = Dhcp6Releasing;
519 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
521 if (EFI_ERROR (Status)) {
528 // Enqueue the sent packet for the retransmission in case reply timeout.
530 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
542 @@ -1524,12 +1610,14 @@ Dhcp6SendRenewRebindMsg (
543 UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
548 // Create the Dhcp6 packet and initialize common fields.
550 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
551 if (Packet == NULL) {
552 - return EFI_OUT_OF_RESOURCES;
553 + Status = EFI_OUT_OF_RESOURCES;
557 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
558 @@ -1543,26 +1631,38 @@ Dhcp6SendRenewRebindMsg (
559 Cursor = Packet->Dhcp6.Option;
561 Length = HTONS (ClientId->Length);
562 - Cursor = Dhcp6AppendOption (
564 + Status = Dhcp6AppendOption (
567 HTONS (Dhcp6OptClientId),
571 + if (EFI_ERROR (Status)) {
575 - Cursor = Dhcp6AppendETOption (
577 + Status = Dhcp6AppendETOption (
583 + if (EFI_ERROR (Status)) {
587 - Cursor = Dhcp6AppendIaOption (
589 + Status = Dhcp6AppendIaOption (
595 Packet->Dhcp6.Header.MessageType
597 + if (EFI_ERROR (Status)) {
601 if (!RebindRequest) {
603 @@ -1578,18 +1678,22 @@ Dhcp6SendRenewRebindMsg (
606 if (Option == NULL) {
608 - return EFI_DEVICE_ERROR;
609 + Status = EFI_DEVICE_ERROR;
613 ServerId = (EFI_DHCP6_DUID *)(Option + 2);
615 - Cursor = Dhcp6AppendOption (
617 + Status = Dhcp6AppendOption (
620 HTONS (Dhcp6OptServerId),
624 + if (EFI_ERROR (Status)) {
630 @@ -1597,18 +1701,19 @@ Dhcp6SendRenewRebindMsg (
632 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
633 UserOpt = Instance->Config->OptionList[Index];
634 - Cursor = Dhcp6AppendOption (
636 + Status = Dhcp6AppendOption (
643 + if (EFI_ERROR (Status)) {
649 - // Determine the size/length of packet.
651 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
653 ASSERT (Packet->Size > Packet->Length + 8);
656 @@ -1618,10 +1723,8 @@ Dhcp6SendRenewRebindMsg (
657 Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;
659 Status = Dhcp6CallbackUser (Instance, Event, &Packet);
661 if (EFI_ERROR (Status)) {
668 @@ -1638,16 +1741,22 @@ Dhcp6SendRenewRebindMsg (
669 Instance->StartTime = 0;
671 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
673 if (EFI_ERROR (Status)) {
680 // Enqueue the sent packet for the retransmission in case reply timeout.
682 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
694 @@ -1811,7 +1920,8 @@ Dhcp6SendInfoRequestMsg (
696 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
697 if (Packet == NULL) {
698 - return EFI_OUT_OF_RESOURCES;
699 + Status = EFI_OUT_OF_RESOURCES;
703 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
704 @@ -1828,44 +1938,56 @@ Dhcp6SendInfoRequestMsg (
707 Length = HTONS (ClientId->Length);
708 - Cursor = Dhcp6AppendOption (
710 + Status = Dhcp6AppendOption (
713 HTONS (Dhcp6OptClientId),
717 + if (EFI_ERROR (Status)) {
722 - Cursor = Dhcp6AppendETOption (
724 + Status = Dhcp6AppendETOption (
730 + if (EFI_ERROR (Status)) {
734 - Cursor = Dhcp6AppendOption (
736 + Status = Dhcp6AppendOption (
739 OptionRequest->OpCode,
740 OptionRequest->OpLen,
743 + if (EFI_ERROR (Status)) {
748 // Append user-defined when configurate Dhcp6 service.
750 for (Index = 0; Index < OptionCount; Index++) {
751 UserOpt = OptionList[Index];
752 - Cursor = Dhcp6AppendOption (
754 + Status = Dhcp6AppendOption (
761 + if (EFI_ERROR (Status)) {
767 - // Determine the size/length of packet.
769 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
770 ASSERT (Packet->Size > Packet->Length + 8);
773 @@ -1877,16 +1999,22 @@ Dhcp6SendInfoRequestMsg (
774 // Send info-request packet with no state.
776 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
778 if (EFI_ERROR (Status)) {
785 // Enqueue the sent packet for the retransmission in case reply timeout.
787 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);
799 @@ -1937,7 +2065,8 @@ Dhcp6SendConfirmMsg (
801 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
802 if (Packet == NULL) {
803 - return EFI_OUT_OF_RESOURCES;
804 + Status = EFI_OUT_OF_RESOURCES;
808 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
809 @@ -1951,54 +2080,64 @@ Dhcp6SendConfirmMsg (
810 Cursor = Packet->Dhcp6.Option;
812 Length = HTONS (ClientId->Length);
813 - Cursor = Dhcp6AppendOption (
815 + Status = Dhcp6AppendOption (
818 HTONS (Dhcp6OptClientId),
822 + if (EFI_ERROR (Status)) {
826 - Cursor = Dhcp6AppendETOption (
828 + Status = Dhcp6AppendETOption (
834 + if (EFI_ERROR (Status)) {
838 - Cursor = Dhcp6AppendIaOption (
840 + Status = Dhcp6AppendIaOption (
846 Packet->Dhcp6.Header.MessageType
848 + if (EFI_ERROR (Status)) {
853 // Append user-defined when configurate Dhcp6 service.
855 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
856 UserOpt = Instance->Config->OptionList[Index];
857 - Cursor = Dhcp6AppendOption (
859 + Status = Dhcp6AppendOption (
866 + if (EFI_ERROR (Status)) {
872 - // Determine the size/length of packet.
874 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
875 ASSERT (Packet->Size > Packet->Length + 8);
878 // Callback to user with the packet to be sent and check the user's feedback.
880 Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);
882 if (EFI_ERROR (Status)) {
889 @@ -2012,16 +2151,22 @@ Dhcp6SendConfirmMsg (
890 Instance->StartTime = 0;
892 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
894 if (EFI_ERROR (Status)) {
901 // Enqueue the sent packet for the retransmission in case reply timeout.
903 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
915 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
916 index e6368b5b1c..8f4bd1eb0f 100644
917 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
918 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.c
919 @@ -142,12 +142,12 @@ Dhcp6GenerateClientId (
922 Status = gRT->SetVariable (
924 - &gEfiDhcp6ServiceBindingProtocolGuid,
925 - (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
930 + &gEfiDhcp6ServiceBindingProtocolGuid,
931 + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
935 if (EFI_ERROR (Status)) {
938 @@ -192,10 +192,10 @@ Dhcp6CopyConfigData (
942 - DstCfg->SolicitRetransmission,
943 - SorCfg->SolicitRetransmission,
944 - sizeof (EFI_DHCP6_RETRANSMISSION)
946 + DstCfg->SolicitRetransmission,
947 + SorCfg->SolicitRetransmission,
948 + sizeof (EFI_DHCP6_RETRANSMISSION)
952 if ((SorCfg->OptionList != NULL) && (SorCfg->OptionCount != 0)) {
953 @@ -221,10 +221,10 @@ Dhcp6CopyConfigData (
957 - DstCfg->OptionList[Index],
958 - SorCfg->OptionList[Index],
961 + DstCfg->OptionList[Index],
962 + SorCfg->OptionList[Index],
968 @@ -422,10 +422,10 @@ Dhcp6CheckAddress (
970 for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
972 - &Addresses[Index1],
973 - &Ia->IaAddress[Index2],
974 - sizeof (EFI_IPv6_ADDRESS)
976 + &Addresses[Index1],
977 + &Ia->IaAddress[Index2],
978 + sizeof (EFI_IPv6_ADDRESS)
983 @@ -503,28 +503,28 @@ Dhcp6DepriveAddress (
985 for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
987 - &Addresses[Index1],
988 - &Ia->IaAddress[Index2],
989 - sizeof (EFI_IPv6_ADDRESS)
991 + &Addresses[Index1],
992 + &Ia->IaAddress[Index2],
993 + sizeof (EFI_IPv6_ADDRESS)
997 // Copy the deprived address to the copy of Ia
1000 - &IaCopy->IaAddress[Index1],
1001 - &Ia->IaAddress[Index2],
1002 - sizeof (EFI_DHCP6_IA_ADDRESS)
1004 + &IaCopy->IaAddress[Index1],
1005 + &Ia->IaAddress[Index2],
1006 + sizeof (EFI_DHCP6_IA_ADDRESS)
1009 // Delete the deprived address from the instance Ia
1011 if (Index2 + 1 < Ia->IaAddressCount) {
1013 - &Ia->IaAddress[Index2],
1014 - &Ia->IaAddress[Index2 + 1],
1015 - (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
1017 + &Ia->IaAddress[Index2],
1018 + &Ia->IaAddress[Index2 + 1],
1019 + (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
1024 @@ -577,24 +577,33 @@ Dhcp6OnTransmitted (
1028 - Append the option to Buf, and move Buf to the end.
1029 + Append the option to Buf, update the length of packet, and move Buf to the end.
1031 - @param[in, out] Buf The pointer to the buffer.
1032 - @param[in] OptType The option type.
1033 - @param[in] OptLen The length of option contents.
1034 - @param[in] Data The pointer to the option content.
1035 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1037 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1038 + will be moved to the end of the option.
1039 + @param[in] OptType The option type.
1040 + @param[in] OptLen The length of option contents.
1041 + @param[in] Data The pointer to the option content.
1043 - @return Buf The position to append the next option.
1044 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1045 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1046 + @retval EFI_SUCCESS The option is appended successfully.
1052 - IN OUT UINT8 *Buf,
1053 - IN UINT16 OptType,
1056 + IN OUT EFI_DHCP6_PACKET *Packet,
1057 + IN OUT UINT8 **PacketCursor,
1058 + IN UINT16 OptType,
1064 + UINT32 BytesNeeded;
1067 // The format of Dhcp6 option:
1069 @@ -607,35 +616,95 @@ Dhcp6AppendOption (
1070 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1073 - ASSERT (OptLen != 0);
1075 + // Verify the arguments are valid
1077 + if (Packet == NULL) {
1078 + return EFI_INVALID_PARAMETER;
1081 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1082 + return EFI_INVALID_PARAMETER;
1085 + if (Data == NULL) {
1086 + return EFI_INVALID_PARAMETER;
1089 + if (OptLen == 0) {
1090 + return EFI_INVALID_PARAMETER;
1094 + // Verify the PacketCursor is within the packet
1096 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1097 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1099 + return EFI_INVALID_PARAMETER;
1103 + // Calculate the bytes needed for the option
1105 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS(OptLen);
1107 - WriteUnaligned16 ((UINT16 *)Buf, OptType);
1109 - WriteUnaligned16 ((UINT16 *)Buf, OptLen);
1111 - CopyMem (Buf, Data, NTOHS (OptLen));
1112 - Buf += NTOHS (OptLen);
1114 + // Space remaining in the packet
1116 + Length = Packet->Size - Packet->Length;
1117 + if (Length < BytesNeeded) {
1118 + return EFI_BUFFER_TOO_SMALL;
1122 + // Verify the PacketCursor is within the packet
1124 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1125 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1127 + return EFI_INVALID_PARAMETER;
1131 + WriteUnaligned16 ((UINT16 *)*PacketCursor, OptType);
1132 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1133 + WriteUnaligned16 ((UINT16 *)*PacketCursor, OptLen);
1134 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1135 + CopyMem (*PacketCursor, Data, NTOHS (OptLen));
1136 + *PacketCursor += NTOHS (OptLen);
1138 + // Update the packet length by the length of the option + 4 bytes
1139 + Packet->Length += BytesNeeded;
1141 + return EFI_SUCCESS;
1145 Append the appointed IA Address option to Buf, and move Buf to the end.
1147 - @param[in, out] Buf The pointer to the position to append.
1148 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1150 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1151 + will be moved to the end of the option.
1152 @param[in] IaAddr The pointer to the IA Address.
1153 @param[in] MessageType Message type of DHCP6 package.
1155 - @return Buf The position to append the next option.
1156 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1157 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1158 + @retval EFI_SUCCESS The option is appended successfully.
1163 Dhcp6AppendIaAddrOption (
1164 - IN OUT UINT8 *Buf,
1165 + IN OUT EFI_DHCP6_PACKET *Packet,
1166 + IN OUT UINT8 **PacketCursor,
1167 IN EFI_DHCP6_IA_ADDRESS *IaAddr,
1168 IN UINT32 MessageType
1171 + UINT32 BytesNeeded;
1174 // The format of the IA Address option is:
1177 @@ -657,17 +726,60 @@ Dhcp6AppendIaAddrOption (
1179 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1182 + // Verify the arguments are valid
1184 + if (Packet == NULL) {
1185 + return EFI_INVALID_PARAMETER;
1188 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1189 + return EFI_INVALID_PARAMETER;
1192 + if (IaAddr == NULL) {
1193 + return EFI_INVALID_PARAMETER;
1197 + // Verify the PacketCursor is within the packet
1199 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1200 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1202 + return EFI_INVALID_PARAMETER;
1205 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1206 + BytesNeeded += sizeof (EFI_IPv6_ADDRESS);
1208 + // Even if the preferred-lifetime is 0, it still needs to store it.
1210 + BytesNeeded += sizeof (IaAddr->PreferredLifetime);
1212 + // Even if the valid-lifetime is 0, it still needs to store it.
1214 + BytesNeeded += sizeof (IaAddr->ValidLifetime);
1217 + // Space remaining in the packet
1219 + Length = Packet->Size - Packet->Length;
1220 + if (Length < BytesNeeded) {
1221 + return EFI_BUFFER_TOO_SMALL;
1225 // Fill the value of Ia Address option type
1227 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));
1229 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr));
1230 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1232 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
1234 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
1235 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1237 - CopyMem (Buf, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
1238 - Buf += sizeof (EFI_IPv6_ADDRESS);
1239 + CopyMem (*PacketCursor, &IaAddr->IpAddress, sizeof (EFI_IPv6_ADDRESS));
1240 + *PacketCursor += sizeof (EFI_IPv6_ADDRESS);
1243 // Fill the value of preferred-lifetime and valid-lifetime.
1244 @@ -675,44 +787,58 @@ Dhcp6AppendIaAddrOption (
1245 // should set to 0 when initiate a Confirm message.
1247 if (MessageType != Dhcp6MsgConfirm) {
1248 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));
1249 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime));
1253 + *PacketCursor += sizeof (IaAddr->PreferredLifetime);
1255 if (MessageType != Dhcp6MsgConfirm) {
1256 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));
1257 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime));
1261 + *PacketCursor += sizeof (IaAddr->ValidLifetime);
1264 + // Update the packet length
1266 + Packet->Length += BytesNeeded;
1269 + return EFI_SUCCESS;
1273 Append the appointed Ia option to Buf, and move Buf to the end.
1275 - @param[in, out] Buf The pointer to the position to append.
1276 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1278 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1279 + will be moved to the end of the option.
1280 @param[in] Ia The pointer to the Ia.
1281 @param[in] T1 The time of T1.
1282 @param[in] T2 The time of T2.
1283 @param[in] MessageType Message type of DHCP6 package.
1285 - @return Buf The position to append the next Ia option.
1286 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1287 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1288 + @retval EFI_SUCCESS The option is appended successfully.
1293 Dhcp6AppendIaOption (
1294 - IN OUT UINT8 *Buf,
1295 - IN EFI_DHCP6_IA *Ia,
1298 - IN UINT32 MessageType
1299 + IN OUT EFI_DHCP6_PACKET *Packet,
1300 + IN OUT UINT8 **PacketCursor,
1301 + IN EFI_DHCP6_IA *Ia,
1304 + IN UINT32 MessageType
1313 + UINT32 BytesNeeded;
1315 + EFI_STATUS Status;
1318 // The format of IA_NA and IA_TA option:
1319 @@ -733,32 +859,74 @@ Dhcp6AppendIaOption (
1320 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1324 + // Verify the arguments are valid
1326 + if (Packet == NULL) {
1327 + return EFI_INVALID_PARAMETER;
1330 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1331 + return EFI_INVALID_PARAMETER;
1335 + return EFI_INVALID_PARAMETER;
1339 + // Verify the PacketCursor is within the packet
1341 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1342 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1344 + return EFI_INVALID_PARAMETER;
1347 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1348 + BytesNeeded += sizeof (Ia->Descriptor.IaId);
1350 + // + N for the IA_NA-options/IA_TA-options
1351 + // Dhcp6AppendIaAddrOption will need to check the length for each address
1353 + if (Ia->Descriptor.Type == Dhcp6OptIana) {
1354 + BytesNeeded += sizeof (T1) + sizeof (T2);
1358 + // Space remaining in the packet
1360 + Length = (UINT16)(Packet->Size - Packet->Length);
1361 + if (Length < BytesNeeded) {
1362 + return EFI_BUFFER_TOO_SMALL;
1366 // Fill the value of Ia option type
1368 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));
1370 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type));
1371 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1374 // Fill the len of Ia option later, keep the pointer first
1376 - Len = (UINT16 *)Buf;
1378 + Len = (UINT16 *)*PacketCursor;
1379 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1382 // Fill the value of iaid
1384 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));
1386 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId));
1387 + *PacketCursor += sizeof (Ia->Descriptor.IaId);
1390 // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
1392 if (Ia->Descriptor.Type == Dhcp6OptIana) {
1393 - WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
1395 - WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
1397 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T1 != 0) ? T1 : 0xffffffff));
1398 + *PacketCursor += sizeof (T1);
1399 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL ((T2 != 0) ? T2 : 0xffffffff));
1400 + *PacketCursor += sizeof (T2);
1404 @@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
1406 for (Index = 0; Index < Ia->IaAddressCount; Index++) {
1407 AddrOpt = (UINT8 *)Ia->IaAddress + Index * sizeof (EFI_DHCP6_IA_ADDRESS);
1408 - Buf = Dhcp6AppendIaAddrOption (Buf, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
1409 + Status = Dhcp6AppendIaAddrOption (Packet, PacketCursor, (EFI_DHCP6_IA_ADDRESS *)AddrOpt, MessageType);
1410 + if (EFI_ERROR (Status)) {
1416 // Fill the value of Ia option length
1418 - *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));
1419 + *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
1423 + // Update the packet length
1425 + Packet->Length += BytesNeeded;
1427 + return EFI_SUCCESS;
1431 Append the appointed Elapsed time option to Buf, and move Buf to the end.
1433 - @param[in, out] Buf The pointer to the position to append.
1434 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1435 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1436 + will be moved to the end of the option.
1437 @param[in] Instance The pointer to the Dhcp6 instance.
1438 @param[out] Elapsed The pointer to the elapsed time value in
1439 - the generated packet.
1440 + the generated packet.
1442 - @return Buf The position to append the next Ia option.
1443 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1444 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1445 + @retval EFI_SUCCESS The option is appended successfully.
1450 Dhcp6AppendETOption (
1451 - IN OUT UINT8 *Buf,
1452 - IN DHCP6_INSTANCE *Instance,
1453 - OUT UINT16 **Elapsed
1454 + IN OUT EFI_DHCP6_PACKET *Packet,
1455 + IN OUT UINT8 **PacketCursor,
1456 + IN DHCP6_INSTANCE *Instance,
1457 + OUT UINT16 **Elapsed
1460 + UINT32 BytesNeeded;
1464 // The format of elapsed time option:
1466 @@ -806,27 +990,70 @@ Dhcp6AppendETOption (
1467 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1471 + // Verify the arguments are valid
1473 + if (Packet == NULL) {
1474 + return EFI_INVALID_PARAMETER;
1477 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1478 + return EFI_INVALID_PARAMETER;
1481 + if (Instance == NULL) {
1482 + return EFI_INVALID_PARAMETER;
1485 + if ((Elapsed == NULL)) {
1486 + return EFI_INVALID_PARAMETER;
1490 + // Verify the PacketCursor is within the packet
1492 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1493 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1495 + return EFI_INVALID_PARAMETER;
1498 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1500 + // + 2 for elapsed-time
1502 + BytesNeeded += sizeof (UINT16);
1504 + // Space remaining in the packet
1506 + Length = Packet->Size - Packet->Length;
1507 + if (Length < BytesNeeded) {
1508 + return EFI_BUFFER_TOO_SMALL;
1512 // Fill the value of elapsed-time option type.
1514 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));
1516 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime));
1517 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1520 // Fill the len of elapsed-time option, which is fixed.
1522 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));
1524 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2));
1525 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1528 // Fill in elapsed time value with 0 value for now. The actual value is
1529 // filled in later just before the packet is transmitted.
1531 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));
1532 - *Elapsed = (UINT16 *)Buf;
1534 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0));
1535 + *Elapsed = (UINT16 *)*PacketCursor;
1536 + *PacketCursor += sizeof (UINT16);
1538 + Packet->Length += BytesNeeded;
1541 + return EFI_SUCCESS;
1545 @@ -852,13 +1079,13 @@ SetElapsedTime (
1547 gRT->GetTime (&Time, NULL);
1548 CurrentStamp = MultU64x32 (
1549 - ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
1552 + ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
1564 // Sentinel value of 0 means that this is the first DHCP packet that we are
1565 @@ -1290,11 +1517,11 @@ Dhcp6GetMappingTimeOut (
1567 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
1568 Status = Ip6Cfg->GetData (
1570 - Ip6ConfigDataTypeDupAddrDetectTransmits,
1575 + Ip6ConfigDataTypeDupAddrDetectTransmits,
1579 if (EFI_ERROR (Status)) {
1582 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
1583 index 046454ff4a..06947f6c1f 100644
1584 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
1585 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Utility.h
1586 @@ -160,69 +160,85 @@ Dhcp6OnTransmitted (
1590 - Append the appointed option to the buf, and move the buf to the end.
1592 - @param[in, out] Buf The pointer to buffer.
1593 - @param[in] OptType The option type.
1594 - @param[in] OptLen The length of option content.s
1595 - @param[in] Data The pointer to the option content.
1597 - @return Buf The position to append the next option.
1599 + Append the option to Buf, update the length of packet, and move Buf to the end.
1601 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1603 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1604 + will be moved to the end of the option.
1605 + @param[in] OptType The option type.
1606 + @param[in] OptLen The length of option contents.
1607 + @param[in] Data The pointer to the option content.
1609 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1610 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1611 + @retval EFI_SUCCESS The option is appended successfully.
1616 - IN OUT UINT8 *Buf,
1617 - IN UINT16 OptType,
1620 + IN OUT EFI_DHCP6_PACKET *Packet,
1621 + IN OUT UINT8 **PacketCursor,
1622 + IN UINT16 OptType,
1628 - Append the Ia option to Buf, and move Buf to the end.
1630 - @param[in, out] Buf The pointer to the position to append.
1631 + Append the appointed Ia option to Buf, update the Ia option length, and move Buf
1632 + to the end of the option.
1633 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1635 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1636 + will be moved to the end of the option.
1637 @param[in] Ia The pointer to the Ia.
1638 @param[in] T1 The time of T1.
1639 @param[in] T2 The time of T2.
1640 @param[in] MessageType Message type of DHCP6 package.
1642 - @return Buf The position to append the next Ia option.
1644 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1645 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1646 + @retval EFI_SUCCESS The option is appended successfully.
1650 Dhcp6AppendIaOption (
1651 - IN OUT UINT8 *Buf,
1652 - IN EFI_DHCP6_IA *Ia,
1655 - IN UINT32 MessageType
1656 + IN OUT EFI_DHCP6_PACKET *Packet,
1657 + IN OUT UINT8 **PacketCursor,
1658 + IN EFI_DHCP6_IA *Ia,
1661 + IN UINT32 MessageType
1665 Append the appointed Elapsed time option to Buf, and move Buf to the end.
1667 - @param[in, out] Buf The pointer to the position to append.
1668 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1669 + @param[in, out] PacketCursor The pointer in the packet, on success PacketCursor
1670 + will be moved to the end of the option.
1671 @param[in] Instance The pointer to the Dhcp6 instance.
1672 @param[out] Elapsed The pointer to the elapsed time value in
1673 the generated packet.
1675 - @return Buf The position to append the next Ia option.
1676 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1677 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1678 + @retval EFI_SUCCESS The option is appended successfully.
1683 Dhcp6AppendETOption (
1684 - IN OUT UINT8 *Buf,
1685 - IN DHCP6_INSTANCE *Instance,
1686 - OUT UINT16 **Elapsed
1687 + IN OUT EFI_DHCP6_PACKET *Packet,
1688 + IN OUT UINT8 **PacketCursor,
1689 + IN DHCP6_INSTANCE *Instance,
1690 + OUT UINT16 **Elapsed
1694 Set the elapsed time based on the given instance and the pointer to the
1695 elapsed time option.
1697 - @param[in] Elapsed The pointer to the position to append.
1698 - @param[in] Instance The pointer to the Dhcp6 instance.
1699 + @retval EFI_INVALID_PARAMETER An argument provided to the function was invalid
1700 + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to append the option.
1701 + @retval EFI_SUCCESS The option is appended successfully.
1709 From 1bd40aba86eecc8acc07547e6d14e563590b1074 Mon Sep 17 00:00:00 2001
1710 From: Doug Flick <dougflick@microsoft.com>
1711 Date: Fri, 15 Dec 2023 11:26:04 -0800
1712 Subject: [PATCH 02/12] SECURITY PATCH TCBZ4535 - CVE-2023-45230 - Host Based
1716 .../GoogleTest/Dhcp6DxeGoogleTest.cpp | 27 +
1717 .../GoogleTest/Dhcp6DxeGoogleTest.inf | 44 ++
1718 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 478 ++++++++++++++++++
1719 NetworkPkg/NetworkPkg.ci.yaml | 3 +
1720 NetworkPkg/Test/NetworkPkgHostTest.dsc | 102 ++++
1721 5 files changed, 654 insertions(+)
1722 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
1723 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
1724 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
1725 create mode 100644 NetworkPkg/Test/NetworkPkgHostTest.dsc
1727 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
1728 new file mode 100644
1729 index 0000000000..b1fe72e195
1731 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
1734 + Acts as the main entry point for the tests for the Dhcp6Dxe module.
1736 + Copyright (c) Microsoft Corporation
1737 + SPDX-License-Identifier: BSD-2-Clause-Patent
1739 +#include <gtest/gtest.h>
1741 +////////////////////////////////////////////////////////////////////////////////
1742 +// Add test files here
1743 +// Google Test will only pick up the tests from the files that are included
1745 +////////////////////////////////////////////////////////////////////////////////
1746 +#include "Dhcp6IoGoogleTest.cpp"
1748 +////////////////////////////////////////////////////////////////////////////////
1750 +////////////////////////////////////////////////////////////////////////////////
1757 + testing::InitGoogleTest (&argc, argv);
1758 + return RUN_ALL_TESTS ();
1760 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
1761 new file mode 100644
1762 index 0000000000..c7ec42b322
1764 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
1767 +# Unit test suite for the Dhcp6Dxe using Google Test
1769 +# Copyright (c) Microsoft Corporation.<BR>
1770 +# SPDX-License-Identifier: BSD-2-Clause-Patent
1773 + INF_VERSION = 0x00010017
1774 + BASE_NAME = Dhcp6DxeGoogleTest
1775 + FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9
1776 + VERSION_STRING = 1.0
1777 + MODULE_TYPE = HOST_APPLICATION
1779 +# The following information is for reference only and not required by the build tools.
1781 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
1784 + Dhcp6DxeGoogleTest.cpp
1785 + Dhcp6IoGoogleTest.cpp
1792 + MdeModulePkg/MdeModulePkg.dec
1793 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
1794 + NetworkPkg/NetworkPkg.dec
1803 + gEfiDhcp6ServiceBindingProtocolGuid
1806 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
1810 \ No newline at end of file
1811 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
1812 new file mode 100644
1813 index 0000000000..dad6a42b12
1815 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
1818 + Tests for Dhcp6Io.c.
1820 + Copyright (c) Microsoft Corporation
1821 + SPDX-License-Identifier: BSD-2-Clause-Patent
1823 +#include <gtest/gtest.h>
1827 + #include <Library/BaseLib.h>
1828 + #include <Library/DebugLib.h>
1829 + #include <Library/BaseMemoryLib.h>
1830 + #include "../Dhcp6Impl.h"
1831 + #include "../Dhcp6Utility.h"
1834 +////////////////////////////////////////////////////////////////////////
1836 +////////////////////////////////////////////////////////////////////////
1838 +#define DHCP6_PACKET_MAX_LEN 1500
1840 +////////////////////////////////////////////////////////////////////////
1841 +////////////////////////////////////////////////////////////////////////
1842 +// Symbol Definitions
1843 +// These functions are not directly under test - but required to compile
1844 +////////////////////////////////////////////////////////////////////////
1846 +// This definition is used by this test but is also required to compile
1848 +EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {
1849 + { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }
1854 +UdpIoSendDatagram (
1856 + IN NET_BUF *Packet,
1857 + IN UDP_END_POINT *EndPoint OPTIONAL,
1858 + IN EFI_IP_ADDRESS *Gateway OPTIONAL,
1859 + IN UDP_IO_CALLBACK CallBack,
1863 + return EFI_SUCCESS;
1868 +UdpIoRecvDatagram (
1870 + IN UDP_IO_CALLBACK CallBack,
1875 + return EFI_SUCCESS;
1878 +////////////////////////////////////////////////////////////////////////
1879 +// Dhcp6AppendOptionTest Tests
1880 +////////////////////////////////////////////////////////////////////////
1882 +class Dhcp6AppendOptionTest : public ::testing::Test {
1884 + UINT8 *Buffer = NULL;
1885 + EFI_DHCP6_PACKET *Packet;
1888 + // Add any setup code if needed
1893 + // Initialize any resources or variables
1894 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
1895 + ASSERT_NE (Buffer, (UINT8 *)NULL);
1897 + Packet = (EFI_DHCP6_PACKET *)Buffer;
1898 + Packet->Size = DHCP6_PACKET_MAX_LEN;
1901 + // Add any cleanup code if needed
1906 + // Clean up any resources or variables
1907 + if (Buffer != NULL) {
1908 + FreePool (Buffer);
1913 +// Test Description:
1914 +// Attempt to append an option to a packet that is too small by a duid that is too large
1915 +TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {
1917 + EFI_DHCP6_DUID *UntrustedDuid;
1918 + EFI_STATUS Status;
1920 + UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
1921 + ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
1923 + UntrustedDuid->Length = NTOHS (0xFFFF);
1925 + Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
1927 + Status = Dhcp6AppendOption (
1928 + Dhcp6AppendOptionTest::Packet,
1930 + HTONS (Dhcp6OptServerId),
1931 + UntrustedDuid->Length,
1932 + UntrustedDuid->Duid
1935 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
1938 +// Test Description:
1939 +// Attempt to append an option to a packet that is large enough
1940 +TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
1942 + EFI_DHCP6_DUID *UntrustedDuid;
1943 + EFI_STATUS Status;
1944 + UINTN OriginalLength;
1946 + UINT8 Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
1948 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
1949 + OriginalLength = Packet->Length;
1951 + UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
1952 + ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
1954 + UntrustedDuid->Length = NTOHS (sizeof (Duid));
1955 + CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid));
1957 + Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
1959 + Status = Dhcp6AppendOption (
1960 + Dhcp6AppendOptionTest::Packet,
1962 + HTONS (Dhcp6OptServerId),
1963 + UntrustedDuid->Length,
1964 + UntrustedDuid->Duid
1967 + ASSERT_EQ (Status, EFI_SUCCESS);
1969 + // verify that the pointer to cursor moved by the expected amount
1970 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4);
1972 + // verify that the length of the packet is now the expected amount
1973 + ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4);
1976 +////////////////////////////////////////////////////////////////////////
1977 +// Dhcp6AppendETOption Tests
1978 +////////////////////////////////////////////////////////////////////////
1980 +class Dhcp6AppendETOptionTest : public ::testing::Test {
1982 + UINT8 *Buffer = NULL;
1983 + EFI_DHCP6_PACKET *Packet;
1986 + // Add any setup code if needed
1991 + // Initialize any resources or variables
1992 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
1993 + ASSERT_NE (Buffer, (UINT8 *)NULL);
1995 + Packet = (EFI_DHCP6_PACKET *)Buffer;
1996 + Packet->Size = DHCP6_PACKET_MAX_LEN;
1997 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2000 + // Add any cleanup code if needed
2005 + // Clean up any resources or variables
2006 + if (Buffer != NULL) {
2007 + FreePool (Buffer);
2012 +// Test Description:
2013 +// Attempt to append an option to a packet that is too small by a duid that is too large
2014 +TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
2016 + EFI_STATUS Status;
2017 + DHCP6_INSTANCE Instance;
2018 + UINT16 ElapsedTimeVal;
2019 + UINT16 *ElapsedTime;
2021 + Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
2022 + ElapsedTime = &ElapsedTimeVal;
2024 + Packet->Length = Packet->Size - 2;
2026 + Status = Dhcp6AppendETOption (
2027 + Dhcp6AppendETOptionTest::Packet,
2029 + &Instance, // Instance is not used in this function
2033 + // verify that we error out because the packet is too small for the option header
2034 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2036 + // reset the length
2037 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2040 +// Test Description:
2041 +// Attempt to append an option to a packet that is large enough
2042 +TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
2044 + EFI_STATUS Status;
2045 + DHCP6_INSTANCE Instance;
2046 + UINT16 ElapsedTimeVal;
2047 + UINT16 *ElapsedTime;
2048 + UINTN ExpectedSize;
2049 + UINTN OriginalLength;
2051 + Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
2052 + ElapsedTime = &ElapsedTimeVal;
2054 + OriginalLength = Packet->Length;
2056 + Status = Dhcp6AppendETOption (
2057 + Dhcp6AppendETOptionTest::Packet,
2059 + &Instance, // Instance is not used in this function
2063 + // verify that the status is EFI_SUCCESS
2064 + ASSERT_EQ (Status, EFI_SUCCESS);
2066 + // verify that the pointer to cursor moved by the expected amount
2067 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2069 + // verify that the length of the packet is now the expected amount
2070 + ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2073 +////////////////////////////////////////////////////////////////////////
2074 +// Dhcp6AppendIaOption Tests
2075 +////////////////////////////////////////////////////////////////////////
2077 +class Dhcp6AppendIaOptionTest : public ::testing::Test {
2079 + UINT8 *Buffer = NULL;
2080 + EFI_DHCP6_PACKET *Packet;
2084 + // Add any setup code if needed
2089 + // Initialize any resources or variables
2090 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
2091 + ASSERT_NE (Buffer, (UINT8 *)NULL);
2093 + Packet = (EFI_DHCP6_PACKET *)Buffer;
2094 + Packet->Size = DHCP6_PACKET_MAX_LEN;
2096 + Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);
2097 + ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);
2099 + CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
2100 + CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
2102 + Ia->IaAddressCount = 2;
2105 + // Add any cleanup code if needed
2110 + // Clean up any resources or variables
2111 + if (Buffer != NULL) {
2112 + FreePool (Buffer);
2121 +// Test Description:
2122 +// Attempt to append an option to a packet that doesn't have enough space
2123 +// for the option header
2124 +TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {
2126 + EFI_STATUS Status;
2128 + Packet->Length = Packet->Size - 2;
2130 + Ia->Descriptor.Type = Dhcp6OptIana;
2131 + Ia->Descriptor.IaId = 0x12345678;
2133 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2135 + Status = Dhcp6AppendIaOption (
2136 + Dhcp6AppendIaOptionTest::Packet,
2144 + // verify that we error out because the packet is too small for the option header
2145 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2147 + // reset the length
2148 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2151 +// Test Description:
2152 +// Attempt to append an option to a packet that doesn't have enough space
2153 +// for the option header
2154 +TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) {
2156 + EFI_STATUS Status;
2158 + // Use up nearly all the space in the packet
2159 + Packet->Length = Packet->Size - 2;
2161 + Ia->Descriptor.Type = Dhcp6OptIata;
2162 + Ia->Descriptor.IaId = 0x12345678;
2164 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2166 + Status = Dhcp6AppendIaOption (
2167 + Dhcp6AppendIaOptionTest::Packet,
2175 + // verify that we error out because the packet is too small for the option header
2176 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2178 + // reset the length
2179 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2182 +TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {
2184 + EFI_STATUS Status;
2185 + UINTN ExpectedSize;
2186 + UINTN OriginalLength;
2189 + // 2 bytes for the option header type
2193 + // 2 bytes for the option header length
2195 + ExpectedSize += 2;
2197 + // 4 bytes for the IAID
2199 + ExpectedSize += 4;
2201 + // + 4 bytes for the T1
2203 + ExpectedSize += 4;
2205 + // + 4 bytes for the T2
2207 + ExpectedSize += 4;
2209 + // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2210 + // + 2 bytes for the option header type
2211 + // + 2 bytes for the option header length
2212 + // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address
2214 + ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2216 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2218 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2219 + OriginalLength = Packet->Length;
2221 + Ia->Descriptor.Type = Dhcp6OptIana;
2222 + Ia->Descriptor.IaId = 0x12345678;
2224 + Status = Dhcp6AppendIaOption (
2225 + Dhcp6AppendIaOptionTest::Packet,
2233 + // verify that the pointer to cursor moved by the expected amount
2234 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2236 + // verify that the length of the packet is now the expected amount
2237 + ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2239 + // verify that the status is EFI_SUCCESS
2240 + ASSERT_EQ (Status, EFI_SUCCESS);
2243 +TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
2245 + EFI_STATUS Status;
2246 + UINTN ExpectedSize;
2247 + UINTN OriginalLength;
2250 + // 2 bytes for the option header type
2254 + // 2 bytes for the option header length
2256 + ExpectedSize += 2;
2258 + // 4 bytes for the IAID
2260 + ExpectedSize += 4;
2262 + // + (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2263 + // + 2 bytes for the option header type
2264 + // + 2 bytes for the option header length
2265 + // + sizeof (EFI_DHCP6_IA_ADDRESS) for the IA Address
2267 + ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2269 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2271 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2272 + OriginalLength = Packet->Length;
2274 + Ia->Descriptor.Type = Dhcp6OptIata;
2275 + Ia->Descriptor.IaId = 0x12345678;
2277 + Status = Dhcp6AppendIaOption (
2278 + Dhcp6AppendIaOptionTest::Packet,
2286 + // verify that the pointer to cursor moved by the expected amount
2287 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2289 + // verify that the length of the packet is now the expected amount
2290 + ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2292 + // verify that the status is EFI_SUCCESS
2293 + ASSERT_EQ (Status, EFI_SUCCESS);
2295 diff --git a/NetworkPkg/NetworkPkg.ci.yaml b/NetworkPkg/NetworkPkg.ci.yaml
2296 index 07dc7abd69..e82e0c6256 100644
2297 --- a/NetworkPkg/NetworkPkg.ci.yaml
2298 +++ b/NetworkPkg/NetworkPkg.ci.yaml
2301 "DscPath": "NetworkPkg.dsc"
2303 + "HostUnitTestCompilerPlugin": {
2304 + "DscPath": "Test/NetworkPkgHostTest.dsc"
2306 "CharEncodingCheck": {
2309 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
2310 new file mode 100644
2311 index 0000000000..5befdf7688
2313 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
2316 +# NetworkPkgHostTest DSC file used to build host-based unit tests.
2318 +# Copyright (c) Microsoft Corporation.<BR>
2319 +# SPDX-License-Identifier: BSD-2-Clause-Patent
2323 + PLATFORM_NAME = NetworkPkgHostTest
2324 + PLATFORM_GUID = 3b68324e-fc07-4d49-9520-9347ede65879
2325 + PLATFORM_VERSION = 0.1
2326 + DSC_SPECIFICATION = 0x00010005
2327 + OUTPUT_DIRECTORY = Build/NetworkPkg/HostTest
2328 + SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
2329 + BUILD_TARGETS = NOOPT
2330 + SKUID_IDENTIFIER = DEFAULT
2332 +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
2335 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
2339 + # Build HOST_APPLICATION that tests NetworkPkg
2341 + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
2343 +# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
2345 + NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
2346 + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
2347 + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
2348 + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
2349 + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
2350 + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
2351 + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
2352 + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
2353 + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
2354 + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
2355 + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
2356 + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
2357 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
2358 + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
2359 + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
2360 + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
2361 + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
2362 + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
2363 + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
2364 + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
2365 + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
2366 + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
2367 + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
2368 + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
2369 +!ifdef CONTINUOUS_INTEGRATION
2370 + BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
2371 + TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
2373 + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
2374 + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
2375 + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
2377 + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
2378 + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
2379 + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
2380 + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
2381 + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
2383 +!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
2384 +[LibraryClasses.X64]
2385 + # Provide StackCookie support lib so that we can link to /GS exports for VS builds
2386 + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
2387 + NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf
2390 +[LibraryClasses.common.UEFI_DRIVER]
2391 + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
2392 + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
2393 + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
2394 +[LibraryClasses.common.UEFI_APPLICATION]
2395 + DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
2396 + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
2397 +[LibraryClasses.ARM, LibraryClasses.AARCH64]
2399 + # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
2400 + # This library provides the instrinsic functions generated by a given compiler.
2401 + # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
2404 +!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
2405 + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
2408 + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
2409 +[LibraryClasses.ARM]
2410 + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
2411 +[LibraryClasses.RISCV64]
2412 + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
2415 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
2416 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
2417 \ No newline at end of file
2422 From 9613e15be77676e119291f28ae46cb13bf37f235 Mon Sep 17 00:00:00 2001
2423 From: Doug Flick <dougflick@microsoft.com>
2424 Date: Fri, 15 Dec 2023 11:26:47 -0800
2425 Subject: [PATCH 03/12] SECURITY PATCH TCBZ4534 - CVE-2023-45229 - Patch
2428 NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 134 ++++++++++++++++++---
2429 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 202 ++++++++++++++++++++++----------
2430 2 files changed, 257 insertions(+), 79 deletions(-)
2432 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
2433 index b552331767..5247b324ac 100644
2434 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
2435 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h
2436 @@ -45,6 +45,20 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
2437 #define DHCP6_SERVICE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'S')
2438 #define DHCP6_INSTANCE_SIGNATURE SIGNATURE_32 ('D', 'H', '6', 'I')
2440 +#define DHCP6_PACKET_ALL 0
2441 +#define DHCP6_PACKET_STATEFUL 1
2442 +#define DHCP6_PACKET_STATELESS 2
2444 +#define DHCP6_BASE_PACKET_SIZE 1024
2446 +#define DHCP6_PORT_CLIENT 546
2447 +#define DHCP6_PORT_SERVER 547
2449 +#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
2451 +#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
2452 +#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
2455 // For more information on DHCP options see RFC 8415, Section 21.1
2457 @@ -59,8 +73,8 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
2458 // | (option-len octets) |
2459 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2461 -#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
2462 -#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
2463 +#define DHCP6_SIZE_OF_OPT_CODE (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode))
2464 +#define DHCP6_SIZE_OF_OPT_LEN (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))
2466 // Combined size of Code and Length
2467 #define DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN (DHCP6_SIZE_OF_OPT_CODE + \
2468 @@ -72,31 +86,121 @@ STATIC_ASSERT (
2471 // Offset to the length is just past the code
2472 -#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
2473 +#define DHCP6_OFFSET_OF_OPT_LEN(a) (a + DHCP6_SIZE_OF_OPT_CODE)
2475 - DHCP6_OPT_LEN_OFFSET (0) == 2,
2476 + DHCP6_OFFSET_OF_OPT_LEN (0) == 2,
2477 "Offset of length is + 2 past start of option"
2480 -#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
2481 +#define DHCP6_OFFSET_OF_OPT_DATA(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
2483 - DHCP6_OPT_DATA_OFFSET(0) == 4,
2484 + DHCP6_OFFSET_OF_OPT_DATA(0) == 4,
2485 "Offset to option data should be +4 from start of option"
2488 +// Identity Association options (both NA (Non-Temporary) and TA (Temporary Association))
2489 +// are defined in RFC 8415 and are a deriviation of a TLV stucture
2490 +// For more information on IA_NA see Section 21.4
2491 +// For more information on IA_TA see Section 21.5
2494 +// The format of IA_NA and IA_TA option:
2496 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2497 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2498 +// | OPTION_IA_NA | option-len |
2499 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2500 +// | IAID (4 octets) |
2501 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2502 +// | T1 (only for IA_NA) |
2503 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2504 +// | T2 (only for IA_NA) |
2505 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2507 +// . IA_NA-options/IA_TA-options .
2509 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2511 +#define DHCP6_SIZE_OF_IAID (sizeof(UINT32))
2512 +#define DHCP6_SIZE_OF_TIME_INTERVAL (sizeof(UINT32))
2514 -#define DHCP6_PACKET_ALL 0
2515 -#define DHCP6_PACKET_STATEFUL 1
2516 -#define DHCP6_PACKET_STATELESS 2
2517 +// Combined size of IAID, T1, and T2
2518 +#define DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 (DHCP6_SIZE_OF_IAID + \
2519 + DHCP6_SIZE_OF_TIME_INTERVAL + \
2520 + DHCP6_SIZE_OF_TIME_INTERVAL)
2522 + DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12,
2523 + "Combined size of IAID, T1, T2 must be 12 per RFC 8415"
2526 -#define DHCP6_BASE_PACKET_SIZE 1024
2527 +// This is the size of IA_TA without options
2528 +#define DHCP6_MIN_SIZE_OF_IA_TA (DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
2529 + DHCP6_SIZE_OF_IAID)
2531 + DHCP6_MIN_SIZE_OF_IA_TA == 8,
2532 + "Minimum combined size of IA_TA per RFC 8415"
2535 -#define DHCP6_PORT_CLIENT 546
2536 -#define DHCP6_PORT_SERVER 547
2537 +// Offset to a IA_TA inner option
2538 +#define DHCP6_OFFSET_OF_IA_TA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_TA)
2540 + DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8,
2541 + "Offset of IA_TA Inner option is + 8 past start of option"
2544 -#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
2545 +// This is the size of IA_NA without options (16)
2546 +#define DHCP6_MIN_SIZE_OF_IA_NA DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
2547 + DHCP6_SIZE_OF_COMBINED_IAID_T1_T2
2549 + DHCP6_MIN_SIZE_OF_IA_NA == 16,
2550 + "Minimum combined size of IA_TA per RFC 8415"
2553 -#define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
2554 -#define DHCP6_SERVICE_FROM_THIS(Service) CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
2555 +#define DHCP6_OFFSET_OF_IA_NA_INNER_OPT(a) (a + DHCP6_MIN_SIZE_OF_IA_NA)
2557 + DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16,
2558 + "Offset of IA_NA Inner option is + 16 past start of option"
2561 +#define DHCP6_OFFSET_OF_IA_NA_T1(a) (a + \
2562 + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
2563 + DHCP6_SIZE_OF_IAID)
2565 + DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8,
2566 + "Offset of IA_NA Inner option is + 8 past start of option"
2569 +#define DHCP6_OFFSET_OF_IA_NA_T2(a) (a + \
2570 + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN +\
2571 + DHCP6_SIZE_OF_IAID + \
2572 + DHCP6_SIZE_OF_TIME_INTERVAL)
2574 + DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12,
2575 + "Offset of IA_NA Inner option is + 12 past start of option"
2579 +// For more information see RFC 8415 Section 21.13
2581 +// The format of the Status Code Option:
2584 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2585 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2586 +// | OPTION_STATUS_CODE | option-len |
2587 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2588 +// | status-code | |
2589 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2591 +// . status-message .
2593 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2595 +#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
2597 + DHCP6_OFFSET_OF_STATUS_CODE (0) == 4,
2598 + "Offset of status is + 4 past start of option"
2601 extern EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress;
2602 extern EFI_DHCP6_PROTOCOL gDhcp6ProtocolTemplate;
2603 diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
2604 index 1401910950..f96b4c7962 100644
2605 --- a/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
2606 +++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Io.c
2607 @@ -598,8 +598,9 @@ Dhcp6UpdateIaInfo (
2608 // The inner options still start with 2 bytes option-code and 2 bytes option-len.
2610 if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
2611 - T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8)));
2612 - T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12)));
2614 + T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1(Option))));
2615 + T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2(Option))));
2617 // Refer to RFC3155 Chapter 22.4. If a client receives an IA_NA with T1 greater than T2,
2618 // and both T1 and T2 are greater than 0, the client discards the IA_NA option and processes
2619 @@ -609,13 +610,14 @@ Dhcp6UpdateIaInfo (
2620 return EFI_DEVICE_ERROR;
2623 - IaInnerOpt = Option + 16;
2624 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 12);
2625 + IaInnerOpt = DHCP6_OFFSET_OF_IA_NA_INNER_OPT(Option);
2626 + IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option)))) - DHCP6_SIZE_OF_COMBINED_IAID_T1_T2);
2630 - IaInnerOpt = Option + 8;
2631 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4);
2633 + IaInnerOpt = DHCP6_OFFSET_OF_IA_TA_INNER_OPT(Option);
2634 + IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option)))) - DHCP6_SIZE_OF_IAID);
2638 @@ -641,7 +643,7 @@ Dhcp6UpdateIaInfo (
2639 Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
2641 if (Option != NULL) {
2642 - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
2643 + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option))));
2644 if (StsCode != Dhcp6StsSuccess) {
2645 return EFI_DEVICE_ERROR;
2647 @@ -661,6 +663,88 @@ Dhcp6UpdateIaInfo (
2652 + Seeks the Inner Options from a DHCP6 Option
2654 + @param[in] IaType The type of the IA option.
2655 + @param[in] Option The pointer to the DHCP6 Option.
2656 + @param[in] OptionLen The length of the DHCP6 Option.
2657 + @param[out] IaInnerOpt The pointer to the IA inner option.
2658 + @param[out] IaInnerLen The length of the IA inner option.
2660 + @retval EFI_SUCCESS Seek the inner option successfully.
2661 + @retval EFI_DEVICE_ERROR The OptionLen is invalid. On Error,
2662 + the pointers are not modified
2665 +Dhcp6SeekInnerOptionSafe (
2668 + IN UINT32 OptionLen,
2669 + OUT UINT8 **IaInnerOpt,
2670 + OUT UINT16 *IaInnerLen
2674 + UINT16 IaInnerLenTmp;
2675 + UINT8 *IaInnerOptTmp;
2677 + if (Option == NULL) {
2678 + ASSERT (Option != NULL);
2679 + return EFI_DEVICE_ERROR;
2682 + if (IaInnerOpt == NULL) {
2683 + ASSERT (IaInnerOpt != NULL);
2684 + return EFI_DEVICE_ERROR;
2687 + if (IaInnerLen == NULL) {
2688 + ASSERT (IaInnerLen != NULL);
2689 + return EFI_DEVICE_ERROR;
2692 + if (IaType == Dhcp6OptIana) {
2693 + // Verify we have a fully formed IA_NA
2694 + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_NA) {
2695 + return EFI_DEVICE_ERROR;
2699 + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT(Option);
2701 + // Verify the IaInnerLen is valid.
2702 + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)DHCP6_OFFSET_OF_OPT_LEN(Option)));
2703 + if (IaInnerLenTmp < DHCP6_SIZE_OF_COMBINED_IAID_T1_T2) {
2704 + return EFI_DEVICE_ERROR;
2707 + IaInnerLenTmp -= DHCP6_SIZE_OF_COMBINED_IAID_T1_T2;
2708 + } else if (IaType == Dhcp6OptIata) {
2709 + // Verify the OptionLen is valid.
2710 + if (OptionLen < DHCP6_MIN_SIZE_OF_IA_TA) {
2711 + return EFI_DEVICE_ERROR;
2714 + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT(Option);
2716 + // Verify the IaInnerLen is valid.
2717 + IaInnerLenTmp = (UINT16)NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_OPT_LEN(Option))));
2718 + if (IaInnerLenTmp < DHCP6_SIZE_OF_IAID) {
2719 + return EFI_DEVICE_ERROR;
2722 + IaInnerLenTmp -= DHCP6_SIZE_OF_IAID;
2724 + return EFI_DEVICE_ERROR;
2727 + *IaInnerOpt = IaInnerOptTmp;
2728 + *IaInnerLen = IaInnerLenTmp;
2730 + return EFI_SUCCESS;
2734 Seek StatusCode Option in package. A Status Code option may appear in the
2735 options field of a DHCP message and/or in the options field of another option.
2736 @@ -684,6 +768,12 @@ Dhcp6SeekStsOption (
2742 + // OptionLen is the length of the Options excluding the DHCP header.
2743 + // Length of the EFI_DHCP6_PACKET from the first byte of the Header field to the last
2744 + // byte of the Option[] field.
2745 + OptionLen = Packet->Length - sizeof (Packet->Dhcp6.Header);
2748 // Seek StatusCode option directly in DHCP message body. That is, search in
2749 @@ -691,12 +781,12 @@ Dhcp6SeekStsOption (
2751 *Option = Dhcp6SeekOption (
2752 Packet->Dhcp6.Option,
2753 - Packet->Length - 4,
2758 if (*Option != NULL) {
2759 - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
2760 + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(DHCP6_OFFSET_OF_STATUS_CODE(*Option))));
2761 if (StsCode != Dhcp6StsSuccess) {
2762 return EFI_DEVICE_ERROR;
2764 @@ -707,7 +797,7 @@ Dhcp6SeekStsOption (
2766 *Option = Dhcp6SeekIaOption (
2767 Packet->Dhcp6.Option,
2768 - Packet->Length - sizeof (EFI_DHCP6_HEADER),
2770 &Instance->Config->IaDescriptor
2772 if (*Option == NULL) {
2773 @@ -715,52 +805,35 @@ Dhcp6SeekStsOption (
2777 - // The format of the IA_NA option is:
2778 + // Calculate the distance from Packet->Dhcp6.Option to the IA option.
2781 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2782 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2783 - // | OPTION_IA_NA | option-len |
2784 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2785 - // | IAID (4 octets) |
2786 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2788 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2790 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2792 - // . IA_NA-options .
2794 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2795 + // Packet->Size and Packet->Length are both UINT32 type, and Packet->Size is
2796 + // the size of the whole packet, including the DHCP header, and Packet->Length
2797 + // is the length of the DHCP message body, excluding the DHCP header.
2799 - // The format of the IA_TA option is:
2800 + // (*Option - Packet->Dhcp6.Option) is the number of bytes from the start of
2801 + // DHCP6 option area to the start of the IA option.
2804 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2805 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2806 - // | OPTION_IA_TA | option-len |
2807 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2808 - // | IAID (4 octets) |
2809 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2811 - // . IA_TA-options .
2813 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2814 + // Dhcp6SeekInnerOptionSafe() is searching starting from the start of the
2815 + // IA option to the end of the DHCP6 option area, thus subtract the space
2816 + // up until this option
2818 + OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option);
2821 - // sizeof (option-code + option-len + IaId) = 8
2822 - // sizeof (option-code + option-len + IaId + T1) = 12
2823 - // sizeof (option-code + option-len + IaId + T1 + T2) = 16
2824 + // Seek the inner option
2826 - // The inner options still start with 2 bytes option-code and 2 bytes option-len.
2828 - if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
2829 - IaInnerOpt = *Option + 16;
2830 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12);
2832 - IaInnerOpt = *Option + 8;
2833 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4);
2835 + Dhcp6SeekInnerOptionSafe (
2836 + Instance->Config->IaDescriptor.Type,
2844 + return EFI_DEVICE_ERROR;
2848 @@ -784,7 +857,7 @@ Dhcp6SeekStsOption (
2850 *Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
2851 if (*Option != NULL) {
2852 - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 4)));
2853 + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE(*Option)))));
2854 if (StsCode != Dhcp6StsSuccess) {
2855 return EFI_DEVICE_ERROR;
2857 @@ -1105,7 +1178,7 @@ Dhcp6SendRequestMsg (
2859 Option = Dhcp6SeekOption (
2860 Instance->AdSelect->Dhcp6.Option,
2861 - Instance->AdSelect->Length - 4,
2862 + Instance->AdSelect->Length - sizeof(EFI_DHCP6_HEADER),
2865 if (Option == NULL) {
2866 @@ -1289,7 +1362,7 @@ Dhcp6SendDeclineMsg (
2868 Option = Dhcp6SeekOption (
2869 LastReply->Dhcp6.Option,
2870 - LastReply->Length - 4,
2871 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2874 if (Option == NULL) {
2875 @@ -1448,7 +1521,7 @@ Dhcp6SendReleaseMsg (
2877 Option = Dhcp6SeekOption (
2878 LastReply->Dhcp6.Option,
2879 - LastReply->Length - 4,
2880 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2883 if (Option == NULL) {
2884 @@ -1674,7 +1747,7 @@ Dhcp6SendRenewRebindMsg (
2886 Option = Dhcp6SeekOption (
2887 LastReply->Dhcp6.Option,
2888 - LastReply->Length - 4,
2889 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2892 if (Option == NULL) {
2893 @@ -2210,7 +2283,7 @@ Dhcp6HandleReplyMsg (
2895 Option = Dhcp6SeekOption (
2896 Packet->Dhcp6.Option,
2897 - Packet->Length - 4,
2898 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2902 @@ -2356,7 +2429,7 @@ Dhcp6HandleReplyMsg (
2904 // Any error status code option is found.
2906 - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
2907 + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE(Option)))));
2909 case Dhcp6StsUnspecFail:
2911 @@ -2489,7 +2562,7 @@ Dhcp6SelectAdvertiseMsg (
2913 Option = Dhcp6SeekOption (
2914 AdSelect->Dhcp6.Option,
2915 - AdSelect->Length - 4,
2916 + AdSelect->Length - sizeof(EFI_DHCP6_HEADER),
2917 Dhcp6OptServerUnicast
2920 @@ -2500,7 +2573,7 @@ Dhcp6SelectAdvertiseMsg (
2921 return EFI_OUT_OF_RESOURCES;
2924 - CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS));
2925 + CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA(Option), sizeof (EFI_IPv6_ADDRESS));
2929 @@ -2553,7 +2626,7 @@ Dhcp6HandleAdvertiseMsg (
2931 Option = Dhcp6SeekOption (
2932 Packet->Dhcp6.Option,
2933 - Packet->Length - 4,
2934 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2938 @@ -2647,7 +2720,8 @@ Dhcp6HandleAdvertiseMsg (
2939 CopyMem (Instance->AdSelect, Packet, Packet->Size);
2941 if (Option != NULL) {
2942 - Instance->AdPref = *(Option + 4);
2943 + Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA(Option));
2948 @@ -2716,11 +2790,11 @@ Dhcp6HandleStateful (
2950 Option = Dhcp6SeekOption (
2951 Packet->Dhcp6.Option,
2952 - Packet->Length - 4,
2953 + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
2957 - if ((Option == NULL) || (CompareMem (Option + 4, ClientId->Duid, ClientId->Length) != 0)) {
2958 + if ((Option == NULL) || (CompareMem (DHCP6_OFFSET_OF_OPT_DATA(Option), ClientId->Duid, ClientId->Length) != 0)) {
2962 @@ -2729,7 +2803,7 @@ Dhcp6HandleStateful (
2964 Option = Dhcp6SeekOption (
2965 Packet->Dhcp6.Option,
2966 - Packet->Length - 4,
2967 + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
2971 @@ -2834,7 +2908,7 @@ Dhcp6HandleStateless (
2973 Option = Dhcp6SeekOption (
2974 Packet->Dhcp6.Option,
2975 - Packet->Length - 4,
2976 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2984 From ac0130907b8a88cca3c4d8eb590f3b4aa33133d8 Mon Sep 17 00:00:00 2001
2985 From: Doug Flick <dougflick@microsoft.com>
2986 Date: Fri, 15 Dec 2023 13:31:38 -0800
2987 Subject: [PATCH 04/12] SECURITY PATCH TCBZ4534 - CVE-2023-45229 - Host Based
2991 .../GoogleTest/Dhcp6DxeGoogleTest.cpp | 54 +-
2992 .../GoogleTest/Dhcp6DxeGoogleTest.inf | 86 +--
2993 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp | 631 ++++++++++++++----
2994 .../Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h | 58 ++
2995 NetworkPkg/Test/NetworkPkgHostTest.dsc | 204 +++---
2996 5 files changed, 726 insertions(+), 307 deletions(-)
2997 create mode 100644 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
2999 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
3000 index b1fe72e195..36fd708cfc 100644
3001 --- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
3002 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
3005 - Acts as the main entry point for the tests for the Dhcp6Dxe module.
3007 - Copyright (c) Microsoft Corporation
3008 - SPDX-License-Identifier: BSD-2-Clause-Patent
3010 -#include <gtest/gtest.h>
3012 -////////////////////////////////////////////////////////////////////////////////
3013 -// Add test files here
3014 -// Google Test will only pick up the tests from the files that are included
3016 -////////////////////////////////////////////////////////////////////////////////
3017 -#include "Dhcp6IoGoogleTest.cpp"
3019 -////////////////////////////////////////////////////////////////////////////////
3021 -////////////////////////////////////////////////////////////////////////////////
3028 - testing::InitGoogleTest (&argc, argv);
3029 - return RUN_ALL_TESTS ();
3032 + Acts as the main entry point for the tests for the Dhcp6Dxe module.
3034 + Copyright (c) Microsoft Corporation
3035 + SPDX-License-Identifier: BSD-2-Clause-Patent
3037 +#include <gtest/gtest.h>
3039 +////////////////////////////////////////////////////////////////////////////////
3040 +// Add test files here
3041 +// Google Test will only pick up the tests from the files that are included
3043 +////////////////////////////////////////////////////////////////////////////////
3044 +#include "Dhcp6IoGoogleTest.cpp"
3046 +////////////////////////////////////////////////////////////////////////////////
3048 +////////////////////////////////////////////////////////////////////////////////
3055 + testing::InitGoogleTest (&argc, argv);
3056 + return RUN_ALL_TESTS ();
3058 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
3059 index c7ec42b322..b74497b6b3 100644
3060 --- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
3061 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
3064 -# Unit test suite for the Dhcp6Dxe using Google Test
3066 -# Copyright (c) Microsoft Corporation.<BR>
3067 -# SPDX-License-Identifier: BSD-2-Clause-Patent
3070 - INF_VERSION = 0x00010017
3071 - BASE_NAME = Dhcp6DxeGoogleTest
3072 - FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9
3073 - VERSION_STRING = 1.0
3074 - MODULE_TYPE = HOST_APPLICATION
3076 -# The following information is for reference only and not required by the build tools.
3078 -# VALID_ARCHITECTURES = IA32 X64 AARCH64
3081 - Dhcp6DxeGoogleTest.cpp
3082 - Dhcp6IoGoogleTest.cpp
3089 - MdeModulePkg/MdeModulePkg.dec
3090 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3091 - NetworkPkg/NetworkPkg.dec
3100 - gEfiDhcp6ServiceBindingProtocolGuid
3103 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
3107 +# Unit test suite for the Dhcp6Dxe using Google Test
3109 +# Copyright (c) Microsoft Corporation.<BR>
3110 +# SPDX-License-Identifier: BSD-2-Clause-Patent
3113 + INF_VERSION = 0x00010017
3114 + BASE_NAME = Dhcp6DxeGoogleTest
3115 + FILE_GUID = 1D2A4C65-38C8-4C2F-BB60-B5FA49625AA9
3116 + VERSION_STRING = 1.0
3117 + MODULE_TYPE = HOST_APPLICATION
3119 +# The following information is for reference only and not required by the build tools.
3121 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
3124 + Dhcp6DxeGoogleTest.cpp
3125 + Dhcp6IoGoogleTest.cpp
3132 + MdeModulePkg/MdeModulePkg.dec
3133 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3134 + NetworkPkg/NetworkPkg.dec
3143 + gEfiDhcp6ServiceBindingProtocolGuid
3146 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
3150 \ No newline at end of file
3151 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
3152 index dad6a42b12..31e848543d 100644
3153 --- a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
3154 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
3156 #include <gtest/gtest.h>
3160 - #include <Library/BaseLib.h>
3161 - #include <Library/DebugLib.h>
3162 - #include <Library/BaseMemoryLib.h>
3163 - #include "../Dhcp6Impl.h"
3164 - #include "../Dhcp6Utility.h"
3166 +#include <Library/BaseLib.h>
3167 +#include <Library/DebugLib.h>
3168 +#include <Library/BaseMemoryLib.h>
3169 +#include "../Dhcp6Impl.h"
3170 +#include "../Dhcp6Utility.h"
3171 +#include "Dhcp6IoGoogleTest.h"
3174 ////////////////////////////////////////////////////////////////////////
3175 @@ -21,7 +22,35 @@ extern "C" {
3177 #define DHCP6_PACKET_MAX_LEN 1500
3179 +// This definition is used by this test but is also required to compile
3181 +#define DHCPV6_OPTION_IA_NA 3
3182 +#define DHCPV6_OPTION_IA_TA 4
3184 +#define SEARCH_PATTERN 0xDEADC0DE
3185 +#define SEARCH_PATTERN_LEN sizeof(SEARCH_PATTERN)
3187 ////////////////////////////////////////////////////////////////////////
3188 +// Test structures for IA_NA and IA_TA options
3189 +////////////////////////////////////////////////////////////////////////
3197 + DHCPv6_OPTION Header;
3200 + UINT8 InnerOptions[0];
3201 +} DHCPv6_OPTION_IA_NA;
3204 + DHCPv6_OPTION Header;
3205 + UINT8 InnerOptions[0];
3206 +} DHCPv6_OPTION_IA_TA;
3208 ////////////////////////////////////////////////////////////////////////
3209 // Symbol Definitions
3210 // These functions are not directly under test - but required to compile
3211 @@ -65,33 +94,33 @@ UdpIoRecvDatagram (
3213 class Dhcp6AppendOptionTest : public ::testing::Test {
3215 - UINT8 *Buffer = NULL;
3216 - EFI_DHCP6_PACKET *Packet;
3217 +UINT8 *Buffer = NULL;
3218 +EFI_DHCP6_PACKET *Packet;
3221 - // Add any setup code if needed
3226 - // Initialize any resources or variables
3227 - Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3228 - ASSERT_NE (Buffer, (UINT8 *)NULL);
3230 - Packet = (EFI_DHCP6_PACKET *)Buffer;
3231 - Packet->Size = DHCP6_PACKET_MAX_LEN;
3233 +// Add any setup code if needed
3238 + // Initialize any resources or variables
3239 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3240 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3242 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3243 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3246 - // Add any cleanup code if needed
3251 - // Clean up any resources or variables
3252 - if (Buffer != NULL) {
3253 - FreePool (Buffer);
3255 +// Add any cleanup code if needed
3260 + // Clean up any resources or variables
3261 + if (Buffer != NULL) {
3262 + FreePool (Buffer);
3267 // Test Description:
3268 @@ -109,12 +138,12 @@ TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {
3269 Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
3271 Status = Dhcp6AppendOption (
3272 - Dhcp6AppendOptionTest::Packet,
3274 - HTONS (Dhcp6OptServerId),
3275 - UntrustedDuid->Length,
3276 - UntrustedDuid->Duid
3278 + Dhcp6AppendOptionTest::Packet,
3280 + HTONS (Dhcp6OptServerId),
3281 + UntrustedDuid->Length,
3282 + UntrustedDuid->Duid
3285 ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
3287 @@ -141,12 +170,12 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
3288 Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
3290 Status = Dhcp6AppendOption (
3291 - Dhcp6AppendOptionTest::Packet,
3293 - HTONS (Dhcp6OptServerId),
3294 - UntrustedDuid->Length,
3295 - UntrustedDuid->Duid
3297 + Dhcp6AppendOptionTest::Packet,
3299 + HTONS (Dhcp6OptServerId),
3300 + UntrustedDuid->Length,
3301 + UntrustedDuid->Duid
3304 ASSERT_EQ (Status, EFI_SUCCESS);
3306 @@ -163,34 +192,34 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
3308 class Dhcp6AppendETOptionTest : public ::testing::Test {
3310 - UINT8 *Buffer = NULL;
3311 - EFI_DHCP6_PACKET *Packet;
3312 +UINT8 *Buffer = NULL;
3313 +EFI_DHCP6_PACKET *Packet;
3316 - // Add any setup code if needed
3321 - // Initialize any resources or variables
3322 - Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3323 - ASSERT_NE (Buffer, (UINT8 *)NULL);
3325 - Packet = (EFI_DHCP6_PACKET *)Buffer;
3326 - Packet->Size = DHCP6_PACKET_MAX_LEN;
3327 - Packet->Length = sizeof (EFI_DHCP6_HEADER);
3329 +// Add any setup code if needed
3334 + // Initialize any resources or variables
3335 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3336 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3338 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3339 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3340 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
3343 - // Add any cleanup code if needed
3348 - // Clean up any resources or variables
3349 - if (Buffer != NULL) {
3350 - FreePool (Buffer);
3352 +// Add any cleanup code if needed
3357 + // Clean up any resources or variables
3358 + if (Buffer != NULL) {
3359 + FreePool (Buffer);
3364 // Test Description:
3365 @@ -208,11 +237,11 @@ TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
3366 Packet->Length = Packet->Size - 2;
3368 Status = Dhcp6AppendETOption (
3369 - Dhcp6AppendETOptionTest::Packet,
3371 - &Instance, // Instance is not used in this function
3374 + Dhcp6AppendETOptionTest::Packet,
3376 + &Instance, // Instance is not used in this function
3380 // verify that we error out because the packet is too small for the option header
3381 ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
3382 @@ -238,11 +267,11 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
3383 OriginalLength = Packet->Length;
3385 Status = Dhcp6AppendETOption (
3386 - Dhcp6AppendETOptionTest::Packet,
3388 - &Instance, // Instance is not used in this function
3391 + Dhcp6AppendETOptionTest::Packet,
3393 + &Instance, // Instance is not used in this function
3397 // verify that the status is EFI_SUCCESS
3398 ASSERT_EQ (Status, EFI_SUCCESS);
3399 @@ -260,46 +289,46 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
3401 class Dhcp6AppendIaOptionTest : public ::testing::Test {
3403 - UINT8 *Buffer = NULL;
3404 - EFI_DHCP6_PACKET *Packet;
3406 +UINT8 *Buffer = NULL;
3407 +EFI_DHCP6_PACKET *Packet;
3411 - // Add any setup code if needed
3416 - // Initialize any resources or variables
3417 - Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3418 - ASSERT_NE (Buffer, (UINT8 *)NULL);
3419 +// Add any setup code if needed
3424 + // Initialize any resources or variables
3425 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3426 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3428 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3429 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3431 - Packet = (EFI_DHCP6_PACKET *)Buffer;
3432 - Packet->Size = DHCP6_PACKET_MAX_LEN;
3433 + Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);
3434 + ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);
3436 - Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);
3437 - ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);
3438 + CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
3439 + CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
3441 - CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
3442 - CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
3443 + Ia->IaAddressCount = 2;
3446 - Ia->IaAddressCount = 2;
3447 +// Add any cleanup code if needed
3452 + // Clean up any resources or variables
3453 + if (Buffer != NULL) {
3454 + FreePool (Buffer);
3457 - // Add any cleanup code if needed
3462 - // Clean up any resources or variables
3463 - if (Buffer != NULL) {
3464 - FreePool (Buffer);
3476 // Test Description:
3477 @@ -317,13 +346,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {
3478 Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3480 Status = Dhcp6AppendIaOption (
3481 - Dhcp6AppendIaOptionTest::Packet,
3488 + Dhcp6AppendIaOptionTest::Packet,
3496 // verify that we error out because the packet is too small for the option header
3497 ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
3498 @@ -348,13 +377,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaInvalidDataExpectBufferTooSmall) {
3499 Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3501 Status = Dhcp6AppendIaOption (
3502 - Dhcp6AppendIaOptionTest::Packet,
3509 + Dhcp6AppendIaOptionTest::Packet,
3517 // verify that we error out because the packet is too small for the option header
3518 ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
3519 @@ -406,13 +435,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {
3520 Ia->Descriptor.IaId = 0x12345678;
3522 Status = Dhcp6AppendIaOption (
3523 - Dhcp6AppendIaOptionTest::Packet,
3530 + Dhcp6AppendIaOptionTest::Packet,
3538 // verify that the pointer to cursor moved by the expected amount
3539 ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
3540 @@ -450,7 +479,7 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
3542 ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
3544 - Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3545 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3547 Packet->Length = sizeof (EFI_DHCP6_HEADER);
3548 OriginalLength = Packet->Length;
3549 @@ -459,13 +488,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
3550 Ia->Descriptor.IaId = 0x12345678;
3552 Status = Dhcp6AppendIaOption (
3553 - Dhcp6AppendIaOptionTest::Packet,
3560 + Dhcp6AppendIaOptionTest::Packet,
3568 // verify that the pointer to cursor moved by the expected amount
3569 ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
3570 @@ -476,3 +505,335 @@ TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
3571 // verify that the status is EFI_SUCCESS
3572 ASSERT_EQ (Status, EFI_SUCCESS);
3575 +////////////////////////////////////////////////////////////////////////
3576 +// Dhcp6SeekInnerOptionSafe Tests
3577 +////////////////////////////////////////////////////////////////////////
3579 +// Define a fixture for your tests if needed
3580 +class Dhcp6SeekInnerOptionSafeTest : public ::testing::Test {
3582 +// Add any setup code if needed
3587 + // Initialize any resources or variables
3590 +// Add any cleanup code if needed
3595 + // Clean up any resources or variables
3599 +// Test Description:
3600 +// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IANA option is found.
3601 +TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAValidOptionExpectSuccess) {
3602 + EFI_STATUS Result;
3603 + UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };
3604 + UINT32 OptionLength = sizeof (Option);
3605 + DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option;
3606 + UINT32 SearchPattern = SEARCH_PATTERN;
3608 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3609 + UINT8 *InnerOptionPtr = NULL;
3610 + UINT16 InnerOptionLength = 0;
3612 + OptionPtr->Header.Code = Dhcp6OptIana;
3613 + OptionPtr->Header.Len = HTONS (4 + 12); // Valid length has to be more than 12
3614 + OptionPtr->Header.IAID = 0x12345678;
3615 + OptionPtr->T1 = 0x11111111;
3616 + OptionPtr->T2 = 0x22222222;
3617 + CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
3619 + Result = Dhcp6SeekInnerOptionSafe (
3624 + &InnerOptionLength
3626 + ASSERT_EQ (Result, EFI_SUCCESS);
3627 + ASSERT_EQ (InnerOptionLength, 4);
3628 + ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
3631 +// Test Description:
3632 +// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_DEIVCE_ERROR when the IANA option size is invalid.
3633 +TEST_F (Dhcp6SeekInnerOptionSafeTest, IANAInvalidSizeExpectFail) {
3634 + // Lets add an inner option of bytes we expect to find
3635 + EFI_STATUS Status;
3636 + UINT8 Option[sizeof (DHCPv6_OPTION_IA_NA) + SEARCH_PATTERN_LEN] = { 0 };
3637 + UINT32 OptionLength = sizeof (Option);
3638 + DHCPv6_OPTION_IA_NA *OptionPtr = (DHCPv6_OPTION_IA_NA *)Option;
3639 + UINT32 SearchPattern = SEARCH_PATTERN;
3641 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3642 + UINT8 *InnerOptionPtr = NULL;
3643 + UINT16 InnerOptionLength = 0;
3645 + OptionPtr->Header.Code = Dhcp6OptIana;
3646 + OptionPtr->Header.Len = HTONS (4); // Set the length to lower than expected (12)
3647 + OptionPtr->Header.IAID = 0x12345678;
3648 + OptionPtr->T1 = 0x11111111;
3649 + OptionPtr->T2 = 0x22222222;
3650 + CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
3652 + // Set the InnerOptionLength to be less than the size of the option
3653 + Status = Dhcp6SeekInnerOptionSafe (
3658 + &InnerOptionLength
3660 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3662 + // Now set the OptionLength to be less than the size of the option
3663 + OptionLength = sizeof (DHCPv6_OPTION_IA_NA) - 1;
3664 + Status = Dhcp6SeekInnerOptionSafe (
3669 + &InnerOptionLength
3671 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3674 +// Test Description:
3675 +// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option is found
3676 +TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAValidOptionExpectSuccess) {
3677 + // Lets add an inner option of bytes we expect to find
3678 + EFI_STATUS Status;
3679 + UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
3680 + UINT32 OptionLength = sizeof (Option);
3681 + DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
3682 + UINT32 SearchPattern = SEARCH_PATTERN;
3684 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3685 + UINT8 *InnerOptionPtr = NULL;
3686 + UINT16 InnerOptionLength = 0;
3688 + OptionPtr->Header.Code = Dhcp6OptIata;
3689 + OptionPtr->Header.Len = HTONS (4 + 4); // Valid length has to be more than 4
3690 + OptionPtr->Header.IAID = 0x12345678;
3691 + CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
3693 + Status = Dhcp6SeekInnerOptionSafe (
3698 + &InnerOptionLength
3700 + ASSERT_EQ (Status, EFI_SUCCESS);
3701 + ASSERT_EQ (InnerOptionLength, 4);
3702 + ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
3705 +// Test Description:
3706 +// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.
3707 +TEST_F (Dhcp6SeekInnerOptionSafeTest, IATAInvalidSizeExpectFail) {
3708 + // Lets add an inner option of bytes we expect to find
3709 + EFI_STATUS Status;
3710 + UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
3711 + UINT32 OptionLength = sizeof (Option);
3712 + DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
3713 + UINT32 SearchPattern = SEARCH_PATTERN;
3715 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3716 + UINT8 *InnerOptionPtr = NULL;
3717 + UINT16 InnerOptionLength = 0;
3719 + OptionPtr->Header.Code = Dhcp6OptIata;
3720 + OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4)
3721 + OptionPtr->Header.IAID = 0x12345678;
3722 + CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
3724 + Status = Dhcp6SeekInnerOptionSafe (
3729 + &InnerOptionLength
3731 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3733 + // Now lets try modifying the OptionLength to be less than the size of the option
3734 + OptionLength = sizeof (DHCPv6_OPTION_IA_TA) - 1;
3735 + Status = Dhcp6SeekInnerOptionSafe (
3740 + &InnerOptionLength
3742 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3745 +// Test Description:
3746 +// This test verifies that any other Option Type fails
3747 +TEST_F (Dhcp6SeekInnerOptionSafeTest, InvalidOption) {
3748 + // Lets add an inner option of bytes we expect to find
3749 + EFI_STATUS Result;
3750 + UINT8 Option[sizeof (DHCPv6_OPTION_IA_TA) + SEARCH_PATTERN_LEN] = { 0 };
3751 + UINT32 OptionLength = sizeof (Option);
3752 + DHCPv6_OPTION_IA_TA *OptionPtr = (DHCPv6_OPTION_IA_TA *)Option;
3753 + UINT32 SearchPattern = SEARCH_PATTERN;
3755 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3756 + UINT8 *InnerOptionPtr = NULL;
3757 + UINT16 InnerOptionLength = 0;
3759 + OptionPtr->Header.Code = 0xC0DE;
3760 + OptionPtr->Header.Len = HTONS (2); // Set the length to lower than expected (4)
3761 + OptionPtr->Header.IAID = 0x12345678;
3762 + CopyMem (OptionPtr->InnerOptions, &SearchPattern, SearchPatternLength);
3764 + Result = Dhcp6SeekInnerOptionSafe (0xC0DE, Option, OptionLength, &InnerOptionPtr, &InnerOptionLength);
3765 + ASSERT_EQ (Result, EFI_DEVICE_ERROR);
3768 +////////////////////////////////////////////////////////////////////////
3769 +// Dhcp6SeekStsOption Tests
3770 +////////////////////////////////////////////////////////////////////////
3772 +#define PACKET_SIZE (1500)
3774 +class Dhcp6SeekStsOptionTest : public ::testing::Test {
3776 +DHCP6_INSTANCE Instance = { 0 };
3777 +EFI_DHCP6_PACKET *Packet = NULL;
3778 +EFI_DHCP6_CONFIG_DATA Config = { 0 };
3781 +// Add any setup code if needed
3786 + // Allocate a packet
3787 + Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
3788 + ASSERT_NE (Packet, nullptr);
3790 + // Initialize the packet
3791 + Packet->Size = PACKET_SIZE;
3793 + Instance.Config = &Config;
3796 +// Add any cleanup code if needed
3801 + // Clean up any resources or variables
3802 + FreePool (Packet);
3806 +// Test Description:
3807 +// This test verifies that Dhcp6SeekStsOption returns EFI_DEVICE_ERROR when the option is invalid
3808 +// This verifies that the calling function is working as expected
3809 +TEST_F (Dhcp6SeekStsOptionTest, SeekIATAOptionExpectFail) {
3810 + EFI_STATUS Status;
3811 + UINT8 *Option = NULL;
3812 + UINT32 SearchPattern = SEARCH_PATTERN;
3813 + UINT16 SearchPatternLength = SEARCH_PATTERN_LEN;
3814 + UINT16 *Len = NULL;
3815 + EFI_DHCP6_IA Ia = { 0 };
3817 + Ia.Descriptor.Type = DHCPV6_OPTION_IA_TA;
3818 + Ia.IaAddressCount = 1;
3819 + Ia.IaAddress[0].PreferredLifetime = 0xDEADBEEF;
3820 + Ia.IaAddress[0].ValidLifetime = 0xDEADAAAA;
3821 + Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress;
3823 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
3825 + Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
3827 + // Let's append the option to the packet
3828 + Status = Dhcp6AppendOption (
3829 + Dhcp6SeekStsOptionTest::Packet,
3831 + Dhcp6OptStatusCode,
3832 + SearchPatternLength,
3833 + (UINT8 *)&SearchPattern
3835 + ASSERT_EQ (Status, EFI_SUCCESS);
3837 + // Inner option length - this will be overwritten later
3838 + Len = (UINT16 *)(Option + 2);
3840 + // Fill in the inner IA option
3841 + Status = Dhcp6AppendIaOption (
3842 + Dhcp6SeekStsOptionTest::Packet,
3849 + ASSERT_EQ (Status, EFI_SUCCESS);
3851 + // overwrite the len of inner Ia option
3854 + Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_TA;
3857 + Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
3859 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3862 +// Test Description:
3863 +// This test verifies that Dhcp6SeekInnerOptionSafe returns EFI_SUCCESS when the IATA option size is invalid.
3864 +TEST_F (Dhcp6SeekStsOptionTest, SeekIANAOptionExpectSuccess) {
3865 + EFI_STATUS Status = EFI_NOT_FOUND;
3866 + UINT8 *Option = NULL;
3867 + UINT32 SearchPattern = SEARCH_PATTERN;
3868 + UINT16 SearchPatternLength = SEARCH_PATTERN_LEN;
3869 + EFI_DHCP6_IA Ia = { 0 };
3871 + Ia.Descriptor.Type = DHCPV6_OPTION_IA_NA;
3872 + Ia.IaAddressCount = 1;
3873 + Ia.IaAddress[0].PreferredLifetime = 0x11111111;
3874 + Ia.IaAddress[0].ValidLifetime = 0x22222222;
3875 + Ia.IaAddress[0].IpAddress = mAllDhcpRelayAndServersAddress;
3876 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
3878 + Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
3880 + Status = Dhcp6AppendOption (
3881 + Dhcp6SeekStsOptionTest::Packet,
3883 + Dhcp6OptStatusCode,
3884 + SearchPatternLength,
3885 + (UINT8 *)&SearchPattern
3887 + ASSERT_EQ (Status, EFI_SUCCESS);
3889 + Status = Dhcp6AppendIaOption (
3890 + Dhcp6SeekStsOptionTest::Packet,
3897 + ASSERT_EQ (Status, EFI_SUCCESS);
3899 + Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_NA;
3902 + Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
3904 + ASSERT_EQ (Status, EFI_SUCCESS);
3906 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
3907 new file mode 100644
3908 index 0000000000..c5e38daf9c
3910 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
3913 + Acts as header for private functions under test in Dhcp6Io.c
3915 + Copyright (c) Microsoft Corporation
3916 + SPDX-License-Identifier: BSD-2-Clause-Patent
3919 +#ifndef DHCP6_IO_GOOGLE_TEST_H
3920 +#define DHCP6_IO_GOOGLE_TEST_H
3922 +////////////////////////////////////////////////////////////////////////////////
3923 +// These are the functions that are being unit tested
3924 +////////////////////////////////////////////////////////////////////////////////
3929 + Seeks the Inner Options from a DHCP6 Option
3931 + @param[in] IaType The type of the IA option.
3932 + @param[in] Option The pointer to the DHCP6 Option.
3933 + @param[in] OptionLen The length of the DHCP6 Option.
3934 + @param[out] IaInnerOpt The pointer to the IA inner option.
3935 + @param[out] IaInnerLen The length of the IA inner option.
3937 + @retval EFI_SUCCESS Seek the inner option successfully.
3938 + @retval EFI_DEVICE_ERROR The OptionLen is invalid.
3941 +Dhcp6SeekInnerOptionSafe (
3945 + UINT8 **IaInnerOpt,
3946 + UINT16 *IaInnerLen
3950 + Seek StatusCode Option in package. A Status Code option may appear in the
3951 + options field of a DHCP message and/or in the options field of another option.
3952 + See details in section 22.13, RFC3315.
3954 + @param[in] Instance The pointer to the Dhcp6 instance.
3955 + @param[in] Packet The pointer to reply messages.
3956 + @param[out] Option The pointer to status code option.
3958 + @retval EFI_SUCCESS Seek status code option successfully.
3959 + @retval EFI_DEVICE_ERROR An unexpected error.
3963 +Dhcp6SeekStsOption (
3964 + IN DHCP6_INSTANCE *Instance,
3965 + IN EFI_DHCP6_PACKET *Packet,
3966 + OUT UINT8 **Option
3969 +#endif // DHCP6_IO_GOOGLE_TEST_H
3970 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
3971 index 5befdf7688..f6459b124f 100644
3972 --- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
3973 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
3976 -# NetworkPkgHostTest DSC file used to build host-based unit tests.
3978 -# Copyright (c) Microsoft Corporation.<BR>
3979 -# SPDX-License-Identifier: BSD-2-Clause-Patent
3983 - PLATFORM_NAME = NetworkPkgHostTest
3984 - PLATFORM_GUID = 3b68324e-fc07-4d49-9520-9347ede65879
3985 - PLATFORM_VERSION = 0.1
3986 - DSC_SPECIFICATION = 0x00010005
3987 - OUTPUT_DIRECTORY = Build/NetworkPkg/HostTest
3988 - SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
3989 - BUILD_TARGETS = NOOPT
3990 - SKUID_IDENTIFIER = DEFAULT
3992 -!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
3995 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3999 - # Build HOST_APPLICATION that tests NetworkPkg
4001 - NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4003 -# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4005 - NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
4006 - DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
4007 - BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
4008 - BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
4009 - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
4010 - HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
4011 - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
4012 - PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
4013 - PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
4014 - UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
4015 - UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
4016 - UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
4017 - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
4018 - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
4019 - UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
4020 - UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
4021 - TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
4022 - PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
4023 - PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
4024 - DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
4025 - DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
4026 - SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
4027 - RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
4028 - VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
4029 -!ifdef CONTINUOUS_INTEGRATION
4030 - BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
4031 - TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
4033 - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
4034 - OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
4035 - TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
4037 - DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
4038 - FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
4039 - FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
4040 - SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
4041 - IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
4043 -!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
4044 -[LibraryClasses.X64]
4045 - # Provide StackCookie support lib so that we can link to /GS exports for VS builds
4046 - RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
4047 - NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf
4050 -[LibraryClasses.common.UEFI_DRIVER]
4051 - HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
4052 - ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
4053 - DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
4054 -[LibraryClasses.common.UEFI_APPLICATION]
4055 - DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
4056 - ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
4057 -[LibraryClasses.ARM, LibraryClasses.AARCH64]
4059 - # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
4060 - # This library provides the instrinsic functions generated by a given compiler.
4061 - # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
4064 -!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
4065 - NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
4068 - NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
4069 -[LibraryClasses.ARM]
4070 - RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
4071 -[LibraryClasses.RISCV64]
4072 - RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
4075 - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
4076 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
4077 \ No newline at end of file
4079 +# NetworkPkgHostTest DSC file used to build host-based unit tests.
4081 +# Copyright (c) Microsoft Corporation.<BR>
4082 +# SPDX-License-Identifier: BSD-2-Clause-Patent
4086 + PLATFORM_NAME = NetworkPkgHostTest
4087 + PLATFORM_GUID = 3b68324e-fc07-4d49-9520-9347ede65879
4088 + PLATFORM_VERSION = 0.1
4089 + DSC_SPECIFICATION = 0x00010005
4090 + OUTPUT_DIRECTORY = Build/NetworkPkg/HostTest
4091 + SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
4092 + BUILD_TARGETS = NOOPT
4093 + SKUID_IDENTIFIER = DEFAULT
4095 +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
4098 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
4102 + # Build HOST_APPLICATION that tests NetworkPkg
4104 + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4106 +# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4108 + NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
4109 + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
4110 + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
4111 + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
4112 + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
4113 + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
4114 + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
4115 + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
4116 + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
4117 + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
4118 + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
4119 + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
4120 + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
4121 + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
4122 + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
4123 + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
4124 + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
4125 + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
4126 + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
4127 + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
4128 + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
4129 + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
4130 + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
4131 + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
4132 +!ifdef CONTINUOUS_INTEGRATION
4133 + BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
4134 + TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
4136 + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
4137 + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
4138 + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
4140 + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
4141 + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
4142 + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
4143 + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
4144 + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
4146 +!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
4147 +[LibraryClasses.X64]
4148 + # Provide StackCookie support lib so that we can link to /GS exports for VS builds
4149 + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
4150 + NULL|MdePkg/Library/BaseBinSecurityLibRng/BaseBinSecurityLibRng.inf
4153 +[LibraryClasses.common.UEFI_DRIVER]
4154 + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
4155 + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
4156 + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
4157 +[LibraryClasses.common.UEFI_APPLICATION]
4158 + DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
4159 + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
4160 +[LibraryClasses.ARM, LibraryClasses.AARCH64]
4162 + # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
4163 + # This library provides the instrinsic functions generated by a given compiler.
4164 + # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
4167 +!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
4168 + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
4171 + NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
4172 +[LibraryClasses.ARM]
4173 + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
4174 +[LibraryClasses.RISCV64]
4175 + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
4178 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
4179 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
4184 From d74c1be05f439ab3b94ac50f8b46cece775c8ee7 Mon Sep 17 00:00:00 2001
4185 From: Doug Flick <dougflick@microsoft.com>
4186 Date: Fri, 15 Dec 2023 13:32:28 -0800
4187 Subject: [PATCH 05/12] SECURITY PATCH TCBZ4536 - CVE-2023-45231 - Patch
4190 NetworkPkg/Ip6Dxe/Ip6Option.c | 112 ++++++++++++++++++----------------
4191 1 file changed, 60 insertions(+), 52 deletions(-)
4193 diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
4194 index 199eea124d..bc74d52a6c 100644
4195 --- a/NetworkPkg/Ip6Dxe/Ip6Option.c
4196 +++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
4197 @@ -76,27 +76,27 @@ Ip6IsOptionValid (
4198 case Ip6OptionParameterProblem:
4199 Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
4204 - &Packet->Ip.Ip6->SourceAddress,
4205 - ICMP_V6_PARAMETER_PROBLEM,
4212 + &Packet->Ip.Ip6->SourceAddress,
4213 + ICMP_V6_PARAMETER_PROBLEM,
4219 if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
4220 Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
4225 - &Packet->Ip.Ip6->SourceAddress,
4226 - ICMP_V6_PARAMETER_PROBLEM,
4233 + &Packet->Ip.Ip6->SourceAddress,
4234 + ICMP_V6_PARAMETER_PROBLEM,
4241 @@ -137,6 +137,14 @@ Ip6IsNDOptionValid (
4246 + // Cannot process truncated options.
4247 + // Cannot process options with a length of 0 as there is no Type field.
4249 + if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
4256 @@ -358,14 +366,14 @@ Ip6IsExtsValid (
4257 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4263 - &Packet->Ip.Ip6->SourceAddress,
4264 - ICMP_V6_PARAMETER_PROBLEM,
4271 + &Packet->Ip.Ip6->SourceAddress,
4272 + ICMP_V6_PARAMETER_PROBLEM,
4279 @@ -438,14 +446,14 @@ Ip6IsExtsValid (
4280 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4286 - &Packet->Ip.Ip6->SourceAddress,
4287 - ICMP_V6_PARAMETER_PROBLEM,
4294 + &Packet->Ip.Ip6->SourceAddress,
4295 + ICMP_V6_PARAMETER_PROBLEM,
4302 @@ -484,14 +492,14 @@ Ip6IsExtsValid (
4304 Pointer = sizeof (UINT32);
4309 - &Packet->Ip.Ip6->SourceAddress,
4310 - ICMP_V6_PARAMETER_PROBLEM,
4317 + &Packet->Ip.Ip6->SourceAddress,
4318 + ICMP_V6_PARAMETER_PROBLEM,
4325 @@ -560,14 +568,14 @@ Ip6IsExtsValid (
4326 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4332 - &Packet->Ip.Ip6->SourceAddress,
4333 - ICMP_V6_PARAMETER_PROBLEM,
4340 + &Packet->Ip.Ip6->SourceAddress,
4341 + ICMP_V6_PARAMETER_PROBLEM,
4348 @@ -774,10 +782,10 @@ Ip6FillFragmentHeader (
4349 // Append the part2 (fragmentable part) of Extension headers
4352 - Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
4353 - ExtHdrs + Part1Len,
4354 - ExtHdrsLen - Part1Len
4356 + Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
4357 + ExtHdrs + Part1Len,
4358 + ExtHdrsLen - Part1Len
4362 *UpdatedExtHdrs = Buffer;
4367 From 2f237a59ec4ea3df4b1614566ac29c90fb106669 Mon Sep 17 00:00:00 2001
4368 From: Doug Flick <dougflick@microsoft.com>
4369 Date: Fri, 15 Dec 2023 13:55:30 -0800
4370 Subject: [PATCH 06/12] SECURITY PATCH TCBZ4536 - CVE-2023-45231 - Host Based
4374 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 27 ++++
4375 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 42 ++++++
4376 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 129 ++++++++++++++++++
4377 NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 +
4378 4 files changed, 199 insertions(+)
4379 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4380 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4381 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4383 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4384 new file mode 100644
4385 index 0000000000..9dd5577249
4387 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4390 + Acts as the main entry point for the tests for the Ip6Dxe module.
4392 + Copyright (c) Microsoft Corporation
4393 + SPDX-License-Identifier: BSD-2-Clause-Patent
4395 +#include <gtest/gtest.h>
4397 +////////////////////////////////////////////////////////////////////////////////
4398 +// Add test files here
4399 +// Google Test will only pick up the tests from the files that are included
4401 +////////////////////////////////////////////////////////////////////////////////
4402 +#include "Ip6OptionGoogleTest.cpp"
4404 +////////////////////////////////////////////////////////////////////////////////
4406 +////////////////////////////////////////////////////////////////////////////////
4413 + testing::InitGoogleTest (&argc, argv);
4414 + return RUN_ALL_TESTS ();
4416 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4417 new file mode 100644
4418 index 0000000000..b85584b796
4420 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4423 +# Unit test suite for the Ip6Dxe using Google Test
4425 +# Copyright (c) Microsoft Corporation.<BR>
4426 +# SPDX-License-Identifier: BSD-2-Clause-Patent
4429 + INF_VERSION = 0x00010017
4430 + BASE_NAME = Ip6DxeUnitTest
4431 + FILE_GUID = 4F05D17D-D3E7-4AAE-820C-576D46D2D34A
4432 + VERSION_STRING = 1.0
4433 + MODULE_TYPE = HOST_APPLICATION
4435 +# The following information is for reference only and not required by the build tools.
4437 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
4440 + Ip6DxeGoogleTest.cpp
4441 + Ip6OptionGoogleTest.cpp
4446 + MdeModulePkg/MdeModulePkg.dec
4447 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
4448 + NetworkPkg/NetworkPkg.dec
4457 + gEfiDhcp6ServiceBindingProtocolGuid
4460 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
4464 \ No newline at end of file
4465 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4466 new file mode 100644
4467 index 0000000000..c4bcfacb92
4469 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4472 + Tests for Ip6Option.c.
4474 + Copyright (c) Microsoft Corporation
4475 + SPDX-License-Identifier: BSD-2-Clause-Patent
4477 +#include <gtest/gtest.h>
4481 + #include <Library/BaseLib.h>
4482 + #include <Library/DebugLib.h>
4483 + #include "../Ip6Impl.h"
4484 + #include "../Ip6Option.h"
4487 +/////////////////////////////////////////////////////////////////////////
4489 +///////////////////////////////////////////////////////////////////////
4491 +#define IP6_PREFIX_INFO_OPTION_DATA_LEN 32
4492 +#define OPTION_HEADER_IP6_PREFIX_DATA_LEN (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN)
4494 +////////////////////////////////////////////////////////////////////////
4495 +// Symbol Definitions
4496 +// These functions are not directly under test - but required to compile
4497 +////////////////////////////////////////////////////////////////////////
4502 + IN IP6_SERVICE *IpSb,
4503 + IN NET_BUF *Packet,
4504 + IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
4505 + IN EFI_IPv6_ADDRESS *DestinationAddress,
4508 + IN UINT32 *Pointer OPTIONAL
4512 + return EFI_SUCCESS;
4515 +////////////////////////////////////////////////////////////////////////
4516 +// Ip6OptionValidation Tests
4517 +////////////////////////////////////////////////////////////////////////
4519 +// Define a fixture for your tests if needed
4520 +class Ip6OptionValidationTest : public ::testing::Test {
4522 + // Add any setup code if needed
4527 + // Initialize any resources or variables
4530 + // Add any cleanup code if needed
4535 + // Clean up any resources or variables
4539 +// Test Description:
4540 +// Null option should return false
4541 +TEST_F (Ip6OptionValidationTest, NullOptionShouldReturnFalse) {
4542 + UINT8 *option = nullptr;
4543 + UINT16 optionLen = 10; // Provide a suitable length
4545 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4548 +// Test Description:
4549 +// Truncated option should return false
4550 +TEST_F (Ip6OptionValidationTest, TruncatedOptionShouldReturnFalse) {
4551 + UINT8 option[] = { 0x01 }; // Provide a truncated option
4552 + UINT16 optionLen = 1;
4554 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4557 +// Test Description:
4558 +// Ip6OptionPrefixInfo Option with zero length should return false
4559 +TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) {
4560 + IP6_OPTION_HEADER optionHeader;
4562 + optionHeader.Type = Ip6OptionPrefixInfo;
4563 + optionHeader.Length = 0;
4564 + UINT8 option[sizeof (IP6_OPTION_HEADER)];
4566 + CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
4567 + UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4569 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4572 +// Test Description:
4573 +// Ip6OptionPrefixInfo Option with valid length should return true
4574 +TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) {
4575 + IP6_OPTION_HEADER optionHeader;
4577 + optionHeader.Type = Ip6OptionPrefixInfo;
4578 + optionHeader.Length = 4; // Length 4 * 8 = 32
4579 + UINT8 option[OPTION_HEADER_IP6_PREFIX_DATA_LEN];
4581 + CopyMem (option, &optionHeader, OPTION_HEADER_IP6_PREFIX_DATA_LEN);
4583 + EXPECT_FALSE (Ip6IsNDOptionValid (option, OPTION_HEADER_IP6_PREFIX_DATA_LEN));
4586 +// Test Description:
4587 +// Ip6OptionPrefixInfo Option with invalid length should return false
4588 +TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) {
4589 + IP6_OPTION_HEADER optionHeader;
4591 + optionHeader.Type = Ip6OptionPrefixInfo;
4592 + optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid)
4593 + UINT8 option[sizeof (IP6_OPTION_HEADER)];
4595 + CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
4596 + UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4598 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4600 \ No newline at end of file
4601 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
4602 index f6459b124f..8ed3585c06 100644
4603 --- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
4604 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
4606 # Build HOST_APPLICATION that tests NetworkPkg
4608 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4609 + NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4611 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4617 From 7ec488242f6c634a6e08fda25e4196ab24bf2d42 Mon Sep 17 00:00:00 2001
4618 From: Doug Flick <dougflick@microsoft.com>
4619 Date: Mon, 18 Dec 2023 10:37:40 -0800
4620 Subject: [PATCH 07/12] SECURITY PATCH TCBZ4537 / TCBZ4538 - CVE-2023-45232 /
4621 CVE-2023-45233 - Patch
4624 NetworkPkg/Ip6Dxe/Ip6Option.c | 81 ++++++++++++++++++++++++++-----
4625 NetworkPkg/Ip6Dxe/Ip6Option.h | 89 +++++++++++++++++++++++++++++++++++
4626 2 files changed, 157 insertions(+), 13 deletions(-)
4628 diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.c b/NetworkPkg/Ip6Dxe/Ip6Option.c
4629 index bc74d52a6c..9ca4d6ae5d 100644
4630 --- a/NetworkPkg/Ip6Dxe/Ip6Option.c
4631 +++ b/NetworkPkg/Ip6Dxe/Ip6Option.c
4634 #include "Ip6Impl.h"
4638 Validate the IP6 option format for both the packets we received
4639 and that we will transmit. It will compute the ICMPv6 error message fields
4641 @param[in] IpSb The IP6 service data.
4642 @param[in] Packet The to be validated packet.
4643 @param[in] Option The first byte of the option.
4644 - @param[in] OptionLen The length of the whole option.
4645 + @param[in] OptionLen The length of all options, expressed in byte length of octets.
4646 + Maximum length is 2046 bytes or ((n + 1) * 8) - 2 where n is 255.
4647 @param[in] Pointer Identifies the octet offset within
4648 the invoking packet where the error was detected.
4650 @@ -31,12 +33,33 @@ Ip6IsOptionValid (
4651 IN IP6_SERVICE *IpSb,
4654 - IN UINT8 OptionLen,
4655 + IN UINT16 OptionLen,
4665 + if (Option == NULL) {
4666 + ASSERT (Option != NULL);
4670 + if (OptionLen <= 0 || OptionLen > IP6_MAX_EXT_DATA_LENGTH) {
4671 + ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);
4675 + if (Packet == NULL) {
4676 + ASSERT (Packet != NULL);
4680 + if (IpSb == NULL) {
4681 + ASSERT (IpSb != NULL);
4687 @@ -54,7 +77,8 @@ Ip6IsOptionValid (
4689 // It is a PadN option
4691 - Offset = (UINT8)(Offset + *(Option + Offset + 1) + 2);
4692 + OptDataLen = *(IP6_OFFSET_OF_OPT_LEN(Option + Offset));
4693 + Offset = IP6_NEXT_OPTION_OFFSET(Offset, OptDataLen);
4695 case Ip6OptionRouterAlert:
4697 @@ -69,7 +93,8 @@ Ip6IsOptionValid (
4699 switch (OptionType & Ip6OptionMask) {
4701 - Offset = (UINT8)(Offset + *(Option + Offset + 1));
4702 + OptDataLen = *(IP6_OFFSET_OF_OPT_LEN(Option + Offset));
4703 + Offset = IP6_NEXT_OPTION_OFFSET(Offset, OptDataLen);
4705 case Ip6OptionDiscard:
4707 @@ -308,7 +333,7 @@ Ip6IsExtsValid (
4716 @@ -385,6 +410,36 @@ Ip6IsExtsValid (
4719 case IP6_DESTINATION:
4721 + // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23
4723 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4724 + // | Next Header | Hdr Ext Len | |
4725 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
4731 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4734 + // Next Header 8-bit selector. Identifies the type of header
4735 + // immediately following the Destination Options
4736 + // header. Uses the same values as the IPv4
4737 + // Protocol field [RFC-1700 et seq.].
4739 + // Hdr Ext Len 8-bit unsigned integer. Length of the
4740 + // Destination Options header in 8-octet units, not
4741 + // including the first 8 octets.
4743 + // Options Variable-length field, of length such that the
4744 + // complete Destination Options header is an
4745 + // integer multiple of 8 octets long. Contains one
4746 + // or more TLV-encoded options, as described in
4750 if (*NextHeader == IP6_DESTINATION) {
4753 @@ -397,8 +452,8 @@ Ip6IsExtsValid (
4757 - Option = ExtHdrs + Offset;
4758 - OptionLen = (UINT8)((*Option + 1) * 8 - 2);
4759 + Option = ExtHdrs + Offset;
4760 + OptionLen = IP6_HDR_EXT_LEN(*Option) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN;
4764 @@ -430,7 +485,7 @@ Ip6IsExtsValid (
4766 // Ignore the routing header and proceed to process the next header.
4768 - Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
4769 + Offset = Offset + IP6_HDR_EXT_LEN(RoutingHead->HeaderLen);
4771 if (UnFragmentLen != NULL) {
4772 *UnFragmentLen = Offset;
4773 @@ -441,7 +496,7 @@ Ip6IsExtsValid (
4774 // to the packet's source address, pointing to the unrecognized routing
4777 - Pointer = Offset + 2 + sizeof (EFI_IP6_HEADER);
4778 + Pointer = Offset + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN + sizeof (EFI_IP6_HEADER);
4779 if ((IpSb != NULL) && (Packet != NULL) &&
4780 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4782 @@ -527,8 +582,8 @@ Ip6IsExtsValid (
4784 // RFC2402, Payload length is specified in 32-bit words, minus "2".
4786 - OptionLen = (UINT8)((*Option + 2) * 4);
4787 - Offset = Offset + OptionLen;
4788 + OptionLen = ((UINT16)(*Option + 2) * 4);
4789 + Offset = Offset + OptionLen;
4792 case IP6_NO_NEXT_HEADER:
4793 diff --git a/NetworkPkg/Ip6Dxe/Ip6Option.h b/NetworkPkg/Ip6Dxe/Ip6Option.h
4794 index bd8e223c8a..1f9237b4e9 100644
4795 --- a/NetworkPkg/Ip6Dxe/Ip6Option.h
4796 +++ b/NetworkPkg/Ip6Dxe/Ip6Option.h
4799 #define IP6_FRAGMENT_OFFSET_MASK (~0x3)
4802 +// Per RFC8200 Section 4.2
4804 +// Two of the currently-defined extension headers -- the Hop-by-Hop
4805 +// Options header and the Destination Options header -- carry a variable
4806 +// number of type-length-value (TLV) encoded "options", of the following
4809 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
4810 +// | Option Type | Opt Data Len | Option Data
4811 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
4813 +// Option Type 8-bit identifier of the type of option.
4815 +// Opt Data Len 8-bit unsigned integer. Length of the Option
4816 +// Data field of this option, in octets.
4818 +// Option Data Variable-length field. Option-Type-specific
4821 +#define IP6_SIZE_OF_OPT_TYPE (sizeof(UINT8))
4822 +#define IP6_SIZE_OF_OPT_LEN (sizeof(UINT8))
4823 +#define IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN (IP6_SIZE_OF_OPT_TYPE + IP6_SIZE_OF_OPT_LEN)
4824 +#define IP6_OFFSET_OF_OPT_LEN(a) (a + IP6_SIZE_OF_OPT_TYPE)
4826 + IP6_OFFSET_OF_OPT_LEN (0) == 1,
4827 + "The Length field should be 1 octet (8 bits) past the start of the option"
4830 +#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN + length)
4832 + IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
4833 + "The next option is minimally the combined size of the option tag and length"
4837 +// For more information see RFC 8200, Section 4.3, 4.4, and 4.6
4839 +// This example format is from section 4.6
4840 +// This does not apply to fragment headers
4842 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4843 +// | Next Header | Hdr Ext Len | |
4844 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
4847 +// . Header-Specific Data .
4850 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4852 +// Next Header 8-bit selector. Identifies the type of
4853 +// header immediately following the extension
4854 +// header. Uses the same values as the IPv4
4855 +// Protocol field [IANA-PN].
4857 +// Hdr Ext Len 8-bit unsigned integer. Length of the
4858 +// Destination Options header in 8-octet units,
4859 +// not including the first 8 octets.
4862 +// These defines apply to the following:
4867 +#define IP6_SIZE_OF_EXT_NEXT_HDR (sizeof(UINT8))
4868 +#define IP6_SIZE_OF_HDR_EXT_LEN (sizeof(UINT8))
4870 +#define IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN (IP6_SIZE_OF_EXT_NEXT_HDR + IP6_SIZE_OF_HDR_EXT_LEN)
4872 + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN == 2,
4873 + "The combined size of Next Header and Len is two 8 bit fields"
4877 +// The "+ 1" in this calculation is because of the "not including the first 8 octets"
4878 +// part of the definition (meaning the value of 0 represents 64 bits)
4880 +#define IP6_HDR_EXT_LEN(a) (((UINT16)(UINT8)(a) + 1) * 8)
4882 +// This is the maxmimum length permissible by a extension header
4883 +// Length is UINT8 of 8 octets not including the first 8 octets
4884 +#define IP6_MAX_EXT_DATA_LENGTH (IP6_HDR_EXT_LEN (MAX_UINT8) - IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN)
4886 + IP6_MAX_EXT_DATA_LENGTH == 2046,
4887 + "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"
4890 typedef struct _IP6_FRAGMENT_HEADER {
4897 From d925ff1f00e769bcdbd04c1cb81560a8dec4e235 Mon Sep 17 00:00:00 2001
4898 From: Doug Flick <dougflick@microsoft.com>
4899 Date: Mon, 18 Dec 2023 10:49:41 -0800
4900 Subject: [PATCH 08/12] SECURITY PATCH TCBZ4537 / TCBZ4538 - CVE-2023-45232 /
4901 CVE-2023-45233 - Host Based Unit Test
4904 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp | 3 +-
4905 .../Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf | 5 +-
4906 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp | 344 +++++++++++++++++-
4907 .../Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h | 33 ++
4908 NetworkPkg/Test/NetworkPkgHostTest.dsc | 2 +-
4909 5 files changed, 376 insertions(+), 11 deletions(-)
4910 create mode 100644 NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
4912 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4913 index 9dd5577249..5525da4231 100644
4914 --- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4915 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4918 - Acts as the main entry point for the tests for the Ip6Dxe module.
4920 + Acts as the main entry point for the tests for the Ip6Dxe driver.
4921 Copyright (c) Microsoft Corporation
4922 SPDX-License-Identifier: BSD-2-Clause-Patent
4924 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4925 index b85584b796..9f4ce85157 100644
4926 --- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4927 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4930 -# Unit test suite for the Ip6Dxe using Google Test
4931 +# Unit test suite for the Ip6DxeGoogleTest using Google Test
4933 # Copyright (c) Microsoft Corporation.<BR>
4934 # SPDX-License-Identifier: BSD-2-Clause-Patent
4941 gEfiDhcp6ServiceBindingProtocolGuid
4944 gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
4948 \ No newline at end of file
4950 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4951 index c4bcfacb92..640e96a17c 100644
4952 --- a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4953 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4956 - Tests for Ip6Option.c.
4957 + Host based unit test for Ip6Option.c.
4959 Copyright (c) Microsoft Corporation
4960 SPDX-License-Identifier: BSD-2-Clause-Patent
4961 @@ -12,18 +12,23 @@ extern "C" {
4962 #include <Library/DebugLib.h>
4963 #include "../Ip6Impl.h"
4964 #include "../Ip6Option.h"
4965 + #include "Ip6OptionGoogleTest.h"
4968 /////////////////////////////////////////////////////////////////////////
4970 -///////////////////////////////////////////////////////////////////////
4971 +////////////////////////////////////////////////////////////////////////
4973 #define IP6_PREFIX_INFO_OPTION_DATA_LEN 32
4974 #define OPTION_HEADER_IP6_PREFIX_DATA_LEN (sizeof (IP6_OPTION_HEADER) + IP6_PREFIX_INFO_OPTION_DATA_LEN)
4976 -////////////////////////////////////////////////////////////////////////
4977 -// Symbol Definitions
4978 -// These functions are not directly under test - but required to compile
4979 +///////////////////////////////////////////////////////////////////////
4980 +// Symbol definitions
4982 +// These symbols / stub functions are required to be defined in order
4983 +// to compile but are not under test. These can be converted to
4984 +// Mock functions if required in the future.
4986 ////////////////////////////////////////////////////////////////////////
4989 @@ -126,4 +131,333 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
4990 UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4992 EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4995 +////////////////////////////////////////////////////////////////////////
4996 +// Ip6IsOptionValid Tests
4997 +////////////////////////////////////////////////////////////////////////
4999 +// Define a fixture for your tests if needed
5000 +class Ip6IsOptionValidTest : public ::testing::Test {
5002 + // Add any setup code if needed
5007 + // Initialize any resources or variables
5010 + // Add any cleanup code if needed
5015 + // Clean up any resources or variables
5019 +// Test Description
5020 +// Verify that a NULL option is Invalid
5021 +TEST_F (Ip6IsOptionValidTest, NullOptionShouldReturnTrue) {
5022 + NET_BUF Packet = { 0 };
5023 + // we need to define enough of the packet to make the function work
5024 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5025 + IP6_SERVICE *IpSb = NULL;
5027 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5028 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5029 + EFI_IP6_HEADER Ip6Header = { 0 };
5031 + Ip6Header.SourceAddress = SourceAddress;
5032 + Ip6Header.DestinationAddress = DestinationAddress;
5033 + Packet.Ip.Ip6 = &Ip6Header;
5035 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
5038 +// Test Description
5039 +// Verify that an unknown option with a length of 0 and type of <unknown> does not cause an infinite loop
5040 +TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength0) {
5041 + NET_BUF Packet = { 0 };
5042 + // we need to define enough of the packet to make the function work
5043 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5044 + UINT32 DeadCode = 0xDeadC0de;
5045 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5046 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5048 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5049 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5050 + EFI_IP6_HEADER Ip6Header = { 0 };
5052 + Ip6Header.SourceAddress = SourceAddress;
5053 + Ip6Header.DestinationAddress = DestinationAddress;
5054 + Packet.Ip.Ip6 = &Ip6Header;
5056 + IP6_OPTION_HEADER optionHeader;
5058 + optionHeader.Type = 23; // Unknown Option
5059 + optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly
5061 + // This should be a valid option even though the length is 0
5062 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5065 +// Test Description
5066 +// Verify that an unknown option with a length of 1 and type of <unknown> does not cause an infinite loop
5067 +TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLength1) {
5068 + NET_BUF Packet = { 0 };
5069 + // we need to define enough of the packet to make the function work
5070 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5071 + UINT32 DeadCode = 0xDeadC0de;
5072 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5073 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5075 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5076 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5077 + EFI_IP6_HEADER Ip6Header = { 0 };
5079 + Ip6Header.SourceAddress = SourceAddress;
5080 + Ip6Header.DestinationAddress = DestinationAddress;
5081 + Packet.Ip.Ip6 = &Ip6Header;
5083 + IP6_OPTION_HEADER optionHeader;
5085 + optionHeader.Type = 23; // Unknown Option
5086 + optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly
5088 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5091 +// Test Description
5092 +// Verify that an unknown option with a length of 2 and type of <unknown> does not cause an infinite loop
5093 +TEST_F (Ip6IsOptionValidTest, VerifyIpSkipUnknownOption) {
5094 + NET_BUF Packet = { 0 };
5095 + // we need to define enough of the packet to make the function work
5096 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5097 + UINT32 DeadCode = 0xDeadC0de;
5098 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5099 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5101 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5102 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5103 + EFI_IP6_HEADER Ip6Header = { 0 };
5105 + Ip6Header.SourceAddress = SourceAddress;
5106 + Ip6Header.DestinationAddress = DestinationAddress;
5107 + Packet.Ip.Ip6 = &Ip6Header;
5109 + IP6_OPTION_HEADER optionHeader;
5111 + optionHeader.Type = 23; // Unknown Option
5112 + optionHeader.Length = 2; // Valid length for an unknown option
5114 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5117 +// Test Description
5118 +// Verify that Ip6OptionPad1 is valid with a length of 0
5119 +TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPad1) {
5120 + NET_BUF Packet = { 0 };
5121 + // we need to define enough of the packet to make the function work
5122 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5123 + UINT32 DeadCode = 0xDeadC0de;
5124 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5125 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5127 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5128 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5129 + EFI_IP6_HEADER Ip6Header = { 0 };
5131 + Ip6Header.SourceAddress = SourceAddress;
5132 + Ip6Header.DestinationAddress = DestinationAddress;
5133 + Packet.Ip.Ip6 = &Ip6Header;
5135 + IP6_OPTION_HEADER optionHeader;
5137 + optionHeader.Type = Ip6OptionPad1;
5138 + optionHeader.Length = 0;
5140 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5143 +// Test Description
5144 +// Verify that Ip6OptionPadN doesn't overflow with various lengths
5145 +TEST_F (Ip6IsOptionValidTest, VerifyIp6OptionPadN) {
5146 + NET_BUF Packet = { 0 };
5147 + // we need to define enough of the packet to make the function work
5148 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5149 + UINT32 DeadCode = 0xDeadC0de;
5150 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5151 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5153 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5154 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5155 + EFI_IP6_HEADER Ip6Header = { 0 };
5157 + Ip6Header.SourceAddress = SourceAddress;
5158 + Ip6Header.DestinationAddress = DestinationAddress;
5159 + Packet.Ip.Ip6 = &Ip6Header;
5161 + IP6_OPTION_HEADER optionHeader;
5163 + optionHeader.Type = Ip6OptionPadN;
5164 + optionHeader.Length = 0xFF;
5165 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5167 + optionHeader.Length = 0xFE;
5168 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5170 + optionHeader.Length = 0xFD;
5171 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5173 + optionHeader.Length = 0xFC;
5174 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5177 +// Test Description
5178 +// Verify an unknown option doesn't cause an infinite loop with various lengths
5179 +TEST_F (Ip6IsOptionValidTest, VerifyNoInfiniteLoopOnUnknownOptionLengthAttemptOverflow) {
5180 + NET_BUF Packet = { 0 };
5181 + // we need to define enough of the packet to make the function work
5182 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5183 + UINT32 DeadCode = 0xDeadC0de;
5184 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5185 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5187 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5188 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5189 + EFI_IP6_HEADER Ip6Header = { 0 };
5191 + Ip6Header.SourceAddress = SourceAddress;
5192 + Ip6Header.DestinationAddress = DestinationAddress;
5193 + Packet.Ip.Ip6 = &Ip6Header;
5195 + IP6_OPTION_HEADER optionHeader;
5197 + optionHeader.Type = 23; // Unknown Option
5198 + optionHeader.Length = 0xFF;
5199 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5201 + optionHeader.Length = 0xFE;
5202 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5204 + optionHeader.Length = 0xFD;
5205 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5207 + optionHeader.Length = 0xFC;
5208 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5211 +// Test Description
5212 +// Verify that the function supports multiple options
5213 +TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) {
5215 + NET_BUF Packet = { 0 };
5216 + // we need to define enough of the packet to make the function work
5217 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5218 + UINT32 DeadCode = 0xDeadC0de;
5219 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5220 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5222 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5223 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5224 + EFI_IP6_HEADER Ip6Header = { 0 };
5226 + Ip6Header.SourceAddress = SourceAddress;
5227 + Ip6Header.DestinationAddress = DestinationAddress;
5228 + Packet.Ip.Ip6 = &Ip6Header;
5230 + UINT8 ExtHdr[1024] = { 0 };
5231 + UINT8 *Cursor = ExtHdr;
5232 + IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr;
5234 + // Let's start chaining options
5236 + Option->Type = 23; // Unknown Option
5237 + Option->Length = 0xFC;
5239 + Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
5241 + Option = (IP6_OPTION_HEADER *)Cursor;
5242 + Option->Type = Ip6OptionPad1;
5244 + Cursor += sizeof (1);
5246 + // Type and length aren't processed, instead it just moves the pointer forward by 4 bytes
5247 + Option = (IP6_OPTION_HEADER *)Cursor;
5248 + Option->Type = Ip6OptionRouterAlert;
5249 + Option->Length = 4;
5251 + Cursor += sizeof (IP6_OPTION_HEADER) + 4;
5253 + Option = (IP6_OPTION_HEADER *)Cursor;
5254 + Option->Type = Ip6OptionPadN;
5255 + Option->Length = 0xFC;
5257 + Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
5259 + Option = (IP6_OPTION_HEADER *)Cursor;
5260 + Option->Type = Ip6OptionRouterAlert;
5261 + Option->Length = 4;
5263 + Cursor += sizeof (IP6_OPTION_HEADER) + 4;
5267 + HdrLen = (UINT16)(Cursor - ExtHdr);
5269 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0));
5272 +// Test Description
5273 +// Verify that a OptionLength that is too small fails
5274 +TEST_F (Ip6IsOptionValidTest, VerifyOptionLengthTooSmall) {
5275 + NET_BUF Packet = { 0 };
5276 + // we need to define enough of the packet to make the function work
5277 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5278 + UINT32 DeadCode = 0xDeadC0de;
5279 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5280 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5282 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5283 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5284 + EFI_IP6_HEADER Ip6Header = { 0 };
5286 + Ip6Header.SourceAddress = SourceAddress;
5287 + Ip6Header.DestinationAddress = DestinationAddress;
5288 + Packet.Ip.Ip6 = &Ip6Header;
5290 + IP6_OPTION_HEADER optionHeader;
5292 + optionHeader.Type = Ip6OptionPad1;
5293 + optionHeader.Length = 0;
5295 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, 0, 0));
5298 +// Test Description
5299 +// Verify that a OptionLength that is too large fails
5300 +TEST_F (Ip6IsOptionValidTest, VerifyOptionLengthTooLarge) {
5301 + NET_BUF Packet = { 0 };
5302 + // we need to define enough of the packet to make the function work
5303 + // The function being tested will pass IpSb to Ip6SendIcmpError which is defined above
5304 + UINT32 DeadCode = 0xDeadC0de;
5305 + // Don't actually use this pointer, just pass it to the function, nothing will be done with it
5306 + IP6_SERVICE *IpSb = (IP6_SERVICE *)&DeadCode;
5308 + EFI_IPv6_ADDRESS SourceAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5309 + EFI_IPv6_ADDRESS DestinationAddress = { 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x42, 0x83, 0x29 };
5310 + EFI_IP6_HEADER Ip6Header = { 0 };
5312 + Ip6Header.SourceAddress = SourceAddress;
5313 + Ip6Header.DestinationAddress = DestinationAddress;
5314 + Packet.Ip.Ip6 = &Ip6Header;
5316 + IP6_OPTION_HEADER optionHeader;
5318 + optionHeader.Type = Ip6OptionPad1;
5319 + optionHeader.Length = 0;
5321 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, MAX_UINT8, 0));
5323 \ No newline at end of file
5324 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
5325 new file mode 100644
5326 index 0000000000..43ad56b4ab
5328 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
5330 +#ifndef __EFI_IP6_OPTION_GOOGLE_TEST_H__
5331 +#define __EFI_IP6_OPTION_GOOGLE_TEST_H__
5334 +#include "../Ip6Impl.h"
5337 + Validate the IP6 option format for both the packets we received
5338 + and that we will transmit. It will compute the ICMPv6 error message fields
5339 + if the option is malformatted.
5341 + @param[in] IpSb The IP6 service data.
5342 + @param[in] Packet The to be validated packet.
5343 + @param[in] Option The first byte of the option.
5344 + @param[in] OptionLen The length of the whole option.
5345 + @param[in] Pointer Identifies the octet offset within
5346 + the invoking packet where the error was detected.
5349 + @retval TRUE The option is properly formatted.
5350 + @retval FALSE The option is malformatted.
5355 + IN IP6_SERVICE *IpSb,
5356 + IN NET_BUF *Packet,
5358 + IN UINT16 OptionLen,
5362 +#endif // __EFI_IP6_OPTION_GOOGLE_TEST_H__
5363 \ No newline at end of file
5364 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
5365 index 8ed3585c06..a95a617d98 100644
5366 --- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
5367 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
5369 SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
5370 BUILD_TARGETS = NOOPT
5371 SKUID_IDENTIFIER = DEFAULT
5374 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
5381 From 813bfde4aa9b099c1eb6d9b38d3dbf3b9e3fa50d Mon Sep 17 00:00:00 2001
5382 From: Doug Flick <dougflick@microsoft.com>
5383 Date: Mon, 18 Dec 2023 11:16:54 -0800
5384 Subject: [PATCH 09/12] SECURITY PATCH TCBZ4539 - CVE-2023-45234 - Patch
5387 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++---
5388 1 file changed, 65 insertions(+), 6 deletions(-)
5390 diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5391 index 425e0cf806..4059fae5fc 100644
5392 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5393 +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5396 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5397 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5398 + Copyright (c) Microsoft Corporation
5400 SPDX-License-Identifier: BSD-2-Clause-Patent
5402 @@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer (
5407 + Cache the DHCPv6 DNS Server addresses
5409 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5410 + @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
5412 + @retval EFI_SUCCESS Cache the DHCPv6 DNS Server address successfully.
5413 + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
5414 + @retval EFI_DEVICE_ERROR The DNS Server Address Length provided by a untrusted
5415 + option is not a multiple of 16 bytes (sizeof (EFI_IPv6_ADDRESS)).
5418 +PxeBcCacheDnsServerAddresses (
5419 + IN PXEBC_PRIVATE_DATA *Private,
5420 + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
5423 + UINT16 DnsServerLen;
5425 + DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen);
5427 + // Make sure that the number is nonzero
5429 + if (DnsServerLen == 0) {
5430 + return EFI_DEVICE_ERROR;
5434 + // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16)
5436 + if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) {
5437 + return EFI_DEVICE_ERROR;
5441 + // This code is currently written to only support a single DNS Server instead
5442 + // of multiple such as is spec defined (RFC3646, Section 3). The proper behavior
5443 + // would be to allocate the full space requested, CopyMem all of the data,
5444 + // and then add a DnsServerCount field to Private and update additional code
5445 + // that depends on this.
5447 + // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen
5449 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
5451 + Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
5452 + if (Private->DnsServer == NULL) {
5453 + return EFI_OUT_OF_RESOURCES;
5457 + // Intentionally only copy over the first server address.
5458 + // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen
5460 + CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
5462 + return EFI_SUCCESS;
5466 Handle the DHCPv6 offer packet.
5468 @@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer (
5472 + ASSERT (Private != NULL);
5473 ASSERT (Private->SelectIndex > 0);
5474 SelectIndex = (UINT32)(Private->SelectIndex - 1);
5475 ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);
5476 @@ -1342,15 +1403,13 @@ PxeBcHandleDhcp6Offer (
5477 Status = EFI_SUCCESS;
5480 - // First try to cache DNS server address if DHCP6 offer provides.
5481 + // First try to cache DNS server addresses if DHCP6 offer provides.
5483 if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {
5484 - Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));
5485 - if (Private->DnsServer == NULL) {
5486 - return EFI_OUT_OF_RESOURCES;
5487 + Status = PxeBcCacheDnsServerAddresses (Private, Cache6);
5488 + if (EFI_ERROR (Status)) {
5492 - CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
5495 if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {
5500 From 688eb3679f795d8699d09acc7a8c2322b389c440 Mon Sep 17 00:00:00 2001
5501 From: Doug Flick <dougflick@microsoft.com>
5502 Date: Mon, 18 Dec 2023 11:17:25 -0800
5503 Subject: [PATCH 10/12] SECURITY PATCH TCBZ4539 - CVE-2023-45234 - Host Based
5507 NetworkPkg/Test/NetworkPkgHostTest.dsc | 1 +
5508 .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 301 ++++++++++++++++++
5509 .../GoogleTest/PxeBcDhcp6GoogleTest.h | 48 +++
5510 .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 21 ++
5511 .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 47 +++
5512 5 files changed, 418 insertions(+)
5513 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
5514 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
5515 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
5516 create mode 100644 NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5518 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
5519 index a95a617d98..b9d031a611 100644
5520 --- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
5521 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
5524 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
5525 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
5526 + NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5528 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
5530 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
5531 new file mode 100644
5532 index 0000000000..9ee805a284
5534 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
5537 + Host based unit test for PxeBcDhcp6.c.
5539 + Copyright (c) Microsoft Corporation
5540 + SPDX-License-Identifier: BSD-2-Clause-Patent
5542 +#include <gtest/gtest.h>
5546 +#include <Library/BaseLib.h>
5547 +#include <Library/DebugLib.h>
5548 +#include "../PxeBcImpl.h"
5549 +#include "../PxeBcDhcp6.h"
5550 +#include "PxeBcDhcp6GoogleTest.h"
5553 +///////////////////////////////////////////////////////////////////////////////
5555 +///////////////////////////////////////////////////////////////////////////////
5557 +#define PACKET_SIZE (1500)
5560 + UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
5561 + UINT16 OptionLen; // The length of the option (e.g., 16 bytes)
5562 + UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier
5563 +} DHCP6_OPTION_SERVER_ID;
5565 +///////////////////////////////////////////////////////////////////////////////
5566 +/// Symbol Definitions
5567 +///////////////////////////////////////////////////////////////////////////////
5571 + IN EFI_PXE_BASE_CODE_PROTOCOL *This,
5572 + IN UINT16 OpFlags,
5573 + IN EFI_IP_ADDRESS *DestIp,
5574 + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
5575 + IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
5576 + IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
5577 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
5578 + IN UINTN *HeaderSize OPTIONAL,
5579 + IN VOID *HeaderPtr OPTIONAL,
5580 + IN UINTN *BufferSize,
5581 + IN VOID *BufferPtr
5584 + return EFI_SUCCESS;
5589 + IN EFI_PXE_BASE_CODE_PROTOCOL *This,
5590 + IN UINT16 OpFlags,
5591 + IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,
5592 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,
5593 + IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,
5594 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
5595 + IN UINTN *HeaderSize OPTIONAL,
5596 + IN VOID *HeaderPtr OPTIONAL,
5597 + IN OUT UINTN *BufferSize,
5598 + IN VOID *BufferPtr
5601 + return EFI_SUCCESS;
5606 + IN EFI_UDP6_PROTOCOL *This,
5607 + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
5610 + return EFI_SUCCESS;
5613 +// Needed by PxeBcSupport
5617 + IN EFI_TPL DpcTpl,
5618 + IN EFI_DPC_PROCEDURE DpcProcedure,
5619 + IN VOID *DpcContext OPTIONAL
5622 + return EFI_SUCCESS;
5625 +///////////////////////////////////////////////////////////////////////////////
5626 +// PxeBcHandleDhcp6OfferTest Tests
5627 +///////////////////////////////////////////////////////////////////////////////
5629 +class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
5631 +PXEBC_PRIVATE_DATA Private = { 0 };
5632 +EFI_UDP6_PROTOCOL Udp6Read;
5633 +EFI_PXE_BASE_CODE_MODE Mode = { 0 };
5636 +// Add any setup code if needed
5641 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
5643 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
5644 + // The function under test really only needs the following:
5648 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
5649 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
5651 + // Need to setup EFI_UDP6_PROTOCOL
5652 + // The function under test really only needs the following:
5655 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
5656 + Private.Udp6Read = &Udp6Read;
5658 + // Need to setup the EFI_PXE_BASE_CODE_MODE
5659 + Private.PxeBc.Mode = &Mode;
5661 + // for this test it doesn't really matter what the Dhcpv6 ack is set to
5664 +// Add any cleanup code if needed
5669 + if (Private.Dhcp6Request != NULL) {
5670 + FreePool (Private.Dhcp6Request);
5673 + // Clean up any resources or variables
5678 +// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
5679 +// properly setup Private structure. Attempting to properly test this function
5680 +// without a signficant refactor is a fools errand. Instead, we will test
5681 +// that we can prevent an overflow in the function.
5682 +TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
5683 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
5684 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
5686 + Private.SelectIndex = 1; // SelectIndex is 1-based
5687 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5689 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
5690 + // Setup the DHCPv6 offer packet
5691 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
5692 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
5694 + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
5697 +class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
5699 +PXEBC_PRIVATE_DATA Private = { 0 };
5702 +// Add any setup code if needed
5709 +// Add any cleanup code if needed
5717 +// Test Description
5718 +// Test that we cache the DNS server address from the DHCPv6 offer packet
5719 +TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
5720 + UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };
5721 + EFI_DHCP6_PACKET_OPTION *Option;
5722 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
5724 + Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
5725 + ASSERT_NE (Option, nullptr);
5727 + Option->OpCode = DHCP6_OPT_SERVER_ID;
5728 + Option->OpLen = NTOHS (sizeof (SearchPattern));
5729 + CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
5731 + Private.SelectIndex = 1; // SelectIndex is 1-based
5732 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5733 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
5735 + Private.DnsServer = nullptr;
5737 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
5738 + ASSERT_NE (Private.DnsServer, nullptr);
5739 + ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);
5741 + if (Private.DnsServer) {
5742 + FreePool (Private.DnsServer);
5746 + FreePool (Option);
5749 +// Test Description
5750 +// Test that we can prevent an overflow in the function
5751 +TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
5752 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
5753 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
5755 + Private.SelectIndex = 1; // SelectIndex is 1-based
5756 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5757 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
5758 + // Setup the DHCPv6 offer packet
5759 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
5760 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
5762 + Private.DnsServer = NULL;
5764 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
5765 + ASSERT_EQ (Private.DnsServer, nullptr);
5767 + if (Private.DnsServer) {
5768 + FreePool (Private.DnsServer);
5772 +// Test Description
5773 +// Test that we can prevent an underflow in the function
5774 +TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {
5775 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
5776 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
5778 + Private.SelectIndex = 1; // SelectIndex is 1-based
5779 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5780 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
5781 + // Setup the DHCPv6 offer packet
5782 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
5783 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2);
5785 + Private.DnsServer = NULL;
5787 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
5788 + ASSERT_EQ (Private.DnsServer, nullptr);
5790 + if (Private.DnsServer) {
5791 + FreePool (Private.DnsServer);
5796 +// Test Description
5797 +// Test that we can handle recursive dns (multiple dns entries)
5798 +TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
5799 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
5800 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
5802 + Private.SelectIndex = 1; // SelectIndex is 1-based
5803 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5804 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
5805 + // Setup the DHCPv6 offer packet
5806 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
5808 + EFI_IPv6_ADDRESS addresses[2] = {
5809 + // 2001:db8:85a3::8a2e:370:7334
5810 + {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
5811 + // fe80::d478:91c3:ecd7:4ff9
5812 + {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}
5816 + CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
5818 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
5820 + Private.DnsServer = NULL;
5822 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
5824 + ASSERT_NE (Private.DnsServer, nullptr);
5827 + // This is expected to fail until DnsServer supports multiple DNS servers
5829 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
5831 + ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
5833 + if (Private.DnsServer) {
5834 + FreePool (Private.DnsServer);
5837 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
5838 new file mode 100644
5839 index 0000000000..724ee468cb
5841 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
5845 + This file exposes the internal interfaces which may be unit tested
5846 + for the PxeBcDhcp6Dxe driver.
5848 + Copyright (c) Microsoft Corporation.<BR>
5849 + SPDX-License-Identifier: BSD-2-Clause-Patent
5851 +#ifndef __PXE_BC_DHCP6_GOOGLE_TEST_H__
5852 +#define __PXE_BC_DHCP6_GOOGLE_TEST_H__
5854 +// Minimal includes needed to compile
5856 +#include "../PxeBcImpl.h"
5859 + Handle the DHCPv6 offer packet.
5861 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5863 + @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully.
5864 + @retval EFI_NO_RESPONSE No response to the following request packet.
5865 + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
5866 + @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet.
5870 +PxeBcHandleDhcp6Offer (
5871 + IN PXEBC_PRIVATE_DATA *Private
5875 + Cache the DHCPv6 Server address
5877 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5878 + @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
5880 + @retval EFI_SUCCESS Cache the DHCPv6 Server address successfully.
5881 + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
5882 + @retval EFI_DEVICE_ERROR Failed to cache the DHCPv6 Server address.
5885 +PxeBcCacheDnsServerAddresses (
5886 + IN PXEBC_PRIVATE_DATA *Private,
5887 + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
5890 +#endif // __PXE_BC_DHCP6_GOOGLE_TEST_H__
5891 \ No newline at end of file
5892 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
5893 new file mode 100644
5894 index 0000000000..cc295f5c88
5896 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
5899 + Acts as the main entry point for the tests for the UefiPxeBcDxe module.
5900 + Copyright (c) Microsoft Corporation
5901 + SPDX-License-Identifier: BSD-2-Clause-Patent
5903 +#include <gtest/gtest.h>
5905 +////////////////////////////////////////////////////////////////////////////////
5906 +// Add test files here
5907 +// Google Test will only pick up the tests from the files that are included
5909 +////////////////////////////////////////////////////////////////////////////////
5910 +#include "PxeBcDhcp6GoogleTest.cpp"
5912 +////////////////////////////////////////////////////////////////////////////////
5914 +////////////////////////////////////////////////////////////////////////////////
5915 +int main(int argc, char* argv[]) {
5916 + testing::InitGoogleTest (&argc, argv);
5917 + return RUN_ALL_TESTS ();
5919 \ No newline at end of file
5920 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5921 new file mode 100644
5922 index 0000000000..c2fd7ae7a9
5924 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5927 +# Unit test suite for the UefiPxeBcDxe using Google Test
5929 +# Copyright (c) Microsoft Corporation.<BR>
5930 +# SPDX-License-Identifier: BSD-2-Clause-Patent
5933 +INF_VERSION = 0x00010005
5934 +BASE_NAME = UefiPxeBcDxeGoogleTest
5935 +FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF
5936 +MODULE_TYPE = HOST_APPLICATION
5937 +VERSION_STRING = 1.0
5940 +# The following information is for reference only and not required by the build tools.
5942 +# VALID_ARCHITECTURES = IA32 X64
5946 + UefiPxeBcDxeGoogleTest.cpp
5947 + PxeBcDhcp6GoogleTest.cpp
5953 + MdeModulePkg/MdeModulePkg.dec
5954 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
5955 + NetworkPkg/NetworkPkg.dec
5964 + gEfiDhcp6ServiceBindingProtocolGuid
5965 + gEfiDns6ServiceBindingProtocolGuid
5966 + gEfiDns6ProtocolGuid
5969 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
5973 \ No newline at end of file
5978 From 4412e98d2835b0a8a0c80763bb1ef4d62015aa12 Mon Sep 17 00:00:00 2001
5979 From: Doug Flick <dougflick@microsoft.com>
5980 Date: Mon, 18 Dec 2023 12:45:31 -0800
5981 Subject: [PATCH 11/12] SECURITY PATCH TCBZ4540 - CVE-2023-45235 - Patch
5984 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 85 +++++++++++++++++++++-------
5985 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++
5986 2 files changed, 83 insertions(+), 19 deletions(-)
5988 diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5989 index 4059fae5fc..a3b977fe2a 100644
5990 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5991 +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
5992 @@ -887,6 +887,7 @@ PxeBcRequestBootService (
5994 EFI_DHCP6_PACKET *IndexOffer;
5996 + UINTN DiscoverLenNeeded;
5998 PxeBc = &Private->PxeBc;
5999 Request = Private->Dhcp6Request;
6000 @@ -898,8 +899,9 @@ PxeBcRequestBootService (
6001 if (Request == NULL) {
6002 return EFI_DEVICE_ERROR;
6005 - Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
6007 + DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
6008 + Discover = AllocateZeroPool (DiscoverLenNeeded);
6009 if (Discover == NULL) {
6010 return EFI_OUT_OF_RESOURCES;
6012 @@ -924,16 +926,34 @@ PxeBcRequestBootService (
6015 if (Option == NULL) {
6016 - return EFI_NOT_FOUND;
6017 + Status = EFI_NOT_FOUND;
6022 // Add Server ID Option.
6024 OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);
6025 - CopyMem (DiscoverOpt, Option, OpLen + 4);
6026 - DiscoverOpt += (OpLen + 4);
6027 - DiscoverLen += (OpLen + 4);
6030 + // Check that the minimum and maximum requirements are met
6032 + if (OpLen < PXEBC_MIN_SIZE_OF_DUID || OpLen > PXEBC_MAX_SIZE_OF_DUID) {
6033 + Status = EFI_INVALID_PARAMETER;
6038 + // Check that the option length is valid.
6040 + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) {
6041 + Status = EFI_OUT_OF_RESOURCES;
6045 + CopyMem (DiscoverOpt, Option, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6046 + DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6047 + DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6050 while (RequestLen < Request->Length) {
6051 @@ -944,16 +964,25 @@ PxeBcRequestBootService (
6052 (OpCode != DHCP6_OPT_SERVER_ID)
6057 + // Check that the option length is valid.
6059 + if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {
6060 + Status = EFI_OUT_OF_RESOURCES;
6065 // Copy all the options except IA option and Server ID
6067 - CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
6068 - DiscoverOpt += (OpLen + 4);
6069 - DiscoverLen += (OpLen + 4);
6070 + CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6071 + DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6072 + DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6075 - RequestOpt += (OpLen + 4);
6076 - RequestLen += (OpLen + 4);
6077 + RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6078 + RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6082 @@ -2154,7 +2183,8 @@ PxeBcDhcp6Discover (
6087 + UINTN DiscoverLenNeeded;
6089 PxeBc = &Private->PxeBc;
6091 Request = Private->Dhcp6Request;
6092 @@ -2168,8 +2198,9 @@ PxeBcDhcp6Discover (
6093 if (Request == NULL) {
6094 return EFI_DEVICE_ERROR;
6097 - Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
6099 + DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
6100 + Discover = AllocateZeroPool (DiscoverLenNeeded);
6101 if (Discover == NULL) {
6102 return EFI_OUT_OF_RESOURCES;
6104 @@ -2185,22 +2216,38 @@ PxeBcDhcp6Discover (
6105 DiscoverLen = sizeof (EFI_DHCP6_HEADER);
6106 RequestLen = DiscoverLen;
6109 + // The request packet is generated by the UEFI network stack. In the DHCP4 DORA and DHCP6 SARR sequence,
6110 + // the first (discover in DHCP4 and solicit in DHCP6) and third (request in both DHCP4 and DHCP6) are
6111 + // generated by the DHCP client (the UEFI network stack in this case). By the time this function executes,
6112 + // the DHCP sequence already has been executed once (see UEFI Specification Figures 24.2 and 24.3), with
6113 + // Private->Dhcp6Request being a cached copy of the DHCP6 request packet that UEFI network stack previously
6114 + // generated and sent.
6116 + // Therefore while this code looks like it could overflow, in practice it's not possible.
6118 while (RequestLen < Request->Length) {
6119 OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);
6120 OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);
6121 if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&
6122 (OpCode != EFI_DHCP6_IA_TYPE_TA))
6125 + if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {
6126 + Status = EFI_OUT_OF_RESOURCES;
6131 // Copy all the options except IA option.
6133 - CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
6134 - DiscoverOpt += (OpLen + 4);
6135 - DiscoverLen += (OpLen + 4);
6136 + CopyMem (DiscoverOpt, RequestOpt, OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6137 + DiscoverOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6138 + DiscoverLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6141 - RequestOpt += (OpLen + 4);
6142 - RequestLen += (OpLen + 4);
6143 + RequestOpt += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6144 + RequestLen += (OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN);
6147 Status = PxeBc->UdpWrite (
6148 diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
6149 index c86f6d391b..2f11f0e1d9 100644
6150 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
6151 +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h
6153 #define PXEBC_ADDR_START_DELIMITER '['
6154 #define PXEBC_ADDR_END_DELIMITER ']'
6157 +// A DUID consists of a 2-octet type code represented in network byte
6158 +// order, followed by a variable number of octets that make up the
6159 +// actual identifier. The length of the DUID (not including the type
6160 +// code) is at least 1 octet and at most 128 octets.
6162 +#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1)
6163 +#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128)
6166 +// This define represents the combineds code and length field from
6167 +// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1
6169 +#define PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN \
6170 + (sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpCode) + \
6171 + sizeof (((EFI_DHCP6_PACKET_OPTION *)0)->OpLen))
6173 #define GET_NEXT_DHCP6_OPTION(Opt) \
6174 (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \
6175 sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)
6180 From bef5afa1c2c6868323332dbad0478b85830cd134 Mon Sep 17 00:00:00 2001
6181 From: Doug Flick <dougflick@microsoft.com>
6182 Date: Mon, 18 Dec 2023 12:49:26 -0800
6183 Subject: [PATCH 12/12] SECURITY PATCH TCBZ4540 - CVE-2023-45235 - Host Based
6187 NetworkPkg/Test/NetworkPkgHostTest.dsc | 11 +-
6188 .../GoogleTest/PxeBcDhcp6GoogleTest.cpp | 871 ++++++++++++------
6189 .../GoogleTest/PxeBcDhcp6GoogleTest.h | 18 +
6190 .../GoogleTest/UefiPxeBcDxeGoogleTest.cpp | 42 +-
6191 .../GoogleTest/UefiPxeBcDxeGoogleTest.inf | 92 +-
6192 5 files changed, 661 insertions(+), 373 deletions(-)
6194 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
6195 index b9d031a611..e6c55692a1 100644
6196 --- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
6197 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
6200 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
6201 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
6202 - NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
6203 + NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
6205 + UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
6208 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
6211 # This library provides the instrinsic functions generated by a given compiler.
6212 # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
6215 -!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
6216 - NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
6217 +!if $(TOOL_CHAIN_TAG) == VS2019 or $(TOOL_CHAIN_TAG) == VS2022
6218 + NULL|MdePkg/Library/CompilerIntrinsicsLib/ArmCompilerIntrinsicsLib.inf
6221 NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
6222 [LibraryClasses.ARM]
6223 RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
6224 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
6225 index 9ee805a284..665aff7d72 100644
6226 --- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
6227 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
6230 - Host based unit test for PxeBcDhcp6.c.
6232 - Copyright (c) Microsoft Corporation
6233 - SPDX-License-Identifier: BSD-2-Clause-Patent
6235 -#include <gtest/gtest.h>
6239 -#include <Library/BaseLib.h>
6240 -#include <Library/DebugLib.h>
6241 -#include "../PxeBcImpl.h"
6242 -#include "../PxeBcDhcp6.h"
6243 -#include "PxeBcDhcp6GoogleTest.h"
6246 -///////////////////////////////////////////////////////////////////////////////
6248 -///////////////////////////////////////////////////////////////////////////////
6250 -#define PACKET_SIZE (1500)
6253 - UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
6254 - UINT16 OptionLen; // The length of the option (e.g., 16 bytes)
6255 - UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier
6256 -} DHCP6_OPTION_SERVER_ID;
6258 -///////////////////////////////////////////////////////////////////////////////
6259 -/// Symbol Definitions
6260 -///////////////////////////////////////////////////////////////////////////////
6264 - IN EFI_PXE_BASE_CODE_PROTOCOL *This,
6265 - IN UINT16 OpFlags,
6266 - IN EFI_IP_ADDRESS *DestIp,
6267 - IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
6268 - IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
6269 - IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
6270 - IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
6271 - IN UINTN *HeaderSize OPTIONAL,
6272 - IN VOID *HeaderPtr OPTIONAL,
6273 - IN UINTN *BufferSize,
6274 - IN VOID *BufferPtr
6277 - return EFI_SUCCESS;
6282 - IN EFI_PXE_BASE_CODE_PROTOCOL *This,
6283 - IN UINT16 OpFlags,
6284 - IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,
6285 - IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,
6286 - IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,
6287 - IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
6288 - IN UINTN *HeaderSize OPTIONAL,
6289 - IN VOID *HeaderPtr OPTIONAL,
6290 - IN OUT UINTN *BufferSize,
6291 - IN VOID *BufferPtr
6294 - return EFI_SUCCESS;
6299 - IN EFI_UDP6_PROTOCOL *This,
6300 - IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
6303 - return EFI_SUCCESS;
6306 -// Needed by PxeBcSupport
6310 - IN EFI_TPL DpcTpl,
6311 - IN EFI_DPC_PROCEDURE DpcProcedure,
6312 - IN VOID *DpcContext OPTIONAL
6315 - return EFI_SUCCESS;
6318 -///////////////////////////////////////////////////////////////////////////////
6319 -// PxeBcHandleDhcp6OfferTest Tests
6320 -///////////////////////////////////////////////////////////////////////////////
6322 -class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
6324 -PXEBC_PRIVATE_DATA Private = { 0 };
6325 -EFI_UDP6_PROTOCOL Udp6Read;
6326 -EFI_PXE_BASE_CODE_MODE Mode = { 0 };
6329 -// Add any setup code if needed
6334 - Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6336 - // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6337 - // The function under test really only needs the following:
6341 - Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6342 - Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6344 - // Need to setup EFI_UDP6_PROTOCOL
6345 - // The function under test really only needs the following:
6348 - Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6349 - Private.Udp6Read = &Udp6Read;
6351 - // Need to setup the EFI_PXE_BASE_CODE_MODE
6352 - Private.PxeBc.Mode = &Mode;
6354 - // for this test it doesn't really matter what the Dhcpv6 ack is set to
6357 -// Add any cleanup code if needed
6362 - if (Private.Dhcp6Request != NULL) {
6363 - FreePool (Private.Dhcp6Request);
6366 - // Clean up any resources or variables
6371 -// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
6372 -// properly setup Private structure. Attempting to properly test this function
6373 -// without a signficant refactor is a fools errand. Instead, we will test
6374 -// that we can prevent an overflow in the function.
6375 -TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
6376 - PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6377 - EFI_DHCP6_PACKET_OPTION Option = { 0 };
6379 - Private.SelectIndex = 1; // SelectIndex is 1-based
6380 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6382 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6383 - // Setup the DHCPv6 offer packet
6384 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6385 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
6387 - ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
6390 -class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
6392 -PXEBC_PRIVATE_DATA Private = { 0 };
6395 -// Add any setup code if needed
6402 -// Add any cleanup code if needed
6410 -// Test Description
6411 -// Test that we cache the DNS server address from the DHCPv6 offer packet
6412 -TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
6413 - UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };
6414 - EFI_DHCP6_PACKET_OPTION *Option;
6415 - PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6417 - Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
6418 - ASSERT_NE (Option, nullptr);
6420 - Option->OpCode = DHCP6_OPT_SERVER_ID;
6421 - Option->OpLen = NTOHS (sizeof (SearchPattern));
6422 - CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
6424 - Private.SelectIndex = 1; // SelectIndex is 1-based
6425 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6426 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
6428 - Private.DnsServer = nullptr;
6430 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6431 - ASSERT_NE (Private.DnsServer, nullptr);
6432 - ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);
6434 - if (Private.DnsServer) {
6435 - FreePool (Private.DnsServer);
6439 - FreePool (Option);
6442 -// Test Description
6443 -// Test that we can prevent an overflow in the function
6444 -TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
6445 - EFI_DHCP6_PACKET_OPTION Option = { 0 };
6446 - PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6448 - Private.SelectIndex = 1; // SelectIndex is 1-based
6449 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6450 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6451 - // Setup the DHCPv6 offer packet
6452 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6453 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
6455 - Private.DnsServer = NULL;
6457 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6458 - ASSERT_EQ (Private.DnsServer, nullptr);
6460 - if (Private.DnsServer) {
6461 - FreePool (Private.DnsServer);
6465 -// Test Description
6466 -// Test that we can prevent an underflow in the function
6467 -TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {
6468 - EFI_DHCP6_PACKET_OPTION Option = { 0 };
6469 - PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6471 - Private.SelectIndex = 1; // SelectIndex is 1-based
6472 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6473 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6474 - // Setup the DHCPv6 offer packet
6475 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6476 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2);
6478 - Private.DnsServer = NULL;
6480 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6481 - ASSERT_EQ (Private.DnsServer, nullptr);
6483 - if (Private.DnsServer) {
6484 - FreePool (Private.DnsServer);
6489 -// Test Description
6490 -// Test that we can handle recursive dns (multiple dns entries)
6491 -TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
6492 - EFI_DHCP6_PACKET_OPTION Option = { 0 };
6493 - PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6495 - Private.SelectIndex = 1; // SelectIndex is 1-based
6496 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6497 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6498 - // Setup the DHCPv6 offer packet
6499 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6501 - EFI_IPv6_ADDRESS addresses[2] = {
6502 - // 2001:db8:85a3::8a2e:370:7334
6503 - {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
6504 - // fe80::d478:91c3:ecd7:4ff9
6505 - {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}
6509 - CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
6511 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
6513 - Private.DnsServer = NULL;
6515 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6517 - ASSERT_NE (Private.DnsServer, nullptr);
6520 - // This is expected to fail until DnsServer supports multiple DNS servers
6522 - // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
6524 - ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
6526 - if (Private.DnsServer) {
6527 - FreePool (Private.DnsServer);
6531 + Host based unit test for PxeBcDhcp6.c.
6533 + Copyright (c) Microsoft Corporation
6534 + SPDX-License-Identifier: BSD-2-Clause-Patent
6536 +#include <gtest/gtest.h>
6537 +#include <Library/GoogleTestLib.h>
6538 +#include <GoogleTest/Library/MockUefiLib.h>
6539 +#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
6543 +#include <Library/BaseLib.h>
6544 +#include <Library/DebugLib.h>
6545 +#include "../PxeBcImpl.h"
6546 +#include "../PxeBcDhcp6.h"
6547 +#include "PxeBcDhcp6GoogleTest.h"
6550 +///////////////////////////////////////////////////////////////////////////////
6552 +///////////////////////////////////////////////////////////////////////////////
6554 +#define PACKET_SIZE (1500)
6557 + UINT16 OptionCode; // The option code for DHCP6_OPT_SERVER_ID (e.g., 0x03)
6558 + UINT16 OptionLen; // The length of the option (e.g., 16 bytes)
6559 + UINT8 ServerId[16]; // The 16-byte DHCPv6 Server Identifier
6560 +} DHCP6_OPTION_SERVER_ID;
6562 +///////////////////////////////////////////////////////////////////////////////
6563 +/// Symbol Definitions
6564 +///////////////////////////////////////////////////////////////////////////////
6568 + IN EFI_PXE_BASE_CODE_PROTOCOL *This,
6569 + IN UINT16 OpFlags,
6570 + IN EFI_IP_ADDRESS *DestIp,
6571 + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort,
6572 + IN EFI_IP_ADDRESS *GatewayIp OPTIONAL,
6573 + IN EFI_IP_ADDRESS *SrcIp OPTIONAL,
6574 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
6575 + IN UINTN *HeaderSize OPTIONAL,
6576 + IN VOID *HeaderPtr OPTIONAL,
6577 + IN UINTN *BufferSize,
6578 + IN VOID *BufferPtr
6581 + return EFI_SUCCESS;
6586 + IN EFI_PXE_BASE_CODE_PROTOCOL *This,
6587 + IN UINT16 OpFlags,
6588 + IN OUT EFI_IP_ADDRESS *DestIp OPTIONAL,
6589 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort OPTIONAL,
6590 + IN OUT EFI_IP_ADDRESS *SrcIp OPTIONAL,
6591 + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort OPTIONAL,
6592 + IN UINTN *HeaderSize OPTIONAL,
6593 + IN VOID *HeaderPtr OPTIONAL,
6594 + IN OUT UINTN *BufferSize,
6595 + IN VOID *BufferPtr
6598 + return EFI_SUCCESS;
6603 + IN EFI_UDP6_PROTOCOL *This,
6604 + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
6607 + return EFI_SUCCESS;
6610 +// Needed by PxeBcSupport
6613 + IN PXEBC_PRIVATE_DATA *Private,
6614 + IN CHAR16 *HostName,
6615 + OUT EFI_IPv6_ADDRESS *IpAddress
6618 + return EFI_SUCCESS;
6622 +PxeBcBuildDhcp6Options (
6623 + IN PXEBC_PRIVATE_DATA *Private,
6624 + OUT EFI_DHCP6_PACKET_OPTION **OptList,
6628 + return EFI_SUCCESS;
6634 + IN EFI_TPL DpcTpl,
6635 + IN EFI_DPC_PROCEDURE DpcProcedure,
6636 + IN VOID *DpcContext OPTIONAL
6639 + return EFI_SUCCESS;
6642 +///////////////////////////////////////////////////////////////////////////////
6643 +// PxeBcHandleDhcp6OfferTest Tests
6644 +///////////////////////////////////////////////////////////////////////////////
6646 +class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
6648 +PXEBC_PRIVATE_DATA Private = { 0 };
6649 +EFI_UDP6_PROTOCOL Udp6Read;
6650 +EFI_PXE_BASE_CODE_MODE Mode = { 0 };
6653 +// Add any setup code if needed
6658 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6660 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6661 + // The function under test really only needs the following:
6665 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6666 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6668 + // Need to setup EFI_UDP6_PROTOCOL
6669 + // The function under test really only needs the following:
6672 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6673 + Private.Udp6Read = &Udp6Read;
6675 + // Need to setup the EFI_PXE_BASE_CODE_MODE
6676 + Private.PxeBc.Mode = &Mode;
6678 + // for this test it doesn't really matter what the Dhcpv6 ack is set to
6681 +// Add any cleanup code if needed
6686 + if (Private.Dhcp6Request != NULL) {
6687 + FreePool (Private.Dhcp6Request);
6690 + // Clean up any resources or variables
6695 +// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
6696 +// properly setup Private structure. Attempting to properly test this function
6697 +// without a signficant refactor is a fools errand. Instead, we will test
6698 +// that we can prevent an overflow in the function.
6699 +TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
6700 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6701 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
6703 + Private.SelectIndex = 1; // SelectIndex is 1-based
6704 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6706 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6707 + // Setup the DHCPv6 offer packet
6708 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6709 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
6711 + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
6714 +class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
6716 +PXEBC_PRIVATE_DATA Private = { 0 };
6719 +// Add any setup code if needed
6726 +// Add any cleanup code if needed
6734 +// Test Description
6735 +// Test that we cache the DNS server address from the DHCPv6 offer packet
6736 +TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
6737 + UINT8 SearchPattern[16] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF };
6738 + EFI_DHCP6_PACKET_OPTION *Option;
6739 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6741 + Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
6742 + ASSERT_NE (Option, nullptr);
6744 + Option->OpCode = DHCP6_OPT_SERVER_ID;
6745 + Option->OpLen = NTOHS (sizeof (SearchPattern));
6746 + CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
6748 + Private.SelectIndex = 1; // SelectIndex is 1-based
6749 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6750 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
6752 + Private.DnsServer = nullptr;
6754 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6755 + ASSERT_NE (Private.DnsServer, nullptr);
6756 + ASSERT_EQ (CompareMem (Private.DnsServer, SearchPattern, sizeof (SearchPattern)), 0);
6758 + if (Private.DnsServer) {
6759 + FreePool (Private.DnsServer);
6763 + FreePool (Option);
6766 +// Test Description
6767 +// Test that we can prevent an overflow in the function
6768 +TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
6769 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
6770 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6772 + Private.SelectIndex = 1; // SelectIndex is 1-based
6773 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6774 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6775 + // Setup the DHCPv6 offer packet
6776 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6777 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (1337);
6779 + Private.DnsServer = NULL;
6781 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6782 + ASSERT_EQ (Private.DnsServer, nullptr);
6784 + if (Private.DnsServer) {
6785 + FreePool (Private.DnsServer);
6789 +// Test Description
6790 +// Test that we can prevent an underflow in the function
6791 +TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptUnderflowTest) {
6792 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
6793 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6795 + Private.SelectIndex = 1; // SelectIndex is 1-based
6796 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6797 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6798 + // Setup the DHCPv6 offer packet
6799 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6800 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (2);
6802 + Private.DnsServer = NULL;
6804 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6805 + ASSERT_EQ (Private.DnsServer, nullptr);
6807 + if (Private.DnsServer) {
6808 + FreePool (Private.DnsServer);
6813 +// Test Description
6814 +// Test that we can handle recursive dns (multiple dns entries)
6815 +TEST_F (PxeBcCacheDnsServerAddressesTest, MultipleDnsEntries) {
6816 + EFI_DHCP6_PACKET_OPTION Option = { 0 };
6817 + PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
6819 + Private.SelectIndex = 1; // SelectIndex is 1-based
6820 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6821 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] = &Option;
6822 + // Setup the DHCPv6 offer packet
6823 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpCode = DHCP6_OPT_SERVER_ID;
6825 + EFI_IPv6_ADDRESS addresses[2] = {
6826 + // 2001:db8:85a3::8a2e:370:7334
6827 + {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34},
6828 + // fe80::d478:91c3:ecd7:4ff9
6829 + {0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x78, 0x91, 0xc3, 0xec, 0xd7, 0x4f, 0xf9}
6833 + CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
6835 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
6837 + Private.DnsServer = NULL;
6839 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6841 + ASSERT_NE (Private.DnsServer, nullptr);
6844 + // This is expected to fail until DnsServer supports multiple DNS servers
6846 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
6848 + ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
6850 + if (Private.DnsServer) {
6851 + FreePool (Private.DnsServer);
6855 +///////////////////////////////////////////////////////////////////////////////
6856 +// PxeBcRequestBootServiceTest Test Cases
6857 +///////////////////////////////////////////////////////////////////////////////
6859 +class PxeBcRequestBootServiceTest : public ::testing::Test {
6861 +PXEBC_PRIVATE_DATA Private = { 0 };
6862 +EFI_UDP6_PROTOCOL Udp6Read;
6865 +// Add any setup code if needed
6870 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6872 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6873 + // The function under test really only needs the following:
6877 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6878 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6880 + // Need to setup EFI_UDP6_PROTOCOL
6881 + // The function under test really only needs the following:
6884 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6885 + Private.Udp6Read = &Udp6Read;
6888 +// Add any cleanup code if needed
6893 + if (Private.Dhcp6Request != NULL) {
6894 + FreePool (Private.Dhcp6Request);
6897 + // Clean up any resources or variables
6901 +TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) {
6902 + PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
6904 + DHCP6_OPTION_SERVER_ID Server = { 0 };
6906 + Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
6907 + Server.OptionLen = HTONS (16); // valid length
6910 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
6912 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6914 + CopyMem (Cursor, &Server, sizeof (Server));
6915 + Cursor += sizeof (Server);
6917 + // Update the packet length
6918 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6919 + Packet->Size = PACKET_SIZE;
6921 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
6924 +TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) {
6925 + PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
6927 + DHCP6_OPTION_SERVER_ID Server = { 0 };
6929 + Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
6930 + Server.OptionLen = HTONS (1500); // This length would overflow without a check
6933 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
6935 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6937 + CopyMem (Cursor, &Server, sizeof (Server));
6938 + Cursor += sizeof (Server);
6940 + // Update the packet length
6941 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6942 + Packet->Size = PACKET_SIZE;
6944 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
6947 +TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) {
6948 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
6950 + RequestOpt.OpCode = HTONS (0x1337);
6951 + RequestOpt.OpLen = 0; // valid length
6955 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
6957 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6959 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
6960 + Cursor += sizeof (RequestOpt);
6962 + // Update the packet length
6963 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6964 + Packet->Size = PACKET_SIZE;
6966 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
6969 +TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {
6970 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
6972 + RequestOpt.OpCode = HTONS (0x1337);
6973 + RequestOpt.OpLen = 1500; // this length would overflow without a check
6977 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
6979 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6981 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
6982 + Cursor += sizeof (RequestOpt);
6984 + // Update the packet length
6985 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6986 + Packet->Size = PACKET_SIZE;
6988 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
6991 +///////////////////////////////////////////////////////////////////////////////
6992 +// PxeBcDhcp6Discover Test
6993 +///////////////////////////////////////////////////////////////////////////////
6995 +class PxeBcDhcp6DiscoverTest : public ::testing::Test {
6997 +PXEBC_PRIVATE_DATA Private = { 0 };
6998 +EFI_UDP6_PROTOCOL Udp6Read;
7001 +MockUefiRuntimeServicesTableLib RtServicesMock;
7003 +// Add any setup code if needed
7008 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
7010 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
7011 + // The function under test really only needs the following:
7015 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
7016 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
7018 + // Need to setup EFI_UDP6_PROTOCOL
7019 + // The function under test really only needs the following:
7022 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
7023 + Private.Udp6Read = &Udp6Read;
7026 +// Add any cleanup code if needed
7031 + if (Private.Dhcp6Request != NULL) {
7032 + FreePool (Private.Dhcp6Request);
7035 + // Clean up any resources or variables
7039 +// Test Description
7040 +// This will cause an overflow by an untrusted packet during the option parsing
7041 +TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) {
7042 + EFI_IPv6_ADDRESS DestIp = { 0 };
7043 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
7045 + RequestOpt.OpCode = HTONS (0x1337);
7046 + RequestOpt.OpLen = HTONS (0xFFFF); // overflow
7048 + UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
7050 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
7051 + Cursor += sizeof (RequestOpt);
7053 + Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
7055 + EXPECT_CALL (RtServicesMock, gRT_GetTime)
7056 + .WillOnce (::testing::Return (0));
7059 + PxeBcDhcp6Discover (
7060 + &(PxeBcDhcp6DiscoverTest::Private),
7064 + (EFI_IP_ADDRESS *)&DestIp
7066 + EFI_OUT_OF_RESOURCES
7070 +// Test Description
7071 +// This will test that we can handle a packet with a valid option length
7072 +TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {
7073 + EFI_IPv6_ADDRESS DestIp = { 0 };
7074 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
7076 + RequestOpt.OpCode = HTONS (0x1337);
7077 + RequestOpt.OpLen = HTONS (0x30);
7079 + UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
7081 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
7082 + Cursor += sizeof (RequestOpt);
7084 + Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
7086 + EXPECT_CALL (RtServicesMock, gRT_GetTime)
7087 + .WillOnce (::testing::Return (0));
7090 + PxeBcDhcp6Discover (
7091 + &(PxeBcDhcp6DiscoverTest::Private),
7095 + (EFI_IP_ADDRESS *)&DestIp
7100 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
7101 index 724ee468cb..4d40594d51 100644
7102 --- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
7103 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
7104 @@ -45,4 +45,22 @@ PxeBcCacheDnsServerAddresses (
7105 IN PXEBC_DHCP6_PACKET_CACHE *Cache6
7109 + Build and send out the request packet for the bootfile, and parse the reply.
7111 + @param[in] Private The pointer to PxeBc private data.
7112 + @param[in] Index PxeBc option boot item type.
7114 + @retval EFI_SUCCESS Successfully discovered the boot file.
7115 + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
7116 + @retval EFI_NOT_FOUND Can't get the PXE reply packet.
7117 + @retval Others Failed to discover the boot file.
7121 +PxeBcRequestBootService (
7122 + IN PXEBC_PRIVATE_DATA *Private,
7126 #endif // __PXE_BC_DHCP6_GOOGLE_TEST_H__
7127 \ No newline at end of file
7128 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
7129 index cc295f5c88..32270d0dcb 100644
7130 --- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
7131 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
7134 - Acts as the main entry point for the tests for the UefiPxeBcDxe module.
7135 - Copyright (c) Microsoft Corporation
7136 - SPDX-License-Identifier: BSD-2-Clause-Patent
7138 -#include <gtest/gtest.h>
7140 -////////////////////////////////////////////////////////////////////////////////
7141 -// Add test files here
7142 -// Google Test will only pick up the tests from the files that are included
7144 -////////////////////////////////////////////////////////////////////////////////
7145 -#include "PxeBcDhcp6GoogleTest.cpp"
7147 -////////////////////////////////////////////////////////////////////////////////
7149 -////////////////////////////////////////////////////////////////////////////////
7150 -int main(int argc, char* argv[]) {
7151 - testing::InitGoogleTest (&argc, argv);
7152 - return RUN_ALL_TESTS ();
7154 \ No newline at end of file
7156 + Acts as the main entry point for the tests for the UefiPxeBcDxe module.
7157 + Copyright (c) Microsoft Corporation
7158 + SPDX-License-Identifier: BSD-2-Clause-Patent
7160 +#include <gtest/gtest.h>
7162 +////////////////////////////////////////////////////////////////////////////////
7163 +// Add test files here
7164 +// Google Test will only pick up the tests from the files that are included
7166 +////////////////////////////////////////////////////////////////////////////////
7167 +#include "PxeBcDhcp6GoogleTest.cpp"
7169 +////////////////////////////////////////////////////////////////////////////////
7171 +////////////////////////////////////////////////////////////////////////////////
7172 +int main(int argc, char* argv[]) {
7173 + testing::InitGoogleTest (&argc, argv);
7174 + return RUN_ALL_TESTS ();
7176 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
7177 index c2fd7ae7a9..2d23db0e46 100644
7178 --- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
7179 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
7182 -# Unit test suite for the UefiPxeBcDxe using Google Test
7184 -# Copyright (c) Microsoft Corporation.<BR>
7185 -# SPDX-License-Identifier: BSD-2-Clause-Patent
7188 -INF_VERSION = 0x00010005
7189 -BASE_NAME = UefiPxeBcDxeGoogleTest
7190 -FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF
7191 -MODULE_TYPE = HOST_APPLICATION
7192 -VERSION_STRING = 1.0
7195 -# The following information is for reference only and not required by the build tools.
7197 -# VALID_ARCHITECTURES = IA32 X64
7201 - UefiPxeBcDxeGoogleTest.cpp
7202 - PxeBcDhcp6GoogleTest.cpp
7208 - MdeModulePkg/MdeModulePkg.dec
7209 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
7210 - NetworkPkg/NetworkPkg.dec
7219 - gEfiDhcp6ServiceBindingProtocolGuid
7220 - gEfiDns6ServiceBindingProtocolGuid
7221 - gEfiDns6ProtocolGuid
7224 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
7228 +# Unit test suite for the UefiPxeBcDxe using Google Test
7230 +# Copyright (c) Microsoft Corporation.<BR>
7231 +# SPDX-License-Identifier: BSD-2-Clause-Patent
7234 +INF_VERSION = 0x00010005
7235 +BASE_NAME = UefiPxeBcDxeGoogleTest
7236 +FILE_GUID = 77D45C64-EC1E-4174-887B-886E89FD1EDF
7237 +MODULE_TYPE = HOST_APPLICATION
7238 +VERSION_STRING = 1.0
7241 +# The following information is for reference only and not required by the build tools.
7243 +# VALID_ARCHITECTURES = IA32 X64
7247 + UefiPxeBcDxeGoogleTest.cpp
7248 + PxeBcDhcp6GoogleTest.cpp
7254 + MdeModulePkg/MdeModulePkg.dec
7255 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
7256 + NetworkPkg/NetworkPkg.dec
7265 + gEfiDhcp6ServiceBindingProtocolGuid
7266 + gEfiDns6ServiceBindingProtocolGuid
7267 + gEfiDns6ProtocolGuid
7270 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
7274 \ No newline at end of file