]> git.proxmox.com Git - pve-edk2-firmware.git/blob - debian/patches/CVE-2023-45229_45237.patch
bump version to 4.2023.08-4
[pve-edk2-firmware.git] / debian / patches / CVE-2023-45229_45237.patch
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
5
6 ---
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(-)
12
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')
20
21 +//
22 +// For more information on DHCP options see RFC 8415, Section 21.1
23 +//
24 +// The format of DHCP options is:
25 +//
26 +// 0 1 2 3
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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 +// | option-data |
32 +// | (option-len octets) |
33 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 +//
35 +#define DHCP6_SIZE_OF_OPT_CODE (sizeof(UINT16))
36 +#define DHCP6_SIZE_OF_OPT_LEN (sizeof(UINT16))
37 +
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)
41 +
42 +STATIC_ASSERT (
43 + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN == 4,
44 + "Combined size of Code and Length must be 4 per RFC 8415"
45 + );
46 +
47 +// Offset to the length is just past the code
48 +#define DHCP6_OPT_LEN_OFFSET(a) (a + DHCP6_SIZE_OF_OPT_CODE)
49 +STATIC_ASSERT (
50 + DHCP6_OPT_LEN_OFFSET (0) == 2,
51 + "Offset of length is + 2 past start of option"
52 + );
53 +
54 +#define DHCP6_OPT_DATA_OFFSET(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
55 +STATIC_ASSERT (
56 + DHCP6_OPT_DATA_OFFSET(0) == 4,
57 + "Offset to option data should be +4 from start of option"
58 + );
59 +
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
67 @@ -3,9 +3,9 @@
68
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
72
73 SPDX-License-Identifier: BSD-2-Clause-Patent
74 -
75 **/
76
77 #include "Dhcp6Impl.h"
78 @@ -930,7 +930,8 @@ Dhcp6SendSolicitMsg (
79 //
80 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
81 if (Packet == NULL) {
82 - return EFI_OUT_OF_RESOURCES;
83 + Status = EFI_OUT_OF_RESOURCES;
84 + goto ON_ERROR;
85 }
86
87 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
88 @@ -944,54 +945,64 @@ Dhcp6SendSolicitMsg (
89 Cursor = Packet->Dhcp6.Option;
90
91 Length = HTONS (ClientId->Length);
92 - Cursor = Dhcp6AppendOption (
93 - Cursor,
94 + Status = Dhcp6AppendOption (
95 + Packet,
96 + &Cursor,
97 HTONS (Dhcp6OptClientId),
98 Length,
99 ClientId->Duid
100 );
101 + if (EFI_ERROR (Status)) {
102 + goto ON_ERROR;
103 + }
104
105 - Cursor = Dhcp6AppendETOption (
106 - Cursor,
107 + Status = Dhcp6AppendETOption (
108 + Packet,
109 + &Cursor,
110 Instance,
111 &Elapsed
112 );
113 + if (EFI_ERROR (Status)) {
114 + goto ON_ERROR;
115 + }
116
117 - Cursor = Dhcp6AppendIaOption (
118 - Cursor,
119 + Status = Dhcp6AppendIaOption (
120 + Packet,
121 + &Cursor,
122 Instance->IaCb.Ia,
123 Instance->IaCb.T1,
124 Instance->IaCb.T2,
125 Packet->Dhcp6.Header.MessageType
126 );
127 + if (EFI_ERROR (Status)) {
128 + goto ON_ERROR;
129 + }
130
131 //
132 // Append user-defined when configurate Dhcp6 service.
133 //
134 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
135 UserOpt = Instance->Config->OptionList[Index];
136 - Cursor = Dhcp6AppendOption (
137 - Cursor,
138 + Status = Dhcp6AppendOption (
139 + Packet,
140 + &Cursor,
141 UserOpt->OpCode,
142 UserOpt->OpLen,
143 UserOpt->Data
144 );
145 + if (EFI_ERROR (Status)) {
146 + goto ON_ERROR;
147 + }
148 }
149
150 - //
151 - // Determine the size/length of packet.
152 - //
153 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
154 ASSERT (Packet->Size > Packet->Length + 8);
155
156 //
157 // Callback to user with the packet to be sent and check the user's feedback.
158 //
159 Status = Dhcp6CallbackUser (Instance, Dhcp6SendSolicit, &Packet);
160 -
161 if (EFI_ERROR (Status)) {
162 - FreePool (Packet);
163 - return Status;
164 + goto ON_ERROR;
165 }
166
167 //
168 @@ -1005,10 +1016,8 @@ Dhcp6SendSolicitMsg (
169 Instance->StartTime = 0;
170
171 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
172 -
173 if (EFI_ERROR (Status)) {
174 - FreePool (Packet);
175 - return Status;
176 + goto ON_ERROR;
177 }
178
179 //
180 @@ -1020,6 +1029,14 @@ Dhcp6SendSolicitMsg (
181 Elapsed,
182 Instance->Config->SolicitRetransmission
183 );
184 +
185 +ON_ERROR:
186 +
187 + if (Packet) {
188 + FreePool (Packet);
189 + }
190 +
191 + return Status;
192 }
193
194 /**
195 @@ -1110,7 +1127,8 @@ Dhcp6SendRequestMsg (
196 //
197 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
198 if (Packet == NULL) {
199 - return EFI_OUT_OF_RESOURCES;
200 + Status = EFI_OUT_OF_RESOURCES;
201 + goto ON_ERROR;
202 }
203
204 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
205 @@ -1124,51 +1142,67 @@ Dhcp6SendRequestMsg (
206 Cursor = Packet->Dhcp6.Option;
207
208 Length = HTONS (ClientId->Length);
209 - Cursor = Dhcp6AppendOption (
210 - Cursor,
211 + Status = Dhcp6AppendOption (
212 + Packet,
213 + &Cursor,
214 HTONS (Dhcp6OptClientId),
215 Length,
216 ClientId->Duid
217 );
218 + if (EFI_ERROR (Status)) {
219 + goto ON_ERROR;
220 + }
221
222 - Cursor = Dhcp6AppendETOption (
223 - Cursor,
224 + Status = Dhcp6AppendETOption (
225 + Packet,
226 + &Cursor,
227 Instance,
228 &Elapsed
229 );
230 + if (EFI_ERROR (Status)) {
231 + goto ON_ERROR;
232 + }
233
234 - Cursor = Dhcp6AppendOption (
235 - Cursor,
236 + Status = Dhcp6AppendOption (
237 + Packet,
238 + &Cursor,
239 HTONS (Dhcp6OptServerId),
240 ServerId->Length,
241 ServerId->Duid
242 );
243 + if (EFI_ERROR (Status)) {
244 + goto ON_ERROR;
245 + }
246
247 - Cursor = Dhcp6AppendIaOption (
248 - Cursor,
249 + Status = Dhcp6AppendIaOption (
250 + Packet,
251 + &Cursor,
252 Instance->IaCb.Ia,
253 Instance->IaCb.T1,
254 Instance->IaCb.T2,
255 Packet->Dhcp6.Header.MessageType
256 );
257 + if (EFI_ERROR (Status)) {
258 + goto ON_ERROR;
259 + }
260
261 //
262 // Append user-defined when configurate Dhcp6 service.
263 //
264 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
265 UserOpt = Instance->Config->OptionList[Index];
266 - Cursor = Dhcp6AppendOption (
267 - Cursor,
268 + Status = Dhcp6AppendOption (
269 + Packet,
270 + &Cursor,
271 UserOpt->OpCode,
272 UserOpt->OpLen,
273 UserOpt->Data
274 );
275 + if (EFI_ERROR (Status)) {
276 + goto ON_ERROR;
277 + }
278 }
279
280 - //
281 - // Determine the size/length of packet.
282 - //
283 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
284 ASSERT (Packet->Size > Packet->Length + 8);
285
286 //
287 @@ -1177,8 +1211,7 @@ Dhcp6SendRequestMsg (
288 Status = Dhcp6CallbackUser (Instance, Dhcp6SendRequest, &Packet);
289
290 if (EFI_ERROR (Status)) {
291 - FreePool (Packet);
292 - return Status;
293 + goto ON_ERROR;
294 }
295
296 //
297 @@ -1194,14 +1227,21 @@ Dhcp6SendRequestMsg (
298 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
299
300 if (EFI_ERROR (Status)) {
301 - FreePool (Packet);
302 - return Status;
303 + goto ON_ERROR;
304 }
305
306 //
307 // Enqueue the sent packet for the retransmission in case reply timeout.
308 //
309 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
310 +
311 +ON_ERROR:
312 +
313 + if (Packet) {
314 + FreePool (Packet);
315 + }
316 +
317 + return Status;
318 }
319
320 /**
321 @@ -1266,7 +1306,8 @@ Dhcp6SendDeclineMsg (
322 //
323 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
324 if (Packet == NULL) {
325 - return EFI_OUT_OF_RESOURCES;
326 + Status = EFI_OUT_OF_RESOURCES;
327 + goto ON_ERROR;
328 }
329
330 Packet->Size = DHCP6_BASE_PACKET_SIZE;
331 @@ -1280,42 +1321,58 @@ Dhcp6SendDeclineMsg (
332 Cursor = Packet->Dhcp6.Option;
333
334 Length = HTONS (ClientId->Length);
335 - Cursor = Dhcp6AppendOption (
336 - Cursor,
337 + Status = Dhcp6AppendOption (
338 + Packet,
339 + &Cursor,
340 HTONS (Dhcp6OptClientId),
341 Length,
342 ClientId->Duid
343 );
344 + if (EFI_ERROR (Status)) {
345 + goto ON_ERROR;
346 + }
347
348 - Cursor = Dhcp6AppendETOption (
349 - Cursor,
350 + Status = Dhcp6AppendETOption (
351 + Packet,
352 + &Cursor,
353 Instance,
354 &Elapsed
355 );
356 + if (EFI_ERROR (Status)) {
357 + goto ON_ERROR;
358 + }
359
360 - Cursor = Dhcp6AppendOption (
361 - Cursor,
362 + Status = Dhcp6AppendOption (
363 + Packet,
364 + &Cursor,
365 HTONS (Dhcp6OptServerId),
366 ServerId->Length,
367 ServerId->Duid
368 );
369 + if (EFI_ERROR (Status)) {
370 + goto ON_ERROR;
371 + }
372
373 - Cursor = Dhcp6AppendIaOption (Cursor, DecIa, 0, 0, Packet->Dhcp6.Header.MessageType);
374 + Status = Dhcp6AppendIaOption (
375 + Packet,
376 + &Cursor,
377 + DecIa,
378 + 0,
379 + 0,
380 + Packet->Dhcp6.Header.MessageType
381 + );
382 + if (EFI_ERROR (Status)) {
383 + goto ON_ERROR;
384 + }
385
386 - //
387 - // Determine the size/length of packet.
388 - //
389 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
390 ASSERT (Packet->Size > Packet->Length + 8);
391
392 //
393 // Callback to user with the packet to be sent and check the user's feedback.
394 //
395 Status = Dhcp6CallbackUser (Instance, Dhcp6SendDecline, &Packet);
396 -
397 if (EFI_ERROR (Status)) {
398 - FreePool (Packet);
399 - return Status;
400 + goto ON_ERROR;
401 }
402
403 //
404 @@ -1329,16 +1386,22 @@ Dhcp6SendDeclineMsg (
405 Instance->StartTime = 0;
406
407 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
408 -
409 if (EFI_ERROR (Status)) {
410 - FreePool (Packet);
411 - return Status;
412 + goto ON_ERROR;
413 }
414
415 //
416 // Enqueue the sent packet for the retransmission in case reply timeout.
417 //
418 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
419 +
420 +ON_ERROR:
421 +
422 + if (Packet) {
423 + FreePool (Packet);
424 + }
425 +
426 + return Status;
427 }
428
429 /**
430 @@ -1399,7 +1462,8 @@ Dhcp6SendReleaseMsg (
431 //
432 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE);
433 if (Packet == NULL) {
434 - return EFI_OUT_OF_RESOURCES;
435 + Status = EFI_OUT_OF_RESOURCES;
436 + goto ON_ERROR;
437 }
438
439 Packet->Size = DHCP6_BASE_PACKET_SIZE;
440 @@ -1413,45 +1477,61 @@ Dhcp6SendReleaseMsg (
441 Cursor = Packet->Dhcp6.Option;
442
443 Length = HTONS (ClientId->Length);
444 - Cursor = Dhcp6AppendOption (
445 - Cursor,
446 + Status = Dhcp6AppendOption (
447 + Packet,
448 + &Cursor,
449 HTONS (Dhcp6OptClientId),
450 Length,
451 ClientId->Duid
452 );
453 + if (EFI_ERROR (Status)) {
454 + goto ON_ERROR;
455 + }
456
457 //
458 // ServerId is extracted from packet, it's network order.
459 //
460 - Cursor = Dhcp6AppendOption (
461 - Cursor,
462 + Status = Dhcp6AppendOption (
463 + Packet,
464 + &Cursor,
465 HTONS (Dhcp6OptServerId),
466 ServerId->Length,
467 ServerId->Duid
468 );
469 + if (EFI_ERROR (Status)) {
470 + goto ON_ERROR;
471 + }
472
473 - Cursor = Dhcp6AppendETOption (
474 - Cursor,
475 + Status = Dhcp6AppendETOption (
476 + Packet,
477 + &Cursor,
478 Instance,
479 &Elapsed
480 );
481 + if (EFI_ERROR (Status)) {
482 + goto ON_ERROR;
483 + }
484
485 - Cursor = Dhcp6AppendIaOption (Cursor, RelIa, 0, 0, Packet->Dhcp6.Header.MessageType);
486 + Status = Dhcp6AppendIaOption (
487 + Packet,
488 + &Cursor,
489 + RelIa,
490 + 0,
491 + 0,
492 + Packet->Dhcp6.Header.MessageType
493 + );
494 + if (EFI_ERROR (Status)) {
495 + goto ON_ERROR;
496 + }
497
498 - //
499 - // Determine the size/length of packet
500 - //
501 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
502 ASSERT (Packet->Size > Packet->Length + 8);
503
504 //
505 // Callback to user with the packet to be sent and check the user's feedback.
506 //
507 Status = Dhcp6CallbackUser (Instance, Dhcp6SendRelease, &Packet);
508 -
509 if (EFI_ERROR (Status)) {
510 - FreePool (Packet);
511 - return Status;
512 + goto ON_ERROR;
513 }
514
515 //
516 @@ -1461,16 +1541,22 @@ Dhcp6SendReleaseMsg (
517 Instance->IaCb.Ia->State = Dhcp6Releasing;
518
519 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
520 -
521 if (EFI_ERROR (Status)) {
522 - FreePool (Packet);
523 - return Status;
524 + goto ON_ERROR;
525 }
526
527 //
528 // Enqueue the sent packet for the retransmission in case reply timeout.
529 //
530 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
531 +
532 +ON_ERROR:
533 +
534 + if (Packet) {
535 + FreePool (Packet);
536 + }
537 +
538 + return Status;
539 }
540
541 /**
542 @@ -1524,12 +1610,14 @@ Dhcp6SendRenewRebindMsg (
543 UserLen += (NTOHS (Instance->Config->OptionList[Index]->OpLen) + 4);
544 }
545
546 +
547 //
548 // Create the Dhcp6 packet and initialize common fields.
549 //
550 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
551 if (Packet == NULL) {
552 - return EFI_OUT_OF_RESOURCES;
553 + Status = EFI_OUT_OF_RESOURCES;
554 + goto ON_ERROR;
555 }
556
557 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
558 @@ -1543,26 +1631,38 @@ Dhcp6SendRenewRebindMsg (
559 Cursor = Packet->Dhcp6.Option;
560
561 Length = HTONS (ClientId->Length);
562 - Cursor = Dhcp6AppendOption (
563 - Cursor,
564 + Status = Dhcp6AppendOption (
565 + Packet,
566 + &Cursor,
567 HTONS (Dhcp6OptClientId),
568 Length,
569 ClientId->Duid
570 );
571 + if (EFI_ERROR (Status)) {
572 + goto ON_ERROR;
573 + }
574
575 - Cursor = Dhcp6AppendETOption (
576 - Cursor,
577 + Status = Dhcp6AppendETOption (
578 + Packet,
579 + &Cursor,
580 Instance,
581 &Elapsed
582 );
583 + if (EFI_ERROR (Status)) {
584 + goto ON_ERROR;
585 + }
586
587 - Cursor = Dhcp6AppendIaOption (
588 - Cursor,
589 + Status = Dhcp6AppendIaOption (
590 + Packet,
591 + &Cursor,
592 Instance->IaCb.Ia,
593 Instance->IaCb.T1,
594 Instance->IaCb.T2,
595 Packet->Dhcp6.Header.MessageType
596 );
597 + if (EFI_ERROR (Status)) {
598 + goto ON_ERROR;
599 + }
600
601 if (!RebindRequest) {
602 //
603 @@ -1578,18 +1678,22 @@ Dhcp6SendRenewRebindMsg (
604 Dhcp6OptServerId
605 );
606 if (Option == NULL) {
607 - FreePool (Packet);
608 - return EFI_DEVICE_ERROR;
609 + Status = EFI_DEVICE_ERROR;
610 + goto ON_ERROR;
611 }
612
613 ServerId = (EFI_DHCP6_DUID *)(Option + 2);
614
615 - Cursor = Dhcp6AppendOption (
616 - Cursor,
617 + Status = Dhcp6AppendOption (
618 + Packet,
619 + &Cursor,
620 HTONS (Dhcp6OptServerId),
621 ServerId->Length,
622 ServerId->Duid
623 );
624 + if (EFI_ERROR (Status)) {
625 + goto ON_ERROR;
626 + }
627 }
628
629 //
630 @@ -1597,18 +1701,19 @@ Dhcp6SendRenewRebindMsg (
631 //
632 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
633 UserOpt = Instance->Config->OptionList[Index];
634 - Cursor = Dhcp6AppendOption (
635 - Cursor,
636 + Status = Dhcp6AppendOption (
637 + Packet,
638 + &Cursor,
639 UserOpt->OpCode,
640 UserOpt->OpLen,
641 UserOpt->Data
642 );
643 + if (EFI_ERROR (Status)) {
644 + goto ON_ERROR;
645 + }
646 }
647
648 - //
649 - // Determine the size/length of packet.
650 - //
651 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
652 +
653 ASSERT (Packet->Size > Packet->Length + 8);
654
655 //
656 @@ -1618,10 +1723,8 @@ Dhcp6SendRenewRebindMsg (
657 Event = (RebindRequest) ? Dhcp6EnterRebinding : Dhcp6EnterRenewing;
658
659 Status = Dhcp6CallbackUser (Instance, Event, &Packet);
660 -
661 if (EFI_ERROR (Status)) {
662 - FreePool (Packet);
663 - return Status;
664 + goto ON_ERROR;
665 }
666
667 //
668 @@ -1638,16 +1741,22 @@ Dhcp6SendRenewRebindMsg (
669 Instance->StartTime = 0;
670
671 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
672 -
673 if (EFI_ERROR (Status)) {
674 - FreePool (Packet);
675 - return Status;
676 + goto ON_ERROR;
677 }
678
679 //
680 // Enqueue the sent packet for the retransmission in case reply timeout.
681 //
682 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
683 +
684 +ON_ERROR:
685 +
686 + if (Packet) {
687 + FreePool (Packet);
688 + }
689 +
690 + return Status;
691 }
692
693 /**
694 @@ -1811,7 +1920,8 @@ Dhcp6SendInfoRequestMsg (
695 //
696 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
697 if (Packet == NULL) {
698 - return EFI_OUT_OF_RESOURCES;
699 + Status = EFI_OUT_OF_RESOURCES;
700 + goto ON_ERROR;
701 }
702
703 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
704 @@ -1828,44 +1938,56 @@ Dhcp6SendInfoRequestMsg (
705
706 if (SendClientId) {
707 Length = HTONS (ClientId->Length);
708 - Cursor = Dhcp6AppendOption (
709 - Cursor,
710 + Status = Dhcp6AppendOption (
711 + Packet,
712 + &Cursor,
713 HTONS (Dhcp6OptClientId),
714 Length,
715 ClientId->Duid
716 );
717 + if (EFI_ERROR (Status)) {
718 + goto ON_ERROR;
719 + }
720 }
721
722 - Cursor = Dhcp6AppendETOption (
723 - Cursor,
724 + Status = Dhcp6AppendETOption (
725 + Packet,
726 + &Cursor,
727 Instance,
728 &Elapsed
729 );
730 + if (EFI_ERROR (Status)) {
731 + goto ON_ERROR;
732 + }
733
734 - Cursor = Dhcp6AppendOption (
735 - Cursor,
736 + Status = Dhcp6AppendOption (
737 + Packet,
738 + &Cursor,
739 OptionRequest->OpCode,
740 OptionRequest->OpLen,
741 OptionRequest->Data
742 );
743 + if (EFI_ERROR (Status)) {
744 + goto ON_ERROR;
745 + }
746
747 //
748 // Append user-defined when configurate Dhcp6 service.
749 //
750 for (Index = 0; Index < OptionCount; Index++) {
751 UserOpt = OptionList[Index];
752 - Cursor = Dhcp6AppendOption (
753 - Cursor,
754 + Status = Dhcp6AppendOption (
755 + Packet,
756 + &Cursor,
757 UserOpt->OpCode,
758 UserOpt->OpLen,
759 UserOpt->Data
760 );
761 + if (EFI_ERROR (Status)) {
762 + goto ON_ERROR;
763 + }
764 }
765
766 - //
767 - // Determine the size/length of packet.
768 - //
769 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
770 ASSERT (Packet->Size > Packet->Length + 8);
771
772 //
773 @@ -1877,16 +1999,22 @@ Dhcp6SendInfoRequestMsg (
774 // Send info-request packet with no state.
775 //
776 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
777 -
778 if (EFI_ERROR (Status)) {
779 - FreePool (Packet);
780 - return Status;
781 + goto ON_ERROR;
782 }
783
784 //
785 // Enqueue the sent packet for the retransmission in case reply timeout.
786 //
787 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, Retransmission);
788 +
789 +ON_ERROR:
790 +
791 + if (Packet) {
792 + FreePool (Packet);
793 + }
794 +
795 + return Status;
796 }
797
798 /**
799 @@ -1937,7 +2065,8 @@ Dhcp6SendConfirmMsg (
800 //
801 Packet = AllocateZeroPool (DHCP6_BASE_PACKET_SIZE + UserLen);
802 if (Packet == NULL) {
803 - return EFI_OUT_OF_RESOURCES;
804 + Status = EFI_OUT_OF_RESOURCES;
805 + goto ON_ERROR;
806 }
807
808 Packet->Size = DHCP6_BASE_PACKET_SIZE + UserLen;
809 @@ -1951,54 +2080,64 @@ Dhcp6SendConfirmMsg (
810 Cursor = Packet->Dhcp6.Option;
811
812 Length = HTONS (ClientId->Length);
813 - Cursor = Dhcp6AppendOption (
814 - Cursor,
815 + Status = Dhcp6AppendOption (
816 + Packet,
817 + &Cursor,
818 HTONS (Dhcp6OptClientId),
819 Length,
820 ClientId->Duid
821 );
822 + if (EFI_ERROR (Status)) {
823 + goto ON_ERROR;
824 + }
825
826 - Cursor = Dhcp6AppendETOption (
827 - Cursor,
828 + Status = Dhcp6AppendETOption (
829 + Packet,
830 + &Cursor,
831 Instance,
832 &Elapsed
833 );
834 + if (EFI_ERROR (Status)) {
835 + goto ON_ERROR;
836 + }
837
838 - Cursor = Dhcp6AppendIaOption (
839 - Cursor,
840 + Status = Dhcp6AppendIaOption (
841 + Packet,
842 + &Cursor,
843 Instance->IaCb.Ia,
844 Instance->IaCb.T1,
845 Instance->IaCb.T2,
846 Packet->Dhcp6.Header.MessageType
847 );
848 + if (EFI_ERROR (Status)) {
849 + goto ON_ERROR;
850 + }
851
852 //
853 // Append user-defined when configurate Dhcp6 service.
854 //
855 for (Index = 0; Index < Instance->Config->OptionCount; Index++) {
856 UserOpt = Instance->Config->OptionList[Index];
857 - Cursor = Dhcp6AppendOption (
858 - Cursor,
859 + Status = Dhcp6AppendOption (
860 + Packet,
861 + &Cursor,
862 UserOpt->OpCode,
863 UserOpt->OpLen,
864 UserOpt->Data
865 );
866 + if (EFI_ERROR (Status)) {
867 + goto ON_ERROR;
868 + }
869 }
870
871 - //
872 - // Determine the size/length of packet.
873 - //
874 - Packet->Length += (UINT32)(Cursor - Packet->Dhcp6.Option);
875 ASSERT (Packet->Size > Packet->Length + 8);
876
877 //
878 // Callback to user with the packet to be sent and check the user's feedback.
879 //
880 Status = Dhcp6CallbackUser (Instance, Dhcp6SendConfirm, &Packet);
881 -
882 if (EFI_ERROR (Status)) {
883 - FreePool (Packet);
884 - return Status;
885 + goto ON_ERROR;
886 }
887
888 //
889 @@ -2012,16 +2151,22 @@ Dhcp6SendConfirmMsg (
890 Instance->StartTime = 0;
891
892 Status = Dhcp6TransmitPacket (Instance, Packet, Elapsed);
893 -
894 if (EFI_ERROR (Status)) {
895 - FreePool (Packet);
896 - return Status;
897 + goto ON_ERROR;
898 }
899
900 //
901 // Enqueue the sent packet for the retransmission in case reply timeout.
902 //
903 return Dhcp6EnqueueRetry (Instance, Packet, Elapsed, NULL);
904 +
905 +ON_ERROR:
906 +
907 + if (Packet) {
908 + FreePool(Packet);
909 + }
910 +
911 + return Status;
912 }
913
914 /**
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 (
920 }
921
922 Status = gRT->SetVariable (
923 - L"ClientId",
924 - &gEfiDhcp6ServiceBindingProtocolGuid,
925 - (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
926 - Duid->Length + 2,
927 - (VOID *)Duid
928 - );
929 + L"ClientId",
930 + &gEfiDhcp6ServiceBindingProtocolGuid,
931 + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
932 + Duid->Length + 2,
933 + (VOID *)Duid
934 + );
935 if (EFI_ERROR (Status)) {
936 FreePool (Duid);
937 return NULL;
938 @@ -192,10 +192,10 @@ Dhcp6CopyConfigData (
939 }
940
941 CopyMem (
942 - DstCfg->SolicitRetransmission,
943 - SorCfg->SolicitRetransmission,
944 - sizeof (EFI_DHCP6_RETRANSMISSION)
945 - );
946 + DstCfg->SolicitRetransmission,
947 + SorCfg->SolicitRetransmission,
948 + sizeof (EFI_DHCP6_RETRANSMISSION)
949 + );
950 }
951
952 if ((SorCfg->OptionList != NULL) && (SorCfg->OptionCount != 0)) {
953 @@ -221,10 +221,10 @@ Dhcp6CopyConfigData (
954 }
955
956 CopyMem (
957 - DstCfg->OptionList[Index],
958 - SorCfg->OptionList[Index],
959 - OptionSize
960 - );
961 + DstCfg->OptionList[Index],
962 + SorCfg->OptionList[Index],
963 + OptionSize
964 + );
965 }
966 }
967
968 @@ -422,10 +422,10 @@ Dhcp6CheckAddress (
969
970 for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
971 if (CompareMem (
972 - &Addresses[Index1],
973 - &Ia->IaAddress[Index2],
974 - sizeof (EFI_IPv6_ADDRESS)
975 - ) == 0)
976 + &Addresses[Index1],
977 + &Ia->IaAddress[Index2],
978 + sizeof (EFI_IPv6_ADDRESS)
979 + ) == 0)
980 {
981 Found = TRUE;
982 break;
983 @@ -503,28 +503,28 @@ Dhcp6DepriveAddress (
984
985 for (Index2 = 0; Index2 < Ia->IaAddressCount; Index2++) {
986 if (CompareMem (
987 - &Addresses[Index1],
988 - &Ia->IaAddress[Index2],
989 - sizeof (EFI_IPv6_ADDRESS)
990 - ) == 0)
991 + &Addresses[Index1],
992 + &Ia->IaAddress[Index2],
993 + sizeof (EFI_IPv6_ADDRESS)
994 + ) == 0)
995 {
996 //
997 // Copy the deprived address to the copy of Ia
998 //
999 CopyMem (
1000 - &IaCopy->IaAddress[Index1],
1001 - &Ia->IaAddress[Index2],
1002 - sizeof (EFI_DHCP6_IA_ADDRESS)
1003 - );
1004 + &IaCopy->IaAddress[Index1],
1005 + &Ia->IaAddress[Index2],
1006 + sizeof (EFI_DHCP6_IA_ADDRESS)
1007 + );
1008 //
1009 // Delete the deprived address from the instance Ia
1010 //
1011 if (Index2 + 1 < Ia->IaAddressCount) {
1012 CopyMem (
1013 - &Ia->IaAddress[Index2],
1014 - &Ia->IaAddress[Index2 + 1],
1015 - (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
1016 - );
1017 + &Ia->IaAddress[Index2],
1018 + &Ia->IaAddress[Index2 + 1],
1019 + (Ia->IaAddressCount - Index2 - 1) * sizeof (EFI_DHCP6_IA_ADDRESS)
1020 + );
1021 }
1022
1023 Found = TRUE;
1024 @@ -577,24 +577,33 @@ Dhcp6OnTransmitted (
1025 }
1026
1027 /**
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.
1030
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
1036 + will be updated.
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.
1042
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.
1047
1048 **/
1049 -UINT8 *
1050 +EFI_STATUS
1051 Dhcp6AppendOption (
1052 - IN OUT UINT8 *Buf,
1053 - IN UINT16 OptType,
1054 - IN UINT16 OptLen,
1055 - IN UINT8 *Data
1056 + IN OUT EFI_DHCP6_PACKET *Packet,
1057 + IN OUT UINT8 **PacketCursor,
1058 + IN UINT16 OptType,
1059 + IN UINT16 OptLen,
1060 + IN UINT8 *Data
1061 )
1062 {
1063 + UINT32 Length;
1064 + UINT32 BytesNeeded;
1065 +
1066 //
1067 // The format of Dhcp6 option:
1068 //
1069 @@ -607,35 +616,95 @@ Dhcp6AppendOption (
1070 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1071 //
1072
1073 - ASSERT (OptLen != 0);
1074 + //
1075 + // Verify the arguments are valid
1076 + //
1077 + if (Packet == NULL) {
1078 + return EFI_INVALID_PARAMETER;
1079 + }
1080 +
1081 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1082 + return EFI_INVALID_PARAMETER;
1083 + }
1084 +
1085 + if (Data == NULL) {
1086 + return EFI_INVALID_PARAMETER;
1087 + }
1088 +
1089 + if (OptLen == 0) {
1090 + return EFI_INVALID_PARAMETER;
1091 + }
1092 +
1093 + //
1094 + // Verify the PacketCursor is within the packet
1095 + //
1096 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1097 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1098 + {
1099 + return EFI_INVALID_PARAMETER;
1100 + }
1101 +
1102 + //
1103 + // Calculate the bytes needed for the option
1104 + //
1105 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + NTOHS(OptLen);
1106
1107 - WriteUnaligned16 ((UINT16 *)Buf, OptType);
1108 - Buf += 2;
1109 - WriteUnaligned16 ((UINT16 *)Buf, OptLen);
1110 - Buf += 2;
1111 - CopyMem (Buf, Data, NTOHS (OptLen));
1112 - Buf += NTOHS (OptLen);
1113 + //
1114 + // Space remaining in the packet
1115 + //
1116 + Length = Packet->Size - Packet->Length;
1117 + if (Length < BytesNeeded) {
1118 + return EFI_BUFFER_TOO_SMALL;
1119 + }
1120 +
1121 + //
1122 + // Verify the PacketCursor is within the packet
1123 + //
1124 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1125 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1126 + {
1127 + return EFI_INVALID_PARAMETER;
1128 + }
1129
1130 - return Buf;
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);
1137 +
1138 + // Update the packet length by the length of the option + 4 bytes
1139 + Packet->Length += BytesNeeded;
1140 +
1141 + return EFI_SUCCESS;
1142 }
1143
1144 /**
1145 Append the appointed IA Address option to Buf, and move Buf to the end.
1146
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
1149 + will be updated.
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.
1154
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.
1159
1160 **/
1161 -UINT8 *
1162 +EFI_STATUS
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
1169 )
1170 {
1171 + UINT32 BytesNeeded;
1172 + UINT32 Length;
1173 +
1174 // The format of the IA Address option is:
1175 //
1176 // 0 1 2 3
1177 @@ -657,17 +726,60 @@ Dhcp6AppendIaAddrOption (
1178 // . .
1179 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1180
1181 + //
1182 + // Verify the arguments are valid
1183 + //
1184 + if (Packet == NULL) {
1185 + return EFI_INVALID_PARAMETER;
1186 + }
1187 +
1188 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1189 + return EFI_INVALID_PARAMETER;
1190 + }
1191 +
1192 + if (IaAddr == NULL) {
1193 + return EFI_INVALID_PARAMETER;
1194 + }
1195 +
1196 + //
1197 + // Verify the PacketCursor is within the packet
1198 + //
1199 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1200 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1201 + {
1202 + return EFI_INVALID_PARAMETER;
1203 + }
1204 +
1205 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1206 + BytesNeeded += sizeof (EFI_IPv6_ADDRESS);
1207 + //
1208 + // Even if the preferred-lifetime is 0, it still needs to store it.
1209 + //
1210 + BytesNeeded += sizeof (IaAddr->PreferredLifetime);
1211 + //
1212 + // Even if the valid-lifetime is 0, it still needs to store it.
1213 + //
1214 + BytesNeeded += sizeof (IaAddr->ValidLifetime);
1215 +
1216 + //
1217 + // Space remaining in the packet
1218 + //
1219 + Length = Packet->Size - Packet->Length;
1220 + if (Length < BytesNeeded) {
1221 + return EFI_BUFFER_TOO_SMALL;
1222 + }
1223 +
1224 //
1225 // Fill the value of Ia Address option type
1226 //
1227 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptIaAddr));
1228 - Buf += 2;
1229 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptIaAddr));
1230 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1231
1232 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
1233 - Buf += 2;
1234 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (sizeof (EFI_DHCP6_IA_ADDRESS)));
1235 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1236
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);
1241
1242 //
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.
1246 //
1247 if (MessageType != Dhcp6MsgConfirm) {
1248 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->PreferredLifetime));
1249 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->PreferredLifetime));
1250 }
1251
1252 - Buf += 4;
1253 + *PacketCursor += sizeof (IaAddr->PreferredLifetime);
1254
1255 if (MessageType != Dhcp6MsgConfirm) {
1256 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (IaAddr->ValidLifetime));
1257 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (IaAddr->ValidLifetime));
1258 }
1259
1260 - Buf += 4;
1261 + *PacketCursor += sizeof (IaAddr->ValidLifetime);
1262 +
1263 + //
1264 + // Update the packet length
1265 + //
1266 + Packet->Length += BytesNeeded;
1267
1268 - return Buf;
1269 + return EFI_SUCCESS;
1270 }
1271
1272 /**
1273 Append the appointed Ia option to Buf, and move Buf to the end.
1274
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
1277 + will be updated.
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.
1284
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.
1289
1290 **/
1291 -UINT8 *
1292 +EFI_STATUS
1293 Dhcp6AppendIaOption (
1294 - IN OUT UINT8 *Buf,
1295 - IN EFI_DHCP6_IA *Ia,
1296 - IN UINT32 T1,
1297 - IN UINT32 T2,
1298 - IN UINT32 MessageType
1299 + IN OUT EFI_DHCP6_PACKET *Packet,
1300 + IN OUT UINT8 **PacketCursor,
1301 + IN EFI_DHCP6_IA *Ia,
1302 + IN UINT32 T1,
1303 + IN UINT32 T2,
1304 + IN UINT32 MessageType
1305 )
1306 {
1307 - UINT8 *AddrOpt;
1308 - UINT16 *Len;
1309 - UINTN Index;
1310 + UINT8 *AddrOpt;
1311 + UINT16 *Len;
1312 + UINTN Index;
1313 + UINT32 BytesNeeded;
1314 + UINT32 Length;
1315 + EFI_STATUS Status;
1316
1317 //
1318 // The format of IA_NA and IA_TA option:
1319 @@ -733,32 +859,74 @@ Dhcp6AppendIaOption (
1320 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1321 //
1322
1323 + //
1324 + // Verify the arguments are valid
1325 + //
1326 + if (Packet == NULL) {
1327 + return EFI_INVALID_PARAMETER;
1328 + }
1329 +
1330 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1331 + return EFI_INVALID_PARAMETER;
1332 + }
1333 +
1334 + if (Ia == NULL) {
1335 + return EFI_INVALID_PARAMETER;
1336 + }
1337 +
1338 + //
1339 + // Verify the PacketCursor is within the packet
1340 + //
1341 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1342 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1343 + {
1344 + return EFI_INVALID_PARAMETER;
1345 + }
1346 +
1347 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1348 + BytesNeeded += sizeof (Ia->Descriptor.IaId);
1349 + //
1350 + // + N for the IA_NA-options/IA_TA-options
1351 + // Dhcp6AppendIaAddrOption will need to check the length for each address
1352 + //
1353 + if (Ia->Descriptor.Type == Dhcp6OptIana) {
1354 + BytesNeeded += sizeof (T1) + sizeof (T2);
1355 + }
1356 +
1357 + //
1358 + // Space remaining in the packet
1359 + //
1360 + Length = (UINT16)(Packet->Size - Packet->Length);
1361 + if (Length < BytesNeeded) {
1362 + return EFI_BUFFER_TOO_SMALL;
1363 + }
1364 +
1365 //
1366 // Fill the value of Ia option type
1367 //
1368 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Ia->Descriptor.Type));
1369 - Buf += 2;
1370 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Ia->Descriptor.Type));
1371 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1372
1373 //
1374 // Fill the len of Ia option later, keep the pointer first
1375 //
1376 - Len = (UINT16 *)Buf;
1377 - Buf += 2;
1378 + Len = (UINT16 *)*PacketCursor;
1379 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1380
1381 //
1382 // Fill the value of iaid
1383 //
1384 - WriteUnaligned32 ((UINT32 *)Buf, HTONL (Ia->Descriptor.IaId));
1385 - Buf += 4;
1386 + WriteUnaligned32 ((UINT32 *)*PacketCursor, HTONL (Ia->Descriptor.IaId));
1387 + *PacketCursor += sizeof (Ia->Descriptor.IaId);
1388
1389 //
1390 // Fill the value of t1 and t2 if iana, keep it 0xffffffff if no specified.
1391 //
1392 if (Ia->Descriptor.Type == Dhcp6OptIana) {
1393 - WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T1 != 0) ? T1 : 0xffffffff));
1394 - Buf += 4;
1395 - WriteUnaligned32 ((UINT32 *)Buf, HTONL ((T2 != 0) ? T2 : 0xffffffff));
1396 - Buf += 4;
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);
1401 }
1402
1403 //
1404 @@ -766,35 +934,51 @@ Dhcp6AppendIaOption (
1405 //
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)) {
1411 + return Status;
1412 + }
1413 }
1414
1415 //
1416 // Fill the value of Ia option length
1417 //
1418 - *Len = HTONS ((UINT16)(Buf - (UINT8 *)Len - 2));
1419 + *Len = HTONS ((UINT16)(*PacketCursor - (UINT8 *)Len - 2));
1420
1421 - return Buf;
1422 + //
1423 + // Update the packet length
1424 + //
1425 + Packet->Length += BytesNeeded;
1426 +
1427 + return EFI_SUCCESS;
1428 }
1429
1430 /**
1431 Append the appointed Elapsed time option to Buf, and move Buf to the end.
1432
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.
1441
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.
1446
1447 **/
1448 -UINT8 *
1449 +EFI_STATUS
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
1458 )
1459 {
1460 + UINT32 BytesNeeded;
1461 + UINT32 Length;
1462 +
1463 //
1464 // The format of elapsed time option:
1465 //
1466 @@ -806,27 +990,70 @@ Dhcp6AppendETOption (
1467 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1468 //
1469
1470 + //
1471 + // Verify the arguments are valid
1472 + //
1473 + if (Packet == NULL) {
1474 + return EFI_INVALID_PARAMETER;
1475 + }
1476 +
1477 + if ((PacketCursor == NULL) || (*PacketCursor == NULL)) {
1478 + return EFI_INVALID_PARAMETER;
1479 + }
1480 +
1481 + if (Instance == NULL) {
1482 + return EFI_INVALID_PARAMETER;
1483 + }
1484 +
1485 + if ((Elapsed == NULL)) {
1486 + return EFI_INVALID_PARAMETER;
1487 + }
1488 +
1489 + //
1490 + // Verify the PacketCursor is within the packet
1491 + //
1492 + if ( (*PacketCursor < Packet->Dhcp6.Option)
1493 + || (*PacketCursor >= Packet->Dhcp6.Option + (Packet->Size - sizeof (EFI_DHCP6_HEADER))))
1494 + {
1495 + return EFI_INVALID_PARAMETER;
1496 + }
1497 +
1498 + BytesNeeded = DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN;
1499 + //
1500 + // + 2 for elapsed-time
1501 + //
1502 + BytesNeeded += sizeof (UINT16);
1503 + //
1504 + // Space remaining in the packet
1505 + //
1506 + Length = Packet->Size - Packet->Length;
1507 + if (Length < BytesNeeded) {
1508 + return EFI_BUFFER_TOO_SMALL;
1509 + }
1510 +
1511 //
1512 // Fill the value of elapsed-time option type.
1513 //
1514 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (Dhcp6OptElapsedTime));
1515 - Buf += 2;
1516 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (Dhcp6OptElapsedTime));
1517 + *PacketCursor += DHCP6_SIZE_OF_OPT_CODE;
1518
1519 //
1520 // Fill the len of elapsed-time option, which is fixed.
1521 //
1522 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (2));
1523 - Buf += 2;
1524 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (2));
1525 + *PacketCursor += DHCP6_SIZE_OF_OPT_LEN;
1526
1527 //
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.
1530 //
1531 - WriteUnaligned16 ((UINT16 *)Buf, HTONS (0));
1532 - *Elapsed = (UINT16 *)Buf;
1533 - Buf += 2;
1534 + WriteUnaligned16 ((UINT16 *)*PacketCursor, HTONS (0));
1535 + *Elapsed = (UINT16 *)*PacketCursor;
1536 + *PacketCursor += sizeof (UINT16);
1537 +
1538 + Packet->Length += BytesNeeded;
1539
1540 - return Buf;
1541 + return EFI_SUCCESS;
1542 }
1543
1544 /**
1545 @@ -852,13 +1079,13 @@ SetElapsedTime (
1546 //
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,
1550 - 100
1551 - ) +
1552 + ((((UINT32)(Time.Year - 2000) * 360 + (Time.Month - 1) * 30 + (Time.Day - 1)) * 24 + Time.Hour) * 60 + Time.Minute) * 60 + Time.Second,
1553 + 100
1554 + ) +
1555 DivU64x32 (
1556 - Time.Nanosecond,
1557 - 10000000
1558 - );
1559 + Time.Nanosecond,
1560 + 10000000
1561 + );
1562
1563 //
1564 // Sentinel value of 0 means that this is the first DHCP packet that we are
1565 @@ -1290,11 +1517,11 @@ Dhcp6GetMappingTimeOut (
1566
1567 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
1568 Status = Ip6Cfg->GetData (
1569 - Ip6Cfg,
1570 - Ip6ConfigDataTypeDupAddrDetectTransmits,
1571 - &DataSize,
1572 - &DadXmits
1573 - );
1574 + Ip6Cfg,
1575 + Ip6ConfigDataTypeDupAddrDetectTransmits,
1576 + &DataSize,
1577 + &DadXmits
1578 + );
1579 if (EFI_ERROR (Status)) {
1580 return Status;
1581 }
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 (
1587 );
1588
1589 /**
1590 - Append the appointed option to the buf, and move the buf to the end.
1591 -
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.
1596 -
1597 - @return Buf The position to append the next option.
1598 -
1599 + Append the option to Buf, update the length of packet, and move Buf to the end.
1600 +
1601 + @param[in, out] Packet A pointer to the packet, on success Packet->Length
1602 + will be updated.
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.
1608 +
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.
1612 **/
1613 -UINT8 *
1614 +EFI_STATUS
1615 Dhcp6AppendOption (
1616 - IN OUT UINT8 *Buf,
1617 - IN UINT16 OptType,
1618 - IN UINT16 OptLen,
1619 - IN UINT8 *Data
1620 + IN OUT EFI_DHCP6_PACKET *Packet,
1621 + IN OUT UINT8 **PacketCursor,
1622 + IN UINT16 OptType,
1623 + IN UINT16 OptLen,
1624 + IN UINT8 *Data
1625 );
1626
1627 /**
1628 - Append the Ia option to Buf, and move Buf to the end.
1629 -
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
1634 + will be updated.
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.
1641
1642 - @return Buf The position to append the next Ia option.
1643 -
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.
1647 **/
1648 -UINT8 *
1649 +EFI_STATUS
1650 Dhcp6AppendIaOption (
1651 - IN OUT UINT8 *Buf,
1652 - IN EFI_DHCP6_IA *Ia,
1653 - IN UINT32 T1,
1654 - IN UINT32 T2,
1655 - IN UINT32 MessageType
1656 + IN OUT EFI_DHCP6_PACKET *Packet,
1657 + IN OUT UINT8 **PacketCursor,
1658 + IN EFI_DHCP6_IA *Ia,
1659 + IN UINT32 T1,
1660 + IN UINT32 T2,
1661 + IN UINT32 MessageType
1662 );
1663
1664 /**
1665 Append the appointed Elapsed time option to Buf, and move Buf to the end.
1666
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.
1674
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.
1679
1680 **/
1681 -UINT8 *
1682 +EFI_STATUS
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
1691 );
1692
1693 /**
1694 Set the elapsed time based on the given instance and the pointer to the
1695 elapsed time option.
1696
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.
1702 **/
1703 VOID
1704 SetElapsedTime (
1705 --
1706 2.41.0
1707
1708
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
1713 Unit Test
1714
1715 ---
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
1726
1727 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
1728 new file mode 100644
1729 index 0000000000..b1fe72e195
1730 --- /dev/null
1731 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.cpp
1732 @@ -0,0 +1,27 @@
1733 +/** @file
1734 + Acts as the main entry point for the tests for the Dhcp6Dxe module.
1735 +
1736 + Copyright (c) Microsoft Corporation
1737 + SPDX-License-Identifier: BSD-2-Clause-Patent
1738 +**/
1739 +#include <gtest/gtest.h>
1740 +
1741 +////////////////////////////////////////////////////////////////////////////////
1742 +// Add test files here
1743 +// Google Test will only pick up the tests from the files that are included
1744 +// here.
1745 +////////////////////////////////////////////////////////////////////////////////
1746 +#include "Dhcp6IoGoogleTest.cpp"
1747 +
1748 +////////////////////////////////////////////////////////////////////////////////
1749 +// Run the tests
1750 +////////////////////////////////////////////////////////////////////////////////
1751 +int
1752 +main (
1753 + int argc,
1754 + char *argv[]
1755 + )
1756 +{
1757 + testing::InitGoogleTest (&argc, argv);
1758 + return RUN_ALL_TESTS ();
1759 +}
1760 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
1761 new file mode 100644
1762 index 0000000000..c7ec42b322
1763 --- /dev/null
1764 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
1765 @@ -0,0 +1,44 @@
1766 +## @file
1767 +# Unit test suite for the Dhcp6Dxe using Google Test
1768 +#
1769 +# Copyright (c) Microsoft Corporation.<BR>
1770 +# SPDX-License-Identifier: BSD-2-Clause-Patent
1771 +##
1772 +[Defines]
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
1778 +#
1779 +# The following information is for reference only and not required by the build tools.
1780 +#
1781 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
1782 +#
1783 +[Sources]
1784 + Dhcp6DxeGoogleTest.cpp
1785 + Dhcp6IoGoogleTest.cpp
1786 + ../Dhcp6Io.c
1787 + ../Dhcp6Utility.c
1788 +
1789 +
1790 +[Packages]
1791 + MdePkg/MdePkg.dec
1792 + MdeModulePkg/MdeModulePkg.dec
1793 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
1794 + NetworkPkg/NetworkPkg.dec
1795 +
1796 +[LibraryClasses]
1797 + GoogleTestLib
1798 + DebugLib
1799 + NetLib
1800 + PcdLib
1801 +
1802 +[Protocols]
1803 + gEfiDhcp6ServiceBindingProtocolGuid
1804 +
1805 +[Pcd]
1806 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
1807 +
1808 +[Guids]
1809 + gZeroGuid
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
1814 --- /dev/null
1815 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.cpp
1816 @@ -0,0 +1,478 @@
1817 +/** @file
1818 + Tests for Dhcp6Io.c.
1819 +
1820 + Copyright (c) Microsoft Corporation
1821 + SPDX-License-Identifier: BSD-2-Clause-Patent
1822 +**/
1823 +#include <gtest/gtest.h>
1824 +
1825 +extern "C" {
1826 + #include <Uefi.h>
1827 + #include <Library/BaseLib.h>
1828 + #include <Library/DebugLib.h>
1829 + #include <Library/BaseMemoryLib.h>
1830 + #include "../Dhcp6Impl.h"
1831 + #include "../Dhcp6Utility.h"
1832 +}
1833 +
1834 +////////////////////////////////////////////////////////////////////////
1835 +// Defines
1836 +////////////////////////////////////////////////////////////////////////
1837 +
1838 +#define DHCP6_PACKET_MAX_LEN 1500
1839 +
1840 +////////////////////////////////////////////////////////////////////////
1841 +////////////////////////////////////////////////////////////////////////
1842 +// Symbol Definitions
1843 +// These functions are not directly under test - but required to compile
1844 +////////////////////////////////////////////////////////////////////////
1845 +
1846 +// This definition is used by this test but is also required to compile
1847 +// by Dhcp6Io.c
1848 +EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {
1849 + { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }
1850 +};
1851 +
1852 +EFI_STATUS
1853 +EFIAPI
1854 +UdpIoSendDatagram (
1855 + IN UDP_IO *UdpIo,
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,
1860 + IN VOID *Context
1861 + )
1862 +{
1863 + return EFI_SUCCESS;
1864 +}
1865 +
1866 +EFI_STATUS
1867 +EFIAPI
1868 +UdpIoRecvDatagram (
1869 + IN UDP_IO *UdpIo,
1870 + IN UDP_IO_CALLBACK CallBack,
1871 + IN VOID *Context,
1872 + IN UINT32 HeadLen
1873 + )
1874 +{
1875 + return EFI_SUCCESS;
1876 +}
1877 +
1878 +////////////////////////////////////////////////////////////////////////
1879 +// Dhcp6AppendOptionTest Tests
1880 +////////////////////////////////////////////////////////////////////////
1881 +
1882 +class Dhcp6AppendOptionTest : public ::testing::Test {
1883 +public:
1884 + UINT8 *Buffer = NULL;
1885 + EFI_DHCP6_PACKET *Packet;
1886 +
1887 +protected:
1888 + // Add any setup code if needed
1889 + virtual void
1890 + SetUp (
1891 + )
1892 + {
1893 + // Initialize any resources or variables
1894 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
1895 + ASSERT_NE (Buffer, (UINT8 *)NULL);
1896 +
1897 + Packet = (EFI_DHCP6_PACKET *)Buffer;
1898 + Packet->Size = DHCP6_PACKET_MAX_LEN;
1899 + }
1900 +
1901 + // Add any cleanup code if needed
1902 + virtual void
1903 + TearDown (
1904 + )
1905 + {
1906 + // Clean up any resources or variables
1907 + if (Buffer != NULL) {
1908 + FreePool (Buffer);
1909 + }
1910 + }
1911 +};
1912 +
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) {
1916 + UINT8 *Cursor;
1917 + EFI_DHCP6_DUID *UntrustedDuid;
1918 + EFI_STATUS Status;
1919 +
1920 + UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
1921 + ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
1922 +
1923 + UntrustedDuid->Length = NTOHS (0xFFFF);
1924 +
1925 + Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
1926 +
1927 + Status = Dhcp6AppendOption (
1928 + Dhcp6AppendOptionTest::Packet,
1929 + &Cursor,
1930 + HTONS (Dhcp6OptServerId),
1931 + UntrustedDuid->Length,
1932 + UntrustedDuid->Duid
1933 + );
1934 +
1935 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
1936 +}
1937 +
1938 +// Test Description:
1939 +// Attempt to append an option to a packet that is large enough
1940 +TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
1941 + UINT8 *Cursor;
1942 + EFI_DHCP6_DUID *UntrustedDuid;
1943 + EFI_STATUS Status;
1944 + UINTN OriginalLength;
1945 +
1946 + UINT8 Duid[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
1947 +
1948 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
1949 + OriginalLength = Packet->Length;
1950 +
1951 + UntrustedDuid = (EFI_DHCP6_DUID *)AllocateZeroPool (sizeof (EFI_DHCP6_DUID));
1952 + ASSERT_NE (UntrustedDuid, (EFI_DHCP6_DUID *)NULL);
1953 +
1954 + UntrustedDuid->Length = NTOHS (sizeof (Duid));
1955 + CopyMem (UntrustedDuid->Duid, Duid, sizeof (Duid));
1956 +
1957 + Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
1958 +
1959 + Status = Dhcp6AppendOption (
1960 + Dhcp6AppendOptionTest::Packet,
1961 + &Cursor,
1962 + HTONS (Dhcp6OptServerId),
1963 + UntrustedDuid->Length,
1964 + UntrustedDuid->Duid
1965 + );
1966 +
1967 + ASSERT_EQ (Status, EFI_SUCCESS);
1968 +
1969 + // verify that the pointer to cursor moved by the expected amount
1970 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendOptionTest::Packet->Dhcp6.Option + sizeof (Duid) + 4);
1971 +
1972 + // verify that the length of the packet is now the expected amount
1973 + ASSERT_EQ (Dhcp6AppendOptionTest::Packet->Length, OriginalLength + sizeof (Duid) + 4);
1974 +}
1975 +
1976 +////////////////////////////////////////////////////////////////////////
1977 +// Dhcp6AppendETOption Tests
1978 +////////////////////////////////////////////////////////////////////////
1979 +
1980 +class Dhcp6AppendETOptionTest : public ::testing::Test {
1981 +public:
1982 + UINT8 *Buffer = NULL;
1983 + EFI_DHCP6_PACKET *Packet;
1984 +
1985 +protected:
1986 + // Add any setup code if needed
1987 + virtual void
1988 + SetUp (
1989 + )
1990 + {
1991 + // Initialize any resources or variables
1992 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
1993 + ASSERT_NE (Buffer, (UINT8 *)NULL);
1994 +
1995 + Packet = (EFI_DHCP6_PACKET *)Buffer;
1996 + Packet->Size = DHCP6_PACKET_MAX_LEN;
1997 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
1998 + }
1999 +
2000 + // Add any cleanup code if needed
2001 + virtual void
2002 + TearDown (
2003 + )
2004 + {
2005 + // Clean up any resources or variables
2006 + if (Buffer != NULL) {
2007 + FreePool (Buffer);
2008 + }
2009 + }
2010 +};
2011 +
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) {
2015 + UINT8 *Cursor;
2016 + EFI_STATUS Status;
2017 + DHCP6_INSTANCE Instance;
2018 + UINT16 ElapsedTimeVal;
2019 + UINT16 *ElapsedTime;
2020 +
2021 + Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
2022 + ElapsedTime = &ElapsedTimeVal;
2023 +
2024 + Packet->Length = Packet->Size - 2;
2025 +
2026 + Status = Dhcp6AppendETOption (
2027 + Dhcp6AppendETOptionTest::Packet,
2028 + &Cursor,
2029 + &Instance, // Instance is not used in this function
2030 + &ElapsedTime
2031 + );
2032 +
2033 + // verify that we error out because the packet is too small for the option header
2034 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2035 +
2036 + // reset the length
2037 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2038 +}
2039 +
2040 +// Test Description:
2041 +// Attempt to append an option to a packet that is large enough
2042 +TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
2043 + UINT8 *Cursor;
2044 + EFI_STATUS Status;
2045 + DHCP6_INSTANCE Instance;
2046 + UINT16 ElapsedTimeVal;
2047 + UINT16 *ElapsedTime;
2048 + UINTN ExpectedSize;
2049 + UINTN OriginalLength;
2050 +
2051 + Cursor = Dhcp6AppendETOptionTest::Packet->Dhcp6.Option;
2052 + ElapsedTime = &ElapsedTimeVal;
2053 + ExpectedSize = 6;
2054 + OriginalLength = Packet->Length;
2055 +
2056 + Status = Dhcp6AppendETOption (
2057 + Dhcp6AppendETOptionTest::Packet,
2058 + &Cursor,
2059 + &Instance, // Instance is not used in this function
2060 + &ElapsedTime
2061 + );
2062 +
2063 + // verify that the status is EFI_SUCCESS
2064 + ASSERT_EQ (Status, EFI_SUCCESS);
2065 +
2066 + // verify that the pointer to cursor moved by the expected amount
2067 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendETOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2068 +
2069 + // verify that the length of the packet is now the expected amount
2070 + ASSERT_EQ (Dhcp6AppendETOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2071 +}
2072 +
2073 +////////////////////////////////////////////////////////////////////////
2074 +// Dhcp6AppendIaOption Tests
2075 +////////////////////////////////////////////////////////////////////////
2076 +
2077 +class Dhcp6AppendIaOptionTest : public ::testing::Test {
2078 +public:
2079 + UINT8 *Buffer = NULL;
2080 + EFI_DHCP6_PACKET *Packet;
2081 + EFI_DHCP6_IA *Ia;
2082 +
2083 +protected:
2084 + // Add any setup code if needed
2085 + virtual void
2086 + SetUp (
2087 + )
2088 + {
2089 + // Initialize any resources or variables
2090 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
2091 + ASSERT_NE (Buffer, (UINT8 *)NULL);
2092 +
2093 + Packet = (EFI_DHCP6_PACKET *)Buffer;
2094 + Packet->Size = DHCP6_PACKET_MAX_LEN;
2095 +
2096 + Ia = (EFI_DHCP6_IA *)AllocateZeroPool (sizeof (EFI_DHCP6_IA) + sizeof (EFI_DHCP6_IA_ADDRESS) * 2);
2097 + ASSERT_NE (Ia, (EFI_DHCP6_IA *)NULL);
2098 +
2099 + CopyMem (Ia->IaAddress, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
2100 + CopyMem (Ia->IaAddress + 1, mAllDhcpRelayAndServersAddress.Addr, sizeof (EFI_IPv6_ADDRESS));
2101 +
2102 + Ia->IaAddressCount = 2;
2103 + }
2104 +
2105 + // Add any cleanup code if needed
2106 + virtual void
2107 + TearDown (
2108 + )
2109 + {
2110 + // Clean up any resources or variables
2111 + if (Buffer != NULL) {
2112 + FreePool (Buffer);
2113 + }
2114 +
2115 + if (Ia != NULL) {
2116 + FreePool (Ia);
2117 + }
2118 + }
2119 +};
2120 +
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) {
2125 + UINT8 *Cursor;
2126 + EFI_STATUS Status;
2127 +
2128 + Packet->Length = Packet->Size - 2;
2129 +
2130 + Ia->Descriptor.Type = Dhcp6OptIana;
2131 + Ia->Descriptor.IaId = 0x12345678;
2132 +
2133 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2134 +
2135 + Status = Dhcp6AppendIaOption (
2136 + Dhcp6AppendIaOptionTest::Packet,
2137 + &Cursor,
2138 + Ia,
2139 + 0x12345678,
2140 + 0x11111111,
2141 + Dhcp6OptIana
2142 + );
2143 +
2144 + // verify that we error out because the packet is too small for the option header
2145 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2146 +
2147 + // reset the length
2148 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2149 +}
2150 +
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) {
2155 + UINT8 *Cursor;
2156 + EFI_STATUS Status;
2157 +
2158 + // Use up nearly all the space in the packet
2159 + Packet->Length = Packet->Size - 2;
2160 +
2161 + Ia->Descriptor.Type = Dhcp6OptIata;
2162 + Ia->Descriptor.IaId = 0x12345678;
2163 +
2164 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2165 +
2166 + Status = Dhcp6AppendIaOption (
2167 + Dhcp6AppendIaOptionTest::Packet,
2168 + &Cursor,
2169 + Ia,
2170 + 0,
2171 + 0,
2172 + Dhcp6OptIata
2173 + );
2174 +
2175 + // verify that we error out because the packet is too small for the option header
2176 + ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
2177 +
2178 + // reset the length
2179 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2180 +}
2181 +
2182 +TEST_F (Dhcp6AppendIaOptionTest, IaNaValidDataExpectSuccess) {
2183 + UINT8 *Cursor;
2184 + EFI_STATUS Status;
2185 + UINTN ExpectedSize;
2186 + UINTN OriginalLength;
2187 +
2188 + //
2189 + // 2 bytes for the option header type
2190 + //
2191 + ExpectedSize = 2;
2192 + //
2193 + // 2 bytes for the option header length
2194 + //
2195 + ExpectedSize += 2;
2196 + //
2197 + // 4 bytes for the IAID
2198 + //
2199 + ExpectedSize += 4;
2200 + //
2201 + // + 4 bytes for the T1
2202 + //
2203 + ExpectedSize += 4;
2204 + //
2205 + // + 4 bytes for the T2
2206 + //
2207 + ExpectedSize += 4;
2208 + //
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
2213 + //
2214 + ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2215 +
2216 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2217 +
2218 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2219 + OriginalLength = Packet->Length;
2220 +
2221 + Ia->Descriptor.Type = Dhcp6OptIana;
2222 + Ia->Descriptor.IaId = 0x12345678;
2223 +
2224 + Status = Dhcp6AppendIaOption (
2225 + Dhcp6AppendIaOptionTest::Packet,
2226 + &Cursor,
2227 + Ia,
2228 + 0x12345678,
2229 + 0x12345678,
2230 + Dhcp6OptIana
2231 + );
2232 +
2233 + // verify that the pointer to cursor moved by the expected amount
2234 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2235 +
2236 + // verify that the length of the packet is now the expected amount
2237 + ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2238 +
2239 + // verify that the status is EFI_SUCCESS
2240 + ASSERT_EQ (Status, EFI_SUCCESS);
2241 +}
2242 +
2243 +TEST_F (Dhcp6AppendIaOptionTest, IaTaValidDataExpectSuccess) {
2244 + UINT8 *Cursor;
2245 + EFI_STATUS Status;
2246 + UINTN ExpectedSize;
2247 + UINTN OriginalLength;
2248 +
2249 + //
2250 + // 2 bytes for the option header type
2251 + //
2252 + ExpectedSize = 2;
2253 + //
2254 + // 2 bytes for the option header length
2255 + //
2256 + ExpectedSize += 2;
2257 + //
2258 + // 4 bytes for the IAID
2259 + //
2260 + ExpectedSize += 4;
2261 + //
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
2266 + //
2267 + ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
2268 +
2269 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
2270 +
2271 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
2272 + OriginalLength = Packet->Length;
2273 +
2274 + Ia->Descriptor.Type = Dhcp6OptIata;
2275 + Ia->Descriptor.IaId = 0x12345678;
2276 +
2277 + Status = Dhcp6AppendIaOption (
2278 + Dhcp6AppendIaOptionTest::Packet,
2279 + &Cursor,
2280 + Ia,
2281 + 0,
2282 + 0,
2283 + Dhcp6OptIata
2284 + );
2285 +
2286 + // verify that the pointer to cursor moved by the expected amount
2287 + ASSERT_EQ (Cursor, (UINT8 *)Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option + ExpectedSize);
2288 +
2289 + // verify that the length of the packet is now the expected amount
2290 + ASSERT_EQ (Dhcp6AppendIaOptionTest::Packet->Length, OriginalLength + ExpectedSize);
2291 +
2292 + // verify that the status is EFI_SUCCESS
2293 + ASSERT_EQ (Status, EFI_SUCCESS);
2294 +}
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
2299 @@ -24,6 +24,9 @@
2300 "CompilerPlugin": {
2301 "DscPath": "NetworkPkg.dsc"
2302 },
2303 + "HostUnitTestCompilerPlugin": {
2304 + "DscPath": "Test/NetworkPkgHostTest.dsc"
2305 + },
2306 "CharEncodingCheck": {
2307 "IgnoreFiles": []
2308 },
2309 diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
2310 new file mode 100644
2311 index 0000000000..5befdf7688
2312 --- /dev/null
2313 +++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
2314 @@ -0,0 +1,102 @@
2315 +## @file
2316 +# NetworkPkgHostTest DSC file used to build host-based unit tests.
2317 +#
2318 +# Copyright (c) Microsoft Corporation.<BR>
2319 +# SPDX-License-Identifier: BSD-2-Clause-Patent
2320 +#
2321 +##
2322 +[Defines]
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
2331 +
2332 +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
2333 +[Packages]
2334 + MdePkg/MdePkg.dec
2335 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
2336 +
2337 +[Components]
2338 + #
2339 + # Build HOST_APPLICATION that tests NetworkPkg
2340 + #
2341 + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
2342 +
2343 +# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
2344 +[LibraryClasses]
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
2372 +!else
2373 + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
2374 + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
2375 + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
2376 +!endif
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
2382 +
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
2388 +!endif
2389 +
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]
2398 + #
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.
2402 + #
2403 + # MU_CHANGE Start
2404 +!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
2405 + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
2406 +!endif
2407 + # MU_CHANGE End
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
2413 +
2414 +[PcdsFixedAtBuild]
2415 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
2416 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
2417 \ No newline at end of file
2418 --
2419 2.41.0
2420
2421
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
2426
2427 ---
2428 NetworkPkg/Dhcp6Dxe/Dhcp6Impl.h | 134 ++++++++++++++++++---
2429 NetworkPkg/Dhcp6Dxe/Dhcp6Io.c | 202 ++++++++++++++++++++++----------
2430 2 files changed, 257 insertions(+), 79 deletions(-)
2431
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')
2439
2440 +#define DHCP6_PACKET_ALL 0
2441 +#define DHCP6_PACKET_STATEFUL 1
2442 +#define DHCP6_PACKET_STATELESS 2
2443 +
2444 +#define DHCP6_BASE_PACKET_SIZE 1024
2445 +
2446 +#define DHCP6_PORT_CLIENT 546
2447 +#define DHCP6_PORT_SERVER 547
2448 +
2449 +#define DHCP_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
2450 +
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)
2453 +
2454 //
2455 // For more information on DHCP options see RFC 8415, Section 21.1
2456 //
2457 @@ -59,8 +73,8 @@ typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
2458 // | (option-len octets) |
2459 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2460 //
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))
2465
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 (
2469 );
2470
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)
2474 STATIC_ASSERT (
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"
2478 );
2479
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)
2482 STATIC_ASSERT (
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"
2486 );
2487 +//
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
2492 +//
2493 +//
2494 +// The format of IA_NA and IA_TA option:
2495 +//
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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2506 +// | |
2507 +// . IA_NA-options/IA_TA-options .
2508 +// . .
2509 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2510 +//
2511 +#define DHCP6_SIZE_OF_IAID (sizeof(UINT32))
2512 +#define DHCP6_SIZE_OF_TIME_INTERVAL (sizeof(UINT32))
2513
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)
2521 +STATIC_ASSERT (
2522 + DHCP6_SIZE_OF_COMBINED_IAID_T1_T2 == 12,
2523 + "Combined size of IAID, T1, T2 must be 12 per RFC 8415"
2524 + );
2525
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)
2530 +STATIC_ASSERT (
2531 + DHCP6_MIN_SIZE_OF_IA_TA == 8,
2532 + "Minimum combined size of IA_TA per RFC 8415"
2533 + );
2534
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)
2539 +STATIC_ASSERT (
2540 + DHCP6_OFFSET_OF_IA_TA_INNER_OPT (0) == 8,
2541 + "Offset of IA_TA Inner option is + 8 past start of option"
2542 + );
2543
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
2548 +STATIC_ASSERT (
2549 + DHCP6_MIN_SIZE_OF_IA_NA == 16,
2550 + "Minimum combined size of IA_TA per RFC 8415"
2551 + );
2552
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)
2556 +STATIC_ASSERT (
2557 + DHCP6_OFFSET_OF_IA_NA_INNER_OPT (0) == 16,
2558 + "Offset of IA_NA Inner option is + 16 past start of option"
2559 + );
2560 +
2561 +#define DHCP6_OFFSET_OF_IA_NA_T1(a) (a + \
2562 + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN + \
2563 + DHCP6_SIZE_OF_IAID)
2564 +STATIC_ASSERT (
2565 + DHCP6_OFFSET_OF_IA_NA_T1 (0) == 8,
2566 + "Offset of IA_NA Inner option is + 8 past start of option"
2567 + );
2568 +
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)
2573 +STATIC_ASSERT (
2574 + DHCP6_OFFSET_OF_IA_NA_T2 (0) == 12,
2575 + "Offset of IA_NA Inner option is + 12 past start of option"
2576 + );
2577 +
2578 +//
2579 +// For more information see RFC 8415 Section 21.13
2580 +//
2581 +// The format of the Status Code Option:
2582 +//
2583 +// 0 1 2 3
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 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
2590 +// . .
2591 +// . status-message .
2592 +// . .
2593 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2594 +//
2595 +#define DHCP6_OFFSET_OF_STATUS_CODE(a) (a + DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN)
2596 +STATIC_ASSERT (
2597 + DHCP6_OFFSET_OF_STATUS_CODE (0) == 4,
2598 + "Offset of status is + 4 past start of option"
2599 + );
2600
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.
2609 //
2610 if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
2611 - T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 8)));
2612 - T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(Option + 12)));
2613 +
2614 + T1 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T1(Option))));
2615 + T2 = NTOHL (ReadUnaligned32 ((UINT32 *)(DHCP6_OFFSET_OF_IA_NA_T2(Option))));
2616 //
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;
2621 }
2622
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);
2627 } else {
2628 T1 = 0;
2629 T2 = 0;
2630 - IaInnerOpt = Option + 8;
2631 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 2))) - 4);
2632 +
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);
2635 }
2636
2637 //
2638 @@ -641,7 +643,7 @@ Dhcp6UpdateIaInfo (
2639 Option = Dhcp6SeekOption (IaInnerOpt, IaInnerLen, Dhcp6OptStatusCode);
2640
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;
2646 }
2647 @@ -661,6 +663,88 @@ Dhcp6UpdateIaInfo (
2648 return Status;
2649 }
2650
2651 +/*
2652 + Seeks the Inner Options from a DHCP6 Option
2653 +
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.
2659 +
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
2663 +*/
2664 +EFI_STATUS
2665 +Dhcp6SeekInnerOptionSafe (
2666 + IN UINT16 IaType,
2667 + IN UINT8 *Option,
2668 + IN UINT32 OptionLen,
2669 + OUT UINT8 **IaInnerOpt,
2670 + OUT UINT16 *IaInnerLen
2671 + )
2672 +{
2673 +
2674 + UINT16 IaInnerLenTmp;
2675 + UINT8 *IaInnerOptTmp;
2676 +
2677 + if (Option == NULL) {
2678 + ASSERT (Option != NULL);
2679 + return EFI_DEVICE_ERROR;
2680 + }
2681 +
2682 + if (IaInnerOpt == NULL) {
2683 + ASSERT (IaInnerOpt != NULL);
2684 + return EFI_DEVICE_ERROR;
2685 + }
2686 +
2687 + if (IaInnerLen == NULL) {
2688 + ASSERT (IaInnerLen != NULL);
2689 + return EFI_DEVICE_ERROR;
2690 + }
2691 +
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;
2696 + }
2697 +
2698 + //
2699 + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_NA_INNER_OPT(Option);
2700 +
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;
2705 + }
2706 +
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;
2712 + }
2713 +
2714 + IaInnerOptTmp = DHCP6_OFFSET_OF_IA_TA_INNER_OPT(Option);
2715 +
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;
2720 + }
2721 +
2722 + IaInnerLenTmp -= DHCP6_SIZE_OF_IAID;
2723 + } else {
2724 + return EFI_DEVICE_ERROR;
2725 + }
2726 +
2727 + *IaInnerOpt = IaInnerOptTmp;
2728 + *IaInnerLen = IaInnerLenTmp;
2729 +
2730 + return EFI_SUCCESS;
2731 +}
2732 +
2733 /**
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 (
2737 UINT8 *IaInnerOpt;
2738 UINT16 IaInnerLen;
2739 UINT16 StsCode;
2740 + UINT32 OptionLen;
2741 +
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);
2746
2747 //
2748 // Seek StatusCode option directly in DHCP message body. That is, search in
2749 @@ -691,12 +781,12 @@ Dhcp6SeekStsOption (
2750 //
2751 *Option = Dhcp6SeekOption (
2752 Packet->Dhcp6.Option,
2753 - Packet->Length - 4,
2754 + OptionLen,
2755 Dhcp6OptStatusCode
2756 );
2757
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;
2763 }
2764 @@ -707,7 +797,7 @@ Dhcp6SeekStsOption (
2765 //
2766 *Option = Dhcp6SeekIaOption (
2767 Packet->Dhcp6.Option,
2768 - Packet->Length - sizeof (EFI_DHCP6_HEADER),
2769 + OptionLen,
2770 &Instance->Config->IaDescriptor
2771 );
2772 if (*Option == NULL) {
2773 @@ -715,52 +805,35 @@ Dhcp6SeekStsOption (
2774 }
2775
2776 //
2777 - // The format of the IA_NA option is:
2778 + // Calculate the distance from Packet->Dhcp6.Option to the IA option.
2779 //
2780 - // 0 1 2 3
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 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2787 - // | T1 |
2788 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2789 - // | T2 |
2790 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2791 - // | |
2792 - // . IA_NA-options .
2793 - // . .
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.
2798 //
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.
2802 //
2803 - // 0 1 2 3
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 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2810 - // | |
2811 - // . IA_TA-options .
2812 - // . .
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
2817 //
2818 + OptionLen = OptionLen - (*Option - Packet->Dhcp6.Option);
2819
2820 //
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
2825 //
2826 - // The inner options still start with 2 bytes option-code and 2 bytes option-len.
2827 - //
2828 - if (Instance->Config->IaDescriptor.Type == Dhcp6OptIana) {
2829 - IaInnerOpt = *Option + 16;
2830 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 12);
2831 - } else {
2832 - IaInnerOpt = *Option + 8;
2833 - IaInnerLen = (UINT16)(NTOHS (ReadUnaligned16 ((UINT16 *)(*Option + 2))) - 4);
2834 + if (EFI_ERROR (
2835 + Dhcp6SeekInnerOptionSafe (
2836 + Instance->Config->IaDescriptor.Type,
2837 + *Option,
2838 + OptionLen,
2839 + &IaInnerOpt,
2840 + &IaInnerLen
2841 + )
2842 + ))
2843 + {
2844 + return EFI_DEVICE_ERROR;
2845 }
2846
2847 //
2848 @@ -784,7 +857,7 @@ Dhcp6SeekStsOption (
2849 //
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;
2856 }
2857 @@ -1105,7 +1178,7 @@ Dhcp6SendRequestMsg (
2858 //
2859 Option = Dhcp6SeekOption (
2860 Instance->AdSelect->Dhcp6.Option,
2861 - Instance->AdSelect->Length - 4,
2862 + Instance->AdSelect->Length - sizeof(EFI_DHCP6_HEADER),
2863 Dhcp6OptServerId
2864 );
2865 if (Option == NULL) {
2866 @@ -1289,7 +1362,7 @@ Dhcp6SendDeclineMsg (
2867 //
2868 Option = Dhcp6SeekOption (
2869 LastReply->Dhcp6.Option,
2870 - LastReply->Length - 4,
2871 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2872 Dhcp6OptServerId
2873 );
2874 if (Option == NULL) {
2875 @@ -1448,7 +1521,7 @@ Dhcp6SendReleaseMsg (
2876 //
2877 Option = Dhcp6SeekOption (
2878 LastReply->Dhcp6.Option,
2879 - LastReply->Length - 4,
2880 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2881 Dhcp6OptServerId
2882 );
2883 if (Option == NULL) {
2884 @@ -1674,7 +1747,7 @@ Dhcp6SendRenewRebindMsg (
2885
2886 Option = Dhcp6SeekOption (
2887 LastReply->Dhcp6.Option,
2888 - LastReply->Length - 4,
2889 + LastReply->Length - sizeof(EFI_DHCP6_HEADER),
2890 Dhcp6OptServerId
2891 );
2892 if (Option == NULL) {
2893 @@ -2210,7 +2283,7 @@ Dhcp6HandleReplyMsg (
2894 //
2895 Option = Dhcp6SeekOption (
2896 Packet->Dhcp6.Option,
2897 - Packet->Length - 4,
2898 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2899 Dhcp6OptRapidCommit
2900 );
2901
2902 @@ -2356,7 +2429,7 @@ Dhcp6HandleReplyMsg (
2903 //
2904 // Any error status code option is found.
2905 //
2906 - StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)(Option + 4)));
2907 + StsCode = NTOHS (ReadUnaligned16 ((UINT16 *)((DHCP6_OFFSET_OF_STATUS_CODE(Option)))));
2908 switch (StsCode) {
2909 case Dhcp6StsUnspecFail:
2910 //
2911 @@ -2489,7 +2562,7 @@ Dhcp6SelectAdvertiseMsg (
2912 //
2913 Option = Dhcp6SeekOption (
2914 AdSelect->Dhcp6.Option,
2915 - AdSelect->Length - 4,
2916 + AdSelect->Length - sizeof(EFI_DHCP6_HEADER),
2917 Dhcp6OptServerUnicast
2918 );
2919
2920 @@ -2500,7 +2573,7 @@ Dhcp6SelectAdvertiseMsg (
2921 return EFI_OUT_OF_RESOURCES;
2922 }
2923
2924 - CopyMem (Instance->Unicast, Option + 4, sizeof (EFI_IPv6_ADDRESS));
2925 + CopyMem (Instance->Unicast, DHCP6_OFFSET_OF_OPT_DATA(Option), sizeof (EFI_IPv6_ADDRESS));
2926 }
2927
2928 //
2929 @@ -2553,7 +2626,7 @@ Dhcp6HandleAdvertiseMsg (
2930 //
2931 Option = Dhcp6SeekOption (
2932 Packet->Dhcp6.Option,
2933 - Packet->Length - 4,
2934 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2935 Dhcp6OptRapidCommit
2936 );
2937
2938 @@ -2647,7 +2720,8 @@ Dhcp6HandleAdvertiseMsg (
2939 CopyMem (Instance->AdSelect, Packet, Packet->Size);
2940
2941 if (Option != NULL) {
2942 - Instance->AdPref = *(Option + 4);
2943 + Instance->AdPref = *(DHCP6_OFFSET_OF_OPT_DATA(Option));
2944 +
2945 }
2946 } else {
2947 //
2948 @@ -2716,11 +2790,11 @@ Dhcp6HandleStateful (
2949 //
2950 Option = Dhcp6SeekOption (
2951 Packet->Dhcp6.Option,
2952 - Packet->Length - 4,
2953 + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
2954 Dhcp6OptClientId
2955 );
2956
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)) {
2959 goto ON_CONTINUE;
2960 }
2961
2962 @@ -2729,7 +2803,7 @@ Dhcp6HandleStateful (
2963 //
2964 Option = Dhcp6SeekOption (
2965 Packet->Dhcp6.Option,
2966 - Packet->Length - 4,
2967 + Packet->Length - DHCP6_SIZE_OF_COMBINED_CODE_AND_LEN,
2968 Dhcp6OptServerId
2969 );
2970
2971 @@ -2834,7 +2908,7 @@ Dhcp6HandleStateless (
2972 //
2973 Option = Dhcp6SeekOption (
2974 Packet->Dhcp6.Option,
2975 - Packet->Length - 4,
2976 + Packet->Length - sizeof(EFI_DHCP6_HEADER),
2977 Dhcp6OptServerId
2978 );
2979
2980 --
2981 2.41.0
2982
2983
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
2988 Unit Test
2989
2990 ---
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
2998
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
3003 @@ -1,27 +1,27 @@
3004 -/** @file
3005 - Acts as the main entry point for the tests for the Dhcp6Dxe module.
3006 -
3007 - Copyright (c) Microsoft Corporation
3008 - SPDX-License-Identifier: BSD-2-Clause-Patent
3009 -**/
3010 -#include <gtest/gtest.h>
3011 -
3012 -////////////////////////////////////////////////////////////////////////////////
3013 -// Add test files here
3014 -// Google Test will only pick up the tests from the files that are included
3015 -// here.
3016 -////////////////////////////////////////////////////////////////////////////////
3017 -#include "Dhcp6IoGoogleTest.cpp"
3018 -
3019 -////////////////////////////////////////////////////////////////////////////////
3020 -// Run the tests
3021 -////////////////////////////////////////////////////////////////////////////////
3022 -int
3023 -main (
3024 - int argc,
3025 - char *argv[]
3026 - )
3027 -{
3028 - testing::InitGoogleTest (&argc, argv);
3029 - return RUN_ALL_TESTS ();
3030 -}
3031 +/** @file
3032 + Acts as the main entry point for the tests for the Dhcp6Dxe module.
3033 +
3034 + Copyright (c) Microsoft Corporation
3035 + SPDX-License-Identifier: BSD-2-Clause-Patent
3036 +**/
3037 +#include <gtest/gtest.h>
3038 +
3039 +////////////////////////////////////////////////////////////////////////////////
3040 +// Add test files here
3041 +// Google Test will only pick up the tests from the files that are included
3042 +// here.
3043 +////////////////////////////////////////////////////////////////////////////////
3044 +#include "Dhcp6IoGoogleTest.cpp"
3045 +
3046 +////////////////////////////////////////////////////////////////////////////////
3047 +// Run the tests
3048 +////////////////////////////////////////////////////////////////////////////////
3049 +int
3050 +main (
3051 + int argc,
3052 + char *argv[]
3053 + )
3054 +{
3055 + testing::InitGoogleTest (&argc, argv);
3056 + return RUN_ALL_TESTS ();
3057 +}
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
3062 @@ -1,44 +1,44 @@
3063 -## @file
3064 -# Unit test suite for the Dhcp6Dxe using Google Test
3065 -#
3066 -# Copyright (c) Microsoft Corporation.<BR>
3067 -# SPDX-License-Identifier: BSD-2-Clause-Patent
3068 -##
3069 -[Defines]
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
3075 -#
3076 -# The following information is for reference only and not required by the build tools.
3077 -#
3078 -# VALID_ARCHITECTURES = IA32 X64 AARCH64
3079 -#
3080 -[Sources]
3081 - Dhcp6DxeGoogleTest.cpp
3082 - Dhcp6IoGoogleTest.cpp
3083 - ../Dhcp6Io.c
3084 - ../Dhcp6Utility.c
3085 -
3086 -
3087 -[Packages]
3088 - MdePkg/MdePkg.dec
3089 - MdeModulePkg/MdeModulePkg.dec
3090 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3091 - NetworkPkg/NetworkPkg.dec
3092 -
3093 -[LibraryClasses]
3094 - GoogleTestLib
3095 - DebugLib
3096 - NetLib
3097 - PcdLib
3098 -
3099 -[Protocols]
3100 - gEfiDhcp6ServiceBindingProtocolGuid
3101 -
3102 -[Pcd]
3103 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
3104 -
3105 -[Guids]
3106 +## @file
3107 +# Unit test suite for the Dhcp6Dxe using Google Test
3108 +#
3109 +# Copyright (c) Microsoft Corporation.<BR>
3110 +# SPDX-License-Identifier: BSD-2-Clause-Patent
3111 +##
3112 +[Defines]
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
3118 +#
3119 +# The following information is for reference only and not required by the build tools.
3120 +#
3121 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
3122 +#
3123 +[Sources]
3124 + Dhcp6DxeGoogleTest.cpp
3125 + Dhcp6IoGoogleTest.cpp
3126 + ../Dhcp6Io.c
3127 + ../Dhcp6Utility.c
3128 +
3129 +
3130 +[Packages]
3131 + MdePkg/MdePkg.dec
3132 + MdeModulePkg/MdeModulePkg.dec
3133 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3134 + NetworkPkg/NetworkPkg.dec
3135 +
3136 +[LibraryClasses]
3137 + GoogleTestLib
3138 + DebugLib
3139 + NetLib
3140 + PcdLib
3141 +
3142 +[Protocols]
3143 + gEfiDhcp6ServiceBindingProtocolGuid
3144 +
3145 +[Pcd]
3146 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
3147 +
3148 +[Guids]
3149 gZeroGuid
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
3155 @@ -7,12 +7,13 @@
3156 #include <gtest/gtest.h>
3157
3158 extern "C" {
3159 - #include <Uefi.h>
3160 - #include <Library/BaseLib.h>
3161 - #include <Library/DebugLib.h>
3162 - #include <Library/BaseMemoryLib.h>
3163 - #include "../Dhcp6Impl.h"
3164 - #include "../Dhcp6Utility.h"
3165 +#include <Uefi.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"
3172 }
3173
3174 ////////////////////////////////////////////////////////////////////////
3175 @@ -21,7 +22,35 @@ extern "C" {
3176
3177 #define DHCP6_PACKET_MAX_LEN 1500
3178
3179 +// This definition is used by this test but is also required to compile
3180 +// by Dhcp6Io.c
3181 +#define DHCPV6_OPTION_IA_NA 3
3182 +#define DHCPV6_OPTION_IA_TA 4
3183 +
3184 +#define SEARCH_PATTERN 0xDEADC0DE
3185 +#define SEARCH_PATTERN_LEN sizeof(SEARCH_PATTERN)
3186 +
3187 ////////////////////////////////////////////////////////////////////////
3188 +// Test structures for IA_NA and IA_TA options
3189 +////////////////////////////////////////////////////////////////////////
3190 +typedef struct {
3191 + UINT16 Code;
3192 + UINT16 Len;
3193 + UINT32 IAID;
3194 +} DHCPv6_OPTION;
3195 +
3196 +typedef struct {
3197 + DHCPv6_OPTION Header;
3198 + UINT32 T1;
3199 + UINT32 T2;
3200 + UINT8 InnerOptions[0];
3201 +} DHCPv6_OPTION_IA_NA;
3202 +
3203 +typedef struct {
3204 + DHCPv6_OPTION Header;
3205 + UINT8 InnerOptions[0];
3206 +} DHCPv6_OPTION_IA_TA;
3207 +
3208 ////////////////////////////////////////////////////////////////////////
3209 // Symbol Definitions
3210 // These functions are not directly under test - but required to compile
3211 @@ -65,33 +94,33 @@ UdpIoRecvDatagram (
3212
3213 class Dhcp6AppendOptionTest : public ::testing::Test {
3214 public:
3215 - UINT8 *Buffer = NULL;
3216 - EFI_DHCP6_PACKET *Packet;
3217 +UINT8 *Buffer = NULL;
3218 +EFI_DHCP6_PACKET *Packet;
3219
3220 protected:
3221 - // Add any setup code if needed
3222 - virtual void
3223 - SetUp (
3224 - )
3225 - {
3226 - // Initialize any resources or variables
3227 - Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3228 - ASSERT_NE (Buffer, (UINT8 *)NULL);
3229 -
3230 - Packet = (EFI_DHCP6_PACKET *)Buffer;
3231 - Packet->Size = DHCP6_PACKET_MAX_LEN;
3232 - }
3233 +// Add any setup code if needed
3234 +virtual void
3235 +SetUp (
3236 + )
3237 +{
3238 + // Initialize any resources or variables
3239 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3240 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3241 +
3242 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3243 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3244 +}
3245
3246 - // Add any cleanup code if needed
3247 - virtual void
3248 - TearDown (
3249 - )
3250 - {
3251 - // Clean up any resources or variables
3252 - if (Buffer != NULL) {
3253 - FreePool (Buffer);
3254 - }
3255 +// Add any cleanup code if needed
3256 +virtual void
3257 +TearDown (
3258 + )
3259 +{
3260 + // Clean up any resources or variables
3261 + if (Buffer != NULL) {
3262 + FreePool (Buffer);
3263 }
3264 +}
3265 };
3266
3267 // Test Description:
3268 @@ -109,12 +138,12 @@ TEST_F (Dhcp6AppendOptionTest, InvalidDataExpectBufferTooSmall) {
3269 Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
3270
3271 Status = Dhcp6AppendOption (
3272 - Dhcp6AppendOptionTest::Packet,
3273 - &Cursor,
3274 - HTONS (Dhcp6OptServerId),
3275 - UntrustedDuid->Length,
3276 - UntrustedDuid->Duid
3277 - );
3278 + Dhcp6AppendOptionTest::Packet,
3279 + &Cursor,
3280 + HTONS (Dhcp6OptServerId),
3281 + UntrustedDuid->Length,
3282 + UntrustedDuid->Duid
3283 + );
3284
3285 ASSERT_EQ (Status, EFI_BUFFER_TOO_SMALL);
3286 }
3287 @@ -141,12 +170,12 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
3288 Cursor = Dhcp6AppendOptionTest::Packet->Dhcp6.Option;
3289
3290 Status = Dhcp6AppendOption (
3291 - Dhcp6AppendOptionTest::Packet,
3292 - &Cursor,
3293 - HTONS (Dhcp6OptServerId),
3294 - UntrustedDuid->Length,
3295 - UntrustedDuid->Duid
3296 - );
3297 + Dhcp6AppendOptionTest::Packet,
3298 + &Cursor,
3299 + HTONS (Dhcp6OptServerId),
3300 + UntrustedDuid->Length,
3301 + UntrustedDuid->Duid
3302 + );
3303
3304 ASSERT_EQ (Status, EFI_SUCCESS);
3305
3306 @@ -163,34 +192,34 @@ TEST_F (Dhcp6AppendOptionTest, ValidDataExpectSuccess) {
3307
3308 class Dhcp6AppendETOptionTest : public ::testing::Test {
3309 public:
3310 - UINT8 *Buffer = NULL;
3311 - EFI_DHCP6_PACKET *Packet;
3312 +UINT8 *Buffer = NULL;
3313 +EFI_DHCP6_PACKET *Packet;
3314
3315 protected:
3316 - // Add any setup code if needed
3317 - virtual void
3318 - SetUp (
3319 - )
3320 - {
3321 - // Initialize any resources or variables
3322 - Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3323 - ASSERT_NE (Buffer, (UINT8 *)NULL);
3324 -
3325 - Packet = (EFI_DHCP6_PACKET *)Buffer;
3326 - Packet->Size = DHCP6_PACKET_MAX_LEN;
3327 - Packet->Length = sizeof (EFI_DHCP6_HEADER);
3328 - }
3329 +// Add any setup code if needed
3330 +virtual void
3331 +SetUp (
3332 + )
3333 +{
3334 + // Initialize any resources or variables
3335 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3336 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3337 +
3338 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3339 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3340 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
3341 +}
3342
3343 - // Add any cleanup code if needed
3344 - virtual void
3345 - TearDown (
3346 - )
3347 - {
3348 - // Clean up any resources or variables
3349 - if (Buffer != NULL) {
3350 - FreePool (Buffer);
3351 - }
3352 +// Add any cleanup code if needed
3353 +virtual void
3354 +TearDown (
3355 + )
3356 +{
3357 + // Clean up any resources or variables
3358 + if (Buffer != NULL) {
3359 + FreePool (Buffer);
3360 }
3361 +}
3362 };
3363
3364 // Test Description:
3365 @@ -208,11 +237,11 @@ TEST_F (Dhcp6AppendETOptionTest, InvalidDataExpectBufferTooSmall) {
3366 Packet->Length = Packet->Size - 2;
3367
3368 Status = Dhcp6AppendETOption (
3369 - Dhcp6AppendETOptionTest::Packet,
3370 - &Cursor,
3371 - &Instance, // Instance is not used in this function
3372 - &ElapsedTime
3373 - );
3374 + Dhcp6AppendETOptionTest::Packet,
3375 + &Cursor,
3376 + &Instance, // Instance is not used in this function
3377 + &ElapsedTime
3378 + );
3379
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;
3384
3385 Status = Dhcp6AppendETOption (
3386 - Dhcp6AppendETOptionTest::Packet,
3387 - &Cursor,
3388 - &Instance, // Instance is not used in this function
3389 - &ElapsedTime
3390 - );
3391 + Dhcp6AppendETOptionTest::Packet,
3392 + &Cursor,
3393 + &Instance, // Instance is not used in this function
3394 + &ElapsedTime
3395 + );
3396
3397 // verify that the status is EFI_SUCCESS
3398 ASSERT_EQ (Status, EFI_SUCCESS);
3399 @@ -260,46 +289,46 @@ TEST_F (Dhcp6AppendETOptionTest, ValidDataExpectSuccess) {
3400
3401 class Dhcp6AppendIaOptionTest : public ::testing::Test {
3402 public:
3403 - UINT8 *Buffer = NULL;
3404 - EFI_DHCP6_PACKET *Packet;
3405 - EFI_DHCP6_IA *Ia;
3406 +UINT8 *Buffer = NULL;
3407 +EFI_DHCP6_PACKET *Packet;
3408 +EFI_DHCP6_IA *Ia;
3409
3410 protected:
3411 - // Add any setup code if needed
3412 - virtual void
3413 - SetUp (
3414 - )
3415 - {
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
3420 +virtual void
3421 +SetUp (
3422 + )
3423 +{
3424 + // Initialize any resources or variables
3425 + Buffer = (UINT8 *)AllocateZeroPool (DHCP6_PACKET_MAX_LEN);
3426 + ASSERT_NE (Buffer, (UINT8 *)NULL);
3427 +
3428 + Packet = (EFI_DHCP6_PACKET *)Buffer;
3429 + Packet->Size = DHCP6_PACKET_MAX_LEN;
3430
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);
3435
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));
3440
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;
3444 +}
3445
3446 - Ia->IaAddressCount = 2;
3447 +// Add any cleanup code if needed
3448 +virtual void
3449 +TearDown (
3450 + )
3451 +{
3452 + // Clean up any resources or variables
3453 + if (Buffer != NULL) {
3454 + FreePool (Buffer);
3455 }
3456
3457 - // Add any cleanup code if needed
3458 - virtual void
3459 - TearDown (
3460 - )
3461 - {
3462 - // Clean up any resources or variables
3463 - if (Buffer != NULL) {
3464 - FreePool (Buffer);
3465 - }
3466 -
3467 - if (Ia != NULL) {
3468 - FreePool (Ia);
3469 - }
3470 + if (Ia != NULL) {
3471 + FreePool (Ia);
3472 }
3473 +}
3474 };
3475
3476 // Test Description:
3477 @@ -317,13 +346,13 @@ TEST_F (Dhcp6AppendIaOptionTest, IaNaInvalidDataExpectBufferTooSmall) {
3478 Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3479
3480 Status = Dhcp6AppendIaOption (
3481 - Dhcp6AppendIaOptionTest::Packet,
3482 - &Cursor,
3483 - Ia,
3484 - 0x12345678,
3485 - 0x11111111,
3486 - Dhcp6OptIana
3487 - );
3488 + Dhcp6AppendIaOptionTest::Packet,
3489 + &Cursor,
3490 + Ia,
3491 + 0x12345678,
3492 + 0x11111111,
3493 + Dhcp6OptIana
3494 + );
3495
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;
3500
3501 Status = Dhcp6AppendIaOption (
3502 - Dhcp6AppendIaOptionTest::Packet,
3503 - &Cursor,
3504 - Ia,
3505 - 0,
3506 - 0,
3507 - Dhcp6OptIata
3508 - );
3509 + Dhcp6AppendIaOptionTest::Packet,
3510 + &Cursor,
3511 + Ia,
3512 + 0,
3513 + 0,
3514 + Dhcp6OptIata
3515 + );
3516
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;
3521
3522 Status = Dhcp6AppendIaOption (
3523 - Dhcp6AppendIaOptionTest::Packet,
3524 - &Cursor,
3525 - Ia,
3526 - 0x12345678,
3527 - 0x12345678,
3528 - Dhcp6OptIana
3529 - );
3530 + Dhcp6AppendIaOptionTest::Packet,
3531 + &Cursor,
3532 + Ia,
3533 + 0x12345678,
3534 + 0x12345678,
3535 + Dhcp6OptIana
3536 + );
3537
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) {
3541 //
3542 ExpectedSize += (4 + sizeof (EFI_DHCP6_IA_ADDRESS)) * 2;
3543
3544 - Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3545 + Cursor = Dhcp6AppendIaOptionTest::Packet->Dhcp6.Option;
3546
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;
3551
3552 Status = Dhcp6AppendIaOption (
3553 - Dhcp6AppendIaOptionTest::Packet,
3554 - &Cursor,
3555 - Ia,
3556 - 0,
3557 - 0,
3558 - Dhcp6OptIata
3559 - );
3560 + Dhcp6AppendIaOptionTest::Packet,
3561 + &Cursor,
3562 + Ia,
3563 + 0,
3564 + 0,
3565 + Dhcp6OptIata
3566 + );
3567
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);
3573 }
3574 +
3575 +////////////////////////////////////////////////////////////////////////
3576 +// Dhcp6SeekInnerOptionSafe Tests
3577 +////////////////////////////////////////////////////////////////////////
3578 +
3579 +// Define a fixture for your tests if needed
3580 +class Dhcp6SeekInnerOptionSafeTest : public ::testing::Test {
3581 +protected:
3582 +// Add any setup code if needed
3583 +virtual void
3584 +SetUp (
3585 + )
3586 +{
3587 + // Initialize any resources or variables
3588 +}
3589 +
3590 +// Add any cleanup code if needed
3591 +virtual void
3592 +TearDown (
3593 + )
3594 +{
3595 + // Clean up any resources or variables
3596 +}
3597 +};
3598 +
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;
3607 +
3608 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3609 + UINT8 *InnerOptionPtr = NULL;
3610 + UINT16 InnerOptionLength = 0;
3611 +
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);
3618 +
3619 + Result = Dhcp6SeekInnerOptionSafe (
3620 + Dhcp6OptIana,
3621 + Option,
3622 + OptionLength,
3623 + &InnerOptionPtr,
3624 + &InnerOptionLength
3625 + );
3626 + ASSERT_EQ (Result, EFI_SUCCESS);
3627 + ASSERT_EQ (InnerOptionLength, 4);
3628 + ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
3629 +}
3630 +
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;
3640 +
3641 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3642 + UINT8 *InnerOptionPtr = NULL;
3643 + UINT16 InnerOptionLength = 0;
3644 +
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);
3651 +
3652 + // Set the InnerOptionLength to be less than the size of the option
3653 + Status = Dhcp6SeekInnerOptionSafe (
3654 + Dhcp6OptIana,
3655 + Option,
3656 + OptionLength,
3657 + &InnerOptionPtr,
3658 + &InnerOptionLength
3659 + );
3660 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3661 +
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 (
3665 + Dhcp6OptIana,
3666 + Option,
3667 + OptionLength,
3668 + &InnerOptionPtr,
3669 + &InnerOptionLength
3670 + );
3671 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3672 +}
3673 +
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;
3683 +
3684 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3685 + UINT8 *InnerOptionPtr = NULL;
3686 + UINT16 InnerOptionLength = 0;
3687 +
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);
3692 +
3693 + Status = Dhcp6SeekInnerOptionSafe (
3694 + Dhcp6OptIata,
3695 + Option,
3696 + OptionLength,
3697 + &InnerOptionPtr,
3698 + &InnerOptionLength
3699 + );
3700 + ASSERT_EQ (Status, EFI_SUCCESS);
3701 + ASSERT_EQ (InnerOptionLength, 4);
3702 + ASSERT_EQ (CompareMem (InnerOptionPtr, &SearchPattern, SearchPatternLength), 0);
3703 +}
3704 +
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;
3714 +
3715 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3716 + UINT8 *InnerOptionPtr = NULL;
3717 + UINT16 InnerOptionLength = 0;
3718 +
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);
3723 +
3724 + Status = Dhcp6SeekInnerOptionSafe (
3725 + Dhcp6OptIata,
3726 + Option,
3727 + OptionLength,
3728 + &InnerOptionPtr,
3729 + &InnerOptionLength
3730 + );
3731 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3732 +
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 (
3736 + Dhcp6OptIata,
3737 + Option,
3738 + OptionLength,
3739 + &InnerOptionPtr,
3740 + &InnerOptionLength
3741 + );
3742 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3743 +}
3744 +
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;
3754 +
3755 + UINTN SearchPatternLength = SEARCH_PATTERN_LEN;
3756 + UINT8 *InnerOptionPtr = NULL;
3757 + UINT16 InnerOptionLength = 0;
3758 +
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);
3763 +
3764 + Result = Dhcp6SeekInnerOptionSafe (0xC0DE, Option, OptionLength, &InnerOptionPtr, &InnerOptionLength);
3765 + ASSERT_EQ (Result, EFI_DEVICE_ERROR);
3766 +}
3767 +
3768 +////////////////////////////////////////////////////////////////////////
3769 +// Dhcp6SeekStsOption Tests
3770 +////////////////////////////////////////////////////////////////////////
3771 +
3772 +#define PACKET_SIZE (1500)
3773 +
3774 +class Dhcp6SeekStsOptionTest : public ::testing::Test {
3775 +public:
3776 +DHCP6_INSTANCE Instance = { 0 };
3777 +EFI_DHCP6_PACKET *Packet = NULL;
3778 +EFI_DHCP6_CONFIG_DATA Config = { 0 };
3779 +
3780 +protected:
3781 +// Add any setup code if needed
3782 +virtual void
3783 +SetUp (
3784 + )
3785 +{
3786 + // Allocate a packet
3787 + Packet = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
3788 + ASSERT_NE (Packet, nullptr);
3789 +
3790 + // Initialize the packet
3791 + Packet->Size = PACKET_SIZE;
3792 +
3793 + Instance.Config = &Config;
3794 +}
3795 +
3796 +// Add any cleanup code if needed
3797 +virtual void
3798 +TearDown (
3799 + )
3800 +{
3801 + // Clean up any resources or variables
3802 + FreePool (Packet);
3803 +}
3804 +};
3805 +
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 };
3816 +
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;
3822 +
3823 + Packet->Length = sizeof (EFI_DHCP6_HEADER);
3824 +
3825 + Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
3826 +
3827 + // Let's append the option to the packet
3828 + Status = Dhcp6AppendOption (
3829 + Dhcp6SeekStsOptionTest::Packet,
3830 + &Option,
3831 + Dhcp6OptStatusCode,
3832 + SearchPatternLength,
3833 + (UINT8 *)&SearchPattern
3834 + );
3835 + ASSERT_EQ (Status, EFI_SUCCESS);
3836 +
3837 + // Inner option length - this will be overwritten later
3838 + Len = (UINT16 *)(Option + 2);
3839 +
3840 + // Fill in the inner IA option
3841 + Status = Dhcp6AppendIaOption (
3842 + Dhcp6SeekStsOptionTest::Packet,
3843 + &Option,
3844 + &Ia,
3845 + 0x12345678,
3846 + 0x11111111,
3847 + 0x22222222
3848 + );
3849 + ASSERT_EQ (Status, EFI_SUCCESS);
3850 +
3851 + // overwrite the len of inner Ia option
3852 + *Len = HTONS (3);
3853 +
3854 + Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_TA;
3855 +
3856 + Option = NULL;
3857 + Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
3858 +
3859 + ASSERT_EQ (Status, EFI_DEVICE_ERROR);
3860 +}
3861 +
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 };
3870 +
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);
3877 +
3878 + Option = Dhcp6SeekStsOptionTest::Packet->Dhcp6.Option;
3879 +
3880 + Status = Dhcp6AppendOption (
3881 + Dhcp6SeekStsOptionTest::Packet,
3882 + &Option,
3883 + Dhcp6OptStatusCode,
3884 + SearchPatternLength,
3885 + (UINT8 *)&SearchPattern
3886 + );
3887 + ASSERT_EQ (Status, EFI_SUCCESS);
3888 +
3889 + Status = Dhcp6AppendIaOption (
3890 + Dhcp6SeekStsOptionTest::Packet,
3891 + &Option,
3892 + &Ia,
3893 + 0x12345678,
3894 + 0x11111111,
3895 + 0x22222222
3896 + );
3897 + ASSERT_EQ (Status, EFI_SUCCESS);
3898 +
3899 + Dhcp6SeekStsOptionTest::Instance.Config->IaDescriptor.Type = DHCPV6_OPTION_IA_NA;
3900 +
3901 + Option = NULL;
3902 + Status = Dhcp6SeekStsOption (&(Dhcp6SeekStsOptionTest::Instance), Dhcp6SeekStsOptionTest::Packet, &Option);
3903 +
3904 + ASSERT_EQ (Status, EFI_SUCCESS);
3905 +}
3906 diff --git a/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
3907 new file mode 100644
3908 index 0000000000..c5e38daf9c
3909 --- /dev/null
3910 +++ b/NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6IoGoogleTest.h
3911 @@ -0,0 +1,58 @@
3912 +/** @file
3913 + Acts as header for private functions under test in Dhcp6Io.c
3914 +
3915 + Copyright (c) Microsoft Corporation
3916 + SPDX-License-Identifier: BSD-2-Clause-Patent
3917 +**/
3918 +
3919 +#ifndef DHCP6_IO_GOOGLE_TEST_H
3920 +#define DHCP6_IO_GOOGLE_TEST_H
3921 +
3922 +////////////////////////////////////////////////////////////////////////////////
3923 +// These are the functions that are being unit tested
3924 +////////////////////////////////////////////////////////////////////////////////
3925 +
3926 +#include <Uefi.h>
3927 +
3928 +/**
3929 + Seeks the Inner Options from a DHCP6 Option
3930 +
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.
3936 +
3937 + @retval EFI_SUCCESS Seek the inner option successfully.
3938 + @retval EFI_DEVICE_ERROR The OptionLen is invalid.
3939 +*/
3940 +EFI_STATUS
3941 +Dhcp6SeekInnerOptionSafe (
3942 + UINT16 IaType,
3943 + UINT8 *Option,
3944 + UINT32 OptionLen,
3945 + UINT8 **IaInnerOpt,
3946 + UINT16 *IaInnerLen
3947 + );
3948 +
3949 +/**
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.
3953 +
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.
3957 +
3958 + @retval EFI_SUCCESS Seek status code option successfully.
3959 + @retval EFI_DEVICE_ERROR An unexpected error.
3960 +
3961 +**/
3962 +EFI_STATUS
3963 +Dhcp6SeekStsOption (
3964 + IN DHCP6_INSTANCE *Instance,
3965 + IN EFI_DHCP6_PACKET *Packet,
3966 + OUT UINT8 **Option
3967 + );
3968 +
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
3974 @@ -1,102 +1,102 @@
3975 -## @file
3976 -# NetworkPkgHostTest DSC file used to build host-based unit tests.
3977 -#
3978 -# Copyright (c) Microsoft Corporation.<BR>
3979 -# SPDX-License-Identifier: BSD-2-Clause-Patent
3980 -#
3981 -##
3982 -[Defines]
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
3991 -
3992 -!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
3993 -[Packages]
3994 - MdePkg/MdePkg.dec
3995 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
3996 -
3997 -[Components]
3998 - #
3999 - # Build HOST_APPLICATION that tests NetworkPkg
4000 - #
4001 - NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4002 -
4003 -# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4004 -[LibraryClasses]
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
4032 -!else
4033 - BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
4034 - OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
4035 - TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
4036 -!endif
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
4042 -
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
4048 -!endif
4049 -
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]
4058 - #
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.
4062 - #
4063 - # MU_CHANGE Start
4064 -!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
4065 - NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
4066 -!endif
4067 - # MU_CHANGE End
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
4073 -
4074 -[PcdsFixedAtBuild]
4075 - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
4076 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
4077 \ No newline at end of file
4078 +## @file
4079 +# NetworkPkgHostTest DSC file used to build host-based unit tests.
4080 +#
4081 +# Copyright (c) Microsoft Corporation.<BR>
4082 +# SPDX-License-Identifier: BSD-2-Clause-Patent
4083 +#
4084 +##
4085 +[Defines]
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
4094 +
4095 +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
4096 +[Packages]
4097 + MdePkg/MdePkg.dec
4098 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
4099 +
4100 +[Components]
4101 + #
4102 + # Build HOST_APPLICATION that tests NetworkPkg
4103 + #
4104 + NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4105 +
4106 +# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4107 +[LibraryClasses]
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
4135 +!else
4136 + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
4137 + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
4138 + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
4139 +!endif
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
4145 +
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
4151 +!endif
4152 +
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]
4161 + #
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.
4165 + #
4166 + # MU_CHANGE Start
4167 +!if $(TOOL_CHAIN_TAG) != VS2017 and $(TOOL_CHAIN_TAG) != VS2015 and $(TOOL_CHAIN_TAG) != VS2019
4168 + NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
4169 +!endif
4170 + # MU_CHANGE End
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
4176 +
4177 +[PcdsFixedAtBuild]
4178 + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2
4179 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|0x4
4180 --
4181 2.41.0
4182
4183
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
4188
4189 ---
4190 NetworkPkg/Ip6Dxe/Ip6Option.c | 112 ++++++++++++++++++----------------
4191 1 file changed, 60 insertions(+), 52 deletions(-)
4192
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);
4200 Ip6SendIcmpError (
4201 - IpSb,
4202 - Packet,
4203 - NULL,
4204 - &Packet->Ip.Ip6->SourceAddress,
4205 - ICMP_V6_PARAMETER_PROBLEM,
4206 - 2,
4207 - &Pointer
4208 - );
4209 + IpSb,
4210 + Packet,
4211 + NULL,
4212 + &Packet->Ip.Ip6->SourceAddress,
4213 + ICMP_V6_PARAMETER_PROBLEM,
4214 + 2,
4215 + &Pointer
4216 + );
4217 return FALSE;
4218 case Ip6OptionMask:
4219 if (!IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress)) {
4220 Pointer = Pointer + Offset + sizeof (EFI_IP6_HEADER);
4221 Ip6SendIcmpError (
4222 - IpSb,
4223 - Packet,
4224 - NULL,
4225 - &Packet->Ip.Ip6->SourceAddress,
4226 - ICMP_V6_PARAMETER_PROBLEM,
4227 - 2,
4228 - &Pointer
4229 - );
4230 + IpSb,
4231 + Packet,
4232 + NULL,
4233 + &Packet->Ip.Ip6->SourceAddress,
4234 + ICMP_V6_PARAMETER_PROBLEM,
4235 + 2,
4236 + &Pointer
4237 + );
4238 }
4239
4240 return FALSE;
4241 @@ -137,6 +137,14 @@ Ip6IsNDOptionValid (
4242 return FALSE;
4243 }
4244
4245 + //
4246 + // Cannot process truncated options.
4247 + // Cannot process options with a length of 0 as there is no Type field.
4248 + //
4249 + if (OptionLen < sizeof (IP6_OPTION_HEADER)) {
4250 + return FALSE;
4251 + }
4252 +
4253 Offset = 0;
4254
4255 //
4256 @@ -358,14 +366,14 @@ Ip6IsExtsValid (
4257 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4258 {
4259 Ip6SendIcmpError (
4260 - IpSb,
4261 - Packet,
4262 - NULL,
4263 - &Packet->Ip.Ip6->SourceAddress,
4264 - ICMP_V6_PARAMETER_PROBLEM,
4265 - 1,
4266 - &Pointer
4267 - );
4268 + IpSb,
4269 + Packet,
4270 + NULL,
4271 + &Packet->Ip.Ip6->SourceAddress,
4272 + ICMP_V6_PARAMETER_PROBLEM,
4273 + 1,
4274 + &Pointer
4275 + );
4276 }
4277
4278 return FALSE;
4279 @@ -438,14 +446,14 @@ Ip6IsExtsValid (
4280 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4281 {
4282 Ip6SendIcmpError (
4283 - IpSb,
4284 - Packet,
4285 - NULL,
4286 - &Packet->Ip.Ip6->SourceAddress,
4287 - ICMP_V6_PARAMETER_PROBLEM,
4288 - 0,
4289 - &Pointer
4290 - );
4291 + IpSb,
4292 + Packet,
4293 + NULL,
4294 + &Packet->Ip.Ip6->SourceAddress,
4295 + ICMP_V6_PARAMETER_PROBLEM,
4296 + 0,
4297 + &Pointer
4298 + );
4299 }
4300
4301 return FALSE;
4302 @@ -484,14 +492,14 @@ Ip6IsExtsValid (
4303 {
4304 Pointer = sizeof (UINT32);
4305 Ip6SendIcmpError (
4306 - IpSb,
4307 - Packet,
4308 - NULL,
4309 - &Packet->Ip.Ip6->SourceAddress,
4310 - ICMP_V6_PARAMETER_PROBLEM,
4311 - 0,
4312 - &Pointer
4313 - );
4314 + IpSb,
4315 + Packet,
4316 + NULL,
4317 + &Packet->Ip.Ip6->SourceAddress,
4318 + ICMP_V6_PARAMETER_PROBLEM,
4319 + 0,
4320 + &Pointer
4321 + );
4322 return FALSE;
4323 }
4324 }
4325 @@ -560,14 +568,14 @@ Ip6IsExtsValid (
4326 !IP6_IS_MULTICAST (&Packet->Ip.Ip6->DestinationAddress))
4327 {
4328 Ip6SendIcmpError (
4329 - IpSb,
4330 - Packet,
4331 - NULL,
4332 - &Packet->Ip.Ip6->SourceAddress,
4333 - ICMP_V6_PARAMETER_PROBLEM,
4334 - 1,
4335 - &Pointer
4336 - );
4337 + IpSb,
4338 + Packet,
4339 + NULL,
4340 + &Packet->Ip.Ip6->SourceAddress,
4341 + ICMP_V6_PARAMETER_PROBLEM,
4342 + 1,
4343 + &Pointer
4344 + );
4345 }
4346
4347 return FALSE;
4348 @@ -774,10 +782,10 @@ Ip6FillFragmentHeader (
4349 // Append the part2 (fragmentable part) of Extension headers
4350 //
4351 CopyMem (
4352 - Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
4353 - ExtHdrs + Part1Len,
4354 - ExtHdrsLen - Part1Len
4355 - );
4356 + Buffer + Part1Len + sizeof (IP6_FRAGMENT_HEADER),
4357 + ExtHdrs + Part1Len,
4358 + ExtHdrsLen - Part1Len
4359 + );
4360 }
4361
4362 *UpdatedExtHdrs = Buffer;
4363 --
4364 2.41.0
4365
4366
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
4371 Unit Test
4372
4373 ---
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
4382
4383 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4384 new file mode 100644
4385 index 0000000000..9dd5577249
4386 --- /dev/null
4387 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.cpp
4388 @@ -0,0 +1,27 @@
4389 +/** @file
4390 + Acts as the main entry point for the tests for the Ip6Dxe module.
4391 +
4392 + Copyright (c) Microsoft Corporation
4393 + SPDX-License-Identifier: BSD-2-Clause-Patent
4394 +**/
4395 +#include <gtest/gtest.h>
4396 +
4397 +////////////////////////////////////////////////////////////////////////////////
4398 +// Add test files here
4399 +// Google Test will only pick up the tests from the files that are included
4400 +// here.
4401 +////////////////////////////////////////////////////////////////////////////////
4402 +#include "Ip6OptionGoogleTest.cpp"
4403 +
4404 +////////////////////////////////////////////////////////////////////////////////
4405 +// Run the tests
4406 +////////////////////////////////////////////////////////////////////////////////
4407 +int
4408 +main (
4409 + int argc,
4410 + char *argv[]
4411 + )
4412 +{
4413 + testing::InitGoogleTest (&argc, argv);
4414 + return RUN_ALL_TESTS ();
4415 +}
4416 diff --git a/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4417 new file mode 100644
4418 index 0000000000..b85584b796
4419 --- /dev/null
4420 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4421 @@ -0,0 +1,42 @@
4422 +## @file
4423 +# Unit test suite for the Ip6Dxe using Google Test
4424 +#
4425 +# Copyright (c) Microsoft Corporation.<BR>
4426 +# SPDX-License-Identifier: BSD-2-Clause-Patent
4427 +##
4428 +[Defines]
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
4434 +#
4435 +# The following information is for reference only and not required by the build tools.
4436 +#
4437 +# VALID_ARCHITECTURES = IA32 X64 AARCH64
4438 +#
4439 +[Sources]
4440 + Ip6DxeGoogleTest.cpp
4441 + Ip6OptionGoogleTest.cpp
4442 + ../Ip6Option.c
4443 +
4444 +[Packages]
4445 + MdePkg/MdePkg.dec
4446 + MdeModulePkg/MdeModulePkg.dec
4447 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
4448 + NetworkPkg/NetworkPkg.dec
4449 +
4450 +[LibraryClasses]
4451 + GoogleTestLib
4452 + DebugLib
4453 + NetLib
4454 + PcdLib
4455 +
4456 +[Protocols]
4457 + gEfiDhcp6ServiceBindingProtocolGuid
4458 +
4459 +[Pcd]
4460 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
4461 +
4462 +[Guids]
4463 + gZeroGuid
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
4468 --- /dev/null
4469 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.cpp
4470 @@ -0,0 +1,129 @@
4471 +/** @file
4472 + Tests for Ip6Option.c.
4473 +
4474 + Copyright (c) Microsoft Corporation
4475 + SPDX-License-Identifier: BSD-2-Clause-Patent
4476 +**/
4477 +#include <gtest/gtest.h>
4478 +
4479 +extern "C" {
4480 + #include <Uefi.h>
4481 + #include <Library/BaseLib.h>
4482 + #include <Library/DebugLib.h>
4483 + #include "../Ip6Impl.h"
4484 + #include "../Ip6Option.h"
4485 +}
4486 +
4487 +/////////////////////////////////////////////////////////////////////////
4488 +// Defines
4489 +///////////////////////////////////////////////////////////////////////
4490 +
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)
4493 +
4494 +////////////////////////////////////////////////////////////////////////
4495 +// Symbol Definitions
4496 +// These functions are not directly under test - but required to compile
4497 +////////////////////////////////////////////////////////////////////////
4498 +UINT32 mIp6Id;
4499 +
4500 +EFI_STATUS
4501 +Ip6SendIcmpError (
4502 + IN IP6_SERVICE *IpSb,
4503 + IN NET_BUF *Packet,
4504 + IN EFI_IPv6_ADDRESS *SourceAddress OPTIONAL,
4505 + IN EFI_IPv6_ADDRESS *DestinationAddress,
4506 + IN UINT8 Type,
4507 + IN UINT8 Code,
4508 + IN UINT32 *Pointer OPTIONAL
4509 + )
4510 +{
4511 + // ..
4512 + return EFI_SUCCESS;
4513 +}
4514 +
4515 +////////////////////////////////////////////////////////////////////////
4516 +// Ip6OptionValidation Tests
4517 +////////////////////////////////////////////////////////////////////////
4518 +
4519 +// Define a fixture for your tests if needed
4520 +class Ip6OptionValidationTest : public ::testing::Test {
4521 +protected:
4522 + // Add any setup code if needed
4523 + virtual void
4524 + SetUp (
4525 + )
4526 + {
4527 + // Initialize any resources or variables
4528 + }
4529 +
4530 + // Add any cleanup code if needed
4531 + virtual void
4532 + TearDown (
4533 + )
4534 + {
4535 + // Clean up any resources or variables
4536 + }
4537 +};
4538 +
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
4544 +
4545 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4546 +}
4547 +
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;
4553 +
4554 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4555 +}
4556 +
4557 +// Test Description:
4558 +// Ip6OptionPrefixInfo Option with zero length should return false
4559 +TEST_F (Ip6OptionValidationTest, OptionWithZeroLengthShouldReturnFalse) {
4560 + IP6_OPTION_HEADER optionHeader;
4561 +
4562 + optionHeader.Type = Ip6OptionPrefixInfo;
4563 + optionHeader.Length = 0;
4564 + UINT8 option[sizeof (IP6_OPTION_HEADER)];
4565 +
4566 + CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
4567 + UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4568 +
4569 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4570 +}
4571 +
4572 +// Test Description:
4573 +// Ip6OptionPrefixInfo Option with valid length should return true
4574 +TEST_F (Ip6OptionValidationTest, ValidPrefixInfoOptionShouldReturnTrue) {
4575 + IP6_OPTION_HEADER optionHeader;
4576 +
4577 + optionHeader.Type = Ip6OptionPrefixInfo;
4578 + optionHeader.Length = 4; // Length 4 * 8 = 32
4579 + UINT8 option[OPTION_HEADER_IP6_PREFIX_DATA_LEN];
4580 +
4581 + CopyMem (option, &optionHeader, OPTION_HEADER_IP6_PREFIX_DATA_LEN);
4582 +
4583 + EXPECT_FALSE (Ip6IsNDOptionValid (option, OPTION_HEADER_IP6_PREFIX_DATA_LEN));
4584 +}
4585 +
4586 +// Test Description:
4587 +// Ip6OptionPrefixInfo Option with invalid length should return false
4588 +TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse) {
4589 + IP6_OPTION_HEADER optionHeader;
4590 +
4591 + optionHeader.Type = Ip6OptionPrefixInfo;
4592 + optionHeader.Length = 3; // Length 3 * 8 = 24 (Invalid)
4593 + UINT8 option[sizeof (IP6_OPTION_HEADER)];
4594 +
4595 + CopyMem (option, &optionHeader, sizeof (IP6_OPTION_HEADER));
4596 + UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4597 +
4598 + EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4599 +}
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
4605 @@ -25,6 +25,7 @@
4606 # Build HOST_APPLICATION that tests NetworkPkg
4607 #
4608 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
4609 + NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
4610
4611 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
4612 [LibraryClasses]
4613 --
4614 2.41.0
4615
4616
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
4622
4623 ---
4624 NetworkPkg/Ip6Dxe/Ip6Option.c | 81 ++++++++++++++++++++++++++-----
4625 NetworkPkg/Ip6Dxe/Ip6Option.h | 89 +++++++++++++++++++++++++++++++++++
4626 2 files changed, 157 insertions(+), 13 deletions(-)
4627
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
4632 @@ -9,6 +9,7 @@
4633
4634 #include "Ip6Impl.h"
4635
4636 +
4637 /**
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
4640 @@ -17,7 +18,8 @@
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.
4649
4650 @@ -31,12 +33,33 @@ Ip6IsOptionValid (
4651 IN IP6_SERVICE *IpSb,
4652 IN NET_BUF *Packet,
4653 IN UINT8 *Option,
4654 - IN UINT8 OptionLen,
4655 + IN UINT16 OptionLen,
4656 IN UINT32 Pointer
4657 )
4658 {
4659 - UINT8 Offset;
4660 - UINT8 OptionType;
4661 + UINT16 Offset;
4662 + UINT8 OptionType;
4663 + UINT8 OptDataLen;
4664 +
4665 + if (Option == NULL) {
4666 + ASSERT (Option != NULL);
4667 + return FALSE;
4668 + }
4669 +
4670 + if (OptionLen <= 0 || OptionLen > IP6_MAX_EXT_DATA_LENGTH) {
4671 + ASSERT (OptionLen > 0 && OptionLen <= IP6_MAX_EXT_DATA_LENGTH);
4672 + return FALSE;
4673 + }
4674 +
4675 + if (Packet == NULL) {
4676 + ASSERT (Packet != NULL);
4677 + return FALSE;
4678 + }
4679 +
4680 + if (IpSb == NULL) {
4681 + ASSERT (IpSb != NULL);
4682 + return FALSE;
4683 + }
4684
4685 Offset = 0;
4686
4687 @@ -54,7 +77,8 @@ Ip6IsOptionValid (
4688 //
4689 // It is a PadN option
4690 //
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);
4694 break;
4695 case Ip6OptionRouterAlert:
4696 //
4697 @@ -69,7 +93,8 @@ Ip6IsOptionValid (
4698 //
4699 switch (OptionType & Ip6OptionMask) {
4700 case Ip6OptionSkip:
4701 - Offset = (UINT8)(Offset + *(Option + Offset + 1));
4702 + OptDataLen = *(IP6_OFFSET_OF_OPT_LEN(Option + Offset));
4703 + Offset = IP6_NEXT_OPTION_OFFSET(Offset, OptDataLen);
4704 break;
4705 case Ip6OptionDiscard:
4706 return FALSE;
4707 @@ -308,7 +333,7 @@ Ip6IsExtsValid (
4708 UINT32 Pointer;
4709 UINT32 Offset;
4710 UINT8 *Option;
4711 - UINT8 OptionLen;
4712 + UINT16 OptionLen;
4713 BOOLEAN Flag;
4714 UINT8 CountD;
4715 UINT8 CountA;
4716 @@ -385,6 +410,36 @@ Ip6IsExtsValid (
4717 // Fall through
4718 //
4719 case IP6_DESTINATION:
4720 + //
4721 + // See https://www.rfc-editor.org/rfc/rfc2460#section-4.2 page 23
4722 + //
4723 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4724 + // | Next Header | Hdr Ext Len | |
4725 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
4726 + // | |
4727 + // . .
4728 + // . Options .
4729 + // . .
4730 + // | |
4731 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4732 + //
4733 + //
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.].
4738 + //
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.
4742 + //
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
4747 + // section 4.2.
4748 + //
4749 +
4750 if (*NextHeader == IP6_DESTINATION) {
4751 CountD++;
4752 }
4753 @@ -397,8 +452,8 @@ Ip6IsExtsValid (
4754 Pointer = Offset;
4755
4756 Offset++;
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;
4761 Option++;
4762 Offset++;
4763
4764 @@ -430,7 +485,7 @@ Ip6IsExtsValid (
4765 //
4766 // Ignore the routing header and proceed to process the next header.
4767 //
4768 - Offset = Offset + (RoutingHead->HeaderLen + 1) * 8;
4769 + Offset = Offset + IP6_HDR_EXT_LEN(RoutingHead->HeaderLen);
4770
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
4775 // type.
4776 //
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))
4781 {
4782 @@ -527,8 +582,8 @@ Ip6IsExtsValid (
4783 //
4784 // RFC2402, Payload length is specified in 32-bit words, minus "2".
4785 //
4786 - OptionLen = (UINT8)((*Option + 2) * 4);
4787 - Offset = Offset + OptionLen;
4788 + OptionLen = ((UINT16)(*Option + 2) * 4);
4789 + Offset = Offset + OptionLen;
4790 break;
4791
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
4797 @@ -12,6 +12,95 @@
4798
4799 #define IP6_FRAGMENT_OFFSET_MASK (~0x3)
4800
4801 +//
4802 +// Per RFC8200 Section 4.2
4803 +//
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
4807 +// format:
4808 +//
4809 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
4810 +// | Option Type | Opt Data Len | Option Data
4811 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- - - - - - - - -
4812 +//
4813 +// Option Type 8-bit identifier of the type of option.
4814 +//
4815 +// Opt Data Len 8-bit unsigned integer. Length of the Option
4816 +// Data field of this option, in octets.
4817 +//
4818 +// Option Data Variable-length field. Option-Type-specific
4819 +// data.
4820 +//
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)
4825 +STATIC_ASSERT (
4826 + IP6_OFFSET_OF_OPT_LEN (0) == 1,
4827 + "The Length field should be 1 octet (8 bits) past the start of the option"
4828 + );
4829 +
4830 +#define IP6_NEXT_OPTION_OFFSET(offset, length) (offset + IP6_COMBINED_SIZE_OF_OPT_TAG_AND_LEN + length)
4831 +STATIC_ASSERT (
4832 + IP6_NEXT_OPTION_OFFSET (0, 0) == 2,
4833 + "The next option is minimally the combined size of the option tag and length"
4834 + );
4835 +
4836 +//
4837 +// For more information see RFC 8200, Section 4.3, 4.4, and 4.6
4838 +//
4839 +// This example format is from section 4.6
4840 +// This does not apply to fragment headers
4841 +//
4842 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4843 +// | Next Header | Hdr Ext Len | |
4844 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
4845 +// | |
4846 +// . .
4847 +// . Header-Specific Data .
4848 +// . .
4849 +// | |
4850 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
4851 +//
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].
4856 +//
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.
4860 +
4861 +//
4862 +// These defines apply to the following:
4863 +// 1. Hop by Hop
4864 +// 2. Routing
4865 +// 3. Destination
4866 +//
4867 +#define IP6_SIZE_OF_EXT_NEXT_HDR (sizeof(UINT8))
4868 +#define IP6_SIZE_OF_HDR_EXT_LEN (sizeof(UINT8))
4869 +
4870 +#define IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN (IP6_SIZE_OF_EXT_NEXT_HDR + IP6_SIZE_OF_HDR_EXT_LEN)
4871 +STATIC_ASSERT (
4872 + IP6_COMBINED_SIZE_OF_NEXT_HDR_AND_LEN == 2,
4873 + "The combined size of Next Header and Len is two 8 bit fields"
4874 + );
4875 +
4876 +//
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)
4879 +//
4880 +#define IP6_HDR_EXT_LEN(a) (((UINT16)(UINT8)(a) + 1) * 8)
4881 +
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)
4885 +STATIC_ASSERT (
4886 + IP6_MAX_EXT_DATA_LENGTH == 2046,
4887 + "Maximum data length is ((MAX_UINT8 + 1) * 8) - 2"
4888 + );
4889 +
4890 typedef struct _IP6_FRAGMENT_HEADER {
4891 UINT8 NextHeader;
4892 UINT8 Reserved;
4893 --
4894 2.41.0
4895
4896
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
4902
4903 ---
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
4911
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
4916 @@ -1,6 +1,5 @@
4917 /** @file
4918 - Acts as the main entry point for the tests for the Ip6Dxe module.
4919 -
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
4923 **/
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
4928 @@ -1,5 +1,5 @@
4929 ## @file
4930 -# Unit test suite for the Ip6Dxe using Google Test
4931 +# Unit test suite for the Ip6DxeGoogleTest using Google Test
4932 #
4933 # Copyright (c) Microsoft Corporation.<BR>
4934 # SPDX-License-Identifier: BSD-2-Clause-Patent
4935 @@ -31,7 +31,6 @@
4936 DebugLib
4937 NetLib
4938 PcdLib
4939 -
4940 [Protocols]
4941 gEfiDhcp6ServiceBindingProtocolGuid
4942
4943 @@ -39,4 +38,4 @@
4944 gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
4945
4946 [Guids]
4947 - gZeroGuid
4948 \ No newline at end of file
4949 + gZeroGuid
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
4954 @@ -1,5 +1,5 @@
4955 /** @file
4956 - Tests for Ip6Option.c.
4957 + Host based unit test for Ip6Option.c.
4958
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"
4966 }
4967
4968 /////////////////////////////////////////////////////////////////////////
4969 // Defines
4970 -///////////////////////////////////////////////////////////////////////
4971 +////////////////////////////////////////////////////////////////////////
4972
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)
4975
4976 -////////////////////////////////////////////////////////////////////////
4977 -// Symbol Definitions
4978 -// These functions are not directly under test - but required to compile
4979 +///////////////////////////////////////////////////////////////////////
4980 +// Symbol definitions
4981 +//
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.
4985 +//
4986 ////////////////////////////////////////////////////////////////////////
4987 UINT32 mIp6Id;
4988
4989 @@ -126,4 +131,333 @@ TEST_F (Ip6OptionValidationTest, InvalidPrefixInfoOptionLengthShouldReturnFalse)
4990 UINT16 optionLen = sizeof (IP6_OPTION_HEADER);
4991
4992 EXPECT_FALSE (Ip6IsNDOptionValid (option, optionLen));
4993 +}
4994 +
4995 +////////////////////////////////////////////////////////////////////////
4996 +// Ip6IsOptionValid Tests
4997 +////////////////////////////////////////////////////////////////////////
4998 +
4999 +// Define a fixture for your tests if needed
5000 +class Ip6IsOptionValidTest : public ::testing::Test {
5001 +protected:
5002 + // Add any setup code if needed
5003 + virtual void
5004 + SetUp (
5005 + )
5006 + {
5007 + // Initialize any resources or variables
5008 + }
5009 +
5010 + // Add any cleanup code if needed
5011 + virtual void
5012 + TearDown (
5013 + )
5014 + {
5015 + // Clean up any resources or variables
5016 + }
5017 +};
5018 +
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;
5026 +
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 };
5030 +
5031 + Ip6Header.SourceAddress = SourceAddress;
5032 + Ip6Header.DestinationAddress = DestinationAddress;
5033 + Packet.Ip.Ip6 = &Ip6Header;
5034 +
5035 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, NULL, 0, 0));
5036 +}
5037 +
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;
5047 +
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 };
5051 +
5052 + Ip6Header.SourceAddress = SourceAddress;
5053 + Ip6Header.DestinationAddress = DestinationAddress;
5054 + Packet.Ip.Ip6 = &Ip6Header;
5055 +
5056 + IP6_OPTION_HEADER optionHeader;
5057 +
5058 + optionHeader.Type = 23; // Unknown Option
5059 + optionHeader.Length = 0; // This will cause an infinite loop if the function is not working correctly
5060 +
5061 + // This should be a valid option even though the length is 0
5062 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5063 +}
5064 +
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;
5074 +
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 };
5078 +
5079 + Ip6Header.SourceAddress = SourceAddress;
5080 + Ip6Header.DestinationAddress = DestinationAddress;
5081 + Packet.Ip.Ip6 = &Ip6Header;
5082 +
5083 + IP6_OPTION_HEADER optionHeader;
5084 +
5085 + optionHeader.Type = 23; // Unknown Option
5086 + optionHeader.Length = 1; // This will cause an infinite loop if the function is not working correctly
5087 +
5088 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5089 +}
5090 +
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;
5100 +
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 };
5104 +
5105 + Ip6Header.SourceAddress = SourceAddress;
5106 + Ip6Header.DestinationAddress = DestinationAddress;
5107 + Packet.Ip.Ip6 = &Ip6Header;
5108 +
5109 + IP6_OPTION_HEADER optionHeader;
5110 +
5111 + optionHeader.Type = 23; // Unknown Option
5112 + optionHeader.Length = 2; // Valid length for an unknown option
5113 +
5114 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5115 +}
5116 +
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;
5126 +
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 };
5130 +
5131 + Ip6Header.SourceAddress = SourceAddress;
5132 + Ip6Header.DestinationAddress = DestinationAddress;
5133 + Packet.Ip.Ip6 = &Ip6Header;
5134 +
5135 + IP6_OPTION_HEADER optionHeader;
5136 +
5137 + optionHeader.Type = Ip6OptionPad1;
5138 + optionHeader.Length = 0;
5139 +
5140 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5141 +}
5142 +
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;
5152 +
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 };
5156 +
5157 + Ip6Header.SourceAddress = SourceAddress;
5158 + Ip6Header.DestinationAddress = DestinationAddress;
5159 + Packet.Ip.Ip6 = &Ip6Header;
5160 +
5161 + IP6_OPTION_HEADER optionHeader;
5162 +
5163 + optionHeader.Type = Ip6OptionPadN;
5164 + optionHeader.Length = 0xFF;
5165 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5166 +
5167 + optionHeader.Length = 0xFE;
5168 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5169 +
5170 + optionHeader.Length = 0xFD;
5171 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5172 +
5173 + optionHeader.Length = 0xFC;
5174 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5175 +}
5176 +
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;
5186 +
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 };
5190 +
5191 + Ip6Header.SourceAddress = SourceAddress;
5192 + Ip6Header.DestinationAddress = DestinationAddress;
5193 + Packet.Ip.Ip6 = &Ip6Header;
5194 +
5195 + IP6_OPTION_HEADER optionHeader;
5196 +
5197 + optionHeader.Type = 23; // Unknown Option
5198 + optionHeader.Length = 0xFF;
5199 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5200 +
5201 + optionHeader.Length = 0xFE;
5202 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5203 +
5204 + optionHeader.Length = 0xFD;
5205 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5206 +
5207 + optionHeader.Length = 0xFC;
5208 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, sizeof (optionHeader), 0));
5209 +}
5210 +
5211 +// Test Description
5212 +// Verify that the function supports multiple options
5213 +TEST_F (Ip6IsOptionValidTest, MultiOptionSupport) {
5214 + UINT16 HdrLen;
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;
5221 +
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 };
5225 +
5226 + Ip6Header.SourceAddress = SourceAddress;
5227 + Ip6Header.DestinationAddress = DestinationAddress;
5228 + Packet.Ip.Ip6 = &Ip6Header;
5229 +
5230 + UINT8 ExtHdr[1024] = { 0 };
5231 + UINT8 *Cursor = ExtHdr;
5232 + IP6_OPTION_HEADER *Option = (IP6_OPTION_HEADER *)ExtHdr;
5233 +
5234 + // Let's start chaining options
5235 +
5236 + Option->Type = 23; // Unknown Option
5237 + Option->Length = 0xFC;
5238 +
5239 + Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
5240 +
5241 + Option = (IP6_OPTION_HEADER *)Cursor;
5242 + Option->Type = Ip6OptionPad1;
5243 +
5244 + Cursor += sizeof (1);
5245 +
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;
5250 +
5251 + Cursor += sizeof (IP6_OPTION_HEADER) + 4;
5252 +
5253 + Option = (IP6_OPTION_HEADER *)Cursor;
5254 + Option->Type = Ip6OptionPadN;
5255 + Option->Length = 0xFC;
5256 +
5257 + Cursor += sizeof (IP6_OPTION_HEADER) + 0xFC;
5258 +
5259 + Option = (IP6_OPTION_HEADER *)Cursor;
5260 + Option->Type = Ip6OptionRouterAlert;
5261 + Option->Length = 4;
5262 +
5263 + Cursor += sizeof (IP6_OPTION_HEADER) + 4;
5264 +
5265 + // Total 524
5266 +
5267 + HdrLen = (UINT16)(Cursor - ExtHdr);
5268 +
5269 + EXPECT_TRUE (Ip6IsOptionValid (IpSb, &Packet, ExtHdr, HdrLen, 0));
5270 +}
5271 +
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;
5281 +
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 };
5285 +
5286 + Ip6Header.SourceAddress = SourceAddress;
5287 + Ip6Header.DestinationAddress = DestinationAddress;
5288 + Packet.Ip.Ip6 = &Ip6Header;
5289 +
5290 + IP6_OPTION_HEADER optionHeader;
5291 +
5292 + optionHeader.Type = Ip6OptionPad1;
5293 + optionHeader.Length = 0;
5294 +
5295 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, 0, 0));
5296 +}
5297 +
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;
5307 +
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 };
5311 +
5312 + Ip6Header.SourceAddress = SourceAddress;
5313 + Ip6Header.DestinationAddress = DestinationAddress;
5314 + Packet.Ip.Ip6 = &Ip6Header;
5315 +
5316 + IP6_OPTION_HEADER optionHeader;
5317 +
5318 + optionHeader.Type = Ip6OptionPad1;
5319 + optionHeader.Length = 0;
5320 +
5321 + EXPECT_FALSE (Ip6IsOptionValid (IpSb, &Packet, (UINT8 *)&optionHeader, MAX_UINT8, 0));
5322 }
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
5327 --- /dev/null
5328 +++ b/NetworkPkg/Ip6Dxe/GoogleTest/Ip6OptionGoogleTest.h
5329 @@ -0,0 +1,33 @@
5330 +#ifndef __EFI_IP6_OPTION_GOOGLE_TEST_H__
5331 +#define __EFI_IP6_OPTION_GOOGLE_TEST_H__
5332 +
5333 +#include <Uefi.h>
5334 +#include "../Ip6Impl.h"
5335 +
5336 +/**
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.
5340 +
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.
5347 +
5348 +
5349 + @retval TRUE The option is properly formatted.
5350 + @retval FALSE The option is malformatted.
5351 +
5352 +**/
5353 +BOOLEAN
5354 +Ip6IsOptionValid (
5355 + IN IP6_SERVICE *IpSb,
5356 + IN NET_BUF *Packet,
5357 + IN UINT8 *Option,
5358 + IN UINT16 OptionLen,
5359 + IN UINT32 Pointer
5360 + );
5361 +
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
5368 @@ -14,7 +14,7 @@
5369 SUPPORTED_ARCHITECTURES = IA32|X64|AARCH64
5370 BUILD_TARGETS = NOOPT
5371 SKUID_IDENTIFIER = DEFAULT
5372 -
5373 +
5374 !include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
5375 [Packages]
5376 MdePkg/MdePkg.dec
5377 --
5378 2.41.0
5379
5380
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
5385
5386 ---
5387 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 71 +++++++++++++++++++++++++---
5388 1 file changed, 65 insertions(+), 6 deletions(-)
5389
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
5394 @@ -3,6 +3,7 @@
5395
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
5399
5400 SPDX-License-Identifier: BSD-2-Clause-Patent
5401
5402 @@ -1312,6 +1313,65 @@ PxeBcSelectDhcp6Offer (
5403 }
5404 }
5405
5406 +/**
5407 + Cache the DHCPv6 DNS Server addresses
5408 +
5409 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5410 + @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
5411 +
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)).
5416 +*/
5417 +EFI_STATUS
5418 +PxeBcCacheDnsServerAddresses (
5419 + IN PXEBC_PRIVATE_DATA *Private,
5420 + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
5421 + )
5422 +{
5423 + UINT16 DnsServerLen;
5424 +
5425 + DnsServerLen = NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen);
5426 + //
5427 + // Make sure that the number is nonzero
5428 + //
5429 + if (DnsServerLen == 0) {
5430 + return EFI_DEVICE_ERROR;
5431 + }
5432 +
5433 + //
5434 + // Make sure the DnsServerlen is a multiple of EFI_IPv6_ADDRESS (16)
5435 + //
5436 + if (DnsServerLen % sizeof (EFI_IPv6_ADDRESS) != 0) {
5437 + return EFI_DEVICE_ERROR;
5438 + }
5439 +
5440 + //
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.
5446 + //
5447 + // To support multiple DNS servers the `AllocationSize` would need to be changed to DnsServerLen
5448 + //
5449 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
5450 + //
5451 + Private->DnsServer = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
5452 + if (Private->DnsServer == NULL) {
5453 + return EFI_OUT_OF_RESOURCES;
5454 + }
5455 +
5456 + //
5457 + // Intentionally only copy over the first server address.
5458 + // To support multiple DNS servers, the `Length` would need to be changed to DnsServerLen
5459 + //
5460 + CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
5461 +
5462 + return EFI_SUCCESS;
5463 +}
5464 +
5465 /**
5466 Handle the DHCPv6 offer packet.
5467
5468 @@ -1335,6 +1395,7 @@ PxeBcHandleDhcp6Offer (
5469 UINT32 SelectIndex;
5470 UINT32 Index;
5471
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;
5478
5479 //
5480 - // First try to cache DNS server address if DHCP6 offer provides.
5481 + // First try to cache DNS server addresses if DHCP6 offer provides.
5482 //
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)) {
5489 + return Status;
5490 }
5491 -
5492 - CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
5493 }
5494
5495 if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {
5496 --
5497 2.41.0
5498
5499
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
5504 Unit Test
5505
5506 ---
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
5517
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
5522 @@ -26,6 +26,7 @@
5523 #
5524 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
5525 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
5526 + NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5527
5528 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
5529 [LibraryClasses]
5530 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
5531 new file mode 100644
5532 index 0000000000..9ee805a284
5533 --- /dev/null
5534 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
5535 @@ -0,0 +1,301 @@
5536 +/** @file
5537 + Host based unit test for PxeBcDhcp6.c.
5538 +
5539 + Copyright (c) Microsoft Corporation
5540 + SPDX-License-Identifier: BSD-2-Clause-Patent
5541 +**/
5542 +#include <gtest/gtest.h>
5543 +
5544 +extern "C" {
5545 +#include <Uefi.h>
5546 +#include <Library/BaseLib.h>
5547 +#include <Library/DebugLib.h>
5548 +#include "../PxeBcImpl.h"
5549 +#include "../PxeBcDhcp6.h"
5550 +#include "PxeBcDhcp6GoogleTest.h"
5551 +}
5552 +
5553 +///////////////////////////////////////////////////////////////////////////////
5554 +// Definitions
5555 +///////////////////////////////////////////////////////////////////////////////
5556 +
5557 +#define PACKET_SIZE (1500)
5558 +
5559 +typedef struct {
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;
5564 +
5565 +///////////////////////////////////////////////////////////////////////////////
5566 +/// Symbol Definitions
5567 +///////////////////////////////////////////////////////////////////////////////
5568 +
5569 +EFI_STATUS
5570 +MockUdpWrite (
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
5582 + )
5583 +{
5584 + return EFI_SUCCESS;
5585 +}
5586 +
5587 +EFI_STATUS
5588 +MockUdpRead (
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
5599 + )
5600 +{
5601 + return EFI_SUCCESS;
5602 +}
5603 +
5604 +EFI_STATUS
5605 +MockConfigure (
5606 + IN EFI_UDP6_PROTOCOL *This,
5607 + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
5608 + )
5609 +{
5610 + return EFI_SUCCESS;
5611 +}
5612 +
5613 +// Needed by PxeBcSupport
5614 +EFI_STATUS
5615 +EFIAPI
5616 +QueueDpc (
5617 + IN EFI_TPL DpcTpl,
5618 + IN EFI_DPC_PROCEDURE DpcProcedure,
5619 + IN VOID *DpcContext OPTIONAL
5620 + )
5621 +{
5622 + return EFI_SUCCESS;
5623 +}
5624 +
5625 +///////////////////////////////////////////////////////////////////////////////
5626 +// PxeBcHandleDhcp6OfferTest Tests
5627 +///////////////////////////////////////////////////////////////////////////////
5628 +
5629 +class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
5630 +public:
5631 +PXEBC_PRIVATE_DATA Private = { 0 };
5632 +EFI_UDP6_PROTOCOL Udp6Read;
5633 +EFI_PXE_BASE_CODE_MODE Mode = { 0 };
5634 +
5635 +protected:
5636 +// Add any setup code if needed
5637 +virtual void
5638 +SetUp (
5639 + )
5640 +{
5641 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
5642 +
5643 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
5644 + // The function under test really only needs the following:
5645 + // UdpWrite
5646 + // UdpRead
5647 +
5648 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
5649 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
5650 +
5651 + // Need to setup EFI_UDP6_PROTOCOL
5652 + // The function under test really only needs the following:
5653 + // Configure
5654 +
5655 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
5656 + Private.Udp6Read = &Udp6Read;
5657 +
5658 + // Need to setup the EFI_PXE_BASE_CODE_MODE
5659 + Private.PxeBc.Mode = &Mode;
5660 +
5661 + // for this test it doesn't really matter what the Dhcpv6 ack is set to
5662 +}
5663 +
5664 +// Add any cleanup code if needed
5665 +virtual void
5666 +TearDown (
5667 + )
5668 +{
5669 + if (Private.Dhcp6Request != NULL) {
5670 + FreePool (Private.Dhcp6Request);
5671 + }
5672 +
5673 + // Clean up any resources or variables
5674 +}
5675 +};
5676 +
5677 +// Note:
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 };
5685 +
5686 + Private.SelectIndex = 1; // SelectIndex is 1-based
5687 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
5688 +
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);
5693 +
5694 + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
5695 +}
5696 +
5697 +class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
5698 +public:
5699 +PXEBC_PRIVATE_DATA Private = { 0 };
5700 +
5701 +protected:
5702 +// Add any setup code if needed
5703 +virtual void
5704 +SetUp (
5705 + )
5706 +{
5707 +}
5708 +
5709 +// Add any cleanup code if needed
5710 +virtual void
5711 +TearDown (
5712 + )
5713 +{
5714 +}
5715 +};
5716 +
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;
5723 +
5724 + Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
5725 + ASSERT_NE (Option, nullptr);
5726 +
5727 + Option->OpCode = DHCP6_OPT_SERVER_ID;
5728 + Option->OpLen = NTOHS (sizeof (SearchPattern));
5729 + CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
5730 +
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;
5734 +
5735 + Private.DnsServer = nullptr;
5736 +
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);
5740 +
5741 + if (Private.DnsServer) {
5742 + FreePool (Private.DnsServer);
5743 + }
5744 +
5745 + if (Option) {
5746 + FreePool (Option);
5747 + }
5748 +}
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;
5754 +
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);
5761 +
5762 + Private.DnsServer = NULL;
5763 +
5764 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
5765 + ASSERT_EQ (Private.DnsServer, nullptr);
5766 +
5767 + if (Private.DnsServer) {
5768 + FreePool (Private.DnsServer);
5769 + }
5770 +}
5771 +
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;
5777 +
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);
5784 +
5785 + Private.DnsServer = NULL;
5786 +
5787 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
5788 + ASSERT_EQ (Private.DnsServer, nullptr);
5789 +
5790 + if (Private.DnsServer) {
5791 + FreePool (Private.DnsServer);
5792 + }
5793 +}
5794 +
5795 +
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;
5801 +
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;
5807 +
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}
5813 + };
5814 +
5815 +
5816 + CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
5817 +
5818 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
5819 +
5820 + Private.DnsServer = NULL;
5821 +
5822 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
5823 +
5824 + ASSERT_NE (Private.DnsServer, nullptr);
5825 +
5826 + //
5827 + // This is expected to fail until DnsServer supports multiple DNS servers
5828 + //
5829 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
5830 + //
5831 + ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
5832 +
5833 + if (Private.DnsServer) {
5834 + FreePool (Private.DnsServer);
5835 + }
5836 +}
5837 diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
5838 new file mode 100644
5839 index 0000000000..724ee468cb
5840 --- /dev/null
5841 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.h
5842 @@ -0,0 +1,48 @@
5843 +/** @file
5844 +
5845 + This file exposes the internal interfaces which may be unit tested
5846 + for the PxeBcDhcp6Dxe driver.
5847 +
5848 + Copyright (c) Microsoft Corporation.<BR>
5849 + SPDX-License-Identifier: BSD-2-Clause-Patent
5850 +**/
5851 +#ifndef __PXE_BC_DHCP6_GOOGLE_TEST_H__
5852 +#define __PXE_BC_DHCP6_GOOGLE_TEST_H__
5853 +
5854 +// Minimal includes needed to compile
5855 +#include <Uefi.h>
5856 +#include "../PxeBcImpl.h"
5857 +
5858 +/**
5859 + Handle the DHCPv6 offer packet.
5860 +
5861 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5862 +
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.
5867 +
5868 +**/
5869 +EFI_STATUS
5870 +PxeBcHandleDhcp6Offer (
5871 + IN PXEBC_PRIVATE_DATA *Private
5872 + );
5873 +
5874 + /**
5875 + Cache the DHCPv6 Server address
5876 +
5877 + @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
5878 + @param[in] Cache6 The pointer to PXEBC_DHCP6_PACKET_CACHE.
5879 +
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.
5883 +*/
5884 +EFI_STATUS
5885 +PxeBcCacheDnsServerAddresses (
5886 + IN PXEBC_PRIVATE_DATA *Private,
5887 + IN PXEBC_DHCP6_PACKET_CACHE *Cache6
5888 + );
5889 +
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
5895 --- /dev/null
5896 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.cpp
5897 @@ -0,0 +1,21 @@
5898 +/** @file
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
5902 +**/
5903 +#include <gtest/gtest.h>
5904 +
5905 +////////////////////////////////////////////////////////////////////////////////
5906 +// Add test files here
5907 +// Google Test will only pick up the tests from the files that are included
5908 +// here.
5909 +////////////////////////////////////////////////////////////////////////////////
5910 +#include "PxeBcDhcp6GoogleTest.cpp"
5911 +
5912 +////////////////////////////////////////////////////////////////////////////////
5913 +// Run the tests
5914 +////////////////////////////////////////////////////////////////////////////////
5915 +int main(int argc, char* argv[]) {
5916 + testing::InitGoogleTest (&argc, argv);
5917 + return RUN_ALL_TESTS ();
5918 +}
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
5923 --- /dev/null
5924 +++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
5925 @@ -0,0 +1,47 @@
5926 +## @file
5927 +# Unit test suite for the UefiPxeBcDxe using Google Test
5928 +#
5929 +# Copyright (c) Microsoft Corporation.<BR>
5930 +# SPDX-License-Identifier: BSD-2-Clause-Patent
5931 +##
5932 +[Defines]
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
5938 +
5939 +#
5940 +# The following information is for reference only and not required by the build tools.
5941 +#
5942 +# VALID_ARCHITECTURES = IA32 X64
5943 +#
5944 +
5945 +[Sources]
5946 + UefiPxeBcDxeGoogleTest.cpp
5947 + PxeBcDhcp6GoogleTest.cpp
5948 + ../PxeBcDhcp6.c
5949 + ../PxeBcSupport.c
5950 +
5951 +[Packages]
5952 + MdePkg/MdePkg.dec
5953 + MdeModulePkg/MdeModulePkg.dec
5954 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
5955 + NetworkPkg/NetworkPkg.dec
5956 +
5957 +[LibraryClasses]
5958 + GoogleTestLib
5959 + DebugLib
5960 + NetLib
5961 + PcdLib
5962 +
5963 +[Protocols]
5964 + gEfiDhcp6ServiceBindingProtocolGuid
5965 + gEfiDns6ServiceBindingProtocolGuid
5966 + gEfiDns6ProtocolGuid
5967 +
5968 +[Pcd]
5969 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
5970 +
5971 +[Guids]
5972 + gZeroGuid
5973 \ No newline at end of file
5974 --
5975 2.41.0
5976
5977
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
5982
5983 ---
5984 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c | 85 +++++++++++++++++++++-------
5985 NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.h | 17 ++++++
5986 2 files changed, 83 insertions(+), 19 deletions(-)
5987
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 (
5993 EFI_STATUS Status;
5994 EFI_DHCP6_PACKET *IndexOffer;
5995 UINT8 *Option;
5996 + UINTN DiscoverLenNeeded;
5997
5998 PxeBc = &Private->PxeBc;
5999 Request = Private->Dhcp6Request;
6000 @@ -898,8 +899,9 @@ PxeBcRequestBootService (
6001 if (Request == NULL) {
6002 return EFI_DEVICE_ERROR;
6003 }
6004 -
6005 - Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
6006 +
6007 + DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
6008 + Discover = AllocateZeroPool (DiscoverLenNeeded);
6009 if (Discover == NULL) {
6010 return EFI_OUT_OF_RESOURCES;
6011 }
6012 @@ -924,16 +926,34 @@ PxeBcRequestBootService (
6013 DHCP6_OPT_SERVER_ID
6014 );
6015 if (Option == NULL) {
6016 - return EFI_NOT_FOUND;
6017 + Status = EFI_NOT_FOUND;
6018 + goto ON_ERROR;
6019 }
6020
6021 //
6022 // Add Server ID Option.
6023 //
6024 OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);
6025 - CopyMem (DiscoverOpt, Option, OpLen + 4);
6026 - DiscoverOpt += (OpLen + 4);
6027 - DiscoverLen += (OpLen + 4);
6028 +
6029 + //
6030 + // Check that the minimum and maximum requirements are met
6031 + //
6032 + if (OpLen < PXEBC_MIN_SIZE_OF_DUID || OpLen > PXEBC_MAX_SIZE_OF_DUID) {
6033 + Status = EFI_INVALID_PARAMETER;
6034 + goto ON_ERROR;
6035 + }
6036 +
6037 + //
6038 + // Check that the option length is valid.
6039 + //
6040 + if ((DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN) > DiscoverLenNeeded) {
6041 + Status = EFI_OUT_OF_RESOURCES;
6042 + goto ON_ERROR;
6043 + }
6044 +
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);
6048 }
6049
6050 while (RequestLen < Request->Length) {
6051 @@ -944,16 +964,25 @@ PxeBcRequestBootService (
6052 (OpCode != DHCP6_OPT_SERVER_ID)
6053 )
6054 {
6055 +
6056 + //
6057 + // Check that the option length is valid.
6058 + //
6059 + if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {
6060 + Status = EFI_OUT_OF_RESOURCES;
6061 + goto ON_ERROR;
6062 + }
6063 +
6064 //
6065 // Copy all the options except IA option and Server ID
6066 //
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);
6073 }
6074
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);
6079 }
6080
6081 //
6082 @@ -2154,7 +2183,8 @@ PxeBcDhcp6Discover (
6083 UINT16 OpLen;
6084 UINT32 Xid;
6085 EFI_STATUS Status;
6086 -
6087 + UINTN DiscoverLenNeeded;
6088 +
6089 PxeBc = &Private->PxeBc;
6090 Mode = PxeBc->Mode;
6091 Request = Private->Dhcp6Request;
6092 @@ -2168,8 +2198,9 @@ PxeBcDhcp6Discover (
6093 if (Request == NULL) {
6094 return EFI_DEVICE_ERROR;
6095 }
6096 -
6097 - Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
6098 +
6099 + DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
6100 + Discover = AllocateZeroPool (DiscoverLenNeeded);
6101 if (Discover == NULL) {
6102 return EFI_OUT_OF_RESOURCES;
6103 }
6104 @@ -2185,22 +2216,38 @@ PxeBcDhcp6Discover (
6105 DiscoverLen = sizeof (EFI_DHCP6_HEADER);
6106 RequestLen = DiscoverLen;
6107
6108 + //
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.
6115 + //
6116 + // Therefore while this code looks like it could overflow, in practice it's not possible.
6117 + //
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))
6123 {
6124 +
6125 + if (DiscoverLen + OpLen + PXEBC_COMBINED_SIZE_OF_OPT_CODE_AND_LEN > DiscoverLenNeeded) {
6126 + Status = EFI_OUT_OF_RESOURCES;
6127 + goto ON_ERROR;
6128 + }
6129 +
6130 //
6131 // Copy all the options except IA option.
6132 //
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);
6139 }
6140
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);
6145 }
6146
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
6152 @@ -34,6 +34,23 @@
6153 #define PXEBC_ADDR_START_DELIMITER '['
6154 #define PXEBC_ADDR_END_DELIMITER ']'
6155
6156 +//
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.
6161 +//
6162 +#define PXEBC_MIN_SIZE_OF_DUID (sizeof(UINT16) + 1)
6163 +#define PXEBC_MAX_SIZE_OF_DUID (sizeof(UINT16) + 128)
6164 +
6165 +//
6166 +// This define represents the combineds code and length field from
6167 +// https://datatracker.ietf.org/doc/html/rfc3315#section-22.1
6168 +//
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))
6172 +
6173 #define GET_NEXT_DHCP6_OPTION(Opt) \
6174 (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \
6175 sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)
6176 --
6177 2.41.0
6178
6179
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
6184 Unit Test
6185
6186 ---
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(-)
6193
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
6198 @@ -26,7 +26,10 @@
6199 #
6200 NetworkPkg/Dhcp6Dxe/GoogleTest/Dhcp6DxeGoogleTest.inf
6201 NetworkPkg/Ip6Dxe/GoogleTest/Ip6DxeGoogleTest.inf
6202 - NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
6203 + NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
6204 + <LibraryClasses>
6205 + UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
6206 + }
6207
6208 # Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
6209 [LibraryClasses]
6210 @@ -88,11 +91,9 @@
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.
6213 #
6214 - # MU_CHANGE Start
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
6219 !endif
6220 - # MU_CHANGE End
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
6228 @@ -1,301 +1,570 @@
6229 -/** @file
6230 - Host based unit test for PxeBcDhcp6.c.
6231 -
6232 - Copyright (c) Microsoft Corporation
6233 - SPDX-License-Identifier: BSD-2-Clause-Patent
6234 -**/
6235 -#include <gtest/gtest.h>
6236 -
6237 -extern "C" {
6238 -#include <Uefi.h>
6239 -#include <Library/BaseLib.h>
6240 -#include <Library/DebugLib.h>
6241 -#include "../PxeBcImpl.h"
6242 -#include "../PxeBcDhcp6.h"
6243 -#include "PxeBcDhcp6GoogleTest.h"
6244 -}
6245 -
6246 -///////////////////////////////////////////////////////////////////////////////
6247 -// Definitions
6248 -///////////////////////////////////////////////////////////////////////////////
6249 -
6250 -#define PACKET_SIZE (1500)
6251 -
6252 -typedef struct {
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;
6257 -
6258 -///////////////////////////////////////////////////////////////////////////////
6259 -/// Symbol Definitions
6260 -///////////////////////////////////////////////////////////////////////////////
6261 -
6262 -EFI_STATUS
6263 -MockUdpWrite (
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
6275 - )
6276 -{
6277 - return EFI_SUCCESS;
6278 -}
6279 -
6280 -EFI_STATUS
6281 -MockUdpRead (
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
6292 - )
6293 -{
6294 - return EFI_SUCCESS;
6295 -}
6296 -
6297 -EFI_STATUS
6298 -MockConfigure (
6299 - IN EFI_UDP6_PROTOCOL *This,
6300 - IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
6301 - )
6302 -{
6303 - return EFI_SUCCESS;
6304 -}
6305 -
6306 -// Needed by PxeBcSupport
6307 -EFI_STATUS
6308 -EFIAPI
6309 -QueueDpc (
6310 - IN EFI_TPL DpcTpl,
6311 - IN EFI_DPC_PROCEDURE DpcProcedure,
6312 - IN VOID *DpcContext OPTIONAL
6313 - )
6314 -{
6315 - return EFI_SUCCESS;
6316 -}
6317 -
6318 -///////////////////////////////////////////////////////////////////////////////
6319 -// PxeBcHandleDhcp6OfferTest Tests
6320 -///////////////////////////////////////////////////////////////////////////////
6321 -
6322 -class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
6323 -public:
6324 -PXEBC_PRIVATE_DATA Private = { 0 };
6325 -EFI_UDP6_PROTOCOL Udp6Read;
6326 -EFI_PXE_BASE_CODE_MODE Mode = { 0 };
6327 -
6328 -protected:
6329 -// Add any setup code if needed
6330 -virtual void
6331 -SetUp (
6332 - )
6333 -{
6334 - Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6335 -
6336 - // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6337 - // The function under test really only needs the following:
6338 - // UdpWrite
6339 - // UdpRead
6340 -
6341 - Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6342 - Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6343 -
6344 - // Need to setup EFI_UDP6_PROTOCOL
6345 - // The function under test really only needs the following:
6346 - // Configure
6347 -
6348 - Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6349 - Private.Udp6Read = &Udp6Read;
6350 -
6351 - // Need to setup the EFI_PXE_BASE_CODE_MODE
6352 - Private.PxeBc.Mode = &Mode;
6353 -
6354 - // for this test it doesn't really matter what the Dhcpv6 ack is set to
6355 -}
6356 -
6357 -// Add any cleanup code if needed
6358 -virtual void
6359 -TearDown (
6360 - )
6361 -{
6362 - if (Private.Dhcp6Request != NULL) {
6363 - FreePool (Private.Dhcp6Request);
6364 - }
6365 -
6366 - // Clean up any resources or variables
6367 -}
6368 -};
6369 -
6370 -// Note:
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 };
6378 -
6379 - Private.SelectIndex = 1; // SelectIndex is 1-based
6380 - Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6381 -
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);
6386 -
6387 - ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
6388 -}
6389 -
6390 -class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
6391 -public:
6392 -PXEBC_PRIVATE_DATA Private = { 0 };
6393 -
6394 -protected:
6395 -// Add any setup code if needed
6396 -virtual void
6397 -SetUp (
6398 - )
6399 -{
6400 -}
6401 -
6402 -// Add any cleanup code if needed
6403 -virtual void
6404 -TearDown (
6405 - )
6406 -{
6407 -}
6408 -};
6409 -
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;
6416 -
6417 - Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
6418 - ASSERT_NE (Option, nullptr);
6419 -
6420 - Option->OpCode = DHCP6_OPT_SERVER_ID;
6421 - Option->OpLen = NTOHS (sizeof (SearchPattern));
6422 - CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
6423 -
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;
6427 -
6428 - Private.DnsServer = nullptr;
6429 -
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);
6433 -
6434 - if (Private.DnsServer) {
6435 - FreePool (Private.DnsServer);
6436 - }
6437 -
6438 - if (Option) {
6439 - FreePool (Option);
6440 - }
6441 -}
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;
6447 -
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);
6454 -
6455 - Private.DnsServer = NULL;
6456 -
6457 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6458 - ASSERT_EQ (Private.DnsServer, nullptr);
6459 -
6460 - if (Private.DnsServer) {
6461 - FreePool (Private.DnsServer);
6462 - }
6463 -}
6464 -
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;
6470 -
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);
6477 -
6478 - Private.DnsServer = NULL;
6479 -
6480 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6481 - ASSERT_EQ (Private.DnsServer, nullptr);
6482 -
6483 - if (Private.DnsServer) {
6484 - FreePool (Private.DnsServer);
6485 - }
6486 -}
6487 -
6488 -
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;
6494 -
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;
6500 -
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}
6506 - };
6507 -
6508 -
6509 - CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
6510 -
6511 - Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
6512 -
6513 - Private.DnsServer = NULL;
6514 -
6515 - ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6516 -
6517 - ASSERT_NE (Private.DnsServer, nullptr);
6518 -
6519 - //
6520 - // This is expected to fail until DnsServer supports multiple DNS servers
6521 - //
6522 - // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
6523 - //
6524 - ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
6525 -
6526 - if (Private.DnsServer) {
6527 - FreePool (Private.DnsServer);
6528 - }
6529 -}
6530 +/** @file
6531 + Host based unit test for PxeBcDhcp6.c.
6532 +
6533 + Copyright (c) Microsoft Corporation
6534 + SPDX-License-Identifier: BSD-2-Clause-Patent
6535 +**/
6536 +#include <gtest/gtest.h>
6537 +#include <Library/GoogleTestLib.h>
6538 +#include <GoogleTest/Library/MockUefiLib.h>
6539 +#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
6540 +
6541 +extern "C" {
6542 +#include <Uefi.h>
6543 +#include <Library/BaseLib.h>
6544 +#include <Library/DebugLib.h>
6545 +#include "../PxeBcImpl.h"
6546 +#include "../PxeBcDhcp6.h"
6547 +#include "PxeBcDhcp6GoogleTest.h"
6548 +}
6549 +
6550 +///////////////////////////////////////////////////////////////////////////////
6551 +// Definitions
6552 +///////////////////////////////////////////////////////////////////////////////
6553 +
6554 +#define PACKET_SIZE (1500)
6555 +
6556 +typedef struct {
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;
6561 +
6562 +///////////////////////////////////////////////////////////////////////////////
6563 +/// Symbol Definitions
6564 +///////////////////////////////////////////////////////////////////////////////
6565 +
6566 +EFI_STATUS
6567 +MockUdpWrite (
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
6579 + )
6580 +{
6581 + return EFI_SUCCESS;
6582 +}
6583 +
6584 +EFI_STATUS
6585 +MockUdpRead (
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
6596 + )
6597 +{
6598 + return EFI_SUCCESS;
6599 +}
6600 +
6601 +EFI_STATUS
6602 +MockConfigure (
6603 + IN EFI_UDP6_PROTOCOL *This,
6604 + IN EFI_UDP6_CONFIG_DATA *UdpConfigData OPTIONAL
6605 + )
6606 +{
6607 + return EFI_SUCCESS;
6608 +}
6609 +
6610 +// Needed by PxeBcSupport
6611 +EFI_STATUS
6612 +PxeBcDns6 (
6613 + IN PXEBC_PRIVATE_DATA *Private,
6614 + IN CHAR16 *HostName,
6615 + OUT EFI_IPv6_ADDRESS *IpAddress
6616 + )
6617 +{
6618 + return EFI_SUCCESS;
6619 +}
6620 +
6621 +UINT32
6622 +PxeBcBuildDhcp6Options (
6623 + IN PXEBC_PRIVATE_DATA *Private,
6624 + OUT EFI_DHCP6_PACKET_OPTION **OptList,
6625 + IN UINT8 *Buffer
6626 + )
6627 +{
6628 + return EFI_SUCCESS;
6629 +}
6630 +
6631 +EFI_STATUS
6632 +EFIAPI
6633 +QueueDpc (
6634 + IN EFI_TPL DpcTpl,
6635 + IN EFI_DPC_PROCEDURE DpcProcedure,
6636 + IN VOID *DpcContext OPTIONAL
6637 + )
6638 +{
6639 + return EFI_SUCCESS;
6640 +}
6641 +
6642 +///////////////////////////////////////////////////////////////////////////////
6643 +// PxeBcHandleDhcp6OfferTest Tests
6644 +///////////////////////////////////////////////////////////////////////////////
6645 +
6646 +class PxeBcHandleDhcp6OfferTest : public ::testing::Test {
6647 +public:
6648 +PXEBC_PRIVATE_DATA Private = { 0 };
6649 +EFI_UDP6_PROTOCOL Udp6Read;
6650 +EFI_PXE_BASE_CODE_MODE Mode = { 0 };
6651 +
6652 +protected:
6653 +// Add any setup code if needed
6654 +virtual void
6655 +SetUp (
6656 + )
6657 +{
6658 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6659 +
6660 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6661 + // The function under test really only needs the following:
6662 + // UdpWrite
6663 + // UdpRead
6664 +
6665 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6666 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6667 +
6668 + // Need to setup EFI_UDP6_PROTOCOL
6669 + // The function under test really only needs the following:
6670 + // Configure
6671 +
6672 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6673 + Private.Udp6Read = &Udp6Read;
6674 +
6675 + // Need to setup the EFI_PXE_BASE_CODE_MODE
6676 + Private.PxeBc.Mode = &Mode;
6677 +
6678 + // for this test it doesn't really matter what the Dhcpv6 ack is set to
6679 +}
6680 +
6681 +// Add any cleanup code if needed
6682 +virtual void
6683 +TearDown (
6684 + )
6685 +{
6686 + if (Private.Dhcp6Request != NULL) {
6687 + FreePool (Private.Dhcp6Request);
6688 + }
6689 +
6690 + // Clean up any resources or variables
6691 +}
6692 +};
6693 +
6694 +// Note:
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 };
6702 +
6703 + Private.SelectIndex = 1; // SelectIndex is 1-based
6704 + Cache6 = &Private.OfferBuffer[Private.SelectIndex - 1].Dhcp6;
6705 +
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);
6710 +
6711 + ASSERT_EQ (PxeBcHandleDhcp6Offer (&(PxeBcHandleDhcp6OfferTest::Private)), EFI_DEVICE_ERROR);
6712 +}
6713 +
6714 +class PxeBcCacheDnsServerAddressesTest : public ::testing::Test {
6715 +public:
6716 +PXEBC_PRIVATE_DATA Private = { 0 };
6717 +
6718 +protected:
6719 +// Add any setup code if needed
6720 +virtual void
6721 +SetUp (
6722 + )
6723 +{
6724 +}
6725 +
6726 +// Add any cleanup code if needed
6727 +virtual void
6728 +TearDown (
6729 + )
6730 +{
6731 +}
6732 +};
6733 +
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;
6740 +
6741 + Option = (EFI_DHCP6_PACKET_OPTION *)AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + sizeof (SearchPattern));
6742 + ASSERT_NE (Option, nullptr);
6743 +
6744 + Option->OpCode = DHCP6_OPT_SERVER_ID;
6745 + Option->OpLen = NTOHS (sizeof (SearchPattern));
6746 + CopyMem (Option->Data, SearchPattern, sizeof (SearchPattern));
6747 +
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;
6751 +
6752 + Private.DnsServer = nullptr;
6753 +
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);
6757 +
6758 + if (Private.DnsServer) {
6759 + FreePool (Private.DnsServer);
6760 + }
6761 +
6762 + if (Option) {
6763 + FreePool (Option);
6764 + }
6765 +}
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;
6771 +
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);
6778 +
6779 + Private.DnsServer = NULL;
6780 +
6781 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6782 + ASSERT_EQ (Private.DnsServer, nullptr);
6783 +
6784 + if (Private.DnsServer) {
6785 + FreePool (Private.DnsServer);
6786 + }
6787 +}
6788 +
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;
6794 +
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);
6801 +
6802 + Private.DnsServer = NULL;
6803 +
6804 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_DEVICE_ERROR);
6805 + ASSERT_EQ (Private.DnsServer, nullptr);
6806 +
6807 + if (Private.DnsServer) {
6808 + FreePool (Private.DnsServer);
6809 + }
6810 +}
6811 +
6812 +
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;
6818 +
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;
6824 +
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}
6830 + };
6831 +
6832 +
6833 + CopyMem(Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, &addresses, sizeof(addresses));
6834 +
6835 + Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen = NTOHS (sizeof(addresses));
6836 +
6837 + Private.DnsServer = NULL;
6838 +
6839 + ASSERT_EQ (PxeBcCacheDnsServerAddresses (&(PxeBcCacheDnsServerAddressesTest::Private), Cache6), EFI_SUCCESS);
6840 +
6841 + ASSERT_NE (Private.DnsServer, nullptr);
6842 +
6843 + //
6844 + // This is expected to fail until DnsServer supports multiple DNS servers
6845 + //
6846 + // This is tracked in https://bugzilla.tianocore.org/show_bug.cgi?id=1886
6847 + //
6848 + ASSERT_EQ (CompareMem(Private.DnsServer, &addresses, sizeof(addresses)), 0);
6849 +
6850 + if (Private.DnsServer) {
6851 + FreePool (Private.DnsServer);
6852 + }
6853 +}
6854 +
6855 +///////////////////////////////////////////////////////////////////////////////
6856 +// PxeBcRequestBootServiceTest Test Cases
6857 +///////////////////////////////////////////////////////////////////////////////
6858 +
6859 +class PxeBcRequestBootServiceTest : public ::testing::Test {
6860 +public:
6861 +PXEBC_PRIVATE_DATA Private = { 0 };
6862 +EFI_UDP6_PROTOCOL Udp6Read;
6863 +
6864 +protected:
6865 +// Add any setup code if needed
6866 +virtual void
6867 +SetUp (
6868 + )
6869 +{
6870 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
6871 +
6872 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
6873 + // The function under test really only needs the following:
6874 + // UdpWrite
6875 + // UdpRead
6876 +
6877 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
6878 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
6879 +
6880 + // Need to setup EFI_UDP6_PROTOCOL
6881 + // The function under test really only needs the following:
6882 + // Configure
6883 +
6884 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
6885 + Private.Udp6Read = &Udp6Read;
6886 +}
6887 +
6888 +// Add any cleanup code if needed
6889 +virtual void
6890 +TearDown (
6891 + )
6892 +{
6893 + if (Private.Dhcp6Request != NULL) {
6894 + FreePool (Private.Dhcp6Request);
6895 + }
6896 +
6897 + // Clean up any resources or variables
6898 +}
6899 +};
6900 +
6901 +TEST_F (PxeBcRequestBootServiceTest, ServerDiscoverBasicUsageTest) {
6902 + PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
6903 +
6904 + DHCP6_OPTION_SERVER_ID Server = { 0 };
6905 +
6906 + Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
6907 + Server.OptionLen = HTONS (16); // valid length
6908 + UINT8 Index = 0;
6909 +
6910 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
6911 +
6912 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6913 +
6914 + CopyMem (Cursor, &Server, sizeof (Server));
6915 + Cursor += sizeof (Server);
6916 +
6917 + // Update the packet length
6918 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6919 + Packet->Size = PACKET_SIZE;
6920 +
6921 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
6922 +}
6923 +
6924 +TEST_F (PxeBcRequestBootServiceTest, AttemptDiscoverOverFlowExpectFailure) {
6925 + PxeBcRequestBootServiceTest::Private.OfferBuffer[0].Dhcp6.OfferType = PxeOfferTypeProxyBinl;
6926 +
6927 + DHCP6_OPTION_SERVER_ID Server = { 0 };
6928 +
6929 + Server.OptionCode = HTONS (DHCP6_OPT_SERVER_ID);
6930 + Server.OptionLen = HTONS (1500); // This length would overflow without a check
6931 + UINT8 Index = 0;
6932 +
6933 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.OfferBuffer[Index].Dhcp6.Packet.Offer;
6934 +
6935 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6936 +
6937 + CopyMem (Cursor, &Server, sizeof (Server));
6938 + Cursor += sizeof (Server);
6939 +
6940 + // Update the packet length
6941 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6942 + Packet->Size = PACKET_SIZE;
6943 +
6944 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
6945 +}
6946 +
6947 +TEST_F (PxeBcRequestBootServiceTest, RequestBasicUsageTest) {
6948 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
6949 +
6950 + RequestOpt.OpCode = HTONS (0x1337);
6951 + RequestOpt.OpLen = 0; // valid length
6952 +
6953 + UINT8 Index = 0;
6954 +
6955 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
6956 +
6957 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6958 +
6959 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
6960 + Cursor += sizeof (RequestOpt);
6961 +
6962 + // Update the packet length
6963 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6964 + Packet->Size = PACKET_SIZE;
6965 +
6966 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_SUCCESS);
6967 +}
6968 +
6969 +TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {
6970 + EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
6971 +
6972 + RequestOpt.OpCode = HTONS (0x1337);
6973 + RequestOpt.OpLen = 1500; // this length would overflow without a check
6974 +
6975 + UINT8 Index = 0;
6976 +
6977 + EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
6978 +
6979 + UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
6980 +
6981 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
6982 + Cursor += sizeof (RequestOpt);
6983 +
6984 + // Update the packet length
6985 + Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
6986 + Packet->Size = PACKET_SIZE;
6987 +
6988 + ASSERT_EQ (PxeBcRequestBootService (&(PxeBcRequestBootServiceTest::Private), Index), EFI_OUT_OF_RESOURCES);
6989 +}
6990 +
6991 +///////////////////////////////////////////////////////////////////////////////
6992 +// PxeBcDhcp6Discover Test
6993 +///////////////////////////////////////////////////////////////////////////////
6994 +
6995 +class PxeBcDhcp6DiscoverTest : public ::testing::Test {
6996 +public:
6997 +PXEBC_PRIVATE_DATA Private = { 0 };
6998 +EFI_UDP6_PROTOCOL Udp6Read;
6999 +
7000 +protected:
7001 +MockUefiRuntimeServicesTableLib RtServicesMock;
7002 +
7003 +// Add any setup code if needed
7004 +virtual void
7005 +SetUp (
7006 + )
7007 +{
7008 + Private.Dhcp6Request = (EFI_DHCP6_PACKET *)AllocateZeroPool (PACKET_SIZE);
7009 +
7010 + // Need to setup the EFI_PXE_BASE_CODE_PROTOCOL
7011 + // The function under test really only needs the following:
7012 + // UdpWrite
7013 + // UdpRead
7014 +
7015 + Private.PxeBc.UdpWrite = (EFI_PXE_BASE_CODE_UDP_WRITE)MockUdpWrite;
7016 + Private.PxeBc.UdpRead = (EFI_PXE_BASE_CODE_UDP_READ)MockUdpRead;
7017 +
7018 + // Need to setup EFI_UDP6_PROTOCOL
7019 + // The function under test really only needs the following:
7020 + // Configure
7021 +
7022 + Udp6Read.Configure = (EFI_UDP6_CONFIGURE)MockConfigure;
7023 + Private.Udp6Read = &Udp6Read;
7024 +}
7025 +
7026 +// Add any cleanup code if needed
7027 +virtual void
7028 +TearDown (
7029 + )
7030 +{
7031 + if (Private.Dhcp6Request != NULL) {
7032 + FreePool (Private.Dhcp6Request);
7033 + }
7034 +
7035 + // Clean up any resources or variables
7036 +}
7037 +};
7038 +
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
7044 +
7045 + RequestOpt.OpCode = HTONS (0x1337);
7046 + RequestOpt.OpLen = HTONS (0xFFFF); // overflow
7047 +
7048 + UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
7049 +
7050 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
7051 + Cursor += sizeof (RequestOpt);
7052 +
7053 + Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
7054 +
7055 + EXPECT_CALL (RtServicesMock, gRT_GetTime)
7056 + .WillOnce (::testing::Return (0));
7057 +
7058 + ASSERT_EQ (
7059 + PxeBcDhcp6Discover (
7060 + &(PxeBcDhcp6DiscoverTest::Private),
7061 + 0,
7062 + NULL,
7063 + FALSE,
7064 + (EFI_IP_ADDRESS *)&DestIp
7065 + ),
7066 + EFI_OUT_OF_RESOURCES
7067 + );
7068 +}
7069 +
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
7075 +
7076 + RequestOpt.OpCode = HTONS (0x1337);
7077 + RequestOpt.OpLen = HTONS (0x30);
7078 +
7079 + UINT8 *Cursor = (UINT8 *)(Private.Dhcp6Request->Dhcp6.Option);
7080 +
7081 + CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
7082 + Cursor += sizeof (RequestOpt);
7083 +
7084 + Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
7085 +
7086 + EXPECT_CALL (RtServicesMock, gRT_GetTime)
7087 + .WillOnce (::testing::Return (0));
7088 +
7089 + ASSERT_EQ (
7090 + PxeBcDhcp6Discover (
7091 + &(PxeBcDhcp6DiscoverTest::Private),
7092 + 0,
7093 + NULL,
7094 + FALSE,
7095 + (EFI_IP_ADDRESS *)&DestIp
7096 + ),
7097 + EFI_SUCCESS
7098 + );
7099 +}
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
7106 );
7107
7108 +/**
7109 + Build and send out the request packet for the bootfile, and parse the reply.
7110 +
7111 + @param[in] Private The pointer to PxeBc private data.
7112 + @param[in] Index PxeBc option boot item type.
7113 +
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.
7118 +
7119 +**/
7120 +EFI_STATUS
7121 +PxeBcRequestBootService (
7122 + IN PXEBC_PRIVATE_DATA *Private,
7123 + IN UINT32 Index
7124 + );
7125 +
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
7132 @@ -1,21 +1,21 @@
7133 -/** @file
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
7137 -**/
7138 -#include <gtest/gtest.h>
7139 -
7140 -////////////////////////////////////////////////////////////////////////////////
7141 -// Add test files here
7142 -// Google Test will only pick up the tests from the files that are included
7143 -// here.
7144 -////////////////////////////////////////////////////////////////////////////////
7145 -#include "PxeBcDhcp6GoogleTest.cpp"
7146 -
7147 -////////////////////////////////////////////////////////////////////////////////
7148 -// Run the tests
7149 -////////////////////////////////////////////////////////////////////////////////
7150 -int main(int argc, char* argv[]) {
7151 - testing::InitGoogleTest (&argc, argv);
7152 - return RUN_ALL_TESTS ();
7153 -}
7154 \ No newline at end of file
7155 +/** @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
7159 +**/
7160 +#include <gtest/gtest.h>
7161 +
7162 +////////////////////////////////////////////////////////////////////////////////
7163 +// Add test files here
7164 +// Google Test will only pick up the tests from the files that are included
7165 +// here.
7166 +////////////////////////////////////////////////////////////////////////////////
7167 +#include "PxeBcDhcp6GoogleTest.cpp"
7168 +
7169 +////////////////////////////////////////////////////////////////////////////////
7170 +// Run the tests
7171 +////////////////////////////////////////////////////////////////////////////////
7172 +int main(int argc, char* argv[]) {
7173 + testing::InitGoogleTest (&argc, argv);
7174 + return RUN_ALL_TESTS ();
7175 +}
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
7180 @@ -1,47 +1,47 @@
7181 -## @file
7182 -# Unit test suite for the UefiPxeBcDxe using Google Test
7183 -#
7184 -# Copyright (c) Microsoft Corporation.<BR>
7185 -# SPDX-License-Identifier: BSD-2-Clause-Patent
7186 -##
7187 -[Defines]
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
7193 -
7194 -#
7195 -# The following information is for reference only and not required by the build tools.
7196 -#
7197 -# VALID_ARCHITECTURES = IA32 X64
7198 -#
7199 -
7200 -[Sources]
7201 - UefiPxeBcDxeGoogleTest.cpp
7202 - PxeBcDhcp6GoogleTest.cpp
7203 - ../PxeBcDhcp6.c
7204 - ../PxeBcSupport.c
7205 -
7206 -[Packages]
7207 - MdePkg/MdePkg.dec
7208 - MdeModulePkg/MdeModulePkg.dec
7209 - UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
7210 - NetworkPkg/NetworkPkg.dec
7211 -
7212 -[LibraryClasses]
7213 - GoogleTestLib
7214 - DebugLib
7215 - NetLib
7216 - PcdLib
7217 -
7218 -[Protocols]
7219 - gEfiDhcp6ServiceBindingProtocolGuid
7220 - gEfiDns6ServiceBindingProtocolGuid
7221 - gEfiDns6ProtocolGuid
7222 -
7223 -[Pcd]
7224 - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
7225 -
7226 -[Guids]
7227 +## @file
7228 +# Unit test suite for the UefiPxeBcDxe using Google Test
7229 +#
7230 +# Copyright (c) Microsoft Corporation.<BR>
7231 +# SPDX-License-Identifier: BSD-2-Clause-Patent
7232 +##
7233 +[Defines]
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
7239 +
7240 +#
7241 +# The following information is for reference only and not required by the build tools.
7242 +#
7243 +# VALID_ARCHITECTURES = IA32 X64
7244 +#
7245 +
7246 +[Sources]
7247 + UefiPxeBcDxeGoogleTest.cpp
7248 + PxeBcDhcp6GoogleTest.cpp
7249 + ../PxeBcDhcp6.c
7250 + ../PxeBcSupport.c
7251 +
7252 +[Packages]
7253 + MdePkg/MdePkg.dec
7254 + MdeModulePkg/MdeModulePkg.dec
7255 + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
7256 + NetworkPkg/NetworkPkg.dec
7257 +
7258 +[LibraryClasses]
7259 + GoogleTestLib
7260 + DebugLib
7261 + NetLib
7262 + PcdLib
7263 +
7264 +[Protocols]
7265 + gEfiDhcp6ServiceBindingProtocolGuid
7266 + gEfiDns6ServiceBindingProtocolGuid
7267 + gEfiDns6ProtocolGuid
7268 +
7269 +[Pcd]
7270 + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType
7271 +
7272 +[Guids]
7273 gZeroGuid
7274 \ No newline at end of file
7275 --
7276 2.41.0
7277